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

View File

@ -99,7 +99,7 @@ clear:
rm -rf build rm -rf build
rm -f *.o *-protocol.h *-protocol.c rm -f *.o *-protocol.h *-protocol.c
rm -f ./hyprctl/hyprctl rm -f ./hyprctl/hyprctl
rm -rf ./wlroots/build rm -rf ./subprojects/wlroots/build
all: all:
make config make config
@ -107,6 +107,10 @@ all:
cd ./hyprctl && make all && cd .. cd ./hyprctl && make all && cd ..
install: 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 make all
mkdir -p ${PREFIX}/share/wayland-sessions mkdir -p ${PREFIX}/share/wayland-sessions
cp ./example/hyprland.desktop ${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_4K.png ${PREFIX}/share/hyprland
cp ./assets/wall_8K.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: uninstall:
rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop
rm -f ${PREFIX}/bin/Hyprland 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 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: fixwlr:
make protocols
sed -i -E 's/(soversion = 11)([^032]|$$)/soversion = 11032/g' subprojects/wlroots/meson.build sed -i -E 's/(soversion = 11)([^032]|$$)/soversion = 11032/g' subprojects/wlroots/meson.build
rm -rf ./subprojects/wlroots/build rm -rf ./subprojects/wlroots/build
config:
make protocols
make fixwlr
cd subprojects/wlroots && meson ./build --prefix=/usr --buildtype=release cd subprojects/wlroots && meson ./build --prefix=/usr --buildtype=release
cd subprojects/wlroots && ninja -C build/ cd subprojects/wlroots && ninja -C build/

View File

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

View File

@ -32,9 +32,13 @@
src = inputs.wlroots; src = inputs.wlroots;
}); });
hyprland = prev.callPackage ./nix/default.nix { 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; wlroots = wlroots-hyprland;
}; };
hyprland-debug = hyprland.override {debug = true;};
waybar-hyprland = prev.waybar.overrideAttrs (oldAttrs: {
mesonFlags = oldAttrs.mesonFlags ++ ["-Dexperimental=true"];
});
}; };
packages = genSystems (system: packages = genSystems (system:

View File

@ -26,6 +26,8 @@ const std::string USAGE = R"#(usage: hyprctl [command] [(opt)args]
dispatch dispatch
keyword keyword
version version
kill
hyprpaper
reload)#"; reload)#";
void request(std::string arg) { void request(std::string arg) {
@ -74,7 +76,65 @@ void request(std::string arg) {
char buffer[8192] = {0}; 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) { if (sizeWritten < 0) {
std::cout << "Couldn't read (5)"; std::cout << "Couldn't read (5)";
@ -109,6 +169,17 @@ void keywordRequest(int argc, char** argv) {
request(rq); 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) { void batchRequest(int argc, char** argv) {
std::string rq = "[[BATCH]]" + std::string(argv[2]); 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], "activewindow")) request("activewindow");
else if (!strcmp(argv[1], "layers")) request("layers"); else if (!strcmp(argv[1], "layers")) request("layers");
else if (!strcmp(argv[1], "version")) request("version"); 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], "devices")) request("devices");
else if (!strcmp(argv[1], "reload")) request("reload"); else if (!strcmp(argv[1], "reload")) request("reload");
else if (!strcmp(argv[1], "dispatch")) dispatchRequest(argc, argv); else if (!strcmp(argv[1], "dispatch")) dispatchRequest(argc, argv);
else if (!strcmp(argv[1], "keyword")) keywordRequest(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], "--batch")) batchRequest(argc, argv);
else if (!strcmp(argv[1], "--help")) printf("%s", USAGE.c_str()); else if (!strcmp(argv[1], "--help")) printf("%s", USAGE.c_str());
else { else {

View File

@ -1,6 +1,15 @@
project('Hyprland', 'cpp', 'c', project('Hyprland', 'cpp', 'c',
version : '0.6.0beta', version : '0.6.2beta',
default_options : ['warning_level=3', 'cpp_std=c++20', 'default_library=static']) 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']) wlroots = subproject('wlroots', default_options: ['examples=false'])
have_xwlr = wlroots.get_variable('features').get('xwayland') have_xwlr = wlroots.get_variable('features').get('xwayland')

View File

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

View File

@ -3,6 +3,11 @@
CCompositor::CCompositor() { CCompositor::CCompositor() {
m_szInstanceSignature = GIT_COMMIT_HASH + std::string("_") + std::to_string(time(NULL)); 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::init(m_szInstanceSignature);
Debug::log(LOG, "Instance Signature: %s", m_szInstanceSignature.c_str()); 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"); 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_sWLDisplay = wl_display_create();
m_sWLRBackend = wlr_backend_autocreate(m_sWLDisplay); m_sWLRBackend = wlr_backend_autocreate(m_sWLDisplay);
@ -121,6 +121,11 @@ CCompositor::CCompositor() {
m_sWLRToplevelMgr = wlr_foreign_toplevel_manager_v1_create(m_sWLDisplay); m_sWLRToplevelMgr = wlr_foreign_toplevel_manager_v1_create(m_sWLDisplay);
m_sWLRTabletManager = wlr_tablet_v2_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() { CCompositor::~CCompositor() {
@ -167,8 +172,8 @@ void CCompositor::cleanupExit() {
m_pLastFocus = nullptr; m_pLastFocus = nullptr;
m_pLastWindow = nullptr; m_pLastWindow = nullptr;
m_lWorkspaces.clear(); m_vWorkspaces.clear();
m_lWindows.clear(); m_vWindows.clear();
if (g_pXWaylandManager->m_sWLRXWayland) { if (g_pXWaylandManager->m_sWLRXWayland) {
wlr_xwayland_destroy(g_pXWaylandManager->m_sWLRXWayland); wlr_xwayland_destroy(g_pXWaylandManager->m_sWLRXWayland);
@ -264,9 +269,9 @@ void CCompositor::startCompositor() {
} }
SMonitor* CCompositor::getMonitorFromID(const int& id) { SMonitor* CCompositor::getMonitorFromID(const int& id) {
for (auto& m : m_lMonitors) { for (auto& m : m_vMonitors) {
if (m.ID == (uint64_t)id) { if (m->ID == (uint64_t)id) {
return &m; return m.get();
} }
} }
@ -274,9 +279,9 @@ SMonitor* CCompositor::getMonitorFromID(const int& id) {
} }
SMonitor* CCompositor::getMonitorFromName(const std::string& name) { SMonitor* CCompositor::getMonitorFromName(const std::string& name) {
for (auto& m : m_lMonitors) { for (auto& m : m_vMonitors) {
if (m.szName == name) { if (m->szName == name) {
return &m; return m.get();
} }
} }
@ -296,18 +301,18 @@ SMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) {
float bestDistance = 0.f; float bestDistance = 0.f;
SMonitor* pBestMon = nullptr; SMonitor* pBestMon = nullptr;
for (auto& m : m_lMonitors) { for (auto& m : m_vMonitors) {
float dist = vecToRectDistanceSquared(point, m.vecPosition, m.vecPosition + m.vecSize); float dist = vecToRectDistanceSquared(point, m->vecPosition, m->vecPosition + m->vecSize);
if (dist < bestDistance || !pBestMon) { if (dist < bestDistance || !pBestMon) {
bestDistance = dist; bestDistance = dist;
pBestMon = &m; pBestMon = m.get();
} }
} }
if (!pBestMon) { // ????? if (!pBestMon) { // ?????
Debug::log(WARN, "getMonitorFromVector no close mon???"); Debug::log(WARN, "getMonitorFromVector no close mon???");
return &m_lMonitors.front(); return m_vMonitors.front().get();
} }
return pBestMon; return pBestMon;
@ -317,13 +322,35 @@ SMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) {
} }
void CCompositor::removeWindowFromVectorSafe(CWindow* pWindow) { void CCompositor::removeWindowFromVectorSafe(CWindow* pWindow) {
if (windowExists(pWindow) && !pWindow->m_bFadingOut) if (windowExists(pWindow) && !pWindow->m_bFadingOut){
m_lWindows.remove(*pWindow); 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) { bool CCompositor::windowExists(CWindow* pWindow) {
for (auto& w : m_lWindows) { for (auto& w : m_vWindows) {
if (&w == pWindow) if (w.get() == pWindow)
return true; return true;
} }
@ -334,24 +361,24 @@ CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
const auto PMONITOR = getMonitorFromVector(pos); const auto PMONITOR = getMonitorFromVector(pos);
if (PMONITOR->specialWorkspaceOpen) { if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) { 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}; 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) 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; return w.get();
} }
} }
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter. // 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_lWindows.rbegin(); w != m_lWindows.rend(); 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}; 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) 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); return w->get();
} }
for (auto& w : m_lWindows) { 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}; 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) 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; return w.get();
} }
return nullptr; return nullptr;
@ -361,17 +388,17 @@ CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
const auto PMONITOR = getMonitorFromVector(pos); const auto PMONITOR = getMonitorFromVector(pos);
if (PMONITOR->specialWorkspaceOpen) { if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) { for (auto& w : m_vWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y}; 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) if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && !w->m_bIsFloating && !w->m_bHidden)
return &w; return w.get();
} }
} }
for (auto& w : m_lWindows) { for (auto& w : m_vWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y}; 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) 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; return w.get();
} }
return nullptr; return nullptr;
@ -382,24 +409,24 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
// special workspace // special workspace
if (PMONITOR->specialWorkspaceOpen) { if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) { for (auto& w : m_vWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y}; 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) if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w->m_bHidden)
return &w; return w.get();
} }
} }
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter. // 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++) { 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}; 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) 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); return w->get();
} }
for (auto& w : m_lWindows) { for (auto& w : m_vWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y}; 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) 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; return w.get();
} }
return nullptr; return nullptr;
@ -409,34 +436,34 @@ CWindow* CCompositor::windowFromCursor() {
const auto PMONITOR = getMonitorFromCursor(); const auto PMONITOR = getMonitorFromCursor();
if (PMONITOR->specialWorkspaceOpen) { if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_lWindows) { for (auto& w : m_vWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y}; 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) if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped)
return &w; return w.get();
} }
} }
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter. // 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++) { 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}; 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)) if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID))
return &(*w); return w->get();
} }
for (auto& w : m_lWindows) { for (auto& w : m_vWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y}; 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) if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace)
return &w; return w.get();
} }
return nullptr; return nullptr;
} }
CWindow* CCompositor::windowFloatingFromCursor() { CWindow* CCompositor::windowFloatingFromCursor() {
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); 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}; 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) 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); return w->get();
} }
return nullptr; return nullptr;
@ -475,9 +502,9 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, CWindow* pW
} }
SMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) { SMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) {
for (auto& m : m_lMonitors) { for (auto& m : m_vMonitors) {
if (m.output == out) { if (m->output == out) {
return &m; return m.get();
} }
} }
@ -586,59 +613,58 @@ bool CCompositor::windowValidMapped(CWindow* pWindow) {
if (pWindow->m_bHidden) if (pWindow->m_bHidden)
return false; return false;
if (!g_pXWaylandManager->getWindowSurface(pWindow))
return false;
return true; return true;
} }
CWindow* CCompositor::getWindowForPopup(wlr_xdg_popup* popup) { CWindow* CCompositor::getWindowForPopup(wlr_xdg_popup* popup) {
for (auto& p : m_lXDGPopups) { for (auto& p : m_vXDGPopups) {
if (p.popup == popup) if (p->popup == popup)
return p.parentWindow; return p->parentWindow;
} }
return nullptr; 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++) { for (auto it = layerSurfaces->rbegin(); it != layerSurfaces->rend(); it++) {
if ((*it)->fadingOut || !(*it)->layerSurface || ((*it)->layerSurface && !(*it)->layerSurface->mapped)) if ((*it)->fadingOut || !(*it)->layerSurface || ((*it)->layerSurface && !(*it)->layerSurface->mapped))
continue; 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); 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 SURFACEAT;
}
} }
return nullptr; return nullptr;
} }
CWindow* CCompositor::getWindowFromSurface(wlr_surface* pSurface) { CWindow* CCompositor::getWindowFromSurface(wlr_surface* pSurface) {
for (auto& w : m_lWindows) { for (auto& w : m_vWindows) {
if (g_pXWaylandManager->getWindowSurface(&w) == pSurface) if (g_pXWaylandManager->getWindowSurface(w.get()) == pSurface)
return &w; return w.get();
} }
return nullptr; return nullptr;
} }
CWindow* CCompositor::getFullscreenWindowOnWorkspace(const int& ID) { CWindow* CCompositor::getFullscreenWindowOnWorkspace(const int& ID) {
for (auto& w : m_lWindows) { for (auto& w : m_vWindows) {
if (w.m_iWorkspaceID == ID && w.m_bIsFullscreen) if (w->m_iWorkspaceID == ID && w->m_bIsFullscreen)
return &w; return w.get();
} }
return nullptr; return nullptr;
} }
bool CCompositor::isWorkspaceVisible(const int& w) { bool CCompositor::isWorkspaceVisible(const int& w) {
for (auto& m : m_lMonitors) { for (auto& m : m_vMonitors) {
if (m.activeWorkspace == w) if (m->activeWorkspace == w)
return true; return true;
if (m.specialWorkspaceOpen && w == SPECIAL_WORKSPACE_ID) if (m->specialWorkspaceOpen && w == SPECIAL_WORKSPACE_ID)
return true; return true;
} }
@ -646,34 +672,42 @@ bool CCompositor::isWorkspaceVisible(const int& w) {
} }
CWorkspace* CCompositor::getWorkspaceByID(const int& id) { CWorkspace* CCompositor::getWorkspaceByID(const int& id) {
for (auto& w : m_lWorkspaces) { for (auto& w : m_vWorkspaces) {
if (w.m_iID == id) if (w->m_iID == id)
return &w; return w.get();
} }
return nullptr; return nullptr;
} }
void CCompositor::sanityCheckWorkspaces() { void CCompositor::sanityCheckWorkspaces() {
for (auto it = m_lWorkspaces.begin(); it != m_lWorkspaces.end(); ++it) { for (auto it = m_vWorkspaces.begin(); it != m_vWorkspaces.end(); ++it) {
if ((getWindowsOnWorkspace(it->m_iID) == 0 && !isWorkspaceVisible(it->m_iID))) { const auto WINDOWSONWORKSPACE = getWindowsOnWorkspace((*it)->m_iID);
it = m_lWorkspaces.erase(it);
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) { if ((*it)->m_iID == SPECIAL_WORKSPACE_ID && WINDOWSONWORKSPACE == 0) {
for (auto& m : m_lMonitors) { for (auto& m : m_vMonitors) {
m.specialWorkspaceOpen = false; 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 CCompositor::getWindowsOnWorkspace(const int& id) {
int no = 0; int no = 0;
for (auto& w : m_lWindows) { for (auto& w : m_vWindows) {
if (w.m_iWorkspaceID == id && w.m_bIsMapped) if (w->m_iWorkspaceID == id && w->m_bIsMapped)
no++; no++;
} }
@ -681,9 +715,9 @@ int CCompositor::getWindowsOnWorkspace(const int& id) {
} }
CWindow* CCompositor::getFirstWindowOnWorkspace(const int& id) { CWindow* CCompositor::getFirstWindowOnWorkspace(const int& id) {
for (auto& w : m_lWindows) { for (auto& w : m_vWindows) {
if (w.m_iWorkspaceID == id) if (w->m_iWorkspaceID == id)
return &w; return w.get();
} }
return nullptr; return nullptr;
@ -697,16 +731,16 @@ void CCompositor::fixXWaylandWindowsOnWorkspace(const int& id) {
if (!PWORKSPACE) if (!PWORKSPACE)
return; return;
for (auto& w : m_lWindows) { for (auto& w : m_vWindows) {
if (w.m_iWorkspaceID == id) { if (w->m_iWorkspaceID == id) {
// moveXWaylandWindow only moves XWayland windows // moveXWaylandWindow only moves XWayland windows
// so there is no need to check here // so there is no need to check here
// if the window is XWayland or not. // if the window is XWayland or not.
if (ISVISIBLE && (!PWORKSPACE->m_bHasFullscreenWindow || w.m_bIsFullscreen)) if (ISVISIBLE && (!PWORKSPACE->m_bHasFullscreenWindow || w->m_bIsFullscreen))
g_pXWaylandManager->moveXWaylandWindow(&w, w.m_vRealPosition.vec()); g_pXWaylandManager->moveXWaylandWindow(w.get(), w->m_vRealPosition.vec());
else else
g_pXWaylandManager->moveXWaylandWindow(&w, Vector2D(42069,42069)); g_pXWaylandManager->moveXWaylandWindow(w.get(), Vector2D(42069,42069));
} }
} }
} }
@ -731,16 +765,16 @@ void CCompositor::moveWindowToTop(CWindow* pWindow) {
if (!windowValidMapped(pWindow)) if (!windowValidMapped(pWindow))
return; return;
for (auto it = m_lWindows.begin(); it != m_lWindows.end(); ++it) { for (auto it = m_vWindows.begin(); it != m_vWindows.end(); ++it) {
if (&(*it) == pWindow) { if (it->get() == pWindow) {
m_lWindows.splice(m_lWindows.end(), m_lWindows, it); std::rotate(it, it + 1, m_vWindows.end());
break; break;
} }
} }
} }
void CCompositor::cleanupFadingOut() { void CCompositor::cleanupFadingOut() {
for (auto& w : m_lWindowsFadingOut) { for (auto& w : m_vWindowsFadingOut) {
bool valid = windowExists(w); bool valid = windowExists(w);
@ -750,18 +784,18 @@ void CCompositor::cleanupFadingOut() {
g_pHyprOpenGL->m_mWindowFramebuffers[w].release(); g_pHyprOpenGL->m_mWindowFramebuffers[w].release();
g_pHyprOpenGL->m_mWindowFramebuffers.erase(w); g_pHyprOpenGL->m_mWindowFramebuffers.erase(w);
m_lWindows.remove(*w); removeWindowFromVectorSafe(w);
m_lWindowsFadingOut.remove(w); m_vWindowsFadingOut.erase(std::remove(m_vWindowsFadingOut.begin(), m_vWindowsFadingOut.end(), w));
Debug::log(LOG, "Cleanup: destroyed a window"); Debug::log(LOG, "Cleanup: destroyed a window");
return; return;
} }
} }
for (auto& ls : m_lSurfacesFadingOut) { for (auto& ls : m_vSurfacesFadingOut) {
if (ls->fadingOut && ls->readyToDelete && !ls->alpha.isBeingAnimated()) { if (ls->fadingOut && ls->readyToDelete && !ls->alpha.isBeingAnimated()) {
for (auto& m : m_lMonitors) { for (auto& m : m_vMonitors) {
for (auto& lsl : m.m_aLayerSurfaceLists) { for (auto& lsl : m->m_aLayerSurfaceLists) {
lsl.remove(ls); lsl.remove(ls);
} }
} }
@ -770,7 +804,7 @@ void CCompositor::cleanupFadingOut() {
g_pHyprOpenGL->m_mLayerFramebuffers.erase(ls); g_pHyprOpenGL->m_mLayerFramebuffers.erase(ls);
delete 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"); Debug::log(LOG, "Cleanup: destroyed a layersurface");
@ -789,11 +823,11 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
auto longestIntersect = -1; auto longestIntersect = -1;
CWindow* longestIntersectWindow = nullptr; CWindow* longestIntersectWindow = nullptr;
for (auto& w : m_lWindows) { for (auto& w : m_vWindows) {
if (&w == pWindow || !windowValidMapped(&w) || w.m_bIsFloating || !isWorkspaceVisible(w.m_iWorkspaceID)) if (w.get() == pWindow || !w->m_bIsMapped || w->m_bHidden || w->m_bIsFloating || !isWorkspaceVisible(w->m_iWorkspaceID))
continue; continue;
const auto BWINDOWIDEALBB = w.getWindowIdealBoundingBoxIgnoreReserved(); const auto BWINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved();
const auto POSB = Vector2D(BWINDOWIDEALBB.x, BWINDOWIDEALBB.y); const auto POSB = Vector2D(BWINDOWIDEALBB.x, BWINDOWIDEALBB.y);
const auto SIZEB = Vector2D(BWINDOWIDEALBB.width, BWINDOWIDEALBB.height); 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)); 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) { if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN; longestIntersect = INTERSECTLEN;
longestIntersectWindow = &w; longestIntersectWindow = w.get();
} }
} }
break; 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)); 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) { if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN; longestIntersect = INTERSECTLEN;
longestIntersectWindow = &w; longestIntersectWindow = w.get();
} }
} }
break; 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)); 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) { if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN; longestIntersect = INTERSECTLEN;
longestIntersectWindow = &w; longestIntersectWindow = w.get();
} }
} }
break; 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)); 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) { if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN; longestIntersect = INTERSECTLEN;
longestIntersectWindow = &w; longestIntersectWindow = w.get();
} }
} }
break; break;
@ -847,30 +881,30 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
} }
void CCompositor::deactivateAllWLRWorkspaces(wlr_ext_workspace_handle_v1* exclude) { void CCompositor::deactivateAllWLRWorkspaces(wlr_ext_workspace_handle_v1* exclude) {
for (auto& w : m_lWorkspaces) { for (auto& w : m_vWorkspaces) {
if (w.m_pWlrHandle && w.m_pWlrHandle != exclude) if (w->m_pWlrHandle && w->m_pWlrHandle != exclude)
w.setActive(false); w->setActive(false);
} }
} }
CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow) { CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow) {
bool gotToWindow = false; bool gotToWindow = false;
for (auto& w : m_lWindows) { for (auto& w : m_vWindows) {
if (&w != pWindow && !gotToWindow) if (w.get() != pWindow && !gotToWindow)
continue; continue;
if (&w == pWindow) { if (w.get() == pWindow) {
gotToWindow = true; gotToWindow = true;
continue; continue;
} }
if (w.m_iWorkspaceID == pWindow->m_iWorkspaceID && windowValidMapped(&w)) if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->m_bHidden)
return &w; return w.get();
} }
for (auto& w : m_lWindows) { for (auto& w : m_vWindows) {
if (&w != pWindow && w.m_iWorkspaceID == pWindow->m_iWorkspaceID && windowValidMapped(&w)) if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->m_bHidden)
return &w; return w.get();
} }
return nullptr; return nullptr;
@ -878,18 +912,18 @@ CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow) {
int CCompositor::getNextAvailableNamedWorkspace() { int CCompositor::getNextAvailableNamedWorkspace() {
int lowest = -1337 + 1; int lowest = -1337 + 1;
for (auto& w : m_lWorkspaces) { for (auto& w : m_vWorkspaces) {
if (w.m_iID < -1 && w.m_iID < lowest) if (w->m_iID < -1 && w->m_iID < lowest)
lowest = w.m_iID; lowest = w->m_iID;
} }
return lowest - 1; return lowest - 1;
} }
CWorkspace* CCompositor::getWorkspaceByName(const std::string& name) { CWorkspace* CCompositor::getWorkspaceByName(const std::string& name) {
for (auto& w : m_lWorkspaces) { for (auto& w : m_vWorkspaces) {
if (w.m_szName == name) if (w->m_szName == name)
return &w; return w.get();
} }
return nullptr; return nullptr;
@ -911,8 +945,8 @@ CWorkspace* CCompositor::getWorkspaceByString(const std::string& str) {
} }
bool CCompositor::isPointOnAnyMonitor(const Vector2D& point) { bool CCompositor::isPointOnAnyMonitor(const Vector2D& point) {
for (auto& m : m_lMonitors) { 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)) if (VECINRECT(point, m->vecPosition.x, m->vecPosition.y, m->vecSize.x + m->vecPosition.x, m->vecSize.y + m->vecPosition.y))
return true; return true;
} }
@ -925,12 +959,12 @@ CWindow* CCompositor::getConstraintWindow(SMouse* pMouse) {
const auto PSURFACE = pMouse->currentConstraint->surface; const auto PSURFACE = pMouse->currentConstraint->surface;
for (auto& w : m_lWindows) { for (auto& w : m_vWindows) {
if (PSURFACE == g_pXWaylandManager->getWindowSurface(&w)) { if (PSURFACE == g_pXWaylandManager->getWindowSurface(w.get())) {
if (!w.m_bIsX11 && !windowValidMapped(&w)) if (!w->m_bIsX11 && w->m_bIsMapped && !w->m_bHidden)
continue; continue;
return &w; return w.get();
} }
} }
@ -944,19 +978,19 @@ SMonitor* CCompositor::getMonitorInDirection(const char& dir) {
auto longestIntersect = -1; auto longestIntersect = -1;
SMonitor* longestIntersectMonitor = nullptr; SMonitor* longestIntersectMonitor = nullptr;
for (auto& m : m_lMonitors) { for (auto& m : m_vMonitors) {
if (&m == m_pLastMonitor) if (m.get() == m_pLastMonitor)
continue; continue;
const auto POSB = m.vecPosition; const auto POSB = m->vecPosition;
const auto SIZEB = m.vecSize; const auto SIZEB = m->vecSize;
switch (dir) { switch (dir) {
case 'l': case 'l':
if (STICKS(POSA.x, POSB.x + SIZEB.x)) { 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)); 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) { if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN; longestIntersect = INTERSECTLEN;
longestIntersectMonitor = &m; longestIntersectMonitor = m.get();
} }
} }
break; 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)); 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) { if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN; longestIntersect = INTERSECTLEN;
longestIntersectMonitor = &m; longestIntersectMonitor = m.get();
} }
} }
break; 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)); 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) { if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN; longestIntersect = INTERSECTLEN;
longestIntersectMonitor = &m; longestIntersectMonitor = m.get();
} }
} }
break; 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)); 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) { if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN; longestIntersect = INTERSECTLEN;
longestIntersectMonitor = &m; longestIntersectMonitor = m.get();
} }
} }
break; break;
@ -999,11 +1033,11 @@ SMonitor* CCompositor::getMonitorInDirection(const char& dir) {
} }
void CCompositor::updateAllWindowsBorders() { void CCompositor::updateAllWindowsBorders() {
for (auto& w : m_lWindows) { for (auto& w : m_vWindows) {
if (!w.m_bIsMapped) if (!w->m_bIsMapped)
continue; continue;
updateWindowBorderColor(&w); updateWindowBorderColor(w.get());
} }
} }
@ -1028,9 +1062,9 @@ void CCompositor::moveWindowToWorkspace(CWindow* pWindow, const std::string& wor
int CCompositor::getNextAvailableMonitorID() { int CCompositor::getNextAvailableMonitorID() {
int64_t topID = -1; int64_t topID = -1;
for (auto& m : m_lMonitors) { for (auto& m : m_vMonitors) {
if ((int64_t)m.ID > topID) if ((int64_t)m->ID > topID)
topID = m.ID; topID = m->ID;
} }
return topID + 1; return topID + 1;
@ -1051,9 +1085,9 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, SMonitor* pMoni
// fix old mon // fix old mon
int nextWorkspaceOnMonitorID = -1; int nextWorkspaceOnMonitorID = -1;
for (auto& w : m_lWorkspaces) { for (auto& w : m_vWorkspaces) {
if (w.m_iMonitorID == POLDMON->ID && w.m_iID != pWorkspace->m_iID) { if (w->m_iMonitorID == POLDMON->ID && w->m_iID != pWorkspace->m_iID) {
nextWorkspaceOnMonitorID = w.m_iID; nextWorkspaceOnMonitorID = w->m_iID;
break; break;
} }
} }
@ -1077,9 +1111,9 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, SMonitor* pMoni
pWorkspace->m_iMonitorID = pMonitor->ID; pWorkspace->m_iMonitorID = pMonitor->ID;
pWorkspace->moveToMonitor(pMonitor->ID); pWorkspace->moveToMonitor(pMonitor->ID);
for (auto& w : m_lWindows) { for (auto& w : m_vWindows) {
if (w.m_iWorkspaceID == pWorkspace->m_iID) if (w->m_iWorkspaceID == pWorkspace->m_iID)
w.m_iMonitorID = pMonitor->ID; w->m_iMonitorID = pMonitor->ID;
} }
if (SWITCHINGISACTIVE) { // if it was active, preserve its' status. If it wasn't, don't. 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 lowestID = 99999;
int highestID = -99999; int highestID = -99999;
for (auto& w : m_lWorkspaces) { for (auto& w : m_vWorkspaces) {
if (w.m_iID < lowestID) if (w->m_iID < lowestID)
lowestID = w.m_iID; lowestID = w->m_iID;
if (w.m_iID > highestID) if (w->m_iID > highestID)
highestID = w.m_iID; highestID = w->m_iID;
} }
return std::clamp(id, lowestID, highestID) != id; 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); g_pXWaylandManager->setWindowFullscreen(pWindow, pWindow->m_bIsFullscreen && mode == FULLSCREEN_FULL);
// make all windows on the same workspace under the fullscreen window // make all windows on the same workspace under the fullscreen window
for (auto& w : g_pCompositor->m_lWindows) { for (auto& w : g_pCompositor->m_vWindows) {
if (w.m_iWorkspaceID == pWindow->m_iWorkspaceID) if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID)
w.m_bCreatedOverFullscreen = false; 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_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr;
wlr_foreign_toplevel_manager_v1* m_sWLRToplevelMgr; wlr_foreign_toplevel_manager_v1* m_sWLRToplevelMgr;
wlr_tablet_manager_v2* m_sWLRTabletManager; wlr_tablet_manager_v2* m_sWLRTabletManager;
wlr_xdg_foreign_registry* m_sWLRForeignRegistry;
// ------------------------------------------------- // // ------------------------------------------------- //
const char* m_szWLDisplaySocket; const char* m_szWLDisplaySocket;
std::string m_szInstanceSignature = ""; std::string m_szInstanceSignature = "";
std::list<SMonitor> m_lMonitors; std::vector<std::unique_ptr<SMonitor>> m_vMonitors;
std::list<CWindow> m_lWindows; std::vector<std::unique_ptr<CWindow>> m_vWindows;
std::list<SXDGPopup> m_lXDGPopups; std::deque<std::unique_ptr<CWindow>> m_dUnmanagedX11Windows;
std::list<CWorkspace> m_lWorkspaces; std::vector<std::unique_ptr<SXDGPopup>> m_vXDGPopups;
std::list<SSubsurface> m_lSubsurfaces; std::vector<std::unique_ptr<CWorkspace>> m_vWorkspaces;
std::list<CWindow*> m_lWindowsFadingOut; std::vector<std::unique_ptr<SSubsurface>> m_vSubsurfaces;
std::list<SLayerSurface*> m_lSurfacesFadingOut; std::vector<CWindow*> m_vWindowsFadingOut;
std::vector<SLayerSurface*> m_vSurfacesFadingOut;
void startCompositor(); void startCompositor();
void cleanupExit(); void cleanupExit();
@ -99,7 +101,7 @@ public:
CWindow* vectorToWindow(const Vector2D&); CWindow* vectorToWindow(const Vector2D&);
CWindow* vectorToWindowIdeal(const Vector2D&); CWindow* vectorToWindowIdeal(const Vector2D&);
CWindow* vectorToWindowTiled(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); wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl);
CWindow* windowFromCursor(); CWindow* windowFromCursor();
CWindow* windowFloatingFromCursor(); CWindow* windowFloatingFromCursor();
@ -133,6 +135,8 @@ public:
void moveWorkspaceToMonitor(CWorkspace*, SMonitor*); void moveWorkspaceToMonitor(CWorkspace*, SMonitor*);
bool workspaceIDOutOfBounds(const int&); bool workspaceIDOutOfBounds(const int&);
void setWindowFullscreen(CWindow*, bool, eFullscreenMode); void setWindowFullscreen(CWindow*, bool, eFullscreenMode);
void moveUnmanagedX11ToWindows(CWindow*);
CWindow* getX11Parent(CWindow*);
private: private:
void initAllSignals(); void initAllSignals();

View File

@ -73,3 +73,20 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
return wlr_box{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y}; 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 // XWayland stuff
bool m_bIsX11 = false; bool m_bIsX11 = false;
bool m_bMappedX11 = false; bool m_bMappedX11 = false;
CWindow* m_pX11Parent = nullptr;
uint64_t m_iX11Type = 0; uint64_t m_iX11Type = 0;
bool m_bIsModal = false; bool m_bIsModal = false;
bool m_bX11DoesntWantBorders = false; bool m_bX11DoesntWantBorders = false;
@ -76,6 +77,7 @@ public:
// For nofocus // For nofocus
bool m_bNoFocus = false; bool m_bNoFocus = false;
bool m_bNoInitialFocus = false;
SSurfaceTreeNode* m_pSurfaceTree = nullptr; SSurfaceTreeNode* m_pSurfaceTree = nullptr;
@ -110,5 +112,7 @@ public:
// methods // methods
wlr_box getFullWindowBoundingBox(); wlr_box getFullWindowBoundingBox();
wlr_box getWindowIdealBoundingBoxIgnoreReserved(); wlr_box getWindowIdealBoundingBoxIgnoreReserved();
void updateWindowDecos();
pid_t getPID();
}; };

View File

@ -15,6 +15,8 @@ CConfigManager::CConfigManager() {
static const char* const ENVHOME = getenv("HOME"); static const char* const ENVHOME = getenv("HOME");
const std::string CONFIGPATH = ENVHOME + (ISDEBUG ? (std::string) "/.config/hypr/hyprlandd.conf" : (std::string) "/.config/hypr/hyprland.conf"); const std::string CONFIGPATH = ENVHOME + (ISDEBUG ? (std::string) "/.config/hypr/hyprlandd.conf" : (std::string) "/.config/hypr/hyprland.conf");
configPaths.emplace_back(CONFIGPATH); configPaths.emplace_back(CONFIGPATH);
Debug::disableLogs = &configValues["debug:disable_logs"].intValue;
} }
void CConfigManager::setDefaultVars() { void CConfigManager::setDefaultVars() {
@ -38,6 +40,8 @@ void CConfigManager::setDefaultVars() {
configValues["debug:int"].intValue = 0; configValues["debug:int"].intValue = 0;
configValues["debug:log_damage"].intValue = 0; configValues["debug:log_damage"].intValue = 0;
configValues["debug:overlay"].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:rounding"].intValue = 1;
configValues["decoration:blur"].intValue = 1; configValues["decoration:blur"].intValue = 1;
@ -47,12 +51,13 @@ void CConfigManager::setDefaultVars() {
configValues["decoration:active_opacity"].floatValue = 1; configValues["decoration:active_opacity"].floatValue = 1;
configValues["decoration:inactive_opacity"].floatValue = 1; configValues["decoration:inactive_opacity"].floatValue = 1;
configValues["decoration:fullscreen_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:no_blur_on_oversized"].intValue = 1;
configValues["decoration:drop_shadow"].intValue = 1; configValues["decoration:drop_shadow"].intValue = 1;
configValues["decoration:shadow_range"].intValue = 4; configValues["decoration:shadow_range"].intValue = 4;
configValues["decoration:shadow_render_power"].intValue = 3; configValues["decoration:shadow_render_power"].intValue = 3;
configValues["decoration:shadow_ignore_window"].intValue = 1; configValues["decoration:shadow_ignore_window"].intValue = 1;
configValues["decoration:shadow_offset"].strValue = "0 0";
configValues["decoration:col.shadow"].intValue = 0xee1a1a1a; configValues["decoration:col.shadow"].intValue = 0xee1a1a1a;
configValues["dwindle:pseudotile"].intValue = 0; configValues["dwindle:pseudotile"].intValue = 0;
@ -103,6 +108,24 @@ void CConfigManager::setDefaultVars() {
configValues["autogenerated"].intValue = 0; 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() { void CConfigManager::init() {
loadConfigLoadVars(); 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."; 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 (COMMAND.find("device:") == 0) {
if (CONFIGENTRY.intValue != -1) { 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 { try {
if (VALUE.find("0x") == 0) { if (VALUE.find("0x") == 0) {
// Values with 0x are hex // Values with 0x are hex
const auto VALUEWITHOUTHEX = VALUE.substr(2); const auto VALUEWITHOUTHEX = VALUE.substr(2);
CONFIGENTRY.intValue = stol(VALUEWITHOUTHEX, nullptr, 16); CONFIGENTRY->intValue = stol(VALUEWITHOUTHEX, nullptr, 16);
} else } else
CONFIGENTRY.intValue = stol(VALUE); CONFIGENTRY->intValue = stol(VALUE);
} catch (...) { } catch (...) {
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str()); Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">."; parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
} }
} else if (CONFIGENTRY.floatValue != -1) { } else if (CONFIGENTRY->floatValue != -1) {
try { try {
CONFIGENTRY.floatValue = stof(VALUE); CONFIGENTRY->floatValue = stof(VALUE);
} catch (...) { } catch (...) {
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str()); Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">."; parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
} }
} else if (CONFIGENTRY.strValue != "") { } else if (CONFIGENTRY->strValue != "") {
try { try {
CONFIGENTRY.strValue = VALUE; CONFIGENTRY->strValue = VALUE;
} catch (...) { } catch (...) {
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str()); Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">."; parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
@ -611,8 +659,8 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
parseError = ""; parseError = "";
// invalidate layouts jic // invalidate layouts jic
for (auto& m : g_pCompositor->m_lMonitors) for (auto& m : g_pCompositor->m_vMonitors)
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m.ID); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
// Update window border colors // Update window border colors
g_pCompositor->updateAllWindowsBorders(); g_pCompositor->updateAllWindowsBorders();
@ -704,6 +752,7 @@ void CConfigManager::loadConfigLoadVars() {
g_pAnimationManager->removeAllBeziers(); g_pAnimationManager->removeAllBeziers();
m_mAdditionalReservedAreas.clear(); m_mAdditionalReservedAreas.clear();
configDynamicVars.clear(); configDynamicVars.clear();
deviceConfigs.clear();
// paths // paths
configPaths.clear(); configPaths.clear();
@ -772,8 +821,8 @@ void CConfigManager::loadConfigLoadVars() {
ifs.close(); ifs.close();
} }
for (auto& m : g_pCompositor->m_lMonitors) for (auto& m : g_pCompositor->m_vMonitors)
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m.ID); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
// Update the keyboard layout to the cfg'd one if this is not the first launch // Update the keyboard layout to the cfg'd one if this is not the first launch
if (!isFirstLaunch) if (!isFirstLaunch)
@ -806,6 +855,10 @@ void CConfigManager::loadConfigLoadVars() {
// Update window border colors // Update window border colors
g_pCompositor->updateAllWindowsBorders(); 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() { void CConfigManager::tick() {
@ -843,7 +896,7 @@ void CConfigManager::tick() {
} }
std::mutex configmtx; std::mutex configmtx;
SConfigValue CConfigManager::getConfigValueSafe(std::string val) { SConfigValue CConfigManager::getConfigValueSafe(const std::string& val) {
std::lock_guard<std::mutex> lg(configmtx); std::lock_guard<std::mutex> lg(configmtx);
SConfigValue copy = configValues[val]; SConfigValue copy = configValues[val];
@ -851,15 +904,38 @@ SConfigValue CConfigManager::getConfigValueSafe(std::string val) {
return copy; 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; return getConfigValueSafe(v).intValue;
} }
float CConfigManager::getFloat(std::string v) { float CConfigManager::getFloat(const std::string& v) {
return getConfigValueSafe(v).floatValue; 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; const auto VAL = getConfigValueSafe(v).strValue;
if (VAL == STRVAL_EMPTY) if (VAL == STRVAL_EMPTY)
@ -868,6 +944,23 @@ std::string CConfigManager::getString(std::string v) {
return VAL; 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) { void CConfigManager::setInt(std::string v, int val) {
configValues[v].intValue = val; configValues[v].intValue = val;
} }
@ -964,14 +1057,30 @@ void CConfigManager::dispatchExecOnce() {
} }
void CConfigManager::performMonitorReload() { void CConfigManager::performMonitorReload() {
for (auto& m : g_pCompositor->m_lMonitors) {
auto rule = getMonitorRuleFor(m.szName); bool overAgain = false;
g_pHyprRenderer->applyMonitorRule(&m, &rule);
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; m_bWantsMonitorReload = false;
} }
SConfigValue* CConfigManager::getConfigValuePtr(std::string val) { SConfigValue* CConfigManager::getConfigValuePtr(std::string val) {
return &configValues[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; int64_t intValue = -1;
float floatValue = -1; float floatValue = -1;
std::string strValue = ""; std::string strValue = "";
bool set = false; // used for device configs
}; };
struct SMonitorRule { struct SMonitorRule {
@ -52,13 +54,18 @@ public:
void tick(); void tick();
void init(); void init();
int getInt(std::string); int getInt(const std::string&);
float getFloat(std::string); float getFloat(const std::string&);
std::string getString(std::string); std::string getString(const std::string&);
void setFloat(std::string, float); void setFloat(std::string, float);
void setInt(std::string, int); void setInt(std::string, int);
void setString(std::string, std::string); 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); SConfigValue* getConfigValuePtr(std::string);
SMonitorRule getMonitorRuleFor(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, 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, std::string> configDynamicVars; // stores dynamic vars declared by the user
std::unordered_map<std::string, SConfigValue> configValues; 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; std::string configCurrentPath;
@ -100,12 +108,15 @@ private:
// internal methods // internal methods
void setDefaultVars(); void setDefaultVars();
void setDeviceDefaultVars(const std::string&);
void applyUserDefinedVars(std::string&, const size_t); void applyUserDefinedVars(std::string&, const size_t);
void loadConfigLoadVars(); void loadConfigLoadVars();
SConfigValue getConfigValueSafe(std::string); SConfigValue getConfigValueSafe(const std::string&);
SConfigValue getConfigValueSafeDevice(const std::string&, const std::string&);
void parseLine(std::string&); void parseLine(std::string&);
void configSetValueSafe(const std::string&, const 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 handleRawExec(const std::string&, const std::string&);
void handleMonitor(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); void handleBind(const std::string&, const std::string&, bool locked = false);

View File

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

View File

@ -15,9 +15,9 @@
std::string monitorsRequest() { std::string monitorsRequest() {
std::string result = ""; std::string result = "";
for (auto& m : g_pCompositor->m_lMonitors) { 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\n", 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.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); 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; return result;
@ -25,19 +25,21 @@ std::string monitorsRequest() {
std::string clientsRequest() { std::string clientsRequest() {
std::string result = ""; std::string result = "";
for (auto& w : g_pCompositor->m_lWindows) { for (auto& w : g_pCompositor->m_vWindows) {
if (w.m_bIsMapped) 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", 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).c_str()); &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; return result;
} }
std::string workspacesRequest() { std::string workspacesRequest() {
std::string result = ""; 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", 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; return result;
} }
@ -48,17 +50,17 @@ std::string activeWindowRequest() {
if (!g_pCompositor->windowValidMapped(PWINDOW)) if (!g_pCompositor->windowValidMapped(PWINDOW))
return "Invalid"; 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", 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()); 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 layersRequest() {
std::string result = ""; std::string result = "";
for (auto& mon : g_pCompositor->m_lMonitors) { for (auto& mon : g_pCompositor->m_vMonitors) {
result += getFormat("Monitor %s:\n"); result += getFormat("Monitor %s:\n");
int layerLevel = 0; int layerLevel = 0;
for (auto& level : mon.m_aLayerSurfaceLists) { for (auto& level : mon->m_aLayerSurfaceLists) {
result += getFormat("\tLayer level %i:\n", layerLevel); result += getFormat("\tLayer level %i:\n", layerLevel);
for (auto& layer : level) { for (auto& layer : level) {
@ -173,6 +175,12 @@ std::string reloadRequest() {
return "ok"; return "ok";
} }
std::string killRequest() {
g_pInputManager->setClickMode(CLICKMODE_KILL);
return "ok";
}
std::string getReply(std::string); std::string getReply(std::string);
std::string dispatchBatch(std::string request) { std::string dispatchBatch(std::string request) {
@ -214,6 +222,8 @@ std::string getReply(std::string request) {
return workspacesRequest(); return workspacesRequest();
else if (request == "clients") else if (request == "clients")
return clientsRequest(); return clientsRequest();
else if (request == "kill")
return killRequest();
else if (request == "activewindow") else if (request == "activewindow")
return activeWindowRequest(); return activeWindowRequest();
else if (request == "layers") else if (request == "layers")

View File

@ -120,7 +120,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
yOffset += 11; yOffset += 11;
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox); 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); g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
return yOffset - offset; return yOffset - offset;
@ -140,7 +140,7 @@ void CHyprDebugOverlay::frameData(SMonitor* pMonitor) {
void CHyprDebugOverlay::draw() { 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) { if (!m_pCairoSurface || !m_pCairo) {
m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecSize.x, PMONITOR->vecSize.y); 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 // draw the things
int offsetY = 0; int offsetY = 0;
for (auto& m : g_pCompositor->m_lMonitors) { for (auto& m : g_pCompositor->m_vMonitors) {
offsetY += m_mMonitorOverlays[&m].draw(offsetY); offsetY += m_mMonitorOverlays[m.get()].draw(offsetY);
offsetY += 5; // for padding between mons 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, ...) { void Debug::log(LogLevel level, const char* fmt, ...) {
if (disableLogs && *disableLogs)
return;
// log to a file // log to a file
std::ofstream ofs; std::ofstream ofs;
ofs.open(logFile, std::ios::out | std::ios::app); ofs.open(logFile, std::ios::out | std::ios::app);

View File

@ -17,4 +17,5 @@ namespace Debug {
void log(LogLevel level, const char* fmt, ...); void log(LogLevel level, const char* fmt, ...);
inline std::string logFile; 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) { void Events::listener_requestMouse(wl_listener* listener, void* data) {
const auto EVENT = (wlr_seat_pointer_request_set_cursor_event*)data; const auto EVENT = (wlr_seat_pointer_request_set_cursor_event*)data;
if (!g_pHyprRenderer->shouldRenderCursor()) g_pInputManager->processMouseRequest(EVENT);
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);
} }
void Events::listener_newInput(wl_listener* listener, void* data) { 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(); SLayerSurface* layerSurface = PMONITOR->m_aLayerSurfaceLists[WLRLAYERSURFACE->pending.layer].back();
if (!WLRLAYERSURFACE->output) { 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"); 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; layersurface->fadingOut = true;
g_pCompositor->m_lSurfacesFadingOut.push_back(layersurface); g_pCompositor->m_vSurfacesFadingOut.push_back(layersurface);
if (layersurface->layerSurface->mapped) if (layersurface->layerSurface->mapped)
layersurface->layerSurface->mapped = false; layersurface->layerSurface->mapped = false;
@ -179,7 +179,7 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
if (!PMONITOR) if (!PMONITOR)
return; 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); g_pHyprRenderer->damageBox(&geomFixed);
// fix if it changed its mon // 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); 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->damageSurface(layersurface->layerSurface->surface, layersurface->position.x, layersurface->position.y);
g_pHyprRenderer->damageMonitor(PMONITOR);
} }

View File

@ -21,24 +21,24 @@ void Events::listener_change(wl_listener* listener, void* data) {
// layout got changed, let's update monitors. // layout got changed, let's update monitors.
const auto CONFIG = wlr_output_configuration_v1_create(); const auto CONFIG = wlr_output_configuration_v1_create();
for (auto& m : g_pCompositor->m_lMonitors) { for (auto& m : g_pCompositor->m_vMonitors) {
const auto CONFIGHEAD = wlr_output_configuration_head_v1_create(CONFIG, m.output); const auto CONFIGHEAD = wlr_output_configuration_head_v1_create(CONFIG, m->output);
// TODO: clients off of disabled // TODO: clients off of disabled
wlr_box BOX; 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.x = BOX.width;
// m.vecSize.y = BOX.height; // m->vecSize.y = BOX.height;
m.vecPosition.x = BOX.x; m->vecPosition.x = BOX.x;
m.vecPosition.y = BOX.y; m->vecPosition.y = BOX.y;
CONFIGHEAD->state.enabled = m.output->enabled; CONFIGHEAD->state.enabled = m->output->enabled;
CONFIGHEAD->state.mode = m.output->current_mode; CONFIGHEAD->state.mode = m->output->current_mode;
CONFIGHEAD->state.x = m.vecPosition.x; CONFIGHEAD->state.x = m->vecPosition.x;
CONFIGHEAD->state.y = m.vecPosition.y; 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); 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.vecSize = monitorRule.resolution;
newMonitor.refreshRate = monitorRule.refreshRate; newMonitor.refreshRate = monitorRule.refreshRate;
g_pCompositor->m_lMonitors.push_back(newMonitor); const auto PNEWMONITOR = g_pCompositor->m_vMonitors.emplace_back(std::make_unique<SMonitor>(newMonitor)).get();
const auto PNEWMONITOR = &g_pCompositor->m_lMonitors.back();
PNEWMONITOR->hyprListener_monitorFrame.initCallback(&OUTPUT->events.frame, &Events::listener_monitorFrame, PNEWMONITOR); PNEWMONITOR->hyprListener_monitorFrame.initCallback(&OUTPUT->events.frame, &Events::listener_monitorFrame, PNEWMONITOR);
PNEWMONITOR->hyprListener_monitorDestroy.initCallback(&OUTPUT->events.destroy, &Events::listener_monitorDestroy, 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 // Workspace
std::string newDefaultWorkspaceName = ""; 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) { 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); newDefaultWorkspaceName = std::to_string(WORKSPACEID);
Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"%s\" is invalid.", monitorRule.defaultWorkspace); 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); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PNEWMONITOR->ID);
PNEWWORKSPACE->startAnim(true,true,true); PNEWWORKSPACE->startAnim(true,true,true);
} else { } 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 // We are required to set the name here immediately
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, newDefaultWorkspaceName.c_str()); wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, newDefaultWorkspaceName.c_str());
PNEWWORKSPACE->m_iID = WORKSPACEID; PNEWWORKSPACE->m_iID = WORKSPACEID;
PNEWWORKSPACE->m_szName = newDefaultWorkspaceName;
} }
PNEWMONITOR->activeWorkspace = PNEWWORKSPACE->m_iID; 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 PDEBUGOVERLAY = &g_pConfigManager->getConfigValuePtr("debug:overlay")->intValue;
static auto *const PDAMAGETRACKINGMODE = &g_pConfigManager->getConfigValuePtr("general:damage_tracking_internal")->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) { if (*PDEBUGOVERLAY == 1) {
startRender = std::chrono::high_resolution_clock::now(); startRender = std::chrono::high_resolution_clock::now();
@ -227,7 +228,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
return; 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); pixman_region32_fini(&damage);
wlr_output_rollback(PMONITOR->output); 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 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 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_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage); 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(); 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_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
wlr_output_render_software_cursors(PMONITOR->output, NULL); 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) 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); 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); wlr_output_set_damage(PMONITOR->output, &frameDamage);
pixman_region32_fini(&frameDamage); pixman_region32_fini(&frameDamage);
pixman_region32_fini(&damage); pixman_region32_fini(&damage);
@ -324,9 +338,9 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
SMonitor* pMonitor = nullptr; SMonitor* pMonitor = nullptr;
for (auto& m : g_pCompositor->m_lMonitors) { for (auto& m : g_pCompositor->m_vMonitors) {
if (m.szName == OUTPUT->name) { if (m->szName == OUTPUT->name) {
pMonitor = &m; pMonitor = m.get();
break; break;
} }
} }
@ -335,7 +349,7 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
return; return;
// Cleanup everything. Move windows back, snap cursor, shit. // 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) { if (!BACKUPMON) {
Debug::log(CRIT, "No monitors! Unplugged last! Exiting."); Debug::log(CRIT, "No monitors! Unplugged last! Exiting.");
@ -351,9 +365,9 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
// move workspaces // move workspaces
std::deque<CWorkspace*> wspToMove; std::deque<CWorkspace*> wspToMove;
for (auto& w : g_pCompositor->m_lWorkspaces) { for (auto& w : g_pCompositor->m_vWorkspaces) {
if (w.m_iMonitorID == pMonitor->ID) { if (w->m_iMonitorID == pMonitor->ID) {
wspToMove.push_back(&w); wspToMove.push_back(w.get());
} }
} }
@ -364,27 +378,23 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
pMonitor->activeWorkspace = -1; pMonitor->activeWorkspace = -1;
for (auto it = g_pCompositor->m_lWorkspaces.begin(); it != g_pCompositor->m_lWorkspaces.end(); ++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; }));
if (it->m_iMonitorID == pMonitor->ID) {
it = g_pCompositor->m_lWorkspaces.erase(it);
}
}
Debug::log(LOG, "Removed monitor %s!", pMonitor->szName.c_str()); Debug::log(LOG, "Removed monitor %s!", pMonitor->szName.c_str());
g_pEventManager->postEvent(SHyprIPCEvent("monitorremoved", pMonitor->szName)); 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 // update the pMostHzMonitor
if (pMostHzMonitor == pMonitor) { if (pMostHzMonitor == pMonitor) {
int mostHz = 0; int mostHz = 0;
SMonitor* pMonitorMostHz = nullptr; SMonitor* pMonitorMostHz = nullptr;
for (auto& m : g_pCompositor->m_lMonitors) { for (auto& m : g_pCompositor->m_vMonitors) {
if (m.refreshRate > mostHz) { if (m->refreshRate > mostHz) {
pMonitorMostHz = &m; pMonitorMostHz = m.get();
mostHz = m.refreshRate; mostHz = m->refreshRate;
} }
} }

View File

@ -76,8 +76,7 @@ void Events::listener_newPopup(void* owner, void* data) {
const auto WLRPOPUP = (wlr_xdg_popup*)data; const auto WLRPOPUP = (wlr_xdg_popup*)data;
g_pCompositor->m_lXDGPopups.push_back(SXDGPopup()); const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
const auto PNEWPOPUP = &g_pCompositor->m_lXDGPopups.back();
const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID); 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; const auto WLRPOPUP = (wlr_xdg_popup*)data;
g_pCompositor->m_lXDGPopups.push_back(SXDGPopup()); const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
const auto PNEWPOPUP = &g_pCompositor->m_lXDGPopups.back();
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); 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; const auto WLRPOPUP = (wlr_xdg_popup*)data;
g_pCompositor->m_lXDGPopups.push_back(SXDGPopup()); const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
const auto PNEWPOPUP = &g_pCompositor->m_lXDGPopups.back();
PNEWPOPUP->popup = WLRPOPUP; PNEWPOPUP->popup = WLRPOPUP;
PNEWPOPUP->parentPopup = PPOPUP; PNEWPOPUP->parentPopup = PPOPUP;
@ -170,5 +167,5 @@ void Events::listener_destroyPopupXDG(void* owner, void* data) {
PPOPUP->pSurfaceTree = nullptr; 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_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
PWINDOW->m_fAlpha = 255.f; PWINDOW->m_fAlpha = 255.f;
if (PWINDOW->m_iX11Type == 2)
g_pCompositor->moveUnmanagedX11ToWindows(PWINDOW);
// Set all windows tiled regardless of anything // Set all windows tiled regardless of anything
g_pXWaylandManager->setWindowStyleTiled(PWINDOW, WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM); 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); const auto PWINDOWSURFACE = g_pXWaylandManager->getWindowSurface(PWINDOW);
if (!PWINDOWSURFACE) { if (!PWINDOWSURFACE) {
g_pCompositor->m_lWindows.remove(*PWINDOW); g_pCompositor->removeWindowFromVectorSafe(PWINDOW);
return; return;
} }
@ -97,7 +100,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_iMonitorID = PMONITOR->ID; PWINDOW->m_iMonitorID = PMONITOR->ID;
} else { } else {
const long int MONITOR = std::stoi(MONITORSTR); 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; PWINDOW->m_iMonitorID = 0;
else else
PWINDOW->m_iMonitorID = MONITOR; 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); 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); 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); Debug::log(LOG, "Window got assigned a surfaceTreeNode %x", PWINDOW->m_pSurfaceTree);
if (!PWINDOW->m_bIsX11) { if (!PWINDOW->m_bIsX11) {
@ -260,16 +261,25 @@ void Events::listener_mapWindow(void* owner, void* data) {
} }
if (requestsFullscreen) { 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); 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); 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) { void Events::listener_unmapWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner; 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) { 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); 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(); 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. // Allow the renderer to catch the last frame.
g_pHyprOpenGL->makeWindowSnapshot(PWINDOW); g_pHyprOpenGL->makeWindowSnapshot(PWINDOW);
@ -318,12 +333,14 @@ void Events::listener_unmapWindow(void* owner, void* data) {
PWINDOW->m_bFadingOut = true; 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)); g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID));
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
// do the animation thing // 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(); PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.vec();
if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in. 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) { void Events::listener_destroyWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner; 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) { if (PWINDOW == g_pCompositor->m_pLastWindow) {
g_pCompositor->m_pLastWindow = nullptr; 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; const auto REQUESTED = &PWINDOW->m_uSurface.xdg->toplevel->requested;
if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen) if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen)
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, true); g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, REQUESTED->fullscreen);
} else { } 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); 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) { void Events::listener_surfaceXWayland(wl_listener* listener, void* data) {
const auto XWSURFACE = (wlr_xwayland_surface*)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 = 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();
const auto PNEWWINDOW = &g_pCompositor->m_lWindows.back();
PNEWWINDOW->m_uSurface.xwayland = XWSURFACE; PNEWWINDOW->m_uSurface.xwayland = XWSURFACE;
PNEWWINDOW->m_iX11Type = XWSURFACE->override_redirect ? 2 : 1; PNEWWINDOW->m_iX11Type = XWSURFACE->override_redirect ? 2 : 1;
PNEWWINDOW->m_bIsX11 = true; 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_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_unmapWindow.initCallback(&XWSURFACE->events.unmap, &Events::listener_unmapWindow, PNEWWINDOW, "XWayland Window");
PNEWWINDOW->hyprListener_destroyWindow.initCallback(&XWSURFACE->events.destroy, &Events::listener_destroyWindow, 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 // A window got opened
const auto XDGSURFACE = (wlr_xdg_surface*)data; 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) if (XDGSURFACE->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL)
return; // TODO: handle? return; // TODO: handle?
g_pCompositor->m_lWindows.emplace_back(); const auto PNEWWINDOW = g_pCompositor->m_vWindows.emplace_back(std::make_unique<CWindow>()).get();
const auto PNEWWINDOW = &g_pCompositor->m_lWindows.back();
PNEWWINDOW->m_uSurface.xdg = XDGSURFACE; PNEWWINDOW->m_uSurface.xdg = XDGSURFACE;
PNEWWINDOW->hyprListener_mapWindow.initCallback(&XDGSURFACE->events.map, &Events::listener_mapWindow, PNEWWINDOW, "XDG Window"); 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) // gets the current vector value (real time)
const Vector2D& vec() const { const Vector2D& vec() const {
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access vec() of AVARTYPE %i!", m_eVarType);
return m_vValue; return m_vValue;
} }
// gets the current float value (real time) // gets the current float value (real time)
const float& fl() const { const float& fl() const {
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access fl() of AVARTYPE %i!", m_eVarType);
return m_fValue; return m_fValue;
} }
// gets the current color value (real time) // gets the current color value (real time)
const CColor& col() const { const CColor& col() const {
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access col() of AVARTYPE %i!", m_eVarType);
return m_cValue; return m_cValue;
} }
// gets the goal vector value // gets the goal vector value
const Vector2D& goalv() const { const Vector2D& goalv() const {
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access goalv() of AVARTYPE %i!", m_eVarType);
return m_vGoal; return m_vGoal;
} }
// gets the goal float value // gets the goal float value
const float& goalf() const { const float& goalf() const {
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access goalf() of AVARTYPE %i!", m_eVarType);
return m_fGoal; return m_fGoal;
} }
// gets the goal color value // gets the goal color value
const CColor& goalc() const { const CColor& goalc() const {
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access goalc() of AVARTYPE %i!", m_eVarType);
return m_cGoal; return m_cGoal;
} }
void operator=(const Vector2D& v) { void operator=(const Vector2D& v) {
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access =v of AVARTYPE %i!", m_eVarType);
m_vGoal = v; m_vGoal = v;
animationBegin = std::chrono::system_clock::now(); animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue; m_vBegun = m_vValue;
} }
void operator=(const float& v) { void operator=(const float& v) {
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access =f of AVARTYPE %i!", m_eVarType);
m_fGoal = v; m_fGoal = v;
animationBegin = std::chrono::system_clock::now(); animationBegin = std::chrono::system_clock::now();
m_fBegun = m_fValue; m_fBegun = m_fValue;
} }
void operator=(const CColor& v) { void operator=(const CColor& v) {
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access =c of AVARTYPE %i!", m_eVarType);
m_cGoal = v; m_cGoal = v;
animationBegin = std::chrono::system_clock::now(); animationBegin = std::chrono::system_clock::now();
m_cBegun = m_cValue; m_cBegun = m_cValue;
@ -90,7 +81,6 @@ public:
// Sets the actual stored value, without affecting the goal, but resets the timer // Sets the actual stored value, without affecting the goal, but resets the timer
void setValue(const Vector2D& v) { void setValue(const Vector2D& v) {
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access setValue(v) of AVARTYPE %i!", m_eVarType);
m_vValue = v; m_vValue = v;
animationBegin = std::chrono::system_clock::now(); animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue; m_vBegun = m_vValue;
@ -98,7 +88,6 @@ public:
// Sets the actual stored value, without affecting the goal, but resets the timer // Sets the actual stored value, without affecting the goal, but resets the timer
void setValue(const float& v) { void setValue(const float& v) {
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access setValue(f) of AVARTYPE %i!", m_eVarType);
m_fValue = v; m_fValue = v;
animationBegin = std::chrono::system_clock::now(); animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue; m_vBegun = m_vValue;
@ -106,7 +95,6 @@ public:
// Sets the actual stored value, without affecting the goal, but resets the timer // Sets the actual stored value, without affecting the goal, but resets the timer
void setValue(const CColor& v) { void setValue(const CColor& v) {
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access setValue(c) of AVARTYPE %i!", m_eVarType);
m_cValue = v; m_cValue = v;
animationBegin = std::chrono::system_clock::now(); animationBegin = std::chrono::system_clock::now();
m_vBegun = m_vValue; m_vBegun = m_vValue;
@ -114,21 +102,18 @@ public:
// Sets the actual value and goal // Sets the actual value and goal
void setValueAndWarp(const Vector2D& v) { void setValueAndWarp(const Vector2D& v) {
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access setValueAndWarp(v) of AVARTYPE %i!", m_eVarType);
m_vGoal = v; m_vGoal = v;
warp(); warp();
} }
// Sets the actual value and goal // Sets the actual value and goal
void setValueAndWarp(const float& v) { void setValueAndWarp(const float& v) {
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access setValueAndWarp(f) of AVARTYPE %i!", m_eVarType);
m_fGoal = v; m_fGoal = v;
warp(); warp();
} }
// Sets the actual value and goal // Sets the actual value and goal
void setValueAndWarp(const CColor& v) { void setValueAndWarp(const CColor& v) {
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access setValueAndWarp(c) of AVARTYPE %i!", m_eVarType);
m_cGoal = v; m_cGoal = v;
warp(); warp();
} }

View File

@ -4,6 +4,41 @@
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include <sys/utsname.h> #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) { void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, std::string ownerString) {
ASSERT(pSignal); ASSERT(pSignal);
ASSERT(pListener); ASSERT(pListener);
@ -79,8 +114,8 @@ std::string getFormat(const char *fmt, ...) {
} }
void scaleBox(wlr_box* box, float scale) { void scaleBox(wlr_box* box, float scale) {
box->width = std::round((box->x + box->width) * scale) - std::round(box->x * scale); box->width = std::round(box->width * scale);
box->height = std::round((box->y + box->height) * scale) - std::round(box->y * scale); box->height = std::round(box->height * scale);
box->x = std::round(box->x * scale); box->x = std::round(box->x * scale);
box->y = std::round(box->y * scale); box->y = std::round(box->y * scale);
} }
@ -135,8 +170,8 @@ float getPlusMinusKeywordResult(std::string source, float relative) {
return result; return result;
} }
bool isNumber(const std::string& str) { bool isNumber(const std::string& str, bool allowfloat) {
return std::ranges::all_of(str.begin(), str.end(), [](char c) { return isdigit(c) != 0 || c == '-'; }); return std::ranges::all_of(str.begin(), str.end(), [&](char c) { return isdigit(c) != 0 || c == '-' || (allowfloat && c == '.'); });
} }
bool isDirection(const std::string& arg) { bool isDirection(const std::string& arg) {
@ -184,12 +219,12 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
int lowestID = 99999; int lowestID = 99999;
int highestID = -99999; int highestID = -99999;
for (auto& w : g_pCompositor->m_lWorkspaces) { for (auto& w : g_pCompositor->m_vWorkspaces) {
if (w.m_iID < lowestID) if (w->m_iID < lowestID)
lowestID = w.m_iID; lowestID = w->m_iID;
if (w.m_iID > highestID) if (w->m_iID > highestID)
highestID = w.m_iID; highestID = w->m_iID;
} }
if (remains < 0) if (remains < 0)
@ -265,3 +300,24 @@ void logSystemInfo() {
Debug::log(NONE, "%s", execAndGet("cat /etc/os-release").c_str()); 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,7 +7,7 @@ void wlr_signal_emit_safe(struct wl_signal *signal, void *data);
std::string getFormat(const char *fmt, ...); // Basically Debug::log to a string std::string getFormat(const char *fmt, ...); // Basically Debug::log to a string
void scaleBox(wlr_box*, float); void scaleBox(wlr_box*, float);
std::string removeBeginEndSpacesTabs(std::string); std::string removeBeginEndSpacesTabs(std::string);
bool isNumber(const std::string&); bool isNumber(const std::string&, bool allowfloat = false);
bool isDirection(const std::string&); bool isDirection(const std::string&);
int getWorkspaceIDFromString(const std::string&, std::string&); int getWorkspaceIDFromString(const std::string&, std::string&);
float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2); float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2);
@ -15,3 +15,5 @@ void logSystemInfo();
std::string execAndGet(const char*); 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 // no damaging if it's not visible
if (!g_pHyprRenderer->shouldRenderWindow(pNode->pWindowOwner)) { 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); Debug::log(LOG, "Refusing to commit damage from %x because it's invisible.", pNode->pWindowOwner);
return; return;
} }
int lx = 0, ly = 0; int lx = 0, ly = 0;
addSurfaceGlobalOffset(pNode, &lx, &ly); 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); g_pHyprRenderer->damageSurface(pNode->pSurface, lx, ly);
} }

View File

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

View File

@ -1,7 +1,7 @@
#include "Workspace.hpp" #include "Workspace.hpp"
#include "../Compositor.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); const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
if (!PMONITOR) { if (!PMONITOR) {
@ -10,7 +10,7 @@ CWorkspace::CWorkspace(int monitorID, bool special) {
} }
m_iMonitorID = monitorID; m_iMonitorID = monitorID;
m_szName = name;
m_bIsSpecialWorkspace = special; m_bIsSpecialWorkspace = special;
if (!special) { if (!special) {
@ -30,6 +30,8 @@ CWorkspace::CWorkspace(int monitorID, bool special) {
m_fAlpha.m_pWorkspace = this; 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.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); m_fAlpha.setValueAndWarp(255.f);
g_pEventManager->postEvent({"createworkspace", m_szName}, true);
} }
CWorkspace::~CWorkspace() { CWorkspace::~CWorkspace() {
@ -42,6 +44,8 @@ CWorkspace::~CWorkspace() {
wlr_ext_workspace_handle_v1_destroy(m_pWlrHandle); wlr_ext_workspace_handle_v1_destroy(m_pWlrHandle);
m_pWlrHandle = nullptr; m_pWlrHandle = nullptr;
} }
g_pEventManager->postEvent({"destroyworkspace", m_szName}, true);
} }
void CWorkspace::startAnim(bool in, bool left, bool instant) { void CWorkspace::startAnim(bool in, bool left, bool instant) {

View File

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

View File

@ -12,7 +12,7 @@ void CHyprError::createQueued() {
m_tTexture.destroyTexture(); 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); 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_tTexture.destroyTexture();
m_bIsCreated = false; m_bIsCreated = false;
m_szQueued = ""; m_szQueued = "";
g_pHyprRenderer->damageMonitor(&g_pCompositor->m_lMonitors.front()); g_pHyprRenderer->damageMonitor(g_pCompositor->m_vMonitors.front().get());
return; 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) if (g_pHyprOpenGL->m_RenderData.pMonitor != PMONITOR)
return; // wrong mon return; // wrong mon

View File

@ -88,6 +88,9 @@ extern "C" {
#include <wlr/types/wlr_pointer_constraints_v1.h> #include <wlr/types/wlr_pointer_constraints_v1.h>
#include <wlr/types/wlr_relative_pointer_v1.h> #include <wlr/types/wlr_relative_pointer_v1.h>
#include <wlr/interfaces/wlr_keyboard.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 #undef class
@ -114,3 +117,5 @@ extern "C" {
#include "helpers/Vector2D.hpp" #include "helpers/Vector2D.hpp"
#include "ext-workspace-unstable-v1-protocol.h" #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); g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
} }
PWINDOW->updateWindowDecos();
} }
void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) { void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
if (pWindow->m_bIsFloating) if (pWindow->m_bIsFloating)
return; 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); const auto PNODE = getNodeFromWindow(pWindow);
@ -399,145 +401,8 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
} }
} }
void CHyprDwindleLayout::changeWindowFloatingMode(CWindow* pWindow) { bool CHyprDwindleLayout::isWindowTiled(CWindow* pWindow) {
return getNodeFromWindow(pWindow) != nullptr;
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);
} }
void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* pWindow) { void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* pWindow) {
@ -551,6 +416,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
if (!PNODE) { 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->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; return;
} }
@ -627,55 +493,6 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
TOPCONTAINER->recalcSizePosRecursive(); 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) { void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode, bool on) {
if (!g_pCompositor->windowValidMapped(pWindow)) if (!g_pCompositor->windowValidMapped(pWindow))
return; return;
@ -731,6 +548,8 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight; fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
fakeNode.workspaceID = pWindow->m_iWorkspaceID; fakeNode.workspaceID = pWindow->m_iWorkspaceID;
pWindow->m_vPosition = fakeNode.position;
pWindow->m_vSize = fakeNode.size;
applyNodeDataToWindow(&fakeNode); applyNodeDataToWindow(&fakeNode);
} }
@ -1002,19 +821,3 @@ void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) {
std::string CHyprDwindleLayout::getLayoutName() { std::string CHyprDwindleLayout::getLayoutName() {
return "dwindle"; 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 { class CHyprDwindleLayout : public IHyprLayout {
public: public:
virtual void onWindowCreated(CWindow*); virtual void onWindowCreatedTiling(CWindow*);
virtual void onWindowRemoved(CWindow*); virtual void onWindowRemovedTiling(CWindow*);
virtual bool isWindowTiled(CWindow*);
virtual void recalculateMonitor(const int&); virtual void recalculateMonitor(const int&);
virtual void recalculateWindow(CWindow*); virtual void recalculateWindow(CWindow*);
virtual void changeWindowFloatingMode(CWindow*);
virtual void onBeginDragWindow();
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr); 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 void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
virtual std::any layoutMessage(SLayoutMessageHeader, std::string); virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*); virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
@ -60,15 +55,10 @@ public:
virtual void alterSplitRatioBy(CWindow*, float); virtual void alterSplitRatioBy(CWindow*, float);
virtual std::string getLayoutName(); virtual std::string getLayoutName();
private: private:
std::list<SDwindleNodeData> m_lDwindleNodesData; std::list<SDwindleNodeData> m_lDwindleNodesData;
Vector2D m_vBeginDragXY;
Vector2D m_vLastDragXY;
Vector2D m_vBeginDragPositionXY;
Vector2D m_vBeginDragSizeXY;
int getNodesOnWorkspace(const int&); int getNodesOnWorkspace(const int&);
void applyNodeDataToWindow(SDwindleNodeData*); void applyNodeDataToWindow(SDwindleNodeData*);
SDwindleNodeData* getNodeFromWindow(CWindow*); 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) 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. 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) 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 Called when the monitor requires a layout recalculation
this usually means reserved area changes this usually means reserved area changes
@ -42,13 +52,13 @@ public:
/* /*
Called when a window is requested to be floated 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 Called when a window is clicked on, beginning a drag
this might be a resize, move, whatever the layout defines it this might be a resize, move, whatever the layout defines it
as. as.
*/ */
virtual void onBeginDragWindow() = 0; virtual void onBeginDragWindow();
/* /*
Called when a user requests a resize of the current window by a vec Called when a user requests a resize of the current window by a vec
Vector2D holds pixel values Vector2D holds pixel values
@ -60,24 +70,18 @@ public:
Vector2D holds pixel values Vector2D holds pixel values
Optional pWindow for a specific window 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 Called when a window is ended being dragged
(mouse up) (mouse up)
*/ */
virtual void onEndDragWindow() = 0; virtual void onEndDragWindow();
/* /*
Called whenever the mouse moves, should the layout want to Called whenever the mouse moves, should the layout want to
do anything with it. do anything with it.
Useful for dragging. Useful for dragging.
*/ */
virtual void onMouseMove(const Vector2D&) = 0; virtual void onMouseMove(const Vector2D&);
/*
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;
/* /*
Called when a window / the user requests to toggle the fullscreen state of a window 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 Called when something wants the current layout's name
*/ */
virtual std::string getLayoutName() = 0; 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"); DEFAULTBEZIER = m_mBezierCurves.find("default");
for (auto& av : m_lAnimatedVariables) { for (auto& av : m_lAnimatedVariables) {
// first of all, check if we need to update it at all
if (!av->isBeingAnimated())
continue;
// get speed // get speed
const auto SPEED = *av->m_pSpeed == 0 ? *PANIMSPEED : *av->m_pSpeed; 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 // window stuff
const auto PWINDOW = (CWindow*)av->m_pWindow; const auto PWINDOW = (CWindow*)av->m_pWindow;
const auto PWORKSPACE = (CWorkspace*)av->m_pWorkspace; const auto PWORKSPACE = (CWorkspace*)av->m_pWorkspace;
@ -47,7 +56,7 @@ void CAnimationManager::tick() {
wlr_box WLRBOXPREV = {0,0,0,0}; wlr_box WLRBOXPREV = {0,0,0,0};
if (PWINDOW) { 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) { } else if (PWORKSPACE) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); 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}; 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 // beziers are with a switch unforto
// TODO: maybe do something cleaner // 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) { switch (av->m_eVarType) {
case AVARTYPE_FLOAT: { case AVARTYPE_FLOAT: {
if (!deltazero(av->m_fValue, av->m_fGoal)) { // for disabled anims just warp
if (*av->m_pEnabled == 0 || animationsDisabled) {
// for disabled anims just warp av->warp();
if (av->m_pEnabled == 0 || animationsDisabled) { break;
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
} }
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; break;
} }
case AVARTYPE_VECTOR: { case AVARTYPE_VECTOR: {
if (!deltazero(av->m_vValue, av->m_vGoal)) { // for disabled anims just warp
if (*av->m_pEnabled == 0 || animationsDisabled) {
// for disabled anims just warp av->warp();
if (av->m_pEnabled == 0 || animationsDisabled) { break;
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
} }
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; break;
} }
case AVARTYPE_COLOR: { case AVARTYPE_COLOR: {
if (!deltazero(av->m_cValue, av->m_cGoal)) { // for disabled anims just warp
if (*av->m_pEnabled == 0 || animationsDisabled) {
// for disabled anims just warp av->warp();
if (av->m_pEnabled == 0 || animationsDisabled) { break;
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
} }
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; break;
} }
default: { default: {
@ -150,8 +143,16 @@ void CAnimationManager::tick() {
if (PWINDOW) { if (PWINDOW) {
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
for (auto& wd : PWINDOW->m_dWindowDecorations) { PWINDOW->updateWindowDecos();
wd->updateWindow(PWINDOW); } 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; break;

View File

@ -87,7 +87,7 @@ void CEventManager::startThread() {
// write all queued events // write all queued events
for (auto& ev : m_dQueuedEvents) { 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) { for (auto& fd : m_dAcceptedSocketFDs) {
write(fd, eventString.c_str(), eventString.length()); write(fd, eventString.c_str(), eventString.length());
} }
@ -104,9 +104,9 @@ void CEventManager::startThread() {
}).detach(); }).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()); Debug::log(WARN, "Suppressed (ignoreevents true) event of type %s, content: %s",event.event.c_str(), event.data.c_str());
return; return;
} }

View File

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

View File

@ -30,7 +30,8 @@ CKeybindManager::CKeybindManager() {
m_mDispatchers["resizeactive"] = resizeActive; m_mDispatchers["resizeactive"] = resizeActive;
m_mDispatchers["moveactive"] = moveActive; m_mDispatchers["moveactive"] = moveActive;
m_mDispatchers["cyclenext"] = circleNext; m_mDispatchers["cyclenext"] = circleNext;
m_mDispatchers["focuswindowbyclass"] = focusWindowByClass; m_mDispatchers["focuswindowbyclass"] = focusWindow;
m_mDispatchers["focuswindow"] = focusWindow;
m_mDispatchers["submap"] = setSubmap; m_mDispatchers["submap"] = setSubmap;
} }
@ -108,7 +109,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t
return found; return found;
} }
bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) { bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
// Handles the CTRL+ALT+FX TTY keybinds // Handles the CTRL+ALT+FX TTY keybinds
if (!(keysym >= XKB_KEY_XF86Switch_VT_1 && keysym <= XKB_KEY_XF86Switch_VT_12)) if (!(keysym >= XKB_KEY_XF86Switch_VT_1 && keysym <= XKB_KEY_XF86Switch_VT_12))
return false; return false;
@ -118,10 +119,10 @@ bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) {
const int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1; const int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
wlr_session_change_vt(PSESSION, TTY); wlr_session_change_vt(PSESSION, TTY);
for (auto& m : g_pCompositor->m_lMonitors) { for (auto& m : g_pCompositor->m_vMonitors) {
g_pHyprOpenGL->destroyMonitorResources(&m); // mark resources as unusable anymore g_pHyprOpenGL->destroyMonitorResources(m.get()); // mark resources as unusable anymore
m.noFrameSchedule = true; m->noFrameSchedule = true;
m.framesToSkip = 2; m->framesToSkip = 2;
} }
Debug::log(LOG, "Switched to VT %i, destroyed all render data, frames to skip for each: 2", TTY); Debug::log(LOG, "Switched to VT %i, destroyed all render data, frames to skip for each: 2", TTY);
@ -132,6 +133,23 @@ bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) {
return false; 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 // Dispatchers
void CKeybindManager::spawn(std::string args) { void CKeybindManager::spawn(std::string args) {
@ -204,6 +222,9 @@ void CKeybindManager::toggleActiveFloating(std::string args) {
const auto ACTIVEWINDOW = g_pCompositor->m_pLastWindow; const auto ACTIVEWINDOW = g_pCompositor->m_pLastWindow;
if (g_pCompositor->windowValidMapped(ACTIVEWINDOW)) { if (g_pCompositor->windowValidMapped(ACTIVEWINDOW)) {
// remove drag status
g_pInputManager->currentlyDraggedWindow = nullptr;
ACTIVEWINDOW->m_bIsFloating = !ACTIVEWINDOW->m_bIsFloating; ACTIVEWINDOW->m_bIsFloating = !ACTIVEWINDOW->m_bIsFloating;
if (ACTIVEWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) { 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) if (const auto POLDWORKSPACE = g_pCompositor->getWorkspaceByID(OLDWORKSPACE); POLDWORKSPACE)
POLDWORKSPACE->startAnim(false, ANIMTOLEFT); POLDWORKSPACE->startAnim(false, ANIMTOLEFT);
g_pCompositor->m_lWorkspaces.emplace_back(PMONITOR->ID, workspaceToChangeTo == SPECIAL_WORKSPACE_ID); const auto PWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(PMONITOR->ID, workspaceName, workspaceToChangeTo == SPECIAL_WORKSPACE_ID)).get();
const auto PWORKSPACE = &g_pCompositor->m_lWorkspaces.back();
// start anim on new workspace // start anim on new workspace
PWORKSPACE->startAnim(true, ANIMTOLEFT); PWORKSPACE->startAnim(true, ANIMTOLEFT);
@ -331,7 +351,6 @@ void CKeybindManager::changeworkspace(std::string args) {
PWORKSPACE->m_iID = workspaceToChangeTo; PWORKSPACE->m_iID = workspaceToChangeTo;
PWORKSPACE->m_iMonitorID = PMONITOR->ID; PWORKSPACE->m_iMonitorID = PMONITOR->ID;
PWORKSPACE->m_szName = workspaceName;
PMONITOR->specialWorkspaceOpen = false; PMONITOR->specialWorkspaceOpen = false;
@ -437,8 +456,8 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
toggleSpecialWorkspace(""); toggleSpecialWorkspace("");
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false, true); g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false, true);
for (auto& m : g_pCompositor->m_lMonitors) for (auto& m : g_pCompositor->m_vMonitors)
m.specialWorkspaceOpen = false; m->specialWorkspaceOpen = false;
} }
g_pInputManager->refocus(); g_pInputManager->refocus();
@ -643,7 +662,7 @@ void CKeybindManager::focusMonitor(std::string arg) {
Debug::log(ERR, "Error in focusMonitor: invalid num"); 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)); changeworkspace(std::to_string(g_pCompositor->getMonitorFromID(monID)->activeWorkspace));
} else { } else {
Debug::log(ERR, "Error in focusMonitor: invalid arg 1"); Debug::log(ERR, "Error in focusMonitor: invalid arg 1");
@ -662,9 +681,9 @@ void CKeybindManager::focusMonitor(std::string arg) {
return; return;
} }
} else { } else {
for (auto& m : g_pCompositor->m_lMonitors) { for (auto& m : g_pCompositor->m_vMonitors) {
if (m.szName == arg) { if (m->szName == arg) {
changeworkspace(std::to_string(m.activeWorkspace)); changeworkspace(std::to_string(m->activeWorkspace));
return; return;
} }
} }
@ -724,11 +743,11 @@ void CKeybindManager::workspaceOpt(std::string args) {
PWORKSPACE->m_bDefaultPseudo = !PWORKSPACE->m_bDefaultPseudo; PWORKSPACE->m_bDefaultPseudo = !PWORKSPACE->m_bDefaultPseudo;
// apply // apply
for (auto& w : g_pCompositor->m_lWindows) { for (auto& w : g_pCompositor->m_vWindows) {
if (!w.m_bIsMapped || w.m_iWorkspaceID != PWORKSPACE->m_iID) if (!w->m_bIsMapped || w->m_iWorkspaceID != PWORKSPACE->m_iID)
continue; continue;
w.m_bIsPseudotiled = PWORKSPACE->m_bDefaultPseudo; w->m_bIsPseudotiled = PWORKSPACE->m_bDefaultPseudo;
} }
} else if (args == "allfloat") { } else if (args == "allfloat") {
PWORKSPACE->m_bDefaultFloating = !PWORKSPACE->m_bDefaultFloating; 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 // we make a copy because changeWindowFloatingMode might invalidate the iterator
std::deque<CWindow*> ptrs; std::deque<CWindow*> ptrs;
for (auto& w : g_pCompositor->m_lWindows) for (auto& w : g_pCompositor->m_vWindows)
ptrs.push_back(&w); ptrs.push_back(w.get());
for (auto& w : ptrs) { for (auto& w : ptrs) {
if (!w->m_bIsMapped || w->m_iWorkspaceID != PWORKSPACE->m_iID) if (!w->m_bIsMapped || w->m_iWorkspaceID != PWORKSPACE->m_iID)
@ -841,8 +860,8 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
bool open = false; bool open = false;
for (auto& m : g_pCompositor->m_lMonitors) { for (auto& m : g_pCompositor->m_vMonitors) {
if (m.specialWorkspaceOpen) { if (m->specialWorkspaceOpen) {
open = true; open = true;
break; break;
} }
@ -854,10 +873,10 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
Debug::log(LOG, "Toggling special workspace to open"); Debug::log(LOG, "Toggling special workspace to open");
if (open) { if (open) {
for (auto& m : g_pCompositor->m_lMonitors) { for (auto& m : g_pCompositor->m_vMonitors) {
if (m.specialWorkspaceOpen != !open) { if (m->specialWorkspaceOpen != !open) {
m.specialWorkspaceOpen = !open; m->specialWorkspaceOpen = !open;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m.ID); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false); 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_pCompositor->m_pLastMonitor->specialWorkspaceOpen = true;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID); 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(); g_pInputManager->refocus();
} }
void CKeybindManager::forceRendererReload(std::string args) { void CKeybindManager::forceRendererReload(std::string args) {
for (auto& m : g_pCompositor->m_lMonitors) { bool overAgain = false;
auto rule = g_pConfigManager->getMonitorRuleFor(m.szName);
g_pHyprRenderer->applyMonitorRule(&m, &rule, true); 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) { 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); wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, MIDPOINT.x, MIDPOINT.y);
} }
void CKeybindManager::focusWindowByClass(std::string clazz) { void CKeybindManager::focusWindow(std::string regexp) {
std::regex classCheck(clazz); 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) { for (auto& w : g_pCompositor->m_vWindows) {
if (!w.m_bIsMapped || w.m_bHidden) if (!w->m_bIsMapped || w->m_bHidden)
continue; 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)) Debug::log(LOG, "Focusing to window name: %s", w->m_szTitle.c_str());
continue;
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); 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 = ""; inline static std::string m_szCurrentSelectedSubmap = "";
bool handleInternalKeybinds(xkb_keysym_t); bool handleInternalKeybinds(xkb_keysym_t);
bool handleVT(xkb_keysym_t);
// -------------- Dispatchers -------------- // // -------------- Dispatchers -------------- //
static void killActive(std::string); static void killActive(std::string);
@ -60,7 +61,7 @@ private:
static void resizeActive(std::string); static void resizeActive(std::string);
static void moveActive(std::string); static void moveActive(std::string);
static void circleNext(std::string); static void circleNext(std::string);
static void focusWindowByClass(std::string); static void focusWindow(std::string);
static void setSubmap(std::string); static void setSubmap(std::string);
friend class CCompositor; friend class CCompositor;

View File

@ -42,9 +42,6 @@ void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate)
} }
void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) { void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) {
if (pWindow == g_pCompositor->m_pLastWindow)
return;
if (pWindow->m_bIsX11) { if (pWindow->m_bIsX11) {
if (pWindow->m_uSurface.xwayland->minimized) if (pWindow->m_uSurface.xwayland->minimized)
wlr_xwayland_surface_set_minimized(pWindow->m_uSurface.xwayland, false); 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"] || 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_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_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; return true;
} }

View File

@ -37,6 +37,13 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
} }
Vector2D mouseCoords = getMouseCoordsInternal(); Vector2D mouseCoords = getMouseCoordsInternal();
const auto MOUSECOORDSFLOORED = mouseCoords.floor();
if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored)
return;
m_vLastCursorPosFloored = MOUSECOORDSFLOORED;
const auto PMONITOR = g_pCompositor->getMonitorFromCursor(); const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
bool didConstraintOnCursor = false; bool didConstraintOnCursor = false;
@ -110,10 +117,11 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
Vector2D surfaceCoords; Vector2D surfaceCoords;
Vector2D surfacePos = Vector2D(-1337, -1337); Vector2D surfacePos = Vector2D(-1337, -1337);
CWindow* pFoundWindow = nullptr; CWindow* pFoundWindow = nullptr;
SLayerSurface* pFoundLayerSurface = nullptr;
// overlay is above fullscreen // overlay is above fullscreen
if (!foundSurface) 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 // then, we check if the workspace doesnt have a fullscreen window
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); 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(); surfacePos = pFoundWindow->m_vRealPosition.vec();
// only check floating because tiled cant be over fullscreen // only check floating because tiled cant be over fullscreen
for (auto w = g_pCompositor->m_lWindows.rbegin(); w != g_pCompositor->m_lWindows.rend(); 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}; 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) { 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); pFoundWindow = (*w).get();
if (!pFoundWindow->m_bIsX11) { if (!pFoundWindow->m_bIsX11) {
foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords); foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords);
@ -141,11 +149,15 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
} }
if (!foundSurface) 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 // then windows
if (!foundSurface) { 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) {
if (!pFoundWindow->m_bIsX11) { if (!pFoundWindow->m_bIsX11) {
foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords); foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords);
@ -158,13 +170,16 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
// then surfaces below // then surfaces below
if (!foundSurface) 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) 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) { 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); wlr_seat_pointer_clear_focus(g_pCompositor->m_sSeat.seat);
@ -199,7 +214,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
} else { } else {
g_pCompositor->focusWindow(pFoundWindow, foundSurface); g_pCompositor->focusWindow(pFoundWindow, foundSurface);
} }
} else } else if (pFoundLayerSurface && pFoundLayerSurface->layerSurface->current.keyboard_interactive)
g_pCompositor->focusSurface(foundSurface); g_pCompositor->focusSurface(foundSurface);
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y); 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(); 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); const auto PKEYBOARD = wlr_seat_get_keyboard(g_pCompositor->m_sSeat.seat);
if (!PKEYBOARD) { // ??? if (!PKEYBOARD) { // ???
Debug::log(ERR, "No active keyboard in onMouseButton??"); Debug::log(ERR, "No active keyboard in processMouseDownNormal??");
return; return;
} }
@ -250,7 +325,30 @@ void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
if (g_pCompositor->doesSeatAcceptInput(g_pCompositor->m_pLastFocus)) { 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); 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) { void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
@ -276,16 +374,15 @@ Vector2D CInputManager::getMouseCoordsInternal() {
} }
void CInputManager::newKeyboard(wlr_input_device* keyboard) { void CInputManager::newKeyboard(wlr_input_device* keyboard) {
m_lKeyboards.push_back(SKeyboard()); const auto PNEWKEYBOARD = &m_lKeyboards.emplace_back();
const auto PNEWKEYBOARD = &m_lKeyboards.back();
PNEWKEYBOARD->keyboard = keyboard; PNEWKEYBOARD->keyboard = keyboard;
const auto REPEATRATE = g_pConfigManager->getInt("input:repeat_rate"); try {
const auto REPEATDELAY = g_pConfigManager->getInt("input:repeat_delay"); PNEWKEYBOARD->name = std::string(keyboard->name);
} catch (std::exception& e) {
wlr_keyboard_set_repeat_info(keyboard->keyboard, std::max(0, REPEATRATE), std::max(0, REPEATDELAY)); Debug::log(ERR, "Keyboard had no name???"); // logic error
}
PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&keyboard->keyboard->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "Keyboard"); 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"); 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) { void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
const auto HASCONFIG = g_pConfigManager->deviceConfigExists(pKeyboard->name);
ASSERT(pKeyboard); ASSERT(pKeyboard);
const auto RULES = g_pConfigManager->getString("input:kb_rules"); const auto REPEATRATE = HASCONFIG ? g_pConfigManager->getDeviceInt(pKeyboard->name, "repeat_rate") : g_pConfigManager->getInt("input:repeat_rate");
const auto MODEL = g_pConfigManager->getString("input:kb_model"); const auto REPEATDELAY = HASCONFIG ? g_pConfigManager->getDeviceInt(pKeyboard->name, "repeat_delay") : g_pConfigManager->getInt("input:repeat_delay");
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");
if (RULES != "" && RULES == pKeyboard->currentRules.rules && MODEL == pKeyboard->currentRules.model && LAYOUT == pKeyboard->currentRules.layout && VARIANT == pKeyboard->currentRules.variant && OPTIONS == pKeyboard->currentRules.options) { const auto NUMLOCKON = HASCONFIG ? g_pConfigManager->getDeviceInt(pKeyboard->name, "numlock_by_default") : g_pConfigManager->getInt("input:numlock_by_default");
Debug::log(LOG, "Not applying config to keyboard, it did not change.");
return; 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 = { xkb_rule_names rules = {
.rules = RULES.c_str(), .rules = RULES.c_str(),
.model = MODEL.c_str(), .model = MODEL.c_str(),
@ -355,7 +469,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
wlr_keyboard_modifiers wlrMods = {0}; wlr_keyboard_modifiers wlrMods = {0};
if (g_pConfigManager->getInt("input:numlock_by_default") == 1) { if (NUMLOCKON == 1) {
// lock numlock // lock numlock
const auto IDX = xkb_map_mod_get_index(KEYMAP, XKB_MOD_NAME_NUM); 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(); const auto PMOUSE = &m_lMice.back();
PMOUSE->mouse = mouse; 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)) { if (wlr_input_device_is_libinput(mouse)) {
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(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); libinput_device_config_click_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
else else
libinput_device_config_click_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); 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 (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); libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED);
else else
libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED); 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 (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); libinput_device_config_tap_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_TAP_ENABLED);
if (libinput_device_config_scroll_has_natural_scroll(LIBINPUTDEV)) { if (libinput_device_config_scroll_has_natural_scroll(LIBINPUTDEV)) {
double w = 0, h = 0; 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 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 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)) { 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); libinput_device_config_dwt_set_enabled(LIBINPUTDEV, DWT);
} }
} }
@ -497,9 +618,12 @@ void CInputManager::updateDragIcon() {
switch (g_pInputManager->m_sDrag.dragIcon->drag->grab_type) { switch (g_pInputManager->m_sDrag.dragIcon->drag->grab_type) {
case WLR_DRAG_GRAB_KEYBOARD: case WLR_DRAG_GRAB_KEYBOARD:
break; 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(); g_pInputManager->m_sDrag.pos = g_pInputManager->getMouseCoordsInternal();
break; break;
}
default: default:
break; break;
} }

