mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-17 13:03:48 -07:00
Compare commits
108 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
751d2851cc | ||
|
a0fcda301d | ||
|
47654a84c2 | ||
|
29e0a7112e | ||
|
a1b7a5a53d | ||
|
ecf98069f6 | ||
|
0476e1b498 | ||
|
a122271f09 | ||
|
600a128f83 | ||
|
55825c301e | ||
|
d8b7ded18c | ||
|
c4e1a9b13b | ||
|
9404972732 | ||
|
3b786419d8 | ||
|
92e535025e | ||
|
d3e5796ee1 | ||
|
56dec1c6a2 | ||
|
931927de29 | ||
|
74cf2281dd | ||
|
2b07d54bc7 | ||
|
66a3719b86 | ||
|
64a084477e | ||
|
7a09d24065 | ||
|
a3e20d2d5f | ||
|
32b3d2b456 | ||
|
447c173cad | ||
|
55b4f84fea | ||
|
73e78f05ad | ||
|
54e51b7acf | ||
|
200cccdd3b | ||
|
15b25d5850 | ||
|
21ba8b363e | ||
|
9d2a5fb417 | ||
|
ed3d5053b2 | ||
|
93a2ac9de4 | ||
|
49fdffacea | ||
|
0f6e530798 | ||
|
88b47dfa83 | ||
|
ba9e7814b0 | ||
|
f10996b575 | ||
|
ef90d1eaaf | ||
|
062f749450 | ||
|
a4db48b46b | ||
|
c44e255194 | ||
|
21e9313c10 | ||
|
7b32b4214d | ||
|
6914103289 | ||
|
ab5497a0c9 | ||
|
f48b3774a2 | ||
|
1c9d6b94d1 | ||
|
4b592d0819 | ||
|
a1924ae435 | ||
|
cb6cfde6e8 | ||
|
8e91c038db | ||
|
86318ce04f | ||
|
59d6a12a7e | ||
|
935c90915a | ||
|
b95c0c318e | ||
|
9abfa9efc6 | ||
|
7a5234a0cc | ||
|
af9440152e | ||
|
7f4b0aaadc | ||
|
4a4e13f8ac | ||
|
1d47e2c408 | ||
|
47256a6ed8 | ||
|
732b058489 | ||
|
92cf1c2337 | ||
|
07714dd5bd | ||
|
5cc33b4e8c | ||
|
b0b88a63b6 | ||
|
5b0dc779ed | ||
|
8991be671f | ||
|
6650e4ba85 | ||
|
a1b138a625 | ||
|
df00727310 | ||
|
03771d3aa9 | ||
|
50a80efad5 | ||
|
14a3c939ce | ||
|
aeb8c8fc70 | ||
|
616ff343b7 | ||
|
2f6729f557 | ||
|
015664eb4c | ||
|
98059b52d7 | ||
|
b135bd6cd4 | ||
|
59f27e7f57 | ||
|
edb26e0306 | ||
|
d0367d8560 | ||
|
95db9108e5 | ||
|
a61eb7694d | ||
|
c6233a790f | ||
|
92311d260a | ||
|
af72404259 | ||
|
4a79718fe8 | ||
|
7f35f33b4c | ||
|
bab2f6a664 | ||
|
bb9d0aed5b | ||
|
386708563c | ||
|
ba5f1d8783 | ||
|
d994e6aea6 | ||
|
6e15590e98 | ||
|
d70cc88dab | ||
|
a0b675ec9e | ||
|
784f8a88fb | ||
|
20e7ccd480 | ||
|
210be10c92 | ||
|
421f5fb221 | ||
|
93676f91a0 | ||
|
54e1c2ccbd |
@@ -33,7 +33,26 @@ add_subdirectory("subprojects/udis86")
|
||||
message(STATUS "Setting up wlroots")
|
||||
|
||||
include(ExternalProject)
|
||||
string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER)
|
||||
|
||||
if(CMAKE_BUILD_TYPE)
|
||||
string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER)
|
||||
if(BUILDTYPE_LOWER STREQUAL "release")
|
||||
# Pass.
|
||||
elseif(BUILDTYPE_LOWER STREQUAL "debug")
|
||||
# Pass.
|
||||
elseif(BUILDTYPE_LOWER STREQUAL "relwithdebinfo")
|
||||
set(BUILDTYPE_LOWER "debugoptimized")
|
||||
elseif(BUILDTYPE_LOWER STREQUAL "minsizerel")
|
||||
set(BUILDTYPE_LOWER "minsize")
|
||||
elseif(BUILDTYPE_LOWER STREQUAL "none")
|
||||
set(BUILDTYPE_LOWER "plain")
|
||||
else()
|
||||
set(BUILDTYPE_LOWER "release")
|
||||
endif()
|
||||
else()
|
||||
set(BUILDTYPE_LOWER "release")
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(
|
||||
wlroots
|
||||
PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots
|
||||
@@ -97,7 +116,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
message(STATUS "Enabling ASan")
|
||||
|
||||
target_link_libraries(Hyprland asan)
|
||||
add_compile_options(-fsanitize=address)
|
||||
target_compile_options(Hyprland PUBLIC -fsanitize=address)
|
||||
endif()
|
||||
|
||||
if(USE_TRACY)
|
||||
@@ -164,14 +183,6 @@ else()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_compile_definitions(Hyprland
|
||||
PRIVATE
|
||||
"GIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\""
|
||||
"GIT_BRANCH=\"${GIT_BRANCH}\""
|
||||
"GIT_COMMIT_MESSAGE=\"${GIT_COMMIT_MESSAGE}\""
|
||||
"GIT_DIRTY=\"${GIT_DIRTY}\""
|
||||
"GIT_TAG=\"${GIT_TAG}\"")
|
||||
|
||||
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
|
||||
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
|
||||
include(CPack)
|
||||
@@ -230,4 +241,4 @@ protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v
|
||||
protocol("staging/cursor-shape/cursor-shape-v1.xml" "cursor-shape-v1" false)
|
||||
|
||||
# hyprctl
|
||||
add_subdirectory(hyprctl)
|
||||
add_subdirectory(hyprctl)
|
||||
|
@@ -33,8 +33,8 @@ void CCustomDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& offset
|
||||
(m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? *PROUNDING : m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying());
|
||||
|
||||
// draw the border
|
||||
wlr_box fullBox = {(int)(m_vLastWindowPos.x - *PBORDERSIZE), (int)(m_vLastWindowPos.y - *PBORDERSIZE), (int)(m_vLastWindowSize.x + 2.0 * *PBORDERSIZE),
|
||||
(int)(m_vLastWindowSize.y + 2.0 * *PBORDERSIZE)};
|
||||
CBox fullBox = {(int)(m_vLastWindowPos.x - *PBORDERSIZE), (int)(m_vLastWindowPos.y - *PBORDERSIZE), (int)(m_vLastWindowSize.x + 2.0 * *PBORDERSIZE),
|
||||
(int)(m_vLastWindowSize.y + 2.0 * *PBORDERSIZE)};
|
||||
|
||||
fullBox.x -= pMonitor->vecPosition.x;
|
||||
fullBox.y -= pMonitor->vecPosition.y;
|
||||
@@ -49,9 +49,9 @@ void CCustomDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& offset
|
||||
if (fullBox.width < 1 || fullBox.height < 1)
|
||||
return; // don't draw invisible shadows
|
||||
|
||||
g_pHyprOpenGL->scissor((wlr_box*)nullptr);
|
||||
g_pHyprOpenGL->scissor((CBox*)nullptr);
|
||||
|
||||
scaleBox(&fullBox, pMonitor->scale);
|
||||
fullBox.scale(pMonitor->scale);
|
||||
g_pHyprOpenGL->renderBorder(&fullBox, CColor(*PCOLOR), *PROUNDING * pMonitor->scale + *PBORDERSIZE * 2, a);
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ void CCustomDecoration::updateWindow(CWindow* pWindow) {
|
||||
}
|
||||
|
||||
void CCustomDecoration::damageEntire() {
|
||||
wlr_box dm = {(int)(m_vLastWindowPos.x - m_seExtents.topLeft.x), (int)(m_vLastWindowPos.y - m_seExtents.topLeft.y),
|
||||
(int)(m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x), (int)m_seExtents.topLeft.y};
|
||||
CBox dm = {(int)(m_vLastWindowPos.x - m_seExtents.topLeft.x), (int)(m_vLastWindowPos.y - m_seExtents.topLeft.y),
|
||||
(int)(m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x), (int)m_seExtents.topLeft.y};
|
||||
g_pHyprRenderer->damageBox(&dm);
|
||||
}
|
@@ -58,8 +58,8 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
||||
|
||||
HyprlandAPI::addNotification(PHANDLE, "Hello World from an example plugin!", CColor{0.f, 1.f, 1.f, 1.f}, 5000);
|
||||
|
||||
HyprlandAPI::registerCallbackDynamic(PHANDLE, "activeWindow", [&](void* self, std::any data) { onActiveWindowChange(self, data); });
|
||||
HyprlandAPI::registerCallbackDynamic(PHANDLE, "openWindow", [&](void* self, std::any data) { onNewWindow(self, data); });
|
||||
HyprlandAPI::registerCallbackDynamic(PHANDLE, "activeWindow", [&](void* self, SCallbackInfo& info, std::any data) { onActiveWindowChange(self, data); });
|
||||
HyprlandAPI::registerCallbackDynamic(PHANDLE, "openWindow", [&](void* self, SCallbackInfo& info, std::any data) { onNewWindow(self, data); });
|
||||
|
||||
g_pCustomLayout = std::make_unique<CHyprCustomLayout>();
|
||||
|
||||
|
@@ -63,6 +63,8 @@ decoration {
|
||||
enabled = true
|
||||
size = 3
|
||||
passes = 1
|
||||
|
||||
vibrancy = 0.1696
|
||||
}
|
||||
|
||||
drop_shadow = true
|
||||
@@ -163,6 +165,10 @@ bind = $mainMod SHIFT, 8, movetoworkspace, 8
|
||||
bind = $mainMod SHIFT, 9, movetoworkspace, 9
|
||||
bind = $mainMod SHIFT, 0, movetoworkspace, 10
|
||||
|
||||
# Example special workspace (scratchpad)
|
||||
bind = $mainMod, S, togglespecialworkspace, magic
|
||||
bind = $mainMod SHIFT, S, movetoworkspace, special:magic
|
||||
|
||||
# Scroll through existing workspaces with mainMod + scroll
|
||||
bind = $mainMod, mouse_down, workspace, e+1
|
||||
bind = $mainMod, mouse_up, workspace, e-1
|
||||
|
20
flake.lock
generated
20
flake.lock
generated
@@ -25,11 +25,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1694767346,
|
||||
"narHash": "sha256-5uH27SiVFUwsTsqC5rs3kS7pBoNhtoy9QfTP9BmknGk=",
|
||||
"lastModified": 1698134075,
|
||||
"narHash": "sha256-foCD+nuKzfh49bIoiCBur4+Fx1nozo+4C/6k8BYk4sg=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "ace5093e36ab1e95cb9463863491bee90d5a4183",
|
||||
"rev": "8efd5d1e283604f75a808a20e6cde0ef313d07d4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -67,18 +67,18 @@
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"host": "gitlab.freedesktop.org",
|
||||
"lastModified": 1696410538,
|
||||
"narHash": "sha256-ecDhdYLXWHsxMv+EWG36mCNDvzRbu9qfjH7dLxL7aGM=",
|
||||
"lastModified": 1697909146,
|
||||
"narHash": "sha256-jU0I6FoCKnj4zIBL4daosFWh81U1fM719Z6cae8PxSY=",
|
||||
"owner": "wlroots",
|
||||
"repo": "wlroots",
|
||||
"rev": "3406c1b17a4a7e6d4e2a7d9c1176affa72bce1bc",
|
||||
"rev": "47bf87ade2bd32395615a385ebde1fefbcdf79a2",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
"host": "gitlab.freedesktop.org",
|
||||
"owner": "wlroots",
|
||||
"repo": "wlroots",
|
||||
"rev": "3406c1b17a4a7e6d4e2a7d9c1176affa72bce1bc",
|
||||
"rev": "47bf87ade2bd32395615a385ebde1fefbcdf79a2",
|
||||
"type": "gitlab"
|
||||
}
|
||||
},
|
||||
@@ -95,11 +95,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1694628480,
|
||||
"narHash": "sha256-Qg9hstRw0pvjGu5hStkr2UX1D73RYcQ9Ns/KnZMIm9w=",
|
||||
"lastModified": 1697981233,
|
||||
"narHash": "sha256-y8q4XUwx+gVK7i2eLjfR32lVo7TYvEslyzrmzYEaPZU=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "8f45a6435069b9e24ebd3160eda736d7a391cbf2",
|
||||
"rev": "22e7a65ff9633e1dedfa5317fdffc49f68de2ff2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@@ -12,7 +12,7 @@
|
||||
host = "gitlab.freedesktop.org";
|
||||
owner = "wlroots";
|
||||
repo = "wlroots";
|
||||
rev = "3406c1b17a4a7e6d4e2a7d9c1176affa72bce1bc";
|
||||
rev = "47bf87ade2bd32395615a385ebde1fefbcdf79a2";
|
||||
flake = false;
|
||||
};
|
||||
|
||||
|
@@ -29,6 +29,7 @@ commands:
|
||||
monitors
|
||||
workspaces
|
||||
activeworkspace
|
||||
workspacerules
|
||||
clients
|
||||
activewindow
|
||||
layers
|
||||
@@ -370,6 +371,8 @@ int main(int argc, char** argv) {
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/activeworkspace"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/workspacerules"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/activewindow"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/layers"))
|
||||
|
@@ -69,14 +69,14 @@ if get_option('buildtype') == 'debug'
|
||||
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
|
||||
endif
|
||||
|
||||
version_h = run_command('sh', '-c', 'scripts/generateVersion.sh')
|
||||
|
||||
globber = run_command('find', 'src', '-name', '*.h*', check: true)
|
||||
headers = globber.stdout().strip().split('\n')
|
||||
foreach file : headers
|
||||
install_headers(file, subdir: 'hyprland', preserve_path: true)
|
||||
endforeach
|
||||
|
||||
version_h = run_command('sh', '-c', 'scripts/generateVersion.sh')
|
||||
|
||||
subdir('protocols')
|
||||
subdir('src')
|
||||
subdir('hyprctl')
|
||||
|
@@ -90,8 +90,9 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
|
||||
then "debug"
|
||||
else "release";
|
||||
|
||||
mesonAutoFeatures = "disabled";
|
||||
|
||||
mesonFlags = builtins.concatLists [
|
||||
["-Dauto_features=disabled"]
|
||||
(lib.optional enableXWayland "-Dxwayland=enabled")
|
||||
(lib.optional legacyRenderer "-Dlegacy_renderer=enabled")
|
||||
(lib.optional withSystemd "-Dsystemd=enabled")
|
||||
|
@@ -1,10 +1,10 @@
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 726933bc..28b4d9ac 100644
|
||||
index 1d2c7f9f..c5ef4e67 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -29,20 +29,7 @@ add_project_arguments(
|
||||
],
|
||||
language: 'cpp')
|
||||
@@ -33,20 +33,7 @@ if cpp_compiler.check_header('execinfo.h')
|
||||
add_project_arguments('-DHAS_EXECINFO', language: 'cpp')
|
||||
endif
|
||||
|
||||
-wlroots = subproject('wlroots', default_options: ['examples=false', 'renderers=gles2'])
|
||||
-have_xwlr = wlroots.get_variable('features').get('xwayland')
|
||||
@@ -24,17 +24,17 @@ index 726933bc..28b4d9ac 100644
|
||||
add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
|
||||
endif
|
||||
|
||||
@@ -71,8 +58,6 @@ foreach file : headers
|
||||
install_headers(file, subdir: 'hyprland', preserve_path: true)
|
||||
endforeach
|
||||
@@ -69,8 +56,6 @@ if get_option('buildtype') == 'debug'
|
||||
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
|
||||
endif
|
||||
|
||||
-version_h = run_command('sh', '-c', 'scripts/generateVersion.sh')
|
||||
-
|
||||
subdir('protocols')
|
||||
subdir('src')
|
||||
subdir('hyprctl')
|
||||
globber = run_command('find', 'src', '-name', '*.h*', check: true)
|
||||
headers = globber.stdout().strip().split('\n')
|
||||
foreach file : headers
|
||||
diff --git a/src/meson.build b/src/meson.build
|
||||
index 2065c6f5..55530605 100644
|
||||
index 0af864b9..38723b8c 100644
|
||||
--- a/src/meson.build
|
||||
+++ b/src/meson.build
|
||||
@@ -9,16 +9,16 @@ executable('Hyprland', src,
|
||||
|
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"version": "0.31.0"
|
||||
"version": "0.32.0"
|
||||
}
|
@@ -121,7 +121,6 @@ void CCompositor::initServer() {
|
||||
signal(SIGSEGV, handleUnrecoverableSignal);
|
||||
signal(SIGABRT, handleUnrecoverableSignal);
|
||||
signal(SIGUSR1, handleUserSignal);
|
||||
//wl_event_loop_add_signal(m_sWLEventLoop, SIGINT, handleCritSignal, nullptr);
|
||||
|
||||
initManagers(STAGE_PRIORITY);
|
||||
|
||||
@@ -215,7 +214,6 @@ void CCompositor::initServer() {
|
||||
|
||||
m_sWLRPresentation = wlr_presentation_create(m_sWLDisplay, m_sWLRBackend);
|
||||
|
||||
m_sWLRIdle = wlr_idle_create(m_sWLDisplay);
|
||||
m_sWLRIdleNotifier = wlr_idle_notifier_v1_create(m_sWLDisplay);
|
||||
|
||||
m_sWLRLayerShell = wlr_layer_shell_v1_create(m_sWLDisplay, 4);
|
||||
@@ -465,6 +463,25 @@ void CCompositor::removeLockFile() {
|
||||
std::filesystem::remove(PATH);
|
||||
}
|
||||
|
||||
void CCompositor::prepareFallbackOutput() {
|
||||
// create a backup monitor
|
||||
wlr_backend* headless = nullptr;
|
||||
wlr_multi_for_each_backend(
|
||||
m_sWLRBackend,
|
||||
[](wlr_backend* b, void* data) {
|
||||
if (wlr_backend_is_headless(b))
|
||||
*((wlr_backend**)data) = b;
|
||||
},
|
||||
&headless);
|
||||
|
||||
if (!headless) {
|
||||
Debug::log(WARN, "Unsafe state will be ineffective, no fallback output");
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_headless_add_output(headless, 1920, 1080);
|
||||
}
|
||||
|
||||
void CCompositor::startCompositor() {
|
||||
initAllSignals();
|
||||
|
||||
@@ -516,6 +533,8 @@ void CCompositor::startCompositor() {
|
||||
throwError("The backend could not start!");
|
||||
}
|
||||
|
||||
prepareFallbackOutput();
|
||||
|
||||
g_pHyprRenderer->setCursorFromName("left_ptr");
|
||||
|
||||
#ifdef USES_SYSTEMD
|
||||
@@ -612,38 +631,35 @@ CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
|
||||
|
||||
if (PMONITOR->specialWorkspaceID) {
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
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_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w->isHidden() &&
|
||||
!w->m_bNoFocus)
|
||||
auto box = w->getWindowMainSurfaceBox();
|
||||
if (w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && box.containsPoint(pos) && !w->isHidden() && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && !w->m_bIsFloating && !w->isHidden() &&
|
||||
!w->m_bNoFocus)
|
||||
auto box = w->getWindowMainSurfaceBox();
|
||||
if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && box.containsPoint(pos) && w->m_bIsMapped && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
}
|
||||
|
||||
// pinned
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
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 && !w->isHidden() && w->m_bPinned && !w->m_bNoFocus)
|
||||
auto box = w->getWindowMainSurfaceBox();
|
||||
if (box.containsPoint(pos) && w->m_bIsMapped && w->m_bIsFloating && !w->isHidden() && w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
// first loop over floating cuz they're above, m_vWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
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->isHidden() && !w->m_bPinned &&
|
||||
!w->m_bNoFocus)
|
||||
auto box = w->getWindowMainSurfaceBox();
|
||||
if (box.containsPoint(pos) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && !w->m_bIsFloating && PMONITOR->activeWorkspace == w->m_iWorkspaceID && !w->isHidden() && !w->m_bNoFocus)
|
||||
auto box = w->getWindowMainSurfaceBox();
|
||||
if (box.containsPoint(pos) && w->m_bIsMapped && !w->m_bIsFloating && PMONITOR->activeWorkspace == w->m_iWorkspaceID && !w->isHidden() && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
@@ -655,15 +671,15 @@ CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
|
||||
|
||||
if (PMONITOR->specialWorkspaceID) {
|
||||
for (auto& w : m_vWindows) {
|
||||
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && wlr_box_contains_point(&box, pos.x, pos.y) && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus)
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && box.containsPoint(pos) && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus)
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (w->m_bIsMapped && box.containsPoint(pos) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
@@ -681,16 +697,16 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
||||
if (PMONITOR->specialWorkspaceID) {
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
const auto BB = w->getWindowInputBox();
|
||||
wlr_box box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
|
||||
if (w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w->isHidden() &&
|
||||
!w->m_bX11ShouldntFocus && !w->m_bNoFocus)
|
||||
CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
|
||||
if (w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && box.containsPoint(pos) && !w->isHidden() && !w->m_bX11ShouldntFocus &&
|
||||
!w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (!w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w->isHidden() &&
|
||||
!w->m_bX11ShouldntFocus && !w->m_bNoFocus)
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (!w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && box.containsPoint(pos) && !w->isHidden() && !w->m_bX11ShouldntFocus &&
|
||||
!w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
}
|
||||
@@ -698,9 +714,9 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
||||
// pinned windows on top of floating regardless
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
const auto BB = w->getWindowInputBox();
|
||||
wlr_box box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
|
||||
CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_bNoFocus) {
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y))
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}))
|
||||
return w.get();
|
||||
|
||||
if (!w->m_bIsX11) {
|
||||
@@ -713,13 +729,13 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
||||
// 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_vWindows | std::views::reverse) {
|
||||
const auto BB = w->getWindowInputBox();
|
||||
wlr_box box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
|
||||
CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_bNoFocus) {
|
||||
// OR windows should add focus to parent
|
||||
if (w->m_bX11ShouldntFocus && w->m_iX11Type != 2)
|
||||
continue;
|
||||
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y)) {
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y})) {
|
||||
|
||||
if (w->m_bIsX11 && w->m_iX11Type == 2 && !wlr_xwayland_or_surface_wants_focus(w->m_uSurface.xwayland)) {
|
||||
// Override Redirect
|
||||
@@ -745,9 +761,9 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
||||
}
|
||||
}
|
||||
for (auto& w : m_vWindows) {
|
||||
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (!w->m_bIsFloating && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->isHidden() &&
|
||||
!w->m_bX11ShouldntFocus && !w->m_bNoFocus)
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->isHidden() && !w->m_bX11ShouldntFocus &&
|
||||
!w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
@@ -759,37 +775,36 @@ CWindow* CCompositor::windowFromCursor() {
|
||||
|
||||
if (PMONITOR->specialWorkspaceID) {
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
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_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) &&
|
||||
CBox 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_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) &&
|
||||
!w->isHidden() && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && !w->m_bNoFocus)
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
}
|
||||
|
||||
// pinned
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
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 && w->m_bPinned && !w->m_bNoFocus)
|
||||
CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
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_bPinned &&
|
||||
!w->m_bNoFocus)
|
||||
CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bNoFocus)
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
@@ -798,14 +813,14 @@ CWindow* CCompositor::windowFromCursor() {
|
||||
|
||||
CWindow* CCompositor::windowFloatingFromCursor() {
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
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 && !w->isHidden() && w->m_bPinned && !w->m_bNoFocus)
|
||||
CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && !w->isHidden() && w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
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->isHidden() &&
|
||||
CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() &&
|
||||
!w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
@@ -825,8 +840,9 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, CWindow* pW
|
||||
double subx, suby;
|
||||
|
||||
// calc for oversized windows... fucking bullshit, again.
|
||||
wlr_box geom;
|
||||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom);
|
||||
CBox geom;
|
||||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, geom.pWlr());
|
||||
geom.applyFromWlr();
|
||||
|
||||
const auto PFOUND = wlr_xdg_surface_surface_at(PSURFACE, pos.x - pWindow->m_vRealPosition.vec().x + geom.x, pos.y - pWindow->m_vRealPosition.vec().y + geom.y, &subx, &suby);
|
||||
|
||||
@@ -867,10 +883,14 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, CWindow* pWindow
|
||||
},
|
||||
&iterData);
|
||||
|
||||
CBox geom = {};
|
||||
wlr_xdg_surface_get_geometry(PSURFACE, geom.pWlr());
|
||||
geom.applyFromWlr();
|
||||
|
||||
if (std::get<1>(iterData) == -1337 && std::get<2>(iterData) == -1337)
|
||||
return vec - pWindow->m_vRealPosition.goalv();
|
||||
|
||||
return vec - pWindow->m_vRealPosition.goalv() - Vector2D{std::get<1>(iterData), std::get<2>(iterData)};
|
||||
return vec - pWindow->m_vRealPosition.goalv() - Vector2D{std::get<1>(iterData), std::get<2>(iterData)} + Vector2D{geom.x, geom.y};
|
||||
}
|
||||
|
||||
CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) {
|
||||
@@ -885,6 +905,8 @@ CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) {
|
||||
|
||||
void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||
|
||||
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||
|
||||
if (g_pCompositor->m_sSeat.exclusiveClient) {
|
||||
Debug::log(LOG, "Disallowing setting focus to a window due to there being an active input inhibitor layer.");
|
||||
return;
|
||||
@@ -1008,6 +1030,9 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||
} else {
|
||||
std::rotate(m_vWindowFocusHistory.begin(), HISTORYPIVOT, HISTORYPIVOT + 1);
|
||||
}
|
||||
|
||||
if (*PFOLLOWMOUSE == 0)
|
||||
g_pInputManager->sendMotionEventsToFocused();
|
||||
}
|
||||
|
||||
void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
|
||||
@@ -1194,24 +1219,33 @@ void CCompositor::sanityCheckWorkspaces() {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto WINDOWSONWORKSPACE = getWindowsOnWorkspace((*it)->m_iID);
|
||||
const auto& WORKSPACE = *it;
|
||||
const auto WINDOWSONWORKSPACE = getWindowsOnWorkspace(WORKSPACE->m_iID);
|
||||
|
||||
if ((WINDOWSONWORKSPACE == 0 && !isWorkspaceVisible((*it)->m_iID))) {
|
||||
if (WINDOWSONWORKSPACE == 0) {
|
||||
if (!isWorkspaceVisible(WORKSPACE->m_iID)) {
|
||||
|
||||
if ((*it)->m_bIsSpecialWorkspace) {
|
||||
if ((*it)->m_fAlpha.fl() > 0.f /* don't abruptly end the fadeout */) {
|
||||
++it;
|
||||
continue;
|
||||
if (WORKSPACE->m_bIsSpecialWorkspace) {
|
||||
if (WORKSPACE->m_fAlpha.fl() > 0.f /* don't abruptly end the fadeout */) {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto PMONITOR = getMonitorFromID(WORKSPACE->m_iMonitorID);
|
||||
|
||||
if (PMONITOR && PMONITOR->specialWorkspaceID == WORKSPACE->m_iID)
|
||||
PMONITOR->setSpecialWorkspace(nullptr);
|
||||
}
|
||||
|
||||
const auto PMONITOR = getMonitorFromID((*it)->m_iMonitorID);
|
||||
|
||||
if (PMONITOR && PMONITOR->specialWorkspaceID == (*it)->m_iID)
|
||||
PMONITOR->setSpecialWorkspace(nullptr);
|
||||
it = m_vWorkspaces.erase(it);
|
||||
continue;
|
||||
}
|
||||
if (!WORKSPACE->m_bOnCreatedEmptyExecuted) {
|
||||
if (auto cmd = WORKSPACERULE.onCreatedEmptyRunCmd)
|
||||
g_pKeybindManager->spawn(*cmd);
|
||||
|
||||
it = m_vWorkspaces.erase(it);
|
||||
continue;
|
||||
WORKSPACE->m_bOnCreatedEmptyExecuted = true;
|
||||
}
|
||||
}
|
||||
|
||||
++it;
|
||||
@@ -1467,82 +1501,144 @@ void CCompositor::addToFadingOutSafe(CWindow* pWindow) {
|
||||
|
||||
CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
|
||||
|
||||
if (!isDirection(dir))
|
||||
return nullptr;
|
||||
|
||||
// 0 -> history, 1 -> shared length
|
||||
static auto* const PMETHOD = &g_pConfigManager->getConfigValuePtr("binds:focus_preferred_method")->intValue;
|
||||
|
||||
const auto WINDOWIDEALBB = pWindow->getWindowIdealBoundingBoxIgnoreReserved();
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
const auto POSA = Vector2D(WINDOWIDEALBB.x, WINDOWIDEALBB.y);
|
||||
const auto SIZEA = Vector2D(WINDOWIDEALBB.width, WINDOWIDEALBB.height);
|
||||
if (!PMONITOR)
|
||||
return nullptr; // ??
|
||||
|
||||
auto leaderValue = -1;
|
||||
CWindow* leaderWindow = nullptr;
|
||||
const auto WINDOWIDEALBB = pWindow->m_bIsFullscreen ? wlr_box{(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y} :
|
||||
pWindow->getWindowIdealBoundingBoxIgnoreReserved();
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w.get() == pWindow || !w->m_bIsMapped || w->isHidden() || w->m_bIsFloating || !isWorkspaceVisible(w->m_iWorkspaceID))
|
||||
continue;
|
||||
const auto POSA = Vector2D(WINDOWIDEALBB.x, WINDOWIDEALBB.y);
|
||||
const auto SIZEA = Vector2D(WINDOWIDEALBB.width, WINDOWIDEALBB.height);
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID);
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !w->m_bIsFullscreen && !w->m_bCreatedOverFullscreen)
|
||||
continue;
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
auto leaderValue = -1;
|
||||
CWindow* leaderWindow = nullptr;
|
||||
|
||||
const auto BWINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved();
|
||||
if (!pWindow->m_bIsFloating) {
|
||||
|
||||
const auto POSB = Vector2D(BWINDOWIDEALBB.x, BWINDOWIDEALBB.y);
|
||||
const auto SIZEB = Vector2D(BWINDOWIDEALBB.width, BWINDOWIDEALBB.height);
|
||||
// for tiled windows, we calc edges
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w.get() == pWindow || !w->m_bIsMapped || w->isHidden() || w->m_bIsFloating || !isWorkspaceVisible(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
double intersectLength = -1;
|
||||
if (pWindow->m_iMonitorID == w->m_iMonitorID && pWindow->m_iWorkspaceID != w->m_iWorkspaceID)
|
||||
continue;
|
||||
|
||||
switch (dir) {
|
||||
case 'l':
|
||||
if (STICKS(POSA.x, POSB.x + SIZEB.x)) {
|
||||
intersectLength = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
if (STICKS(POSA.x + SIZEA.x, POSB.x)) {
|
||||
intersectLength = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
case 'u':
|
||||
if (STICKS(POSA.y, POSB.y + SIZEB.y)) {
|
||||
intersectLength = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
case 'd':
|
||||
if (STICKS(POSA.y + SIZEA.y, POSB.y)) {
|
||||
intersectLength = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !w->m_bIsFullscreen && !w->m_bCreatedOverFullscreen)
|
||||
continue;
|
||||
|
||||
if (*PMETHOD == 0 /* history */) {
|
||||
if (intersectLength > 0) {
|
||||
const auto BWINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved();
|
||||
|
||||
// get idx
|
||||
int windowIDX = -1;
|
||||
for (size_t i = 0; i < g_pCompositor->m_vWindowFocusHistory.size(); ++i) {
|
||||
if (g_pCompositor->m_vWindowFocusHistory[i] == w.get()) {
|
||||
windowIDX = i;
|
||||
break;
|
||||
const auto POSB = Vector2D(BWINDOWIDEALBB.x, BWINDOWIDEALBB.y);
|
||||
const auto SIZEB = Vector2D(BWINDOWIDEALBB.width, BWINDOWIDEALBB.height);
|
||||
|
||||
double intersectLength = -1;
|
||||
|
||||
switch (dir) {
|
||||
case 'l':
|
||||
if (STICKS(POSA.x, POSB.x + SIZEB.x)) {
|
||||
intersectLength = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
if (STICKS(POSA.x + SIZEA.x, POSB.x)) {
|
||||
intersectLength = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
case 'u':
|
||||
if (STICKS(POSA.y, POSB.y + SIZEB.y)) {
|
||||
intersectLength = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
case 'd':
|
||||
if (STICKS(POSA.y + SIZEA.y, POSB.y)) {
|
||||
intersectLength = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (*PMETHOD == 0 /* history */) {
|
||||
if (intersectLength > 0) {
|
||||
|
||||
// get idx
|
||||
int windowIDX = -1;
|
||||
for (size_t i = 0; i < g_pCompositor->m_vWindowFocusHistory.size(); ++i) {
|
||||
if (g_pCompositor->m_vWindowFocusHistory[i] == w.get()) {
|
||||
windowIDX = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
windowIDX = g_pCompositor->m_vWindowFocusHistory.size() - windowIDX;
|
||||
|
||||
if (windowIDX > leaderValue) {
|
||||
leaderValue = windowIDX;
|
||||
leaderWindow = w.get();
|
||||
}
|
||||
}
|
||||
|
||||
windowIDX = g_pCompositor->m_vWindowFocusHistory.size() - windowIDX;
|
||||
|
||||
if (windowIDX > leaderValue) {
|
||||
leaderValue = windowIDX;
|
||||
} else /* length */ {
|
||||
if (intersectLength > leaderValue) {
|
||||
leaderValue = intersectLength;
|
||||
leaderWindow = w.get();
|
||||
}
|
||||
}
|
||||
} else /* length */ {
|
||||
if (intersectLength > leaderValue) {
|
||||
leaderValue = intersectLength;
|
||||
}
|
||||
} else {
|
||||
// for floating windows, we calculate best distance and angle.
|
||||
// if there is a window with angle better than THRESHOLD, only distance counts
|
||||
|
||||
if (dir == 'u')
|
||||
dir = 't';
|
||||
if (dir == 'd')
|
||||
dir = 'b';
|
||||
|
||||
static const std::unordered_map<char, Vector2D> VECTORS = {{'r', {1, 0}}, {'t', {0, -1}}, {'b', {0, 1}}, {'l', {-1, 0}}};
|
||||
|
||||
//
|
||||
auto vectorAngles = [](Vector2D a, Vector2D b) -> double {
|
||||
double dot = a.x * b.x + a.y * b.y;
|
||||
double ang = std::acos(dot / (a.size() * b.size()));
|
||||
return ang;
|
||||
};
|
||||
|
||||
float bestAngleAbs = 2.0 * M_PI;
|
||||
constexpr float THRESHOLD = 0.3 * M_PI;
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w.get() == pWindow || !w->m_bIsMapped || w->isHidden() || !w->m_bIsFloating || !isWorkspaceVisible(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
if (pWindow->m_iMonitorID == w->m_iMonitorID && pWindow->m_iWorkspaceID != w->m_iWorkspaceID)
|
||||
continue;
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !w->m_bIsFullscreen && !w->m_bCreatedOverFullscreen)
|
||||
continue;
|
||||
|
||||
const auto DIST = w->middle().distance(pWindow->middle());
|
||||
const auto ANGLE = vectorAngles(Vector2D{w->middle() - pWindow->middle()}, VECTORS.at(dir));
|
||||
|
||||
if (ANGLE > M_PI_2)
|
||||
continue; // if the angle is over 90 degrees, ignore. Wrong direction entirely.
|
||||
|
||||
if ((bestAngleAbs < THRESHOLD && DIST < leaderValue && ANGLE < THRESHOLD) || (ANGLE < bestAngleAbs && bestAngleAbs > THRESHOLD) || leaderValue == -1) {
|
||||
leaderValue = DIST;
|
||||
bestAngleAbs = ANGLE;
|
||||
leaderWindow = w.get();
|
||||
}
|
||||
}
|
||||
|
||||
if (!leaderWindow && PWORKSPACE->m_bHasFullscreenWindow)
|
||||
leaderWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
}
|
||||
|
||||
if (leaderValue != -1)
|
||||
@@ -2158,7 +2254,7 @@ void CCompositor::updateFullscreenFadeOnWorkspace(CWorkspace* pWorkspace) {
|
||||
}
|
||||
|
||||
void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode mode) {
|
||||
if (!windowValidMapped(pWindow))
|
||||
if (!windowValidMapped(pWindow) || g_pCompositor->m_bUnsafeState)
|
||||
return;
|
||||
|
||||
if (pWindow->m_bPinned) {
|
||||
@@ -2254,6 +2350,21 @@ CWindow* CCompositor::getWindowByRegex(const std::string& regexp) {
|
||||
} else if (regexp.starts_with("pid:")) {
|
||||
mode = MODE_PID;
|
||||
matchCheck = regexp.substr(4);
|
||||
} else if (regexp.starts_with("floating") || regexp.starts_with("tiled")) {
|
||||
// first floating on the current ws
|
||||
if (!m_pLastWindow)
|
||||
return nullptr;
|
||||
|
||||
const bool FLOAT = regexp.starts_with("floating");
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
if (!w->m_bIsMapped || w->m_bIsFloating != FLOAT || w->m_iWorkspaceID != m_pLastWindow->m_iWorkspaceID || w->isHidden())
|
||||
continue;
|
||||
|
||||
return w.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
@@ -2568,12 +2679,10 @@ CWindow* CCompositor::getForceFocus() {
|
||||
}
|
||||
|
||||
void CCompositor::notifyIdleActivity() {
|
||||
wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
|
||||
wlr_idle_notifier_v1_notify_activity(g_pCompositor->m_sWLRIdleNotifier, g_pCompositor->m_sSeat.seat);
|
||||
}
|
||||
|
||||
void CCompositor::setIdleActivityInhibit(bool enabled) {
|
||||
wlr_idle_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, enabled);
|
||||
wlr_idle_notifier_v1_set_inhibited(g_pCompositor->m_sWLRIdleNotifier, !enabled);
|
||||
}
|
||||
void CCompositor::arrangeMonitors() {
|
||||
@@ -2641,24 +2750,10 @@ void CCompositor::enterUnsafeState() {
|
||||
|
||||
Debug::log(LOG, "Entering unsafe state");
|
||||
|
||||
if (!m_pUnsafeOutput->m_bEnabled)
|
||||
m_pUnsafeOutput->onConnect(false);
|
||||
|
||||
m_bUnsafeState = true;
|
||||
|
||||
// create a backup monitor
|
||||
wlr_backend* headless = nullptr;
|
||||
wlr_multi_for_each_backend(
|
||||
m_sWLRBackend,
|
||||
[](wlr_backend* b, void* data) {
|
||||
if (wlr_backend_is_headless(b))
|
||||
*((wlr_backend**)data) = b;
|
||||
},
|
||||
&headless);
|
||||
|
||||
if (!headless) {
|
||||
Debug::log(WARN, "Entering an unsafe state without a headless backend");
|
||||
return;
|
||||
}
|
||||
|
||||
m_pUnsafeOutput = wlr_headless_add_output(headless, 1920, 1080);
|
||||
}
|
||||
|
||||
void CCompositor::leaveUnsafeState() {
|
||||
@@ -2669,8 +2764,29 @@ void CCompositor::leaveUnsafeState() {
|
||||
|
||||
m_bUnsafeState = false;
|
||||
|
||||
if (m_pUnsafeOutput)
|
||||
wlr_output_destroy(m_pUnsafeOutput);
|
||||
CMonitor* pNewMonitor = nullptr;
|
||||
for (auto& pMonitor : m_vMonitors) {
|
||||
if (pMonitor->output != m_pUnsafeOutput->output) {
|
||||
pNewMonitor = pMonitor.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_pUnsafeOutput = nullptr;
|
||||
RASSERT(pNewMonitor, "Tried to leave unsafe without a monitor");
|
||||
|
||||
if (m_pUnsafeOutput->m_bEnabled)
|
||||
m_pUnsafeOutput->onDisconnect();
|
||||
|
||||
for (auto& m : m_vMonitors) {
|
||||
scheduleFrameForMonitor(m.get());
|
||||
}
|
||||
}
|
||||
|
||||
void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scale) {
|
||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(pSurface, scale);
|
||||
wlr_surface_set_preferred_buffer_scale(pSurface, static_cast<int32_t>(std::ceil(scale)));
|
||||
}
|
||||
|
||||
void CCompositor::setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform) {
|
||||
wlr_surface_set_preferred_buffer_transform(pSurface, transform);
|
||||
}
|
@@ -54,7 +54,6 @@ class CCompositor {
|
||||
wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr;
|
||||
wlr_xdg_activation_v1* m_sWLRXDGActivation;
|
||||
wlr_output_layout* m_sWLROutputLayout;
|
||||
wlr_idle* m_sWLRIdle;
|
||||
wlr_idle_notifier_v1* m_sWLRIdleNotifier;
|
||||
wlr_layer_shell_v1* m_sWLRLayerShell;
|
||||
wlr_xdg_shell* m_sWLRXDGShell;
|
||||
@@ -122,7 +121,8 @@ class CCompositor {
|
||||
bool m_bSessionActive = true;
|
||||
bool m_bDPMSStateON = true;
|
||||
bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
|
||||
wlr_output* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state
|
||||
bool m_bNextIsUnsafe = false; // because wlroots
|
||||
CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state
|
||||
bool m_bIsShuttingDown = false;
|
||||
|
||||
// ------------------------------------------------- //
|
||||
@@ -207,6 +207,8 @@ class CCompositor {
|
||||
void arrangeMonitors();
|
||||
void enterUnsafeState();
|
||||
void leaveUnsafeState();
|
||||
void setPreferredScaleForSurface(wlr_surface* pSurface, double scale);
|
||||
void setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform);
|
||||
|
||||
std::string explicitConfigPath;
|
||||
|
||||
@@ -214,6 +216,7 @@ class CCompositor {
|
||||
void initAllSignals();
|
||||
void setRandomSplash();
|
||||
void initManagers(eManagersInitStage stage);
|
||||
void prepareFallbackOutput();
|
||||
|
||||
uint64_t m_iHyprlandPID = 0;
|
||||
};
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "helpers/Vector2D.hpp"
|
||||
|
||||
enum eIcons
|
||||
{
|
||||
ICON_WARNING = 0,
|
||||
@@ -22,4 +24,22 @@ enum eRenderStage
|
||||
RENDER_POST_MIRROR, /* After rendering a mirror */
|
||||
RENDER_PRE_WINDOW, /* Before rendering a window (any pass) Note some windows (e.g. tiled) may have 2 passes (main & popup) */
|
||||
RENDER_POST_WINDOW, /* After rendering a window (any pass) */
|
||||
};
|
||||
|
||||
struct SCallbackInfo {
|
||||
bool cancelled = false; /* on cancellable events, will cancel the event. */
|
||||
};
|
||||
|
||||
struct SWindowDecorationExtents {
|
||||
Vector2D topLeft;
|
||||
Vector2D bottomRight;
|
||||
|
||||
//
|
||||
SWindowDecorationExtents operator*(const double& scale) const {
|
||||
return SWindowDecorationExtents{topLeft * scale, bottomRight * scale};
|
||||
}
|
||||
|
||||
SWindowDecorationExtents floor() {
|
||||
return {topLeft.floor(), bottomRight.floor()};
|
||||
}
|
||||
};
|
@@ -55,12 +55,12 @@ SWindowDecorationExtents CWindow::getFullWindowExtents() {
|
||||
}
|
||||
|
||||
if (m_pWLSurface.exists() && !m_bIsX11) {
|
||||
wlr_box surfaceExtents = {0, 0, 0, 0};
|
||||
CBox surfaceExtents = {0, 0, 0, 0};
|
||||
// TODO: this could be better, perhaps make a getFullWindowRegion?
|
||||
wlr_xdg_surface_for_each_popup_surface(
|
||||
m_uSurface.xdg,
|
||||
[](wlr_surface* surf, int sx, int sy, void* data) {
|
||||
wlr_box* pSurfaceExtents = (wlr_box*)data;
|
||||
CBox* pSurfaceExtents = (CBox*)data;
|
||||
if (sx < pSurfaceExtents->x)
|
||||
pSurfaceExtents->x = sx;
|
||||
if (sy < pSurfaceExtents->y)
|
||||
@@ -88,21 +88,21 @@ SWindowDecorationExtents CWindow::getFullWindowExtents() {
|
||||
return maxExtents;
|
||||
}
|
||||
|
||||
wlr_box CWindow::getFullWindowBoundingBox() {
|
||||
CBox CWindow::getFullWindowBoundingBox() {
|
||||
if (m_sAdditionalConfigData.dimAround) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||
}
|
||||
|
||||
auto maxExtents = getFullWindowExtents();
|
||||
auto maxExtents = getFullWindowExtents();
|
||||
|
||||
wlr_box finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y,
|
||||
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
||||
CBox finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y,
|
||||
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
||||
|
||||
return finalBox;
|
||||
}
|
||||
|
||||
wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
||||
CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
|
||||
@@ -113,7 +113,7 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
||||
POS = PMONITOR->vecPosition;
|
||||
SIZE = PMONITOR->vecSize;
|
||||
|
||||
return wlr_box{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
||||
return CBox{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
||||
}
|
||||
|
||||
if (DELTALESSTHAN(POS.y - PMONITOR->vecPosition.y, PMONITOR->vecReservedTopLeft.y, 1)) {
|
||||
@@ -131,10 +131,10 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
||||
SIZE.y += PMONITOR->vecReservedBottomRight.y;
|
||||
}
|
||||
|
||||
return wlr_box{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
||||
return CBox{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
||||
}
|
||||
|
||||
wlr_box CWindow::getWindowInputBox() {
|
||||
CBox CWindow::getWindowInputBox() {
|
||||
const int BORDERSIZE = getRealBorderSize();
|
||||
|
||||
if (m_sAdditionalConfigData.dimAround) {
|
||||
@@ -146,7 +146,7 @@ wlr_box CWindow::getWindowInputBox() {
|
||||
|
||||
for (auto& wd : m_dWindowDecorations) {
|
||||
|
||||
if (!wd->allowsInput())
|
||||
if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT))
|
||||
continue;
|
||||
|
||||
const auto EXTENTS = wd->getWindowDecorationExtents();
|
||||
@@ -165,12 +165,16 @@ wlr_box CWindow::getWindowInputBox() {
|
||||
}
|
||||
|
||||
// Add extents to the real base BB and return
|
||||
wlr_box finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y,
|
||||
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
||||
CBox finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y,
|
||||
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
||||
|
||||
return finalBox;
|
||||
}
|
||||
|
||||
CBox CWindow::getWindowMainSurfaceBox() {
|
||||
return {m_vRealPosition.vec().x, m_vRealPosition.vec().y, m_vRealSize.vec().x, m_vRealSize.vec().y};
|
||||
}
|
||||
|
||||
SWindowDecorationExtents CWindow::getFullWindowReservedArea() {
|
||||
SWindowDecorationExtents extents;
|
||||
|
||||
@@ -219,6 +223,9 @@ pid_t CWindow::getPID() {
|
||||
|
||||
wl_client_get_credentials(wl_resource_get_client(m_uSurface.xdg->resource), &PID, nullptr, nullptr);
|
||||
} else {
|
||||
if (!m_bIsMapped || !m_bMappedX11)
|
||||
return -1;
|
||||
|
||||
PID = m_uSurface.xwayland->pid;
|
||||
}
|
||||
|
||||
@@ -325,7 +332,8 @@ void CWindow::updateSurfaceOutputs() {
|
||||
m_pWLSurface.wlr(),
|
||||
[](wlr_surface* surf, int x, int y, void* data) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(((CWindow*)data)->m_iMonitorID);
|
||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(surf, PMONITOR ? PMONITOR->scale : 1.f);
|
||||
g_pCompositor->setPreferredScaleForSurface(surf, PMONITOR ? PMONITOR->scale : 1.f);
|
||||
g_pCompositor->setPreferredTransformForSurface(surf, PMONITOR->transform);
|
||||
},
|
||||
this);
|
||||
}
|
||||
@@ -334,6 +342,10 @@ void CWindow::moveToWorkspace(int workspaceID) {
|
||||
if (m_iWorkspaceID == workspaceID)
|
||||
return;
|
||||
|
||||
static auto* const PCLOSEONLASTSPECIAL = &g_pConfigManager->getConfigValuePtr("misc:close_special_on_empty")->intValue;
|
||||
|
||||
const int OLDWORKSPACE = m_iWorkspaceID;
|
||||
|
||||
m_iWorkspaceID = workspaceID;
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
|
||||
@@ -352,6 +364,15 @@ void CWindow::moveToWorkspace(int workspaceID) {
|
||||
|
||||
// update xwayland coords
|
||||
g_pXWaylandManager->setWindowSize(this, m_vRealSize.vec());
|
||||
|
||||
if (g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE) && g_pCompositor->getWindowsOnWorkspace(OLDWORKSPACE) == 0 && *PCLOSEONLASTSPECIAL) {
|
||||
const auto PWS = g_pCompositor->getWorkspaceByID(OLDWORKSPACE);
|
||||
|
||||
if (PWS) {
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWS->m_iMonitorID); PMONITOR)
|
||||
PMONITOR->setSpecialWorkspace(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CWindow* CWindow::X11TransientFor() {
|
||||
@@ -424,6 +445,7 @@ void CWindow::onUnmap() {
|
||||
void CWindow::onMap() {
|
||||
|
||||
m_pWLSurface.assign(g_pXWaylandManager->getWindowSurface(this));
|
||||
m_pWLSurface.m_pOwner = this;
|
||||
|
||||
// JIC, reset the callbacks. If any are set, we'll make sure they are cleared so we don't accidentally unset them. (In case a window got remapped)
|
||||
m_vRealPosition.resetAllCallbacks();
|
||||
@@ -453,6 +475,8 @@ void CWindow::onMap() {
|
||||
|
||||
hyprListener_unmapWindow.initCallback(m_bIsX11 ? &m_uSurface.xwayland->surface->events.unmap : &m_uSurface.xdg->surface->events.unmap, &Events::listener_unmapWindow, this,
|
||||
"CWindow");
|
||||
|
||||
m_vReportedSize = m_vPendingReportedSize;
|
||||
}
|
||||
|
||||
void CWindow::onBorderAngleAnimEnd(void* ptr) {
|
||||
@@ -499,6 +523,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||
m_sAdditionalConfigData.forceOpaque = true;
|
||||
} else if (r.szRule == "immediate") {
|
||||
m_sAdditionalConfigData.forceTearing = true;
|
||||
} else if (r.szRule == "nearestneighbor") {
|
||||
m_sAdditionalConfigData.nearestNeighbor = true;
|
||||
} else if (r.szRule.starts_with("rounding")) {
|
||||
try {
|
||||
m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||
@@ -588,6 +614,7 @@ void CWindow::updateDynamicRules() {
|
||||
m_sAdditionalConfigData.keepAspectRatio = false;
|
||||
m_sAdditionalConfigData.xray = -1;
|
||||
m_sAdditionalConfigData.forceTearing = false;
|
||||
m_sAdditionalConfigData.nearestNeighbor = false;
|
||||
|
||||
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(this);
|
||||
for (auto& r : WINDOWRULES) {
|
||||
@@ -630,9 +657,9 @@ bool CWindow::isInCurvedCorner(double x, double y) {
|
||||
void findExtensionForVector2D(wlr_surface* surface, int x, int y, void* data) {
|
||||
const auto DATA = (SExtensionFindingData*)data;
|
||||
|
||||
wlr_box box = {DATA->origin.x + x, DATA->origin.y + y, surface->current.width, surface->current.height};
|
||||
CBox box = {DATA->origin.x + x, DATA->origin.y + y, surface->current.width, surface->current.height};
|
||||
|
||||
if (wlr_box_contains_point(&box, DATA->vec.x, DATA->vec.y))
|
||||
if (box.containsPoint(DATA->vec))
|
||||
*DATA->found = surface;
|
||||
}
|
||||
|
||||
@@ -743,6 +770,15 @@ int CWindow::getGroupSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
bool CWindow::canBeGroupedInto(CWindow* pWindow) {
|
||||
return !g_pKeybindManager->m_bGroupsLocked // global group lock disengaged
|
||||
&& ((m_eGroupRules & GROUP_INVADE && m_bFirstMap) // window ignore local group locks, or
|
||||
|| (!pWindow->getGroupHead()->m_sGroupData.locked // target unlocked
|
||||
&& !(m_sGroupData.pNextWindow && getGroupHead()->m_sGroupData.locked))) // source unlocked or isn't group
|
||||
&& !m_sGroupData.deny // source is not denied entry
|
||||
&& !(m_eGroupRules & GROUP_BARRED && m_bFirstMap); // group rule doesn't prevent adding window
|
||||
}
|
||||
|
||||
CWindow* CWindow::getGroupWindowByIndex(int index) {
|
||||
const int SIZE = getGroupSize();
|
||||
index = ((index % SIZE) + SIZE) % SIZE;
|
||||
@@ -882,6 +918,9 @@ bool CWindow::opaque() {
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
|
||||
|
||||
if (m_pWLSurface.small() && !m_pWLSurface.m_bFillIgnoreSmall)
|
||||
return false;
|
||||
|
||||
if (PWORKSPACE->m_fAlpha.fl() != 1.f)
|
||||
return false;
|
||||
|
||||
|
@@ -32,6 +32,8 @@ enum eGroupRules
|
||||
GROUP_OVERRIDE = 1 << 6, // Override other rules
|
||||
};
|
||||
|
||||
class IWindowTransformer;
|
||||
|
||||
template <typename T>
|
||||
class CWindowOverridableVar {
|
||||
public:
|
||||
@@ -141,6 +143,7 @@ struct SWindowAdditionalConfigData {
|
||||
CWindowOverridableVar<int> xray = -1; // -1 means unset, takes precedence over the renderdata one
|
||||
CWindowOverridableVar<int> borderSize = -1; // -1 means unset, takes precedence over the renderdata one
|
||||
CWindowOverridableVar<bool> forceTearing = false;
|
||||
CWindowOverridableVar<bool> nearestNeighbor = false;
|
||||
};
|
||||
|
||||
struct SWindowRule {
|
||||
@@ -203,6 +206,7 @@ class CWindow {
|
||||
// for not spamming the protocols
|
||||
Vector2D m_vReportedPosition;
|
||||
Vector2D m_vReportedSize;
|
||||
Vector2D m_vPendingReportedSize;
|
||||
|
||||
// for restoring floating statuses
|
||||
Vector2D m_vLastFloatingSize;
|
||||
@@ -289,6 +293,9 @@ class CWindow {
|
||||
SWindowSpecialRenderData m_sSpecialRenderData;
|
||||
SWindowAdditionalConfigData m_sAdditionalConfigData;
|
||||
|
||||
// Transformers
|
||||
std::vector<std::unique_ptr<IWindowTransformer>> m_vTransformers;
|
||||
|
||||
// for alpha
|
||||
CAnimatedVariable m_fActiveInactiveAlpha;
|
||||
|
||||
@@ -329,10 +336,11 @@ class CWindow {
|
||||
}
|
||||
|
||||
// methods
|
||||
wlr_box getFullWindowBoundingBox();
|
||||
CBox getFullWindowBoundingBox();
|
||||
SWindowDecorationExtents getFullWindowExtents();
|
||||
wlr_box getWindowInputBox();
|
||||
wlr_box getWindowIdealBoundingBoxIgnoreReserved();
|
||||
CBox getWindowInputBox();
|
||||
CBox getWindowMainSurfaceBox();
|
||||
CBox getWindowIdealBoundingBoxIgnoreReserved();
|
||||
void updateWindowDecos();
|
||||
pid_t getPID();
|
||||
IHyprWindowDecoration* getDecorationByType(eDecorationType);
|
||||
@@ -371,6 +379,7 @@ class CWindow {
|
||||
CWindow* getGroupPrevious();
|
||||
CWindow* getGroupWindowByIndex(int);
|
||||
int getGroupSize();
|
||||
bool canBeGroupedInto(CWindow* pWindow);
|
||||
void setGroupCurrent(CWindow* pWindow);
|
||||
void insertWindowToGroup(CWindow* pWindow);
|
||||
void updateGroupOutputs();
|
||||
@@ -420,4 +429,4 @@ struct std::formatter<CWindow*, CharT> : std::formatter<CharT> {
|
||||
std::format_to(out, ", class: {}", g_pXWaylandManager->getAppIDClass(w));
|
||||
return std::format_to(out, "]");
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@@ -2,6 +2,7 @@
|
||||
#include "../managers/KeybindManager.hpp"
|
||||
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
@@ -128,6 +129,7 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["group:insert_after_current"].intValue = 1;
|
||||
configValues["group:focus_removed_window"].intValue = 1;
|
||||
|
||||
configValues["group:groupbar:font_family"].strValue = "Sans";
|
||||
configValues["group:groupbar:font_size"].intValue = 8;
|
||||
configValues["group:groupbar:gradients"].intValue = 1;
|
||||
configValues["group:groupbar:render_titles"].intValue = 1;
|
||||
@@ -151,34 +153,36 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["debug:suppress_errors"].intValue = 0;
|
||||
configValues["debug:watchdog_timeout"].intValue = 5;
|
||||
|
||||
configValues["decoration:rounding"].intValue = 0;
|
||||
configValues["decoration:blur:enabled"].intValue = 1;
|
||||
configValues["decoration:blur:size"].intValue = 8;
|
||||
configValues["decoration:blur:passes"].intValue = 1;
|
||||
configValues["decoration:blur:ignore_opacity"].intValue = 0;
|
||||
configValues["decoration:blur:new_optimizations"].intValue = 1;
|
||||
configValues["decoration:blur:xray"].intValue = 0;
|
||||
configValues["decoration:blur:noise"].floatValue = 0.0117;
|
||||
configValues["decoration:blur:contrast"].floatValue = 0.8916;
|
||||
configValues["decoration:blur:brightness"].floatValue = 0.8172;
|
||||
configValues["decoration:blur:special"].intValue = 0;
|
||||
configValues["decoration:active_opacity"].floatValue = 1;
|
||||
configValues["decoration:inactive_opacity"].floatValue = 1;
|
||||
configValues["decoration:fullscreen_opacity"].floatValue = 1;
|
||||
configValues["decoration:no_blur_on_oversized"].intValue = 0;
|
||||
configValues["decoration:drop_shadow"].intValue = 1;
|
||||
configValues["decoration:shadow_range"].intValue = 4;
|
||||
configValues["decoration:shadow_render_power"].intValue = 3;
|
||||
configValues["decoration:shadow_ignore_window"].intValue = 1;
|
||||
configValues["decoration:shadow_offset"].vecValue = Vector2D();
|
||||
configValues["decoration:shadow_scale"].floatValue = 1.f;
|
||||
configValues["decoration:col.shadow"].intValue = 0xee1a1a1a;
|
||||
configValues["decoration:col.shadow_inactive"].intValue = INT_MAX;
|
||||
configValues["decoration:dim_inactive"].intValue = 0;
|
||||
configValues["decoration:dim_strength"].floatValue = 0.5f;
|
||||
configValues["decoration:dim_special"].floatValue = 0.2f;
|
||||
configValues["decoration:dim_around"].floatValue = 0.4f;
|
||||
configValues["decoration:screen_shader"].strValue = STRVAL_EMPTY;
|
||||
configValues["decoration:rounding"].intValue = 0;
|
||||
configValues["decoration:blur:enabled"].intValue = 1;
|
||||
configValues["decoration:blur:size"].intValue = 8;
|
||||
configValues["decoration:blur:passes"].intValue = 1;
|
||||
configValues["decoration:blur:ignore_opacity"].intValue = 0;
|
||||
configValues["decoration:blur:new_optimizations"].intValue = 1;
|
||||
configValues["decoration:blur:xray"].intValue = 0;
|
||||
configValues["decoration:blur:contrast"].floatValue = 0.8916;
|
||||
configValues["decoration:blur:brightness"].floatValue = 1.0;
|
||||
configValues["decoration:blur:vibrancy"].floatValue = 0.1696;
|
||||
configValues["decoration:blur:vibrancy_darkness"].floatValue = 0.0;
|
||||
configValues["decoration:blur:noise"].floatValue = 0.0117;
|
||||
configValues["decoration:blur:special"].intValue = 0;
|
||||
configValues["decoration:active_opacity"].floatValue = 1;
|
||||
configValues["decoration:inactive_opacity"].floatValue = 1;
|
||||
configValues["decoration:fullscreen_opacity"].floatValue = 1;
|
||||
configValues["decoration:no_blur_on_oversized"].intValue = 0;
|
||||
configValues["decoration:drop_shadow"].intValue = 1;
|
||||
configValues["decoration:shadow_range"].intValue = 4;
|
||||
configValues["decoration:shadow_render_power"].intValue = 3;
|
||||
configValues["decoration:shadow_ignore_window"].intValue = 1;
|
||||
configValues["decoration:shadow_offset"].vecValue = Vector2D();
|
||||
configValues["decoration:shadow_scale"].floatValue = 1.f;
|
||||
configValues["decoration:col.shadow"].intValue = 0xee1a1a1a;
|
||||
configValues["decoration:col.shadow_inactive"].intValue = INT_MAX;
|
||||
configValues["decoration:dim_inactive"].intValue = 0;
|
||||
configValues["decoration:dim_strength"].floatValue = 0.5f;
|
||||
configValues["decoration:dim_special"].floatValue = 0.2f;
|
||||
configValues["decoration:dim_around"].floatValue = 0.4f;
|
||||
configValues["decoration:screen_shader"].strValue = STRVAL_EMPTY;
|
||||
|
||||
configValues["dwindle:pseudotile"].intValue = 0;
|
||||
configValues["dwindle:force_split"].intValue = 0;
|
||||
@@ -242,13 +246,14 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["input:tablet:region_position"].vecValue = Vector2D();
|
||||
configValues["input:tablet:region_size"].vecValue = Vector2D();
|
||||
|
||||
configValues["binds:pass_mouse_when_bound"].intValue = 0;
|
||||
configValues["binds:scroll_event_delay"].intValue = 300;
|
||||
configValues["binds:workspace_back_and_forth"].intValue = 0;
|
||||
configValues["binds:allow_workspace_cycles"].intValue = 0;
|
||||
configValues["binds:workspace_center_on"].intValue = 1;
|
||||
configValues["binds:focus_preferred_method"].intValue = 0;
|
||||
configValues["binds:ignore_group_lock"].intValue = 0;
|
||||
configValues["binds:pass_mouse_when_bound"].intValue = 0;
|
||||
configValues["binds:scroll_event_delay"].intValue = 300;
|
||||
configValues["binds:workspace_back_and_forth"].intValue = 0;
|
||||
configValues["binds:allow_workspace_cycles"].intValue = 0;
|
||||
configValues["binds:workspace_center_on"].intValue = 1;
|
||||
configValues["binds:focus_preferred_method"].intValue = 0;
|
||||
configValues["binds:ignore_group_lock"].intValue = 0;
|
||||
configValues["binds:movefocus_cycles_fullscreen"].intValue = 1;
|
||||
|
||||
configValues["gestures:workspace_swipe"].intValue = 0;
|
||||
configValues["gestures:workspace_swipe_fingers"].intValue = 3;
|
||||
@@ -832,6 +837,7 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
|
||||
bool mouse = false;
|
||||
bool nonConsuming = false;
|
||||
bool transparent = false;
|
||||
bool ignoreMods = false;
|
||||
const auto BINDARGS = command.substr(4);
|
||||
|
||||
for (auto& arg : BINDARGS) {
|
||||
@@ -847,6 +853,8 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
|
||||
nonConsuming = true;
|
||||
} else if (arg == 't') {
|
||||
transparent = true;
|
||||
} else if (arg == 'i') {
|
||||
ignoreMods = true;
|
||||
} else {
|
||||
parseError = "bind: invalid flag";
|
||||
return;
|
||||
@@ -904,12 +912,13 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
|
||||
|
||||
if (KEY != "") {
|
||||
if (isNumber(KEY) && std::stoi(KEY) > 9)
|
||||
g_pKeybindManager->addKeybind(SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent});
|
||||
g_pKeybindManager->addKeybind(
|
||||
SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent, ignoreMods});
|
||||
else if (KEY.starts_with("code:") && isNumber(KEY.substr(5)))
|
||||
g_pKeybindManager->addKeybind(
|
||||
SKeybind{"", std::stoi(KEY.substr(5)), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent});
|
||||
SKeybind{"", std::stoi(KEY.substr(5)), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent, ignoreMods});
|
||||
else
|
||||
g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent});
|
||||
g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent, ignoreMods});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -930,7 +939,7 @@ bool windowRuleValid(const std::string& RULE) {
|
||||
RULE == "nomaximizerequest" || RULE == "fakefullscreen" || RULE == "nomaxsize" || RULE == "pin" || RULE == "noanim" || RULE == "dimaround" || RULE == "windowdance" ||
|
||||
RULE == "maximize" || RULE == "keepaspectratio" || RULE.starts_with("animation") || RULE.starts_with("rounding") || RULE.starts_with("workspace") ||
|
||||
RULE.starts_with("bordercolor") || RULE == "forcergbx" || RULE == "noinitialfocus" || RULE == "stayfocused" || RULE.starts_with("bordersize") || RULE.starts_with("xray") ||
|
||||
RULE.starts_with("center") || RULE.starts_with("group") || RULE == "immediate";
|
||||
RULE.starts_with("center") || RULE.starts_with("group") || RULE == "immediate" || RULE == "nearestneighbor";
|
||||
}
|
||||
|
||||
bool layerRuleValid(const std::string& RULE) {
|
||||
@@ -1172,7 +1181,10 @@ void CConfigManager::handleWorkspaceRules(const std::string& command, const std:
|
||||
rules = value.substr(WORKSPACE_DELIM + 1);
|
||||
}
|
||||
|
||||
auto assignRule = [&](std::string rule) {
|
||||
const static std::string ruleOnCreatedEmtpy = "on-created-empty:";
|
||||
const static int ruleOnCreatedEmtpyLen = ruleOnCreatedEmtpy.length();
|
||||
|
||||
auto assignRule = [&](std::string rule) {
|
||||
size_t delim = std::string::npos;
|
||||
if ((delim = rule.find("gapsin:")) != std::string::npos)
|
||||
wsRule.gapsIn = std::stoi(rule.substr(delim + 7));
|
||||
@@ -1194,6 +1206,8 @@ void CConfigManager::handleWorkspaceRules(const std::string& command, const std:
|
||||
wsRule.isDefault = configStringToInt(rule.substr(delim + 8));
|
||||
else if ((delim = rule.find("persistent:")) != std::string::npos)
|
||||
wsRule.isPersistent = configStringToInt(rule.substr(delim + 11));
|
||||
else if ((delim = rule.find(ruleOnCreatedEmtpy)) != std::string::npos)
|
||||
wsRule.onCreatedEmptyRunCmd = cleanCmdForWorkspace(name, rule.substr(delim + ruleOnCreatedEmtpyLen));
|
||||
};
|
||||
|
||||
size_t pos = 0;
|
||||
@@ -1374,13 +1388,20 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
|
||||
handleBlurLS(COMMAND, VALUE);
|
||||
else if (COMMAND == "wsbind")
|
||||
handleBindWS(COMMAND, VALUE);
|
||||
else if (COMMAND == "plugin")
|
||||
handlePlugin(COMMAND, VALUE);
|
||||
else if (COMMAND.starts_with("env"))
|
||||
handleEnv(COMMAND, VALUE);
|
||||
else if (COMMAND.starts_with("plugin"))
|
||||
handlePlugin(COMMAND, VALUE);
|
||||
else {
|
||||
configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE);
|
||||
needsLayoutRecalc = 2;
|
||||
// try config
|
||||
const auto IT = std::find_if(pluginKeywords.begin(), pluginKeywords.end(), [&](const auto& other) { return other.name == COMMAND; });
|
||||
|
||||
if (IT != pluginKeywords.end()) {
|
||||
IT->fn(COMMAND, VALUE);
|
||||
} else {
|
||||
configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE);
|
||||
needsLayoutRecalc = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (dynamic) {
|
||||
@@ -1514,6 +1535,8 @@ void CConfigManager::parseLine(std::string& line) {
|
||||
}
|
||||
|
||||
void CConfigManager::loadConfigLoadVars() {
|
||||
EMIT_HOOK_EVENT("preConfigReload", nullptr);
|
||||
|
||||
Debug::log(LOG, "Reloading the config!");
|
||||
parseError = ""; // reset the error
|
||||
currentCategory = ""; // reset the category
|
||||
@@ -1846,7 +1869,10 @@ SMonitorRule CConfigManager::getMonitorRuleFor(const std::string& name, const st
|
||||
SWorkspaceRule CConfigManager::getWorkspaceRuleFor(CWorkspace* pWorkspace) {
|
||||
const auto WORKSPACEIDSTR = std::to_string(pWorkspace->m_iID);
|
||||
const auto IT = std::find_if(m_dWorkspaceRules.begin(), m_dWorkspaceRules.end(), [&](const auto& other) {
|
||||
return other.workspaceName == pWorkspace->m_szName || (pWorkspace->m_iID > 0 && WORKSPACEIDSTR == other.workspaceName);
|
||||
return other.workspaceName == pWorkspace->m_szName /* name matches */
|
||||
|| (pWorkspace->m_bIsSpecialWorkspace && other.workspaceName.starts_with("special:") &&
|
||||
other.workspaceName.substr(8) == pWorkspace->m_szName) /* special and special:name */
|
||||
|| (pWorkspace->m_iID > 0 && WORKSPACEIDSTR == other.workspaceName); /* id matches and workspace is numerical */
|
||||
});
|
||||
if (IT == m_dWorkspaceRules.end())
|
||||
return SWorkspaceRule{};
|
||||
@@ -2044,7 +2070,7 @@ void CConfigManager::performMonitorReload() {
|
||||
bool overAgain = false;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
if (!m->output)
|
||||
if (!m->output || m->isUnsafeFallback)
|
||||
continue;
|
||||
|
||||
auto rule = getMonitorRuleFor(m->szName, m->output->description ? m->output->description : "");
|
||||
@@ -2125,15 +2151,13 @@ bool CConfigManager::shouldBlurLS(const std::string& ns) {
|
||||
|
||||
void CConfigManager::ensureMonitorStatus() {
|
||||
for (auto& rm : g_pCompositor->m_vRealMonitors) {
|
||||
if (!rm->output)
|
||||
if (!rm->output || rm->isUnsafeFallback)
|
||||
continue;
|
||||
|
||||
auto rule = getMonitorRuleFor(rm->szName, rm->output->description ? rm->output->description : "");
|
||||
|
||||
if (rule.disabled == rm->m_bEnabled) {
|
||||
rm->m_pThisWrap = &rm;
|
||||
if (rule.disabled == rm->m_bEnabled)
|
||||
g_pHyprRenderer->applyMonitorRule(rm.get(), &rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2299,8 +2323,13 @@ void CConfigManager::addPluginConfigVar(HANDLE handle, const std::string& name,
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigManager::addPluginKeyword(HANDLE handle, const std::string& name, std::function<void(const std::string&, const std::string&)> fn) {
|
||||
pluginKeywords.emplace_back(SPluginKeyword{handle, name, fn});
|
||||
}
|
||||
|
||||
void CConfigManager::removePluginConfig(HANDLE handle) {
|
||||
std::erase_if(pluginConfigs, [&](const auto& other) { return other.first == handle; });
|
||||
std::erase_if(pluginKeywords, [&](const auto& other) { return other.handle == handle; });
|
||||
}
|
||||
|
||||
std::string CConfigManager::getDefaultWorkspaceFor(const std::string& name) {
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include <algorithm>
|
||||
#include <regex>
|
||||
#include <optional>
|
||||
#include <functional>
|
||||
#include <xf86drmMode.h>
|
||||
#include "../Window.hpp"
|
||||
#include "../helpers/WLClasses.hpp"
|
||||
@@ -36,19 +37,20 @@ struct SConfigValue {
|
||||
};
|
||||
|
||||
struct SWorkspaceRule {
|
||||
std::string monitor = "";
|
||||
std::string workspaceString = "";
|
||||
std::string workspaceName = "";
|
||||
int workspaceId = -1;
|
||||
bool isDefault = false;
|
||||
bool isPersistent = false;
|
||||
std::optional<int64_t> gapsIn;
|
||||
std::optional<int64_t> gapsOut;
|
||||
std::optional<int64_t> borderSize;
|
||||
std::optional<int> border;
|
||||
std::optional<int> rounding;
|
||||
std::optional<int> decorate;
|
||||
std::optional<int> shadow;
|
||||
std::string monitor = "";
|
||||
std::string workspaceString = "";
|
||||
std::string workspaceName = "";
|
||||
int workspaceId = -1;
|
||||
bool isDefault = false;
|
||||
bool isPersistent = false;
|
||||
std::optional<int64_t> gapsIn;
|
||||
std::optional<int64_t> gapsOut;
|
||||
std::optional<int64_t> borderSize;
|
||||
std::optional<int> border;
|
||||
std::optional<int> rounding;
|
||||
std::optional<int> decorate;
|
||||
std::optional<int> shadow;
|
||||
std::optional<std::string> onCreatedEmptyRunCmd;
|
||||
};
|
||||
|
||||
struct SMonitorAdditionalReservedArea {
|
||||
@@ -70,6 +72,12 @@ struct SAnimationPropertyConfig {
|
||||
SAnimationPropertyConfig* pParentAnimation = nullptr;
|
||||
};
|
||||
|
||||
struct SPluginKeyword {
|
||||
HANDLE handle = 0;
|
||||
std::string name = "";
|
||||
std::function<void(const std::string&, const std::string&)> fn;
|
||||
};
|
||||
|
||||
struct SExecRequestedRule {
|
||||
std::string szRule = "";
|
||||
uint64_t iPid = 0;
|
||||
@@ -119,7 +127,8 @@ class CConfigManager {
|
||||
std::unordered_map<std::string, SAnimationPropertyConfig> getAnimationConfig();
|
||||
|
||||
void addPluginConfigVar(HANDLE handle, const std::string& name, const SConfigValue& value);
|
||||
void removePluginConfig(HANDLE handle);
|
||||
void addPluginKeyword(HANDLE handle, const std::string& name, std::function<void(const std::string& cmd, const std::string& val)> fun);
|
||||
void removePluginConfig(HANDLE handle);
|
||||
|
||||
// no-op when done.
|
||||
void dispatchExecOnce();
|
||||
@@ -162,6 +171,7 @@ class CConfigManager {
|
||||
|
||||
std::vector<std::string> m_vDeclaredPlugins;
|
||||
std::unordered_map<HANDLE, std::unique_ptr<std::unordered_map<std::string, SConfigValue>>> pluginConfigs; // stores plugin configs
|
||||
std::vector<SPluginKeyword> pluginKeywords;
|
||||
|
||||
bool isFirstLaunch = true; // For exec-once
|
||||
|
||||
|
@@ -172,6 +172,10 @@ bind = $mainMod SHIFT, 8, movetoworkspace, 8
|
||||
bind = $mainMod SHIFT, 9, movetoworkspace, 9
|
||||
bind = $mainMod SHIFT, 0, movetoworkspace, 10
|
||||
|
||||
# Example special workspace (scratchpad)
|
||||
bind = $mainMod, S, togglespecialworkspace, magic
|
||||
bind = $mainMod SHIFT, S, movetoworkspace, special:magic
|
||||
|
||||
# Scroll through existing workspaces with mainMod + scroll
|
||||
bind = $mainMod, mouse_down, workspace, e+1
|
||||
bind = $mainMod, mouse_up, workspace, e-1
|
||||
|
@@ -132,6 +132,14 @@ static std::string getGroupedData(CWindow* w, HyprCtl::eHyprCtlOutputFormat form
|
||||
}
|
||||
|
||||
static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat format) {
|
||||
auto getFocusHistoryID = [](CWindow* wnd) -> int {
|
||||
for (size_t i = 0; i < g_pCompositor->m_vWindowFocusHistory.size(); ++i) {
|
||||
if (g_pCompositor->m_vWindowFocusHistory[i] == wnd)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
return std::format(
|
||||
R"#({{
|
||||
@@ -157,7 +165,8 @@ static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat forma
|
||||
"fullscreenMode": {},
|
||||
"fakeFullscreen": {},
|
||||
"grouped": [{}],
|
||||
"swallowing": "0x{:x}"
|
||||
"swallowing": "0x{:x}",
|
||||
"focusHistoryID": {}
|
||||
}},)#",
|
||||
(uintptr_t)w, (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition.goalv().x, (int)w->m_vRealPosition.goalv().y,
|
||||
(int)w->m_vRealSize.goalv().x, (int)w->m_vRealSize.goalv().y, w->m_iWorkspaceID,
|
||||
@@ -168,13 +177,13 @@ static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat forma
|
||||
escapeJSONStrings(g_pXWaylandManager->getTitle(w)), escapeJSONStrings(w->m_szInitialClass), escapeJSONStrings(w->m_szInitialTitle), w->getPID(),
|
||||
((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"), (w->m_bIsFullscreen ? "true" : "false"),
|
||||
(w->m_bIsFullscreen ? (g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? (int)g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_efFullscreenMode : 0) : 0),
|
||||
w->m_bFakeFullscreenState ? "true" : "false", getGroupedData(w, format), (uintptr_t)w->m_pSwallowed);
|
||||
w->m_bFakeFullscreenState ? "true" : "false", getGroupedData(w, format), (uintptr_t)w->m_pSwallowed, getFocusHistoryID(w));
|
||||
} else {
|
||||
return std::format(
|
||||
"Window {:x} -> {}:\n\tmapped: {}\n\thidden: {}\n\tat: {},{}\n\tsize: {},{}\n\tworkspace: {} ({})\n\tfloating: {}\n\tmonitor: {}\n\tclass: {}\n\ttitle: "
|
||||
"{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: "
|
||||
"{}\n\txwayland: {}\n\tpinned: "
|
||||
"{}\n\tfullscreen: {}\n\tfullscreenmode: {}\n\tfakefullscreen: {}\n\tgrouped: {}\n\tswallowing: {:x}\n\n",
|
||||
"{}\n\tfullscreen: {}\n\tfullscreenmode: {}\n\tfakefullscreen: {}\n\tgrouped: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\n",
|
||||
(uintptr_t)w, w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition.goalv().x, (int)w->m_vRealPosition.goalv().y,
|
||||
(int)w->m_vRealSize.goalv().x, (int)w->m_vRealSize.goalv().y, w->m_iWorkspaceID,
|
||||
(w->m_iWorkspaceID == -1 ? "" :
|
||||
@@ -183,7 +192,7 @@ static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat forma
|
||||
(int)w->m_bIsFloating, (int64_t)w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w), g_pXWaylandManager->getTitle(w), w->m_szInitialClass, w->m_szInitialTitle,
|
||||
w->getPID(), (int)w->m_bIsX11, (int)w->m_bPinned, (int)w->m_bIsFullscreen,
|
||||
(w->m_bIsFullscreen ? (g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_efFullscreenMode : 0) : 0),
|
||||
(int)w->m_bFakeFullscreenState, getGroupedData(w, format), (uintptr_t)w->m_pSwallowed);
|
||||
(int)w->m_bFakeFullscreenState, getGroupedData(w, format), (uintptr_t)w->m_pSwallowed, getFocusHistoryID(w));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,20 +224,60 @@ static std::string getWorkspaceData(CWorkspace* w, HyprCtl::eHyprCtlOutputFormat
|
||||
"id": {},
|
||||
"name": "{}",
|
||||
"monitor": "{}",
|
||||
"monitorID": {},
|
||||
"windows": {},
|
||||
"hasfullscreen": {},
|
||||
"lastwindow": "0x{:x}",
|
||||
"lastwindowtitle": "{}"
|
||||
}})#",
|
||||
w->m_iID, escapeJSONStrings(w->m_szName), escapeJSONStrings(PMONITOR ? PMONITOR->szName : "?"), g_pCompositor->getWindowsOnWorkspace(w->m_iID),
|
||||
w->m_iID, escapeJSONStrings(w->m_szName), escapeJSONStrings(PMONITOR ? PMONITOR->szName : "?"),
|
||||
escapeJSONStrings(PMONITOR ? std::to_string(PMONITOR->ID) : "null"), g_pCompositor->getWindowsOnWorkspace(w->m_iID),
|
||||
((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false"), (uintptr_t)PLASTW, PLASTW ? escapeJSONStrings(PLASTW->m_szTitle) : "");
|
||||
} else {
|
||||
return std::format("workspace ID {} ({}) on monitor {}:\n\twindows: {}\n\thasfullscreen: {}\n\tlastwindow: 0x{:x}\n\tlastwindowtitle: {}\n\n", w->m_iID, w->m_szName,
|
||||
PMONITOR ? PMONITOR->szName : "?", g_pCompositor->getWindowsOnWorkspace(w->m_iID), (int)w->m_bHasFullscreenWindow, (uintptr_t)PLASTW,
|
||||
PLASTW ? PLASTW->m_szTitle : "");
|
||||
return std::format("workspace ID {} ({}) on monitor {}:\n\tmonitorID: {}\n\twindows: {}\n\thasfullscreen: {}\n\tlastwindow: 0x{:x}\n\tlastwindowtitle: {}\n\n", w->m_iID,
|
||||
w->m_szName, PMONITOR ? PMONITOR->szName : "?", PMONITOR ? std::to_string(PMONITOR->ID) : "null", g_pCompositor->getWindowsOnWorkspace(w->m_iID),
|
||||
(int)w->m_bHasFullscreenWindow, (uintptr_t)PLASTW, PLASTW ? PLASTW->m_szTitle : "");
|
||||
}
|
||||
}
|
||||
|
||||
static std::string getWorkspaceRuleData(const SWorkspaceRule& r, HyprCtl::eHyprCtlOutputFormat format) {
|
||||
const auto boolToString = [](const bool b) -> std::string { return b ? "true" : "false"; };
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
const std::string monitor = r.monitor.empty() ? "" : std::format(",\n \"monitor\": \"{}\"", escapeJSONStrings(r.monitor));
|
||||
const std::string default_ = (bool)(r.isDefault) ? std::format(",\n \"default\": {}", boolToString(r.isDefault)) : "";
|
||||
const std::string persistent = (bool)(r.isPersistent) ? std::format(",\n \"persistent\": {}", boolToString(r.isPersistent)) : "";
|
||||
const std::string gapsIn = (bool)(r.gapsIn) ? std::format(",\n \"gapsIn\": {}", r.gapsIn.value()) : "";
|
||||
const std::string gapsOut = (bool)(r.gapsOut) ? std::format(",\n \"gapsOut\": {}", r.gapsOut.value()) : "";
|
||||
const std::string borderSize = (bool)(r.borderSize) ? std::format(",\n \"borderSize\": {}", r.borderSize.value()) : "";
|
||||
const std::string border = (bool)(r.border) ? std::format(",\n \"border\": {}", boolToString(r.border.value())) : "";
|
||||
const std::string rounding = (bool)(r.rounding) ? std::format(",\n \"rounding\": {}", boolToString(r.rounding.value())) : "";
|
||||
const std::string decorate = (bool)(r.decorate) ? std::format(",\n \"decorate\": {}", boolToString(r.decorate.value())) : "";
|
||||
const std::string shadow = (bool)(r.shadow) ? std::format(",\n \"shadow\": {}", boolToString(r.shadow.value())) : "";
|
||||
|
||||
std::string result = std::format(R"#({{
|
||||
"workspaceString": "{}"{}{}{}{}{}{}{}{}
|
||||
}})#",
|
||||
escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, borderSize, border, rounding, decorate, shadow);
|
||||
|
||||
return result;
|
||||
} else {
|
||||
const std::string monitor = std::format("\tmonitor: {}\n", r.monitor.empty() ? "<unset>" : escapeJSONStrings(r.monitor));
|
||||
const std::string default_ = std::format("\tdefault: {}\n", (bool)(r.isDefault) ? boolToString(r.isDefault) : "<unset>");
|
||||
const std::string persistent = std::format("\tpersistent: {}\n", (bool)(r.isPersistent) ? boolToString(r.isPersistent) : "<unset>");
|
||||
const std::string gapsIn = std::format("\tgapsIn: {}\n", (bool)(r.gapsIn) ? std::to_string(r.gapsIn.value()) : "<unset>");
|
||||
const std::string gapsOut = std::format("\tgapsOut: {}\n", (bool)(r.gapsOut) ? std::to_string(r.gapsOut.value()) : "<unset>");
|
||||
const std::string borderSize = std::format("\tborderSize: {}\n", (bool)(r.borderSize) ? std::to_string(r.borderSize.value()) : "<unset>");
|
||||
const std::string border = std::format("\tborder: {}\n", (bool)(r.border) ? boolToString(r.border.value()) : "<unset>");
|
||||
const std::string rounding = std::format("\trounding: {}\n", (bool)(r.rounding) ? boolToString(r.rounding.value()) : "<unset>");
|
||||
const std::string decorate = std::format("\tdecorate: {}\n", (bool)(r.decorate) ? boolToString(r.decorate.value()) : "<unset>");
|
||||
const std::string shadow = std::format("\tshadow: {}\n", (bool)(r.shadow) ? boolToString(r.shadow.value()) : "<unset>");
|
||||
|
||||
std::string result = std::format("Workspace rule {}:\n{}{}{}{}{}{}{}{}{}{}\n", escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut,
|
||||
borderSize, border, rounding, decorate, shadow);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
std::string activeWorkspaceRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
if (!g_pCompositor->m_pLastMonitor)
|
||||
return "unsafe state";
|
||||
@@ -263,6 +312,26 @@ std::string workspacesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string workspaceRulesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string result = "";
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
result += "[";
|
||||
for (auto& r : g_pConfigManager->getAllWorkspaceRules()) {
|
||||
result += getWorkspaceRuleData(r, format);
|
||||
result += ",";
|
||||
}
|
||||
|
||||
trimTrailingComma(result);
|
||||
result += "]";
|
||||
} else {
|
||||
for (auto& r : g_pConfigManager->getAllWorkspaceRules()) {
|
||||
result += getWorkspaceRuleData(r, format);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string activeWindowRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
|
||||
@@ -1013,6 +1082,8 @@ std::string dispatchSetProp(std::string request) {
|
||||
PWINDOW->m_sAdditionalConfigData.keepAspectRatio.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "immediate") {
|
||||
PWINDOW->m_sAdditionalConfigData.forceTearing.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "nearestneighbor") {
|
||||
PWINDOW->m_sAdditionalConfigData.nearestNeighbor.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else {
|
||||
return "prop not found";
|
||||
}
|
||||
@@ -1259,6 +1330,8 @@ std::string getReply(std::string request) {
|
||||
return monitorsRequest(format);
|
||||
else if (request == "workspaces")
|
||||
return workspacesRequest(format);
|
||||
else if (request == "workspacerules")
|
||||
return workspaceRulesRequest(format);
|
||||
else if (request == "activeworkspace")
|
||||
return activeWorkspaceRequest(format);
|
||||
else if (request == "clients")
|
||||
|
@@ -233,6 +233,6 @@ void CHyprDebugOverlay::draw() {
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
||||
|
||||
wlr_box pMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||
CBox pMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ class CHyprMonitorDebugOverlay {
|
||||
std::deque<float> m_dLastAnimationTicks;
|
||||
std::chrono::high_resolution_clock::time_point m_tpLastFrame;
|
||||
CMonitor* m_pMonitor = nullptr;
|
||||
wlr_box m_wbLastDrawnBox;
|
||||
CBox m_wbLastDrawnBox;
|
||||
|
||||
friend class CHyprRenderer;
|
||||
};
|
||||
|
@@ -3,7 +3,7 @@
|
||||
#include <pango/pangocairo.h>
|
||||
|
||||
CHyprNotificationOverlay::CHyprNotificationOverlay() {
|
||||
g_pHookSystem->hookDynamic("focusedMon", [&](void* self, std::any param) {
|
||||
g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) {
|
||||
if (m_dNotifications.size() == 0)
|
||||
return;
|
||||
|
||||
@@ -50,7 +50,7 @@ void CHyprNotificationOverlay::addNotification(const std::string& text, const CC
|
||||
}
|
||||
}
|
||||
|
||||
wlr_box CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
|
||||
CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
|
||||
static constexpr auto ANIM_DURATION_MS = 600.0;
|
||||
static constexpr auto ANIM_LAG_MS = 100.0;
|
||||
static constexpr auto NOTIF_LEFTBAR_SIZE = 5.0;
|
||||
@@ -170,7 +170,7 @@ wlr_box CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
|
||||
// cleanup notifs
|
||||
std::erase_if(m_dNotifications, [](const auto& notif) { return notif->started.getMillis() > notif->timeMs; });
|
||||
|
||||
return wlr_box{(int)(pMonitor->vecPosition.x + pMonitor->vecSize.x - maxWidth - 20), (int)pMonitor->vecPosition.y, (int)maxWidth + 20, (int)offsetY + 10};
|
||||
return CBox{(int)(pMonitor->vecPosition.x + pMonitor->vecSize.x - maxWidth - 20), (int)pMonitor->vecPosition.y, (int)maxWidth + 20, (int)offsetY + 10};
|
||||
}
|
||||
|
||||
void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
|
||||
@@ -201,7 +201,7 @@ void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
|
||||
|
||||
cairo_surface_flush(m_pCairoSurface);
|
||||
|
||||
wlr_box damage = drawNotifications(pMonitor);
|
||||
CBox damage = drawNotifications(pMonitor);
|
||||
|
||||
g_pHyprRenderer->damageBox(&damage);
|
||||
g_pHyprRenderer->damageBox(&m_bLastDamage);
|
||||
@@ -224,6 +224,6 @@ void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
||||
|
||||
wlr_box pMonBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
|
||||
CBox pMonBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
|
||||
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
|
||||
}
|
@@ -44,8 +44,8 @@ class CHyprNotificationOverlay {
|
||||
void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE);
|
||||
|
||||
private:
|
||||
wlr_box drawNotifications(CMonitor* pMonitor);
|
||||
wlr_box m_bLastDamage;
|
||||
CBox drawNotifications(CMonitor* pMonitor);
|
||||
CBox m_bLastDamage;
|
||||
|
||||
std::deque<std::unique_ptr<SNotification>> m_dNotifications;
|
||||
|
||||
|
@@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <wlr/util/log.h>
|
||||
#include <format>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <chrono>
|
||||
#include "../includes.hpp"
|
||||
#include "../helpers/MiscFunctions.hpp"
|
||||
|
||||
#define LOGMESSAGESIZE 1024
|
||||
@@ -79,4 +79,4 @@ namespace Debug {
|
||||
}
|
||||
|
||||
void wlrLog(wlr_log_importance level, const char* fmt, va_list args);
|
||||
};
|
||||
};
|
||||
|
@@ -95,8 +95,8 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) {
|
||||
PMONITOR->scheduledRecalc = true;
|
||||
|
||||
// and damage
|
||||
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
|
||||
layersurface->geometry.height};
|
||||
CBox geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
|
||||
layersurface->geometry.height};
|
||||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
||||
|
||||
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
|
||||
|
||||
const bool GRABSFOCUS = layersurface->layerSurface->current.keyboard_interactive &&
|
||||
const bool GRABSFOCUS = layersurface->layerSurface->current.keyboard_interactive != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE &&
|
||||
// don't focus if constrained
|
||||
(!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint);
|
||||
|
||||
@@ -157,8 +157,8 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
||||
|
||||
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
|
||||
|
||||
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
|
||||
layersurface->geometry.height};
|
||||
CBox geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
|
||||
layersurface->geometry.height};
|
||||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
const auto WORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
|
||||
@@ -171,7 +171,8 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"openlayer", std::string(layersurface->layerSurface->_namespace ? layersurface->layerSurface->_namespace : "")});
|
||||
EMIT_HOOK_EVENT("openLayer", layersurface);
|
||||
|
||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(layersurface->layerSurface->surface, PMONITOR->scale);
|
||||
g_pCompositor->setPreferredScaleForSurface(layersurface->layerSurface->surface, PMONITOR->scale);
|
||||
g_pCompositor->setPreferredTransformForSurface(layersurface->layerSurface->surface, PMONITOR->transform);
|
||||
}
|
||||
|
||||
void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
||||
@@ -246,8 +247,8 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
||||
}
|
||||
}
|
||||
|
||||
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
|
||||
layersurface->geometry.height};
|
||||
CBox geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
|
||||
layersurface->geometry.height};
|
||||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
|
||||
geomFixed = {layersurface->geometry.x + (int)PMONITOR->vecPosition.x, layersurface->geometry.y + (int)PMONITOR->vecPosition.y,
|
||||
@@ -269,7 +270,7 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
|
||||
if (layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM)
|
||||
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); // so that blur is recalc'd
|
||||
|
||||
wlr_box geomFixed = {layersurface->geometry.x, layersurface->geometry.y, layersurface->geometry.width, layersurface->geometry.height};
|
||||
CBox geomFixed = {layersurface->geometry.x, layersurface->geometry.y, layersurface->geometry.width, layersurface->geometry.height};
|
||||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
|
||||
// fix if it changed its mon
|
||||
@@ -342,5 +343,6 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
|
||||
|
||||
g_pHyprRenderer->damageSurface(layersurface->layerSurface->surface, layersurface->position.x, layersurface->position.y);
|
||||
|
||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(layersurface->layerSurface->surface, PMONITOR->scale);
|
||||
g_pCompositor->setPreferredScaleForSurface(layersurface->layerSurface->surface, PMONITOR->scale);
|
||||
g_pCompositor->setPreferredTransformForSurface(layersurface->layerSurface->surface, PMONITOR->transform);
|
||||
}
|
||||
|
@@ -28,8 +28,9 @@ void Events::listener_change(wl_listener* listener, void* data) {
|
||||
|
||||
const auto CONFIGHEAD = wlr_output_configuration_head_v1_create(CONFIG, m->output);
|
||||
|
||||
wlr_box BOX;
|
||||
wlr_output_layout_get_box(g_pCompositor->m_sWLROutputLayout, m->output, &BOX);
|
||||
CBox BOX;
|
||||
wlr_output_layout_get_box(g_pCompositor->m_sWLROutputLayout, m->output, BOX.pWlr());
|
||||
BOX.applyFromWlr();
|
||||
|
||||
//m->vecSize.x = BOX.width;
|
||||
// m->vecSize.y = BOX.height;
|
||||
@@ -67,52 +68,31 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_pCompositor->m_bUnsafeState)
|
||||
Debug::log(WARN, "Recovering from an unsafe state. May you be lucky.");
|
||||
|
||||
// add it to real
|
||||
std::shared_ptr<CMonitor>* PNEWMONITORWRAP = nullptr;
|
||||
|
||||
PNEWMONITORWRAP = &g_pCompositor->m_vRealMonitors.emplace_back(std::make_shared<CMonitor>());
|
||||
if (std::string("HEADLESS-1") == OUTPUT->name)
|
||||
g_pCompositor->m_pUnsafeOutput = PNEWMONITORWRAP->get();
|
||||
|
||||
(*PNEWMONITORWRAP)->ID = g_pCompositor->getNextAvailableMonitorID(OUTPUT->name);
|
||||
(*PNEWMONITORWRAP)->output = OUTPUT;
|
||||
const bool FALLBACK = g_pCompositor->m_pUnsafeOutput ? OUTPUT == g_pCompositor->m_pUnsafeOutput->output : false;
|
||||
(*PNEWMONITORWRAP)->ID = FALLBACK ? -1 : g_pCompositor->getNextAvailableMonitorID(OUTPUT->name);
|
||||
const auto PNEWMONITOR = PNEWMONITORWRAP->get();
|
||||
PNEWMONITOR->isUnsafeFallback = FALLBACK;
|
||||
|
||||
const auto PNEWMONITOR = PNEWMONITORWRAP->get();
|
||||
if (!FALLBACK)
|
||||
PNEWMONITOR->onConnect(false);
|
||||
|
||||
PNEWMONITOR->output = OUTPUT;
|
||||
PNEWMONITOR->m_pThisWrap = PNEWMONITORWRAP;
|
||||
if (!PNEWMONITOR->m_bEnabled || FALLBACK)
|
||||
return;
|
||||
|
||||
PNEWMONITOR->onConnect(false);
|
||||
// ready to process if we have a real monitor
|
||||
|
||||
if ((!g_pHyprRenderer->m_pMostHzMonitor || PNEWMONITOR->refreshRate > g_pHyprRenderer->m_pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled)
|
||||
g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR;
|
||||
|
||||
// wlroots will instantly call this handler before we get a return to the wlr_output* in CCompositor::enterUnsafeState
|
||||
const bool PROBABLYFALLBACK = (g_pCompositor->m_bUnsafeState && !g_pCompositor->m_pUnsafeOutput) || OUTPUT == g_pCompositor->m_pUnsafeOutput;
|
||||
|
||||
// ready to process if we have a real monitor
|
||||
if (PNEWMONITOR->m_bEnabled && !PROBABLYFALLBACK) {
|
||||
// leave unsafe state
|
||||
if (g_pCompositor->m_bUnsafeState) {
|
||||
// recover workspaces
|
||||
std::vector<CWorkspace*> wsp;
|
||||
for (auto& ws : g_pCompositor->m_vWorkspaces) {
|
||||
wsp.push_back(ws.get());
|
||||
}
|
||||
for (auto& ws : wsp) {
|
||||
// because this can realloc the vec
|
||||
g_pCompositor->moveWorkspaceToMonitor(ws, PNEWMONITOR);
|
||||
}
|
||||
|
||||
g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR;
|
||||
|
||||
const auto POS = PNEWMONITOR->middle();
|
||||
if (g_pCompositor->m_sSeat.mouse)
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, POS.x, POS.y);
|
||||
}
|
||||
|
||||
g_pCompositor->m_bReadyToProcess = true;
|
||||
}
|
||||
g_pCompositor->m_bReadyToProcess = true;
|
||||
|
||||
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||
g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR);
|
||||
@@ -138,7 +118,9 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) {
|
||||
Debug::log(WARN, "Attempted to render frame on inactive session!");
|
||||
|
||||
if (g_pCompositor->m_bUnsafeState && PMONITOR->output != g_pCompositor->m_pUnsafeOutput) {
|
||||
if (g_pCompositor->m_bUnsafeState && std::ranges::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& m) {
|
||||
return m->output != g_pCompositor->m_pUnsafeOutput->output;
|
||||
})) {
|
||||
// restore from unsafe state
|
||||
g_pCompositor->leaveUnsafeState();
|
||||
}
|
||||
@@ -218,9 +200,6 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
|
||||
pMonitor->output = nullptr;
|
||||
pMonitor->m_bRenderingInitPassed = false;
|
||||
|
||||
if (g_pCompositor->m_pUnsafeOutput == OUTPUT)
|
||||
g_pCompositor->m_pUnsafeOutput = nullptr;
|
||||
|
||||
Debug::log(LOG, "Removing monitor {} from realMonitors", pMonitor->szName);
|
||||
|
||||
std::erase_if(g_pCompositor->m_vRealMonitors, [&](std::shared_ptr<CMonitor>& el) { return el.get() == pMonitor; });
|
||||
@@ -251,7 +230,7 @@ void Events::listener_monitorCommit(void* owner, void* data) {
|
||||
|
||||
const auto E = (wlr_output_event_commit*)data;
|
||||
|
||||
if (E->committed & WLR_OUTPUT_STATE_BUFFER) {
|
||||
if (E->state->committed & WLR_OUTPUT_STATE_BUFFER) {
|
||||
g_pProtocolManager->m_pScreencopyProtocolManager->onOutputCommit(PMONITOR, E);
|
||||
g_pProtocolManager->m_pToplevelExportProtocolManager->onOutputCommit(PMONITOR, E);
|
||||
}
|
||||
|
@@ -64,9 +64,9 @@ void createNewPopup(wlr_xdg_popup* popup, SXDGPopup* pHyprPopup) {
|
||||
|
||||
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
||||
|
||||
wlr_box box = {.x = PMONITOR->vecPosition.x - pHyprPopup->lx, .y = PMONITOR->vecPosition.y - pHyprPopup->ly, .width = PMONITOR->vecSize.x, .height = PMONITOR->vecSize.y};
|
||||
CBox box = {PMONITOR->vecPosition.x - pHyprPopup->lx, PMONITOR->vecPosition.y - pHyprPopup->ly, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||
|
||||
wlr_xdg_popup_unconstrain_from_box(popup, &box);
|
||||
wlr_xdg_popup_unconstrain_from_box(popup, box.pWlr());
|
||||
|
||||
pHyprPopup->monitor = PMONITOR;
|
||||
|
||||
@@ -159,13 +159,16 @@ void Events::listener_mapPopupXDG(void* owner, void* data) {
|
||||
int lx = 0, ly = 0;
|
||||
addPopupGlobalCoords(PPOPUP, &lx, &ly);
|
||||
|
||||
wlr_box extents;
|
||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, &extents);
|
||||
CBox extents;
|
||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr());
|
||||
extents.applyFromWlr();
|
||||
|
||||
g_pHyprRenderer->damageBox(lx - extents.x, ly - extents.y, extents.width + 2, extents.height + 2);
|
||||
|
||||
if (PPOPUP->monitor)
|
||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(PPOPUP->popup->base->surface, PPOPUP->monitor->scale);
|
||||
if (PPOPUP->monitor) {
|
||||
g_pCompositor->setPreferredScaleForSurface(PPOPUP->popup->base->surface, PPOPUP->monitor->scale);
|
||||
g_pCompositor->setPreferredTransformForSurface(PPOPUP->popup->base->surface, PPOPUP->monitor->transform);
|
||||
}
|
||||
|
||||
Debug::log(LOG, "XDG Popup got assigned a surfaceTreeNode {:x}", (uintptr_t)PPOPUP->pSurfaceTree);
|
||||
}
|
||||
@@ -178,11 +181,18 @@ void Events::listener_repositionPopupXDG(void* owner, void* data) {
|
||||
int lx = 0, ly = 0;
|
||||
addPopupGlobalCoords(PPOPUP, &lx, &ly);
|
||||
|
||||
wlr_box extents;
|
||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, &extents);
|
||||
CBox extents;
|
||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr());
|
||||
extents.applyFromWlr();
|
||||
|
||||
PPOPUP->lastPos = {lx - extents.x, ly - extents.y};
|
||||
PPOPUP->repositionRequested = true;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
||||
|
||||
CBox box = {PMONITOR->vecPosition.x - lx + PPOPUP->popup->current.geometry.x, PMONITOR->vecPosition.y - ly + PPOPUP->popup->current.geometry.y, PMONITOR->vecSize.x,
|
||||
PMONITOR->vecSize.y};
|
||||
wlr_xdg_popup_unconstrain_from_box(PPOPUP->popup, box.pWlr());
|
||||
}
|
||||
|
||||
void Events::listener_unmapPopupXDG(void* owner, void* data) {
|
||||
@@ -199,8 +209,9 @@ void Events::listener_unmapPopupXDG(void* owner, void* data) {
|
||||
int lx = 0, ly = 0;
|
||||
addPopupGlobalCoords(PPOPUP, &lx, &ly);
|
||||
|
||||
wlr_box extents;
|
||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, &extents);
|
||||
CBox extents;
|
||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr());
|
||||
extents.applyFromWlr();
|
||||
|
||||
g_pHyprRenderer->damageBox(lx - extents.x, ly - extents.y, extents.width + 2, extents.height + 2);
|
||||
|
||||
@@ -225,8 +236,9 @@ void Events::listener_commitPopupXDG(void* owner, void* data) {
|
||||
int lx = 0, ly = 0;
|
||||
addPopupGlobalCoords(PPOPUP, &lx, &ly);
|
||||
|
||||
wlr_box extents;
|
||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, &extents);
|
||||
CBox extents;
|
||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr());
|
||||
extents.applyFromWlr();
|
||||
|
||||
if (PPOPUP->repositionRequested)
|
||||
g_pHyprRenderer->damageBox(PPOPUP->lastPos.x, PPOPUP->lastPos.y, extents.width + 2, extents.height + 2);
|
||||
|
@@ -96,7 +96,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
|
||||
if (PWORKSPACE->m_bDefaultPseudo) {
|
||||
PWINDOW->m_bIsPseudotiled = true;
|
||||
wlr_box desiredGeometry = {0};
|
||||
CBox desiredGeometry = {0};
|
||||
g_pXWaylandManager->getGeometryForWindow(PWINDOW, &desiredGeometry);
|
||||
PWINDOW->m_vPseudoSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
|
||||
}
|
||||
@@ -468,11 +468,13 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
const auto PLSFROMFOCUS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus);
|
||||
if (PLSFROMFOCUS && PLSFROMFOCUS->layerSurface->current.keyboard_interactive)
|
||||
PWINDOW->m_bNoInitialFocus = true;
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !requestsFullscreen) {
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !requestsFullscreen && !PWINDOW->m_bIsFloating) {
|
||||
if (*PNEWTAKESOVERFS == 0)
|
||||
PWINDOW->m_bNoInitialFocus = true;
|
||||
else if (*PNEWTAKESOVERFS == 2)
|
||||
g_pCompositor->setWindowFullscreen(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), false, FULLSCREEN_INVALID);
|
||||
else if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED)
|
||||
requestsMaximize = true;
|
||||
else
|
||||
requestsFullscreen = true;
|
||||
}
|
||||
@@ -644,7 +646,14 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->m_bIsFullscreen && !PWINDOW->m_bIsFloating)
|
||||
PWINDOW->m_fAlpha.setValueAndWarp(0.f);
|
||||
|
||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale);
|
||||
g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale);
|
||||
g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->transform);
|
||||
|
||||
if (g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal()) == g_pCompositor->m_pLastWindow)
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
|
||||
// fix some xwayland apps that don't behave nicely
|
||||
PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize;
|
||||
}
|
||||
|
||||
void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
@@ -732,12 +741,10 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
|
||||
Debug::log(LOG, "On closed window, new focused candidate is {}", PWINDOWCANDIDATE);
|
||||
|
||||
if (PWINDOWCANDIDATE != g_pCompositor->m_pLastWindow) {
|
||||
if (!PWINDOWCANDIDATE)
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
else
|
||||
g_pCompositor->focusWindow(PWINDOWCANDIDATE);
|
||||
} else
|
||||
if (PWINDOWCANDIDATE != g_pCompositor->m_pLastWindow && PWINDOWCANDIDATE)
|
||||
g_pCompositor->focusWindow(PWINDOWCANDIDATE);
|
||||
|
||||
if (g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal()) == PWINDOWCANDIDATE)
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
|
||||
// CWindow::onUnmap will remove this window's active status, but we can't really do it above.
|
||||
@@ -787,6 +794,8 @@ void Events::listener_commitWindow(void* owner, void* data) {
|
||||
if (!PWINDOW->m_bMappedX11 || PWINDOW->isHidden() || (PWINDOW->m_bIsX11 && !PWINDOW->m_bMappedX11))
|
||||
return;
|
||||
|
||||
PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged.
|
||||
|
||||
PWINDOW->updateSurfaceOutputs();
|
||||
|
||||
g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y,
|
||||
@@ -846,8 +855,8 @@ void Events::listener_destroyWindow(void* owner, void* data) {
|
||||
PWINDOW->m_bReadyToDelete = true;
|
||||
|
||||
if (!PWINDOW->m_bFadingOut) {
|
||||
g_pCompositor->removeWindowFromVectorSafe(PWINDOW); // most likely X11 unmanaged or sumn
|
||||
Debug::log(LOG, "Unmapped {} removed instantly", PWINDOW);
|
||||
g_pCompositor->removeWindowFromVectorSafe(PWINDOW); // most likely X11 unmanaged or sumn
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1004,6 +1013,7 @@ void Events::listener_configureX11(void* owner, void* data) {
|
||||
|
||||
if (!PWINDOW->m_uSurface.xwayland->surface || !PWINDOW->m_uSurface.xwayland->surface->mapped || !PWINDOW->m_bMappedX11) {
|
||||
wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height);
|
||||
PWINDOW->m_vReportedSize = {E->width, E->height};
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1049,6 +1059,8 @@ void Events::listener_configureX11(void* owner, void* data) {
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
|
||||
PWINDOW->updateWindowDecos();
|
||||
|
||||
PWINDOW->m_vReportedSize = {E->width, E->height};
|
||||
}
|
||||
|
||||
void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
|
||||
|
112
src/helpers/Box.cpp
Normal file
112
src/helpers/Box.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
#include "Box.hpp"
|
||||
wlr_box CBox::wlr() {
|
||||
CBox rounded = roundInternal();
|
||||
m_bWlrBox = wlr_box{(int)rounded.x, (int)rounded.y, (int)rounded.w, (int)rounded.h};
|
||||
return m_bWlrBox;
|
||||
}
|
||||
|
||||
wlr_box* CBox::pWlr() {
|
||||
CBox rounded = roundInternal();
|
||||
m_bWlrBox = wlr_box{(int)rounded.x, (int)rounded.y, (int)rounded.w, (int)rounded.h};
|
||||
return &m_bWlrBox;
|
||||
}
|
||||
|
||||
CBox& CBox::scale(double scale) {
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
w *= scale;
|
||||
h *= scale;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::scale(const Vector2D& scale) {
|
||||
x *= scale.x;
|
||||
y *= scale.y;
|
||||
w *= scale.x;
|
||||
h *= scale.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::translate(const Vector2D& vec) {
|
||||
x += vec.x;
|
||||
y += vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector2D CBox::middle() const {
|
||||
return Vector2D{x + w / 2.0, y + h / 2.0};
|
||||
}
|
||||
|
||||
bool CBox::containsPoint(const Vector2D& vec) const {
|
||||
return VECINRECT(vec, x, y, x + w, y + h);
|
||||
}
|
||||
|
||||
bool CBox::empty() const {
|
||||
return w == 0 || h == 0;
|
||||
}
|
||||
|
||||
CBox& CBox::applyFromWlr() {
|
||||
x = m_bWlrBox.x;
|
||||
y = m_bWlrBox.y;
|
||||
w = m_bWlrBox.width;
|
||||
h = m_bWlrBox.height;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::round() {
|
||||
float newW = x + w - std::round(x);
|
||||
float newH = y + h - std::round(y);
|
||||
x = std::round(x);
|
||||
y = std::round(y);
|
||||
w = std::round(newW);
|
||||
h = std::round(newH);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::transform(const wl_output_transform t, double w, double h) {
|
||||
wlr_box_transform(&m_bWlrBox, pWlr(), t, w, h);
|
||||
applyFromWlr();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::addExtents(const SWindowDecorationExtents& e) {
|
||||
x -= e.topLeft.x;
|
||||
y -= e.topLeft.y;
|
||||
w += e.topLeft.x + e.bottomRight.x;
|
||||
h += e.topLeft.y + e.bottomRight.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::scaleFromCenter(double scale) {
|
||||
double oldW = w, oldH = h;
|
||||
|
||||
w *= scale;
|
||||
h *= scale;
|
||||
|
||||
x -= (w - oldW) / 2.0;
|
||||
y -= (h - oldH) / 2.0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox CBox::roundInternal() {
|
||||
float newW = x + w - std::floor(x);
|
||||
float newH = y + h - std::floor(y);
|
||||
|
||||
return CBox{std::floor(x), std::floor(y), std::floor(newW), std::floor(newH)};
|
||||
}
|
||||
|
||||
Vector2D CBox::pos() const {
|
||||
return {x, y};
|
||||
}
|
||||
|
||||
Vector2D CBox::size() const {
|
||||
return {w, h};
|
||||
}
|
80
src/helpers/Box.hpp
Normal file
80
src/helpers/Box.hpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
|
||||
#include "Vector2D.hpp"
|
||||
#include "../SharedDefs.hpp"
|
||||
#include "../includes.hpp"
|
||||
|
||||
class CBox {
|
||||
public:
|
||||
CBox(double x_, double y_, double w_, double h_) {
|
||||
x = x_;
|
||||
y = y_;
|
||||
w = w_;
|
||||
h = h_;
|
||||
}
|
||||
|
||||
CBox() {
|
||||
w = 0;
|
||||
h = 0;
|
||||
}
|
||||
|
||||
CBox(const wlr_box& box) {
|
||||
x = box.x;
|
||||
y = box.y;
|
||||
w = box.width;
|
||||
h = box.height;
|
||||
}
|
||||
|
||||
CBox(const double d) {
|
||||
x = d;
|
||||
y = d;
|
||||
w = d;
|
||||
h = d;
|
||||
}
|
||||
|
||||
CBox(const Vector2D& pos, const Vector2D& size) {
|
||||
x = pos.x;
|
||||
y = pos.y;
|
||||
w = size.x;
|
||||
h = size.y;
|
||||
}
|
||||
|
||||
wlr_box wlr();
|
||||
wlr_box* pWlr();
|
||||
|
||||
CBox& applyFromWlr();
|
||||
CBox& scale(double scale);
|
||||
CBox& scaleFromCenter(double scale);
|
||||
CBox& scale(const Vector2D& scale);
|
||||
CBox& translate(const Vector2D& vec);
|
||||
CBox& round();
|
||||
CBox& transform(const wl_output_transform t, double w, double h);
|
||||
CBox& addExtents(const SWindowDecorationExtents& e);
|
||||
|
||||
Vector2D middle() const;
|
||||
Vector2D pos() const;
|
||||
Vector2D size() const;
|
||||
|
||||
bool containsPoint(const Vector2D& vec) const;
|
||||
bool empty() const;
|
||||
|
||||
double x = 0, y = 0;
|
||||
union {
|
||||
double w;
|
||||
double width;
|
||||
};
|
||||
union {
|
||||
double h;
|
||||
double height;
|
||||
};
|
||||
|
||||
//
|
||||
bool operator==(const CBox& rhs) const {
|
||||
return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h;
|
||||
}
|
||||
|
||||
private:
|
||||
CBox roundInternal();
|
||||
|
||||
wlr_box m_bWlrBox;
|
||||
};
|
@@ -2,6 +2,7 @@
|
||||
#include "../defines.hpp"
|
||||
#include <algorithm>
|
||||
#include "../Compositor.hpp"
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <sys/utsname.h>
|
||||
#include <iomanip>
|
||||
@@ -184,13 +185,6 @@ std::string escapeJSONStrings(const std::string& str) {
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
void scaleBox(wlr_box* box, float scale) {
|
||||
box->width = std::round(box->width * scale);
|
||||
box->height = std::round(box->height * scale);
|
||||
box->x = std::round(box->x * scale);
|
||||
box->y = std::round(box->y * scale);
|
||||
}
|
||||
|
||||
std::string removeBeginEndSpacesTabs(std::string str) {
|
||||
if (str.empty())
|
||||
return str;
|
||||
@@ -248,6 +242,10 @@ bool isDirection(const std::string& arg) {
|
||||
return arg == "l" || arg == "r" || arg == "u" || arg == "d" || arg == "t" || arg == "b";
|
||||
}
|
||||
|
||||
bool isDirection(const char& arg) {
|
||||
return arg == 'l' || arg == 'r' || arg == 'u' || arg == 'd' || arg == 't' || arg == 'b';
|
||||
}
|
||||
|
||||
int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
int result = INT_MAX;
|
||||
if (in.starts_with("special")) {
|
||||
@@ -503,6 +501,43 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::optional<std::string> cleanCmdForWorkspace(const std::string& inWorkspaceName, std::string dirtyCmd) {
|
||||
|
||||
std::string cmd = removeBeginEndSpacesTabs(dirtyCmd);
|
||||
|
||||
if (!cmd.empty()) {
|
||||
std::string rules;
|
||||
const std::string workspaceRule = "workspace " + inWorkspaceName;
|
||||
|
||||
if (cmd[0] == '[') {
|
||||
const int closingBracketIdx = cmd.find_last_of(']');
|
||||
auto tmpRules = cmd.substr(1, closingBracketIdx - 1);
|
||||
cmd = cmd.substr(closingBracketIdx + 1);
|
||||
|
||||
auto rulesList = CVarList(tmpRules, 0, ';');
|
||||
|
||||
bool hadWorkspaceRule = false;
|
||||
rulesList.map([&](std::string& rule) {
|
||||
if (rule.find("workspace") == 0) {
|
||||
rule = workspaceRule;
|
||||
hadWorkspaceRule = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!hadWorkspaceRule)
|
||||
rulesList.append(workspaceRule);
|
||||
|
||||
rules = "[" + rulesList.join(";") + "]";
|
||||
} else {
|
||||
rules = "[" + workspaceRule + "]";
|
||||
}
|
||||
|
||||
return std::optional<std::string>(rules + " " + cmd);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2) {
|
||||
const float DX = std::max({0.0, p1.x - vec.x, vec.x - p2.x});
|
||||
const float DY = std::max({0.0, p1.y - vec.y, vec.y - p2.y});
|
||||
@@ -594,8 +629,8 @@ int64_t getPPIDof(int64_t pid) {
|
||||
|
||||
return 0;
|
||||
#else
|
||||
std::string dir = "/proc/" + std::to_string(pid) + "/status";
|
||||
FILE* infile;
|
||||
std::string dir = "/proc/" + std::to_string(pid) + "/status";
|
||||
FILE* infile;
|
||||
|
||||
infile = fopen(dir.c_str(), "r");
|
||||
if (!infile)
|
||||
@@ -712,4 +747,21 @@ std::vector<SCallstackFrameInfo> getBacktrace() {
|
||||
void throwError(const std::string& err) {
|
||||
Debug::log(CRIT, "Critical error thrown: {}", err);
|
||||
throw std::runtime_error(err);
|
||||
}
|
||||
|
||||
uint32_t drmFormatToGL(uint32_t drm) {
|
||||
switch (drm) {
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
case DRM_FORMAT_XBGR8888: return GL_RGBA; // doesn't matter, opengl is gucci in this case.
|
||||
case DRM_FORMAT_XRGB2101010:
|
||||
case DRM_FORMAT_XBGR2101010:
|
||||
#ifdef GLES2
|
||||
return GL_RGB10_A2_EXT;
|
||||
#else
|
||||
return GL_RGB10_A2;
|
||||
#endif
|
||||
default: return GL_RGBA;
|
||||
}
|
||||
UNREACHABLE();
|
||||
return GL_RGBA;
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <wayland-server.h>
|
||||
#include <wlr/util/box.h>
|
||||
@@ -15,11 +16,12 @@ struct SCallstackFrameInfo {
|
||||
std::string absolutePath(const std::string&, const std::string&);
|
||||
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString);
|
||||
std::string escapeJSONStrings(const std::string& str);
|
||||
void scaleBox(wlr_box*, float);
|
||||
std::string removeBeginEndSpacesTabs(std::string);
|
||||
bool isNumber(const std::string&, bool allowfloat = false);
|
||||
bool isDirection(const std::string&);
|
||||
bool isDirection(const char&);
|
||||
int getWorkspaceIDFromString(const std::string&, std::string&);
|
||||
std::optional<std::string> cleanCmdForWorkspace(const std::string&, std::string);
|
||||
float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2);
|
||||
void logSystemInfo();
|
||||
std::string execAndGet(const char*);
|
||||
@@ -31,6 +33,7 @@ double normalizeAngleRad(double ang);
|
||||
std::string replaceInString(std::string subject, const std::string& search, const std::string& replace);
|
||||
std::vector<SCallstackFrameInfo> getBacktrace();
|
||||
void throwError(const std::string& err);
|
||||
uint32_t drmFormatToGL(uint32_t drm);
|
||||
|
||||
template <typename... Args>
|
||||
[[deprecated("use std::format instead")]] std::string getFormat(std::format_string<Args...> fmt, Args&&... args) {
|
||||
|
@@ -109,20 +109,20 @@ void CMonitor::onConnect(bool noRule) {
|
||||
m_bRenderingInitPassed = true;
|
||||
}
|
||||
|
||||
if (!m_pThisWrap) {
|
||||
std::shared_ptr<CMonitor>* thisWrapper = nullptr;
|
||||
|
||||
// find the wrap
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
if (m->ID == ID) {
|
||||
m_pThisWrap = &m;
|
||||
break;
|
||||
}
|
||||
// find the wrap
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
if (m->ID == ID) {
|
||||
thisWrapper = &m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end()) {
|
||||
g_pCompositor->m_vMonitors.push_back(*m_pThisWrap);
|
||||
}
|
||||
RASSERT(thisWrapper->get(), "CMonitor::onConnect: Had no wrapper???");
|
||||
|
||||
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end())
|
||||
g_pCompositor->m_vMonitors.push_back(*thisWrapper);
|
||||
|
||||
m_bEnabled = true;
|
||||
|
||||
@@ -132,6 +132,8 @@ void CMonitor::onConnect(bool noRule) {
|
||||
if (!noRule)
|
||||
g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true);
|
||||
|
||||
wlr_output_commit(output);
|
||||
|
||||
wlr_damage_ring_set_bounds(&damage, vecTransformedSize.x, vecTransformedSize.y);
|
||||
|
||||
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, scale);
|
||||
@@ -152,8 +154,6 @@ void CMonitor::onConnect(bool noRule) {
|
||||
if (scale < 0.1)
|
||||
scale = getDefaultScale();
|
||||
|
||||
m_pThisWrap = nullptr;
|
||||
|
||||
forceFullFrames = 3; // force 3 full frames to make sure there is no blinking due to double-buffering.
|
||||
//
|
||||
|
||||
@@ -184,6 +184,8 @@ void CMonitor::onConnect(bool noRule) {
|
||||
g_pCompositor->setActiveMonitor(this);
|
||||
|
||||
renderTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, ratHandler, this);
|
||||
|
||||
g_pCompositor->scheduleFrameForMonitor(this);
|
||||
}
|
||||
|
||||
void CMonitor::onDisconnect() {
|
||||
@@ -221,9 +223,6 @@ void CMonitor::onDisconnect() {
|
||||
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||
}
|
||||
|
||||
m_bEnabled = false;
|
||||
m_bRenderingInitPassed = false;
|
||||
|
||||
hyprListener_monitorFrame.removeCallback();
|
||||
hyprListener_monitorDamage.removeCallback();
|
||||
hyprListener_monitorNeedsFrame.removeCallback();
|
||||
@@ -248,6 +247,9 @@ void CMonitor::onDisconnect() {
|
||||
g_pCompositor->enterUnsafeState();
|
||||
}
|
||||
|
||||
m_bEnabled = false;
|
||||
m_bRenderingInitPassed = false;
|
||||
|
||||
if (BACKUPMON) {
|
||||
// snap cursor
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, BACKUPMON->vecPosition.x + BACKUPMON->vecTransformedSize.x / 2.f,
|
||||
@@ -256,7 +258,7 @@ void CMonitor::onDisconnect() {
|
||||
// move workspaces
|
||||
std::deque<CWorkspace*> wspToMove;
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
if (w->m_iMonitorID == ID) {
|
||||
if (w->m_iMonitorID == ID || !g_pCompositor->getMonitorFromID(w->m_iMonitorID)) {
|
||||
wspToMove.push_back(w.get());
|
||||
}
|
||||
}
|
||||
@@ -315,14 +317,14 @@ void CMonitor::addDamage(const CRegion* rg) {
|
||||
addDamage(const_cast<CRegion*>(rg)->pixman());
|
||||
}
|
||||
|
||||
void CMonitor::addDamage(const wlr_box* box) {
|
||||
void CMonitor::addDamage(const CBox* box) {
|
||||
static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue;
|
||||
if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) {
|
||||
wlr_damage_ring_add_whole(&damage);
|
||||
g_pCompositor->scheduleFrameForMonitor(this);
|
||||
}
|
||||
|
||||
if (wlr_damage_ring_add_box(&damage, box))
|
||||
if (wlr_damage_ring_add_box(&damage, const_cast<CBox*>(box)->pWlr()))
|
||||
g_pCompositor->scheduleFrameForMonitor(this);
|
||||
}
|
||||
|
||||
@@ -414,19 +416,22 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
|
||||
vecPosition = RULE.offset;
|
||||
|
||||
// push to mvmonitors
|
||||
if (!m_pThisWrap) {
|
||||
// find the wrap
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
if (m->ID == ID) {
|
||||
m_pThisWrap = &m;
|
||||
break;
|
||||
}
|
||||
|
||||
std::shared_ptr<CMonitor>* thisWrapper = nullptr;
|
||||
|
||||
// find the wrap
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
if (m->ID == ID) {
|
||||
thisWrapper = &m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RASSERT(thisWrapper->get(), "CMonitor::setMirror: Had no wrapper???");
|
||||
|
||||
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) ==
|
||||
g_pCompositor->m_vMonitors.end()) {
|
||||
g_pCompositor->m_vMonitors.push_back(*m_pThisWrap);
|
||||
g_pCompositor->m_vMonitors.push_back(*thisWrapper);
|
||||
}
|
||||
|
||||
setupDefaultWS(RULE);
|
||||
|
@@ -61,10 +61,12 @@ class CMonitor {
|
||||
bool gammaChanged = false;
|
||||
float xwaylandScale = 1.f;
|
||||
|
||||
bool dpmsStatus = true;
|
||||
bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
|
||||
bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
|
||||
bool createdByUser = false;
|
||||
bool dpmsStatus = true;
|
||||
bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
|
||||
bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
|
||||
bool createdByUser = false;
|
||||
uint32_t drmFormat = DRM_FORMAT_INVALID;
|
||||
bool isUnsafeFallback = false;
|
||||
|
||||
bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after
|
||||
bool renderingActive = false;
|
||||
@@ -107,24 +109,23 @@ class CMonitor {
|
||||
DYNLISTENER(monitorBind);
|
||||
|
||||
// methods
|
||||
void onConnect(bool noRule);
|
||||
void onDisconnect();
|
||||
void addDamage(const pixman_region32_t* rg);
|
||||
void addDamage(const CRegion* rg);
|
||||
void addDamage(const wlr_box* box);
|
||||
void setMirror(const std::string&);
|
||||
bool isMirror();
|
||||
float getDefaultScale();
|
||||
void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false);
|
||||
void changeWorkspace(const int& id, bool internal = false);
|
||||
void setSpecialWorkspace(CWorkspace* const pWorkspace);
|
||||
void setSpecialWorkspace(const int& id);
|
||||
void moveTo(const Vector2D& pos);
|
||||
Vector2D middle();
|
||||
void onConnect(bool noRule);
|
||||
void onDisconnect();
|
||||
void addDamage(const pixman_region32_t* rg);
|
||||
void addDamage(const CRegion* rg);
|
||||
void addDamage(const CBox* box);
|
||||
void setMirror(const std::string&);
|
||||
bool isMirror();
|
||||
float getDefaultScale();
|
||||
void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false);
|
||||
void changeWorkspace(const int& id, bool internal = false);
|
||||
void setSpecialWorkspace(CWorkspace* const pWorkspace);
|
||||
void setSpecialWorkspace(const int& id);
|
||||
void moveTo(const Vector2D& pos);
|
||||
Vector2D middle();
|
||||
|
||||
std::shared_ptr<CMonitor>* m_pThisWrap = nullptr;
|
||||
bool m_bEnabled = false;
|
||||
bool m_bRenderingInitPassed = false;
|
||||
bool m_bEnabled = false;
|
||||
bool m_bRenderingInitPassed = false;
|
||||
|
||||
// For the list lookup
|
||||
|
||||
|
@@ -21,6 +21,10 @@ CRegion::CRegion(wlr_box* box) {
|
||||
pixman_region32_init_rect(&m_rRegion, box->x, box->y, box->width, box->height);
|
||||
}
|
||||
|
||||
CRegion::CRegion(CBox* box) {
|
||||
pixman_region32_init_rect(&m_rRegion, box->x, box->y, box->w, box->h);
|
||||
}
|
||||
|
||||
CRegion::CRegion(pixman_box32_t* box) {
|
||||
pixman_region32_init_rect(&m_rRegion, box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1);
|
||||
}
|
||||
@@ -100,7 +104,7 @@ std::vector<pixman_box32_t> CRegion::getRects() const {
|
||||
return result;
|
||||
}
|
||||
|
||||
wlr_box CRegion::getExtents() {
|
||||
CBox CRegion::getExtents() {
|
||||
pixman_box32_t* box = pixman_region32_extents(&m_rRegion);
|
||||
return {box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1};
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@
|
||||
#include <pixman.h>
|
||||
#include <vector>
|
||||
#include "Vector2D.hpp"
|
||||
#include "Box.hpp"
|
||||
|
||||
struct wlr_box;
|
||||
|
||||
@@ -15,6 +16,8 @@ class CRegion {
|
||||
CRegion(double x, double y, double w, double h);
|
||||
/* Create from a wlr_box */
|
||||
CRegion(wlr_box* box);
|
||||
/* Create from a CBox */
|
||||
CRegion(CBox* box);
|
||||
/* Create from a pixman_box32_t */
|
||||
CRegion(pixman_box32_t* box);
|
||||
|
||||
@@ -43,7 +46,7 @@ class CRegion {
|
||||
CRegion& translate(const Vector2D& vec);
|
||||
CRegion& invert(pixman_box32_t* box);
|
||||
CRegion& scale(float scale);
|
||||
wlr_box getExtents();
|
||||
CBox getExtents();
|
||||
bool containsPoint(const Vector2D& vec) const;
|
||||
bool empty() const;
|
||||
Vector2D closestPoint(const Vector2D& vec) const;
|
||||
@@ -51,7 +54,7 @@ class CRegion {
|
||||
std::vector<pixman_box32_t> getRects() const;
|
||||
|
||||
pixman_region32_t* pixman() {
|
||||
return &m_rRegion;
|
||||
return &m_rRegion;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@@ -98,8 +98,9 @@ void SubsurfaceTree::destroySurfaceTree(SSurfaceTreeNode* pNode) {
|
||||
|
||||
// damage
|
||||
if (pNode->pSurface && pNode->pSurface->exists()) {
|
||||
wlr_box extents = {};
|
||||
wlr_surface_get_extends(pNode->pSurface->wlr(), &extents);
|
||||
CBox extents = {};
|
||||
wlr_surface_get_extends(pNode->pSurface->wlr(), extents.pWlr());
|
||||
extents.applyFromWlr();
|
||||
|
||||
int lx = 0, ly = 0;
|
||||
addSurfaceGlobalOffset(pNode, &lx, &ly);
|
||||
@@ -198,7 +199,7 @@ void Events::listener_unmapSubsurface(void* owner, void* data) {
|
||||
int lx = 0, ly = 0;
|
||||
addSurfaceGlobalOffset(PNODE, &lx, &ly);
|
||||
|
||||
wlr_box extents = {lx, ly, 0, 0};
|
||||
CBox extents = {lx, ly, 0, 0};
|
||||
|
||||
extents.width = PNODE->pSurface->wlr()->current.width;
|
||||
extents.height = PNODE->pSurface->wlr()->current.height;
|
||||
@@ -247,6 +248,9 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
|
||||
g_pHyprRenderer->damageSurface(pNode->pSurface->wlr(), lx, ly, SCALE);
|
||||
|
||||
if (pNode->pWindowOwner) {
|
||||
// update reported size. Some windows do not send a ::commit afterwards. Odd.
|
||||
pNode->pWindowOwner->m_vReportedSize = pNode->pWindowOwner->m_vPendingReportedSize;
|
||||
|
||||
// tearing: if solitary, redraw it. This still might be a single surface window
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pNode->pWindowOwner->m_iMonitorID);
|
||||
if (PMONITOR->solitaryClient == pNode->pWindowOwner && pNode->pWindowOwner->canBeTorn() && PMONITOR->tearingState.canTear &&
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "../macros.hpp"
|
||||
@@ -20,6 +21,15 @@ class CVarList {
|
||||
|
||||
std::string join(const std::string& joiner, size_t from = 0, size_t to = 0) const;
|
||||
|
||||
void map(std::function<void(std::string&)> func) {
|
||||
for (auto& s : m_vArgs)
|
||||
func(s);
|
||||
}
|
||||
|
||||
void append(const std::string arg) {
|
||||
m_vArgs.emplace_back(arg);
|
||||
}
|
||||
|
||||
std::string operator[](const size_t& idx) const {
|
||||
if (idx >= m_vArgs.size())
|
||||
return "";
|
||||
|
@@ -45,3 +45,7 @@ bool Vector2D::inTriangle(const Vector2D& p1, const Vector2D& p2, const Vector2D
|
||||
|
||||
return 0 <= a && a <= 1 && 0 <= b && b <= 1 && 0 <= c && c <= 1;
|
||||
}
|
||||
|
||||
double Vector2D::size() const {
|
||||
return std::sqrt(x * x + y * y);
|
||||
}
|
||||
|
@@ -22,6 +22,9 @@ class Vector2D {
|
||||
Vector2D operator-(const Vector2D& a) const {
|
||||
return Vector2D(this->x - a.x, this->y - a.y);
|
||||
}
|
||||
Vector2D operator-() const {
|
||||
return Vector2D(-this->x, -this->y);
|
||||
}
|
||||
Vector2D operator*(const float& a) const {
|
||||
return Vector2D(this->x * a, this->y * a);
|
||||
}
|
||||
@@ -54,7 +57,7 @@ class Vector2D {
|
||||
}
|
||||
|
||||
double distance(const Vector2D& other) const;
|
||||
|
||||
double size() const;
|
||||
Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D()) const;
|
||||
|
||||
Vector2D floor() const;
|
||||
|
@@ -33,7 +33,7 @@ struct SLayerSurface {
|
||||
DYNLISTENER(commitLayerSurface);
|
||||
DYNLISTENER(newPopup);
|
||||
|
||||
wlr_box geometry = {0, 0, 0, 0};
|
||||
CBox geometry = {0, 0, 0, 0};
|
||||
Vector2D position;
|
||||
zwlr_layer_shell_v1_layer layer;
|
||||
|
||||
@@ -65,12 +65,12 @@ class CMonitor;
|
||||
struct SRenderData {
|
||||
CMonitor* pMonitor;
|
||||
timespec* when;
|
||||
int x, y;
|
||||
double x, y;
|
||||
|
||||
// for iters
|
||||
void* data = nullptr;
|
||||
wlr_surface* surface = nullptr;
|
||||
int w, h;
|
||||
double w, h;
|
||||
|
||||
// for rounding
|
||||
bool dontRound = true;
|
||||
|
@@ -27,17 +27,45 @@ wlr_surface* CWLSurface::wlr() const {
|
||||
return m_pWLRSurface;
|
||||
}
|
||||
|
||||
bool CWLSurface::small() const {
|
||||
if (!m_pOwner || !exists())
|
||||
return false;
|
||||
|
||||
return m_pOwner->m_vReportedSize.x > m_pWLRSurface->current.buffer_width + 1 || m_pOwner->m_vReportedSize.y > m_pWLRSurface->current.buffer_height + 1;
|
||||
}
|
||||
|
||||
Vector2D CWLSurface::correctSmallVec() const {
|
||||
if (!m_pOwner || !exists() || !small() || m_bFillIgnoreSmall)
|
||||
return {};
|
||||
|
||||
const auto SIZE = getViewporterCorrectedSize();
|
||||
|
||||
return Vector2D{(m_pOwner->m_vReportedSize.x - SIZE.x) / 2, (m_pOwner->m_vReportedSize.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}) *
|
||||
(m_pOwner->m_vRealSize.vec() / m_pOwner->m_vReportedSize);
|
||||
}
|
||||
|
||||
Vector2D CWLSurface::getViewporterCorrectedSize() const {
|
||||
if (!exists())
|
||||
return {};
|
||||
|
||||
return m_pWLRSurface->current.viewport.has_dst ? Vector2D{m_pWLRSurface->current.viewport.dst_width, m_pWLRSurface->current.viewport.dst_height} :
|
||||
Vector2D{m_pWLRSurface->current.buffer_width, m_pWLRSurface->current.buffer_height};
|
||||
}
|
||||
|
||||
void CWLSurface::destroy() {
|
||||
if (!m_pWLRSurface)
|
||||
return;
|
||||
|
||||
hyprListener_destroy.removeCallback();
|
||||
m_pWLRSurface->data = nullptr;
|
||||
m_pOwner = nullptr;
|
||||
|
||||
if (g_pCompositor->m_pLastFocus == m_pWLRSurface)
|
||||
g_pCompositor->m_pLastFocus = nullptr;
|
||||
if (g_pInputManager->m_pLastMouseSurface == m_pWLRSurface)
|
||||
g_pInputManager->m_pLastMouseSurface = nullptr;
|
||||
if (g_pHyprRenderer->m_sLastCursorData.surf == m_pWLRSurface)
|
||||
g_pInputManager->setCursorImageOverride("left_ptr");
|
||||
|
||||
m_pWLRSurface = nullptr;
|
||||
|
||||
|
@@ -1,6 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "../defines.hpp"
|
||||
|
||||
class CWindow;
|
||||
|
||||
class CWLSurface {
|
||||
public:
|
||||
CWLSurface() = default;
|
||||
@@ -10,20 +13,29 @@ class CWLSurface {
|
||||
void assign(wlr_surface* pSurface);
|
||||
void unassign();
|
||||
|
||||
CWLSurface(const CWLSurface&) = delete;
|
||||
CWLSurface(CWLSurface&&) = delete;
|
||||
CWLSurface(const CWLSurface&) = delete;
|
||||
CWLSurface(CWLSurface&&) = delete;
|
||||
CWLSurface& operator=(const CWLSurface&) = delete;
|
||||
CWLSurface& operator=(CWLSurface&&) = delete;
|
||||
CWLSurface& operator=(CWLSurface&&) = delete;
|
||||
|
||||
wlr_surface* wlr() const;
|
||||
bool exists() const;
|
||||
bool small() const; // means surface is smaller than the requested size
|
||||
Vector2D correctSmallVec() const; // returns a corrective vector for small() surfaces
|
||||
Vector2D getViewporterCorrectedSize() const;
|
||||
|
||||
CWLSurface& operator=(wlr_surface* pSurface) {
|
||||
destroy();
|
||||
m_pWLRSurface = pSurface;
|
||||
init();
|
||||
// allow stretching. Useful for plugins.
|
||||
bool m_bFillIgnoreSmall = false;
|
||||
|
||||
return *this;
|
||||
// if present, means this is a base surface of a window. Cleaned on unassign()
|
||||
CWindow* m_pOwner = nullptr;
|
||||
|
||||
CWLSurface& operator=(wlr_surface* pSurface) {
|
||||
destroy();
|
||||
m_pWLRSurface = pSurface;
|
||||
init();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const CWLSurface& other) const {
|
||||
@@ -38,6 +50,10 @@ class CWLSurface {
|
||||
return exists();
|
||||
}
|
||||
|
||||
static CWLSurface* surfaceFromWlr(wlr_surface* pSurface) {
|
||||
return (CWLSurface*)pSurface->data;
|
||||
}
|
||||
|
||||
private:
|
||||
wlr_surface* m_pWLRSurface = nullptr;
|
||||
|
||||
|
@@ -4,8 +4,7 @@
|
||||
#include <string>
|
||||
#include "../defines.hpp"
|
||||
|
||||
enum eFullscreenMode : int8_t
|
||||
{
|
||||
enum eFullscreenMode : int8_t {
|
||||
FULLSCREEN_INVALID = -1,
|
||||
FULLSCREEN_FULL = 0,
|
||||
FULLSCREEN_MAXIMIZED
|
||||
@@ -53,6 +52,9 @@ class CWorkspace {
|
||||
// last monitor (used on reconnect)
|
||||
std::string m_szLastMonitor = "";
|
||||
|
||||
// Whether the user configured command for on-created-empty has been executed, if any
|
||||
bool m_bOnCreatedEmptyExecuted = false;
|
||||
|
||||
void startAnim(bool in, bool left, bool instant = false);
|
||||
void setActive(bool on);
|
||||
|
||||
|
@@ -5,7 +5,7 @@ CHyprError::CHyprError() {
|
||||
m_fFadeOpacity.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), nullptr, AVARDAMAGE_NONE);
|
||||
m_fFadeOpacity.registerVar();
|
||||
|
||||
g_pHookSystem->hookDynamic("focusedMon", [&](void* self, std::any param) {
|
||||
g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) {
|
||||
if (!m_bIsCreated)
|
||||
return;
|
||||
|
||||
@@ -13,7 +13,7 @@ CHyprError::CHyprError() {
|
||||
m_bMonitorChanged = true;
|
||||
});
|
||||
|
||||
g_pHookSystem->hookDynamic("preRender", [&](void* self, std::any param) {
|
||||
g_pHookSystem->hookDynamic("preRender", [&](void* self, SCallbackInfo& info, std::any param) {
|
||||
if (!m_bIsCreated)
|
||||
return;
|
||||
|
||||
@@ -154,7 +154,7 @@ void CHyprError::draw() {
|
||||
|
||||
const auto PMONITOR = g_pHyprOpenGL->m_RenderData.pMonitor;
|
||||
|
||||
wlr_box monbox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||
CBox monbox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||
|
||||
m_bDamageBox.x = (int)PMONITOR->vecPosition.x;
|
||||
m_bDamageBox.y = (int)PMONITOR->vecPosition.y;
|
||||
|
@@ -23,7 +23,7 @@ class CHyprError {
|
||||
bool m_bIsCreated = false;
|
||||
CTexture m_tTexture;
|
||||
CAnimatedVariable m_fFadeOpacity;
|
||||
wlr_box m_bDamageBox = {0, 0, 0, 0};
|
||||
CBox m_bDamageBox = {0, 0, 0, 0};
|
||||
|
||||
bool m_bMonitorChanged = false;
|
||||
};
|
||||
|
@@ -47,7 +47,6 @@ extern "C" {
|
||||
#include <wlr/types/wlr_export_dmabuf_v1.h>
|
||||
#include <wlr/types/wlr_linux_dmabuf_v1.h>
|
||||
#include <wlr/types/wlr_gamma_control_v1.h>
|
||||
#include <wlr/types/wlr_idle.h>
|
||||
#include <wlr/types/wlr_input_device.h>
|
||||
#include <wlr/types/wlr_keyboard.h>
|
||||
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||
@@ -106,6 +105,7 @@ extern "C" {
|
||||
#include <wlr/types/wlr_idle_notify_v1.h>
|
||||
#include <wlr/types/wlr_cursor_shape_v1.h>
|
||||
#include <wlr/types/wlr_tearing_control_v1.h>
|
||||
#include <wlr/util/box.h>
|
||||
|
||||
#include <libdrm/drm_fourcc.h>
|
||||
|
||||
@@ -146,3 +146,5 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include "helpers/Vector2D.hpp"
|
||||
#include "helpers/Box.hpp"
|
||||
#include "SharedDefs.hpp"
|
||||
|
@@ -9,7 +9,7 @@ void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverrid
|
||||
static auto* const PFLMULT = &g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier")->floatValue;
|
||||
|
||||
if (*PPRESERVESPLIT == 0 && *PSMARTSPLIT == 0) {
|
||||
splitTop = size.y * *PFLMULT > size.x;
|
||||
splitTop = box.h * *PFLMULT > box.w;
|
||||
}
|
||||
|
||||
if (verticalOverride == true)
|
||||
@@ -21,18 +21,14 @@ void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverrid
|
||||
|
||||
if (SPLITSIDE) {
|
||||
// split left/right
|
||||
int const FIRSTSIZE = std::round(size.x / 2 * splitRatio);
|
||||
children[0]->position = position;
|
||||
children[0]->size = Vector2D(FIRSTSIZE, size.y);
|
||||
children[1]->position = Vector2D(position.x + FIRSTSIZE, position.y);
|
||||
children[1]->size = Vector2D(size.x - FIRSTSIZE, size.y);
|
||||
const float FIRSTSIZE = box.w / 2.0 * splitRatio;
|
||||
children[0]->box = CBox{box.x, box.y, FIRSTSIZE, box.h};
|
||||
children[1]->box = CBox{box.x + FIRSTSIZE, box.y, box.w - FIRSTSIZE, box.h};
|
||||
} else {
|
||||
// split top/bottom
|
||||
int const FIRSTSIZE = std::round(size.y / 2 * splitRatio);
|
||||
children[0]->position = position;
|
||||
children[0]->size = Vector2D(size.x, FIRSTSIZE);
|
||||
children[1]->position = Vector2D(position.x, position.y + FIRSTSIZE);
|
||||
children[1]->size = Vector2D(size.x, size.y - FIRSTSIZE);
|
||||
const float FIRSTSIZE = box.h / 2.0 * splitRatio;
|
||||
children[0]->box = CBox{box.x, box.y, box.w, FIRSTSIZE};
|
||||
children[1]->box = CBox{box.x, box.y + FIRSTSIZE, box.w, box.h - FIRSTSIZE};
|
||||
}
|
||||
|
||||
children[0]->recalcSizePosRecursive(force);
|
||||
@@ -109,16 +105,19 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||
}
|
||||
|
||||
// for gaps outer
|
||||
const bool DISPLAYLEFT = STICKS(pNode->position.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
|
||||
const bool DISPLAYRIGHT = STICKS(pNode->position.x + pNode->size.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
|
||||
const bool DISPLAYTOP = STICKS(pNode->position.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
|
||||
const bool DISPLAYBOTTOM = STICKS(pNode->position.y + pNode->size.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
|
||||
const bool DISPLAYLEFT = STICKS(pNode->box.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
|
||||
const bool DISPLAYRIGHT = STICKS(pNode->box.x + pNode->box.w, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
|
||||
const bool DISPLAYTOP = STICKS(pNode->box.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
|
||||
const bool DISPLAYBOTTOM = STICKS(pNode->box.y + pNode->box.h, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
|
||||
|
||||
const auto PWINDOW = pNode->pWindow;
|
||||
// get specific gaps and rules for this workspace,
|
||||
// if user specified them in config
|
||||
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID));
|
||||
|
||||
if (PWINDOW->m_bIsFullscreen && !pNode->ignoreFullscreenChecks)
|
||||
return;
|
||||
|
||||
PWINDOW->updateSpecialRenderData();
|
||||
|
||||
static auto* const PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue;
|
||||
@@ -134,8 +133,11 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||
return;
|
||||
}
|
||||
|
||||
PWINDOW->m_vSize = pNode->size;
|
||||
PWINDOW->m_vPosition = pNode->position;
|
||||
CBox nodeBox = pNode->box;
|
||||
nodeBox.round();
|
||||
|
||||
PWINDOW->m_vSize = nodeBox.size();
|
||||
PWINDOW->m_vPosition = nodeBox.pos();
|
||||
|
||||
const auto NODESONWORKSPACE = getNodesOnWorkspace(PWINDOW->m_iWorkspaceID);
|
||||
|
||||
@@ -156,6 +158,8 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||
|
||||
PWINDOW->updateWindowDecos();
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -203,10 +207,13 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||
// if special, we adjust the coords a bit
|
||||
static auto* const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("dwindle:special_scale_factor")->floatValue;
|
||||
|
||||
PWINDOW->m_vRealPosition = calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f;
|
||||
PWINDOW->m_vRealSize = calcSize * *PSCALEFACTOR;
|
||||
CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR};
|
||||
wb.round(); // avoid rounding mess
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * *PSCALEFACTOR);
|
||||
PWINDOW->m_vRealPosition = wb.pos();
|
||||
PWINDOW->m_vRealSize = wb.size();
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
|
||||
} else {
|
||||
PWINDOW->m_vRealSize = calcSize;
|
||||
PWINDOW->m_vRealPosition = calcPos;
|
||||
@@ -281,7 +288,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
}
|
||||
|
||||
// first, check if OPENINGON isn't too big.
|
||||
const auto PREDSIZEMAX = OPENINGON ? Vector2D(OPENINGON->size.x, OPENINGON->size.y) : PMONITOR->vecSize;
|
||||
const auto PREDSIZEMAX = OPENINGON ? Vector2D(OPENINGON->box.w, OPENINGON->box.h) : PMONITOR->vecSize;
|
||||
if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); MAXSIZE.x < PREDSIZEMAX.x || MAXSIZE.y < PREDSIZEMAX.y) {
|
||||
// we can't continue. make it floating.
|
||||
pWindow->m_bIsFloating = true;
|
||||
@@ -302,8 +309,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
|
||||
// if it's the first, it's easy. Make it fullscreen.
|
||||
if (!OPENINGON || OPENINGON->pWindow == pWindow) {
|
||||
PNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
PNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
PNODE->box = CBox{PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft, PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight};
|
||||
|
||||
applyNodeDataToWindow(PNODE);
|
||||
|
||||
@@ -312,33 +318,29 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_vOverrideFocalPoint && g_pInputManager->m_bWasDraggingWindow) {
|
||||
for (auto& wd : OPENINGON->pWindow->m_dWindowDecorations) {
|
||||
if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT))
|
||||
continue;
|
||||
|
||||
if (wd->getWindowDecorationRegion().containsPoint(MOUSECOORDS)) {
|
||||
if (!wd->onEndWindowDragOnDeco(pWindow, MOUSECOORDS))
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if it's a group, add the window
|
||||
if (OPENINGON->pWindow->m_sGroupData.pNextWindow // target is group
|
||||
&& !g_pKeybindManager->m_bGroupsLocked // global group lock disengaged
|
||||
&& ((pWindow->m_eGroupRules & GROUP_INVADE && pWindow->m_bFirstMap) // window ignore local group locks, or
|
||||
|| (!OPENINGON->pWindow->getGroupHead()->m_sGroupData.locked // target unlocked
|
||||
&& !(pWindow->m_sGroupData.pNextWindow && pWindow->getGroupHead()->m_sGroupData.locked))) // source unlocked or isn't group
|
||||
&& !pWindow->m_sGroupData.deny // source is not denied entry
|
||||
&& !(pWindow->m_eGroupRules & GROUP_BARRED && pWindow->m_bFirstMap) // group rule doesn't prevent adding window
|
||||
&& !m_vOverrideFocalPoint // we are not moving window
|
||||
) {
|
||||
if (OPENINGON->pWindow->m_sGroupData.pNextWindow // target is group
|
||||
&& pWindow->canBeGroupedInto(OPENINGON->pWindow) && !m_vOverrideFocalPoint) { // we are not moving window
|
||||
if (!pWindow->m_sGroupData.pNextWindow)
|
||||
pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||
|
||||
m_lDwindleNodesData.remove(*PNODE);
|
||||
|
||||
const wlr_box box = OPENINGON->pWindow->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents();
|
||||
if (wlr_box_contains_point(&box, MOUSECOORDS.x, MOUSECOORDS.y)) { // TODO: Deny when not using mouse
|
||||
const int SIZE = OPENINGON->pWindow->getGroupSize();
|
||||
const int INDEX = (int)((MOUSECOORDS.x - box.x) * 2 * SIZE / box.width + 1) / 2 - 1;
|
||||
CWindow* pWindowInsertAfter = OPENINGON->pWindow->getGroupWindowByIndex(INDEX);
|
||||
pWindowInsertAfter->insertWindowToGroup(pWindow);
|
||||
if (INDEX == -1)
|
||||
std::swap(pWindow->m_sGroupData.pNextWindow->m_sGroupData.head, pWindow->m_sGroupData.head);
|
||||
} else {
|
||||
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue;
|
||||
(*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow);
|
||||
}
|
||||
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue;
|
||||
(*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow);
|
||||
|
||||
OPENINGON->pWindow->setGroupCurrent(pWindow);
|
||||
pWindow->applyGroupRules();
|
||||
@@ -354,8 +356,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
const auto NEWPARENT = &m_lDwindleNodesData.back();
|
||||
|
||||
// make the parent have the OPENINGON's stats
|
||||
NEWPARENT->position = OPENINGON->position;
|
||||
NEWPARENT->size = OPENINGON->size;
|
||||
NEWPARENT->box = OPENINGON->box;
|
||||
NEWPARENT->workspaceID = OPENINGON->workspaceID;
|
||||
NEWPARENT->pParent = OPENINGON->pParent;
|
||||
NEWPARENT->isNode = true; // it is a node
|
||||
@@ -364,7 +365,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
const auto PWIDTHMULTIPLIER = &g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier")->floatValue;
|
||||
|
||||
// if cursor over first child, make it first, etc
|
||||
const auto SIDEBYSIDE = NEWPARENT->size.x > NEWPARENT->size.y * *PWIDTHMULTIPLIER;
|
||||
const auto SIDEBYSIDE = NEWPARENT->box.w > NEWPARENT->box.h * *PWIDTHMULTIPLIER;
|
||||
NEWPARENT->splitTop = !SIDEBYSIDE;
|
||||
|
||||
static auto* const PFORCESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:force_split")->intValue;
|
||||
@@ -396,11 +397,11 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
if (*PERMANENTDIRECTIONOVERRIDE == 0)
|
||||
overrideDirection = DIRECTION_DEFAULT;
|
||||
} else if (*PSMARTSPLIT == 1) {
|
||||
const auto tl = NEWPARENT->position;
|
||||
const auto tr = NEWPARENT->position + Vector2D(NEWPARENT->size.x, 0);
|
||||
const auto bl = NEWPARENT->position + Vector2D(0, NEWPARENT->size.y);
|
||||
const auto br = NEWPARENT->position + NEWPARENT->size;
|
||||
const auto cc = NEWPARENT->position + NEWPARENT->size / 2;
|
||||
const auto tl = NEWPARENT->box.pos();
|
||||
const auto tr = NEWPARENT->box.pos() + Vector2D(NEWPARENT->box.w, 0);
|
||||
const auto bl = NEWPARENT->box.pos() + Vector2D(0, NEWPARENT->box.h);
|
||||
const auto br = NEWPARENT->box.pos() + NEWPARENT->box.size();
|
||||
const auto cc = NEWPARENT->box.pos() + NEWPARENT->box.size() / 2;
|
||||
|
||||
if (MOUSECOORDS.inTriangle(tl, tr, cc)) {
|
||||
NEWPARENT->splitTop = true;
|
||||
@@ -421,11 +422,9 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
}
|
||||
} else if (*PFORCESPLIT == 0 || !pWindow->m_bFirstMap) {
|
||||
if ((SIDEBYSIDE &&
|
||||
VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / *PWIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x / 2.f,
|
||||
NEWPARENT->position.y + NEWPARENT->size.y)) ||
|
||||
VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y + NEWPARENT->box.h)) ||
|
||||
(!SIDEBYSIDE &&
|
||||
VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / *PWIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x,
|
||||
NEWPARENT->position.y + NEWPARENT->size.y / 2.f))) {
|
||||
VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w, NEWPARENT->box.y + NEWPARENT->box.h / 2.f))) {
|
||||
// we are hovering over the first node, make PNODE first.
|
||||
NEWPARENT->children[1] = OPENINGON;
|
||||
NEWPARENT->children[0] = PNODE;
|
||||
@@ -454,18 +453,14 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
}
|
||||
|
||||
// Update the children
|
||||
if (!verticalOverride && (NEWPARENT->size.x * *PWIDTHMULTIPLIER > NEWPARENT->size.y || horizontalOverride)) {
|
||||
if (!verticalOverride && (NEWPARENT->box.w * *PWIDTHMULTIPLIER > NEWPARENT->box.h || horizontalOverride)) {
|
||||
// split left/right -> forced
|
||||
OPENINGON->position = NEWPARENT->position;
|
||||
OPENINGON->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y);
|
||||
PNODE->position = Vector2D(NEWPARENT->position.x + NEWPARENT->size.x / 2.f, NEWPARENT->position.y);
|
||||
PNODE->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y);
|
||||
OPENINGON->box = {NEWPARENT->box.pos(), Vector2D(NEWPARENT->box.w / 2.f, NEWPARENT->box.h)};
|
||||
PNODE->box = {Vector2D(NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y), Vector2D(NEWPARENT->box.w / 2.f, NEWPARENT->box.h)};
|
||||
} else {
|
||||
// split top/bottom
|
||||
OPENINGON->position = NEWPARENT->position;
|
||||
OPENINGON->size = Vector2D(NEWPARENT->size.x, NEWPARENT->size.y / 2.f);
|
||||
PNODE->position = Vector2D(NEWPARENT->position.x, NEWPARENT->position.y + NEWPARENT->size.y / 2.f);
|
||||
PNODE->size = Vector2D(NEWPARENT->size.x, NEWPARENT->size.y / 2.f);
|
||||
OPENINGON->box = {NEWPARENT->box.pos(), Vector2D(NEWPARENT->box.w, NEWPARENT->box.h / 2.f)};
|
||||
PNODE->box = {Vector2D(NEWPARENT->box.x, NEWPARENT->box.y + NEWPARENT->box.h / 2.f), Vector2D(NEWPARENT->box.w, NEWPARENT->box.h / 2.f)};
|
||||
}
|
||||
|
||||
OPENINGON->pParent = NEWPARENT;
|
||||
@@ -502,9 +497,8 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||
|
||||
const auto PSIBLING = PPARENT->children[0] == PNODE ? PPARENT->children[1] : PPARENT->children[0];
|
||||
|
||||
PSIBLING->position = PPARENT->position;
|
||||
PSIBLING->size = PPARENT->size;
|
||||
PSIBLING->pParent = PPARENT->pParent;
|
||||
PSIBLING->box = PPARENT->box;
|
||||
PSIBLING->pParent = PPARENT->pParent;
|
||||
|
||||
if (PPARENT->pParent != nullptr) {
|
||||
if (PPARENT->pParent->children[0] == PPARENT) {
|
||||
@@ -543,8 +537,7 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
|
||||
const auto TOPNODE = getMasterNodeOnWorkspace(PMONITOR->specialWorkspaceID);
|
||||
|
||||
if (TOPNODE && PMONITOR) {
|
||||
TOPNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
TOPNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
TOPNODE->box = {PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft, PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight};
|
||||
TOPNODE->recalcSizePosRecursive();
|
||||
}
|
||||
}
|
||||
@@ -559,11 +552,11 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
|
||||
} else if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) {
|
||||
SDwindleNodeData fakeNode;
|
||||
fakeNode.pWindow = PFULLWINDOW;
|
||||
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
fakeNode.box = {PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft, PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight};
|
||||
fakeNode.workspaceID = PWORKSPACE->m_iID;
|
||||
PFULLWINDOW->m_vPosition = fakeNode.position;
|
||||
PFULLWINDOW->m_vSize = fakeNode.size;
|
||||
PFULLWINDOW->m_vPosition = fakeNode.box.pos();
|
||||
PFULLWINDOW->m_vSize = fakeNode.box.size();
|
||||
fakeNode.ignoreFullscreenChecks = true;
|
||||
|
||||
applyNodeDataToWindow(&fakeNode);
|
||||
}
|
||||
@@ -574,8 +567,7 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
|
||||
const auto TOPNODE = getMasterNodeOnWorkspace(PMONITOR->activeWorkspace);
|
||||
|
||||
if (TOPNODE && PMONITOR) {
|
||||
TOPNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
TOPNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
TOPNODE->box = {PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft, PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight};
|
||||
TOPNODE->recalcSizePosRecursive();
|
||||
}
|
||||
}
|
||||
@@ -620,7 +612,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
m_PseudoDragFlags.started = true;
|
||||
|
||||
const auto pseudoSize = PWINDOW->m_vRealSize.goalv();
|
||||
const auto mouseOffset = g_pInputManager->getMouseCoordsInternal() - (PNODE->position + ((PNODE->size / 2) - (pseudoSize / 2)));
|
||||
const auto mouseOffset = g_pInputManager->getMouseCoordsInternal() - (PNODE->box.pos() + ((PNODE->box.size() / 2) - (pseudoSize / 2)));
|
||||
|
||||
if (mouseOffset.x > 0 && mouseOffset.x < pseudoSize.x && mouseOffset.y > 0 && mouseOffset.y < pseudoSize.y) {
|
||||
m_PseudoDragFlags.pseudo = true;
|
||||
@@ -643,8 +635,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
else
|
||||
PWINDOW->m_vPseudoSize.y -= pixResize.y * 2;
|
||||
|
||||
PWINDOW->m_vPseudoSize.x = std::clamp(PWINDOW->m_vPseudoSize.x, 30.0, PNODE->size.x);
|
||||
PWINDOW->m_vPseudoSize.y = std::clamp(PWINDOW->m_vPseudoSize.y, 30.0, PNODE->size.y);
|
||||
PWINDOW->m_vPseudoSize.x = std::clamp(PWINDOW->m_vPseudoSize.x, 30.0, PNODE->box.w);
|
||||
PWINDOW->m_vPseudoSize.y = std::clamp(PWINDOW->m_vPseudoSize.y, 30.0, PNODE->box.h);
|
||||
|
||||
PWINDOW->m_vLastFloatingSize = PWINDOW->m_vPseudoSize;
|
||||
PNODE->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
@@ -691,30 +683,30 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
}
|
||||
|
||||
if (PHOUTER) {
|
||||
PHOUTER->pParent->splitRatio = std::clamp(PHOUTER->pParent->splitRatio + allowedMovement.x * 2.f / PHOUTER->pParent->size.x, 0.1, 1.9);
|
||||
PHOUTER->pParent->splitRatio = std::clamp(PHOUTER->pParent->splitRatio + allowedMovement.x * 2.f / PHOUTER->pParent->box.w, 0.1, 1.9);
|
||||
|
||||
if (PHINNER) {
|
||||
const auto ORIGINAL = PHINNER->size.x;
|
||||
const auto ORIGINAL = PHINNER->box.w;
|
||||
PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
if (PHINNER->pParent->children[0] == PHINNER)
|
||||
PHINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.x) / PHINNER->pParent->size.x * 2.f, 0.1, 1.9);
|
||||
PHINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.x) / PHINNER->pParent->box.w * 2.f, 0.1, 1.9);
|
||||
else
|
||||
PHINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.x) / PHINNER->pParent->size.x * 2.f, 0.1, 1.9);
|
||||
PHINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.x) / PHINNER->pParent->box.w * 2.f, 0.1, 1.9);
|
||||
PHINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
} else
|
||||
PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
}
|
||||
|
||||
if (PVOUTER) {
|
||||
PVOUTER->pParent->splitRatio = std::clamp(PVOUTER->pParent->splitRatio + allowedMovement.y * 2.f / PVOUTER->pParent->size.y, 0.1, 1.9);
|
||||
PVOUTER->pParent->splitRatio = std::clamp(PVOUTER->pParent->splitRatio + allowedMovement.y * 2.f / PVOUTER->pParent->box.h, 0.1, 1.9);
|
||||
|
||||
if (PVINNER) {
|
||||
const auto ORIGINAL = PVINNER->size.y;
|
||||
const auto ORIGINAL = PVINNER->box.h;
|
||||
PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
if (PVINNER->pParent->children[0] == PVINNER)
|
||||
PVINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.y) / PVINNER->pParent->size.y * 2.f, 0.1, 1.9);
|
||||
PVINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.y) / PVINNER->pParent->box.h * 2.f, 0.1, 1.9);
|
||||
else
|
||||
PVINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.y) / PVINNER->pParent->size.y * 2.f, 0.1, 1.9);
|
||||
PVINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.y) / PVINNER->pParent->box.h * 2.f, 0.1, 1.9);
|
||||
PVINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
} else
|
||||
PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
@@ -734,11 +726,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
// No parent means we have only 2 windows, and thus one axis of freedom
|
||||
if (!PPARENT2) {
|
||||
if (PARENTSIDEBYSIDE) {
|
||||
allowedMovement.x *= 2.f / PPARENT->size.x;
|
||||
allowedMovement.x *= 2.f / PPARENT->box.w;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
} else {
|
||||
allowedMovement.y *= 2.f / PPARENT->size.y;
|
||||
allowedMovement.y *= 2.f / PPARENT->box.h;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
}
|
||||
@@ -753,11 +745,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
// no parent, one axis of freedom
|
||||
if (!PPARENT2) {
|
||||
if (PARENTSIDEBYSIDE) {
|
||||
allowedMovement.x *= 2.f / PPARENT->size.x;
|
||||
allowedMovement.x *= 2.f / PPARENT->box.w;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
} else {
|
||||
allowedMovement.y *= 2.f / PPARENT->size.y;
|
||||
allowedMovement.y *= 2.f / PPARENT->box.h;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
}
|
||||
@@ -769,8 +761,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
const auto SIDECONTAINER = PARENTSIDEBYSIDE ? PPARENT : PPARENT2;
|
||||
const auto TOPCONTAINER = PARENTSIDEBYSIDE ? PPARENT2 : PPARENT;
|
||||
|
||||
allowedMovement.x *= 2.f / SIDECONTAINER->size.x;
|
||||
allowedMovement.y *= 2.f / TOPCONTAINER->size.y;
|
||||
allowedMovement.x *= 2.f / SIDECONTAINER->box.w;
|
||||
allowedMovement.y *= 2.f / TOPCONTAINER->box.h;
|
||||
|
||||
SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||
TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||
@@ -838,11 +830,10 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
|
||||
|
||||
SDwindleNodeData fakeNode;
|
||||
fakeNode.pWindow = pWindow;
|
||||
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
fakeNode.box = {PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft, PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight};
|
||||
fakeNode.workspaceID = pWindow->m_iWorkspaceID;
|
||||
pWindow->m_vPosition = fakeNode.position;
|
||||
pWindow->m_vSize = fakeNode.size;
|
||||
pWindow->m_vPosition = fakeNode.box.pos();
|
||||
pWindow->m_vSize = fakeNode.box.size();
|
||||
|
||||
applyNodeDataToWindow(&fakeNode);
|
||||
}
|
||||
@@ -954,17 +945,15 @@ void CHyprDwindleLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
|
||||
}
|
||||
|
||||
if (ACTIVE1) {
|
||||
ACTIVE1->position = PNODE->position;
|
||||
ACTIVE1->size = PNODE->size;
|
||||
ACTIVE1->pWindow->m_vPosition = ACTIVE1->position;
|
||||
ACTIVE1->pWindow->m_vSize = ACTIVE1->size;
|
||||
ACTIVE1->box = PNODE->box;
|
||||
ACTIVE1->pWindow->m_vPosition = ACTIVE1->box.pos();
|
||||
ACTIVE1->pWindow->m_vSize = ACTIVE1->box.size();
|
||||
}
|
||||
|
||||
if (ACTIVE2) {
|
||||
ACTIVE2->position = PNODE2->position;
|
||||
ACTIVE2->size = PNODE2->size;
|
||||
ACTIVE2->pWindow->m_vPosition = ACTIVE2->position;
|
||||
ACTIVE2->pWindow->m_vSize = ACTIVE2->size;
|
||||
ACTIVE2->box = PNODE2->box;
|
||||
ACTIVE2->pWindow->m_vPosition = ACTIVE2->box.pos();
|
||||
ACTIVE2->pWindow->m_vSize = ACTIVE2->box.size();
|
||||
}
|
||||
|
||||
g_pHyprRenderer->damageWindow(pWindow);
|
||||
|
@@ -21,8 +21,7 @@ struct SDwindleNodeData {
|
||||
|
||||
bool splitTop = false; // for preserve_split
|
||||
|
||||
Vector2D position;
|
||||
Vector2D size;
|
||||
CBox box = {0};
|
||||
|
||||
int workspaceID = -1;
|
||||
|
||||
@@ -30,10 +29,12 @@ struct SDwindleNodeData {
|
||||
|
||||
bool valid = true;
|
||||
|
||||
bool ignoreFullscreenChecks = false;
|
||||
|
||||
// For list lookup
|
||||
bool operator==(const SDwindleNodeData& rhs) const {
|
||||
return pWindow == rhs.pWindow && workspaceID == rhs.workspaceID && position == rhs.position && size == rhs.size && pParent == rhs.pParent &&
|
||||
children[0] == rhs.children[0] && children[1] == rhs.children[1];
|
||||
return pWindow == rhs.pWindow && workspaceID == rhs.workspaceID && box == rhs.box && pParent == rhs.pParent && children[0] == rhs.children[0] &&
|
||||
children[1] == rhs.children[1];
|
||||
}
|
||||
|
||||
void recalcSizePosRecursive(bool force = false, bool horizontalOverride = false, bool verticalOverride = false);
|
||||
@@ -94,7 +95,7 @@ struct std::formatter<SDwindleNodeData*, CharT> : std::formatter<CharT> {
|
||||
auto out = ctx.out();
|
||||
if (!node)
|
||||
return std::format_to(out, "[Node nullptr]");
|
||||
std::format_to(out, "[Node {:x}: workspace: {}, pos: {:j2}, size: {:j2}", (uintptr_t)node, node->workspaceID, node->position, node->size);
|
||||
std::format_to(out, "[Node {:x}: workspace: {}, pos: {:j2}, size: {:j2}", (uintptr_t)node, node->workspaceID, node->box.pos(), node->box.size());
|
||||
if (!node->isNode && node->pWindow)
|
||||
std::format_to(out, ", window: {:x}", node->pWindow);
|
||||
return std::format_to(out, "]");
|
||||
|
@@ -6,7 +6,7 @@ void IHyprLayout::onWindowCreated(CWindow* pWindow, eDirection direction) {
|
||||
if (pWindow->m_bIsFloating) {
|
||||
onWindowCreatedFloating(pWindow);
|
||||
} else {
|
||||
wlr_box desiredGeometry = {0};
|
||||
CBox desiredGeometry = {};
|
||||
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
|
||||
|
||||
if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
|
||||
@@ -75,7 +75,7 @@ void IHyprLayout::onWindowRemovedFloating(CWindow* pWindow) {
|
||||
|
||||
void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||
|
||||
wlr_box desiredGeometry = {0};
|
||||
CBox desiredGeometry = {0};
|
||||
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
@@ -162,7 +162,8 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
|
||||
|
||||
g_pCompositor->changeWindowZOrder(pWindow, true);
|
||||
}
|
||||
} else
|
||||
pWindow->m_vPendingReportedSize = pWindow->m_vRealSize.goalv();
|
||||
}
|
||||
|
||||
void IHyprLayout::onBeginDragWindow() {
|
||||
@@ -254,6 +255,7 @@ void IHyprLayout::onEndDragWindow() {
|
||||
g_pInputManager->unsetCursorImage();
|
||||
|
||||
g_pInputManager->currentlyDraggedWindow = nullptr;
|
||||
g_pInputManager->m_bWasDraggingWindow = true;
|
||||
|
||||
if (DRAGGINGWINDOW->m_bDraggingTiled) {
|
||||
DRAGGINGWINDOW->m_bIsFloating = false;
|
||||
@@ -265,6 +267,8 @@ void IHyprLayout::onEndDragWindow() {
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
|
||||
g_pCompositor->focusWindow(DRAGGINGWINDOW);
|
||||
|
||||
g_pInputManager->m_bWasDraggingWindow = false;
|
||||
}
|
||||
|
||||
void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
@@ -301,11 +305,13 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
|
||||
if (g_pInputManager->dragMode == MBIND_MOVE) {
|
||||
|
||||
if (*PANIMATEMOUSE) {
|
||||
DRAGGINGWINDOW->m_vRealPosition = m_vBeginDragPositionXY + DELTA;
|
||||
} else {
|
||||
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(m_vBeginDragPositionXY + DELTA);
|
||||
}
|
||||
CBox wb = {m_vBeginDragPositionXY + DELTA, DRAGGINGWINDOW->m_vRealSize.goalv()};
|
||||
wb.round();
|
||||
|
||||
if (*PANIMATEMOUSE)
|
||||
DRAGGINGWINDOW->m_vRealPosition = wb.pos();
|
||||
else
|
||||
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos());
|
||||
|
||||
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
|
||||
} else if (g_pInputManager->dragMode == MBIND_RESIZE || g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) {
|
||||
@@ -357,12 +363,15 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
else if (m_eGrabbedCorner == CORNER_BOTTOMLEFT)
|
||||
newPos = newPos + Vector2D((m_vBeginDragSizeXY - newSize).x, 0);
|
||||
|
||||
CBox wb = {newPos, newSize};
|
||||
wb.round();
|
||||
|
||||
if (*PANIMATE) {
|
||||
DRAGGINGWINDOW->m_vRealSize = newSize;
|
||||
DRAGGINGWINDOW->m_vRealPosition = newPos;
|
||||
DRAGGINGWINDOW->m_vRealSize = wb.size();
|
||||
DRAGGINGWINDOW->m_vRealPosition = wb.pos();
|
||||
} else {
|
||||
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(newSize);
|
||||
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(newPos);
|
||||
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(wb.size());
|
||||
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos());
|
||||
}
|
||||
|
||||
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
|
||||
|
@@ -94,33 +94,30 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc
|
||||
|
||||
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
|
||||
|
||||
if (g_pInputManager->m_bWasDraggingWindow && OPENINGON) {
|
||||
for (auto& wd : OPENINGON->pWindow->m_dWindowDecorations) {
|
||||
if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT))
|
||||
continue;
|
||||
|
||||
if (wd->getWindowDecorationRegion().containsPoint(MOUSECOORDS)) {
|
||||
if (!wd->onEndWindowDragOnDeco(pWindow, MOUSECOORDS))
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if it's a group, add the window
|
||||
if (OPENINGON && OPENINGON != PNODE && OPENINGON->pWindow->m_sGroupData.pNextWindow // target is group
|
||||
&& !g_pKeybindManager->m_bGroupsLocked // global group lock disengaged
|
||||
&& ((pWindow->m_eGroupRules & GROUP_INVADE && pWindow->m_bFirstMap) // window ignore local group locks, or
|
||||
|| (!OPENINGON->pWindow->getGroupHead()->m_sGroupData.locked // target unlocked
|
||||
&& !(pWindow->m_sGroupData.pNextWindow && pWindow->getGroupHead()->m_sGroupData.locked))) // source unlocked or isn't group
|
||||
&& !pWindow->m_sGroupData.deny // source is not denied entry
|
||||
&& !(pWindow->m_eGroupRules & GROUP_BARRED) // group rule doesn't prevent adding window
|
||||
) {
|
||||
if (OPENINGON && OPENINGON != PNODE && OPENINGON->pWindow->m_sGroupData.pNextWindow // target is group
|
||||
&& pWindow->canBeGroupedInto(OPENINGON->pWindow)) {
|
||||
|
||||
if (!pWindow->m_sGroupData.pNextWindow)
|
||||
pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||
|
||||
m_lMasterNodesData.remove(*PNODE);
|
||||
|
||||
const wlr_box box = OPENINGON->pWindow->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents();
|
||||
if (wlr_box_contains_point(&box, MOUSECOORDS.x, MOUSECOORDS.y)) { // TODO: Deny when not using mouse
|
||||
const int SIZE = OPENINGON->pWindow->getGroupSize();
|
||||
const int INDEX = (int)((MOUSECOORDS.x - box.x) * 2 * SIZE / box.width + 1) / 2 - 1;
|
||||
CWindow* pWindowInsertAfter = OPENINGON->pWindow->getGroupWindowByIndex(INDEX);
|
||||
pWindowInsertAfter->insertWindowToGroup(pWindow);
|
||||
if (INDEX == -1)
|
||||
std::swap(pWindow->m_sGroupData.pNextWindow->m_sGroupData.head, pWindow->m_sGroupData.head);
|
||||
} else {
|
||||
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue;
|
||||
(*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow);
|
||||
}
|
||||
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue;
|
||||
(*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow);
|
||||
|
||||
OPENINGON->pWindow->setGroupCurrent(pWindow);
|
||||
pWindow->applyGroupRules();
|
||||
@@ -136,34 +133,67 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc
|
||||
const auto PWORKSPACEDATA = getMasterWorkspaceData(pWindow->m_iWorkspaceID);
|
||||
eOrientation orientation = PWORKSPACEDATA->orientation;
|
||||
const auto NODEIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *PNODE);
|
||||
|
||||
bool forceDropAsMaster = false;
|
||||
// if dragging window to move, drop it at the cursor position instead of bottom/top of stack
|
||||
if (*PDROPATCURSOR && g_pInputManager->dragMode == MBIND_MOVE) {
|
||||
// if dragging window to move, drop it at the cursor position instead of bottom/top of stack
|
||||
for (auto it = m_lMasterNodesData.begin(); it != m_lMasterNodesData.end(); ++it) {
|
||||
if (it->workspaceID != pWindow->m_iWorkspaceID)
|
||||
continue;
|
||||
const wlr_box box = it->pWindow->getWindowIdealBoundingBoxIgnoreReserved();
|
||||
if (wlr_box_contains_point(&box, MOUSECOORDS.x, MOUSECOORDS.y)) { // TODO: Deny when not using mouse
|
||||
switch (orientation) {
|
||||
case ORIENTATION_LEFT:
|
||||
case ORIENTATION_RIGHT:
|
||||
if (MOUSECOORDS.y > it->pWindow->middle().y)
|
||||
++it;
|
||||
break;
|
||||
case ORIENTATION_TOP:
|
||||
case ORIENTATION_BOTTOM:
|
||||
if (MOUSECOORDS.x > it->pWindow->middle().x)
|
||||
++it;
|
||||
break;
|
||||
case ORIENTATION_CENTER: break;
|
||||
default: UNREACHABLE();
|
||||
if (WINDOWSONWORKSPACE > 2) {
|
||||
for (auto it = m_lMasterNodesData.begin(); it != m_lMasterNodesData.end(); ++it) {
|
||||
if (it->workspaceID != pWindow->m_iWorkspaceID)
|
||||
continue;
|
||||
const CBox box = it->pWindow->getWindowIdealBoundingBoxIgnoreReserved();
|
||||
if (box.containsPoint(MOUSECOORDS)) {
|
||||
switch (orientation) {
|
||||
case ORIENTATION_LEFT:
|
||||
case ORIENTATION_RIGHT:
|
||||
if (MOUSECOORDS.y > it->pWindow->middle().y)
|
||||
++it;
|
||||
break;
|
||||
case ORIENTATION_TOP:
|
||||
case ORIENTATION_BOTTOM:
|
||||
if (MOUSECOORDS.x > it->pWindow->middle().x)
|
||||
++it;
|
||||
break;
|
||||
case ORIENTATION_CENTER: break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
m_lMasterNodesData.splice(it, m_lMasterNodesData, NODEIT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (WINDOWSONWORKSPACE == 2) {
|
||||
// when dropping as the second tiled window in the workspace,
|
||||
// make it the master only if the cursor is on the master side of the screen
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
|
||||
switch (orientation) {
|
||||
case ORIENTATION_LEFT:
|
||||
case ORIENTATION_CENTER:
|
||||
if (MOUSECOORDS.x < nd.pWindow->middle().x)
|
||||
forceDropAsMaster = true;
|
||||
break;
|
||||
case ORIENTATION_RIGHT:
|
||||
if (MOUSECOORDS.x > nd.pWindow->middle().x)
|
||||
forceDropAsMaster = true;
|
||||
break;
|
||||
case ORIENTATION_TOP:
|
||||
if (MOUSECOORDS.y < nd.pWindow->middle().y)
|
||||
forceDropAsMaster = true;
|
||||
break;
|
||||
case ORIENTATION_BOTTOM:
|
||||
if (MOUSECOORDS.y > nd.pWindow->middle().y)
|
||||
forceDropAsMaster = true;
|
||||
break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
}
|
||||
m_lMasterNodesData.splice(it, m_lMasterNodesData, NODEIT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*PNEWISMASTER || WINDOWSONWORKSPACE == 1 || (!pWindow->m_bFirstMap && OPENINGON->isMaster)) {
|
||||
if ((*PNEWISMASTER && g_pInputManager->dragMode != MBIND_MOVE) || WINDOWSONWORKSPACE == 1 || (WINDOWSONWORKSPACE > 2 && !pWindow->m_bFirstMap && OPENINGON->isMaster) ||
|
||||
forceDropAsMaster) {
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
|
||||
nd.isMaster = false;
|
||||
@@ -599,6 +629,9 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||
// if user specified them in config
|
||||
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID));
|
||||
|
||||
if (PWINDOW->m_bIsFullscreen && !pNode->ignoreFullscreenChecks)
|
||||
return;
|
||||
|
||||
PWINDOW->updateSpecialRenderData();
|
||||
|
||||
static auto* const PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue;
|
||||
@@ -635,6 +668,8 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||
|
||||
PWINDOW->updateWindowDecos();
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -657,15 +692,21 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||
if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID)) {
|
||||
static auto* const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("master:special_scale_factor")->floatValue;
|
||||
|
||||
PWINDOW->m_vRealPosition = calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f;
|
||||
PWINDOW->m_vRealSize = calcSize * *PSCALEFACTOR;
|
||||
CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR};
|
||||
wb.round(); // avoid rounding mess
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * *PSCALEFACTOR);
|
||||
PWINDOW->m_vRealPosition = wb.pos();
|
||||
PWINDOW->m_vRealSize = wb.size();
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
|
||||
} else {
|
||||
PWINDOW->m_vRealSize = calcSize;
|
||||
PWINDOW->m_vRealPosition = calcPos;
|
||||
CBox wb = {calcPos, calcSize};
|
||||
wb.round(); // avoid rounding mess
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
|
||||
PWINDOW->m_vRealPosition = wb.pos();
|
||||
PWINDOW->m_vRealSize = wb.size();
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
|
||||
}
|
||||
|
||||
if (m_bForceWarps && !*PANIMATE) {
|
||||
@@ -742,8 +783,9 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
|
||||
const auto workspaceIdForResizing = PMONITOR->specialWorkspaceID == 0 ? PMONITOR->activeWorkspace : PMONITOR->specialWorkspaceID;
|
||||
for (auto& n : m_lMasterNodesData) {
|
||||
if (n.isMaster && n.workspaceID == PMONITOR->activeWorkspace)
|
||||
if (n.isMaster && n.workspaceID == workspaceIdForResizing)
|
||||
n.percMaster = std::clamp(n.percMaster + delta, 0.05, 0.95);
|
||||
}
|
||||
|
||||
@@ -884,12 +926,13 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
|
||||
// To keep consistent with the settings without C+P code
|
||||
|
||||
SMasterNodeData fakeNode;
|
||||
fakeNode.pWindow = pWindow;
|
||||
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
fakeNode.workspaceID = pWindow->m_iWorkspaceID;
|
||||
pWindow->m_vPosition = fakeNode.position;
|
||||
pWindow->m_vSize = fakeNode.size;
|
||||
fakeNode.pWindow = pWindow;
|
||||
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
fakeNode.workspaceID = pWindow->m_iWorkspaceID;
|
||||
pWindow->m_vPosition = fakeNode.position;
|
||||
pWindow->m_vSize = fakeNode.size;
|
||||
fakeNode.ignoreFullscreenChecks = true;
|
||||
|
||||
applyNodeDataToWindow(&fakeNode);
|
||||
}
|
||||
@@ -927,7 +970,16 @@ void CHyprMasterLayout::moveWindowTo(CWindow* pWindow, const std::string& dir) {
|
||||
|
||||
const auto PWINDOW2 = g_pCompositor->getWindowInDirection(pWindow, dir[0]);
|
||||
|
||||
switchWindows(pWindow, PWINDOW2);
|
||||
if (pWindow->m_iWorkspaceID != PWINDOW2->m_iWorkspaceID) {
|
||||
// if different monitors, send to monitor
|
||||
onWindowRemovedTiling(pWindow);
|
||||
pWindow->moveToWorkspace(PWINDOW2->m_iWorkspaceID);
|
||||
pWindow->m_iMonitorID = PWINDOW2->m_iMonitorID;
|
||||
onWindowCreatedTiling(pWindow);
|
||||
} else {
|
||||
// if same monitor, switch windows
|
||||
switchWindows(pWindow, PWINDOW2);
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
|
||||
|
@@ -10,8 +10,7 @@
|
||||
enum eFullscreenMode : int8_t;
|
||||
|
||||
//orientation determines which side of the screen the master area resides
|
||||
enum eOrientation : uint8_t
|
||||
{
|
||||
enum eOrientation : uint8_t {
|
||||
ORIENTATION_LEFT = 0,
|
||||
ORIENTATION_TOP,
|
||||
ORIENTATION_RIGHT,
|
||||
@@ -32,7 +31,10 @@ struct SMasterNodeData {
|
||||
|
||||
int workspaceID = -1;
|
||||
|
||||
bool operator==(const SMasterNodeData& rhs) const {
|
||||
bool ignoreFullscreenChecks = false;
|
||||
|
||||
//
|
||||
bool operator==(const SMasterNodeData& rhs) const {
|
||||
return pWindow == rhs.pWindow;
|
||||
}
|
||||
};
|
||||
@@ -41,7 +43,8 @@ struct SMasterWorkspaceData {
|
||||
int workspaceID = -1;
|
||||
eOrientation orientation = ORIENTATION_LEFT;
|
||||
|
||||
bool operator==(const SMasterWorkspaceData& rhs) const {
|
||||
//
|
||||
bool operator==(const SMasterWorkspaceData& rhs) const {
|
||||
return workspaceID == rhs.workspaceID;
|
||||
}
|
||||
};
|
||||
|
@@ -104,6 +104,8 @@ int main(int argc, char** argv) {
|
||||
// If all's good to go, start.
|
||||
g_pCompositor->startCompositor();
|
||||
|
||||
g_pCompositor->m_bIsShuttingDown = true;
|
||||
|
||||
// If we are here it means we got yote.
|
||||
Debug::log(LOG, "Hyprland reached the end.");
|
||||
g_pCompositor.reset();
|
||||
|
@@ -81,7 +81,7 @@ void CAnimationManager::tick() {
|
||||
CMonitor* PMONITOR = nullptr;
|
||||
bool animationsDisabled = animGlobalDisabled;
|
||||
|
||||
wlr_box WLRBOXPREV = {0, 0, 0, 0};
|
||||
CBox WLRBOXPREV = {0, 0, 0, 0};
|
||||
if (PWINDOW) {
|
||||
WLRBOXPREV = PWINDOW->getFullWindowBoundingBox();
|
||||
PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
@@ -236,7 +236,7 @@ void CAnimationManager::tick() {
|
||||
BORDERSIZE + ROUNDINGSIZE); // bottom
|
||||
|
||||
// damage for new box
|
||||
const wlr_box WLRBOXNEW = {PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x, PWINDOW->m_vRealSize.vec().y};
|
||||
const CBox WLRBOXNEW = {PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x, PWINDOW->m_vRealSize.vec().y};
|
||||
g_pHyprRenderer->damageBox(WLRBOXNEW.x - BORDERSIZE, WLRBOXNEW.y - BORDERSIZE, WLRBOXNEW.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // top
|
||||
g_pHyprRenderer->damageBox(WLRBOXNEW.x - BORDERSIZE, WLRBOXNEW.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, WLRBOXNEW.height + 2 * BORDERSIZE); // left
|
||||
g_pHyprRenderer->damageBox(WLRBOXNEW.x + WLRBOXNEW.width - ROUNDINGSIZE, WLRBOXNEW.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE,
|
||||
@@ -255,9 +255,8 @@ void CAnimationManager::tick() {
|
||||
if (PDECO) {
|
||||
const auto EXTENTS = PDECO->getWindowDecorationExtents();
|
||||
|
||||
wlr_box dmg = {PWINDOW->m_vRealPosition.vec().x - EXTENTS.topLeft.x, PWINDOW->m_vRealPosition.vec().y - EXTENTS.topLeft.y,
|
||||
PWINDOW->m_vRealSize.vec().x + EXTENTS.topLeft.x + EXTENTS.bottomRight.x,
|
||||
PWINDOW->m_vRealSize.vec().y + EXTENTS.topLeft.y + EXTENTS.bottomRight.y};
|
||||
CBox dmg = {PWINDOW->m_vRealPosition.vec().x - EXTENTS.topLeft.x, PWINDOW->m_vRealPosition.vec().y - EXTENTS.topLeft.y,
|
||||
PWINDOW->m_vRealSize.vec().x + EXTENTS.topLeft.x + EXTENTS.bottomRight.x, PWINDOW->m_vRealSize.vec().y + EXTENTS.topLeft.y + EXTENTS.bottomRight.y};
|
||||
|
||||
if (!*PSHADOWIGNOREWINDOW) {
|
||||
// easy, damage the entire box
|
||||
|
@@ -26,7 +26,7 @@ void CHookSystemManager::unhook(HOOK_CALLBACK_FN* fn) {
|
||||
}
|
||||
}
|
||||
|
||||
void CHookSystemManager::emit(const std::vector<SCallbackFNPtr>* callbacks, std::any data) {
|
||||
void CHookSystemManager::emit(const std::vector<SCallbackFNPtr>* callbacks, SCallbackInfo& info, std::any data) {
|
||||
if (callbacks->empty())
|
||||
return;
|
||||
|
||||
@@ -38,7 +38,7 @@ void CHookSystemManager::emit(const std::vector<SCallbackFNPtr>* callbacks, std:
|
||||
|
||||
if (!cb.handle) {
|
||||
// we don't guard hl hooks
|
||||
(*cb.fn)(cb.fn, data);
|
||||
(*cb.fn)(cb.fn, info, data);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ void CHookSystemManager::emit(const std::vector<SCallbackFNPtr>* callbacks, std:
|
||||
|
||||
try {
|
||||
if (!setjmp(m_jbHookFaultJumpBuf))
|
||||
(*cb.fn)(cb.fn, data);
|
||||
(*cb.fn)(cb.fn, info, data);
|
||||
else {
|
||||
// this module crashed.
|
||||
throw std::exception();
|
||||
|
@@ -12,7 +12,8 @@
|
||||
#include "../plugins/PluginAPI.hpp"
|
||||
|
||||
// global typedef for hooked functions. Passes itself as a ptr when called, and `data` additionally.
|
||||
typedef std::function<void(void*, std::any)> HOOK_CALLBACK_FN;
|
||||
|
||||
typedef std::function<void(void*, SCallbackInfo& info, std::any data)> HOOK_CALLBACK_FN;
|
||||
|
||||
struct SCallbackFNPtr {
|
||||
HOOK_CALLBACK_FN* fn = nullptr;
|
||||
@@ -22,7 +23,17 @@ struct SCallbackFNPtr {
|
||||
#define EMIT_HOOK_EVENT(name, param) \
|
||||
{ \
|
||||
static auto* const PEVENTVEC = g_pHookSystem->getVecForEvent(name); \
|
||||
g_pHookSystem->emit(PEVENTVEC, param); \
|
||||
SCallbackInfo info; \
|
||||
g_pHookSystem->emit(PEVENTVEC, info, param); \
|
||||
}
|
||||
|
||||
#define EMIT_HOOK_EVENT_CANCELLABLE(name, param) \
|
||||
{ \
|
||||
static auto* const PEVENTVEC = g_pHookSystem->getVecForEvent(name); \
|
||||
SCallbackInfo info; \
|
||||
g_pHookSystem->emit(PEVENTVEC, info, param); \
|
||||
if (info.cancelled) \
|
||||
return; \
|
||||
}
|
||||
|
||||
class CHookSystemManager {
|
||||
@@ -34,7 +45,7 @@ class CHookSystemManager {
|
||||
void hookStatic(const std::string& event, HOOK_CALLBACK_FN* fn, HANDLE handle = nullptr);
|
||||
void unhook(HOOK_CALLBACK_FN* fn);
|
||||
|
||||
void emit(const std::vector<SCallbackFNPtr>* callbacks, std::any data = 0);
|
||||
void emit(const std::vector<SCallbackFNPtr>* callbacks, SCallbackInfo& info, std::any data = 0);
|
||||
std::vector<SCallbackFNPtr>* getVecForEvent(const std::string& event);
|
||||
|
||||
bool m_bCurrentEventPlugin = false;
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#include "KeybindManager.hpp"
|
||||
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
||||
#include "debug/Log.hpp"
|
||||
#include "helpers/VarList.hpp"
|
||||
|
||||
#include <regex>
|
||||
|
||||
@@ -77,7 +79,7 @@ CKeybindManager::CKeybindManager() {
|
||||
|
||||
m_tScrollTimer.reset();
|
||||
|
||||
g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, std::any param) {
|
||||
g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, SCallbackInfo& info, std::any param) {
|
||||
// clear cuz realloc'd
|
||||
m_pActiveKeybind = nullptr;
|
||||
m_vPressedSpecialBinds.clear();
|
||||
@@ -435,7 +437,8 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
|
||||
const bool IGNORECONDITIONS =
|
||||
SPECIALDISPATCHER && !pressed && SPECIALTRIGGERED; // ignore mods. Pass, global dispatchers should be released immediately once the key is released.
|
||||
|
||||
if (!IGNORECONDITIONS && (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || k.shadowed))
|
||||
if (!IGNORECONDITIONS &&
|
||||
((modmask != k.modmask && !k.ignoreMods) || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || k.shadowed))
|
||||
continue;
|
||||
|
||||
if (!key.empty()) {
|
||||
@@ -1001,7 +1004,8 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
||||
}
|
||||
|
||||
void CKeybindManager::moveFocusTo(std::string args) {
|
||||
char arg = args[0];
|
||||
static auto* const PFULLCYCLE = &g_pConfigManager->getConfigValuePtr("binds:movefocus_cycles_fullscreen")->intValue;
|
||||
char arg = args[0];
|
||||
|
||||
if (!isDirection(args)) {
|
||||
Debug::log(ERR, "Cannot move focus in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg);
|
||||
@@ -1017,7 +1021,7 @@ void CKeybindManager::moveFocusTo(std::string args) {
|
||||
// remove constraints
|
||||
g_pInputManager->unconstrainMouse();
|
||||
|
||||
const auto PWINDOWTOCHANGETO = PLASTWINDOW->m_bIsFullscreen ?
|
||||
const auto PWINDOWTOCHANGETO = *PFULLCYCLE && PLASTWINDOW->m_bIsFullscreen ?
|
||||
(arg == 'd' || arg == 'b' || arg == 'r' ? g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true) : g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW, true)) :
|
||||
g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
|
||||
|
||||
@@ -1836,25 +1840,22 @@ void CKeybindManager::mouse(std::string args) {
|
||||
const auto mouseCoords = g_pInputManager->getMouseCoordsInternal();
|
||||
CWindow* pWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
|
||||
|
||||
if (pWindow && !pWindow->m_bIsFullscreen && !pWindow->hasPopupAt(mouseCoords) && pWindow->m_sGroupData.pNextWindow) {
|
||||
const wlr_box box = pWindow->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents();
|
||||
if (wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y)) {
|
||||
const int SIZE = pWindow->getGroupSize();
|
||||
pWindow = pWindow->getGroupWindowByIndex((mouseCoords.x - box.x) * SIZE / box.width);
|
||||
if (pWindow && !pWindow->m_bIsFullscreen && !pWindow->hasPopupAt(mouseCoords)) {
|
||||
for (auto& wd : pWindow->m_dWindowDecorations) {
|
||||
if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT))
|
||||
continue;
|
||||
|
||||
// hack
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow);
|
||||
if (!pWindow->m_bIsFloating) {
|
||||
const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_bGroupsLocked;
|
||||
g_pKeybindManager->m_bGroupsLocked = true;
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(pWindow);
|
||||
g_pKeybindManager->m_bGroupsLocked = GROUPSLOCKEDPREV;
|
||||
if (wd->getWindowDecorationRegion().containsPoint(mouseCoords)) {
|
||||
wd->onBeginWindowDragOnDeco(mouseCoords);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_pInputManager->currentlyDraggedWindow = pWindow;
|
||||
g_pInputManager->dragMode = MBIND_MOVE;
|
||||
if (!g_pInputManager->currentlyDraggedWindow)
|
||||
g_pInputManager->currentlyDraggedWindow = pWindow;
|
||||
|
||||
g_pInputManager->dragMode = MBIND_MOVE;
|
||||
g_pLayoutManager->getCurrentLayout()->onBeginDragWindow();
|
||||
} else {
|
||||
g_pKeybindManager->m_bIsMouseBindActive = false;
|
||||
|
@@ -23,12 +23,14 @@ struct SKeybind {
|
||||
bool mouse = false;
|
||||
bool nonConsuming = false;
|
||||
bool transparent = false;
|
||||
bool ignoreMods = false;
|
||||
|
||||
// DO NOT INITIALIZE
|
||||
bool shadowed = false;
|
||||
};
|
||||
|
||||
enum eFocusWindowMode {
|
||||
enum eFocusWindowMode
|
||||
{
|
||||
MODE_CLASS_REGEX = 0,
|
||||
MODE_TITLE_REGEX,
|
||||
MODE_ADDRESS,
|
||||
|
@@ -74,7 +74,7 @@ void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) {
|
||||
g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID)->m_pLastFocusedWindow = pWindow;
|
||||
}
|
||||
|
||||
void CHyprXWaylandManager::getGeometryForWindow(CWindow* pWindow, wlr_box* pbox) {
|
||||
void CHyprXWaylandManager::getGeometryForWindow(CWindow* pWindow, CBox* pbox) {
|
||||
if (pWindow->m_bIsX11) {
|
||||
const auto SIZEHINTS = pWindow->m_uSurface.xwayland->size_hints;
|
||||
|
||||
@@ -89,8 +89,10 @@ void CHyprXWaylandManager::getGeometryForWindow(CWindow* pWindow, wlr_box* pbox)
|
||||
pbox->width = pWindow->m_uSurface.xwayland->width;
|
||||
pbox->height = pWindow->m_uSurface.xwayland->height;
|
||||
}
|
||||
} else
|
||||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, pbox);
|
||||
} else {
|
||||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, pbox->pWlr());
|
||||
pbox->applyFromWlr();
|
||||
}
|
||||
}
|
||||
|
||||
std::string CHyprXWaylandManager::getTitle(CWindow* pWindow) {
|
||||
@@ -163,8 +165,8 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool f
|
||||
if (!force && ((pWindow->m_vReportedSize == size && windowPos == pWindow->m_vReportedPosition) || (pWindow->m_vReportedSize == size && !pWindow->m_bIsX11)))
|
||||
return;
|
||||
|
||||
pWindow->m_vReportedPosition = windowPos;
|
||||
pWindow->m_vReportedSize = size;
|
||||
pWindow->m_vReportedPosition = windowPos;
|
||||
pWindow->m_vPendingReportedSize = size;
|
||||
|
||||
pWindow->m_fX11SurfaceScaledBy = 1.f;
|
||||
|
||||
|
@@ -15,7 +15,7 @@ class CHyprXWaylandManager {
|
||||
wlr_surface* getWindowSurface(CWindow*);
|
||||
void activateSurface(wlr_surface*, bool);
|
||||
void activateWindow(CWindow*, bool);
|
||||
void getGeometryForWindow(CWindow*, wlr_box*);
|
||||
void getGeometryForWindow(CWindow*, CBox*);
|
||||
std::string getTitle(CWindow*);
|
||||
std::string getAppIDClass(CWindow*);
|
||||
void sendCloseWindow(CWindow*);
|
||||
|
@@ -41,8 +41,6 @@ void CInputManager::simulateMouseMovement() {
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
m_vLastCursorPosFloored = m_vLastCursorPosFloored - Vector2D(1, 1); // hack: force the mouseMoveUnified to report without making this a refocus.
|
||||
mouseMoveUnified(now.tv_sec * 1000 + now.tv_nsec / 10000000);
|
||||
|
||||
m_tmrLastCursorMovement.reset();
|
||||
}
|
||||
|
||||
void CInputManager::sendMotionEventsToFocused() {
|
||||
@@ -67,7 +65,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
static auto* const PMOUSEREFOCUS = &g_pConfigManager->getConfigValuePtr("input:mouse_refocus")->intValue;
|
||||
static auto* const PMOUSEDPMS = &g_pConfigManager->getConfigValuePtr("misc:mouse_move_enables_dpms")->intValue;
|
||||
static auto* const PFOLLOWONDND = &g_pConfigManager->getConfigValuePtr("misc:always_follow_on_dnd")->intValue;
|
||||
static auto* const PHOGFOCUS = &g_pConfigManager->getConfigValuePtr("misc:layers_hog_keyboard_focus")->intValue;
|
||||
static auto* const PFLOATBEHAVIOR = &g_pConfigManager->getConfigValuePtr("input:float_switch_override_focus")->intValue;
|
||||
static auto* const PMOUSEFOCUSMON = &g_pConfigManager->getConfigValuePtr("misc:mouse_move_focuses_monitor")->intValue;
|
||||
static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue;
|
||||
@@ -99,11 +96,11 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored && !refocus)
|
||||
return;
|
||||
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("mouseMove", MOUSECOORDSFLOORED);
|
||||
|
||||
if (time)
|
||||
g_pCompositor->notifyIdleActivity();
|
||||
|
||||
EMIT_HOOK_EVENT("mouseMove", MOUSECOORDSFLOORED);
|
||||
|
||||
m_vLastCursorPosFloored = MOUSECOORDSFLOORED;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
|
||||
@@ -185,7 +182,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
// update stuff
|
||||
updateDragIcon();
|
||||
|
||||
if (!m_sDrag.drag && !m_lCurrentlyHeldButtons.empty() && g_pCompositor->m_pLastFocus) {
|
||||
if (!m_sDrag.drag && !m_lCurrentlyHeldButtons.empty() && g_pCompositor->m_pLastFocus && m_pLastMouseSurface) {
|
||||
if (m_bLastFocusOnLS) {
|
||||
foundSurface = m_pLastMouseSurface;
|
||||
pFoundLayerSurface = g_pCompositor->getLayerSurfaceFromSurface(foundSurface);
|
||||
@@ -304,15 +301,16 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
if (g_pHyprRenderer->m_bHasARenderedCursor) {
|
||||
// TODO: maybe wrap?
|
||||
if (m_ecbClickBehavior == CLICKMODE_KILL)
|
||||
g_pHyprRenderer->setCursorFromName("crosshair");
|
||||
setCursorImageOverride("crosshair");
|
||||
else
|
||||
g_pHyprRenderer->setCursorFromName("left_ptr");
|
||||
setCursorImageOverride("left_ptr");
|
||||
}
|
||||
|
||||
m_bEmptyFocusCursorSet = true;
|
||||
}
|
||||
|
||||
wlr_seat_pointer_clear_focus(g_pCompositor->m_sSeat.seat);
|
||||
m_pLastMouseSurface = nullptr;
|
||||
|
||||
if (refocus || !g_pCompositor->m_pLastWindow) // if we are forcing a refocus, and we don't find a surface, clear the kb focus too!
|
||||
g_pCompositor->focusWindow(nullptr);
|
||||
@@ -337,12 +335,11 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
|
||||
bool allowKeyboardRefocus = true;
|
||||
|
||||
if (*PHOGFOCUS && !refocus && g_pCompositor->m_pLastFocus) {
|
||||
if (!refocus && g_pCompositor->m_pLastFocus) {
|
||||
const auto PLS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus);
|
||||
|
||||
if (PLS && PLS->layerSurface->current.keyboard_interactive) {
|
||||
if (PLS && PLS->layerSurface->current.keyboard_interactive == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE)
|
||||
allowKeyboardRefocus = false;
|
||||
}
|
||||
}
|
||||
|
||||
// set the values for use
|
||||
@@ -358,6 +355,14 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pFoundWindow && foundSurface == pFoundWindow->m_pWLSurface.wlr() && !m_bCursorImageOverridden) {
|
||||
const auto BOX = pFoundWindow->getWindowMainSurfaceBox();
|
||||
if (!VECINRECT(mouseCoords, BOX.x, BOX.y, BOX.x + BOX.width, BOX.y + BOX.height))
|
||||
setCursorImageOverride("left_ptr");
|
||||
else
|
||||
restoreCursorIconToApp();
|
||||
}
|
||||
|
||||
if (pFoundWindow) {
|
||||
// change cursor icon if hovering over border
|
||||
if (*PRESIZEONBORDER && *PRESIZECURSORICON) {
|
||||
@@ -382,11 +387,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
}
|
||||
|
||||
if (pFoundWindow == g_pCompositor->m_pLastWindow) {
|
||||
if (foundSurface != g_pCompositor->m_pLastFocus || m_bLastFocusOnLS) {
|
||||
// ^^^ changed the subsurface ^^^ came back from a LS
|
||||
m_pLastMouseSurface = foundSurface;
|
||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||
}
|
||||
m_pLastMouseSurface = foundSurface;
|
||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||
}
|
||||
|
||||
if (FOLLOWMOUSE != 0 || pFoundWindow == g_pCompositor->m_pLastWindow)
|
||||
@@ -409,7 +411,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
}
|
||||
|
||||
if (pFoundLayerSurface &&
|
||||
(pFoundLayerSurface->layerSurface->current.keyboard_interactive || (pFoundLayerSurface->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP && !g_pCompositor->m_pLastWindow)) &&
|
||||
(pFoundLayerSurface->layerSurface->current.keyboard_interactive != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE ||
|
||||
(pFoundLayerSurface->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP && !g_pCompositor->m_pLastWindow)) &&
|
||||
FOLLOWMOUSE != 3 && allowKeyboardRefocus) {
|
||||
g_pCompositor->focusSurface(foundSurface);
|
||||
}
|
||||
@@ -424,9 +427,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
}
|
||||
|
||||
void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
|
||||
g_pCompositor->notifyIdleActivity();
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("mouseButton", e);
|
||||
|
||||
EMIT_HOOK_EVENT("mouseButton", e);
|
||||
g_pCompositor->notifyIdleActivity();
|
||||
|
||||
m_tmrLastCursorMovement.reset();
|
||||
|
||||
@@ -465,25 +468,65 @@ void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_even
|
||||
if (!cursorImageUnlocked() || !g_pHyprRenderer->m_bHasARenderedCursor)
|
||||
return;
|
||||
|
||||
// cursorSurfaceInfo.pSurface = e->surface;
|
||||
if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) {
|
||||
m_sCursorSurfaceInfo.wlSurface.unassign();
|
||||
|
||||
// if (e->surface) {
|
||||
// hyprListener_CursorSurfaceDestroy.removeCallback();
|
||||
// hyprListener_CursorSurfaceDestroy.initCallback(
|
||||
// &e->surface->events.destroy, [&](void* owner, void* data) { cursorSurfaceInfo.pSurface = nullptr; }, this, "InputManager");
|
||||
// cursorSurfaceInfo.vHotspot = {e->hotspot_x, e->hotspot_y};
|
||||
// }
|
||||
if (e->surface) {
|
||||
m_sCursorSurfaceInfo.wlSurface.assign(e->surface);
|
||||
m_sCursorSurfaceInfo.vHotspot = {e->hotspot_x, e->hotspot_y};
|
||||
m_sCursorSurfaceInfo.hidden = false;
|
||||
} else {
|
||||
m_sCursorSurfaceInfo.vHotspot = {};
|
||||
m_sCursorSurfaceInfo.hidden = true;
|
||||
}
|
||||
|
||||
if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client)
|
||||
m_sCursorSurfaceInfo.name = "";
|
||||
|
||||
m_sCursorSurfaceInfo.inUse = true;
|
||||
g_pHyprRenderer->setCursorSurface(e->surface, e->hotspot_x, e->hotspot_y);
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::processMouseRequest(wlr_cursor_shape_manager_v1_request_set_shape_event* e) {
|
||||
if (!g_pHyprRenderer->m_bHasARenderedCursor || !cursorImageUnlocked())
|
||||
return;
|
||||
|
||||
if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client)
|
||||
g_pHyprRenderer->setCursorFromName(wlr_cursor_shape_v1_name(e->shape));
|
||||
if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) {
|
||||
m_sCursorSurfaceInfo.wlSurface.unassign();
|
||||
m_sCursorSurfaceInfo.vHotspot = {};
|
||||
m_sCursorSurfaceInfo.name = wlr_cursor_shape_v1_name(e->shape);
|
||||
m_sCursorSurfaceInfo.hidden = false;
|
||||
|
||||
m_sCursorSurfaceInfo.inUse = true;
|
||||
g_pHyprRenderer->setCursorFromName(m_sCursorSurfaceInfo.name);
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::restoreCursorIconToApp() {
|
||||
if (m_sCursorSurfaceInfo.inUse)
|
||||
return;
|
||||
|
||||
if (m_sCursorSurfaceInfo.hidden) {
|
||||
g_pHyprRenderer->setCursorSurface(nullptr, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_sCursorSurfaceInfo.name.empty()) {
|
||||
if (m_sCursorSurfaceInfo.wlSurface.exists())
|
||||
g_pHyprRenderer->setCursorSurface(m_sCursorSurfaceInfo.wlSurface.wlr(), m_sCursorSurfaceInfo.vHotspot.x, m_sCursorSurfaceInfo.vHotspot.y);
|
||||
} else {
|
||||
g_pHyprRenderer->setCursorFromName(m_sCursorSurfaceInfo.name);
|
||||
}
|
||||
|
||||
m_sCursorSurfaceInfo.inUse = true;
|
||||
}
|
||||
|
||||
void CInputManager::setCursorImageOverride(const std::string& name) {
|
||||
if (m_bCursorImageOverridden)
|
||||
return;
|
||||
|
||||
m_sCursorSurfaceInfo.inUse = false;
|
||||
g_pHyprRenderer->setCursorFromName(name);
|
||||
}
|
||||
|
||||
bool CInputManager::cursorImageUnlocked() {
|
||||
@@ -540,16 +583,15 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
||||
const auto mouseCoords = g_pInputManager->getMouseCoordsInternal();
|
||||
const auto w = g_pCompositor->vectorToWindowIdeal(mouseCoords);
|
||||
|
||||
if (w && !w->m_bIsFullscreen && !w->hasPopupAt(mouseCoords) && w->m_sGroupData.pNextWindow) {
|
||||
const wlr_box box = w->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents();
|
||||
if (wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y)) {
|
||||
if (e->state == WLR_BUTTON_PRESSED) {
|
||||
const int SIZE = w->getGroupSize();
|
||||
CWindow* pWindow = w->getGroupWindowByIndex((mouseCoords.x - box.x) * SIZE / box.width);
|
||||
if (w != pWindow)
|
||||
w->setGroupCurrent(pWindow);
|
||||
if (w && !w->m_bIsFullscreen && !w->hasPopupAt(mouseCoords)) {
|
||||
for (auto& wd : w->m_dWindowDecorations) {
|
||||
if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT))
|
||||
continue;
|
||||
|
||||
if (wd->getWindowDecorationRegion().containsPoint(mouseCoords)) {
|
||||
wd->onMouseButtonOnDeco(mouseCoords, e);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -557,8 +599,8 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
||||
// TODO detect click on LS properly
|
||||
if (*PRESIZEONBORDER && !m_bLastFocusOnLS) {
|
||||
if (w && !w->m_bIsFullscreen) {
|
||||
const wlr_box real = {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(&real, mouseCoords.x, mouseCoords.y) || w->isInCurvedCorner(mouseCoords.x, mouseCoords.y)) && !w->hasPopupAt(mouseCoords)) {
|
||||
const CBox real = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if ((!real.containsPoint(mouseCoords) || w->isInCurvedCorner(mouseCoords.x, mouseCoords.y)) && !w->hasPopupAt(mouseCoords)) {
|
||||
g_pKeybindManager->resizeWithBorder(e);
|
||||
return;
|
||||
}
|
||||
@@ -633,8 +675,8 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
|
||||
const auto pWindow = g_pCompositor->vectorToWindowIdeal(MOUSECOORDS);
|
||||
|
||||
if (*PGROUPBARSCROLLING && pWindow && !pWindow->m_bIsFullscreen && !pWindow->hasPopupAt(MOUSECOORDS) && pWindow->m_sGroupData.pNextWindow) {
|
||||
const wlr_box box = pWindow->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents();
|
||||
if (wlr_box_contains_point(&box, MOUSECOORDS.x, MOUSECOORDS.y)) {
|
||||
const CBox box = pWindow->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents();
|
||||
if (box.containsPoint(MOUSECOORDS)) {
|
||||
if (e->delta > 0)
|
||||
pWindow->setGroupCurrent(pWindow->m_sGroupData.pNextWindow);
|
||||
else
|
||||
@@ -1165,7 +1207,7 @@ void CInputManager::updateDragIcon() {
|
||||
switch (m_sDrag.dragIcon->drag->grab_type) {
|
||||
case WLR_DRAG_GRAB_KEYBOARD: break;
|
||||
case WLR_DRAG_GRAB_KEYBOARD_POINTER: {
|
||||
wlr_box box = {m_sDrag.pos.x - 2, m_sDrag.pos.y - 2, m_sDrag.dragIcon->surface->current.width + 4, m_sDrag.dragIcon->surface->current.height + 4};
|
||||
CBox box = {m_sDrag.pos.x - 2, m_sDrag.pos.y - 2, m_sDrag.dragIcon->surface->current.width + 4, m_sDrag.dragIcon->surface->current.height + 4};
|
||||
g_pHyprRenderer->damageBox(&box);
|
||||
m_sDrag.pos = getMouseCoordsInternal();
|
||||
break;
|
||||
@@ -1205,7 +1247,7 @@ void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* co
|
||||
g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y})) :
|
||||
PWINDOW->m_vRealPosition.goalv();
|
||||
|
||||
PCONSTRAINT->cursorPosOnActivate = MOUSECOORDS - RELATIVETO;
|
||||
PCONSTRAINT->cursorPosOnActivate = (MOUSECOORDS - RELATIVETO) * PWINDOW->m_fX11SurfaceScaledBy;
|
||||
}
|
||||
|
||||
if (constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) {
|
||||
@@ -1432,9 +1474,9 @@ void CInputManager::setTabletConfigs() {
|
||||
|
||||
const auto REGION_POS = g_pConfigManager->getDeviceVec(t.name, "region_position", "input:tablet:region_position");
|
||||
const auto REGION_SIZE = g_pConfigManager->getDeviceVec(t.name, "region_size", "input:tablet:region_size");
|
||||
const auto REGION = wlr_box{REGION_POS.x, REGION_POS.y, REGION_SIZE.x, REGION_SIZE.y};
|
||||
if (!wlr_box_empty(®ION))
|
||||
wlr_cursor_map_input_to_region(g_pCompositor->m_sWLRCursor, t.wlrDevice, ®ION);
|
||||
auto regionBox = CBox{REGION_POS.x, REGION_POS.y, REGION_SIZE.x, REGION_SIZE.y};
|
||||
if (!regionBox.empty())
|
||||
wlr_cursor_map_input_to_region(g_pCompositor->m_sWLRCursor, t.wlrDevice, regionBox.pWlr());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1492,7 +1534,8 @@ void CInputManager::destroySwitch(SSwitchDevice* pDevice) {
|
||||
|
||||
void CInputManager::setCursorImageUntilUnset(std::string name) {
|
||||
g_pHyprRenderer->setCursorFromName(name.c_str());
|
||||
m_bCursorImageOverridden = true;
|
||||
m_bCursorImageOverridden = true;
|
||||
m_sCursorSurfaceInfo.inUse = false;
|
||||
}
|
||||
|
||||
void CInputManager::unsetCursorImage() {
|
||||
@@ -1500,8 +1543,7 @@ void CInputManager::unsetCursorImage() {
|
||||
return;
|
||||
|
||||
m_bCursorImageOverridden = false;
|
||||
if (!g_pHyprRenderer->m_bWindowRequestedCursorHide)
|
||||
g_pHyprRenderer->setCursorFromName("left_ptr");
|
||||
restoreCursorIconToApp();
|
||||
}
|
||||
|
||||
std::string CInputManager::deviceNameToInternalString(std::string in) {
|
||||
@@ -1579,49 +1621,70 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) {
|
||||
// give a small leeway (10 px) for corner icon
|
||||
const auto CORNER = *PROUNDING + BORDERSIZE + 10;
|
||||
const auto mouseCoords = getMouseCoordsInternal();
|
||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
CBox box = w->getWindowMainSurfaceBox();
|
||||
eBorderIconDirection direction = BORDERICON_NONE;
|
||||
wlr_box boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE),
|
||||
box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)};
|
||||
CBox boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE),
|
||||
box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)};
|
||||
|
||||
if (!wlr_box_contains_point(&boxFullGrabInput, mouseCoords.x, mouseCoords.y) || (!m_lCurrentlyHeldButtons.empty() && !currentlyDraggedWindow)) {
|
||||
if (w->hasPopupAt(mouseCoords))
|
||||
direction = BORDERICON_NONE;
|
||||
} else if (wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y)) {
|
||||
if (!w->isInCurvedCorner(mouseCoords.x, mouseCoords.y)) {
|
||||
direction = BORDERICON_NONE;
|
||||
} else {
|
||||
if (mouseCoords.y < box.y + CORNER) {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_UP_LEFT;
|
||||
else
|
||||
direction = BORDERICON_UP_RIGHT;
|
||||
} else {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_DOWN_LEFT;
|
||||
else
|
||||
direction = BORDERICON_DOWN_RIGHT;
|
||||
else if (!boxFullGrabInput.containsPoint(mouseCoords) || (!m_lCurrentlyHeldButtons.empty() && !currentlyDraggedWindow))
|
||||
direction = BORDERICON_NONE;
|
||||
else {
|
||||
|
||||
bool onDeco = false;
|
||||
|
||||
for (auto& wd : w->m_dWindowDecorations) {
|
||||
if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT))
|
||||
continue;
|
||||
|
||||
if (wd->getWindowDecorationRegion().containsPoint(mouseCoords)) {
|
||||
onDeco = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mouseCoords.y < box.y + CORNER) {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_UP_LEFT;
|
||||
else if (mouseCoords.x > box.x + box.width - CORNER)
|
||||
direction = BORDERICON_UP_RIGHT;
|
||||
else
|
||||
direction = BORDERICON_UP;
|
||||
} else if (mouseCoords.y > box.y + box.height - CORNER) {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_DOWN_LEFT;
|
||||
else if (mouseCoords.x > box.x + box.width - CORNER)
|
||||
direction = BORDERICON_DOWN_RIGHT;
|
||||
else
|
||||
direction = BORDERICON_DOWN;
|
||||
} else {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_LEFT;
|
||||
else if (mouseCoords.x > box.x + box.width - CORNER)
|
||||
direction = BORDERICON_RIGHT;
|
||||
|
||||
if (onDeco)
|
||||
direction = BORDERICON_NONE;
|
||||
else {
|
||||
if (box.containsPoint(mouseCoords)) {
|
||||
if (!w->isInCurvedCorner(mouseCoords.x, mouseCoords.y)) {
|
||||
direction = BORDERICON_NONE;
|
||||
} else {
|
||||
if (mouseCoords.y < box.y + CORNER) {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_UP_LEFT;
|
||||
else
|
||||
direction = BORDERICON_UP_RIGHT;
|
||||
} else {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_DOWN_LEFT;
|
||||
else
|
||||
direction = BORDERICON_DOWN_RIGHT;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mouseCoords.y < box.y + CORNER) {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_UP_LEFT;
|
||||
else if (mouseCoords.x > box.x + box.width - CORNER)
|
||||
direction = BORDERICON_UP_RIGHT;
|
||||
else
|
||||
direction = BORDERICON_UP;
|
||||
} else if (mouseCoords.y > box.y + box.height - CORNER) {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_DOWN_LEFT;
|
||||
else if (mouseCoords.x > box.x + box.width - CORNER)
|
||||
direction = BORDERICON_DOWN_RIGHT;
|
||||
else
|
||||
direction = BORDERICON_DOWN;
|
||||
} else {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_LEFT;
|
||||
else if (mouseCoords.x > box.x + box.width - CORNER)
|
||||
direction = BORDERICON_RIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -7,14 +7,12 @@
|
||||
#include "../../helpers/Timer.hpp"
|
||||
#include "InputMethodRelay.hpp"
|
||||
|
||||
enum eClickBehaviorMode
|
||||
{
|
||||
enum eClickBehaviorMode {
|
||||
CLICKMODE_DEFAULT = 0,
|
||||
CLICKMODE_KILL
|
||||
};
|
||||
|
||||
enum eMouseBindMode
|
||||
{
|
||||
enum eMouseBindMode {
|
||||
MBIND_INVALID = -1,
|
||||
MBIND_MOVE = 0,
|
||||
MBIND_RESIZE = 1,
|
||||
@@ -22,8 +20,7 @@ enum eMouseBindMode
|
||||
MBIND_RESIZE_FORCE_RATIO = 3
|
||||
};
|
||||
|
||||
enum eBorderIconDirection
|
||||
{
|
||||
enum eBorderIconDirection {
|
||||
BORDERICON_NONE,
|
||||
BORDERICON_UP,
|
||||
BORDERICON_DOWN,
|
||||
@@ -118,6 +115,7 @@ class CInputManager {
|
||||
// for dragging floating windows
|
||||
CWindow* currentlyDraggedWindow = nullptr;
|
||||
eMouseBindMode dragMode = MBIND_INVALID;
|
||||
bool m_bWasDraggingWindow = false;
|
||||
|
||||
// for refocus to be forced
|
||||
CWindow* m_pForcedFocus = nullptr;
|
||||
@@ -229,15 +227,22 @@ class CInputManager {
|
||||
void setBorderCursorIcon(eBorderIconDirection);
|
||||
void setCursorIconOnBorder(CWindow* w);
|
||||
|
||||
// temporary. Obeys setUntilUnset.
|
||||
void setCursorImageOverride(const std::string& name);
|
||||
|
||||
// cursor surface
|
||||
// struct cursorSI {
|
||||
// wlr_surface* pSurface = nullptr;
|
||||
// Vector2D vHotspot;
|
||||
// bool bUsed = false;
|
||||
// } cursorSurfaceInfo;
|
||||
// DYNLISTENER(CursorSurfaceDestroy);
|
||||
struct cursorSI {
|
||||
bool hidden = false; // null surface = hidden
|
||||
CWLSurface wlSurface;
|
||||
Vector2D vHotspot;
|
||||
std::string name; // if not empty, means set by name.
|
||||
bool inUse = false;
|
||||
} m_sCursorSurfaceInfo;
|
||||
|
||||
void restoreCursorIconToApp(); // no-op if restored
|
||||
|
||||
friend class CKeybindManager;
|
||||
friend class CWLSurface;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CInputManager> g_pInputManager;
|
||||
|
@@ -3,7 +3,7 @@
|
||||
#include "../../Compositor.hpp"
|
||||
|
||||
CInputMethodRelay::CInputMethodRelay() {
|
||||
g_pHookSystem->hookDynamic("keyboardFocus", [&](void* self, std::any param) { onKeyboardFocus(std::any_cast<wlr_surface*>(param)); });
|
||||
g_pHookSystem->hookDynamic("keyboardFocus", [&](void* self, SCallbackInfo& info, std::any param) { onKeyboardFocus(std::any_cast<wlr_surface*>(param)); });
|
||||
}
|
||||
|
||||
void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
|
||||
@@ -178,7 +178,7 @@ void CInputMethodRelay::updateInputPopup(SIMEPopup* pPopup) {
|
||||
|
||||
bool cursorRect = PFOCUSEDTI->pWlrInput ? PFOCUSEDTI->pWlrInput->current.features & WLR_TEXT_INPUT_V3_FEATURE_CURSOR_RECTANGLE : true;
|
||||
const auto PFOCUSEDSURFACE = focusedSurface(PFOCUSEDTI);
|
||||
auto cursorBox = PFOCUSEDTI->pWlrInput ? PFOCUSEDTI->pWlrInput->current.cursor_rectangle : PFOCUSEDTI->pV1Input->cursorRectangle;
|
||||
CBox cursorBox = PFOCUSEDTI->pWlrInput ? PFOCUSEDTI->pWlrInput->current.cursor_rectangle : PFOCUSEDTI->pV1Input->cursorRectangle;
|
||||
CMonitor* pMonitor = nullptr;
|
||||
|
||||
Vector2D parentPos;
|
||||
@@ -209,7 +209,7 @@ void CInputMethodRelay::updateInputPopup(SIMEPopup* pPopup) {
|
||||
if (!pMonitor)
|
||||
return;
|
||||
|
||||
wlr_box finalBox = cursorBox;
|
||||
CBox finalBox = cursorBox;
|
||||
|
||||
if (cursorBox.y + parentPos.y + pPopup->pSurface->surface->current.height + finalBox.height > pMonitor->vecPosition.y + pMonitor->vecSize.y)
|
||||
finalBox.y -= pPopup->pSurface->surface->current.height + finalBox.height;
|
||||
@@ -225,7 +225,7 @@ void CInputMethodRelay::updateInputPopup(SIMEPopup* pPopup) {
|
||||
|
||||
pPopup->lastSize = Vector2D(pPopup->pSurface->surface->current.width, pPopup->pSurface->surface->current.height);
|
||||
|
||||
wlr_input_popup_surface_v2_send_text_input_rectangle(pPopup->pSurface, &finalBox);
|
||||
wlr_input_popup_surface_v2_send_text_input_rectangle(pPopup->pSurface, finalBox.pWlr());
|
||||
|
||||
damagePopup(pPopup);
|
||||
}
|
||||
|
@@ -244,8 +244,6 @@ void CInputManager::focusTablet(STablet* pTab, wlr_tablet_tool* pTool, bool moti
|
||||
if (const auto PWINDOW = g_pCompositor->m_pLastWindow; PWINDOW) {
|
||||
const auto CURSORPOS = g_pInputManager->getMouseCoordsInternal();
|
||||
|
||||
const auto LOCAL = CURSORPOS - PWINDOW->m_vRealPosition.goalv();
|
||||
|
||||
if (PTOOL->pSurface != g_pCompositor->m_pLastFocus)
|
||||
wlr_tablet_v2_tablet_tool_notify_proximity_out(PTOOL->wlrTabletToolV2);
|
||||
|
||||
@@ -254,8 +252,14 @@ void CInputManager::focusTablet(STablet* pTab, wlr_tablet_tool* pTool, bool moti
|
||||
wlr_tablet_v2_tablet_tool_notify_proximity_in(PTOOL->wlrTabletToolV2, pTab->wlrTabletV2, g_pCompositor->m_pLastFocus);
|
||||
}
|
||||
|
||||
if (motion)
|
||||
wlr_tablet_v2_tablet_tool_notify_motion(PTOOL->wlrTabletToolV2, LOCAL.x, LOCAL.y);
|
||||
if (motion) {
|
||||
auto local = CURSORPOS - PWINDOW->m_vRealPosition.goalv();
|
||||
|
||||
if (PWINDOW->m_bIsX11)
|
||||
local = local * PWINDOW->m_fX11SurfaceScaledBy;
|
||||
|
||||
wlr_tablet_v2_tablet_tool_notify_motion(PTOOL->wlrTabletToolV2, local.x, local.y);
|
||||
}
|
||||
} else {
|
||||
if (PTOOL->pSurface)
|
||||
wlr_tablet_v2_tablet_tool_notify_proximity_out(PTOOL->wlrTabletToolV2);
|
||||
|
@@ -32,12 +32,12 @@ void CInputManager::onTouchDown(wlr_touch_down_event* e) {
|
||||
|
||||
if (m_sTouchData.touchFocusWindow) {
|
||||
if (m_sTouchData.touchFocusWindow->m_bIsX11) {
|
||||
local = g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchFocusWindow->m_vRealPosition.goalv();
|
||||
local = (g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchFocusWindow->m_vRealPosition.goalv()) * m_sTouchData.touchFocusWindow->m_fX11SurfaceScaledBy;
|
||||
m_sTouchData.touchSurfaceOrigin = m_sTouchData.touchFocusWindow->m_vRealPosition.goalv();
|
||||
} else {
|
||||
g_pCompositor->vectorWindowToSurface(g_pInputManager->getMouseCoordsInternal(), m_sTouchData.touchFocusWindow, local);
|
||||
m_sTouchData.touchSurfaceOrigin = g_pInputManager->getMouseCoordsInternal() - local;
|
||||
}
|
||||
|
||||
m_sTouchData.touchSurfaceOrigin = g_pInputManager->getMouseCoordsInternal() - local;
|
||||
} else if (m_sTouchData.touchFocusLS) {
|
||||
local = g_pInputManager->getMouseCoordsInternal() - Vector2D(m_sTouchData.touchFocusLS->geometry.x, m_sTouchData.touchFocusLS->geometry.y);
|
||||
|
||||
@@ -63,7 +63,9 @@ void CInputManager::onTouchMove(wlr_touch_motion_event* e) {
|
||||
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PMONITOR->vecPosition.x + e->x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e->y * PMONITOR->vecSize.y);
|
||||
|
||||
const auto local = g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchSurfaceOrigin;
|
||||
auto local = g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchSurfaceOrigin;
|
||||
if (m_sTouchData.touchFocusWindow->m_bIsX11)
|
||||
local = local * m_sTouchData.touchFocusWindow->m_fX11SurfaceScaledBy;
|
||||
|
||||
wlr_seat_touch_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id, local.x, local.y);
|
||||
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, local.x, local.y);
|
||||
|
@@ -9,6 +9,10 @@
|
||||
|
||||
#include <sstream>
|
||||
|
||||
APICALL const char* __hyprland_api_get_hash() {
|
||||
return GIT_COMMIT_HASH;
|
||||
}
|
||||
|
||||
APICALL bool HyprlandAPI::registerCallbackStatic(HANDLE handle, const std::string& event, HOOK_CALLBACK_FN* fn) {
|
||||
auto* const PLUGIN = g_pPluginSystem->getPluginByHandle(handle);
|
||||
|
||||
@@ -160,6 +164,19 @@ APICALL bool HyprlandAPI::addConfigValue(HANDLE handle, const std::string& name,
|
||||
return true;
|
||||
}
|
||||
|
||||
APICALL bool HyprlandAPI::addConfigKeyword(HANDLE handle, const std::string& name, std::function<void(const std::string& key, const std::string& val)> fn) {
|
||||
auto* const PLUGIN = g_pPluginSystem->getPluginByHandle(handle);
|
||||
|
||||
if (!g_pPluginSystem->m_bAllowConfigVars)
|
||||
return false;
|
||||
|
||||
if (!PLUGIN)
|
||||
return false;
|
||||
|
||||
g_pConfigManager->addPluginKeyword(handle, name, fn);
|
||||
return true;
|
||||
}
|
||||
|
||||
APICALL SConfigValue* HyprlandAPI::getConfigValue(HANDLE handle, const std::string& name) {
|
||||
auto* const PLUGIN = g_pPluginSystem->getPluginByHandle(handle);
|
||||
|
||||
|
@@ -29,7 +29,7 @@ Feel like the API is missing something you'd like to use in your plugin? Open an
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
typedef std::function<void(void*, std::any)> HOOK_CALLBACK_FN;
|
||||
typedef std::function<void(void*, SCallbackInfo&, std::any)> HOOK_CALLBACK_FN;
|
||||
typedef struct {
|
||||
std::string name;
|
||||
std::string description;
|
||||
@@ -114,6 +114,14 @@ namespace HyprlandAPI {
|
||||
*/
|
||||
APICALL bool addConfigValue(HANDLE handle, const std::string& name, const SConfigValue& value);
|
||||
|
||||
/*
|
||||
Add a config keyword.
|
||||
This method may only be called in "pluginInit"
|
||||
|
||||
returns: true on success, false on fail
|
||||
*/
|
||||
APICALL bool addConfigKeyword(HANDLE handle, const std::string& name, std::function<void(const std::string& key, const std::string& val)> fn);
|
||||
|
||||
/*
|
||||
Get a config value.
|
||||
|
||||
@@ -272,7 +280,11 @@ namespace HyprlandAPI {
|
||||
|
||||
This function will end up in both hyprland and any/all plugins,
|
||||
and can be found by a simple dlsym()
|
||||
|
||||
_get_hash() is server,
|
||||
_get_client_hash() is client.
|
||||
*/
|
||||
APICALL inline EXPORT const char* __hyprland_api_get_hash() {
|
||||
APICALL EXPORT const char* __hyprland_api_get_hash();
|
||||
APICALL inline EXPORT const char* __hyprland_api_get_client_hash() {
|
||||
return GIT_COMMIT_HASH;
|
||||
}
|
||||
|
@@ -78,6 +78,11 @@ void CFractionalScaleProtocolManager::getFractionalScale(wl_client* client, wl_r
|
||||
const auto PSURFACE = wlr_surface_from_resource(surface);
|
||||
const auto PADDON = getAddonForSurface(PSURFACE);
|
||||
|
||||
if (PADDON->pResource) {
|
||||
wl_resource_post_error(resource, WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_FRACTIONAL_SCALE_EXISTS, "Fractional scale exists.");
|
||||
return;
|
||||
}
|
||||
|
||||
PADDON->pResource = wl_resource_create(client, &wp_fractional_scale_v1_interface, wl_resource_get_version(resource), id);
|
||||
wl_resource_set_implementation(PADDON->pResource, &fractionalScaleAddonImpl, PADDON, handleAddonDestroy);
|
||||
|
||||
|
@@ -119,7 +119,7 @@ CScreencopyClient::~CScreencopyClient() {
|
||||
CScreencopyClient::CScreencopyClient() {
|
||||
lastMeasure.reset();
|
||||
lastFrame.reset();
|
||||
tickCallback = g_pHookSystem->hookDynamic("tick", [&](void* self, std::any data) { onTick(); });
|
||||
tickCallback = g_pHookSystem->hookDynamic("tick", [&](void* self, SCallbackInfo& info, std::any data) { onTick(); });
|
||||
}
|
||||
|
||||
void CScreencopyClient::onTick() {
|
||||
@@ -183,7 +183,7 @@ void CScreencopyProtocolManager::removeFrame(SScreencopyFrame* frame, bool force
|
||||
m_lFrames.remove(*frame);
|
||||
}
|
||||
|
||||
void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* output, wlr_box box) {
|
||||
void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* output, CBox box) {
|
||||
const auto PCLIENT = clientFromResource(resource);
|
||||
|
||||
const auto PFRAME = &m_lFrames.emplace_back();
|
||||
@@ -239,8 +239,7 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r
|
||||
}
|
||||
int ow, oh;
|
||||
wlr_output_effective_resolution(PFRAME->pMonitor->output, &ow, &oh);
|
||||
wlr_box_transform(&PFRAME->box, &PFRAME->box, PFRAME->pMonitor->transform, ow, oh);
|
||||
scaleBox(&PFRAME->box, PFRAME->pMonitor->scale);
|
||||
PFRAME->box.transform(PFRAME->pMonitor->transform, ow, oh).scale(PFRAME->pMonitor->scale);
|
||||
|
||||
PFRAME->shmStride = (PSHMINFO->bpp / 8) * PFRAME->box.width;
|
||||
|
||||
@@ -263,7 +262,7 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PBUFFER = wlr_buffer_from_resource(buffer);
|
||||
const auto PBUFFER = wlr_buffer_try_from_resource(buffer);
|
||||
if (!PBUFFER) {
|
||||
Debug::log(ERR, "[sc] invalid buffer in {:x}", (uintptr_t)PFRAME);
|
||||
wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer");
|
||||
@@ -332,7 +331,7 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou
|
||||
}
|
||||
|
||||
void CScreencopyProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e) {
|
||||
m_pLastMonitorBackBuffer = e->buffer;
|
||||
m_pLastMonitorBackBuffer = e->state->buffer;
|
||||
shareAllFrames(pMonitor);
|
||||
m_pLastMonitorBackBuffer = nullptr;
|
||||
}
|
||||
|
@@ -46,7 +46,7 @@ struct SScreencopyFrame {
|
||||
|
||||
uint32_t shmFormat = 0;
|
||||
uint32_t dmabufFormat = 0;
|
||||
wlr_box box = {0};
|
||||
CBox box = {};
|
||||
int shmStride = 0;
|
||||
|
||||
bool overlayCursor = false;
|
||||
@@ -73,7 +73,7 @@ class CScreencopyProtocolManager {
|
||||
void removeFrame(SScreencopyFrame* frame, bool force = false);
|
||||
void displayDestroy();
|
||||
|
||||
void captureOutput(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* output, wlr_box box = {0, 0, 0, 0});
|
||||
void captureOutput(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* output, CBox box = {0, 0, 0, 0});
|
||||
|
||||
void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer);
|
||||
|
||||
|
@@ -200,7 +200,7 @@ void CTextInputV1ProtocolManager::handleSetContentType(wl_client* client, wl_res
|
||||
|
||||
void CTextInputV1ProtocolManager::handleSetCursorRectangle(wl_client* client, wl_resource* resource, int32_t x, int32_t y, int32_t width, int32_t height) {
|
||||
const auto PTI = tiFromResource(resource);
|
||||
PTI->cursorRectangle = wlr_box{x, y, width, height};
|
||||
PTI->cursorRectangle = CBox{x, y, width, height};
|
||||
}
|
||||
|
||||
void CTextInputV1ProtocolManager::handleSetPreferredLanguage(wl_client* client, wl_resource* resource, const char* language) {
|
||||
|
@@ -39,9 +39,9 @@ struct STextInputV1 {
|
||||
uint32_t purpose = 0;
|
||||
} pendingContentType;
|
||||
|
||||
wlr_box cursorRectangle = {0, 0, 0, 0};
|
||||
CBox cursorRectangle = {0, 0, 0, 0};
|
||||
|
||||
bool operator==(const STextInputV1& other) {
|
||||
bool operator==(const STextInputV1& other) {
|
||||
return other.client == client && other.resourceCaller == resourceCaller && other.resourceImpl == resourceImpl;
|
||||
}
|
||||
};
|
||||
|
@@ -201,7 +201,7 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou
|
||||
PFRAME->box = {0, 0, (int)(PFRAME->pWindow->m_vRealSize.vec().x * PMONITOR->scale), (int)(PFRAME->pWindow->m_vRealSize.vec().y * PMONITOR->scale)};
|
||||
int ow, oh;
|
||||
wlr_output_effective_resolution(PMONITOR->output, &ow, &oh);
|
||||
wlr_box_transform(&PFRAME->box, &PFRAME->box, PMONITOR->transform, ow, oh);
|
||||
PFRAME->box.transform(PMONITOR->transform, ow, oh);
|
||||
|
||||
PFRAME->shmStride = (PSHMINFO->bpp / 8) * PFRAME->box.width;
|
||||
|
||||
@@ -229,7 +229,7 @@ void CToplevelExportProtocolManager::copyFrame(wl_client* client, wl_resource* r
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PBUFFER = wlr_buffer_from_resource(buffer);
|
||||
const auto PBUFFER = wlr_buffer_try_from_resource(buffer);
|
||||
if (!PBUFFER) {
|
||||
wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer");
|
||||
removeFrame(PFRAME);
|
||||
@@ -301,9 +301,9 @@ void CToplevelExportProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_outp
|
||||
if (PMONITOR != g_pCompositor->getMonitorFromID(f->pWindow->m_iMonitorID))
|
||||
continue;
|
||||
|
||||
wlr_box geometry = {f->pWindow->m_vRealPosition.vec().x, f->pWindow->m_vRealPosition.vec().y, f->pWindow->m_vRealSize.vec().x, f->pWindow->m_vRealSize.vec().y};
|
||||
CBox geometry = {f->pWindow->m_vRealPosition.vec().x, f->pWindow->m_vRealPosition.vec().y, f->pWindow->m_vRealSize.vec().x, f->pWindow->m_vRealSize.vec().y};
|
||||
|
||||
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, &geometry))
|
||||
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, geometry.pWlr()))
|
||||
continue;
|
||||
|
||||
shareFrame(f);
|
||||
@@ -448,7 +448,7 @@ bool CToplevelExportProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame, ti
|
||||
|
||||
g_pHyprOpenGL->bindWlrOutputFb();
|
||||
|
||||
wlr_box monbox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||
CBox monbox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||
g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 1.f);
|
||||
|
||||
g_pHyprOpenGL->end();
|
||||
|
@@ -58,9 +58,9 @@ void CXDGOutputProtocol::bindManager(wl_client* client, void* data, uint32_t ver
|
||||
}
|
||||
|
||||
CXDGOutputProtocol::CXDGOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||
g_pHookSystem->hookDynamic("monitorLayoutChanged", [this](void* self, std::any param) { this->updateAllOutputs(); });
|
||||
g_pHookSystem->hookDynamic("configReloaded", [this](void* self, std::any param) { this->updateAllOutputs(); });
|
||||
g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, std::any param) {
|
||||
g_pHookSystem->hookDynamic("monitorLayoutChanged", [this](void* self, SCallbackInfo& info, std::any param) { this->updateAllOutputs(); });
|
||||
g_pHookSystem->hookDynamic("configReloaded", [this](void* self, SCallbackInfo& info, std::any param) { this->updateAllOutputs(); });
|
||||
g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) {
|
||||
const auto PMONITOR = std::any_cast<CMonitor*>(param);
|
||||
std::erase_if(m_vXDGOutputs, [&](const auto& other) {
|
||||
const auto REMOVE = other->monitor == PMONITOR;
|
||||
@@ -72,15 +72,9 @@ CXDGOutputProtocol::CXDGOutputProtocol(const wl_interface* iface, const int& ver
|
||||
}
|
||||
|
||||
void CXDGOutputProtocol::onManagerGetXDGOutput(wl_client* client, wl_resource* resource, uint32_t id, wl_resource* outputResource) {
|
||||
const auto OUTPUT = wlr_output_from_resource(outputResource);
|
||||
const auto OUTPUT = wlr_output_from_resource(outputResource);
|
||||
|
||||
if (!OUTPUT)
|
||||
return;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(OUTPUT);
|
||||
|
||||
if (!PMONITOR)
|
||||
return;
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(OUTPUT);
|
||||
|
||||
SXDGOutput* pXDGOutput = m_vXDGOutputs.emplace_back(std::make_unique<SXDGOutput>(PMONITOR)).get();
|
||||
#ifndef NO_XWAYLAND
|
||||
@@ -99,6 +93,10 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(wl_client* client, wl_resource* r
|
||||
|
||||
pXDGOutput->resource->setImplementation(&OUTPUT_IMPL, nullptr);
|
||||
pXDGOutput->resource->setData(this);
|
||||
|
||||
if (!PMONITOR)
|
||||
return;
|
||||
|
||||
const auto XDGVER = pXDGOutput->resource->version();
|
||||
|
||||
if (XDGVER >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION)
|
||||
@@ -116,7 +114,7 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(wl_client* client, wl_resource* r
|
||||
void CXDGOutputProtocol::updateOutputDetails(SXDGOutput* pOutput) {
|
||||
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
||||
|
||||
if (!pOutput->resource->good())
|
||||
if (!pOutput->resource->good() || !pOutput->monitor)
|
||||
return;
|
||||
|
||||
const auto POS = pOutput->isXWayland ? pOutput->monitor->vecXWaylandPosition : pOutput->monitor->vecPosition;
|
||||
@@ -133,6 +131,10 @@ void CXDGOutputProtocol::updateOutputDetails(SXDGOutput* pOutput) {
|
||||
|
||||
void CXDGOutputProtocol::updateAllOutputs() {
|
||||
for (auto& o : m_vXDGOutputs) {
|
||||
|
||||
if (!o->monitor)
|
||||
continue;
|
||||
|
||||
updateOutputDetails(o.get());
|
||||
|
||||
wlr_output_schedule_done(o->monitor->output);
|
||||
|
@@ -1,10 +1,19 @@
|
||||
#include "Framebuffer.hpp"
|
||||
#include "OpenGL.hpp"
|
||||
|
||||
bool CFramebuffer::alloc(int w, int h) {
|
||||
bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) {
|
||||
bool firstAlloc = false;
|
||||
RASSERT((w > 1 && h > 1), "cannot alloc a FB with negative / zero size! (attempted {}x{})", w, h);
|
||||
|
||||
uint32_t glFormat = drmFormatToGL(drmFormat);
|
||||
uint32_t glType = glFormat != GL_RGBA ?
|
||||
#ifdef GLES2
|
||||
GL_UNSIGNED_INT_2_10_10_10_REV_EXT :
|
||||
#else
|
||||
GL_UNSIGNED_INT_2_10_10_10_REV :
|
||||
#endif
|
||||
GL_UNSIGNED_BYTE;
|
||||
|
||||
if (m_iFb == (uint32_t)-1) {
|
||||
firstAlloc = true;
|
||||
glGenFramebuffers(1, &m_iFb);
|
||||
@@ -22,7 +31,7 @@ bool CFramebuffer::alloc(int w, int h) {
|
||||
|
||||
if (firstAlloc || m_vSize != Vector2D(w, h)) {
|
||||
glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, glFormat, w, h, 0, GL_RGBA, glType, 0);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_iFb);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_cTex.m_iTexID, 0);
|
||||
|
@@ -7,7 +7,7 @@ class CFramebuffer {
|
||||
public:
|
||||
~CFramebuffer();
|
||||
|
||||
bool alloc(int w, int h);
|
||||
bool alloc(int w, int h, uint32_t format = GL_RGBA);
|
||||
void bind();
|
||||
void release();
|
||||
void reset();
|
||||
|
@@ -37,7 +37,7 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
|
||||
Debug::log(WARN, "!RENDERER: Using the legacy GLES2 renderer!");
|
||||
#endif
|
||||
|
||||
g_pHookSystem->hookDynamic("preRender", [&](void* self, std::any data) { preRender(std::any_cast<CMonitor*>(data)); });
|
||||
g_pHookSystem->hookDynamic("preRender", [&](void* self, SCallbackInfo& info, std::any data) { preRender(std::any_cast<CMonitor*>(data)); });
|
||||
|
||||
RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT), "Couldn't unset current EGL!");
|
||||
|
||||
@@ -128,10 +128,12 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) {
|
||||
m_RenderData.pCurrentMonData->primaryFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
m_RenderData.pCurrentMonData->mirrorFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
m_RenderData.pCurrentMonData->offMainFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
|
||||
m_RenderData.pCurrentMonData->primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
m_RenderData.pCurrentMonData->primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
|
||||
m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
|
||||
m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
|
||||
m_RenderData.pCurrentMonData->offMainFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
|
||||
|
||||
createBGTextureForMonitor(pMonitor);
|
||||
}
|
||||
@@ -149,6 +151,8 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) {
|
||||
|
||||
m_bFakeFrame = fake;
|
||||
|
||||
m_RenderData.currentFB = &m_RenderData.pCurrentMonData->primaryFB;
|
||||
|
||||
if (m_bReloadScreenShader) {
|
||||
m_bReloadScreenShader = false;
|
||||
applyScreenShader(g_pConfigManager->getString("decoration:screen_shader"));
|
||||
@@ -168,17 +172,14 @@ void CHyprOpenGLImpl::end() {
|
||||
saveBufferForMirror(); // save with original damage region
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb);
|
||||
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
CBox monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
|
||||
if (m_RenderData.mouseZoomFactor != 1.f) {
|
||||
const auto ZOOMCENTER = m_RenderData.mouseZoomUseMouse ?
|
||||
(g_pInputManager->getMouseCoordsInternal() - m_RenderData.pMonitor->vecPosition) * m_RenderData.pMonitor->scale :
|
||||
m_RenderData.pMonitor->vecTransformedSize / 2.f;
|
||||
monbox.x -= ZOOMCENTER.x;
|
||||
monbox.y -= ZOOMCENTER.y;
|
||||
scaleBox(&monbox, m_RenderData.mouseZoomFactor);
|
||||
monbox.x += *PZOOMRIGID ? m_RenderData.pMonitor->vecTransformedSize.x / 2 : ZOOMCENTER.x;
|
||||
monbox.y += *PZOOMRIGID ? m_RenderData.pMonitor->vecTransformedSize.y / 2 : ZOOMCENTER.y;
|
||||
|
||||
monbox.translate(-ZOOMCENTER).scale(m_RenderData.mouseZoomFactor).translate(*PZOOMRIGID ? m_RenderData.pMonitor->vecTransformedSize / 2.0 : ZOOMCENTER);
|
||||
|
||||
if (monbox.x > 0)
|
||||
monbox.x = 0;
|
||||
@@ -234,8 +235,10 @@ void CHyprOpenGLImpl::initShaders() {
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.program = prog;
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.proj = glGetUniformLocation(prog, "proj");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.tex = glGetUniformLocation(prog, "tex");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.alphaMatte = glGetUniformLocation(prog, "texMatte");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.alpha = glGetUniformLocation(prog, "alpha");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.matteTexAttrib = glGetAttribLocation(prog, "texcoordMatte");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.discardAlpha = glGetUniformLocation(prog, "discardAlpha");
|
||||
@@ -245,6 +248,7 @@ void CHyprOpenGLImpl::initShaders() {
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.radius = glGetUniformLocation(prog, "radius");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.applyTint = glGetUniformLocation(prog, "applyTint");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.tint = glGetUniformLocation(prog, "tint");
|
||||
m_RenderData.pCurrentMonData->m_shRGBA.useAlphaMatte = glGetUniformLocation(prog, "useAlphaMatte");
|
||||
|
||||
prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBAPASSTHRU);
|
||||
m_RenderData.pCurrentMonData->m_shPASSTHRURGBA.program = prog;
|
||||
@@ -253,6 +257,14 @@ void CHyprOpenGLImpl::initShaders() {
|
||||
m_RenderData.pCurrentMonData->m_shPASSTHRURGBA.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_RenderData.pCurrentMonData->m_shPASSTHRURGBA.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
|
||||
prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBAMATTE);
|
||||
m_RenderData.pCurrentMonData->m_shMATTE.program = prog;
|
||||
m_RenderData.pCurrentMonData->m_shMATTE.proj = glGetUniformLocation(prog, "proj");
|
||||
m_RenderData.pCurrentMonData->m_shMATTE.tex = glGetUniformLocation(prog, "tex");
|
||||
m_RenderData.pCurrentMonData->m_shMATTE.alphaMatte = glGetUniformLocation(prog, "texMatte");
|
||||
m_RenderData.pCurrentMonData->m_shMATTE.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_RenderData.pCurrentMonData->m_shMATTE.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
|
||||
prog = createProgram(TEXVERTSRC, FRAGGLITCH);
|
||||
m_RenderData.pCurrentMonData->m_shGLITCH.program = prog;
|
||||
m_RenderData.pCurrentMonData->m_shGLITCH.proj = glGetUniformLocation(prog, "proj");
|
||||
@@ -295,15 +307,18 @@ void CHyprOpenGLImpl::initShaders() {
|
||||
m_RenderData.pCurrentMonData->m_shEXT.applyTint = glGetUniformLocation(prog, "applyTint");
|
||||
m_RenderData.pCurrentMonData->m_shEXT.tint = glGetUniformLocation(prog, "tint");
|
||||
|
||||
prog = createProgram(TEXVERTSRC, FRAGBLUR1);
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.program = prog;
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.tex = glGetUniformLocation(prog, "tex");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.alpha = glGetUniformLocation(prog, "alpha");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.proj = glGetUniformLocation(prog, "proj");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.radius = glGetUniformLocation(prog, "radius");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.halfpixel = glGetUniformLocation(prog, "halfpixel");
|
||||
prog = createProgram(TEXVERTSRC, FRAGBLUR1);
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.program = prog;
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.tex = glGetUniformLocation(prog, "tex");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.alpha = glGetUniformLocation(prog, "alpha");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.proj = glGetUniformLocation(prog, "proj");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.radius = glGetUniformLocation(prog, "radius");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.halfpixel = glGetUniformLocation(prog, "halfpixel");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.passes = glGetUniformLocation(prog, "passes");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.vibrancy = glGetUniformLocation(prog, "vibrancy");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR1.vibrancy_darkness = glGetUniformLocation(prog, "vibrancy_darkness");
|
||||
|
||||
prog = createProgram(TEXVERTSRC, FRAGBLUR2);
|
||||
m_RenderData.pCurrentMonData->m_shBLUR2.program = prog;
|
||||
@@ -315,28 +330,39 @@ void CHyprOpenGLImpl::initShaders() {
|
||||
m_RenderData.pCurrentMonData->m_shBLUR2.radius = glGetUniformLocation(prog, "radius");
|
||||
m_RenderData.pCurrentMonData->m_shBLUR2.halfpixel = glGetUniformLocation(prog, "halfpixel");
|
||||
|
||||
prog = createProgram(TEXVERTSRC, FRAGBLURPREPARE);
|
||||
m_RenderData.pCurrentMonData->m_shBLURPREPARE.program = prog;
|
||||
m_RenderData.pCurrentMonData->m_shBLURPREPARE.tex = glGetUniformLocation(prog, "tex");
|
||||
m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj = glGetUniformLocation(prog, "proj");
|
||||
m_RenderData.pCurrentMonData->m_shBLURPREPARE.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_RenderData.pCurrentMonData->m_shBLURPREPARE.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_RenderData.pCurrentMonData->m_shBLURPREPARE.contrast = glGetUniformLocation(prog, "contrast");
|
||||
m_RenderData.pCurrentMonData->m_shBLURPREPARE.brightness = glGetUniformLocation(prog, "brightness");
|
||||
|
||||
prog = createProgram(TEXVERTSRC, FRAGBLURFINISH);
|
||||
m_RenderData.pCurrentMonData->m_shBLURFINISH.program = prog;
|
||||
m_RenderData.pCurrentMonData->m_shBLURFINISH.tex = glGetUniformLocation(prog, "tex");
|
||||
m_RenderData.pCurrentMonData->m_shBLURFINISH.proj = glGetUniformLocation(prog, "proj");
|
||||
m_RenderData.pCurrentMonData->m_shBLURFINISH.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_RenderData.pCurrentMonData->m_shBLURFINISH.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_RenderData.pCurrentMonData->m_shBLURFINISH.noise = glGetUniformLocation(prog, "noise");
|
||||
m_RenderData.pCurrentMonData->m_shBLURFINISH.contrast = glGetUniformLocation(prog, "contrast");
|
||||
m_RenderData.pCurrentMonData->m_shBLURFINISH.brightness = glGetUniformLocation(prog, "brightness");
|
||||
m_RenderData.pCurrentMonData->m_shBLURFINISH.noise = glGetUniformLocation(prog, "noise");
|
||||
|
||||
prog = createProgram(QUADVERTSRC, FRAGSHADOW);
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.program = prog;
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.proj = glGetUniformLocation(prog, "proj");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.topLeft = glGetUniformLocation(prog, "topLeft");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.fullSize = glGetUniformLocation(prog, "fullSize");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.radius = glGetUniformLocation(prog, "radius");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.range = glGetUniformLocation(prog, "range");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.color = glGetUniformLocation(prog, "color");
|
||||
prog = createProgram(QUADVERTSRC, FRAGSHADOW);
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.program = prog;
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.proj = glGetUniformLocation(prog, "proj");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.matteTexAttrib = glGetAttribLocation(prog, "texcoordMatte");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.alphaMatte = glGetUniformLocation(prog, "alphaMatte");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.topLeft = glGetUniformLocation(prog, "topLeft");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.fullSize = glGetUniformLocation(prog, "fullSize");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.radius = glGetUniformLocation(prog, "radius");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.range = glGetUniformLocation(prog, "range");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.color = glGetUniformLocation(prog, "color");
|
||||
m_RenderData.pCurrentMonData->m_shSHADOW.useAlphaMatte = glGetUniformLocation(prog, "useAlphaMatte");
|
||||
|
||||
prog = createProgram(QUADVERTSRC, FRAGBORDER1);
|
||||
m_RenderData.pCurrentMonData->m_shBORDER1.program = prog;
|
||||
@@ -349,6 +375,7 @@ void CHyprOpenGLImpl::initShaders() {
|
||||
m_RenderData.pCurrentMonData->m_shBORDER1.fullSize = glGetUniformLocation(prog, "fullSize");
|
||||
m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed = glGetUniformLocation(prog, "fullSizeUntransformed");
|
||||
m_RenderData.pCurrentMonData->m_shBORDER1.radius = glGetUniformLocation(prog, "radius");
|
||||
m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter = glGetUniformLocation(prog, "radiusOuter");
|
||||
m_RenderData.pCurrentMonData->m_shBORDER1.gradient = glGetUniformLocation(prog, "gradient");
|
||||
m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength = glGetUniformLocation(prog, "gradientLength");
|
||||
m_RenderData.pCurrentMonData->m_shBORDER1.angle = glGetUniformLocation(prog, "angle");
|
||||
@@ -410,7 +437,7 @@ void CHyprOpenGLImpl::clear(const CColor& color) {
|
||||
}
|
||||
}
|
||||
|
||||
scissor((wlr_box*)nullptr);
|
||||
scissor((CBox*)nullptr);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::blend(bool enabled) {
|
||||
@@ -423,7 +450,7 @@ void CHyprOpenGLImpl::blend(bool enabled) {
|
||||
m_bBlend = enabled;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::scissor(const wlr_box* pBox, bool transform) {
|
||||
void CHyprOpenGLImpl::scissor(const CBox* pBox, bool transform) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to scissor without begin()!");
|
||||
|
||||
if (!pBox) {
|
||||
@@ -431,14 +458,14 @@ void CHyprOpenGLImpl::scissor(const wlr_box* pBox, bool transform) {
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_box newBox = *pBox;
|
||||
CBox newBox = *pBox;
|
||||
|
||||
if (transform) {
|
||||
int w, h;
|
||||
wlr_output_transformed_resolution(m_RenderData.pMonitor->output, &w, &h);
|
||||
|
||||
const auto TR = wlr_output_transform_invert(m_RenderData.pMonitor->transform);
|
||||
wlr_box_transform(&newBox, &newBox, TR, w, h);
|
||||
newBox.transform(TR, w, h);
|
||||
}
|
||||
|
||||
glScissor(newBox.x, newBox.y, newBox.width, newBox.height);
|
||||
@@ -453,22 +480,22 @@ void CHyprOpenGLImpl::scissor(const pixman_box32* pBox, bool transform) {
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_box newBox = {pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1};
|
||||
CBox newBox = {pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1};
|
||||
|
||||
scissor(&newBox, transform);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h, bool transform) {
|
||||
wlr_box box = {x, y, w, h};
|
||||
CBox box = {x, y, w, h};
|
||||
scissor(&box, transform);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) {
|
||||
void CHyprOpenGLImpl::renderRect(CBox* box, const CColor& col, int round) {
|
||||
if (!m_RenderData.damage.empty())
|
||||
renderRectWithDamage(box, col, &m_RenderData.damage, round);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderRectWithBlur(wlr_box* box, const CColor& col, int round, float blurA) {
|
||||
void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round, float blurA) {
|
||||
if (m_RenderData.damage.empty())
|
||||
return;
|
||||
|
||||
@@ -481,7 +508,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(wlr_box* box, const CColor& col, int ro
|
||||
m_RenderData.pCurrentMonData->primaryFB.bind();
|
||||
|
||||
// make a stencil for rounded corners to work with blur
|
||||
scissor((wlr_box*)nullptr); // allow the entire window and stencil to render
|
||||
scissor((CBox*)nullptr); // allow the entire window and stencil to render
|
||||
glClearStencil(0);
|
||||
glClear(GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
@@ -498,7 +525,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(wlr_box* box, const CColor& col, int ro
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
|
||||
scissor(box);
|
||||
wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
CBox MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
m_bEndFrame = true; // fix transformed
|
||||
const auto SAVEDRENDERMODIF = m_RenderData.renderModif;
|
||||
m_RenderData.renderModif = {}; // fix shit
|
||||
@@ -511,26 +538,24 @@ void CHyprOpenGLImpl::renderRectWithBlur(wlr_box* box, const CColor& col, int ro
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
glStencilMask(-1);
|
||||
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
||||
scissor((wlr_box*)nullptr);
|
||||
scissor((CBox*)nullptr);
|
||||
|
||||
renderRectWithDamage(box, col, &m_RenderData.damage, round);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, CRegion* damage, int round) {
|
||||
void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion* damage, int round) {
|
||||
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
|
||||
|
||||
TRACY_GPU_ZONE("RenderRectWithDamage");
|
||||
|
||||
wlr_box newBox = *box;
|
||||
scaleBox(&newBox, m_RenderData.renderModif.scale);
|
||||
newBox.x += m_RenderData.renderModif.translate.x;
|
||||
newBox.y += m_RenderData.renderModif.translate.y;
|
||||
CBox newBox = *box;
|
||||
newBox.scale(m_RenderData.renderModif.scale).translate(m_RenderData.renderModif.translate);
|
||||
|
||||
box = &newBox;
|
||||
|
||||
float matrix[9];
|
||||
wlr_matrix_project_box(matrix, box, wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0,
|
||||
wlr_matrix_project_box(matrix, box->pWlr(), 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];
|
||||
@@ -548,9 +573,9 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, CReg
|
||||
// premultiply the color as well as we don't work with straight alpha
|
||||
glUniform4f(m_RenderData.pCurrentMonData->m_shQUAD.color, col.r * col.a, col.g * col.a, col.b * col.a, col.a);
|
||||
|
||||
wlr_box transformedBox;
|
||||
wlr_box_transform(&transformedBox, box, wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x,
|
||||
m_RenderData.pMonitor->vecTransformedSize.y);
|
||||
CBox transformedBox = *box;
|
||||
transformedBox.transform(wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x,
|
||||
m_RenderData.pMonitor->vecTransformedSize.y);
|
||||
|
||||
const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y);
|
||||
const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height);
|
||||
@@ -584,22 +609,22 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, CReg
|
||||
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, wlr_box* pBox, float alpha, int round, bool allowCustomUV) {
|
||||
void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, CBox* pBox, float alpha, int round, bool allowCustomUV) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||
|
||||
renderTexture(CTexture(tex), pBox, alpha, round, false, allowCustomUV);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardActive, bool allowCustomUV) {
|
||||
void CHyprOpenGLImpl::renderTexture(const CTexture& tex, CBox* pBox, float alpha, int round, bool discardActive, bool allowCustomUV) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||
|
||||
renderTextureInternalWithDamage(tex, pBox, alpha, &m_RenderData.damage, round, discardActive, false, allowCustomUV, true);
|
||||
|
||||
scissor((wlr_box*)nullptr);
|
||||
scissor((CBox*)nullptr);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, CRegion* damage, int round, bool discardActive, bool noAA,
|
||||
bool allowCustomUV, bool allowDim) {
|
||||
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox* pBox, float alpha, CRegion* damage, int round, bool discardActive, bool noAA, bool allowCustomUV,
|
||||
bool allowDim) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
|
||||
|
||||
@@ -610,17 +635,15 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
|
||||
if (m_RenderData.damage.empty())
|
||||
return;
|
||||
|
||||
wlr_box newBox = *pBox;
|
||||
scaleBox(&newBox, m_RenderData.renderModif.scale);
|
||||
newBox.x += m_RenderData.renderModif.translate.x;
|
||||
newBox.y += m_RenderData.renderModif.translate.y;
|
||||
CBox newBox = *pBox;
|
||||
newBox.scale(m_RenderData.renderModif.scale).translate(m_RenderData.renderModif.translate);
|
||||
|
||||
static auto* const PDIMINACTIVE = &g_pConfigManager->getConfigValuePtr("decoration:dim_inactive")->intValue;
|
||||
|
||||
// get transform
|
||||
const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform);
|
||||
float matrix[9];
|
||||
wlr_matrix_project_box(matrix, &newBox, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
||||
wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
||||
|
||||
float glMatrix[9];
|
||||
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
|
||||
@@ -703,9 +726,9 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
|
||||
}
|
||||
}
|
||||
|
||||
wlr_box transformedBox;
|
||||
wlr_box_transform(&transformedBox, &newBox, wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x,
|
||||
m_RenderData.pMonitor->vecTransformedSize.y);
|
||||
CBox transformedBox = newBox;
|
||||
transformedBox.transform(wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x,
|
||||
m_RenderData.pMonitor->vecTransformedSize.y);
|
||||
|
||||
const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y);
|
||||
const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height);
|
||||
@@ -766,7 +789,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
|
||||
glBindTexture(tex.m_iTarget, 0);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, wlr_box* pBox) {
|
||||
void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, CBox* pBox) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
|
||||
|
||||
@@ -775,15 +798,13 @@ void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, wlr_box* pBox)
|
||||
if (m_RenderData.damage.empty())
|
||||
return;
|
||||
|
||||
wlr_box newBox = *pBox;
|
||||
scaleBox(&newBox, m_RenderData.renderModif.scale);
|
||||
newBox.x += m_RenderData.renderModif.translate.x;
|
||||
newBox.y += m_RenderData.renderModif.translate.y;
|
||||
CBox newBox = *pBox;
|
||||
newBox.scale(m_RenderData.renderModif.scale).translate(m_RenderData.renderModif.translate);
|
||||
|
||||
// get transform
|
||||
const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform);
|
||||
float matrix[9];
|
||||
wlr_matrix_project_box(matrix, &newBox, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
||||
wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
||||
|
||||
float glMatrix[9];
|
||||
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
|
||||
@@ -814,7 +835,65 @@ void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, wlr_box* pBox)
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
|
||||
scissor((wlr_box*)nullptr);
|
||||
scissor((CBox*)nullptr);
|
||||
|
||||
glDisableVertexAttribArray(shader->posAttrib);
|
||||
glDisableVertexAttribArray(shader->texAttrib);
|
||||
|
||||
glBindTexture(tex.m_iTarget, 0);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
|
||||
|
||||
TRACY_GPU_ZONE("RenderTextureMatte");
|
||||
|
||||
if (m_RenderData.damage.empty())
|
||||
return;
|
||||
|
||||
CBox newBox = *pBox;
|
||||
newBox.scale(m_RenderData.renderModif.scale).translate(m_RenderData.renderModif.translate);
|
||||
|
||||
// get transform
|
||||
const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform);
|
||||
float matrix[9];
|
||||
wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
||||
|
||||
float glMatrix[9];
|
||||
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
|
||||
|
||||
CShader* shader = &m_RenderData.pCurrentMonData->m_shMATTE;
|
||||
|
||||
glUseProgram(shader->program);
|
||||
|
||||
#ifndef GLES2
|
||||
glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix);
|
||||
#else
|
||||
wlr_matrix_transpose(glMatrix, glMatrix);
|
||||
glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix);
|
||||
#endif
|
||||
glUniform1i(shader->tex, 0);
|
||||
glUniform1i(shader->alphaMatte, 1);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(tex.m_iTarget, tex.m_iTexID);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + 1);
|
||||
glBindTexture(matte.m_cTex.m_iTarget, matte.m_cTex.m_iTexID);
|
||||
|
||||
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
|
||||
glEnableVertexAttribArray(shader->posAttrib);
|
||||
glEnableVertexAttribArray(shader->texAttrib);
|
||||
|
||||
for (auto& RECT : m_RenderData.damage.getRects()) {
|
||||
scissor(&RECT);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
|
||||
scissor((CBox*)nullptr);
|
||||
|
||||
glDisableVertexAttribArray(shader->posAttrib);
|
||||
glDisableVertexAttribArray(shader->texAttrib);
|
||||
@@ -837,15 +916,17 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
|
||||
// get transforms for the full monitor
|
||||
const auto TRANSFORM = wlr_output_transform_invert(m_RenderData.pMonitor->transform);
|
||||
float matrix[9];
|
||||
wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
wlr_matrix_project_box(matrix, &MONITORBOX, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
||||
CBox MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
wlr_matrix_project_box(matrix, MONITORBOX.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
||||
|
||||
float glMatrix[9];
|
||||
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
|
||||
|
||||
// get the config settings
|
||||
static auto* const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur:size")->intValue;
|
||||
static auto* const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur:passes")->intValue;
|
||||
static auto* const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur:size")->intValue;
|
||||
static auto* const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur:passes")->intValue;
|
||||
static auto* const PBLURVIBRANCY = &g_pConfigManager->getConfigValuePtr("decoration:blur:vibrancy")->floatValue;
|
||||
static auto* const PBLURVIBRANCYDARKNESS = &g_pConfigManager->getConfigValuePtr("decoration:blur:vibrancy_darkness")->floatValue;
|
||||
|
||||
// prep damage
|
||||
CRegion damage{*originalDamage};
|
||||
@@ -859,7 +940,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
|
||||
|
||||
CFramebuffer* currentRenderToFB = PMIRRORFB;
|
||||
|
||||
// begin with color adjustments
|
||||
// Begin with base color adjustments - global brightness and contrast
|
||||
// TODO: make this a part of the first pass maybe to save on a drawcall?
|
||||
{
|
||||
static auto* const PBLURCONTRAST = &g_pConfigManager->getConfigValuePtr("decoration:blur:contrast")->floatValue;
|
||||
@@ -873,24 +954,23 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
|
||||
|
||||
glTexParameteri(m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glUseProgram(m_RenderData.pCurrentMonData->m_shBLURFINISH.program);
|
||||
glUseProgram(m_RenderData.pCurrentMonData->m_shBLURPREPARE.program);
|
||||
|
||||
#ifndef GLES2
|
||||
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_TRUE, glMatrix);
|
||||
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj, 1, GL_TRUE, glMatrix);
|
||||
#else
|
||||
wlr_matrix_transpose(glMatrix, glMatrix);
|
||||
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_FALSE, glMatrix);
|
||||
#endif
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.contrast, *PBLURCONTRAST);
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.brightness, *PBLURBRIGHTNESS);
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shBLURPREPARE.contrast, *PBLURCONTRAST);
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shBLURPREPARE.brightness, *PBLURBRIGHTNESS);
|
||||
glUniform1i(m_RenderData.pCurrentMonData->m_shBLURPREPARE.tex, 0);
|
||||
|
||||
glUniform1i(m_RenderData.pCurrentMonData->m_shBLURFINISH.tex, 0);
|
||||
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBLURPREPARE.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBLURPREPARE.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
|
||||
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBLURFINISH.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBLURFINISH.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
|
||||
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURFINISH.posAttrib);
|
||||
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURFINISH.texAttrib);
|
||||
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURPREPARE.posAttrib);
|
||||
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURPREPARE.texAttrib);
|
||||
|
||||
if (!damage.empty()) {
|
||||
for (auto& RECT : damage.getRects()) {
|
||||
@@ -899,8 +979,8 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
|
||||
}
|
||||
}
|
||||
|
||||
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURFINISH.posAttrib);
|
||||
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURFINISH.texAttrib);
|
||||
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURPREPARE.posAttrib);
|
||||
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURPREPARE.texAttrib);
|
||||
|
||||
currentRenderToFB = PMIRRORSWAPFB;
|
||||
}
|
||||
@@ -928,10 +1008,13 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
|
||||
glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix);
|
||||
#endif
|
||||
glUniform1f(pShader->radius, *PBLURSIZE * a); // this makes the blursize change with a
|
||||
if (pShader == &m_RenderData.pCurrentMonData->m_shBLUR1)
|
||||
if (pShader == &m_RenderData.pCurrentMonData->m_shBLUR1) {
|
||||
glUniform2f(m_RenderData.pCurrentMonData->m_shBLUR1.halfpixel, 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f),
|
||||
0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f));
|
||||
else
|
||||
glUniform1i(m_RenderData.pCurrentMonData->m_shBLUR1.passes, *PBLURPASSES);
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shBLUR1.vibrancy, *PBLURVIBRANCY);
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shBLUR1.vibrancy_darkness, *PBLURVIBRANCYDARKNESS);
|
||||
} else
|
||||
glUniform2f(m_RenderData.pCurrentMonData->m_shBLUR2.halfpixel, 0.5f / (m_RenderData.pMonitor->vecPixelSize.x * 2.f),
|
||||
0.5f / (m_RenderData.pMonitor->vecPixelSize.y * 2.f));
|
||||
glUniform1i(pShader->tex, 0);
|
||||
@@ -977,9 +1060,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
|
||||
drawPass(&m_RenderData.pCurrentMonData->m_shBLUR2, &tempDamage); // up
|
||||
}
|
||||
|
||||
// finalize with noise
|
||||
// finalize the image
|
||||
{
|
||||
static auto* const PBLURNOISE = &g_pConfigManager->getConfigValuePtr("decoration:blur:noise")->floatValue;
|
||||
static auto* const PBLURNOISE = &g_pConfigManager->getConfigValuePtr("decoration:blur:noise")->floatValue;
|
||||
static auto* const PBLURBRIGHTNESS = &g_pConfigManager->getConfigValuePtr("decoration:blur:brightness")->floatValue;
|
||||
|
||||
if (currentRenderToFB == PMIRRORFB)
|
||||
PMIRRORSWAPFB->bind();
|
||||
@@ -1001,6 +1085,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
|
||||
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_FALSE, glMatrix);
|
||||
#endif
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.noise, *PBLURNOISE);
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.brightness, *PBLURBRIGHTNESS);
|
||||
|
||||
glUniform1i(m_RenderData.pCurrentMonData->m_shBLURFINISH.tex, 0);
|
||||
|
||||
@@ -1130,11 +1215,11 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() {
|
||||
|
||||
// make the fake dmg
|
||||
CRegion fakeDamage{0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
wlr_box wholeMonitor = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
CBox wholeMonitor = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
const auto POUTFB = blurMainFramebufferWithDamage(1, &fakeDamage);
|
||||
|
||||
// render onto blurFB
|
||||
m_RenderData.pCurrentMonData->blurFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y);
|
||||
m_RenderData.pCurrentMonData->blurFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y, m_RenderData.pMonitor->drmFormat);
|
||||
m_RenderData.pCurrentMonData->blurFB.bind();
|
||||
|
||||
clear(CColor(0, 0, 0, 0));
|
||||
@@ -1189,7 +1274,7 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(SLayerSurface* pLayer, CWind
|
||||
return false;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, float a, wlr_surface* pSurface, int round, bool blockBlurOptimization, float blurA) {
|
||||
void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, float a, wlr_surface* pSurface, int round, bool blockBlurOptimization, float blurA) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!");
|
||||
|
||||
static auto* const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue;
|
||||
@@ -1243,7 +1328,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
||||
m_RenderData.pCurrentMonData->primaryFB.bind();
|
||||
|
||||
// make a stencil for rounded corners to work with blur
|
||||
scissor((wlr_box*)nullptr); // allow the entire window and stencil to render
|
||||
scissor((CBox*)nullptr); // allow the entire window and stencil to render
|
||||
glClearStencil(0);
|
||||
glClear(GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
@@ -1263,7 +1348,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
|
||||
// stencil done. Render everything.
|
||||
wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
CBox MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
// render our great blurred FB
|
||||
static auto* const PBLURIGNOREOPACITY = &g_pConfigManager->getConfigValuePtr("decoration:blur:ignore_opacity")->intValue;
|
||||
m_bEndFrame = true; // fix transformed
|
||||
@@ -1283,17 +1368,17 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
||||
|
||||
glStencilMask(-1);
|
||||
glStencilFunc(GL_ALWAYS, 1, 0xFF);
|
||||
scissor((wlr_box*)nullptr);
|
||||
scissor((CBox*)nullptr);
|
||||
}
|
||||
|
||||
void pushVert2D(float x, float y, float* arr, int& counter, wlr_box* box) {
|
||||
void pushVert2D(float x, float y, float* arr, int& counter, CBox* box) {
|
||||
// 0-1 space god damnit
|
||||
arr[counter * 2 + 0] = x / box->width;
|
||||
arr[counter * 2 + 1] = y / box->height;
|
||||
counter++;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad, int round, int borderSize, float a) {
|
||||
void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, int round, int borderSize, float a, int outerRound) {
|
||||
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()!");
|
||||
|
||||
@@ -1302,10 +1387,8 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad,
|
||||
if (m_RenderData.damage.empty() || (m_pCurrentWindow && m_pCurrentWindow->m_sAdditionalConfigData.forceNoBorder))
|
||||
return;
|
||||
|
||||
wlr_box newBox = *box;
|
||||
scaleBox(&newBox, m_RenderData.renderModif.scale);
|
||||
newBox.x += m_RenderData.renderModif.translate.x;
|
||||
newBox.y += m_RenderData.renderModif.translate.y;
|
||||
CBox newBox = *box;
|
||||
newBox.scale(m_RenderData.renderModif.scale).translate(m_RenderData.renderModif.translate);
|
||||
|
||||
box = &newBox;
|
||||
|
||||
@@ -1323,7 +1406,7 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad,
|
||||
round += round == 0 ? 0 : scaledBorderSize;
|
||||
|
||||
float matrix[9];
|
||||
wlr_matrix_project_box(matrix, box, wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0,
|
||||
wlr_matrix_project_box(matrix, box->pWlr(), 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];
|
||||
@@ -1348,9 +1431,9 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad,
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.angle, (int)(grad.m_fAngle / (PI / 180.0)) % 360 * (PI / 180.0));
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.alpha, a);
|
||||
|
||||
wlr_box transformedBox;
|
||||
wlr_box_transform(&transformedBox, box, wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x,
|
||||
m_RenderData.pMonitor->vecTransformedSize.y);
|
||||
CBox transformedBox = *box;
|
||||
transformedBox.transform(wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x,
|
||||
m_RenderData.pMonitor->vecTransformedSize.y);
|
||||
|
||||
const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y);
|
||||
const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height);
|
||||
@@ -1359,6 +1442,7 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad,
|
||||
glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||
glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box->width, (float)box->height);
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round);
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound);
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, scaledBorderSize);
|
||||
|
||||
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
@@ -1424,10 +1508,12 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(CWindow* pWindow, CFramebuffer* pFra
|
||||
|
||||
pFramebuffer->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
|
||||
pFramebuffer->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
||||
pFramebuffer->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat);
|
||||
|
||||
pFramebuffer->bind();
|
||||
|
||||
m_RenderData.currentFB = pFramebuffer;
|
||||
|
||||
clear(CColor(0, 0, 0, 0)); // JIC
|
||||
|
||||
g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, false, RENDER_PASS_ALL, true);
|
||||
@@ -1482,10 +1568,12 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
|
||||
|
||||
PFRAMEBUFFER->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
|
||||
PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
||||
PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat);
|
||||
|
||||
PFRAMEBUFFER->bind();
|
||||
|
||||
m_RenderData.currentFB = PFRAMEBUFFER;
|
||||
|
||||
clear(CColor(0, 0, 0, 0)); // JIC
|
||||
|
||||
g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders, RENDER_PASS_ALL);
|
||||
@@ -1527,10 +1615,12 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) {
|
||||
|
||||
glViewport(0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y);
|
||||
|
||||
PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
||||
PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat);
|
||||
|
||||
PFRAMEBUFFER->bind();
|
||||
|
||||
m_RenderData.currentFB = PFRAMEBUFFER;
|
||||
|
||||
clear(CColor(0, 0, 0, 0)); // JIC
|
||||
|
||||
timespec now;
|
||||
@@ -1578,7 +1668,7 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) {
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
|
||||
wlr_box windowBox;
|
||||
CBox windowBox;
|
||||
// some mafs to figure out the correct box
|
||||
// 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)),
|
||||
@@ -1592,7 +1682,7 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) {
|
||||
CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
|
||||
|
||||
if (*PDIMAROUND && (*pWindow)->m_sAdditionalConfigData.dimAround) {
|
||||
wlr_box monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y};
|
||||
CBox monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y};
|
||||
g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMAROUND * PWINDOW->m_fAlpha.fl()));
|
||||
g_pHyprRenderer->damageMonitor(PMONITOR);
|
||||
}
|
||||
@@ -1620,7 +1710,7 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) {
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PLAYER->monitorID);
|
||||
|
||||
wlr_box monbox = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
|
||||
CBox monbox = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
|
||||
|
||||
CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
|
||||
|
||||
@@ -1631,7 +1721,7 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) {
|
||||
m_bEndFrame = false;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, float a) {
|
||||
void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, float a) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!");
|
||||
RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!");
|
||||
RASSERT(m_pCurrentWindow, "Tried to render shadow without a window!");
|
||||
@@ -1641,10 +1731,8 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
|
||||
|
||||
TRACY_GPU_ZONE("RenderShadow");
|
||||
|
||||
wlr_box newBox = *box;
|
||||
scaleBox(&newBox, m_RenderData.renderModif.scale);
|
||||
newBox.x += m_RenderData.renderModif.translate.x;
|
||||
newBox.y += m_RenderData.renderModif.translate.y;
|
||||
CBox newBox = *box;
|
||||
newBox.scale(m_RenderData.renderModif.scale).translate(m_RenderData.renderModif.translate);
|
||||
|
||||
box = &newBox;
|
||||
|
||||
@@ -1655,7 +1743,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
|
||||
const auto col = m_pCurrentWindow->m_cRealShadowColor.col();
|
||||
|
||||
float matrix[9];
|
||||
wlr_matrix_project_box(matrix, box, wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0,
|
||||
wlr_matrix_project_box(matrix, box->pWlr(), 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];
|
||||
@@ -1715,11 +1803,11 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
|
||||
void CHyprOpenGLImpl::saveBufferForMirror() {
|
||||
|
||||
if (!m_RenderData.pCurrentMonData->monitorMirrorFB.isAllocated())
|
||||
m_RenderData.pCurrentMonData->monitorMirrorFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y);
|
||||
m_RenderData.pCurrentMonData->monitorMirrorFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y, m_RenderData.pMonitor->drmFormat);
|
||||
|
||||
m_RenderData.pCurrentMonData->monitorMirrorFB.bind();
|
||||
|
||||
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
|
||||
CBox monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
|
||||
|
||||
blend(false);
|
||||
|
||||
@@ -1731,7 +1819,7 @@ void CHyprOpenGLImpl::saveBufferForMirror() {
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderMirrored() {
|
||||
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
|
||||
CBox monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
|
||||
|
||||
const auto PFB = &m_mMonitorRenderResources[m_RenderData.pMonitor->pMirrorOf].monitorMirrorFB;
|
||||
|
||||
@@ -1766,7 +1854,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
|
||||
static auto* const PFORCEHYPRCHAN = &g_pConfigManager->getConfigValuePtr("misc:force_hypr_chan")->intValue;
|
||||
static auto* const PFORCEWALLPAPER = &g_pConfigManager->getConfigValuePtr("misc:force_default_wallpaper")->intValue;
|
||||
|
||||
const auto FORCEWALLPAPER = std::clamp(*PFORCEWALLPAPER, -1L, 2L);
|
||||
const auto FORCEWALLPAPER = std::clamp(*PFORCEWALLPAPER, static_cast<int64_t>(-1L), static_cast<int64_t>(2L));
|
||||
|
||||
// release the last tex if exists
|
||||
const auto PTEX = &m_mMonitorBGTextures[pMonitor];
|
||||
@@ -1834,7 +1922,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
|
||||
origin.x = (m_RenderData.pMonitor->vecTransformedSize.x - PTEX->m_vSize.x * scale) / 2.0;
|
||||
}
|
||||
|
||||
wlr_box box = {origin.x, origin.y, PTEX->m_vSize.x * scale, PTEX->m_vSize.y * scale};
|
||||
CBox box = {origin.x, origin.y, PTEX->m_vSize.x * scale, PTEX->m_vSize.y * scale};
|
||||
|
||||
m_mMonitorRenderResources[pMonitor].backgroundTexBox = box;
|
||||
|
||||
@@ -1890,6 +1978,7 @@ void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) {
|
||||
g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].mirrorSwapFB.release();
|
||||
g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].monitorMirrorFB.release();
|
||||
g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].blurFB.release();
|
||||
g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].offMainFB.release();
|
||||
g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].stencilTex.destroyTexture();
|
||||
g_pHyprOpenGL->m_mMonitorBGTextures[pMonitor].destroyTexture();
|
||||
g_pHyprOpenGL->m_mMonitorRenderResources.erase(pMonitor);
|
||||
@@ -1912,3 +2001,23 @@ void CHyprOpenGLImpl::setMatrixScaleTranslate(const Vector2D& translate, const f
|
||||
void CHyprOpenGLImpl::restoreMatrix() {
|
||||
memcpy(m_RenderData.projection, m_RenderData.savedProjection, 9 * sizeof(float));
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::bindOffMain() {
|
||||
m_RenderData.pCurrentMonData->offMainFB.bind();
|
||||
clear(CColor(0, 0, 0, 0));
|
||||
m_RenderData.currentFB = &m_RenderData.pCurrentMonData->offMainFB;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderOffToMain(CFramebuffer* off) {
|
||||
CBox monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
renderTexturePrimitive(off->m_cTex, &monbox);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::bindBackOnMain() {
|
||||
m_RenderData.pCurrentMonData->primaryFB.bind();
|
||||
m_RenderData.currentFB = &m_RenderData.pCurrentMonData->primaryFB;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::setMonitorTransformEnabled(bool enabled) {
|
||||
m_bEndFrame = !enabled;
|
||||
}
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include "Shader.hpp"
|
||||
#include "Texture.hpp"
|
||||
#include "Framebuffer.hpp"
|
||||
#include "Transformer.hpp"
|
||||
|
||||
#include "../debug/TracyDefines.hpp"
|
||||
|
||||
@@ -41,6 +42,7 @@ struct SMonitorRenderData {
|
||||
CFramebuffer primaryFB;
|
||||
CFramebuffer mirrorFB; // these are used for some effects,
|
||||
CFramebuffer mirrorSwapFB; // etc
|
||||
CFramebuffer offMainFB;
|
||||
|
||||
CFramebuffer monitorMirrorFB; // used for mirroring outputs
|
||||
|
||||
@@ -50,17 +52,19 @@ struct SMonitorRenderData {
|
||||
bool blurFBDirty = true;
|
||||
bool blurFBShouldRender = false;
|
||||
|
||||
wlr_box backgroundTexBox;
|
||||
CBox backgroundTexBox;
|
||||
|
||||
// Shaders
|
||||
bool m_bShadersInitialized = false;
|
||||
CShader m_shQUAD;
|
||||
CShader m_shRGBA;
|
||||
CShader m_shPASSTHRURGBA;
|
||||
CShader m_shMATTE;
|
||||
CShader m_shRGBX;
|
||||
CShader m_shEXT;
|
||||
CShader m_shBLUR1;
|
||||
CShader m_shBLUR2;
|
||||
CShader m_shBLURPREPARE;
|
||||
CShader m_shBLURFINISH;
|
||||
CShader m_shSHADOW;
|
||||
CShader m_shBORDER1;
|
||||
@@ -75,6 +79,7 @@ struct SCurrentRenderData {
|
||||
float savedProjection[9];
|
||||
|
||||
SMonitorRenderData* pCurrentMonData = nullptr;
|
||||
CFramebuffer* currentFB = nullptr;
|
||||
|
||||
CRegion damage;
|
||||
|
||||
@@ -86,7 +91,7 @@ struct SCurrentRenderData {
|
||||
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
|
||||
wlr_box clipBox = {};
|
||||
CBox clipBox = {};
|
||||
|
||||
uint32_t discardMode = DISCARD_OPAQUE;
|
||||
float discardOpacity = 0.f;
|
||||
@@ -102,14 +107,17 @@ class CHyprOpenGLImpl {
|
||||
void end();
|
||||
void bindWlrOutputFb();
|
||||
|
||||
void renderRect(wlr_box*, const CColor&, int round = 0);
|
||||
void renderRectWithBlur(wlr_box*, const CColor&, int round = 0, float blurA = 1.f);
|
||||
void renderRectWithDamage(wlr_box*, const CColor&, CRegion* damage, int round = 0);
|
||||
void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0, bool allowCustomUV = false);
|
||||
void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
|
||||
void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f);
|
||||
void renderRoundedShadow(wlr_box*, int round, int range, float a = 1.0);
|
||||
void renderBorder(wlr_box*, const CGradientValueData&, int round, int borderSize, float a = 1.0);
|
||||
void renderRect(CBox*, const CColor&, int round = 0);
|
||||
void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f);
|
||||
void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0);
|
||||
void renderTexture(wlr_texture*, CBox*, float a, int round = 0, bool allowCustomUV = false);
|
||||
void renderTexture(const CTexture&, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
|
||||
void renderTextureWithBlur(const CTexture&, CBox*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f);
|
||||
void renderRoundedShadow(CBox*, int round, int range, float a = 1.0);
|
||||
void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */);
|
||||
void renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte);
|
||||
|
||||
void setMonitorTransformEnabled(bool enabled);
|
||||
|
||||
void saveMatrix();
|
||||
void setMatrixScaleTranslate(const Vector2D& translate, const float& scale);
|
||||
@@ -125,7 +133,7 @@ class CHyprOpenGLImpl {
|
||||
|
||||
void clear(const CColor&);
|
||||
void clearWithTex();
|
||||
void scissor(const wlr_box*, bool transform = true);
|
||||
void scissor(const CBox*, bool transform = true);
|
||||
void scissor(const pixman_box32*, bool transform = true);
|
||||
void scissor(const int x, const int y, const int w, const int h, bool transform = true);
|
||||
|
||||
@@ -142,6 +150,10 @@ class CHyprOpenGLImpl {
|
||||
|
||||
void applyScreenShader(const std::string& path);
|
||||
|
||||
void bindOffMain();
|
||||
void renderOffToMain(CFramebuffer* off);
|
||||
void bindBackOnMain();
|
||||
|
||||
SCurrentRenderData m_RenderData;
|
||||
|
||||
GLint m_iCurrentOutputFb = 0;
|
||||
@@ -180,9 +192,9 @@ class CHyprOpenGLImpl {
|
||||
// returns the out FB, can be either Mirror or MirrorSwap
|
||||
CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage);
|
||||
|
||||
void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false,
|
||||
void renderTextureInternalWithDamage(const CTexture&, CBox* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false,
|
||||
bool allowCustomUV = false, bool allowDim = false);
|
||||
void renderTexturePrimitive(const CTexture& tex, wlr_box* pBox);
|
||||
void renderTexturePrimitive(const CTexture& tex, CBox* pBox);
|
||||
void renderSplash(cairo_t* const, cairo_surface_t* const, double);
|
||||
|
||||
void preBlurForCurrentMonitor();
|
||||
|
@@ -22,10 +22,31 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
|
||||
double outputX = 0, outputY = 0;
|
||||
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, RDATA->pMonitor->output, &outputX, &outputY);
|
||||
|
||||
wlr_box windowBox;
|
||||
if (RDATA->surface && surface == RDATA->surface)
|
||||
CBox windowBox;
|
||||
if (RDATA->surface && surface == RDATA->surface) {
|
||||
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, RDATA->w, RDATA->h};
|
||||
else { // here we clamp to 2, these might be some tiny specks
|
||||
|
||||
// however, if surface buffer w / h < box, we need to adjust them
|
||||
auto* const PSURFACE = CWLSurface::surfaceFromWlr(surface);
|
||||
|
||||
if (PSURFACE && !PSURFACE->m_bFillIgnoreSmall && PSURFACE->small() /* guarantees m_pOwner */) {
|
||||
const auto CORRECT = PSURFACE->correctSmallVec();
|
||||
const auto SIZE = PSURFACE->getViewporterCorrectedSize();
|
||||
const auto INTERACTIVERESIZEINPROGRESS = g_pInputManager->currentlyDraggedWindow == PSURFACE->m_pOwner && g_pInputManager->dragMode == MBIND_RESIZE;
|
||||
|
||||
if (!INTERACTIVERESIZEINPROGRESS) {
|
||||
windowBox.x += CORRECT.x;
|
||||
windowBox.y += CORRECT.y;
|
||||
|
||||
windowBox.width = SIZE.x * (PSURFACE->m_pOwner->m_vRealSize.vec().x / PSURFACE->m_pOwner->m_vReportedSize.x);
|
||||
windowBox.height = SIZE.y * (PSURFACE->m_pOwner->m_vRealSize.vec().y / PSURFACE->m_pOwner->m_vReportedSize.y);
|
||||
} else {
|
||||
windowBox.width = SIZE.x;
|
||||
windowBox.height = SIZE.y;
|
||||
}
|
||||
}
|
||||
|
||||
} else { // here we clamp to 2, these might be some tiny specks
|
||||
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, std::max(surface->current.width, 2), std::max(surface->current.height, 2)};
|
||||
if (RDATA->pWindow && RDATA->pWindow->m_vRealSize.isBeingAnimated() && RDATA->surface && RDATA->surface != surface && RDATA->squishOversized /* subsurface */) {
|
||||
// adjust subsurfaces to the window
|
||||
@@ -41,9 +62,13 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
|
||||
windowBox.height = RDATA->h - y;
|
||||
}
|
||||
|
||||
if (windowBox.width <= 1 || windowBox.height <= 1)
|
||||
return; // invisible
|
||||
|
||||
g_pHyprRenderer->calculateUVForSurface(RDATA->pWindow, surface, RDATA->squishOversized);
|
||||
|
||||
scaleBox(&windowBox, RDATA->pMonitor->scale);
|
||||
windowBox.scale(RDATA->pMonitor->scale);
|
||||
windowBox.round();
|
||||
|
||||
float rounding = RDATA->rounding;
|
||||
|
||||
@@ -52,7 +77,8 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
|
||||
if (RDATA->dontRound)
|
||||
rounding = 0;
|
||||
|
||||
const bool CANDISABLEBLEND = RDATA->alpha >= 1.f && rounding == 0 && surface->opaque;
|
||||
const bool WINDOWOPAQUE = RDATA->pWindow && RDATA->pWindow->m_pWLSurface.wlr() == surface ? RDATA->pWindow->opaque() : false;
|
||||
const bool CANDISABLEBLEND = RDATA->alpha * RDATA->fadeAlpha >= 1.f && rounding == 0 && (WINDOWOPAQUE || surface->opaque);
|
||||
|
||||
if (CANDISABLEBLEND)
|
||||
g_pHyprOpenGL->blend(false);
|
||||
@@ -85,9 +111,9 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
|
||||
}
|
||||
|
||||
bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, CMonitor* pMonitor, CWorkspace* pWorkspace) {
|
||||
wlr_box geometry = pWindow->getFullWindowBoundingBox();
|
||||
CBox geometry = pWindow->getFullWindowBoundingBox();
|
||||
|
||||
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, &geometry))
|
||||
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, geometry.pWlr()))
|
||||
return false;
|
||||
|
||||
if (pWindow->m_iWorkspaceID == -1)
|
||||
@@ -316,8 +342,16 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
const auto REALPOS = pWindow->m_vRealPosition.vec() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset.vec());
|
||||
static auto* const PDIMAROUND = &g_pConfigManager->getConfigValuePtr("decoration:dim_around")->floatValue;
|
||||
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||
static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue;
|
||||
|
||||
SRenderData renderdata = {pMonitor, time};
|
||||
CBox textureBox = {REALPOS.x, REALPOS.y, std::max(pWindow->m_vRealSize.vec().x, 5.0), std::max(pWindow->m_vRealSize.vec().y, 5.0)};
|
||||
|
||||
renderdata.x = textureBox.x;
|
||||
renderdata.y = textureBox.y;
|
||||
renderdata.w = textureBox.w;
|
||||
renderdata.h = textureBox.h;
|
||||
|
||||
SRenderData renderdata = {pMonitor, time, REALPOS.x, REALPOS.y};
|
||||
if (ignorePosition) {
|
||||
renderdata.x = pMonitor->vecPosition.x;
|
||||
renderdata.y = pMonitor->vecPosition.y;
|
||||
@@ -327,8 +361,6 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
decorate = false;
|
||||
|
||||
renderdata.surface = pWindow->m_pWLSurface.wlr();
|
||||
renderdata.w = std::max(pWindow->m_vRealSize.vec().x, 5.0); // clamp the size to min 5,
|
||||
renderdata.h = std::max(pWindow->m_vRealSize.vec().y, 5.0); // otherwise we'll have issues later with invalid boxes
|
||||
renderdata.dontRound = (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) || (!pWindow->m_sSpecialRenderData.rounding);
|
||||
renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (pWindow->m_bPinned ? 1.f : PWORKSPACE->m_fAlpha.fl());
|
||||
renderdata.alpha = pWindow->m_fActiveInactiveAlpha.fl();
|
||||
@@ -351,13 +383,15 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
EMIT_HOOK_EVENT("render", RENDER_PRE_WINDOW);
|
||||
|
||||
if (*PDIMAROUND && pWindow->m_sAdditionalConfigData.dimAround && !m_bRenderingSnapshot && mode != RENDER_PASS_POPUP) {
|
||||
wlr_box monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
CBox monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMAROUND * renderdata.alpha * renderdata.fadeAlpha));
|
||||
}
|
||||
|
||||
// clip box for animated offsets
|
||||
Vector2D offset;
|
||||
const Vector2D PREOFFSETPOS = {renderdata.x, renderdata.y};
|
||||
if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bPinned) {
|
||||
Vector2D offset;
|
||||
|
||||
if (PWORKSPACE->m_vRenderOffset.vec().x != 0) {
|
||||
const auto PWSMON = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
||||
const auto PROGRESS = PWORKSPACE->m_vRenderOffset.vec().x / PWSMON->vecSize.x;
|
||||
@@ -386,14 +420,44 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
|
||||
// render window decorations first, if not fullscreen full
|
||||
if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_MAIN) {
|
||||
if (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL)
|
||||
for (auto& wd : pWindow->m_dWindowDecorations)
|
||||
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, offset);
|
||||
|
||||
const bool TRANSFORMERSPRESENT = !pWindow->m_vTransformers.empty();
|
||||
|
||||
if (TRANSFORMERSPRESENT) {
|
||||
g_pHyprOpenGL->bindOffMain();
|
||||
|
||||
for (auto& t : pWindow->m_vTransformers) {
|
||||
t->preWindowRender(&renderdata);
|
||||
}
|
||||
}
|
||||
|
||||
if (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL) {
|
||||
for (auto& wd : pWindow->m_dWindowDecorations) {
|
||||
if (wd->getDecorationLayer() != DECORATION_LAYER_BOTTOM)
|
||||
continue;
|
||||
|
||||
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, Vector2D{renderdata.x, renderdata.y} - PREOFFSETPOS);
|
||||
}
|
||||
|
||||
for (auto& wd : pWindow->m_dWindowDecorations) {
|
||||
if (wd->getDecorationLayer() != DECORATION_LAYER_UNDER)
|
||||
continue;
|
||||
|
||||
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, Vector2D{renderdata.x, renderdata.y} - PREOFFSETPOS);
|
||||
}
|
||||
}
|
||||
|
||||
static auto* const PXWLUSENN = &g_pConfigManager->getConfigValuePtr("xwayland:use_nearest_neighbor")->intValue;
|
||||
if (pWindow->m_bIsX11 && *PXWLUSENN)
|
||||
if ((pWindow->m_bIsX11 && *PXWLUSENN) || pWindow->m_sAdditionalConfigData.nearestNeighbor.toUnderlying())
|
||||
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true;
|
||||
|
||||
if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall && renderdata.blur && *PBLUR) {
|
||||
CBox wb = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h};
|
||||
wb.scale(pMonitor->scale).round();
|
||||
g_pHyprOpenGL->renderRectWithBlur(&wb, CColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1, renderdata.fadeAlpha);
|
||||
renderdata.blur = false;
|
||||
}
|
||||
|
||||
wlr_surface_for_each_surface(pWindow->m_pWLSurface.wlr(), renderSurface, &renderdata);
|
||||
|
||||
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false;
|
||||
@@ -408,9 +472,9 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
grad.m_fAngle = normalizeAngleRad(grad.m_fAngle);
|
||||
}
|
||||
|
||||
wlr_box windowBox = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h};
|
||||
CBox windowBox = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h};
|
||||
|
||||
scaleBox(&windowBox, pMonitor->scale);
|
||||
windowBox.scale(pMonitor->scale).round();
|
||||
|
||||
int borderSize = pWindow->m_sSpecialRenderData.borderSize.toUnderlying() == -1 ? *PBORDERSIZE : pWindow->m_sSpecialRenderData.borderSize.toUnderlying();
|
||||
if (pWindow->m_sAdditionalConfigData.borderSize.toUnderlying() != -1)
|
||||
@@ -423,12 +487,31 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
g_pHyprOpenGL->renderBorder(&windowBox, g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColorPrevious, renderdata.rounding, borderSize, a2);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& wd : pWindow->m_dWindowDecorations) {
|
||||
if (wd->getDecorationLayer() != DECORATION_LAYER_OVER)
|
||||
continue;
|
||||
|
||||
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, Vector2D{renderdata.x, renderdata.y} - PREOFFSETPOS);
|
||||
}
|
||||
|
||||
if (TRANSFORMERSPRESENT) {
|
||||
|
||||
CFramebuffer* last = g_pHyprOpenGL->m_RenderData.currentFB;
|
||||
for (auto& t : pWindow->m_vTransformers) {
|
||||
last = t->transform(last);
|
||||
}
|
||||
|
||||
g_pHyprOpenGL->bindBackOnMain();
|
||||
g_pHyprOpenGL->renderOffToMain(last);
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_POPUP) {
|
||||
if (!pWindow->m_bIsX11) {
|
||||
wlr_box geom;
|
||||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom);
|
||||
CBox geom;
|
||||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, geom.pWlr());
|
||||
geom.applyFromWlr();
|
||||
|
||||
renderdata.x -= geom.x;
|
||||
renderdata.y -= geom.y;
|
||||
@@ -436,7 +519,20 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
renderdata.dontRound = true; // don't round popups
|
||||
renderdata.pMonitor = pMonitor;
|
||||
renderdata.squishOversized = false; // don't squish popups
|
||||
|
||||
if (pWindow->m_sAdditionalConfigData.nearestNeighbor.toUnderlying())
|
||||
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true;
|
||||
|
||||
wlr_xdg_surface_for_each_popup_surface(pWindow->m_uSurface.xdg, renderSurface, &renderdata);
|
||||
|
||||
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false;
|
||||
}
|
||||
|
||||
for (auto& wd : pWindow->m_dWindowDecorations) {
|
||||
if (wd->getDecorationLayer() != DECORATION_LAYER_OVERLAY)
|
||||
continue;
|
||||
|
||||
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, Vector2D{renderdata.x, renderdata.y} - PREOFFSETPOS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -515,7 +611,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace*
|
||||
|
||||
if (!g_pCompositor->m_sSeat.exclusiveClient && g_pSessionLockManager->isSessionLocked()) {
|
||||
// locked with no exclusive, draw only red
|
||||
wlr_box boxe = {0, 0, INT16_MAX, INT16_MAX};
|
||||
CBox boxe = {0, 0, INT16_MAX, INT16_MAX};
|
||||
g_pHyprOpenGL->renderRect(&boxe, CColor(1.0, 0.2, 0.2, 1.0));
|
||||
return;
|
||||
}
|
||||
@@ -565,12 +661,12 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace*
|
||||
const bool ANIMOUT = !pMonitor->specialWorkspaceID;
|
||||
|
||||
if (*PDIMSPECIAL != 0.f) {
|
||||
wlr_box monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale};
|
||||
CBox monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale};
|
||||
g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMSPECIAL * (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS)));
|
||||
}
|
||||
|
||||
if (*PBLURSPECIAL && *PBLUR) {
|
||||
wlr_box monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale};
|
||||
CBox monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale};
|
||||
g_pHyprOpenGL->renderRectWithBlur(&monbox, CColor(0, 0, 0, 0), 0, (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS));
|
||||
}
|
||||
|
||||
@@ -622,7 +718,7 @@ void CHyprRenderer::renderLockscreen(CMonitor* pMonitor, timespec* now) {
|
||||
|
||||
if (!PSLS) {
|
||||
// locked with no surface, fill with red
|
||||
wlr_box boxe = {0, 0, INT16_MAX, INT16_MAX};
|
||||
CBox boxe = {0, 0, INT16_MAX, INT16_MAX};
|
||||
g_pHyprOpenGL->renderRect(&boxe, CColor(1.0, 0.2, 0.2, 1.0));
|
||||
} else {
|
||||
renderSessionLockSurface(PSLS, pMonitor, now);
|
||||
@@ -664,11 +760,12 @@ void CHyprRenderer::calculateUVForSurface(CWindow* pWindow, wlr_surface* pSurfac
|
||||
if (!main || !pWindow)
|
||||
return;
|
||||
|
||||
wlr_box geom;
|
||||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom);
|
||||
CBox geom;
|
||||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, geom.pWlr());
|
||||
geom.applyFromWlr();
|
||||
|
||||
// ignore X and Y, adjust uv
|
||||
if (geom.x != 0 || geom.y != 0 || geom.width > pWindow->m_vRealSize.goalv().x || geom.height > pWindow->m_vRealSize.goalv().y) {
|
||||
if (geom.x != 0 || geom.y != 0 || geom.width > pWindow->m_vRealSize.vec().x || geom.height > pWindow->m_vRealSize.vec().y) {
|
||||
const auto XPERC = (double)geom.x / (double)pSurface->current.width;
|
||||
const auto YPERC = (double)geom.y / (double)pSurface->current.height;
|
||||
const auto WPERC = (double)(geom.x + geom.width) / (double)pSurface->current.width;
|
||||
@@ -678,9 +775,9 @@ void CHyprRenderer::calculateUVForSurface(CWindow* pWindow, wlr_surface* pSurfac
|
||||
uvBR = uvBR - Vector2D(1.0 - WPERC * (uvBR.x - uvTL.x), 1.0 - HPERC * (uvBR.y - uvTL.y));
|
||||
uvTL = uvTL + TOADDTL;
|
||||
|
||||
if (geom.width > pWindow->m_vRealSize.goalv().x || geom.height > pWindow->m_vRealSize.goalv().y) {
|
||||
uvBR.x = uvBR.x * (pWindow->m_vRealSize.goalv().x / geom.width);
|
||||
uvBR.y = uvBR.y * (pWindow->m_vRealSize.goalv().y / geom.height);
|
||||
if (geom.width > pWindow->m_vRealSize.vec().x || geom.height > pWindow->m_vRealSize.vec().y) {
|
||||
uvBR.x = uvBR.x * (pWindow->m_vRealSize.vec().x / geom.width);
|
||||
uvBR.y = uvBR.y * (pWindow->m_vRealSize.vec().y / geom.height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -984,7 +1081,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||
}
|
||||
g_pHyprOpenGL->blend(true);
|
||||
|
||||
wlr_box renderBox = {0, 0, (int)pMonitor->vecPixelSize.x, (int)pMonitor->vecPixelSize.y};
|
||||
CBox renderBox = {0, 0, (int)pMonitor->vecPixelSize.x, (int)pMonitor->vecPixelSize.y};
|
||||
renderWorkspace(pMonitor, g_pCompositor->getWorkspaceByID(pMonitor->activeWorkspace), &now, renderBox);
|
||||
|
||||
renderLockscreen(pMonitor, &now);
|
||||
@@ -1002,7 +1099,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||
}
|
||||
|
||||
if (*PDAMAGEBLINK && damageBlinkCleanup == 0) {
|
||||
wlr_box monrect = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y};
|
||||
CBox monrect = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y};
|
||||
g_pHyprOpenGL->renderRect(&monrect, CColor(1.0, 0.0, 1.0, 100.0 / 255.0), 0);
|
||||
damageBlinkCleanup = 1;
|
||||
} else if (*PDAMAGEBLINK) {
|
||||
@@ -1104,7 +1201,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const wlr_box& geometry) {
|
||||
void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const CBox& geometry) {
|
||||
Vector2D translate = {geometry.x, geometry.y};
|
||||
float scale = (float)geometry.width / pMonitor->vecPixelSize.x;
|
||||
|
||||
@@ -1261,8 +1358,8 @@ void apply_exclusive(struct wlr_box* usable_area, uint32_t anchor, int32_t exclu
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vector<std::unique_ptr<SLayerSurface>>& layerSurfaces, bool exclusiveZone, wlr_box* usableArea) {
|
||||
wlr_box full_area = {pMonitor->vecPosition.x, pMonitor->vecPosition.y, pMonitor->vecSize.x, pMonitor->vecSize.y};
|
||||
void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vector<std::unique_ptr<SLayerSurface>>& layerSurfaces, bool exclusiveZone, CBox* usableArea) {
|
||||
CBox full_area = {pMonitor->vecPosition.x, pMonitor->vecPosition.y, pMonitor->vecSize.x, pMonitor->vecSize.y};
|
||||
|
||||
for (auto& ls : layerSurfaces) {
|
||||
if (ls->fadingOut || ls->readyToDelete || !ls->layerSurface || ls->noProcess)
|
||||
@@ -1273,7 +1370,7 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vector<std:
|
||||
if (exclusiveZone != (PSTATE->exclusive_zone > 0))
|
||||
continue;
|
||||
|
||||
wlr_box bounds;
|
||||
CBox bounds;
|
||||
if (PSTATE->exclusive_zone == -1)
|
||||
bounds = full_area;
|
||||
else
|
||||
@@ -1281,7 +1378,7 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vector<std:
|
||||
|
||||
const Vector2D OLDSIZE = {ls->geometry.width, ls->geometry.height};
|
||||
|
||||
wlr_box box = {.width = PSTATE->desired_width, .height = PSTATE->desired_height};
|
||||
CBox box = {0, 0, PSTATE->desired_width, PSTATE->desired_height};
|
||||
// Horizontal axis
|
||||
const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
|
||||
if (box.width == 0) {
|
||||
@@ -1336,7 +1433,9 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vector<std:
|
||||
// Apply
|
||||
ls->geometry = box;
|
||||
|
||||
apply_exclusive(usableArea, PSTATE->anchor, PSTATE->exclusive_zone, PSTATE->margin.top, PSTATE->margin.right, PSTATE->margin.bottom, PSTATE->margin.left);
|
||||
apply_exclusive(usableArea->pWlr(), PSTATE->anchor, PSTATE->exclusive_zone, PSTATE->margin.top, PSTATE->margin.right, PSTATE->margin.bottom, PSTATE->margin.left);
|
||||
|
||||
usableArea->applyFromWlr();
|
||||
|
||||
if (Vector2D{box.width, box.height} != OLDSIZE)
|
||||
wlr_layer_surface_v1_configure(ls->layerSurface, box.width, box.height);
|
||||
@@ -1356,7 +1455,7 @@ void CHyprRenderer::arrangeLayersForMonitor(const int& monitor) {
|
||||
PMONITOR->vecReservedBottomRight = Vector2D();
|
||||
PMONITOR->vecReservedTopLeft = Vector2D();
|
||||
|
||||
wlr_box usableArea = {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||
CBox usableArea = {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||
|
||||
for (auto& la : PMONITOR->m_aLayerSurfaceLayers)
|
||||
arrangeLayerArray(PMONITOR, la, true, &usableArea);
|
||||
@@ -1392,6 +1491,13 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y, dou
|
||||
if (g_pCompositor->m_bUnsafeState)
|
||||
return;
|
||||
|
||||
auto* const PSURFACE = CWLSurface::surfaceFromWlr(pSurface);
|
||||
if (PSURFACE && PSURFACE->m_pOwner && PSURFACE->small()) {
|
||||
const auto CORRECTION = PSURFACE->correctSmallVec();
|
||||
x += CORRECTION.x;
|
||||
y += CORRECTION.y;
|
||||
}
|
||||
|
||||
CRegion damageBox;
|
||||
wlr_surface_get_effective_damage(pSurface, damageBox.pixman());
|
||||
if (scale != 1.0)
|
||||
@@ -1433,10 +1539,10 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) {
|
||||
if (g_pCompositor->m_bUnsafeState)
|
||||
return;
|
||||
|
||||
wlr_box damageBox = pWindow->getFullWindowBoundingBox();
|
||||
CBox damageBox = pWindow->getFullWindowBoundingBox();
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
wlr_box fixedDamageBox = {damageBox.x - m->vecPosition.x, damageBox.y - m->vecPosition.y, damageBox.width, damageBox.height};
|
||||
scaleBox(&fixedDamageBox, m->scale);
|
||||
CBox fixedDamageBox = {damageBox.x - m->vecPosition.x, damageBox.y - m->vecPosition.y, damageBox.width, damageBox.height};
|
||||
fixedDamageBox.scale(m->scale);
|
||||
m->addDamage(&fixedDamageBox);
|
||||
}
|
||||
|
||||
@@ -1453,7 +1559,7 @@ void CHyprRenderer::damageMonitor(CMonitor* pMonitor) {
|
||||
if (g_pCompositor->m_bUnsafeState || pMonitor->isMirror())
|
||||
return;
|
||||
|
||||
wlr_box damageBox = {0, 0, INT16_MAX, INT16_MAX};
|
||||
CBox damageBox = {0, 0, INT16_MAX, INT16_MAX};
|
||||
pMonitor->addDamage(&damageBox);
|
||||
|
||||
static auto* const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
||||
@@ -1462,7 +1568,7 @@ void CHyprRenderer::damageMonitor(CMonitor* pMonitor) {
|
||||
Debug::log(LOG, "Damage: Monitor {}", pMonitor->szName);
|
||||
}
|
||||
|
||||
void CHyprRenderer::damageBox(wlr_box* pBox) {
|
||||
void CHyprRenderer::damageBox(CBox* pBox) {
|
||||
if (g_pCompositor->m_bUnsafeState)
|
||||
return;
|
||||
|
||||
@@ -1470,8 +1576,8 @@ void CHyprRenderer::damageBox(wlr_box* pBox) {
|
||||
if (m->isMirror())
|
||||
continue; // don't damage mirrors traditionally
|
||||
|
||||
wlr_box damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height};
|
||||
scaleBox(&damageBox, m->scale);
|
||||
CBox damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height};
|
||||
damageBox.scale(m->scale);
|
||||
m->addDamage(&damageBox);
|
||||
}
|
||||
|
||||
@@ -1482,7 +1588,7 @@ void CHyprRenderer::damageBox(wlr_box* pBox) {
|
||||
}
|
||||
|
||||
void CHyprRenderer::damageBox(const int& x, const int& y, const int& w, const int& h) {
|
||||
wlr_box box = {x, y, w, h};
|
||||
CBox box = {x, y, w, h};
|
||||
damageBox(&box);
|
||||
}
|
||||
|
||||
@@ -1515,8 +1621,8 @@ void CHyprRenderer::renderDragIcon(CMonitor* pMonitor, timespec* time) {
|
||||
|
||||
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};
|
||||
CBox 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);
|
||||
}
|
||||
|
||||
@@ -1808,7 +1914,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
bool set10bit = false;
|
||||
bool set10bit = false;
|
||||
pMonitor->drmFormat = DRM_FORMAT_INVALID;
|
||||
|
||||
for (auto& fmt : formats[(int)!pMonitorRule->enable10bit]) {
|
||||
wlr_output_set_render_format(pMonitor->output, fmt.second);
|
||||
@@ -1819,6 +1926,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
Debug::log(LOG, "output {} succeeded basic test on format {}", pMonitor->szName, fmt.first);
|
||||
if (pMonitorRule->enable10bit && fmt.first.contains("101010"))
|
||||
set10bit = true;
|
||||
|
||||
pMonitor->drmFormat = fmt.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1835,9 +1944,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
pMonitor->vecTransformedSize = Vector2D(x, y);
|
||||
|
||||
if (pMonitor->createdByUser) {
|
||||
wlr_box transformedBox = {0, 0, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y};
|
||||
wlr_box_transform(&transformedBox, &transformedBox, wlr_output_transform_invert(pMonitor->output->transform), (int)pMonitor->vecTransformedSize.x,
|
||||
(int)pMonitor->vecTransformedSize.y);
|
||||
CBox transformedBox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y};
|
||||
transformedBox.transform(wlr_output_transform_invert(pMonitor->output->transform), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y);
|
||||
|
||||
pMonitor->vecPixelSize = Vector2D(transformedBox.width, transformedBox.height);
|
||||
}
|
||||
@@ -1872,11 +1980,23 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
void CHyprRenderer::setCursorSurface(wlr_surface* surf, int hotspotX, int hotspotY) {
|
||||
m_bCursorHasSurface = surf;
|
||||
|
||||
if (surf == m_sLastCursorData.surf)
|
||||
return;
|
||||
|
||||
m_sLastCursorData.name = "";
|
||||
m_sLastCursorData.surf = surf;
|
||||
|
||||
wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, surf, hotspotX, hotspotY);
|
||||
}
|
||||
void CHyprRenderer::setCursorFromName(const std::string& name) {
|
||||
m_bCursorHasSurface = true;
|
||||
|
||||
if (name == m_sLastCursorData.name)
|
||||
return;
|
||||
|
||||
m_sLastCursorData.name = name;
|
||||
m_sLastCursorData.surf.reset();
|
||||
|
||||
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, name.c_str());
|
||||
}
|
||||
|
||||
@@ -1981,9 +2101,9 @@ void CHyprRenderer::setOccludedForBackLayers(CRegion& region, CWorkspace* pWorks
|
||||
const Vector2D POS = w->m_vRealPosition.vec() + Vector2D{ROUNDING, ROUNDING} - PMONITOR->vecPosition + (w->m_bPinned ? Vector2D{} : pWorkspace->m_vRenderOffset.vec());
|
||||
const Vector2D SIZE = w->m_vRealSize.vec() - Vector2D{ROUNDING * 2, ROUNDING * 2};
|
||||
|
||||
wlr_box box = {POS.x, POS.y, SIZE.x, SIZE.y};
|
||||
CBox box = {POS.x, POS.y, SIZE.x, SIZE.y};
|
||||
|
||||
scaleBox(&box, PMONITOR->scale);
|
||||
box.scale(PMONITOR->scale);
|
||||
|
||||
rg.add(&box);
|
||||
}
|
||||
|
@@ -40,7 +40,7 @@ class CHyprRenderer {
|
||||
void arrangeLayersForMonitor(const int&);
|
||||
void damageSurface(wlr_surface*, double, double, double scale = 1.0);
|
||||
void damageWindow(CWindow*);
|
||||
void damageBox(wlr_box*);
|
||||
void damageBox(CBox*);
|
||||
void damageBox(const int& x, const int& y, const int& w, const int& h);
|
||||
void damageRegion(const CRegion&);
|
||||
void damageMonitor(CMonitor*);
|
||||
@@ -83,8 +83,13 @@ class CHyprRenderer {
|
||||
|
||||
CTimer m_tRenderTimer;
|
||||
|
||||
struct {
|
||||
std::optional<wlr_surface*> surf = nullptr;
|
||||
std::string name;
|
||||
} m_sLastCursorData;
|
||||
|
||||
private:
|
||||
void arrangeLayerArray(CMonitor*, const std::vector<std::unique_ptr<SLayerSurface>>&, bool, wlr_box*);
|
||||
void arrangeLayerArray(CMonitor*, const std::vector<std::unique_ptr<SLayerSurface>>&, bool, CBox*);
|
||||
void renderWorkspaceWindowsFullscreen(CMonitor*, CWorkspace*, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special)
|
||||
void renderWorkspaceWindows(CMonitor*, CWorkspace*, timespec*); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special)
|
||||
void renderWindow(CWindow*, CMonitor*, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool ignoreAllGeometry = false);
|
||||
@@ -92,7 +97,7 @@ class CHyprRenderer {
|
||||
void renderSessionLockSurface(SSessionLockSurface*, CMonitor*, timespec*);
|
||||
void renderDragIcon(CMonitor*, timespec*);
|
||||
void renderIMEPopup(SIMEPopup*, CMonitor*, timespec*);
|
||||
void renderWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const wlr_box& geometry);
|
||||
void renderWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const CBox& geometry);
|
||||
void renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f);
|
||||
|
||||
bool m_bHasARenderedCursor = true;
|
||||
|
@@ -10,10 +10,12 @@ class CShader {
|
||||
GLuint program = 0;
|
||||
GLint proj = -1;
|
||||
GLint color = -1;
|
||||
GLint alphaMatte = -1;
|
||||
GLint tex = -1;
|
||||
GLint alpha = -1;
|
||||
GLint posAttrib = -1;
|
||||
GLint texAttrib = -1;
|
||||
GLint matteTexAttrib = -1;
|
||||
GLint discardOpaque = -1;
|
||||
GLint discardAlpha = -1;
|
||||
GLfloat discardAlphaValue = -1;
|
||||
@@ -23,13 +25,15 @@ class CShader {
|
||||
GLint fullSize = -1;
|
||||
GLint fullSizeUntransformed = -1;
|
||||
GLint radius = -1;
|
||||
GLint radiusOuter = -1;
|
||||
|
||||
GLint thick = -1;
|
||||
|
||||
GLint halfpixel = -1;
|
||||
|
||||
GLint range = -1;
|
||||
GLint shadowPower = -1;
|
||||
GLint range = -1;
|
||||
GLint shadowPower = -1;
|
||||
GLint useAlphaMatte = -1; // always inverted
|
||||
|
||||
GLint applyTint = -1;
|
||||
GLint tint = -1;
|
||||
@@ -42,13 +46,21 @@ class CShader {
|
||||
GLint distort = -1;
|
||||
GLint output = -1;
|
||||
|
||||
GLint noise = -1;
|
||||
GLint contrast = -1;
|
||||
GLint brightness = -1;
|
||||
// Blur prepare
|
||||
GLint contrast = -1;
|
||||
|
||||
GLint getUniformLocation(const std::string&);
|
||||
// Blur
|
||||
GLint passes = -1; // Used by `vibrancy`
|
||||
GLint vibrancy = -1;
|
||||
GLint vibrancy_darkness = -1;
|
||||
|
||||
void destroy();
|
||||
// Blur finish
|
||||
GLint brightness = -1;
|
||||
GLint noise = -1;
|
||||
|
||||
GLint getUniformLocation(const std::string&);
|
||||
|
||||
void destroy();
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, GLint> m_muUniforms;
|
||||
|
5
src/render/Transformer.cpp
Normal file
5
src/render/Transformer.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "Transformer.hpp"
|
||||
|
||||
void IWindowTransformer::preWindowRender(SRenderData* pRenderData) {
|
||||
;
|
||||
}
|
20
src/render/Transformer.hpp
Normal file
20
src/render/Transformer.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "Framebuffer.hpp"
|
||||
|
||||
struct SRenderData;
|
||||
|
||||
// A window transformer can be attached to a window.
|
||||
// If any is attached, Hyprland will render the window to a separate fb, then call the transform() func with it,
|
||||
// and finally render it back to the main fb after all transformers pass.
|
||||
//
|
||||
// Worth noting transformers for now only affect the main pass (not popups)
|
||||
class IWindowTransformer {
|
||||
public:
|
||||
// called by Hyprland. For more data about what is being rendered, inspect render data.
|
||||
// returns the out fb.
|
||||
virtual CFramebuffer* transform(CFramebuffer* in) = 0;
|
||||
|
||||
// called by Hyprland before a window main pass is started.
|
||||
virtual void preWindowRender(SRenderData* pRenderData);
|
||||
};
|
@@ -29,8 +29,8 @@ void CHyprDropShadowDecoration::damageEntire() {
|
||||
if (*PSHADOWS != 1)
|
||||
return; // disabled
|
||||
|
||||
wlr_box dm = {m_vLastWindowPos.x - m_seExtents.topLeft.x, m_vLastWindowPos.y - m_seExtents.topLeft.y, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x,
|
||||
m_vLastWindowSize.y + m_seExtents.topLeft.y + m_seExtents.bottomRight.y};
|
||||
CBox dm = {m_vLastWindowPos.x - m_seExtents.topLeft.x, m_vLastWindowPos.y - m_seExtents.topLeft.y, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x,
|
||||
m_vLastWindowSize.y + m_seExtents.topLeft.y + m_seExtents.bottomRight.y};
|
||||
g_pHyprRenderer->damageBox(&dm);
|
||||
}
|
||||
|
||||
@@ -45,6 +45,31 @@ void CHyprDropShadowDecoration::updateWindow(CWindow* pWindow) {
|
||||
m_vLastWindowSize = pWindow->m_vRealSize.vec();
|
||||
|
||||
damageEntire();
|
||||
|
||||
const auto BORDER = m_pWindow->getRealBorderSize();
|
||||
|
||||
// calculate extents of decos with the DECORATION_PART_OF_MAIN_WINDOW flag
|
||||
SWindowDecorationExtents maxExtents;
|
||||
|
||||
for (auto& wd : m_pWindow->m_dWindowDecorations) {
|
||||
// conveniently, this will also skip us.
|
||||
if (!(wd->getDecorationFlags() & DECORATION_PART_OF_MAIN_WINDOW))
|
||||
continue;
|
||||
|
||||
const auto EXTENTS = wd->getWindowDecorationExtents();
|
||||
|
||||
if (maxExtents.topLeft.x < EXTENTS.topLeft.x)
|
||||
maxExtents.topLeft.x = EXTENTS.topLeft.x;
|
||||
if (maxExtents.topLeft.y < EXTENTS.topLeft.y)
|
||||
maxExtents.topLeft.y = EXTENTS.topLeft.y;
|
||||
if (maxExtents.bottomRight.x < EXTENTS.bottomRight.x)
|
||||
maxExtents.bottomRight.x = EXTENTS.bottomRight.x;
|
||||
if (maxExtents.bottomRight.y < EXTENTS.bottomRight.y)
|
||||
maxExtents.bottomRight.y = EXTENTS.bottomRight.y;
|
||||
}
|
||||
|
||||
m_bLastWindowBox = {m_vLastWindowPos.x, m_vLastWindowPos.y, m_vLastWindowSize.x, m_vLastWindowSize.y};
|
||||
m_eLastExtents = {{maxExtents.topLeft + Vector2D{BORDER, BORDER}}, {maxExtents.bottomRight + Vector2D{BORDER, BORDER}}};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +92,6 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D
|
||||
|
||||
static auto* const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
|
||||
static auto* const PSHADOWSIZE = &g_pConfigManager->getConfigValuePtr("decoration:shadow_range")->intValue;
|
||||
static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
|
||||
static auto* const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue;
|
||||
static auto* const PSHADOWSCALE = &g_pConfigManager->getConfigValuePtr("decoration:shadow_scale")->floatValue;
|
||||
static auto* const PSHADOWOFFSET = &g_pConfigManager->getConfigValuePtr("decoration:shadow_offset")->vecValue;
|
||||
@@ -75,84 +99,72 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D
|
||||
if (*PSHADOWS != 1)
|
||||
return; // disabled
|
||||
|
||||
const auto ROUNDING = !m_pWindow->m_sSpecialRenderData.rounding ?
|
||||
0 :
|
||||
(m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? *PROUNDING : m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying());
|
||||
const auto ROUNDING = m_pWindow->rounding() + m_pWindow->getRealBorderSize();
|
||||
|
||||
// draw the shadow
|
||||
wlr_box fullBox = {m_vLastWindowPos.x - *PSHADOWSIZE, m_vLastWindowPos.y - *PSHADOWSIZE, m_vLastWindowSize.x + 2.0 * *PSHADOWSIZE, m_vLastWindowSize.y + 2.0 * *PSHADOWSIZE};
|
||||
|
||||
fullBox.x -= pMonitor->vecPosition.x;
|
||||
fullBox.y -= pMonitor->vecPosition.y;
|
||||
CBox fullBox = {m_bLastWindowBox.x, m_bLastWindowBox.y, m_bLastWindowBox.width, m_bLastWindowBox.height};
|
||||
fullBox.addExtents(m_eLastExtents).translate(-pMonitor->vecPosition);
|
||||
fullBox.x -= *PSHADOWSIZE;
|
||||
fullBox.y -= *PSHADOWSIZE;
|
||||
fullBox.w += 2 * *PSHADOWSIZE;
|
||||
fullBox.h += 2 * *PSHADOWSIZE;
|
||||
|
||||
const float SHADOWSCALE = std::clamp(*PSHADOWSCALE, 0.f, 1.f);
|
||||
|
||||
// scale the box in relation to the center of the box
|
||||
const Vector2D NEWSIZE = Vector2D{fullBox.width, fullBox.height} * SHADOWSCALE;
|
||||
fullBox.width = NEWSIZE.x;
|
||||
fullBox.height = NEWSIZE.y;
|
||||
|
||||
if (PSHADOWOFFSET->x < 0) {
|
||||
fullBox.x += PSHADOWOFFSET->x;
|
||||
} else if (PSHADOWOFFSET->x > 0) {
|
||||
fullBox.x = m_vLastWindowPos.x + m_vLastWindowSize.x - fullBox.width + (SHADOWSCALE * *PSHADOWSIZE) + PSHADOWOFFSET->x - pMonitor->vecPosition.x;
|
||||
} else {
|
||||
fullBox.x += ((m_vLastWindowSize.x + 2.0 * *PSHADOWSIZE) - NEWSIZE.x) / 2.0;
|
||||
}
|
||||
|
||||
if (PSHADOWOFFSET->y < 0) {
|
||||
fullBox.y += PSHADOWOFFSET->y;
|
||||
} else if (PSHADOWOFFSET->y > 0) {
|
||||
fullBox.y = m_vLastWindowPos.y + m_vLastWindowSize.y - fullBox.height + (SHADOWSCALE * *PSHADOWSIZE) + PSHADOWOFFSET->y - pMonitor->vecPosition.y;
|
||||
} else {
|
||||
fullBox.y += ((m_vLastWindowSize.y + 2.0 * *PSHADOWSIZE) - NEWSIZE.y) / 2.0;
|
||||
}
|
||||
fullBox.scaleFromCenter(SHADOWSCALE).translate(*PSHADOWOFFSET);
|
||||
|
||||
m_seExtents = {{m_vLastWindowPos.x - fullBox.x - pMonitor->vecPosition.x + 2, m_vLastWindowPos.y - fullBox.y - pMonitor->vecPosition.y + 2},
|
||||
{fullBox.x + fullBox.width + pMonitor->vecPosition.x - m_vLastWindowPos.x - m_vLastWindowSize.x + 2,
|
||||
fullBox.y + fullBox.height + pMonitor->vecPosition.y - m_vLastWindowPos.y - m_vLastWindowSize.y + 2}};
|
||||
|
||||
fullBox.x += offset.x;
|
||||
fullBox.y += offset.y;
|
||||
fullBox.translate(offset);
|
||||
|
||||
if (fullBox.width < 1 || fullBox.height < 1)
|
||||
return; // don't draw invisible shadows
|
||||
|
||||
g_pHyprOpenGL->scissor((wlr_box*)nullptr);
|
||||
g_pHyprOpenGL->scissor((CBox*)nullptr);
|
||||
|
||||
// we'll take the liberty of using this as it should not be used rn
|
||||
CFramebuffer& alphaFB = g_pHyprOpenGL->m_RenderData.pCurrentMonData->mirrorFB;
|
||||
CFramebuffer& alphaSwapFB = g_pHyprOpenGL->m_RenderData.pCurrentMonData->mirrorSwapFB;
|
||||
auto* LASTFB = g_pHyprOpenGL->m_RenderData.currentFB;
|
||||
|
||||
fullBox.scale(pMonitor->scale).round();
|
||||
|
||||
if (*PSHADOWIGNOREWINDOW) {
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
CBox windowBox = m_bLastWindowBox;
|
||||
|
||||
glClearStencil(0);
|
||||
glClear(GL_STENCIL_BUFFER_BIT);
|
||||
windowBox.translate(-pMonitor->vecPosition).scale(pMonitor->scale);
|
||||
windowBox.round();
|
||||
|
||||
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);
|
||||
windowBox.addExtents(SWindowDecorationExtents{m_eLastExtents * pMonitor->scale}.floor()).round();
|
||||
|
||||
if (windowBox.width < 1 || windowBox.height < 1) {
|
||||
glClearStencil(0);
|
||||
glClear(GL_STENCIL_BUFFER_BIT);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
return; // prevent assert failed
|
||||
}
|
||||
|
||||
g_pHyprOpenGL->renderRect(&windowBox, CColor(0, 0, 0, 0), ROUNDING * pMonitor->scale);
|
||||
alphaFB.bind();
|
||||
g_pHyprOpenGL->clear(CColor(0, 0, 0, 0));
|
||||
|
||||
glStencilFunc(GL_NOTEQUAL, 1, -1);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
}
|
||||
g_pHyprOpenGL->renderRect(&windowBox, CColor(1.0, 1.0, 1.0, 1.0), ROUNDING * pMonitor->scale);
|
||||
|
||||
scaleBox(&fullBox, pMonitor->scale);
|
||||
g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a);
|
||||
alphaSwapFB.bind();
|
||||
g_pHyprOpenGL->clear(CColor(0, 0, 0, 0));
|
||||
|
||||
if (*PSHADOWIGNOREWINDOW) {
|
||||
// cleanup
|
||||
glClearStencil(0);
|
||||
glClear(GL_STENCIL_BUFFER_BIT);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a);
|
||||
|
||||
LASTFB->bind();
|
||||
|
||||
CBox monbox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y};
|
||||
g_pHyprOpenGL->setMonitorTransformEnabled(false);
|
||||
g_pHyprOpenGL->renderTextureMatte(alphaSwapFB.m_cTex, &monbox, alphaFB);
|
||||
g_pHyprOpenGL->setMonitorTransformEnabled(true);
|
||||
} else {
|
||||
g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a);
|
||||
}
|
||||
}
|
||||
|
||||
eDecorationLayer CHyprDropShadowDecoration::getDecorationLayer() {
|
||||
return DECORATION_LAYER_BOTTOM;
|
||||
}
|
@@ -17,6 +17,8 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration {
|
||||
|
||||
virtual void damageEntire();
|
||||
|
||||
virtual eDecorationLayer getDecorationLayer();
|
||||
|
||||
private:
|
||||
SWindowDecorationExtents m_seExtents;
|
||||
|
||||
@@ -24,4 +26,7 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration {
|
||||
|
||||
Vector2D m_vLastWindowPos;
|
||||
Vector2D m_vLastWindowSize;
|
||||
|
||||
CBox m_bLastWindowBox = {0};
|
||||
SWindowDecorationExtents m_eLastExtents = {};
|
||||
};
|
@@ -24,6 +24,7 @@ eDecorationType CHyprGroupBarDecoration::getDecorationType() {
|
||||
constexpr int BAR_INDICATOR_HEIGHT = 3;
|
||||
constexpr int BAR_PADDING_OUTER_VERT = 2;
|
||||
constexpr int BAR_TEXT_PAD = 2;
|
||||
constexpr int BAR_HORIZONTAL_PADDING = 2;
|
||||
|
||||
//
|
||||
|
||||
@@ -75,8 +76,8 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
|
||||
}
|
||||
|
||||
void CHyprGroupBarDecoration::damageEntire() {
|
||||
wlr_box dm = {m_vLastWindowPos.x - m_seExtents.topLeft.x, m_vLastWindowPos.y - m_seExtents.topLeft.y, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x,
|
||||
m_seExtents.topLeft.y};
|
||||
CBox dm = {m_vLastWindowPos.x - m_seExtents.topLeft.x, m_vLastWindowPos.y - m_seExtents.topLeft.y, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x,
|
||||
m_seExtents.topLeft.y};
|
||||
g_pHyprRenderer->damageBox(&dm);
|
||||
}
|
||||
|
||||
@@ -93,20 +94,18 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D&
|
||||
if (!m_pWindow->m_sSpecialRenderData.decorate)
|
||||
return;
|
||||
|
||||
const int PAD = 2; //2px
|
||||
m_fBarWidth = (m_vLastWindowSize.x - BAR_HORIZONTAL_PADDING * (barsToDraw - 1)) / barsToDraw;
|
||||
|
||||
const int BARW = (m_vLastWindowSize.x - PAD * (barsToDraw - 1)) / barsToDraw;
|
||||
|
||||
int xoff = 0;
|
||||
int xoff = 0;
|
||||
|
||||
for (int i = 0; i < barsToDraw; ++i) {
|
||||
wlr_box rect = {m_vLastWindowPos.x + xoff - pMonitor->vecPosition.x + offset.x,
|
||||
m_vLastWindowPos.y - BAR_PADDING_OUTER_VERT - BORDERSIZE - BAR_INDICATOR_HEIGHT - pMonitor->vecPosition.y + offset.y, BARW, BAR_INDICATOR_HEIGHT};
|
||||
CBox rect = {m_vLastWindowPos.x + xoff - pMonitor->vecPosition.x + offset.x,
|
||||
m_vLastWindowPos.y - BAR_PADDING_OUTER_VERT - BORDERSIZE - BAR_INDICATOR_HEIGHT - pMonitor->vecPosition.y + offset.y, m_fBarWidth, BAR_INDICATOR_HEIGHT};
|
||||
|
||||
if (rect.width <= 0 || rect.height <= 0)
|
||||
break;
|
||||
|
||||
scaleBox(&rect, pMonitor->scale);
|
||||
rect.scale(pMonitor->scale);
|
||||
|
||||
static auto* const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.active")->data;
|
||||
static auto* const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.inactive")->data;
|
||||
@@ -127,15 +126,15 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D&
|
||||
CTitleTex* pTitleTex = textureFromTitle(m_dwGroupMembers[i]->m_szTitle);
|
||||
|
||||
if (!pTitleTex)
|
||||
pTitleTex =
|
||||
m_sTitleTexs.titleTexs
|
||||
.emplace_back(std::make_unique<CTitleTex>(m_dwGroupMembers[i], Vector2D{BARW * pMonitor->scale, (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale}))
|
||||
.get();
|
||||
pTitleTex = m_sTitleTexs.titleTexs
|
||||
.emplace_back(std::make_unique<CTitleTex>(m_dwGroupMembers[i],
|
||||
Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale}))
|
||||
.get();
|
||||
|
||||
rect.height = (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * 0.8 * pMonitor->scale;
|
||||
|
||||
rect.y -= rect.height;
|
||||
rect.width = BARW * pMonitor->scale;
|
||||
rect.width = m_fBarWidth * pMonitor->scale;
|
||||
|
||||
refreshGradients();
|
||||
|
||||
@@ -148,7 +147,7 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D&
|
||||
g_pHyprOpenGL->renderTexture(pTitleTex->tex, &rect, 1.f);
|
||||
}
|
||||
|
||||
xoff += PAD + BARW;
|
||||
xoff += BAR_HORIZONTAL_PADDING + m_fBarWidth;
|
||||
}
|
||||
|
||||
if (*PRENDERTITLES)
|
||||
@@ -180,8 +179,9 @@ CTitleTex::CTitleTex(CWindow* pWindow, const Vector2D& bufferSize) {
|
||||
const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, bufferSize.x, bufferSize.y);
|
||||
const auto CAIRO = cairo_create(CAIROSURFACE);
|
||||
|
||||
static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue;
|
||||
static auto* const PTEXTCOLOR = &g_pConfigManager->getConfigValuePtr("group:groupbar:text_color")->intValue;
|
||||
static auto* const PTITLEFONTFAMILY = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_family")->strValue;
|
||||
static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue;
|
||||
static auto* const PTEXTCOLOR = &g_pConfigManager->getConfigValuePtr("group:groupbar:text_color")->intValue;
|
||||
|
||||
const CColor COLOR = CColor(*PTEXTCOLOR);
|
||||
|
||||
@@ -195,7 +195,7 @@ CTitleTex::CTitleTex(CWindow* pWindow, const Vector2D& bufferSize) {
|
||||
PangoLayout* layout = pango_cairo_create_layout(CAIRO);
|
||||
pango_layout_set_text(layout, szContent.c_str(), -1);
|
||||
|
||||
PangoFontDescription* fontDesc = pango_font_description_from_string("Sans");
|
||||
PangoFontDescription* fontDesc = pango_font_description_from_string(PTITLEFONTFAMILY->c_str());
|
||||
pango_font_description_set_size(fontDesc, *PTITLEFONTSIZE * PANGO_SCALE);
|
||||
pango_layout_set_font_description(layout, fontDesc);
|
||||
pango_font_description_free(fontDesc);
|
||||
@@ -302,6 +302,113 @@ void CHyprGroupBarDecoration::refreshGradients() {
|
||||
renderGradientTo(m_tGradientInactive, ((CGradientValueData*)PCOLINACTIVE->get())->m_vColors[0]);
|
||||
}
|
||||
|
||||
bool CHyprGroupBarDecoration::allowsInput() {
|
||||
return true;
|
||||
bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D& pos) {
|
||||
|
||||
if (!pDraggedWindow->canBeGroupedInto(m_pWindow))
|
||||
return true;
|
||||
|
||||
const float BARRELATIVEX = pos.x - m_vLastWindowPos.x - m_fBarWidth / 2;
|
||||
const int WINDOWINDEX = BARRELATIVEX < 0 ? -1 : (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING);
|
||||
|
||||
CWindow* pWindowInsertAfter = m_pWindow->getGroupWindowByIndex(WINDOWINDEX);
|
||||
CWindow* pWindowInsertEnd = pWindowInsertAfter->m_sGroupData.pNextWindow;
|
||||
CWindow* pDraggedHead = pDraggedWindow->m_sGroupData.pNextWindow ? pDraggedWindow->getGroupHead() : pDraggedWindow;
|
||||
|
||||
if (pDraggedWindow->m_sGroupData.pNextWindow) {
|
||||
|
||||
// stores group data
|
||||
std::vector<CWindow*> members;
|
||||
CWindow* curr = pDraggedHead;
|
||||
const bool WASLOCKED = pDraggedHead->m_sGroupData.locked;
|
||||
do {
|
||||
members.push_back(curr);
|
||||
curr = curr->m_sGroupData.pNextWindow;
|
||||
} while (curr != members[0]);
|
||||
|
||||
// removes all windows
|
||||
for (CWindow* w : members) {
|
||||
w->m_sGroupData.pNextWindow = nullptr;
|
||||
w->m_sGroupData.head = false;
|
||||
w->m_sGroupData.locked = false;
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(w);
|
||||
}
|
||||
|
||||
// restores the group
|
||||
for (auto it = members.begin(); it != members.end(); ++it) {
|
||||
if (std::next(it) != members.end())
|
||||
(*it)->m_sGroupData.pNextWindow = *std::next(it);
|
||||
else
|
||||
(*it)->m_sGroupData.pNextWindow = members[0];
|
||||
}
|
||||
members[0]->m_sGroupData.head = true;
|
||||
members[0]->m_sGroupData.locked = WASLOCKED;
|
||||
} else {
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pDraggedWindow);
|
||||
}
|
||||
|
||||
pWindowInsertAfter->insertWindowToGroup(pDraggedWindow);
|
||||
|
||||
if (WINDOWINDEX == -1)
|
||||
std::swap(pDraggedHead->m_sGroupData.head, pWindowInsertEnd->m_sGroupData.head);
|
||||
|
||||
m_pWindow->setGroupCurrent(pDraggedWindow);
|
||||
pDraggedWindow->applyGroupRules();
|
||||
pDraggedWindow->updateWindowDecos();
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateWindow(pDraggedWindow);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, wlr_pointer_button_event* e) {
|
||||
if (e->state != WLR_BUTTON_PRESSED)
|
||||
return;
|
||||
|
||||
const float BARRELATIVEX = pos.x - m_vLastWindowPos.x;
|
||||
const int WINDOWINDEX = (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING);
|
||||
|
||||
if (BARRELATIVEX - (m_fBarWidth + BAR_HORIZONTAL_PADDING) * WINDOWINDEX > m_fBarWidth) {
|
||||
if (!g_pCompositor->isWindowActive(m_pWindow))
|
||||
g_pCompositor->focusWindow(m_pWindow);
|
||||
return;
|
||||
}
|
||||
|
||||
CWindow* pWindow = m_pWindow->getGroupWindowByIndex(WINDOWINDEX);
|
||||
|
||||
if (pWindow != m_pWindow)
|
||||
pWindow->setGroupCurrent(pWindow);
|
||||
|
||||
if (!g_pCompositor->isWindowActive(pWindow))
|
||||
g_pCompositor->focusWindow(pWindow);
|
||||
}
|
||||
|
||||
void CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) {
|
||||
const float BARRELATIVEX = pos.x - m_vLastWindowPos.x;
|
||||
const int WINDOWINDEX = (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING);
|
||||
|
||||
if (BARRELATIVEX - (m_fBarWidth + BAR_HORIZONTAL_PADDING) * WINDOWINDEX > m_fBarWidth)
|
||||
return;
|
||||
|
||||
CWindow* pWindow = m_pWindow->getGroupWindowByIndex(WINDOWINDEX);
|
||||
|
||||
// hack
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow);
|
||||
if (!pWindow->m_bIsFloating) {
|
||||
const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_bGroupsLocked;
|
||||
g_pKeybindManager->m_bGroupsLocked = true;
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(pWindow);
|
||||
g_pKeybindManager->m_bGroupsLocked = GROUPSLOCKEDPREV;
|
||||
}
|
||||
|
||||
g_pInputManager->currentlyDraggedWindow = pWindow;
|
||||
|
||||
if (!g_pCompositor->isWindowActive(pWindow))
|
||||
g_pCompositor->focusWindow(pWindow);
|
||||
}
|
||||
|
||||
eDecorationLayer CHyprGroupBarDecoration::getDecorationLayer() {
|
||||
return DECORATION_LAYER_OVER;
|
||||
}
|
||||
|
||||
uint64_t CHyprGroupBarDecoration::getDecorationFlags() {
|
||||
return DECORATION_ALLOWS_MOUSE_INPUT;
|
||||
}
|
@@ -33,7 +33,15 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration {
|
||||
|
||||
virtual SWindowDecorationExtents getWindowDecorationReservedArea();
|
||||
|
||||
virtual bool allowsInput();
|
||||
virtual void onBeginWindowDragOnDeco(const Vector2D&);
|
||||
|
||||
virtual bool onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D&);
|
||||
|
||||
virtual void onMouseButtonOnDeco(const Vector2D&, wlr_pointer_button_event*);
|
||||
|
||||
virtual eDecorationLayer getDecorationLayer();
|
||||
|
||||
virtual uint64_t getDecorationFlags();
|
||||
|
||||
private:
|
||||
SWindowDecorationExtents m_seExtents;
|
||||
@@ -45,6 +53,8 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration {
|
||||
|
||||
std::deque<CWindow*> m_dwGroupMembers;
|
||||
|
||||
float m_fBarWidth;
|
||||
|
||||
CTitleTex* textureFromTitle(const std::string&);
|
||||
void invalidateTextures();
|
||||
|
||||
|
@@ -25,6 +25,22 @@ CRegion IHyprWindowDecoration::getWindowDecorationRegion() {
|
||||
m_pWindow->m_vRealSize.vec().y + 2 * BORDERSIZE));
|
||||
}
|
||||
|
||||
bool IHyprWindowDecoration::allowsInput() {
|
||||
return false;
|
||||
void IHyprWindowDecoration::onBeginWindowDragOnDeco(const Vector2D&) {
|
||||
;
|
||||
}
|
||||
|
||||
bool IHyprWindowDecoration::onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D&) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void IHyprWindowDecoration::onMouseButtonOnDeco(const Vector2D&, wlr_pointer_button_event*) {
|
||||
;
|
||||
}
|
||||
|
||||
eDecorationLayer IHyprWindowDecoration::getDecorationLayer() {
|
||||
return DECORATION_LAYER_UNDER;
|
||||
}
|
||||
|
||||
uint64_t IHyprWindowDecoration::getDecorationFlags() {
|
||||
return 0;
|
||||
}
|
@@ -3,16 +3,26 @@
|
||||
#include "../../defines.hpp"
|
||||
#include "../../helpers/Region.hpp"
|
||||
|
||||
enum eDecorationType {
|
||||
enum eDecorationType
|
||||
{
|
||||
DECORATION_NONE = -1,
|
||||
DECORATION_GROUPBAR,
|
||||
DECORATION_SHADOW,
|
||||
DECORATION_CUSTOM
|
||||
};
|
||||
|
||||
struct SWindowDecorationExtents {
|
||||
Vector2D topLeft;
|
||||
Vector2D bottomRight;
|
||||
enum eDecorationLayer
|
||||
{
|
||||
DECORATION_LAYER_BOTTOM = 0, /* lowest. */
|
||||
DECORATION_LAYER_UNDER, /* under the window, but above BOTTOM */
|
||||
DECORATION_LAYER_OVER, /* above the window, but below its popups */
|
||||
DECORATION_LAYER_OVERLAY /* above everything of the window, including popups */
|
||||
};
|
||||
|
||||
enum eDecorationFlags
|
||||
{
|
||||
DECORATION_ALLOWS_MOUSE_INPUT = 1 << 0, /* this decoration accepts mouse input */
|
||||
DECORATION_PART_OF_MAIN_WINDOW = 1 << 1, /* this decoration is a *seamless* part of the main window, so stuff like shadows will include it */
|
||||
};
|
||||
|
||||
class CWindow;
|
||||
@@ -37,7 +47,15 @@ class IHyprWindowDecoration {
|
||||
|
||||
virtual CRegion getWindowDecorationRegion();
|
||||
|
||||
virtual bool allowsInput();
|
||||
virtual void onBeginWindowDragOnDeco(const Vector2D&); // called when the user calls the "movewindow" mouse dispatcher on the deco
|
||||
|
||||
virtual bool onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D&); // returns true if the window should be placed by the layout
|
||||
|
||||
virtual void onMouseButtonOnDeco(const Vector2D&, wlr_pointer_button_event*);
|
||||
|
||||
virtual eDecorationLayer getDecorationLayer();
|
||||
|
||||
virtual uint64_t getDecorationFlags();
|
||||
|
||||
private:
|
||||
CWindow* m_pWindow = nullptr;
|
||||
|
@@ -12,6 +12,7 @@ uniform vec2 topLeft;
|
||||
uniform vec2 fullSize;
|
||||
uniform vec2 fullSizeUntransformed;
|
||||
uniform float radius;
|
||||
uniform float radiusOuter;
|
||||
uniform float thick;
|
||||
|
||||
uniform vec4 gradient[10];
|
||||
@@ -51,6 +52,7 @@ vec4 getColorForCoord(vec2 normalizedCoord) {
|
||||
void main() {
|
||||
|
||||
highp vec2 pixCoord = vec2(gl_FragCoord);
|
||||
highp vec2 pixCoordOuter = pixCoord;
|
||||
highp vec2 originalPixCoord = v_texcoord;
|
||||
originalPixCoord *= fullSizeUntransformed;
|
||||
float additionalAlpha = 1.0;
|
||||
@@ -61,25 +63,33 @@ void main() {
|
||||
|
||||
pixCoord -= topLeft + fullSize * 0.5;
|
||||
pixCoord *= vec2(lessThan(pixCoord, vec2(0.0))) * -2.0 + 1.0;
|
||||
pixCoordOuter = pixCoord;
|
||||
pixCoord -= fullSize * 0.5 - radius;
|
||||
pixCoord += vec2(1.0, 1.0) / fullSize; // center the pix dont make it top-left
|
||||
pixCoordOuter -= fullSize * 0.5 - radiusOuter;
|
||||
|
||||
// center the pixes dont make it top-left
|
||||
pixCoord += vec2(1.0, 1.0) / fullSize;
|
||||
pixCoordOuter += vec2(1.0, 1.0) / fullSize;
|
||||
|
||||
if (min(pixCoord.x, pixCoord.y) > 0.0 && radius > 0.0) {
|
||||
|
||||
float dist = length(pixCoord);
|
||||
float distOuter = length(pixCoordOuter);
|
||||
float h = (thick / 2.0);
|
||||
|
||||
if (dist < radius - h) {
|
||||
// lower
|
||||
float normalized = smoothstep(0.0, 1.0, dist - radius + thick + 0.5);
|
||||
additionalAlpha *= normalized;
|
||||
} else {
|
||||
done = true;
|
||||
} else if (min(pixCoordOuter.x, pixCoordOuter.y) > 0.0) {
|
||||
// higher
|
||||
float normalized = 1.0 - smoothstep(0.0, 1.0, dist - radius + 0.5);
|
||||
float normalized = 1.0 - smoothstep(0.0, 1.0, distOuter - radiusOuter + 0.5);
|
||||
additionalAlpha *= normalized;
|
||||
done = true;
|
||||
} else if (distOuter < radiusOuter - h) {
|
||||
additionalAlpha = 1.0;
|
||||
done = true;
|
||||
}
|
||||
|
||||
done = true;
|
||||
}
|
||||
|
||||
// now check for other shit
|
||||
|
@@ -5,7 +5,9 @@
|
||||
inline const std::string FRAGSHADOW = R"#(
|
||||
precision mediump float;
|
||||
varying vec4 v_color;
|
||||
uniform sampler2D alphaMatte;
|
||||
varying vec2 v_texcoord;
|
||||
varying vec2 v_texcoordMatte;
|
||||
|
||||
uniform vec2 topLeft;
|
||||
uniform vec2 bottomRight;
|
||||
@@ -13,6 +15,7 @@ uniform vec2 fullSize;
|
||||
uniform float radius;
|
||||
uniform float range;
|
||||
uniform float shadowPower;
|
||||
uniform int useAlphaMatte;
|
||||
|
||||
float pixAlphaRoundedDistance(float distanceToCorner) {
|
||||
if (distanceToCorner > radius) {
|
||||
@@ -74,6 +77,10 @@ void main() {
|
||||
}
|
||||
}
|
||||
|
||||
if (useAlphaMatte == 1) {
|
||||
pixColor[3] *= 1.0 - texture2D(alphaMatte, v_texcoordMatte)[3];
|
||||
}
|
||||
|
||||
if (pixColor[3] == 0.0) {
|
||||
discard; return;
|
||||
}
|
||||
|
@@ -37,13 +37,16 @@ uniform mat3 proj;
|
||||
uniform vec4 color;
|
||||
attribute vec2 pos;
|
||||
attribute vec2 texcoord;
|
||||
attribute vec2 texcoordMatte;
|
||||
varying vec4 v_color;
|
||||
varying vec2 v_texcoord;
|
||||
varying vec2 v_texcoordMatte;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);
|
||||
v_color = color;
|
||||
v_texcoord = texcoord;
|
||||
v_texcoordMatte = texcoordMatte;
|
||||
})#";
|
||||
|
||||
inline const std::string QUADFRAGSRC = R"#(
|
||||
@@ -127,6 +130,16 @@ void main() {
|
||||
gl_FragColor = texture2D(tex, v_texcoord);
|
||||
})#";
|
||||
|
||||
inline const std::string TEXFRAGSRCRGBAMATTE = R"#(
|
||||
precision mediump float;
|
||||
varying vec2 v_texcoord; // is in 0-1
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D texMatte;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = texture2D(tex, v_texcoord) * (1.0 - texture2D(texMatte, v_texcoord)[3]);
|
||||
})#";
|
||||
|
||||
inline const std::string TEXFRAGSRCRGBX = R"#(
|
||||
precision mediump float;
|
||||
varying vec2 v_texcoord;
|
||||
@@ -167,12 +180,116 @@ void main() {
|
||||
|
||||
inline const std::string FRAGBLUR1 = R"#(
|
||||
#version 100
|
||||
precision mediump float;
|
||||
precision mediump float;
|
||||
varying mediump vec2 v_texcoord; // is in 0-1
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D tex;
|
||||
|
||||
uniform float radius;
|
||||
uniform vec2 halfpixel;
|
||||
uniform float radius;
|
||||
uniform vec2 halfpixel;
|
||||
uniform int passes;
|
||||
uniform float vibrancy;
|
||||
uniform float vibrancy_darkness;
|
||||
|
||||
// see http://alienryderflex.com/hsp.html
|
||||
const float Pr = 0.299;
|
||||
const float Pg = 0.587;
|
||||
const float Pb = 0.114;
|
||||
|
||||
// Y is "v" ( brightness ). X is "s" ( saturation )
|
||||
// see https://www.desmos.com/3d/a88652b9a4
|
||||
// Determines if high brightness or high saturation is more important
|
||||
const float a = 0.93;
|
||||
const float b = 0.11;
|
||||
const float c = 0.66; // Determines the smoothness of the transition of unboosted to boosted colors
|
||||
//
|
||||
|
||||
// http://www.flong.com/archive/texts/code/shapers_circ/
|
||||
float doubleCircleSigmoid(float x, float a) {
|
||||
float min_param_a = 0.0;
|
||||
float max_param_a = 1.0;
|
||||
a = max(min_param_a, min(max_param_a, a));
|
||||
|
||||
float y = .0;
|
||||
if (x <= a) {
|
||||
y = a - sqrt(a * a - x * x);
|
||||
} else {
|
||||
y = a + sqrt(pow(1. - a, 2.) - pow(x - 1., 2.));
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
vec3 rgb2hsl(vec3 col) {
|
||||
float red = col.r;
|
||||
float green = col.g;
|
||||
float blue = col.b;
|
||||
|
||||
float minc = min(col.r, min(col.g, col.b));
|
||||
float maxc = max(col.r, max(col.g, col.b));
|
||||
float delta = maxc - minc;
|
||||
|
||||
float lum = (minc + maxc) * 0.5;
|
||||
float sat = 0.0;
|
||||
float hue = 0.0;
|
||||
|
||||
if (lum > 0.0 && lum < 1.0) {
|
||||
float mul = (lum < 0.5) ? (lum) : (1.0 - lum);
|
||||
sat = delta / (mul * 2.0);
|
||||
}
|
||||
|
||||
vec3 masks = vec3((maxc == red && maxc != green) ? 1.0 : 0.0, (maxc == green && maxc != blue) ? 1.0 : 0.0, (maxc == blue && maxc != red) ? 1.0 : 0.0);
|
||||
|
||||
vec3 adds = vec3(((green - blue) / delta), 2.0 + ((blue - red) / delta), 4.0 + ((red - green) / delta));
|
||||
|
||||
float deltaGtz = (delta > 0.0) ? 1.0 : 0.0;
|
||||
|
||||
hue += dot(adds, masks);
|
||||
hue *= deltaGtz;
|
||||
hue /= 6.0;
|
||||
|
||||
if (hue < 0.0)
|
||||
hue += 1.0;
|
||||
|
||||
return vec3(hue, sat, lum);
|
||||
}
|
||||
vec3 hsl2rgb(vec3 col) {
|
||||
const float onethird = 1.0 / 3.0;
|
||||
const float twothird = 2.0 / 3.0;
|
||||
const float rcpsixth = 6.0;
|
||||
|
||||
float hue = col.x;
|
||||
float sat = col.y;
|
||||
float lum = col.z;
|
||||
|
||||
vec3 xt = vec3(rcpsixth * (hue - twothird), 0.0, rcpsixth * (1.0 - hue));
|
||||
|
||||
if (hue < twothird) {
|
||||
xt.r = 0.0;
|
||||
xt.g = rcpsixth * (twothird - hue);
|
||||
xt.b = rcpsixth * (hue - onethird);
|
||||
}
|
||||
|
||||
if (hue < onethird) {
|
||||
xt.r = rcpsixth * (onethird - hue);
|
||||
xt.g = rcpsixth * hue;
|
||||
xt.b = 0.0;
|
||||
}
|
||||
|
||||
xt = min(xt, 1.0);
|
||||
|
||||
float sat2 = 2.0 * sat;
|
||||
float satinv = 1.0 - sat;
|
||||
float luminv = 1.0 - lum;
|
||||
float lum2m1 = (2.0 * lum) - 1.0;
|
||||
vec3 ct = (sat2 * xt) + satinv;
|
||||
|
||||
vec3 rgb;
|
||||
if (lum >= 0.5)
|
||||
rgb = (luminv * ct) + lum2m1;
|
||||
else
|
||||
rgb = lum * ct;
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 uv = v_texcoord * 2.0;
|
||||
@@ -183,7 +300,28 @@ void main() {
|
||||
sum += texture2D(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius);
|
||||
sum += texture2D(tex, uv - vec2(halfpixel.x, -halfpixel.y) * radius);
|
||||
|
||||
gl_FragColor = sum / 8.0;
|
||||
vec4 color = sum / 8.0;
|
||||
|
||||
if (vibrancy == 0.0) {
|
||||
gl_FragColor = color;
|
||||
} else {
|
||||
// Invert it so that it correctly maps to the config setting
|
||||
float vibrancy_darkness1 = 1.0 - vibrancy_darkness;
|
||||
|
||||
// Decrease the RGB components based on their perceived brightness, to prevent visually dark colors from overblowing the rest.
|
||||
vec3 hsl = rgb2hsl(color.rgb);
|
||||
// Calculate perceived brightness, as not boost visually dark colors like deep blue as much as equally saturated yellow
|
||||
float perceivedBrightness = doubleCircleSigmoid(sqrt(color.r * color.r * Pr + color.g * color.g * Pg + color.b * color.b * Pb), 0.8 * vibrancy_darkness1);
|
||||
|
||||
float b1 = b * vibrancy_darkness1;
|
||||
float boostBase = hsl[1] > 0.0 ? smoothstep(b1 - c * 0.5, b1 + c * 0.5, 1.0 - (pow(1.0 - hsl[1] * cos(a), 2.0) + pow(1.0 - perceivedBrightness * sin(a), 2.0))) : 0.0;
|
||||
|
||||
float saturation = clamp(hsl[1] + (boostBase * vibrancy) / float(passes), 0.0, 1.0);
|
||||
|
||||
vec3 newColor = hsl2rgb(vec3(hsl[0], saturation, hsl[2]));
|
||||
|
||||
gl_FragColor = vec4(newColor, color[3]);
|
||||
}
|
||||
}
|
||||
)#";
|
||||
|
||||
@@ -213,35 +351,66 @@ void main() {
|
||||
}
|
||||
)#";
|
||||
|
||||
inline const std::string FRAGBLURFINISH = R"#(
|
||||
precision mediump float;
|
||||
varying vec2 v_texcoord; // is in 0-1
|
||||
inline const std::string FRAGBLURPREPARE = R"#(
|
||||
precision mediump float;
|
||||
varying vec2 v_texcoord; // is in 0-1
|
||||
uniform sampler2D tex;
|
||||
|
||||
uniform float contrast;
|
||||
uniform float noise;
|
||||
uniform float brightness;
|
||||
uniform float contrast;
|
||||
uniform float brightness;
|
||||
|
||||
float hash(vec2 p) {
|
||||
return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
|
||||
float gain(float x, float k) {
|
||||
float a = 0.5 * pow(2.0 * ((x < 0.5) ? x : 1.0 - x), k);
|
||||
return (x < 0.5) ? a : 1.0 - a;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 pixColor = texture2D(tex, v_texcoord);
|
||||
|
||||
// contrast
|
||||
pixColor.rgb = (pixColor.rgb - 0.5) * contrast + 0.5;
|
||||
if (contrast != 1.0) {
|
||||
pixColor.r = gain(pixColor.r, contrast);
|
||||
pixColor.g = gain(pixColor.g, contrast);
|
||||
pixColor.b = gain(pixColor.b, contrast);
|
||||
}
|
||||
|
||||
// brightness
|
||||
pixColor.rgb *= brightness;
|
||||
if (brightness > 1.0) {
|
||||
pixColor.rgb *= brightness;
|
||||
}
|
||||
|
||||
gl_FragColor = pixColor;
|
||||
}
|
||||
)#";
|
||||
|
||||
inline const std::string FRAGBLURFINISH = R"#(
|
||||
precision mediump float;
|
||||
varying vec2 v_texcoord; // is in 0-1
|
||||
uniform sampler2D tex;
|
||||
|
||||
uniform float noise;
|
||||
uniform float brightness;
|
||||
|
||||
float hash(vec2 p) {
|
||||
return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 pixColor = texture2D(tex, v_texcoord);
|
||||
|
||||
// noise
|
||||
float noiseHash = hash(v_texcoord);
|
||||
float noiseHash = hash(v_texcoord);
|
||||
float noiseAmount = (mod(noiseHash, 1.0) - 0.5);
|
||||
pixColor.rgb += noiseAmount * noise;
|
||||
|
||||
// brightness
|
||||
if (brightness < 1.0) {
|
||||
pixColor.rgb *= brightness;
|
||||
}
|
||||
|
||||
gl_FragColor = pixColor;
|
||||
})#";
|
||||
}
|
||||
)#";
|
||||
|
||||
inline const std::string TEXFRAGSRCEXT = R"#(
|
||||
#extension GL_OES_EGL_image_external : require
|
||||
|
Submodule subprojects/tracy updated: 897aec5b06...37aff70dfa
Submodule subprojects/wlroots updated: 3406c1b17a...47bf87ade2
@@ -1,7 +1,7 @@
|
||||
[wrap-git]
|
||||
directory = wlroots
|
||||
url = https://gitlab.freedesktop.org/wlroots/wlroots.git
|
||||
revision = 3406c1b17a4a7e6d4e2a7d9c1176affa72bce1bc
|
||||
revision = 47bf87ade2bd32395615a385ebde1fefbcdf79a2
|
||||
depth = 1
|
||||
|
||||
diff_files = wlroots-meson-build.patch
|
||||
|
Reference in New Issue
Block a user