Compare commits

..

108 Commits

Author SHA1 Message Date
Vaxry
751d2851cc props: bump ver to 0.32.0 2023-11-07 21:06:38 +00:00
Vaxry
a0fcda301d layout: round box in mouseMove
fixes #3792
2023-11-07 20:47:09 +00:00
Vaxry
47654a84c2 main: set isShuttingDown after display dispatch reaches the end
relates to #3558
2023-11-07 14:53:56 +00:00
Visual-Dawg
29e0a7112e renderer: added new customization options to the blur shaders (#3650)
Adds to `decoration:blur:` `vibrancy` and `vibrancy_darkness`
2023-11-06 18:49:03 +00:00
Vaxry
a1b7a5a53d layout: fix various rounding errors
maybe finally will end #3761
2023-11-06 17:00:37 +00:00
Vaxry
ecf98069f6 layout: round window boxes after special scale factor
fixes #3761 again
2023-11-05 19:57:23 +00:00
David Leal
0476e1b498 groups: add option to configure font name (#3751) 2023-11-05 19:25:50 +00:00
Brett Alcox
a122271f09 includes: fix box headers (#3771) 2023-11-05 17:32:27 +00:00
Vaxry
600a128f83 compositor: allow windowfromregex tiled param 2023-11-05 16:22:43 +00:00
Vaxry
55825c301e compositor: allow windowfromregex floating param
fixes #3766
2023-11-05 16:21:47 +00:00
Vaxry
d8b7ded18c compositor: find windows in direction on floating 2023-11-05 16:18:41 +00:00
Vaxry
c4e1a9b13b box: use std::round instead of std::floor in ::round()
fixes #3761, possibly also #3511
2023-11-05 14:47:24 +00:00
Vaxry
9404972732 events: set reported size on floating map
fixes #3767
2023-11-05 14:12:55 +00:00
Vaxry
3b786419d8 subprojects: update tracy 2023-11-05 00:32:22 +00:00
Vaxry
92e535025e region: include box in the header 2023-11-04 23:12:08 +00:00
Vaxry
d3e5796ee1 layout: fix missed setWindowSize in no_gaps_when_only node apply
fixes #3758
2023-11-04 23:00:20 +00:00
Vaxry
56dec1c6a2 renderer: properly set currentFB on snapshot renders 2023-11-04 22:25:09 +00:00
Vaxry
931927de29 dwindle: move to CBox for expressing nodes 2023-11-04 21:45:34 +00:00
Vaxry
74cf2281dd binds: add movefocus_cycles_fullscreen
fixes #3738
2023-11-04 21:03:08 +00:00
Vaxry
2b07d54bc7 shadow: fix missed fullBox.scale 2023-11-04 20:11:22 +00:00
Vaxry
66a3719b86 renderer: allow transform enabling from outside opengl 2023-11-04 19:35:49 +00:00
Vaxry
64a084477e shadows: fix on transformed 2023-11-04 19:32:50 +00:00
Vaxry
7a09d24065 shadow: fix ignore_window false 2023-11-04 17:45:31 +00:00
Vaxry
a3e20d2d5f wlsurface: fix small detection 2023-11-04 17:39:56 +00:00
Vaxry
32b3d2b456 includes: include vector2d for sharedDefs 2023-11-04 17:27:21 +00:00
Vaxry
447c173cad includes: include sharedDefs in includes.hpp 2023-11-04 17:04:10 +00:00
Vaxry
55b4f84fea Internal: Hyprland box implementation (#3755)
* box impl

* remove unused operators

* missed applyfromwlr
2023-11-04 17:03:05 +00:00
Vaxry
73e78f05ad Decos: Window decoration flags, shadow improvements (#3739) 2023-11-04 13:10:52 +00:00
Vaxry
54e51b7acf events: better adjust to unreported sizes for xwayland apps
fixes #3745
2023-11-04 13:09:33 +00:00
Vaxry
200cccdd3b events: set reported size on the end of mapping
fixes #3743
2023-11-03 22:47:12 +00:00
Vaxry
15b25d5850 renderer: render oversized blur with respect to fade alpha 2023-11-03 21:58:02 +00:00
Vaxry
21ba8b363e fractional-scale: fix addon existence check 2023-11-03 21:02:12 +00:00
Vaxry
9d2a5fb417 renderer: improvements to wayland surface small() detection 2023-11-03 19:12:09 +00:00
thejch
ed3d5053b2 Master: fix drop_at_cursor when there are only two windows (#3734)
* make drop_at_cursor work when dragging into a one-window workspace

* fix drop_at_cursor when new_is_master is enabled
2023-11-03 17:02:59 +00:00
Vaxry
93a2ac9de4 fractional-scale: post error on taken fs objects
fixes #3735
2023-11-03 15:51:43 +00:00
pastalian
49fdffacea renderer: fix legacy_renderer build (#3732)
In GLES2, `GL_RGB10_A2` and `GL_UNSIGNED_INT_2_10_10_10_REV` are defined as
`GL_RGB10_A2_EXT` and `GL_UNSIGNED_INT_2_10_10_10_REV_EXT` respectively.
2023-11-03 15:47:20 +00:00
vaxerski
0f6e530798 layout: better storage for no fullscreen checks var
fixes #3731
2023-11-03 12:19:23 +00:00
Vaxry
88b47dfa83 xdg: use std::ceil for sending scale to surfaces
fixes #3724
2023-11-02 23:29:47 +00:00
Vaxry
ba9e7814b0 input: simulate movement only if mouse is over in open/close window
fixes #3726
2023-11-02 21:36:16 +00:00
thejch
f10996b575 master: fix moving window between monitors (#3721) 2023-11-02 17:20:32 +00:00
q234rty
ef90d1eaaf Map cmake None to meson's plain
empty is not a build type that exists in meson.

I have no idea why I typed "empty" in #3614 ...

Fixes: ba5f1d8783
2023-11-02 19:20:09 +02:00
Dashie
062f749450 xdg: send unconstrain events after a popup reposition (#3716)
* fix: Use unconstrain_from_box after reposition request

* chore: Remove unused include

* chore: remove variable specifier
2023-11-01 20:31:52 +00:00
Vaxry
a4db48b46b input: simulate mouse movement to fix focus on open/close window
fixes #3679
2023-11-01 19:50:32 +00:00
MightyPlaza
c44e255194 group: fixes for dragging groups onto groupbars (#3708)
* fixes for dragging groups onto groupbars

modified:   src/render/decorations/CHyprGroupBarDecoration.cpp

* use onWindowRemoved()
modified:   src/render/decorations/CHyprGroupBarDecoration.cpp
2023-11-01 19:13:39 +00:00
Vaxry
21e9313c10 Core: various unsafe state improvements (#3713)
Fixes #3637
2023-11-01 18:53:36 +00:00
Vaxry
7b32b4214d layout: avoid redundant size sets on new fullscreen 2023-11-01 01:28:43 +00:00
Vaxry
6914103289 cmake: set asan for only hyprland not others 2023-10-31 21:45:27 +00:00
Vaxry
ab5497a0c9 input: properly track xdg surfaces' geometry in vectorToSurfaceLocal
fixes #3703
2023-10-30 19:36:45 +00:00
André Silva
f48b3774a2 nix: use mesonAutoFeatures attribute 2023-10-30 21:00:04 +02:00
Vaxry
1c9d6b94d1 renderer: fix small surface's blur region being offset by monitor coords 2023-10-30 16:20:30 +00:00
Vaxry
4b592d0819 renderer: properly pass 10-bit formats to opengl 2023-10-30 15:56:16 +00:00
MightyPlaza
a1924ae435 internal: create canBeGroupedInto() (#3693)
modified:   src/Window.cpp
modified:   src/Window.hpp
modified:   src/layout/DwindleLayout.cpp
modified:   src/layout/MasterLayout.cpp
modified:   src/render/decorations/CHyprGroupBarDecoration.cpp
2023-10-30 14:54:12 +00:00
Vaxry
cb6cfde6e8 window: update window reported size on damage events 2023-10-30 14:49:49 +00:00
Vaxry
8e91c038db renderer: use optional for cursor surface storing
because nullptr is a valid surface.

fixes #3692
2023-10-30 00:18:40 +00:00
Vaxry
86318ce04f input: let input-grabbing decos have prio over resize on border 2023-10-29 23:37:12 +00:00
Vaxry
59d6a12a7e config: fixup usage of plugin in handles
would filter calls to keyword plugin: and stuff
2023-10-29 22:35:26 +00:00
Vaxry
935c90915a pluginapi: fixup get_hash functions 2023-10-29 21:21:54 +00:00
Vaxry
b95c0c318e renderer: fixup blend disable conditions in renderSurface
Fixes #3680
2023-10-29 20:54:14 +00:00
MightyPlaza
9abfa9efc6 input: handle mouse on decorations (#3560) 2023-10-29 20:14:47 +00:00
Vaxry
7a5234a0cc input: better cursor image infrastructure
Improves handling of cursor images/surfaces
Fixes an issue with decos and cursors
Fixes #3471
2023-10-29 18:09:05 +00:00
Vaxry
af9440152e pluginapi: add a config keyword adding method 2023-10-29 16:59:50 +00:00
Vaxry
7f4b0aaadc hyprctl: add focusHistoryID to hyprctl clients
fixes #3661
2023-10-28 17:22:42 +01:00
vaxerski
4a4e13f8ac events: ignore takes_over_fullscreen for floating windows
fixes #3622. Floating windows should not respect the config option, they should be shown on top. That option is meant for tiled only
2023-10-27 12:45:17 +01:00
Antoine Dutot
1d47e2c408 input: fix force_zero_scaling for tablet and touch (#3644)
* Attempt to fix force_zero_scaling for tablet and touch for XWayland apps.

* Formated using clang-format.

* Simpler way to compute touch origin.
2023-10-27 10:15:29 +01:00
Vaxry
47256a6ed8 input: remove incorrect check in re-enter
fixes #3659
2023-10-26 22:21:13 +01:00
Vaxry
732b058489 input: send motion events on focusWindow if follows_mouse is 0 2023-10-26 22:17:49 +01:00
Vaxry
92cf1c2337 input: fix mouse down handling on unset last surface
fixes #3659
2023-10-26 18:54:19 +01:00
Tyler Schneider
07714dd5bd input: Apply scaling to cursorPosOnActivate position (#3664) 2023-10-26 02:05:10 +01:00
fufexan
5cc33b4e8c [gha] Nix: update inputs 2023-10-26 00:03:23 +00:00
Vaxry
b0b88a63b6 renderer: fix missed box scale 2023-10-25 22:38:14 +01:00
Vaxry
5b0dc779ed renderer: blur properly behind small surfaces 2023-10-25 22:20:58 +01:00
Vaxry
8991be671f renderer: respect viewporter dest on base surfaces 2023-10-25 22:05:04 +01:00
Vaxry
6650e4ba85 compositor: remove old comment 2023-10-25 18:32:04 +01:00
vaxerski
a1b138a625 [gha] Nix: update wlroots 2023-10-24 23:28:24 +00:00
Vaxry
df00727310 deps: update wlroots 2023-10-25 00:27:16 +01:00
Vaxry
03771d3aa9 windowrules: add nearestneighbor 2023-10-24 21:29:03 +01:00
André Silva
50a80efad5 flake.lock: update nixpkgs and xdph 2023-10-24 21:06:00 +03:00
Vaxry
14a3c939ce hyprctl: log monitor id in workspaces request
fixes #3640
2023-10-24 01:03:40 +01:00
Vaxry
aeb8c8fc70 internal: honor close_special_on_empty on moveToWorkspace
fixes #3602
2023-10-24 00:58:44 +01:00
Vaxry
616ff343b7 input: fix warn 2023-10-24 00:53:59 +01:00
Vaxry
2f6729f557 example: add special workspace to default config 2023-10-24 00:50:45 +01:00
Vaxry
015664eb4c compositor: do not process fullscreen events in unsafe 2023-10-23 00:53:33 +01:00
Vaxry
98059b52d7 layershell: support ON_DEMAND keyboard mode
fixes #2264
2023-10-22 23:32:55 +01:00
Brenno Lemos
b135bd6cd4 workspacerules: Add new optional "default command" for auto-launching apps on new workspaces (#3559) 2023-10-22 23:11:03 +01:00
Vaxry
59f27e7f57 compositor: send preferred scale and transform events to surfaces
fixes #3635
2023-10-22 16:58:06 +01:00
Vaxry
edb26e0306 cmake: remove old definitions from cmakelists 2023-10-22 12:25:26 +01:00
Vaxry
d0367d8560 renderer: use preOffset pos instead of offset
offset is not passed to transformers, so if they change pos, decos will be in the wrong place
2023-10-21 19:51:14 +01:00
Vaxry
95db9108e5 transformers: allow modifying renderdata pre-pass 2023-10-21 19:25:44 +01:00
Vaxry
a61eb7694d hooksystem: add callbackinfo struct and cancellable events 2023-10-21 14:52:43 +01:00
Vaxry
c6233a790f renderer: avoid drawing invisibly small surfaces in renderSurface 2023-10-21 14:20:06 +01:00
Vaxry
92311d260a renderer: add transformers 2023-10-21 14:15:56 +01:00
Roberto Previdi
af72404259 hyprctl: add a query for workspace rules (#3630) 2023-10-21 02:28:34 +01:00
Vaxry
4a79718fe8 renderer: fix shimmers when manual resizing 2023-10-20 20:32:47 +01:00
Vaxry
7f35f33b4c surface/wayland: conform to small surface requirements
do not stretch small surfaces, instead center them if they fit.
2023-10-20 20:15:57 +01:00
thejch
bab2f6a664 master: fix movewindow across monitors (#3628) 2023-10-20 18:01:04 +01:00
thejch
bb9d0aed5b compositor: Fix a lack of a check for workspace equality on same monitors in getInDirection (#3625)
* prevent movefocus and movewindow from going into main workspace when in special workspace

* compare workspace IDs instead

* change comparison and make code more readable
2023-10-20 10:53:37 +01:00
Vaxry
386708563c workspacerules: search for special properly
fixes #3537
2023-10-19 16:04:59 +01:00
q234rty
ba5f1d8783 cmake: Map cmake None to meson empty (#3614)
While not explicitly mentioned by the cmake documentation, cmake
upstream seems to think of None as a vaild CMAKE_BUILD_TYPE. [1]
Handle it properly by mapping it to meson's empty.

[1]: ce1cadd35a
2023-10-19 15:59:24 +01:00
Campbell Barton
d994e6aea6 cmake: Fix error building without CMAKE_BUILD_TYPE being set (#3590)
* Fix error building without CMAKE_BUILD_TYPE being set

This resolves the error building without a CMAKE_BUILD_TYPE.
CMake Error at CMakeLists.txt:36 (string):                                                                                                                                                          
  string no output variable specified

* CMake: convert CMake's build type to meson build type

Fix error when the CMAKE_BUILD_TYPE variable isn't set & properly convert the build type to mesons build type.
2023-10-19 15:00:58 +01:00
Vaxry
6e15590e98 shaders: support changing the outer radius of borders independently 2023-10-19 14:05:02 +01:00
memchr
d70cc88dab meson: generate version.h before install_headers (#3612)
Otherwise, meson install would not install version.h as a header in a
clean build.
2023-10-19 00:09:06 +01:00
Vaxry
a0b675ec9e binds: add ignoreMods flag 2023-10-17 20:10:07 +01:00
André Silva
784f8a88fb input: don't reset cursor movement timer on simulateMouseMovement (#3595)
Fixes #2570
2023-10-17 17:00:39 +01:00
thejch
20e7ccd480 master: fix resizing wrong window behind in special workspace (#3591) 2023-10-17 12:06:16 +01:00
outfoxxed
210be10c92 meson/nix: Fix meson.build nix patch (#3594)
`meson.build` was modified in #3547 but `nix/patches/meson-build.patch`
was not updated to reflect the changes.
2023-10-17 12:05:38 +01:00
eriedaberrie
421f5fb221 events: make new windows taking over fullscreen keep the existing mode (#3588) 2023-10-17 11:41:27 +01:00
Jan Beich
93676f91a0 renderer: cast std::clamp args to be of the same type (#3589)
src/render/OpenGL.cpp:1769:41: error: no matching function for call to 'clamp'
    const auto         FORCEWALLPAPER = std::clamp(*PFORCEWALLPAPER, -1L, 2L);
                                        ^~~~~~~~~~
/usr/include/c++/v1/__algorithm/clamp.h:38:1: note: candidate template ignored: deduced conflicting types for parameter '_Tp' ('int64_t' (aka 'long long') vs. 'long')
clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi)
^
/usr/include/c++/v1/__algorithm/clamp.h:27:1: note: candidate function template not viable: requires 4 arguments, but 3 were provided
clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi, _Compare __comp)
^
2023-10-17 01:29:06 +01:00
memchr
54e1c2ccbd fix(build): do not include wlr headers directly, use includes.hpp instead. (#3587) 2023-10-16 17:39:12 +01:00
96 changed files with 2606 additions and 1122 deletions

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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>();

View File

@@ -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
View File

@@ -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": {

View File

@@ -12,7 +12,7 @@
host = "gitlab.freedesktop.org";
owner = "wlroots";
repo = "wlroots";
rev = "3406c1b17a4a7e6d4e2a7d9c1176affa72bce1bc";
rev = "47bf87ade2bd32395615a385ebde1fefbcdf79a2";
flake = false;
};

View File

@@ -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"))

View File

@@ -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')

View File

@@ -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")

View File

@@ -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,

View File

@@ -1,3 +1,3 @@
{
"version": "0.31.0"
"version": "0.32.0"
}

View File

@@ -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);
}

View File

@@ -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;
};

View File

@@ -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()};
}
};

View File

@@ -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;

View File

@@ -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, "]");
}
};
};

View File

@@ -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) {

View File

@@ -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

View File

@@ -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

View File

@@ -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")

View File

@@ -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);
}

View File

@@ -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;
};

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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);
};
};

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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
View 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
View 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;
};

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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

View File

@@ -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};
}

View File

@@ -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:

View File

@@ -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 &&

View File

@@ -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 "";

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;
};

View File

@@ -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"

View File

@@ -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);

View File

@@ -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, "]");

View File

@@ -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());

View File

@@ -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) {

View File

@@ -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;
}
};

View File

@@ -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();

View File

@@ -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

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;

View File

@@ -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,

View File

@@ -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;

View File

@@ -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*);

View File

@@ -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(&REGION))
wlr_cursor_map_input_to_region(g_pCompositor->m_sWLRCursor, t.wlrDevice, &REGION);
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;
}
}
}
}

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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;
}
};

View File

@@ -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();

View File

@@ -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);

View File

@@ -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);

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -0,0 +1,5 @@
#include "Transformer.hpp"
void IWindowTransformer::preWindowRender(SRenderData* pRenderData) {
;
}

View 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);
};

View File

@@ -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;
}

View File

@@ -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 = {};
};

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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