View File

@ -6,6 +6,11 @@
#include "../../Window.hpp" #include "../../Window.hpp"
#include "../../helpers/Timer.hpp" #include "../../helpers/Timer.hpp"
enum eClickBehaviorMode {
CLICKMODE_DEFAULT = 0,
CLICKMODE_KILL
};
class CInputManager { class CInputManager {
public: public:
@ -32,6 +37,10 @@ public:
void updateDragIcon(); void updateDragIcon();
void updateCapabilities(wlr_input_device*); void updateCapabilities(wlr_input_device*);
void setClickMode(eClickBehaviorMode);
eClickBehaviorMode getClickMode();
void processMouseRequest(wlr_seat_pointer_request_set_cursor_event*);
// for dragging floating windows // for dragging floating windows
CWindow* currentlyDraggedWindow = nullptr; CWindow* currentlyDraggedWindow = nullptr;
@ -58,6 +67,13 @@ public:
private: 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; uint32_t m_uiCapabilities = 0;
void mouseMoveUnified(uint32_t, bool refocus = false); void mouseMoveUnified(uint32_t, bool refocus = false);

View File

@ -4,6 +4,12 @@
void CInputManager::newTabletTool(wlr_input_device* pDevice) { void CInputManager::newTabletTool(wlr_input_device* pDevice) {
const auto PNEWTABLET = &m_lTablets.emplace_back(); 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->wlrTablet = pDevice->tablet;
PNEWTABLET->wlrDevice = pDevice; PNEWTABLET->wlrDevice = pDevice;
PNEWTABLET->wlrTabletV2 = wlr_tablet_create(g_pCompositor->m_sWLRTabletManager, g_pCompositor->m_sSeat.seat, 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) { void CInputManager::newTabletPad(wlr_input_device* pDevice) {
const auto PNEWPAD = &m_lTabletPads.emplace_back(); 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->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) { 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.posAttrib = glGetAttribLocation(prog, "pos");
m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord"); 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."); Debug::log(LOG, "Shaders initialized successfully.");
// End shaders // 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); 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); 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; m_iWLROutputFb = m_iCurrentOutputFb;
// ensure a framebuffer for the monitor exists // ensure a framebuffer for the monitor exists
if (m_mMonitorRenderResources.find(pMonitor) == m_mMonitorRenderResources.end() || m_mMonitorRenderResources[pMonitor].primaryFB.m_Size != pMonitor->vecPixelSize) { if (m_mMonitorRenderResources.find(pMonitor) == m_mMonitorRenderResources.end() || m_RenderData.pCurrentMonData->primaryFB.m_Size != pMonitor->vecPixelSize) {
m_mMonitorRenderResources[pMonitor].stencilTex.allocate(); m_RenderData.pCurrentMonData->stencilTex.allocate();
m_mMonitorRenderResources[pMonitor].primaryFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex; m_RenderData.pCurrentMonData->primaryFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
m_mMonitorRenderResources[pMonitor].mirrorFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex; m_RenderData.pCurrentMonData->mirrorFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
m_mMonitorRenderResources[pMonitor].mirrorSwapFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex; m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
m_mMonitorRenderResources[pMonitor].primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); m_RenderData.pCurrentMonData->primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
m_mMonitorRenderResources[pMonitor].mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
m_mMonitorRenderResources[pMonitor].mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
createBGTextureForMonitor(pMonitor); createBGTextureForMonitor(pMonitor);
} }
// bind the primary Hypr Framebuffer // bind the primary Hypr Framebuffer
m_mMonitorRenderResources[pMonitor].primaryFB.bind(); m_RenderData.pCurrentMonData->primaryFB.bind();
m_RenderData.pDamage = pDamage; m_RenderData.pDamage = pDamage;
@ -180,7 +188,7 @@ void CHyprOpenGLImpl::end() {
m_bEndFrame = true; 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; 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; static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
// Rounded corners // Rounded corners
glUniform2f(glGetUniformLocation(m_shQUAD.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y); glUniform2f(m_shQUAD.getUniformLocation("topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(glGetUniformLocation(m_shQUAD.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y); glUniform2f(m_shQUAD.getUniformLocation("bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(glGetUniformLocation(m_shQUAD.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y); glUniform2f(m_shQUAD.getUniformLocation("fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(glGetUniformLocation(m_shQUAD.program, "radius"), round); glUniform1f(m_shQUAD.getUniformLocation("radius"), round);
glUniform1i(glGetUniformLocation(m_shQUAD.program, "primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0)); glUniform1i(m_shQUAD.getUniformLocation("primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0));
glVertexAttribPointer(m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_shQUAD.texAttrib, 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); 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()!"); 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); 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(m_RenderData.pMonitor, "Tried to render texture without begin()!");
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!"); 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!"); 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); glActiveTexture(GL_TEXTURE0);
glBindTexture(tex.m_iTarget, tex.m_iTexID); 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; static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
// Rounded corners // Rounded corners
glUniform2f(glGetUniformLocation(shader->program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y); glUniform2f(shader->getUniformLocation("topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(glGetUniformLocation(shader->program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y); glUniform2f(shader->getUniformLocation("bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(glGetUniformLocation(shader->program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y); glUniform2f(shader->getUniformLocation("fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(glGetUniformLocation(shader->program, "radius"), round); glUniform1f(shader->getUniformLocation("radius"), round);
glUniform1i(glGetUniformLocation(shader->program, "primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !border && !noAA)); glUniform1i(shader->getUniformLocation("primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !noAA));
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); 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->posAttrib);
glDisableVertexAttribArray(shader->texAttrib); glDisableVertexAttribArray(shader->texAttrib);
glBindTexture(tex.m_iTarget, 0); 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 // 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); wlr_region_expand(&damage, &damage, pow(2, *PBLURPASSES) * *PBLURSIZE);
// helper // helper
const auto PMIRRORFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorFB; const auto PMIRRORFB = &m_RenderData.pCurrentMonData->mirrorFB;
const auto PMIRRORSWAPFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorSwapFB; 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 // declare the draw func
auto drawPass = [&](CShader* pShader, pixman_region32_t* pDamage) { auto drawPass = [&](CShader* pShader, pixman_region32_t* pDamage) {
@ -500,11 +471,11 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
// prep two shaders // prep two shaders
glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix); 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) 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 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); glUniform1i(pShader->tex, 0);
glVertexAttribPointer(pShader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); 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. // draw the things.
// first draw is prim -> mirr // first draw is prim -> mirr
PMIRRORFB->bind(); 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 // damage region will be scaled, make a temp
pixman_region32_t tempDamage; pixman_region32_t tempDamage;
@ -566,14 +537,14 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
return currentRenderToFB; 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()!"); 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 PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
static auto* const PNOBLUROVERSIZED = &g_pConfigManager->getConfigValuePtr("decoration:no_blur_on_oversized")->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)) { 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; return;
} }
@ -596,7 +567,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
} }
if (!pixman_region32_not_empty(&inverseOpaque)) { 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; return;
} }
@ -606,7 +577,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
pixman_region32_fini(&inverseOpaque); pixman_region32_fini(&inverseOpaque);
// bind primary // bind primary
m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.bind(); m_RenderData.pCurrentMonData->primaryFB.bind();
// make a stencil for rounded corners to work with blur // make a stencil for rounded corners to work with blur
scissor((wlr_box*)nullptr); // allow the entire window and stencil to render 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)) { if (pixman_region32_not_empty(&damage)) {
// render our great blurred FB // render our great blurred FB
static auto *const PBLURIGNOREOPACITY = &g_pConfigManager->getConfigValuePtr("decoration:blur_ignore_opacity")->intValue; 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 // render the window, but clear stencil
glClearStencil(0); glClearStencil(0);
@ -638,36 +609,11 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
// draw window // draw window
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true, true); renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, 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);
} }
// disable the stencil (if no border), finalize everything glStencilMask(-1);
if (!border) { glStencilFunc(GL_ALWAYS, 1, 0xFF);
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);
pixman_region32_fini(&damage); pixman_region32_fini(&damage);
scissor((wlr_box*)nullptr); scissor((wlr_box*)nullptr);
} }
@ -679,23 +625,67 @@ void pushVert2D(float x, float y, float* arr, int& counter, wlr_box* box) {
counter++; 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((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
// this method assumes a set stencil and scaled box static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
box->x -= thick; static auto *const PMULTISAMPLE = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
box->y -= thick;
box->width += 2 * thick;
box->height += 2 * thick;
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. round += *PBORDERSIZE;
glStencilFunc(GL_NOTEQUAL, 1, -1);
// draw a rounded rect float matrix[9];
renderRect(box, col, round); 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) { void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
@ -744,7 +734,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
clear(CColor(0, 0, 0, 0)); // JIC clear(CColor(0, 0, 0, 0)); // JIC
wlr_box fullMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y}; 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 // restore original fb
#ifndef GLES2 #ifndef GLES2
@ -823,12 +813,13 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) {
wlr_box windowBox; wlr_box windowBox;
// some mafs to figure out the correct box // 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.width = PMONITOR->vecPixelSize.x * scaleXY.x;
windowBox.height = PMONITOR->vecPixelSize.y * scaleXY.y; 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.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) - ((PWINDOW->m_vOriginalClosedPos.y - PMONITOR->vecPosition.y) * scaleXY.y); 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_t fakeDamage;
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); 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 PSHADOWCOL = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow")->intValue;
static auto *const PSHADOWPOWER = &g_pConfigManager->getConfigValuePtr("decoration:shadow_render_power")->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); 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); glUseProgram(m_shSHADOW.program);
glUniformMatrix3fv(m_shSHADOW.proj, 1, GL_FALSE, glMatrix); 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 TOPLEFT = Vector2D(range + round, range + round);
const auto BOTTOMRIGHT = Vector2D(box->width - (range + round), box->height - (range + round)); const auto BOTTOMRIGHT = Vector2D(box->width - (range + round), box->height - (range + round));
const auto FULLSIZE = Vector2D(box->width, box->height); const auto FULLSIZE = Vector2D(box->width, box->height);
// Rounded corners // Rounded corners
glUniform2f(glGetUniformLocation(m_shSHADOW.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y); glUniform2f(m_shSHADOW.getUniformLocation("topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(glGetUniformLocation(m_shSHADOW.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y); glUniform2f(m_shSHADOW.getUniformLocation("bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(glGetUniformLocation(m_shSHADOW.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y); glUniform2f(m_shSHADOW.getUniformLocation("fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(glGetUniformLocation(m_shSHADOW.program, "radius"), range + round); glUniform1f(m_shSHADOW.getUniformLocation("radius"), range + round);
glUniform1f(glGetUniformLocation(m_shSHADOW.program, "range"), range); glUniform1f(m_shSHADOW.getUniformLocation("range"), range);
glUniform1f(glGetUniformLocation(m_shSHADOW.program, "shadowPower"), SHADOWPOWER); glUniform1f(m_shSHADOW.getUniformLocation("shadowPower"), SHADOWPOWER);
glUniform1i(glGetUniformLocation(m_shSHADOW.program, "ignoreWindow"), *PSHADOWIGNOREWINDOW);
glVertexAttribPointer(m_shSHADOW.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(m_shSHADOW.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_shSHADOW.texAttrib, 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 -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 { struct SMonitorRenderData {
CFramebuffer primaryFB; CFramebuffer primaryFB;
CFramebuffer mirrorFB; CFramebuffer mirrorFB;
@ -48,6 +37,19 @@ struct SMonitorRenderData {
CTexture stencilTex; 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 { class CHyprOpenGLImpl {
public: public:
@ -59,9 +61,10 @@ public:
void renderRect(wlr_box*, const CColor&, int round = 0); void renderRect(wlr_box*, const CColor&, int round = 0);
void renderRectWithDamage(wlr_box*, const CColor&, pixman_region32_t* damage, 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(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 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, bool border = 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 renderRoundedShadow(wlr_box*, int round, int range, float a = 1.0);
void renderBorder(wlr_box*, const CColor&, int round);
void makeWindowSnapshot(CWindow*); void makeWindowSnapshot(CWindow*);
void makeLayerSnapshot(SLayerSurface*); void makeLayerSnapshot(SLayerSurface*);
@ -101,13 +104,14 @@ private:
bool m_bEndFrame = false; bool m_bEndFrame = false;
// Shaders // Shaders
SQuad m_shQUAD; CShader m_shQUAD;
CShader m_shRGBA; CShader m_shRGBA;
CShader m_shRGBX; CShader m_shRGBX;
CShader m_shEXT; CShader m_shEXT;
CShader m_shBLUR1; CShader m_shBLUR1;
CShader m_shBLUR2; CShader m_shBLUR2;
CShader m_shSHADOW; CShader m_shSHADOW;
CShader m_shBORDER1;
// //
GLuint createProgram(const std::string&, const std::string&); GLuint createProgram(const std::string&, const std::string&);
@ -117,8 +121,7 @@ private:
// returns the out FB, can be either Mirror or MirrorSwap // returns the out FB, can be either Mirror or MirrorSwap
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage); 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 renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowPrimary = false);
void renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0);
}; };
inline std::unique_ptr<CHyprOpenGLImpl> g_pHyprOpenGL; 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) { if (RDATA->surface && surface == RDATA->surface) {
g_pHyprOpenGL->m_RenderData.renderingPrimarySurface = true; 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 else
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, false, false); 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)) if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
return true; return true;
for (auto& m : g_pCompositor->m_lMonitors) { for (auto& m : g_pCompositor->m_vMonitors) {
if (PWORKSPACE && PWORKSPACE->m_iMonitorID == m.ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())) if (PWORKSPACE && PWORKSPACE->m_iMonitorID == m->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()))
return true; return true;
if (m.specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) if (m->specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
return true; return true;
} }
@ -82,37 +88,37 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) {
void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWorkspace* pWorkspace, timespec* time) { void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWorkspace* pWorkspace, timespec* time) {
CWindow* pWorkspaceWindow = nullptr; CWindow* pWorkspaceWindow = nullptr;
for (auto& w : g_pCompositor->m_lWindows) { for (auto& w : g_pCompositor->m_vWindows) {
if (w.m_iWorkspaceID != pWorkspace->m_iID || !w.m_bIsFullscreen) if (w->m_iWorkspaceID != pWorkspace->m_iID || !w->m_bIsFullscreen)
continue; continue;
// found it! // 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 // then render windows over fullscreen
for (auto& w : g_pCompositor->m_lWindows) { for (auto& w : g_pCompositor->m_vWindows) {
if (w.m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || !w.m_bCreatedOverFullscreen || !w.m_bIsMapped) if (w->m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || !w->m_bCreatedOverFullscreen || !w->m_bIsMapped)
continue; continue;
renderWindow(&w, pMonitor, time, true); renderWindow(w.get(), pMonitor, time, true);
} }
// and then special windows // and then special windows
for (auto& w : g_pCompositor->m_lWindows) { for (auto& w : g_pCompositor->m_vWindows) {
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut) if (!g_pCompositor->windowValidMapped(w.get()) && !w->m_bFadingOut)
continue; continue;
if (w.m_iWorkspaceID != SPECIAL_WORKSPACE_ID) if (w->m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
continue; continue;
if (!shouldRenderWindow(&w, pMonitor)) if (!shouldRenderWindow(w.get(), pMonitor))
continue; continue;
// render the bad boy // render the bad boy
renderWindow(&w, pMonitor, time, true); renderWindow(w.get(), pMonitor, time, true);
} }
// and the overlay layers // and the overlay layers
@ -130,7 +136,7 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWor
renderDragIcon(pMonitor, time); renderDragIcon(pMonitor, time);
// if correct monitor draw hyprerror // if correct monitor draw hyprerror
if (pMonitor == &g_pCompositor->m_lMonitors.front()) if (pMonitor == g_pCompositor->m_vMonitors.front().get())
g_pHyprError->draw(); 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.dontRound = pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (PWORKSPACE->m_fAlpha.fl() / 255.f); 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.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; renderdata.rounding = pWindow->m_sAdditionalConfigData.rounding;
// apply window special data // apply window special data
@ -166,8 +172,8 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
g_pHyprOpenGL->m_pCurrentWindow = pWindow; g_pHyprOpenGL->m_pCurrentWindow = pWindow;
// render window decorations first // render window decorations first, if not fullscreen full
for (auto& wd : pWindow->m_dWindowDecorations) if (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL) for (auto& wd : pWindow->m_dWindowDecorations)
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha / 255.f); wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha / 255.f);
if (!pWindow->m_bIsX11) { if (!pWindow->m_bIsX11) {
@ -238,54 +244,54 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
} }
// Non-floating // Non-floating
for (auto& w : g_pCompositor->m_lWindows) { for (auto& w : g_pCompositor->m_vWindows) {
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut) if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
continue; continue;
if (w.m_bIsFloating) if (w->m_bIsFloating)
continue; // floating are in the second pass 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 continue; // special are in the third pass
if (!shouldRenderWindow(&w, PMONITOR)) if (!shouldRenderWindow(w.get(), PMONITOR))
continue; continue;
// render the bad boy // render the bad boy
renderWindow(&w, PMONITOR, time, true); renderWindow(w.get(), PMONITOR, time, true);
} }
// floating on top // floating on top
for (auto& w : g_pCompositor->m_lWindows) { for (auto& w : g_pCompositor->m_vWindows) {
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut) if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
continue; continue;
if (!w.m_bIsFloating) if (!w->m_bIsFloating)
continue; continue;
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID) if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
continue; continue;
if (!shouldRenderWindow(&w, PMONITOR)) if (!shouldRenderWindow(w.get(), PMONITOR))
continue; continue;
// render the bad boy // render the bad boy
renderWindow(&w, PMONITOR, time, true); renderWindow(w.get(), PMONITOR, time, true);
} }
// and then special // and then special
for (auto& w : g_pCompositor->m_lWindows) { for (auto& w : g_pCompositor->m_vWindows) {
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut) if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
continue; continue;
if (w.m_iWorkspaceID != SPECIAL_WORKSPACE_ID) if (w->m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
continue; continue;
if (!shouldRenderWindow(&w, PMONITOR)) if (!shouldRenderWindow(w.get(), PMONITOR))
continue; continue;
// render the bad boy // render the bad boy
renderWindow(&w, PMONITOR, time, true); renderWindow(w.get(), PMONITOR, time, true);
} }
// Render surfaces above windows for monitor // Render surfaces above windows for monitor
@ -545,14 +551,19 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
pixman_region32_init(&damageBox); pixman_region32_init(&damageBox);
wlr_surface_get_effective_damage(pSurface, &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); 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; 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); pixman_region32_translate(&damageBox, lx, ly);
wlr_region_scale(&damageBox, &damageBox, m.scale); wlr_region_scale(&damageBox, &damageBox, m->scale);
wlr_output_damage_add(m.damage, &damageBox); wlr_output_damage_add(m->damage, &damageBox);
pixman_region32_translate(&damageBox, -lx, -ly); 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) { void CHyprRenderer::damageWindow(CWindow* pWindow) {
if (!pWindow->m_bIsFloating) { wlr_box damageBox = pWindow->getFullWindowBoundingBox();
// damage by size & pos for (auto& m : g_pCompositor->m_vMonitors) {
// TODO TEMP: revise when added shadows/etc wlr_box fixedDamageBox = {damageBox.x - m->vecPosition.x, damageBox.y - m->vecPosition.y, damageBox.width, damageBox.height};
scaleBox(&fixedDamageBox, m->scale);
wlr_box damageBox = pWindow->getFullWindowBoundingBox(); wlr_output_damage_add_box(m->damage, &fixedDamageBox);
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);
} }
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) { void CHyprRenderer::damageMonitor(SMonitor* pMonitor) {
@ -611,10 +600,10 @@ void CHyprRenderer::damageMonitor(SMonitor* pMonitor) {
} }
void CHyprRenderer::damageBox(wlr_box* pBox) { void CHyprRenderer::damageBox(wlr_box* pBox) {
for (auto& m : g_pCompositor->m_lMonitors) { for (auto& m : g_pCompositor->m_vMonitors) {
wlr_box damageBox = {pBox->x - m.vecPosition.x, pBox->y - m.vecPosition.y, pBox->width, pBox->height}; wlr_box damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height};
scaleBox(&damageBox, m.scale); scaleBox(&damageBox, m->scale);
wlr_output_damage_add_box(m.damage, &damageBox); wlr_output_damage_add_box(m->damage, &damageBox);
} }
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue; 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; renderdata.h = g_pInputManager->m_sDrag.dragIcon->surface->current.height;
wlr_surface_for_each_surface(g_pInputManager->m_sDrag.dragIcon->surface, renderSurface, &renderdata); 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) { DAMAGETRACKINGMODES CHyprRenderer::damageTrackingModeFromStr(const std::string& mode) {
@ -651,14 +643,23 @@ DAMAGETRACKINGMODES CHyprRenderer::damageTrackingModeFromStr(const std::string&
return DAMAGE_TRACKING_INVALID; 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()); 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 // 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) { 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()); 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); wlr_output_set_scale(pMonitor->output, pMonitorRule->scale);
@ -697,23 +698,32 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
} }
if (!found) { 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) { if (!wlr_output_test(pMonitor->output)) {
Debug::log(ERR, "Monitor %s has NO PREFERRED MODE, and an INVALID one was requested: %ix%i@%2f", Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
(int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate);
return; 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 { } else {
wlr_output_set_custom_mode(pMonitor->output, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (int)pMonitorRule->refreshRate * 1000); 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)) { if (!wlr_output_commit(pMonitor->output)) {
Debug::log(ERR, "Couldn't commit output named %s", pMonitor->output->name); Debug::log(ERR, "Couldn't commit output named %s", pMonitor->output->name);
return; return true;
} }
int x, y; int x, y;
@ -752,6 +762,8 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
// frame skip // frame skip
pMonitor->framesToSkip = 1; pMonitor->framesToSkip = 1;
return true;
} }
void CHyprRenderer::ensureCursorRenderingMode() { void CHyprRenderer::ensureCursorRenderingMode() {
@ -767,8 +779,8 @@ void CHyprRenderer::ensureCursorRenderingMode() {
Debug::log(LOG, "Hiding the cursor (timeout)"); Debug::log(LOG, "Hiding the cursor (timeout)");
for (auto& m : g_pCompositor->m_lMonitors) for (auto& m : g_pCompositor->m_vMonitors)
g_pHyprRenderer->damageMonitor(&m); // TODO: maybe just damage the cursor area? g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area?
} else if (*PCURSORTIMEOUT > PASSEDCURSORSECONDS && !m_bHasARenderedCursor) { } else if (*PCURSORTIMEOUT > PASSEDCURSORSECONDS && !m_bHasARenderedCursor) {
m_bHasARenderedCursor = true; m_bHasARenderedCursor = true;
@ -777,8 +789,8 @@ void CHyprRenderer::ensureCursorRenderingMode() {
Debug::log(LOG, "Showing the cursor (timeout)"); Debug::log(LOG, "Showing the cursor (timeout)");
for (auto& m : g_pCompositor->m_lMonitors) for (auto& m : g_pCompositor->m_vMonitors)
g_pHyprRenderer->damageMonitor(&m); // TODO: maybe just damage the cursor area? g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area?
} }
} else { } else {
m_bHasARenderedCursor = true; m_bHasARenderedCursor = true;

View File

@ -28,7 +28,7 @@ public:
void damageBox(wlr_box*); void damageBox(wlr_box*);
void damageBox(const int& x, const int& y, const int& w, const int& h); void damageBox(const int& x, const int& y, const int& w, const int& h);
void damageMonitor(SMonitor*); void damageMonitor(SMonitor*);
void applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false); bool applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false);
bool shouldRenderWindow(CWindow*, SMonitor*); bool shouldRenderWindow(CWindow*, SMonitor*);
bool shouldRenderWindow(CWindow*); bool shouldRenderWindow(CWindow*);
void ensureCursorRenderingMode(); 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 #pragma once
#include "../defines.hpp" #include "../defines.hpp"
#include <unordered_map>
struct SQuad {
GLuint program;
GLint proj;
GLint color;
GLint posAttrib;
GLint texAttrib;
};
class CShader { class CShader {
public: public:
GLuint program; GLuint program;
GLint proj; GLint proj;
GLint color;
GLint tex; GLint tex;
GLint alpha; GLint alpha;
GLint posAttrib; GLint posAttrib;
GLint texAttrib; GLint texAttrib;
GLint discardOpaque; GLint discardOpaque;
GLint getUniformLocation(const std::string&);
private:
std::unordered_map<std::string, GLint> m_muUniforms;
}; };

View File

@ -2,3 +2,4 @@
#include "shaders/Textures.hpp" #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) { void CHyprDropShadowDecoration::updateWindow(CWindow* pWindow) {
damageEntire(); 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) { void CHyprDropShadowDecoration::draw(SMonitor* pMonitor, float a) {
@ -45,16 +56,29 @@ void CHyprDropShadowDecoration::draw(SMonitor* pMonitor, float a) {
static auto *const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue; 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 PSHADOWSIZE = &g_pConfigManager->getConfigValuePtr("decoration:shadow_range")->intValue;
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->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) if (*PSHADOWS != 1)
return; // disabled return; // disabled
// update the extents if needed // get the real offset
if (*PSHADOWSIZE != m_seExtents.topLeft.x) Vector2D offset;
m_seExtents = {{*PSHADOWSIZE + 2, *PSHADOWSIZE + 2}, {*PSHADOWSIZE + 2, *PSHADOWSIZE + 2}}; 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(); if (isNumber(X, true) && isNumber(Y, true)) {
m_vLastWindowSize = m_pWindow->m_vRealSize.vec(); 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 // 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}; 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};
@ -62,5 +86,40 @@ void CHyprDropShadowDecoration::draw(SMonitor* pMonitor, float a) {
fullBox.x -= pMonitor->vecPosition.x; fullBox.x -= pMonitor->vecPosition.x;
fullBox.y -= pMonitor->vecPosition.y; 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); 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) { void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
damageEntire(); 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 // we draw 3px above the window's border with 3px
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size"); const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
m_seExtents.topLeft = Vector2D(0, BORDERSIZE + 3 + 3); m_seExtents.topLeft = Vector2D(0, BORDERSIZE + 3 + 3);
m_seExtents.bottomRight = Vector2D(); m_seExtents.bottomRight = Vector2D();
m_vLastWindowPos = pWindow->m_vRealPosition.vec(); m_vLastWindowPos = pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET;
m_vLastWindowSize = pWindow->m_vRealSize.vec(); m_vLastWindowSize = pWindow->m_vRealSize.vec();
} }

View File

@ -16,7 +16,7 @@ struct SWindowDecorationExtents {
class CWindow; class CWindow;
struct SMonitor; struct SMonitor;
class IHyprWindowDecoration { interface IHyprWindowDecoration {
public: public:
virtual ~IHyprWindowDecoration() = 0; 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 radius;
uniform float range; uniform float range;
uniform float shadowPower; uniform float shadowPower;
uniform int ignoreWindow;
float pixAlphaRoundedDistance(float distanceToCorner) { float pixAlphaRoundedDistance(float distanceToCorner) {
if (distanceToCorner > radius) { 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; discard; return;
} }

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