Compare commits

..

382 Commits

Author SHA1 Message Date
vaxerski
9f1d7f7fc7 properly scan for subsurfaces in fullscreen input refocus 2022-10-30 12:28:37 +00:00
vaxerski
6245c92bd0 avoid creating bound WS-es in moveWorkspaceToMonitor 2022-10-30 12:14:12 +00:00
vaxerski
2e32e202e9 set lastmonitor in onDisconnect 2022-10-29 22:45:01 +01:00
vaxerski
d994ad75e8 revert output smart layout reporting 2022-10-29 17:32:03 +01:00
vaxerski
2caebb3b10 fix default 0 in box passing test 2022-10-29 14:37:33 +01:00
vaxerski
05f3eebd96 avoid layout changes when unnecessary in applyMonitorRule 2022-10-29 12:24:44 +01:00
vaxerski
74d05d0adc ensure VRR for current display only in onConnect 2022-10-28 23:48:48 +01:00
vaxerski
341a0616aa avoid applying offset twice in onConnect 2022-10-28 23:23:23 +01:00
vaxerski
ea7f617df6 remove redundant check 2022-10-28 22:33:47 +01:00
vaxerski
644c64d79d lower IME errors to WARNs 2022-10-28 21:47:08 +01:00
vaxerski
d193d70ecf guard primaryFB tex in end() 2022-10-28 21:46:19 +01:00
vaxerski
9e227a52c0 allow cyclenext on null focus 2022-10-28 21:31:39 +01:00
vaxerski
1a767b021b fix minor focus oopsie 2022-10-28 20:12:17 +01:00
vaxerski
83e4006b16 properly find the constraint window 2022-10-28 19:35:02 +01:00
vaxerski
1759b0483c constrain mouse on focus change 2022-10-28 19:20:12 +01:00
vaxerski
f7174acc48 minor fixes for xwayland refocus 2022-10-28 19:18:10 +01:00
vaxerski
c2cd718e89 ignore pointer constraints in touch 2022-10-27 23:44:23 +01:00
Hilton Chain
c21808dd2d meson: Fallback to 'opengl' when 'GL' is not found.
This patch adds 'opengl' as a fallback to 'GL' for dependency lookup, to
link with libglvnd configured without X11 support.

For OpenGL, libglvnd provides two pkg-config files: `gl.pc' with GLX
support while `opengl.pc' not.  When building without X11 support, the
former won't be installed.
2022-10-28 00:50:58 +03:00
Vaxry
2c2e35eec1 Merge pull request #912 from riley-martin/hyprctl
Improve several hyprctl commands
2022-10-27 16:17:15 +01:00
Riley Martin
c064711d2a Improve hyprctl
Added better help for some hyprctl commands.
Failed commands should now 'fail' by returning a nonzero status to the shell

Fix typos
2022-10-27 10:39:21 -04:00
vaxerski
7d6ccca695 add 10bit support to displays 2022-10-27 13:26:47 +01:00
vaxerski
28c81fc71e add disabling pointer devices 2022-10-27 12:58:10 +01:00
Vaxry
d5a0610ea2 No xwayland overhaul (#920) 2022-10-27 11:26:35 +01:00
vaxerski
4aebb73de0 Added hyprctl cursorpos 2022-10-26 13:19:37 +01:00
vaxerski
46e51a81c4 unrestrict hyprctl message size 2022-10-26 13:11:05 +01:00
vaxerski
83ad59fae7 Allow 100%- for move rule 2022-10-26 12:34:26 +01:00
vaxerski
f9a7b6bf26 default focus_on_activate to false 2022-10-25 18:53:18 +01:00
vaxerski
cdb331076a allow # escaping in config 2022-10-25 14:32:25 +01:00
vaxerski
ba9a8a9ded unify LS unmap focus 2022-10-25 14:19:24 +01:00
vaxerski
34bd2cf803 respect wsbind in workspace silent rules 2022-10-25 10:30:25 +01:00
vaxerski
69f1d7b360 Rework workspace rules 2022-10-24 18:36:31 +01:00
vaxerski
e0bc952c83 minor fix to silent ws rules 2022-10-24 17:00:08 +01:00
vaxerski
cf869d9636 allow nofocus + workspace silent 2022-10-24 12:37:07 +01:00
vaxerski
077c1491a8 respect nofocus in candidate searching 2022-10-24 12:28:41 +01:00
vaxerski
c04563734e Rework candidate finding on close window 2022-10-24 12:25:36 +01:00
vaxerski
1d0d350fc3 fix silent + size windowrules 2022-10-24 12:03:15 +01:00
vaxerski
d55338a3f5 fix debug nest black screen 2022-10-24 11:58:07 +01:00
vaxerski
c6a3092b45 more safety around shutting down and mouse movements 2022-10-24 00:14:42 +01:00
vaxerski
10303259f7 always report sizes after a window unmap 2022-10-22 22:10:34 +01:00
Mihai Fufezan
3dca2fd61e Nix: override wayland-protocols 2022-10-23 00:01:55 +03:00
vaxerski
47eac4be1c disable adaptive sync with no_vfr off 2022-10-22 21:45:17 +01:00
vaxerski
2995867760 Transpose matrices on LEGACY_RENDERER 2022-10-22 21:10:49 +01:00
vaxerski
c132f5a91f [gha] bump flake inputs 2022-10-22 20:02:58 +00:00
vaxerski
24587492dd update wlroots dep 2022-10-22 21:01:45 +01:00
vaxerski
44cee0f5f8 more safety for focus requests 2022-10-22 16:45:33 +01:00
vaxerski
2c714eace5 handle activate requests 2022-10-22 16:43:47 +01:00
vaxerski
0d7d7a970d fix crash in event manager on hangup 2022-10-22 16:15:52 +01:00
Vaxry
3a27ef5e12 Merge pull request #893 from wael444/main
meson.build,CMakeLists.txt: use sh instead of bash
2022-10-22 11:57:36 +01:00
wael
6d273c8e44 CMakeLists.txt: use sh instead of bash 2022-10-22 09:23:52 +03:00
wael
c775153e01 meson.build: use sh instead of bash 2022-10-22 09:23:26 +03:00
vaxerski
b71d7c9007 minor workspace rule parsing fixes 2022-10-21 10:45:12 +01:00
vaxerski
ce5f025428 T1C: window dance compat 2022-10-20 22:38:49 +01:00
vaxerski
6df6aea1ba fix swipe with fullscreen maximized 2022-10-20 20:37:37 +01:00
Kainoa Kanter
ca2d2db0ef Add windowrules for noblur and noshadow (#884) 2022-10-20 20:36:27 +01:00
vaxerski
1ccb0b5f96 bump xdg ver to 5 2022-10-20 18:04:21 +01:00
vaxerski
c2545b3ae6 fix refocus on last window 2022-10-20 18:00:29 +01:00
vaxerski
dada872981 minor swipe on new fixes 2022-10-20 17:52:17 +01:00
vaxerski
1eec5161bd minor fix for swipes from empty workspaces 2022-10-20 15:47:35 +01:00
vaxerski
53c3644c29 fix minor anim issue with swipe new 2022-10-20 15:02:46 +01:00
vaxerski
6d66dde208 added swipe create new 2022-10-20 14:54:32 +01:00
vaxerski
1b349f79ac don't set custom mode in change 2022-10-19 22:12:02 +01:00
vaxerski
da8be82c9a Fix self-noding in changeWindowFloatingMode 2022-10-19 21:32:30 +01:00
vaxerski
8ffd244ef6 fix animate_manual_resizes with moves 2022-10-19 21:17:49 +01:00
vaxerski
bf9d31ce49 fix maximized windows not hiding tiled 2022-10-19 15:17:35 +01:00
vaxerski
98a32f5e52 render layer snapshot without blur 2022-10-19 11:00:59 +01:00
vaxerski
dc1737f128 allow glob wildcard in addreserved 2022-10-17 23:23:07 +01:00
Mihai Fufezan
48634d7e4a Nix & meson: 0.15.3 -> 0.16.0 2022-10-18 01:16:44 +03:00
vaxerski
ecf0cdaba4 a bit more default config nice addons 2022-10-17 16:59:52 +01:00
vaxerski
286cb90c48 ignore OR windows' size hints 2022-10-17 14:26:18 +01:00
vaxerski
3f77cde50e set XCURSOR_SIZE if not set in init 2022-10-17 14:01:04 +01:00
vaxerski
1145654987 default & example config overhaul 2022-10-17 13:48:21 +01:00
vaxerski
da4cfb9c32 use size hints when available in xwayland default geom 2022-10-17 11:18:45 +01:00
vaxerski
58375bc87a Add support for rgba() and rgb() colors in the config 2022-10-16 22:26:02 +01:00
Vaxry
83d99ce5bd Merge pull request #857 from K1llf0rce/max_size_rule
add maxsize window rule
2022-10-15 20:09:14 +01:00
K1llf0rce
dca30815b0 add maxsize window rule 2022-10-15 17:04:57 +02:00
vaxerski
edeb759bb1 add loose focus behavior 2022-10-15 14:13:21 +01:00
Mihai Fufezan
610d4d9473 Nix: update nixpkgs 2022-10-15 02:21:13 +03:00
Mihai Fufezan
f30e572e00 Nix & meson: 0.15.0beta -> 0.15.3beta
Nix: remove merged libdrm update
2022-10-15 01:40:25 +03:00
vaxerski
34cd8b125a rework focus system to be more safe and faster 2022-10-14 20:46:32 +01:00
vaxerski
b0544dbfff remove old log 2022-10-14 14:25:28 +01:00
vaxerski
a7bdfc06ca added bringactivetotop dispatcher 2022-10-14 14:22:31 +01:00
Narice
7e7cb40909 Nix modules: fix environment variables 2022-10-14 16:19:14 +03:00
vaxerski
724fa4a7d4 add touch binding to output 2022-10-14 12:38:44 +01:00
Vaxry
cee0645fd1 Merge pull request #813 from histausse/touch_dev_rotation
Add input:touchdevice:transform config
2022-10-14 12:26:31 +01:00
vaxerski
df9409b8a2 rename transform in DC to touch_transform 2022-10-14 12:23:11 +01:00
Vaxry
f274a70edf Merge pull request #852 from NotAShelf/patch-1
add `PKGBUILD` to ignored files
2022-10-14 11:11:28 +01:00
NotAShelf
ef24a27ade add PKGBUILD to ignored files 2022-10-14 11:46:34 +03:00
vaxerski
670d6ce8f4 fix windowsOut disabled with fadeOut enabled 2022-10-13 21:32:28 +01:00
Vaxry
f3917f2122 Merge pull request #844 from brodi1/hyprctl-json-fix
fix invalid json output by adding a missing comma
2022-10-13 15:32:46 +01:00
Brodi
5d6e56b67c fix invalid json output by adding a missing comma 2022-10-13 16:21:58 +02:00
vaxerski
624303bfb9 check for same workspace in workspace rule 2022-10-13 15:19:30 +01:00
vaxerski
eb3c132fc5 set workspace name in previous 2022-10-13 15:17:16 +01:00
vaxerski
170def35d7 simplify shouldRenderWindow and fix one cond 2022-10-12 18:37:11 +01:00
vaxerski
2ee9fb0675 don't recalc offset on monitor reload offset auto 2022-10-12 15:16:31 +01:00
vaxerski
1396d2a39b fix crash in renderWorkspaceWithFullscreenWindow 2022-10-11 20:29:51 +01:00
vaxerski
7ecc41db9c unsetenv on no XWayland 2022-10-11 12:00:06 +01:00
vaxerski
7ffe4eda12 [gha] build man pages 2022-10-11 10:58:53 +00:00
Simplykyle
25756afad5 Add debug coredump instructions (#812) 2022-10-11 11:58:26 +01:00
vaxerski
8880298f50 [gha] bump flake inputs 2022-10-11 09:33:36 +00:00
vaxerski
d89355f0a6 update wlroots 2022-10-11 10:32:11 +01:00
Vaxry
ae91f6610f Merge pull request #825 from Dickby/Fix_nproc_in_Makefile
Replace $(nproc) with $(shell nproc).
2022-10-10 22:36:10 +01:00
Felix Dick
6e7143e0f5 Replace $(nproc) with $(shell nproc). 2022-10-10 17:13:56 +02:00
Vaxry
f55f56f260 Merge pull request #823 from Dickby/simplify_matrix_calculations
Simplify matrix calculations
2022-10-10 15:59:25 +01:00
Histausse
6287f2b71b use static for transformation matrices 2022-10-10 12:52:12 +02:00
Felix Dick
7e781f24c5 Merge branch 'main' into simplify_matrix_calculations 2022-10-10 02:45:40 +02:00
Felix Dick
3bf7c5aea1 Change matrixProjection function stop use matrixFlip180 everywhere. 2022-10-10 01:35:42 +02:00
Felix Dick
092dbda88a Let openGL transpose the matrixes for us. 2022-10-10 01:32:04 +02:00
vaxerski
cb687c208c [gha] bump flake inputs 2022-10-09 20:30:56 +00:00
vaxerski
945b4d7139 update wlroots dep 2022-10-09 21:29:54 +01:00
vaxerski
881f828250 better subsurface handling on unmaps 2022-10-09 17:40:30 +01:00
vaxerski
0743dab3f0 use popup base surface instead of subsurface for addPopupGlobalCoords 2022-10-09 17:10:20 +01:00
vaxerski
496e37d044 ensure texture safety in clearWithTex() 2022-10-09 17:02:39 +01:00
Vaxry
1263bd5dcb Merge pull request #817 from Dickby/transform_box_in_renderRectWithDamage
inverse_transform the box in renderRectWithDamage.
2022-10-09 09:46:22 +01:00
Felix Dick
9ee78b1a92 inverse_transform the box in renderRectWithDamage. 2022-10-09 01:58:00 +02:00
Histausse
406b2fe6dc Add additionnal matrices and rename config var 2022-10-09 00:45:34 +02:00
vaxerski
90f2259f5e [gha] bump flake inputs 2022-10-08 17:01:31 +00:00
vaxerski
948f4978e7 update wlroots dep 2022-10-08 18:00:20 +01:00
Histausse
32ae0c51f0 Add input:touchdevice:td_rotation config
Add support for touch device roation. The rotation is
set globally with `input:touchdevice:td_rotation config` and by
device with `td_rotation` in a device block.
2022-10-08 15:25:46 +02:00
Vaxry
fe4a97f245 Merge pull request #794 from Dickby/pixman_early_outs
Check earlier if pixman_region is empty in some places.
2022-10-08 12:00:17 +01:00
Felix Dick
2f3528c076 Check earlier if pixman regions are empty. 2022-10-08 11:20:04 +02:00
vaxerski
1964bcb13f add open/close layer events 2022-10-07 22:25:00 +01:00
Vaxry
4b779ac142 Merge pull request #811 from Dickby/add_missing_pixman_region32_fini
Add missing pixman_region32_fini.
2022-10-07 22:20:35 +01:00
vaxerski
abc2d442dd fix a VRAM leak in destroyMonitorResources 2022-10-07 22:19:23 +01:00
Felix Dick
b64f1fc5c4 Add missing pixman_region32_fini. 2022-10-07 23:11:20 +02:00
vaxerski
33d264eaa7 release all fbs in destroyMonitorResources 2022-10-07 21:13:28 +01:00
Vaxry
5e3b8c3233 Merge pull request #807 from Dickby/fix_monitor_transforms
Transform the box data send to texture shaders.
2022-10-07 20:12:28 +01:00
Felix Dick
bbdfb7853d Transform the box data send to texture shaders. 2022-10-07 20:55:41 +02:00
vaxerski
a19b152e4a make swipe respect slidevert 2022-10-07 16:52:53 +01:00
vaxerski
1468001d3b offset floating windows out of bounds on ws anims 2022-10-07 12:34:54 +01:00
vaxerski
7faa3c367d Added clipping support, clip windows on slide anim 2022-10-07 10:43:51 +01:00
vaxerski
fd379db846 swallow improvements 2022-10-07 09:46:01 +01:00
vaxerski
28a6e0ce31 [gha] bump flake inputs 2022-10-06 21:09:10 +00:00
vaxerski
af7d60b3f8 revert wlroots ver to fix critical gpu issue 2022-10-06 22:08:08 +01:00
Vaxry
c4487534d2 Merge pull request #801 from fufexan/scrollfactor
Add input:touchpad:scroll_factor
2022-10-06 21:26:11 +01:00
Mihai Fufezan
e4820d1c71 Add input:touchpad:scroll_factor 2022-10-06 22:47:05 +03:00
vaxerski
b4a8efc1a7 fix naming when workspace back and forth 2022-10-06 20:40:58 +01:00
vaxerski
9480c0fb90 fix workspace previous with multi-mon ws moves 2022-10-06 20:18:49 +01:00
vaxerski
f901c60da5 return true on vt switch keysyms to avoid printing stuff 2022-10-06 19:31:32 +01:00
vaxerski
922e978f56 reset sigmask on fork 2022-10-06 19:02:03 +01:00
vaxerski
0508c7d384 more monitor checks for shutdown: 2022-10-06 18:43:50 +01:00
vaxerski
ee3b770cfd more checks in pid gathering 2022-10-06 17:58:38 +01:00
Vaxry
a29af89545 Merge pull request #793 from Dickby/fix_compiler_warnings
Fix compiler warnings.
2022-10-06 12:54:04 +01:00
Felix Dick
552c4b7361 Fix compiler warnings. 2022-10-06 13:42:52 +02:00
vaxerski
d7ef19e2e7 map touch to the correct output 2022-10-06 09:26:05 +01:00
vaxerski
190ddb5697 added a noanim rule 2022-10-06 09:16:40 +01:00
vaxerski
095688712d add minsize rule 2022-10-06 09:09:58 +01:00
vaxerski
d264fbd36a fix string corruption in hyprctl monitors -j 2022-10-06 09:04:46 +01:00
vaxerski
e4527c6b60 use goalv in clientsRequest 2022-10-06 08:54:09 +01:00
Vaxry
32e8eda40a Merge pull request #787 from fufexan/libinput
Add accel profile and scroll method
2022-10-05 21:58:40 +01:00
Mihai Fufezan
477ad2dd82 Add accel profile and scroll method 2022-10-05 23:51:08 +03:00
vaxerski
e90c5c6347 fix tty switch freeze 2022-10-05 21:41:27 +01:00
vaxerski
11ce468996 add dpms status info in hyprctl 2022-10-05 18:14:11 +01:00
vaxerski
9c5023ab1a monitor desc improvements 2022-10-05 17:38:36 +01:00
vaxerski
0e4a894edb add dpms per output 2022-10-05 10:31:47 +01:00
vaxerski
71e2562a41 add desc: to monitor rules 2022-10-05 10:22:33 +01:00
Vaxry
9153a81090 Merge pull request #781 from Dickby/fix_left_handed
Fix getDeviceInt string arg "input:left_handed"
2022-10-05 08:06:38 +01:00
Felix Dick
0d7f6eac9e Merge branch 'make_TTY_unsigned' into fix_left_handed 2022-10-05 04:51:48 +02:00
Felix Dick
6d46ed4011 Fix getDeviceInt string arg "input:left_handed" 2022-10-05 04:25:26 +02:00
Felix Dick
f825b87c2a Fix compiler warnig comparing signed and unsigned integers. 2022-10-05 02:42:51 +02:00
vaxerski
44da575ea8 [gha] bump flake inputs 2022-10-04 22:25:26 +00:00
vaxerski
a587909fd5 update wlroots dep 2022-10-04 23:24:31 +01:00
vaxerski
fd81ba5a4f [gha] bump flake inputs 2022-10-04 22:22:12 +00:00
Vaxry
934f81c93d Merge pull request #777 from Dickby/fix_shader_error
Remove texcoord from QUADFRAGSRC.
2022-10-04 23:20:52 +01:00
Felix Dick
e8be1507ef Remove texcoord from QUADFRAGSRC.
texcoord is unused in the rounding part of the textureshaders.
QUADFRAGSRC isn't using that variable inside the non rounding code.
Because of that opengl optimizes that variable out, and is complaining
if glGetAttribLocation is called on it.
2022-10-05 00:04:32 +02:00
vaxerski
60c414ccad add left_handed config for input 2022-10-04 21:46:41 +01:00
vaxerski
0d702b556d Add switch device handling and binds 2022-10-04 20:07:21 +01:00
vaxerski
9bbae5b8e2 ignore VT switches to current vt 2022-10-04 16:53:09 +01:00
vaxerski
719a5b4f0b use vectorToWindowIdeal in mouse binds 2022-10-04 16:08:55 +01:00
Vaxry
7bdfdaa28a Merge pull request #742 from Dickby/rework_rounding_shader
Rework rounding shader
2022-10-04 14:17:16 +01:00
vaxerski
a80e0cecfe fixes to window swallowing with same pid 2022-10-04 11:16:49 +01:00
vaxerski
3e3f6aef5e additional logic for identical pid swallowing 2022-10-04 10:17:10 +01:00
Vaxry
996938b7e7 Merge pull request #773 from lylac-1/main
focusedmon event check change
2022-10-04 10:04:10 +01:00
lylac
f9325b1655 focusedmon event check change
Compare PLASTWINDOW & PWINDOWTOCHANGETO m_iMonitorID's instead of PWINDOWTOCHANGETO->m_iMonitorID & g_pCompositor->m_pLastMonitor->ID
2022-10-04 18:19:14 +13:00
vaxerski
63dfe305dd log GPU info for debugging 2022-10-03 23:10:15 +01:00
Mihai Fufezan
ec0c6fa22a Nix & meson: 0.14.0 -> 0.15.0 2022-10-04 00:51:49 +03:00
vaxerski
ff5843bd85 anchor to proper quad in floating resize 2022-10-03 22:41:12 +01:00
vaxerski
3bb5971c2e [gha] bump flake inputs 2022-10-03 21:17:33 +00:00
vaxerski
a1d9404f9f update wlroots dep 2022-10-03 22:16:02 +01:00
vaxerski
ab82c4806d allow one less arg in bind 2022-10-03 21:01:08 +01:00
vaxerski
49ab3890aa remove polling from socket2, fully event based 2022-10-03 20:47:15 +01:00
vaxerski
85eea70be4 fix commas in free binds 2022-10-03 16:38:05 +01:00
vaxerski
174b593438 optimize removing trailing spaces 2022-10-03 14:36:56 +01:00
vaxerski
0a08830375 Unify arg lists, allow for trailing spaces in args 2022-10-03 14:29:45 +01:00
vaxerski
a97621b1cb Added window swallowing 2022-10-01 19:19:15 +01:00
vaxerski
355366714e minor OR XWayland fixes 2022-10-01 18:25:02 +01:00
vaxerski
590fbf808b send a focusedmon event on focus change mon 2022-10-01 10:38:53 +01:00
vaxerski
bbeed21e62 fix crash 2022-10-01 08:54:43 +01:00
Felix Dick
c6333ba796 Remove unused ignoreCorners variable from texture shaders. 2022-10-01 03:30:58 +02:00
Felix Dick
6fe103cf06 Cut the number of pixels that call length() in half. 2022-10-01 03:14:13 +02:00
Felix Dick
71733f68ef Merge branch 'fix_rounding_in_size_changing_windows' into rework_rounding_shader 2022-10-01 01:35:13 +02:00
vaxerski
e6c9e3f81d add case for empty strings in isNumber 2022-09-30 21:54:13 +01:00
vaxerski
7579e03b64 include shaders only in opengl.cpp 2022-09-30 18:38:10 +01:00
vaxerski
1ef23a304a remove redundant attrib setting 2022-09-30 17:04:33 +01:00
vaxerski
3c27d1ab13 optimize vector config value setting 2022-09-30 17:03:14 +01:00
vaxerski
59a3c43913 guard event in maximize request 2022-09-30 10:37:09 +01:00
Felix Dick
d867d42366 Merge branch 'main' into fix_rounding_in_size_changing_windows 2022-09-30 01:38:50 +02:00
Felix Dick
6eb7d00386 Send absolute screen coordinates to texture shaders. 2022-09-29 23:19:56 +02:00
vaxerski
2d73da1a79 enter outputs for non-interactive ls-es too 2022-09-29 22:16:43 +01:00
Vaxry
45fe185cb9 Merge pull request #736 from Dickby/fix_bordersize_again
Scale the border size, revert the window scaling according to border
2022-09-29 22:01:06 +01:00
Felix Dick
09268d756f Merge branch 'main' into rework_rounding_shader 2022-09-29 21:15:08 +02:00
Felix Dick
e5dced8b3f Merge branch 'main' into fix_rounding_in_size_changing_windows 2022-09-29 21:13:48 +02:00
Felix Dick
b38e7b596f Don't pass bottomRight to textureShaders compute it within. 2022-09-29 21:10:05 +02:00
vaxerski
da40bf823f apply new node data to all group windows on close 2022-09-29 19:46:33 +01:00
vaxerski
caeb0636fa fix crash on dwindle splitratio alter on single group 2022-09-29 19:41:49 +01:00
Felix Dick
1424539e4d Merge branch 'main' into rework_rounding_shader 2022-09-29 20:41:39 +02:00
vaxerski
bdd9680adf fix ipc event missing on silent movetoworkspace 2022-09-29 19:33:43 +01:00
vaxerski
ff4c22ca90 add fullscreen info to clients request 2022-09-29 19:30:49 +01:00
vaxerski
9f9129e536 focusable checks in nextWindow calls 2022-09-29 16:53:31 +01:00
Felix Dick
ab42e4bccf Merge branch 'main' into fix_bordersize_again 2022-09-29 14:29:03 +02:00
Felix Dick
425b07d1e5 Merge branch 'main' into rework_rounding_shader 2022-09-29 14:24:59 +02:00
vaxerski
2636abca2d use the event data for determining maximize status in requests 2022-09-29 10:24:54 +01:00
vaxerski
ead0e74471 handle maximize toplevel request 2022-09-29 10:20:17 +01:00
Vaxry
dcf5e34bfa Merge pull request #735 from Dickby/fix_splash_position
Splash position fix
2022-09-29 10:07:27 +01:00
Felix Dick
65fb526d5c Even less branching (taken more or less from the border shader). 2022-09-29 06:56:17 +02:00
Felix Dick
10c4f4ba35 Shift splash up if monitor has wider ratio than bgTexture. 2022-09-29 05:29:03 +02:00
Felix Dick
a1319e5110 Merge branch 'main' into fix_bordersize_again 2022-09-29 01:42:28 +02:00
Felix Dick
5233746ac5 Change scaledBorderSize to int. 2022-09-29 01:40:19 +02:00
Felix Dick
0549aa193f fixing your shit. 2022-09-28 23:33:18 +02:00
Felix Dick
168a326609 Merge branch 'main' into rework_rounding_shader 2022-09-28 23:11:11 +02:00
Vaxry
31cb4c49d9 Merge pull request #743 from Dickby/use_double_literals
Use double literals, don't cast integer or float literals to double.
2022-09-28 19:28:13 +01:00
Felix Dick
11ee78f88b Use double literals, don't cast a integer literal to double. 2022-09-28 20:08:41 +02:00
Felix Dick
7edbaea23d Make the rounding texture shaders smaller and more efficient. 2022-09-28 18:40:04 +02:00
vaxerski
ec5ffe8839 rewrite isNumber 2022-09-28 15:32:53 +01:00
vaxerski
e3b1d3c3c5 allow for pure workspace names in dispatchers 2022-09-28 15:26:41 +01:00
vaxerski
458ba3237b use goalv in movetoworkspace 2022-09-28 15:12:15 +01:00
Felix Dick
5ff44467d7 Avoid 38 files to compile every time a shader is modified. 2022-09-28 14:48:05 +02:00
Vaxry
7a775c0584 Merge pull request #737 from Dickby/use_max_instead_of_clamp_in_some_places
Replace clamp with max if there is no upper bound.
2022-09-26 20:49:56 +01:00
Felix Dick
87afc8c250 Replace clamp with max if there is no upper bound. 2022-09-26 21:10:24 +02:00
Felix Dick
cd2b2c4fba Scale the border size, revert the window scaling according to border 2022-09-26 17:38:08 +02:00
Felix Dick
c48336aac3 Scale the cairo matrix to fit the monitor dimensions. 2022-09-26 06:35:00 +02:00
Vaxry
f70b57f360 Merge pull request #732 from Dickby/main
Remove trailing whitespace.
2022-09-25 19:32:24 +01:00
Felix Dick
bf3f519eb7 Remove trailing whitespace. 2022-09-25 20:07:48 +02:00
Vaxry
190229942f Merge pull request #727 from Dickby/main
Scale border size in window size pos calculation
2022-09-25 17:21:31 +01:00
Dickby
e476382d08 scale border size in dwindle layout window sizes. 2022-09-25 18:12:42 +02:00
Dickby
c885afcbc6 Scale border size in calculations of windows 2022-09-25 12:42:39 +02:00
vaxerski
fad5fc587d guard kb settings in xkb translation state 2022-09-24 21:07:18 +01:00
vaxerski
73dbacd16d overwrite wsbind rules on existing 2022-09-24 13:42:18 +01:00
vaxerski
65fb0cf0f6 fix custom rules on null modelist 2022-09-24 13:10:11 +01:00
vaxerski
5101ddeff1 fix oopsies in rule code 2022-09-24 11:30:41 +01:00
Vaxry
959557ecc3 Merge pull request #716 from Dickby/main
Fixing my last change
2022-09-23 18:18:55 +01:00
Dickby
bccc81d306 Fixing my last change
It wasn't a problem with the bug i tried to fix.
But there  would be a problem if some function would dereference pPreviousGroupMember from the node that was PHEAD->pNextGroupMember.
Please don't be mean!
2022-09-23 19:13:05 +02:00
Vaxry
718de0d9fa Merge pull request #715 from Dickby/main
fix crash
2022-09-23 17:05:04 +01:00
vaxerski
fd6116c0cd style 2022-09-23 17:01:27 +01:00
Dickby
00b16888bf style fix 2022-09-23 17:59:33 +02:00
Vaxry
abee2da5bd Merge pull request #706 from DashieTM/main
Add "highest" mode to Monitor for autoconfiguration.
2022-09-23 16:50:24 +01:00
vaxerski
695411f1bd don't decorate on only no gaps 2022-09-23 16:47:58 +01:00
Dickby
f9d8b3096a fix crash
Fixes #711
2022-09-23 17:01:46 +02:00
vaxerski
e5d143b238 support more wlr_cursor events 2022-09-22 21:14:02 +01:00
vaxerski
37f2e1ddbe don't recalc pseudo on fullscreen 2022-09-22 20:57:09 +01:00
vaxerski
ef3eb37c7f support max in size rules 2022-09-22 18:13:23 +01:00
Mihai Fufezan
db551b8970 Nix & meson: bump to 0.14.0 2022-09-22 19:59:38 +03:00
vaxerski
c08218301b disallow pinning fullscreen 2022-09-22 16:48:40 +01:00
vaxerski
75aaf11a9c default pass_mouse_when_bound to 0 2022-09-22 16:33:45 +01:00
Fabio Lenherr
c4e782ca5d remove more silly mistakes 2022-09-22 00:50:23 +02:00
Fabio Lenherr
da2c2ddc21 remove empty line 2022-09-22 00:47:09 +02:00
Fabio Lenherr
5272588270 fix silly mistakes 2022-09-22 00:45:56 +02:00
Fabio Lenherr
215125bd66 add refreshrate or resolution preference 2022-09-22 00:22:39 +02:00
Fabio Lenherr
30d16373d0 fix Hz Log 2022-09-21 22:40:01 +02:00
Fabio Lenherr
c1feb683ce added high to monitor resolution 2022-09-21 22:29:52 +02:00
vaxerski
d3ffccd45f accept any case in binds 2022-09-21 17:41:26 +01:00
Mihai Fufezan
d49af1cc18 flake: add libdrm overlay until it gets updated 2022-09-21 18:10:35 +03:00
vaxerski
8b46d0b5a9 simplify some local vars 2022-09-21 15:11:09 +01:00
vaxerski
336883dda3 [gha] bump flake inputs 2022-09-21 14:09:05 +00:00
vaxerski
65ec8c7694 update wlroots dep 2022-09-21 15:07:57 +01:00
vaxerski
79c645f8cd handle touch devices internally as objects 2022-09-21 14:39:34 +01:00
vaxerski
d44cc9f112 [gha] bump flake inputs 2022-09-21 13:23:15 +00:00
vaxerski
1963da2d47 update wlroots dep 2022-09-21 14:22:05 +01:00
vaxerski
2b99dbb446 better cycling in fullscreen with pinned 2022-09-21 14:16:13 +01:00
vaxerski
d24f31de51 disallow fullscreen pinned 2022-09-21 14:09:26 +01:00
Fabio Lenherr / DashieTM
d51c7ca135 change Preferred mode to use highest refreshrate 2022-09-20 23:41:03 +02:00
vaxerski
8b11a2e1b1 minor mouse bind handling fixes 2022-09-20 22:23:02 +01:00
vaxerski
b4bcba935d disallow move/resize dispatchers on fullscreen windows 2022-09-20 19:58:08 +01:00
vaxerski
7f3750bd75 disable enabling groups on fullscreen windows 2022-09-20 18:08:10 +01:00
vaxerski
7a9423c782 better dwindle swapping with groups 2022-09-20 18:04:39 +01:00
vaxerski
6f98b3cbd8 fix pinned fade on fs 2022-09-20 15:33:53 +01:00
vaxerski
2dd1661aec fix groups with fullscreen 2022-09-20 12:17:34 +01:00
vaxerski
cde624ec6a fix moving between fullscreen workspaces 2022-09-20 10:16:58 +01:00
vaxerski
b82621c4ec fix mouse binds being stuck 2022-09-20 10:02:20 +01:00
vaxerski
5b6c8d5b0f fix misc fullscreen issues 2022-09-20 09:55:25 +01:00
vaxerski
4dca2b945b fix LS fading out on ws change 2022-09-20 09:46:55 +01:00
Vaxry
a8943246a7 Merge pull request #684 from tomahk/main
fix some bugs with attaching/disabling monitors
2022-09-19 21:08:48 +01:00
vaxerski
e42de0b778 export HYPRLAND_CMD for scripts 2022-09-19 21:06:44 +01:00
tomahk
5146165599 this is c++, use nullptr 2022-09-19 21:45:00 +02:00
tomahk
73e19aee6f prevent assert killing Hyprland after reenabling monitor 2022-09-19 20:44:33 +02:00
tomahk
3780361b95 fix hyprland freeze when undocking from docking station 2022-09-19 20:42:59 +02:00
vaxerski
ec6144e5da fix fadeout on unmap fullscreen 2022-09-19 19:09:21 +01:00
vaxerski
b6eaeffcf6 introduce new mouse binds in default and example cfgs 2022-09-19 19:06:22 +01:00
vaxerski
c24b45671a mouse binds overhaul 2022-09-19 19:04:48 +01:00
vaxerski
85c7aaf155 fade control for fullscreen action on windows 2022-09-19 17:26:11 +01:00
vaxerski
696253b348 fix special workspace dispatcher logic 2022-09-19 16:01:42 +01:00
vaxerski
abb6db9c37 don't apply alpha to fadingOut on setWindowFullscreen 2022-09-19 11:44:11 +01:00
vaxerski
18b483b8e1 fix ws switching with LS opacity 2022-09-19 10:40:42 +01:00
vaxerski
7c809a3059 fullscreen animation en-nice-ment 2022-09-19 10:23:13 +01:00
vaxerski
4070e1a148 fix wonky focus on movetoworkspace 2022-09-18 17:26:12 +01:00
vaxerski
dd61f88ed1 guard invalid FB allocs 2022-09-18 12:40:49 +01:00
vaxerski
29626989e7 fix focus follows mouse 0 event sending on wrong window 2022-09-18 12:35:05 +01:00
vaxerski
cf32d28082 fix groupbar being wonk on scaled 2022-09-18 12:13:16 +01:00
vaxerski
5131a4acaf fix special fullscreen 2022-09-17 15:07:03 +01:00
vaxerski
a72a39ebd5 minor swipe fixes 2022-09-17 15:05:12 +01:00
vaxerski
151e013241 fix refocus on same workspace 2022-09-17 12:10:06 +01:00
vaxerski
fa2d81b649 fix animation issues with workspace silent 2022-09-16 21:17:03 +01:00
vaxerski
037d4ed422 handle multi-ws swaps in layouts 2022-09-14 17:30:16 +02:00
vaxerski
9f82278d65 simplify dwindle swap 2022-09-14 17:24:45 +02:00
vaxerski
8e0f7b9b11 Various subsurface handling fixes 2022-09-14 16:34:41 +02:00
vaxerski
a96acc8fa4 only check for visible on xdg 2022-09-13 22:23:48 +02:00
vaxerski
5a146e9d90 guard surface in addsurfaceglobaloffset 2022-09-13 21:49:55 +02:00
vaxerski
da10022d84 fix an unholy memory safety issue 2022-09-13 20:27:07 +02:00
vaxerski
e518adf1ac don't iterate over subsurfaces in unmap 2022-09-13 15:44:50 +02:00
vaxerski
d8dbe26f31 tick config after reload request 2022-09-13 15:36:49 +02:00
vaxerski
e9f226797e Added monitor mirroring 2022-09-13 15:25:42 +02:00
vaxerski
7d4f0a3199 verify visibility of new geom in floating creation 2022-09-13 12:29:56 +02:00
vaxerski
0062281092 added wsbind 2022-09-12 21:05:52 +02:00
vaxerski
81f267dff9 add default speed to hyprctl devices mice 2022-09-12 17:09:04 +02:00
vaxerski
a09c614c2d more forceRendering checks in shouldRenderWindow 2022-09-12 15:33:25 +02:00
Vaxry
b49d7007b5 Merge pull request #659 from hyprwm/hyprctl-nopoll
hyprctl-nopoll
2022-09-11 20:48:22 +02:00
vaxerski
864e227f5d fix decos on pinned 2022-09-11 20:27:59 +02:00
vaxerski
82aa78916d hyprctl-nopoll 2022-09-10 21:21:28 +02:00
vaxerski
f024d7114f allow current in monitorfromstring 2022-09-10 19:57:57 +02:00
vaxerski
8808d40008 added misc:disable_autoreload 2022-09-10 17:28:41 +02:00
vaxerski
d94fe3d063 added window pinning 2022-09-10 13:11:02 +02:00
vaxerski
f663fa209c minor code styling fixes 2022-09-09 19:08:11 +02:00
Mihai Fufezan
9370c7aa8a Nix modules: add recommendedEnvironment option 2022-09-09 17:01:24 +03:00
vaxerski
928158bbfb prevent missed surface size updates on fullscreen window close 2022-09-08 23:02:29 +02:00
vaxerski
bacfae3084 guard drag in destroyDrag 2022-09-08 21:25:16 +02:00
vaxerski
0d95a0174c more guarding in cleanup pid gathering 2022-09-08 20:55:25 +02:00
vaxerski
0eb5ecafb9 consistent output of window addresses 2022-09-08 18:47:39 +02:00
vaxerski
49a55f136e fix addreserved lag 2022-09-08 14:11:32 +02:00
vaxerski
64be57b780 fix group decos on added windows 2022-09-07 20:36:39 +02:00
Vaxry
6e195a6b8c Merge pull request #636 from viperML/fix-man
docs: fix github workflow
2022-09-07 13:05:16 +02:00
Fernando Ayats
8d3f6c5d84 docs: fix github workflow 2022-09-07 12:44:20 +02:00
vaxerski
5c470d2e54 damage drag on destroy 2022-09-07 12:18:52 +02:00
Mihai Fufezan
26910a8b63 Nix HM module: fix build error
Apparently HM doesn't like having `lib.mkDefault` near strings.

Fixes #635
2022-09-07 13:11:03 +03:00
vaxerski
44a2d755c6 Added Xwayland and floating props to windowrulev2 2022-09-07 11:25:44 +02:00
Mars
cf5426f2d8 Fix typo in module.nix 2022-09-07 11:48:08 +03:00
Mihai Fufezan
1d631c8a23 Nix modules: add common environment variables 2022-09-07 01:24:09 +03:00
vaxerski
789eedd115 fix a minor bug with no gaps when only and groups 2022-09-06 19:59:59 +02:00
vaxerski
4a8274e5f0 fix dwindle no gaps when only when dissolving a group 2022-09-06 18:12:41 +02:00
vaxerski
4b7d28d2cb fix last partial commit 2022-09-06 18:12:25 +02:00
vaxerski
5fdd1dd60f simplify config monitor reloads and rearrange layers 2022-09-06 17:26:18 +02:00
vaxerski
e71a4d75de Added windowrulev2 2022-09-06 11:57:11 +02:00
vaxerski
f002bd1603 wrap lastwindow in quotes in hyprctl json 2022-09-05 23:07:56 +02:00
vaxerski
16f1d1b99b guard unsafe state in unmap ls 2022-09-05 22:35:41 +02:00
vaxerski
c1bc8d46e9 use lastMonitor in mapWindow 2022-09-05 22:04:49 +02:00
vaxerski
94ca386a8c set last monitor and dont refocus in some cases (changeworkspace) 2022-09-05 21:36:22 +02:00
vaxerski
2ba7cb2414 escape json strings in workspaces lastwindow title 2022-09-05 21:32:37 +02:00
vaxerski
5b5f36f494 fix transformed blur on new optimizations 2022-09-05 21:26:21 +02:00
vaxerski
a74b8033ca added a submap IPC event 2022-09-05 13:50:52 +02:00
vaxerski
41883e0522 fix wonky behavior with silent workspace rule 2022-09-05 11:44:43 +02:00
vaxerski
3ea89e6171 fix splash positioning 2022-09-05 11:31:54 +02:00
vaxerski
d6c06318af don't accumulate from virtual 2022-09-05 11:19:40 +02:00
vaxerski
cb839c9dcc guard pFoundWindow in CInputManager under fullscreen 2022-09-05 00:59:13 +02:00
vaxerski
3dd514a452 fix a damage issue with transformed blur 2022-09-04 23:08:04 +02:00
vaxerski
6afab12b91 fix blur on transformed displays 2022-09-04 19:27:38 +02:00
vaxerski
7a3b57c99c send accumulated modifiers to surfaces 2022-09-04 18:46:28 +02:00
vaxerski
ba0c5fe0bb fix mouse focus not returning from a LS on follow mouse 0 2022-09-04 18:42:11 +02:00
vaxerski
f6ecef0959 add lastwindow info to hyprctl workspaces 2022-09-04 18:32:03 +02:00
vaxerski
ff26531e11 use activateSurface in unconstrainMouse 2022-09-04 11:29:49 +02:00
vaxerski
fbd2b4799d Fix some more crimes against humanity 2022-09-03 22:49:52 +02:00
Mihai Fufezan
1664f81cae Nix: revert HM module import fix
fixes #619
2022-09-03 23:22:39 +03:00
vaxerski
c425e620af fix some minor crimes against humanity 2022-09-03 19:35:17 +02:00
vaxerski
f4add0ac6d refocus on reserved area 2022-09-03 15:35:53 +02:00
vaxerski
3c3f80c2fe simplify code and update monitor on warp 2022-09-03 11:55:19 +02:00
Mihai Fufezan
eee0cad4d0 Nix modules: fix imports 2022-09-03 02:20:20 +03:00
Mihai Fufezan
0ea96e87c0 flake: remove overlay warning 2022-09-03 01:55:28 +03:00
vaxerski
5d09bb647b fix up styling 2022-09-02 23:56:22 +02:00
vaxerski
f5697095bc unify monitor args 2022-09-02 11:53:12 +02:00
vaxerski
56203b1757 fix no_gaps_when_only with a group 2022-09-01 19:46:38 +02:00
Fernando Ayats
c0a7dffcdc nix: move wlroots and add nvidia patches (#608) 2022-09-01 20:35:50 +03:00
vaxerski
8581e71789 optimize calls in toggleSpecialWorkspace 2022-09-01 11:47:48 +02:00
vaxerski
bb90ff0461 sanity check on last window 2022-09-01 11:46:41 +02:00
vaxerski
1d4d2f4793 [gha] bump flake inputs 2022-09-01 09:25:26 +00:00
vaxerski
7f62cbc48a Update wlroots dep 2022-09-01 11:24:15 +02:00
vaxerski
f2d84a7e3a guard parent in X11TransientFor 2022-09-01 10:16:23 +02:00
vaxerski
095185cfe7 guard parent in X11TransientFor 2022-09-01 10:15:55 +02:00
vaxerski
f77fac9df9 warp only on another monitor in changeworkspace 2022-08-31 21:39:27 +02:00
vaxerski
dacaf72e02 remember last window on workspace 2022-08-31 17:02:49 +02:00
Mihai Fufezan
0ad261aa9c flake: formatting 2022-08-31 12:26:12 +03:00
Mihai Fufezan
7610c20761 Nix & meson: 0.11.1 -> 0.12.1
flake: add commit to wlroots version
2022-08-31 12:22:32 +03:00
vaxerski
4103bca056 default rounding to 0 2022-08-31 11:17:04 +02:00
vaxerski
21a1b62b6a remove tiling node when invalid 2022-08-31 11:14:33 +02:00
vaxerski
7f483dfdb0 guard psurface in activateSurface 2022-08-31 11:12:46 +02:00
vaxerski
1cf46fd6a2 added closewindow dispatcher 2022-08-30 21:35:27 +02:00
87 changed files with 4321 additions and 1861 deletions

View File

@@ -62,7 +62,7 @@ jobs:
run: |
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
pacman --noconfirm --noprogressbar -Syyu
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd cmake
- name: Checkout Hyprland
uses: actions/checkout@v3
with:
@@ -73,13 +73,23 @@ jobs:
-Ddefault_library=static
- name: Compile
run: ninja -C obj-x86_64-pc-linux-gnu
# - name: Compress artifacts
# run: |
# mkdir x86_64-pc-linux-gnu
# DESTDIR=$PWD/x86_64-pc-linux-gnu meson install -C obj-x86_64-pc-linux-gnu --tags runtime
# tar -cvf x86_64-pc-linux-gnu.tar.xz x86_64-pc-linux-gnu
# - name: Upload artifacts
# uses: actions/upload-artifact@v3
# with:
# name: Build artifacts (x86_64-pc-linux-gnu)
# path: x86_64-pc-linux-gnu.tar.xz
noxwayland:
name: "Build Hyprland in pure Wayland (Arch)"
runs-on: ubuntu-latest
container:
image: archlinux
steps:
- name: Download dependencies
run: |
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
pacman --noconfirm --noprogressbar -Syyu
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd
- name: Checkout Hyprland
uses: actions/checkout@v3
with:
submodules: true
- name: Configure
run: mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DNO_XWAYLAND:STRING=true -H./ -B./build -G Ninja
- name: Compile
run: make config && make release

View File

@@ -5,6 +5,8 @@ on:
push:
paths:
- docs/**
branches:
- 'main'
jobs:
main:

2
.gitignore vendored
View File

@@ -25,3 +25,5 @@ hyprctl/hyprctl
gmon.out
*.out
*.tar.gz
PKGBUILD

View File

@@ -5,7 +5,7 @@ project(Hyprland
set(CMAKE_MESSAGE_LOG_LEVEL "STATUS")
message(STATUS "Configuring Hyprland!")
message(STATUS "Gathering git info")
# Get git info
# hash and branch
@@ -22,27 +22,38 @@ execute_process(
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(
COMMAND bash -c "git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1"
COMMAND sh -c "git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_MESSAGE
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(
COMMAND bash -c "git diff-index --quiet HEAD -- || echo \"dirty\""
COMMAND sh -c "git diff-index --quiet HEAD -- || echo \"dirty\""
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_DIRTY
OUTPUT_STRIP_TRAILING_WHITESPACE)
#
#
IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "Configuring Hyprland in Debug with CMake")
add_definitions( -DHYPRLAND_DEBUG )
ELSE()
add_compile_options( -O3 )
message(STATUS "Configuring Hyprland in Release with CMake")
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
include_directories(. PRIVATE "subprojects/wlroots/include/")
include_directories(. PRIVATE "subprojects/wlroots/build/include/")
add_compile_options(-std=c++23 -DWLR_USE_UNSTABLE )
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing)
message(STATUS "Checking deps...")
find_package(Threads REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo pango pangocairo libdrm egl xkbcommon libinput xcb) # we do not check for wlroots, as we provide it ourselves
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo pango pangocairo libdrm egl xkbcommon libinput) # we do not check for wlroots, as we provide it ourselves
file(GLOB_RECURSE SRCFILES "src/*.cpp")
@@ -56,15 +67,11 @@ ENDIF(LEGACY_RENDERER MATCHES true)
IF(NO_XWAYLAND MATCHES true)
message(STATUS "Using the NO_XWAYLAND flag, disabling XWayland!")
add_definitions( -DNO_XWAYLAND )
ENDIF(NO_XWAYLAND MATCHES true)
IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "Configuring Hyprland in Debug with CMake!")
add_definitions( -DHYPRLAND_DEBUG )
ELSE()
add_compile_options( -O3 )
message(STATUS "Configuring Hyprland in Release with CMake!")
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "XWAYLAND Enabled (NO_XWAYLAND not defined) checking deps...")
pkg_check_modules(xcbdep REQUIRED xcb)
target_link_libraries(Hyprland xcb)
ENDIF(NO_XWAYLAND MATCHES true)
target_compile_definitions(Hyprland PRIVATE "-DGIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\"")
target_compile_definitions(Hyprland PRIVATE "-DGIT_BRANCH=\"${GIT_BRANCH}\"")
@@ -77,6 +84,8 @@ set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
message(STATUS "Setting link libraries")
target_link_libraries(Hyprland PkgConfig::deps)
target_link_libraries(Hyprland
@@ -90,6 +99,8 @@ target_link_libraries(Hyprland
)
IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "Setting debug flags")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg -no-pie -fno-builtin")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg -no-pie -fno-builtin")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pg -no-pie -fno-builtin")

View File

@@ -93,19 +93,19 @@ wlr-output-power-management-unstable-v1-protocol.o: wlr-output-power-management-
legacyrenderer:
mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DLEGACY_RENDERER:STRING=true -H./ -B./build -G Ninja
cmake --build ./build --config Release --target all -j $(nproc)
cmake --build ./build --config Release --target all -j$(shell nproc)
legacyrendererdebug:
mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DLEGACY_RENDERER:STRING=true -H./ -B./build -G Ninja
cmake --build ./build --config Release --target all -j $(nproc)
cmake --build ./build --config Release --target all -j$(shell nproc)
release:
mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -H./ -B./build -G Ninja
cmake --build ./build --config Release --target all -j $(nproc)
cmake --build ./build --config Release --target all -j$(shell nproc)
debug:
mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -H./ -B./build -G Ninja
cmake --build ./build --config Debug --target all -j $(nproc)
cmake --build ./build --config Debug --target all -j$(shell nproc)
clear:
rm -rf build

View File

@@ -1,6 +1,6 @@
.\" Automatically generated by Pandoc 2.5
.\"
.TH "Hyprland" "1" "24 Aug 2022" "" "Hyprland User Manual"
.TH "Hyprland" "1" "11 Oct 2022" "" "Hyprland User Manual"
.hy
.SH NAME
.PP

View File

@@ -57,3 +57,15 @@ coredumpctl info [PID]
```
where `[PID]` is the PID you remembered.
## Obtaining the debug Hyprland coredump
In very rare cases, the normal coredump would not be enough.
If that's the case, you could try obtaining the debug coredump.
1. [Compile Hyprland with debug mode](http://wiki.hyprland.org/Contributing-and-Debugging/#build-in-debug-mode)
> Note: The config file used will be `hyprlandd.conf` instead of `hyprland.conf`
2. Reproduce the crash in debug mode.
3. `env DEBUGINFOD_URLS="https://debuginfod.archlinux.org/" coredumpctl debug [PID]`(see section above)
4. Wait until the `(gdb)` appears
5. If gdb asks you `press y to continue without paging?` Type `y`
6. `bt -full`
7. copy the output of the command and provide that.

View File

@@ -1,6 +1,6 @@
.\" Automatically generated by Pandoc 2.5
.\"
.TH "hyprctl" "1" "24 Aug 2022" "" "hyprctl User Manual"
.TH "hyprctl" "1" "11 Oct 2022" "" "hyprctl User Manual"
.hy
.SH NAME
.PP

View File

@@ -1,19 +1,27 @@
# This is an example Hyprland config file.
# Syntax is the same as in Hypr, but settings might differ.
#
# Refer to the wiki for more information.
#
# Please note not all available settings / options are set here.
# For a full list, see the wiki (basic and advanced configuring)
# For a full list, see the wiki
#
# See https://wiki.hyprland.org/Configuring/Monitors/
monitor=,preferred,auto,1
workspace=DP-1,1
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
# Execute your favorite apps at launch
# exec-once = waybar & hyprpaper & firefox
# Source a file (multi-file configs)
# source = ~/.config/hypr/myColors.conf
# For all categories, see https://wiki.hyprland.org/Configuring/Variables/
input {
kb_file=
kb_layout=
kb_layout = us
kb_variant =
kb_model =
kb_options =
@@ -29,87 +37,122 @@ input {
}
general {
main_mod=SUPER
# See https://wiki.hyprland.org/Configuring/Variables/ for more
gaps_in = 5
gaps_out = 20
border_size = 2
col.active_border=0x66ee1111
col.inactive_border=0x66333333
col.active_border = rgba(1affffee)
col.inactive_border = rgba(595959aa)
apply_sens_to_raw=0 # whether to apply the sensitivity to raw input (e.g. used by games where you aim using your mouse)
damage_tracking=full # leave it on full unless you hate your GPU and want to make it suffer
layout = dwindle
}
decoration {
# See https://wiki.hyprland.org/Configuring/Variables/ for more
rounding = 10
blur=1
blur_size=3 # minimum 1
blur_passes=1 # minimum 1
blur_new_optimizations=1
blur = yes
blur_size = 3
blur_passes = 1
blur_new_optimizations = on
drop_shadow = yes
shadow_range = 4
shadow_render_power = 3
col.shadow = rgba(1a1a1aee)
}
animations {
enabled=1
animation=windows,1,7,default
enabled = yes
# Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
bezier = myBezier, 0.05, 0.9, 0.1, 1.05
animation = windows, 1, 7, myBezier
animation = windowsOut, 1, 7, default, popin 80%
animation = border, 1, 10, default
animation=fade,1,10,default
animation = fade, 1, 7, default
animation = workspaces, 1, 6, default
}
dwindle {
pseudotile=0 # enable pseudotiling on dwindle
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
pseudotile = yes # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
preserve_split = yes # you probably want this
}
master {
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
new_is_master = true
}
gestures {
workspace_swipe=no
# See https://wiki.hyprland.org/Configuring/Variables/ for more
workspace_swipe = off
}
# example window rules
# for windows named/classed as abc and xyz
#windowrule=move 69 420,abc
#windowrule=size 420 69,abc
#windowrule=tile,xyz
#windowrule=float,abc
#windowrule=pseudo,abc
#windowrule=monitor 0,xyz
# Example per-device config
# See https://wiki.hyprland.org/Configuring/Keywords/#executing for more
device:epic mouse V1 {
sensitivity = -0.5
}
# example binds
bind=SUPER,Q,exec,kitty
bind=SUPER,C,killactive,
bind=SUPER,M,exit,
bind=SUPER,E,exec,dolphin
bind=SUPER,V,togglefloating,
bind=SUPER,R,exec,wofi --show drun -o DP-3
bind=SUPER,P,pseudo,
# Example windowrule v1
# windowrule = float, ^(kitty)$
# Example windowrule v2
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
bind=SUPER,left,movefocus,l
bind=SUPER,right,movefocus,r
bind=SUPER,up,movefocus,u
bind=SUPER,down,movefocus,d
bind=SUPER,1,workspace,1
bind=SUPER,2,workspace,2
bind=SUPER,3,workspace,3
bind=SUPER,4,workspace,4
bind=SUPER,5,workspace,5
bind=SUPER,6,workspace,6
bind=SUPER,7,workspace,7
bind=SUPER,8,workspace,8
bind=SUPER,9,workspace,9
bind=SUPER,0,workspace,10
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
$mainMod = SUPER
bind=ALT,1,movetoworkspace,1
bind=ALT,2,movetoworkspace,2
bind=ALT,3,movetoworkspace,3
bind=ALT,4,movetoworkspace,4
bind=ALT,5,movetoworkspace,5
bind=ALT,6,movetoworkspace,6
bind=ALT,7,movetoworkspace,7
bind=ALT,8,movetoworkspace,8
bind=ALT,9,movetoworkspace,9
bind=ALT,0,movetoworkspace,10
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
bind = $mainMod, Q, exec, kitty
bind = $mainMod, C, killactive,
bind = $mainMod, M, exit,
bind = $mainMod, E, exec, dolphin
bind = $mainMod, V, togglefloating,
bind = $mainMod, R, exec, wofi --show drun
bind = $mainMod, P, pseudo, # dwindle
bind = $mainMod, J, togglesplit, # dwindle
bind=SUPER,mouse_down,workspace,e+1
bind=SUPER,mouse_up,workspace,e-1
# Move focus with mainMod + arrow keys
bind = $mainMod, left, movefocus, l
bind = $mainMod, right, movefocus, r
bind = $mainMod, up, movefocus, u
bind = $mainMod, down, movefocus, d
# Switch workspaces with mainMod + [0-9]
bind = $mainMod, 1, workspace, 1
bind = $mainMod, 2, workspace, 2
bind = $mainMod, 3, workspace, 3
bind = $mainMod, 4, workspace, 4
bind = $mainMod, 5, workspace, 5
bind = $mainMod, 6, workspace, 6
bind = $mainMod, 7, workspace, 7
bind = $mainMod, 8, workspace, 8
bind = $mainMod, 9, workspace, 9
bind = $mainMod, 0, workspace, 10
# Move active window to a workspace with mainMod + SHIFT + [0-9]
bind = $mainMod SHIFT, 1, movetoworkspace, 1
bind = $mainMod SHIFT, 2, movetoworkspace, 2
bind = $mainMod SHIFT, 3, movetoworkspace, 3
bind = $mainMod SHIFT, 4, movetoworkspace, 4
bind = $mainMod SHIFT, 5, movetoworkspace, 5
bind = $mainMod SHIFT, 6, movetoworkspace, 6
bind = $mainMod SHIFT, 7, movetoworkspace, 7
bind = $mainMod SHIFT, 8, movetoworkspace, 8
bind = $mainMod SHIFT, 9, movetoworkspace, 9
bind = $mainMod SHIFT, 0, movetoworkspace, 10
# Scroll through existing workspaces with mainMod + scroll
bind = $mainMod, mouse_down, workspace, e+1
bind = $mainMod, mouse_up, workspace, e-1
# Move/resize windows with mainMod + LMB/RMB and dragging
bindm = $mainMod, mouse:272, movewindow
bindm = $mainMod, mouse:273, resizewindow

12
flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1660908602,
"narHash": "sha256-SwZ85IPWvC4NxxFhWhRMTJpApSHbY1u4YK2UFWEBWvY=",
"lastModified": 1666377499,
"narHash": "sha256-dZZCGvWcxc7oGnUgFVf0UeNHsJ4VhkTM0v5JRe8EwR8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "495b19d5b3e62b4ec7e846bdfb6ef3d9c3b83492",
"rev": "301aada7a64812853f2e2634a530ef5d34505048",
"type": "github"
},
"original": {
@@ -26,11 +26,11 @@
"flake": false,
"locked": {
"host": "gitlab.freedesktop.org",
"lastModified": 1660930713,
"narHash": "sha256-bY7q1NqG/sjCUAWPn/Ne9NCigLlPlH5Lk1WCMqv3rTU=",
"lastModified": 1666466001,
"narHash": "sha256-ZjxAnqtcGmHQHKL1Z9sIraDnzIqrJleWcJXfPtzAm74=",
"owner": "wlroots",
"repo": "wlroots",
"rev": "7c575922c05e4d5fd9a403c2aa631a54c7531d44",
"rev": "c2d2773df57750081b16d56da13b5015d752cbd7",
"type": "gitlab"
},
"original": {

View File

@@ -20,22 +20,34 @@
"aarch64-linux"
"x86_64-linux"
];
pkgsFor = nixpkgs.legacyPackages;
pkgsFor = genSystems (system: import nixpkgs {
inherit system;
overlays = [(_: prev: {
wayland-protocols = prev.wayland-protocols.overrideAttrs (old: rec {
version = "1.27";
src = prev.fetchurl {
url = "https://gitlab.freedesktop.org/wayland/${old.pname}/-/releases/${version}/downloads/${old.pname}-${version}.tar.xz";
hash = "sha256-kEbxCkJdTioAlloDrPtrP7V1pWUDrHLCuGghxpZTN1w=";
};
});
})];
});
mkDate = longDate: (lib.concatStringsSep "-" [
(__substring 0 4 longDate)
(__substring 4 2 longDate)
(__substring 6 2 longDate)
(builtins.substring 0 4 longDate)
(builtins.substring 4 2 longDate)
(builtins.substring 6 2 longDate)
]);
in {
overlays.default = _: prev: rec {
wlroots-hyprland = prev.wlroots.overrideAttrs (__: {
version = mkDate (inputs.wlroots.lastModifiedDate or "19700101");
wlroots-hyprland = prev.callPackage ./nix/wlroots.nix {
version = mkDate (inputs.wlroots.lastModifiedDate or "19700101") + "_" + (inputs.wlroots.shortRev or "dirty");
src = inputs.wlroots;
});
};
hyprland = prev.callPackage ./nix/default.nix {
stdenv = prev.gcc12Stdenv;
version = "0.11.1beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
version = "0.16.0beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
wlroots = wlroots-hyprland;
};
hyprland-debug = hyprland.override {debug = true;};
@@ -66,8 +78,6 @@
nixosModules.default = import ./nix/module.nix self;
homeManagerModules.default = import ./nix/hm-module.nix self;
overlay = throw "Hyprland: .overlay output is deprecated, please use the .overlays.default output";
};
nixConfig = {

View File

@@ -36,6 +36,7 @@ commands:
reload
setcursor
getoption
cursorpos
flags:
-j -> output in JSON
@@ -80,6 +81,7 @@ void request(std::string arg) {
return;
}
std::string reply = "";
char buffer[8192] = {0};
sizeWritten = read(SERVERSOCKET, buffer, 8192);
@@ -89,9 +91,20 @@ void request(std::string arg) {
return;
}
reply += std::string(buffer, sizeWritten);
while (sizeWritten == 8192) {
sizeWritten = read(SERVERSOCKET, buffer, 8192);
if (sizeWritten < 0) {
std::cout << "Couldn't read (5)";
return;
}
reply += std::string(buffer, sizeWritten);
}
close(SERVERSOCKET);
std::cout << std::string(buffer);
std::cout << reply;
}
void requestHyprpaper(std::string arg) {
@@ -145,11 +158,12 @@ void requestHyprpaper(std::string arg) {
std::cout << std::string(buffer);
}
void dispatchRequest(int argc, char** argv) {
int dispatchRequest(int argc, char** argv) {
if (argc < 4) {
std::cout << "dispatch requires 2 params";
return;
std::cout << "Usage: hyprctl dispatch <dispatcher> <arg>\n\
Execute a hyprland keybind dispatcher with the given argument";
return 1;
}
std::string rq = "/dispatch";
@@ -158,12 +172,14 @@ void dispatchRequest(int argc, char** argv) {
rq += " " + std::string(argv[i]);
request(rq);
return 0;
}
void keywordRequest(int argc, char** argv) {
int keywordRequest(int argc, char** argv) {
if (argc < 4) {
std::cout << "keyword requires 2 params";
return;
std::cout << "Usage: hyprctl keyword <keyword> <arg>\n\
Execute a hyprland keyword with the given argument";
return 1;
}
std::string rq = "/keyword";
@@ -172,28 +188,33 @@ void keywordRequest(int argc, char** argv) {
rq += " " + std::string(argv[i]);
request(rq);
return 0;
}
void hyprpaperRequest(int argc, char** argv) {
int hyprpaperRequest(int argc, char** argv) {
if (argc < 4) {
std::cout << "hyprpaper requires 2 params";
return;
std::cout << "Usage: hyprctl hyprpaper <command> <arg>\n\
Execute a hyprpaper command with the given argument";
return 1;
}
std::string rq = std::string(argv[2]) + " " + std::string(argv[3]);
requestHyprpaper(rq);
return 0;
}
void setcursorRequest(int argc, char** argv) {
int setcursorRequest(int argc, char** argv) {
if (argc < 4) {
std::cout << "setcursor requires 2 params";
return;
std::cout << "Usage: hyprctl setcursor <theme> <size>\n\
Sets the cursor theme for everything except GTK and reloads the cursor";
return 1;
}
std::string rq = "setcursor " + std::string(argv[2]) + " " + std::string(argv[3]);
request(rq);
return 0;
}
void batchRequest(std::string arg) {
@@ -254,6 +275,8 @@ int main(int argc, char** argv) {
fullRequest = fullArgs + "/" + fullRequest;
int exitStatus = 0;
if (fullRequest.contains("/--batch")) batchRequest(fullRequest);
else if (fullRequest.contains("/monitors")) request(fullRequest);
else if (fullRequest.contains("/clients")) request(fullRequest);
@@ -266,10 +289,11 @@ int main(int argc, char** argv) {
else if (fullRequest.contains("/devices")) request(fullRequest);
else if (fullRequest.contains("/reload")) request(fullRequest);
else if (fullRequest.contains("/getoption")) request(fullRequest);
else if (fullRequest.contains("/setcursor")) setcursorRequest(argc, argv);
else if (fullRequest.contains("/dispatch")) dispatchRequest(argc, argv);
else if (fullRequest.contains("/keyword")) keywordRequest(argc, argv);
else if (fullRequest.contains("/hyprpaper")) hyprpaperRequest(argc, argv);
else if (fullRequest.contains("/cursorpos")) request(fullRequest);
else if (fullRequest.contains("/setcursor")) exitStatus = setcursorRequest(argc, argv);
else if (fullRequest.contains("/dispatch")) exitStatus = dispatchRequest(argc, argv);
else if (fullRequest.contains("/keyword")) exitStatus = keywordRequest(argc, argv);
else if (fullRequest.contains("/hyprpaper")) exitStatus = hyprpaperRequest(argc, argv);
else if (fullRequest.contains("/--help")) printf("%s", USAGE.c_str());
else {
printf("%s\n", USAGE.c_str());
@@ -277,5 +301,5 @@ int main(int argc, char** argv) {
}
printf("\n");
return 0;
return exitStatus;
}

View File

@@ -1,5 +1,5 @@
project('Hyprland', 'cpp', 'c',
version : '0.11.1beta',
version : '0.16.0beta',
default_options : [
'warning_level=2',
'default_library=static',
@@ -20,8 +20,8 @@ endif
GIT_BRANCH = run_command('git', 'rev-parse', '--abbrev-ref', 'HEAD', check: false).stdout().strip()
GIT_COMMIT_HASH = run_command('git', 'rev-parse', 'HEAD', check: false).stdout().strip()
GIT_COMMIT_MESSAGE = run_command('bash', '-c', 'git show | head -n 5 | tail -n 1', check: false).stdout().strip()
GIT_DIRTY = run_command('bash', '-c', 'git diff-index --quiet HEAD -- || echo "dirty"', check: false).stdout().strip()
GIT_COMMIT_MESSAGE = run_command('sh', '-c', 'git show | head -n 5 | tail -n 1', check: false).stdout().strip()
GIT_DIRTY = run_command('sh', '-c', 'git diff-index --quiet HEAD -- || echo "dirty"', check: false).stdout().strip()
add_project_arguments(
[

View File

@@ -24,6 +24,7 @@
enableXWayland ? true,
hidpiXWayland ? true,
legacyRenderer ? false,
nvidiaPatches ? false,
version ? "git",
}: let
assertXWayland = lib.assertMsg (hidpiXWayland -> enableXWayland) ''
@@ -68,11 +69,7 @@ in
wayland
wayland-protocols
wayland-scanner
(
if hidpiXWayland
then (import ./hidpi_wlroots.nix {inherit wlroots xwayland fetchpatch;})
else wlroots.override {inherit enableXWayland;}
)
(wlroots.override {inherit enableXWayland hidpiXWayland nvidiaPatches;})
xcbutilwm
]
++ lib.optional enableXWayland xwayland;

View File

@@ -1,31 +0,0 @@
{
wlroots,
xwayland,
fetchpatch,
}:
(wlroots.overrideAttrs
(old: {
patches =
(old.patches or [])
++ [
(fetchpatch {
url = "https://gitlab.freedesktop.org/lilydjwg/wlroots/-/commit/6c5ffcd1fee9e44780a6a8792f74ecfbe24a1ca7.diff";
sha256 = "sha256-Eo1pTa/PIiJsRZwIUnHGTIFFIedzODVf0ZeuXb0a3TQ=";
})
(fetchpatch {
url = "https://gitlab.freedesktop.org/wlroots/wlroots/-/commit/18595000f3a21502fd60bf213122859cc348f9af.diff";
sha256 = "sha256-jvfkAMh3gzkfuoRhB4E9T5X1Hu62wgUjj4tZkJm0mrI=";
revert = true;
})
];
}))
.override {
xwayland = xwayland.overrideAttrs (old: {
patches =
(old.patches or [])
++ [
./xwayland-vsync.patch
./xwayland-hidpi.patch
];
});
}

View File

@@ -67,6 +67,16 @@ in {
'';
};
recommendedEnvironment = lib.mkOption {
type = lib.types.bool;
default = true;
defaultText = lib.literalExpression "true";
example = lib.literalExpression "false";
description = ''
Whether to set the recommended environment variables.
'';
};
imports = [
(
lib.mkRenamedOptionModule
@@ -81,10 +91,17 @@ in {
lib.optional (cfg.package != null) cfg.package
++ lib.optional cfg.xwayland.enable pkgs.xwayland;
home.sessionVariables = lib.mkIf cfg.recommendedEnvironment {
GDK_BACKEND = "wayland,x11";
_JAVA_AWT_WM_NONREPARENTING = "1";
NIXOS_OZONE_WL = "1";
XCURSOR_SIZE = toString config.home.pointerCursor.size or "24";
XDG_SESSION_TYPE = "wayland";
};
xdg.configFile."hypr/hyprland.conf" = {
text =
(lib.optionalString cfg.systemdIntegration ''
exec-once=export XDG_SESSION_TYPE=wayland
exec-once=${pkgs.dbus}/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP
exec-once=systemctl --user start hyprland-session.target
'')

View File

@@ -8,6 +8,10 @@ self: {
with lib; let
cfg = config.programs.hyprland;
in {
imports = [
(mkRemovedOptionModule ["programs" "hyprland" "extraPackages"] "extraPackages has been removed. Use environment.systemPackages instead.")
];
options.programs.hyprland = {
enable = mkEnableOption ''
Hyprland, the dynamic tiling Wayland compositor that doesn't sacrifice on its looks.
@@ -27,20 +31,40 @@ in {
'';
};
imports = [
(mkRemovedOptionModule ["programs" "hyprland" "extraPackages"] "extraPackages has been removed. Use environment.systemPackages instead.")
];
recommendedEnvironment = mkOption {
type = types.bool;
default = true;
defaultText = literalExpression "true";
example = literalExpression "false";
description = ''
Whether to set the recommended environment variables.
'';
};
};
config = mkIf cfg.enable {
environment.systemPackages = lib.optional (cfg.package != null) cfg.package;
security.polkit.enable = true;
hardware.opengl.enable = mkDefault true;
environment = {
systemPackages = lib.optional (cfg.package != null) cfg.package;
sessionVariables = mkIf cfg.recommendedEnvironment {
GDK_BACKEND = "wayland,x11";
_JAVA_AWT_WM_NONREPARENTING = "1";
NIXOS_OZONE_WL = "1";
XCURSOR_SIZE = "24";
XDG_SESSION_TYPE = "wayland";
};
};
fonts.enableDefaultFonts = mkDefault true;
programs.dconf.enable = mkDefault true;
hardware.opengl.enable = mkDefault true;
programs = {
dconf.enable = mkDefault true;
xwayland.enable = mkDefault true;
};
security.polkit.enable = true;
services.xserver.displayManager.sessionPackages = lib.optional (cfg.package != null) cfg.package;
programs.xwayland.enable = mkDefault true;
xdg.portal.enable = mkDefault true;
xdg.portal.extraPortals = [pkgs.xdg-desktop-portal-wlr];
xdg.portal = {
enable = mkDefault true;
extraPortals = [pkgs.xdg-desktop-portal-wlr];
};
};
}

64
nix/wlroots.nix Normal file
View File

@@ -0,0 +1,64 @@
{
version,
src,
#
wlroots,
xwayland,
fetchpatch,
lib,
hidpiXWayland ? true,
enableXWayland ? true,
nvidiaPatches ? false,
}:
assert (lib.assertMsg (hidpiXWayland -> enableXWayland) ''
wlroots-hyprland: cannot have hidpiXWayland when enableXWayland is false.
'');
(wlroots.overrideAttrs
(old: {
inherit version src;
pname =
old.pname
+ "-hyprland"
+ (
if hidpiXWayland
then "-hidpi"
else ""
)
+ (
if nvidiaPatches
then "-nvidia"
else ""
);
patches =
(old.patches or [])
++ (lib.optionals (enableXWayland && hidpiXWayland) [
(fetchpatch {
url = "https://gitlab.freedesktop.org/lilydjwg/wlroots/-/commit/6c5ffcd1fee9e44780a6a8792f74ecfbe24a1ca7.diff";
sha256 = "sha256-Eo1pTa/PIiJsRZwIUnHGTIFFIedzODVf0ZeuXb0a3TQ=";
})
(fetchpatch {
url = "https://gitlab.freedesktop.org/wlroots/wlroots/-/commit/18595000f3a21502fd60bf213122859cc348f9af.diff";
sha256 = "sha256-jvfkAMh3gzkfuoRhB4E9T5X1Hu62wgUjj4tZkJm0mrI=";
revert = true;
})
]);
postPatch =
(old.postPatch or "")
+ (
if nvidiaPatches
then ''
substituteInPlace render/gles2/renderer.c --replace "glFlush();" "glFinish();"
''
else ""
);
}))
.override {
xwayland = xwayland.overrideAttrs (old: {
patches =
(old.patches or [])
++ (lib.optionals hidpiXWayland [
./xwayland-vsync.patch
./xwayland-hidpi.patch
]);
});
}

View File

@@ -107,7 +107,7 @@ CCompositor::CCompositor() {
m_sWLRScene = wlr_scene_create();
wlr_scene_attach_output_layout(m_sWLRScene, m_sWLROutputLayout);
m_sWLRXDGShell = wlr_xdg_shell_create(m_sWLDisplay, 4);
m_sWLRXDGShell = wlr_xdg_shell_create(m_sWLDisplay, 5);
m_sWLRCursor = wlr_cursor_create();
wlr_cursor_attach_output_layout(m_sWLRCursor, m_sWLROutputLayout);
@@ -115,6 +115,9 @@ CCompositor::CCompositor() {
m_sWLRXCursorMgr = wlr_xcursor_manager_create(nullptr, 24);
wlr_xcursor_manager_load(m_sWLRXCursorMgr, 1);
if (const auto XCURSORENV = getenv("XCURSOR_SIZE"); !XCURSORENV || std::string(XCURSORENV).empty())
setenv("XCURSOR_SIZE", "24", true);
m_sSeat.seat = wlr_seat_create(m_sWLDisplay, "seat0");
m_sWLRPresentation = wlr_presentation_create(m_sWLDisplay, m_sWLRBackend);
@@ -167,6 +170,8 @@ CCompositor::CCompositor() {
m_sWLRTextInputMgr = wlr_text_input_manager_v3_create(m_sWLDisplay);
m_sWLRIMEMgr = wlr_input_method_manager_v2_create(m_sWLDisplay);
m_sWLRActivation = wlr_xdg_activation_v1_create(m_sWLDisplay);
}
CCompositor::~CCompositor() {
@@ -198,6 +203,9 @@ void CCompositor::initAllSignals() {
addWLSignal(&m_sWLRCursor->events.touch_down, &Events::listen_touchBegin, m_sWLRCursor, "WLRCursor");
addWLSignal(&m_sWLRCursor->events.touch_up, &Events::listen_touchEnd, m_sWLRCursor, "WLRCursor");
addWLSignal(&m_sWLRCursor->events.touch_motion, &Events::listen_touchUpdate, m_sWLRCursor, "WLRCursor");
addWLSignal(&m_sWLRCursor->events.touch_frame, &Events::listen_touchFrame, m_sWLRCursor, "WLRCursor");
addWLSignal(&m_sWLRCursor->events.hold_begin, &Events::listen_holdBegin, m_sWLRCursor, "WLRCursor");
addWLSignal(&m_sWLRCursor->events.hold_end, &Events::listen_holdEnd, m_sWLRCursor, "WLRCursor");
addWLSignal(&m_sWLRBackend->events.new_input, &Events::listen_newInput, m_sWLRBackend, "Backend");
addWLSignal(&m_sSeat.seat->events.request_set_cursor, &Events::listen_requestMouse, &m_sSeat, "Seat");
addWLSignal(&m_sSeat.seat->events.request_set_selection, &Events::listen_requestSetSel, &m_sSeat, "Seat");
@@ -220,6 +228,7 @@ void CCompositor::initAllSignals() {
addWLSignal(&m_sWLROutputPowerMgr->events.set_mode, &Events::listen_powerMgrSetMode, m_sWLROutputPowerMgr, "PowerMgr");
addWLSignal(&m_sWLRIMEMgr->events.input_method, &Events::listen_newIME, m_sWLRIMEMgr, "IMEMgr");
addWLSignal(&m_sWLRTextInputMgr->events.text_input, &Events::listen_newTextInput, m_sWLRTextInputMgr, "TextInputMgr");
addWLSignal(&m_sWLRActivation->events.request_activate, &Events::listen_activateXDG, m_sWLRActivation, "ActivationV1");
if(m_sWRLDRMLeaseMgr)
addWLSignal(&m_sWRLDRMLeaseMgr->events.request, &Events::listen_leaseRequest, &m_sWRLDRMLeaseMgr, "DRM");
@@ -232,19 +241,19 @@ void CCompositor::cleanup() {
if (!m_sWLDisplay || m_bIsShuttingDown)
return;
m_bIsShuttingDown = true;
m_pLastFocus = nullptr;
m_pLastWindow = nullptr;
// accumulate all PIDs for killing, also request closing.
for (auto& w : m_vWindows) {
if (w->m_bIsMapped && !w->isHidden())
m_dProcessPIDsOnShutdown.push_back(w->getPID());
closeWindow(w.get());
}
// end threads
g_pEventManager->m_tThread = std::thread();
HyprCtl::tThread = std::thread();
m_vWorkspaces.clear();
m_vWindows.clear();
@@ -256,6 +265,8 @@ void CCompositor::cleanup() {
wlr_output_commit(m->output);
}
m_vMonitors.clear();
if (g_pXWaylandManager->m_sWLRXWayland) {
wlr_xwayland_destroy(g_pXWaylandManager->m_sWLRXWayland);
g_pXWaylandManager->m_sWLRXWayland = nullptr;
@@ -263,8 +274,6 @@ void CCompositor::cleanup() {
wl_display_terminate(m_sWLDisplay);
m_bIsShuttingDown = true;
g_pKeybindManager->spawn("sleep 5 && kill -9 " + std::to_string(m_iHyprlandPID)); // this is to prevent that random "freezing"
// the PID should not be reused.
}
@@ -442,27 +451,34 @@ CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
if (PMONITOR->specialWorkspaceOpen) {
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && (*w)->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !(*w)->m_bHidden)
if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && (*w)->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !(*w)->isHidden())
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 == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && !w->m_bIsFloating && !w->m_bHidden)
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && !w->m_bIsFloating && !w->isHidden())
return w.get();
}
}
// pinned
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, pos.x, pos.y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && !(*w)->isHidden() && (*w)->m_bPinned)
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.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, pos.x, pos.y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden)
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)
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->m_bHidden)
if (wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && !w->m_bIsFloating && PMONITOR->activeWorkspace == w->m_iWorkspaceID && !w->isHidden())
return w.get();
}
@@ -475,14 +491,14 @@ CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
if (PMONITOR->specialWorkspaceOpen) {
for (auto& w : m_vWindows) {
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && !w->m_bIsFloating && !w->m_bHidden)
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && !w->m_bIsFloating && !w->isHidden())
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->m_bHidden)
if (w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bIsFloating && !w->isHidden())
return w.get();
}
@@ -505,21 +521,21 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
if (PMONITOR->specialWorkspaceOpen) {
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && (*w)->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !(*w)->m_bHidden && !(*w)->m_bX11ShouldntFocus)
if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && (*w)->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !(*w)->isHidden() && !(*w)->m_bX11ShouldntFocus)
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 == SPECIAL_WORKSPACE_ID && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w->m_bHidden && !w->m_bX11ShouldntFocus)
if (!w->m_bIsFloating && w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w->isHidden() && !w->m_bX11ShouldntFocus)
return w.get();
}
}
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
// pinned windows on top of floating regardless
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if ((*w)->m_bIsFloating && (*w)->m_bIsMapped && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden && !(*w)->m_bX11ShouldntFocus) {
if ((*w)->m_bIsFloating && (*w)->m_bIsMapped && !(*w)->isHidden() && !(*w)->m_bX11ShouldntFocus && (*w)->m_bPinned) {
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y))
return w->get();
@@ -535,9 +551,40 @@ 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.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if ((*w)->m_bIsFloating && (*w)->m_bIsMapped && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->isHidden() && !(*w)->m_bPinned) {
// 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 ((*w)->m_iX11Type == 2) {
// Override Redirect
return g_pCompositor->m_pLastWindow; // we kinda trick everything here.
// TODO: this is wrong, we should focus the parent, but idk how to get it considering it's nullptr in most cases.
}
return w->get();
}
if (!(*w)->m_bIsX11) {
wlr_surface* resultSurf = nullptr;
Vector2D origin =(*w)->m_vRealPosition.vec();
SExtensionFindingData data = {origin, pos, &resultSurf};
wlr_xdg_surface_for_each_popup_surface((*w)->m_uSurface.xdg, findExtensionForVector2D, &data);
if (resultSurf)
return w->get();
}
}
}
// for windows, we need to check their extensions too, first.
for (auto& w : m_vWindows) {
if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bHidden && !w->m_bX11ShouldntFocus) {
if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->isHidden() && !w->m_bX11ShouldntFocus) {
wlr_surface* resultSurf = nullptr;
Vector2D origin = w->m_vRealPosition.vec();
SExtensionFindingData data = {origin, pos, &resultSurf};
@@ -549,7 +596,7 @@ 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->m_bHidden && !w->m_bX11ShouldntFocus)
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)
return w.get();
}
@@ -562,7 +609,7 @@ CWindow* CCompositor::windowFromCursor() {
if (PMONITOR->specialWorkspaceOpen) {
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && (*w)->m_bIsMapped && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && !(*w)->m_bHidden)
if ((*w)->m_bIsFloating && (*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && (*w)->m_bIsMapped && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && !(*w)->isHidden())
return (*w).get();
}
@@ -573,10 +620,17 @@ CWindow* CCompositor::windowFromCursor() {
}
}
// pinned
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && (*w)->m_bPinned)
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.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID))
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)
return w->get();
}
@@ -592,7 +646,13 @@ CWindow* CCompositor::windowFromCursor() {
CWindow* CCompositor::windowFloatingFromCursor() {
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden)
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && !(*w)->isHidden() && (*w)->m_bPinned)
return w->get();
}
for (auto w = m_vWindows.rbegin(); w != m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && (*w)->m_bIsMapped && (*w)->m_bIsFloating && isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->isHidden() && !(*w)->m_bPinned)
return w->get();
}
@@ -655,6 +715,8 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
if (windowValidMapped(PLASTWINDOW)) {
updateWindowAnimatedDecorationValues(PLASTWINDOW);
g_pXWaylandManager->activateWindow(PLASTWINDOW, false);
if (PLASTWINDOW->m_phForeignToplevel)
wlr_foreign_toplevel_handle_v1_set_activated(PLASTWINDOW->m_phForeignToplevel, false);
}
@@ -663,6 +725,8 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","});
g_pLayoutManager->getCurrentLayout()->onWindowFocusChange(nullptr);
m_pLastFocus = nullptr;
return;
}
@@ -675,6 +739,9 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
if (m_pLastWindow == pWindow && m_sSeat.seat->keyboard_state.focused_surface == pSurface)
return;
if (pWindow->m_bPinned)
pWindow->m_iWorkspaceID = m_pLastMonitor->activeWorkspace;
if (!isWorkspaceVisible(pWindow->m_iWorkspaceID))
g_pKeybindManager->changeworkspace("[internal]" + std::to_string(pWindow->m_iWorkspaceID));
@@ -685,10 +752,8 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
if (windowValidMapped(PLASTWINDOW)) {
updateWindowAnimatedDecorationValues(PLASTWINDOW);
if (PLASTWINDOW->m_bIsX11) {
wlr_seat_keyboard_notify_clear_focus(m_sSeat.seat);
wlr_seat_pointer_clear_focus(m_sSeat.seat);
}
if (!pWindow->m_bIsX11 || pWindow->m_iX11Type == 1)
g_pXWaylandManager->activateWindow(PLASTWINDOW, false);
if (PLASTWINDOW->m_phForeignToplevel)
wlr_foreign_toplevel_handle_v1_set_activated(PLASTWINDOW->m_phForeignToplevel, false);
@@ -711,8 +776,18 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
// Send an event
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", g_pXWaylandManager->getAppIDClass(pWindow) + "," + pWindow->m_szTitle});
g_pLayoutManager->getCurrentLayout()->onWindowFocusChange(pWindow);
if (pWindow->m_phForeignToplevel)
wlr_foreign_toplevel_handle_v1_set_activated(pWindow->m_phForeignToplevel, true);
if (!pWindow->m_bIsX11) {
const auto PCONSTRAINT = wlr_pointer_constraints_v1_constraint_for_surface(m_sWLRPointerConstraints, pWindow->m_uSurface.xdg->surface, m_sSeat.seat);
if (PCONSTRAINT)
g_pInputManager->constrainMouse(m_sSeat.mouse, PCONSTRAINT);
}
}
void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
@@ -721,7 +796,7 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
return; // Don't focus when already focused on this.
// Unfocus last surface if should
if (m_pLastFocus && ((m_sSeat.seat->keyboard_state.focused_surface && wlr_surface_is_xdg_surface(m_pLastFocus)) || !pSurface))
if (m_pLastFocus && !pWindowOwner)
g_pXWaylandManager->activateSurface(m_pLastFocus, false);
if (!pSurface) {
@@ -758,6 +833,9 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
}
bool CCompositor::windowValidMapped(CWindow* pWindow) {
if (!pWindow)
return false;
if (!windowExists(pWindow))
return false;
@@ -767,7 +845,7 @@ bool CCompositor::windowValidMapped(CWindow* pWindow) {
if (!pWindow->m_bIsMapped)
return false;
if (pWindow->m_bHidden)
if (pWindow->isHidden())
return false;
return true;
@@ -784,7 +862,7 @@ CWindow* CCompositor::getWindowForPopup(wlr_xdg_popup* popup) {
wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<std::unique_ptr<SLayerSurface>>* layerSurfaces, Vector2D* sCoords, SLayerSurface** ppLayerSurfaceFound) {
for (auto it = layerSurfaces->rbegin(); it != layerSurfaces->rend(); it++) {
if ((*it)->fadingOut || !(*it)->layerSurface || ((*it)->layerSurface && !(*it)->layerSurface->mapped))
if ((*it)->fadingOut || !(*it)->layerSurface || ((*it)->layerSurface && !(*it)->layerSurface->mapped) || (*it)->alpha.fl() == 0.f)
continue;
const auto SURFACEAT = wlr_layer_surface_v1_surface_at((*it)->layerSurface, pos.x - (*it)->geometry.x, pos.y - (*it)->geometry.y, &sCoords->x, &sCoords->y);
@@ -877,7 +955,7 @@ int CCompositor::getWindowsOnWorkspace(const int& id) {
CWindow* CCompositor::getFirstWindowOnWorkspace(const int& id) {
for (auto& w : m_vWindows) {
if (w->m_iWorkspaceID == id && w->m_bIsMapped && !w->m_bHidden)
if (w->m_iWorkspaceID == id && w->m_bIsMapped && !w->isHidden())
return w.get();
}
@@ -923,7 +1001,7 @@ void CCompositor::moveWindowToTop(CWindow* pWindow) {
std::deque<CWindow*> toMove;
for (auto& w : m_vWindows) {
if (w->m_bIsMapped && w->m_bMappedX11 && !w->m_bHidden && w->m_bIsX11 && w->X11TransientFor() == pWindow) {
if (w->m_bIsMapped && w->m_bMappedX11 && !w->isHidden() && w->m_bIsX11 && w->X11TransientFor() == pWindow) {
toMove.emplace_back(w.get());
}
}
@@ -1046,7 +1124,7 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
CWindow* longestIntersectWindow = nullptr;
for (auto& w : m_vWindows) {
if (w.get() == pWindow || !w->m_bIsMapped || w->m_bHidden || w->m_bIsFloating || !isWorkspaceVisible(w->m_iWorkspaceID))
if (w.get() == pWindow || !w->m_bIsMapped || w->isHidden() || w->m_bIsFloating || !isWorkspaceVisible(w->m_iWorkspaceID))
continue;
const auto BWINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved();
@@ -1057,7 +1135,7 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
switch (dir) {
case 'l':
if (STICKS(POSA.x, POSB.x + SIZEB.x)) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectWindow = w.get();
@@ -1066,7 +1144,7 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
break;
case 'r':
if (STICKS(POSA.x + SIZEA.x, POSB.x)) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectWindow = w.get();
@@ -1076,7 +1154,7 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
case 't':
case 'u':
if (STICKS(POSA.y, POSB.y + SIZEB.y)) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectWindow = w.get();
@@ -1086,7 +1164,7 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
case 'b':
case 'd':
if (STICKS(POSA.y + SIZEA.y, POSB.y)) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectWindow = w.get();
@@ -1109,7 +1187,7 @@ void CCompositor::deactivateAllWLRWorkspaces(wlr_ext_workspace_handle_v1* exclud
}
}
CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow) {
CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow, bool focusableOnly) {
bool gotToWindow = false;
for (auto& w : m_vWindows) {
if (w.get() != pWindow && !gotToWindow)
@@ -1120,19 +1198,19 @@ CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow) {
continue;
}
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->m_bHidden)
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_bNoFocus))
return w.get();
}
for (auto& w : m_vWindows) {
if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->m_bHidden)
if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_bNoFocus))
return w.get();
}
return nullptr;
}
CWindow* CCompositor::getPrevWindowOnWorkspace(CWindow* pWindow) {
CWindow* CCompositor::getPrevWindowOnWorkspace(CWindow* pWindow, bool focusableOnly) {
bool gotToWindow = false;
for (auto it = m_vWindows.rbegin(); it != m_vWindows.rend(); it++) {
if (it->get() != pWindow && !gotToWindow)
@@ -1143,12 +1221,12 @@ CWindow* CCompositor::getPrevWindowOnWorkspace(CWindow* pWindow) {
continue;
}
if ((*it)->m_iWorkspaceID == pWindow->m_iWorkspaceID && (*it)->m_bIsMapped && !(*it)->m_bHidden)
if ((*it)->m_iWorkspaceID == pWindow->m_iWorkspaceID && (*it)->m_bIsMapped && !(*it)->isHidden() && (!focusableOnly || !(*it)->m_bNoFocus))
return it->get();
}
for (auto it = m_vWindows.rbegin(); it != m_vWindows.rend(); it++) {
if (it->get() != pWindow && (*it)->m_iWorkspaceID == pWindow->m_iWorkspaceID && (*it)->m_bIsMapped && !(*it)->m_bHidden)
if (it->get() != pWindow && (*it)->m_iWorkspaceID == pWindow->m_iWorkspaceID && (*it)->m_bIsMapped && !(*it)->isHidden() && (!focusableOnly || !(*it)->m_bNoFocus))
return it->get();
}
@@ -1198,6 +1276,11 @@ bool CCompositor::isPointOnAnyMonitor(const Vector2D& point) {
return false;
}
void checkFocusSurfaceIter(wlr_surface* pSurface, int x, int y, void* data) {
auto pair = (std::pair<wlr_surface*, bool>*)data;
pair->second = pair->second || pSurface == pair->first;
}
CWindow* CCompositor::getConstraintWindow(SMouse* pMouse) {
if (!pMouse->currentConstraint)
return nullptr;
@@ -1205,10 +1288,17 @@ CWindow* CCompositor::getConstraintWindow(SMouse* pMouse) {
const auto PSURFACE = pMouse->currentConstraint->surface;
for (auto& w : m_vWindows) {
if (PSURFACE == g_pXWaylandManager->getWindowSurface(w.get())) {
if (!w->m_bIsX11 && w->m_bIsMapped && !w->m_bHidden)
if (w->isHidden() || !w->m_bMappedX11 || !w->m_bIsMapped || !g_pXWaylandManager->getWindowSurface(w.get()))
continue;
if (w->m_bIsX11) {
if (PSURFACE == g_pXWaylandManager->getWindowSurface(w.get()))
return w.get();
} else {
std::pair<wlr_surface*, bool> check = {PSURFACE, false};
wlr_surface_for_each_surface(w->m_uSurface.xdg->surface, checkFocusSurfaceIter, &check);
if (check.second)
return w.get();
}
}
@@ -1232,7 +1322,7 @@ CMonitor* CCompositor::getMonitorInDirection(const char& dir) {
switch (dir) {
case 'l':
if (STICKS(POSA.x, POSB.x + SIZEB.x)) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectMonitor = m.get();
@@ -1241,7 +1331,7 @@ CMonitor* CCompositor::getMonitorInDirection(const char& dir) {
break;
case 'r':
if (STICKS(POSA.x + SIZEA.x, POSB.x)) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectMonitor = m.get();
@@ -1251,7 +1341,7 @@ CMonitor* CCompositor::getMonitorInDirection(const char& dir) {
case 't':
case 'u':
if (STICKS(POSA.y, POSB.y + SIZEB.y)) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectMonitor = m.get();
@@ -1261,7 +1351,7 @@ CMonitor* CCompositor::getMonitorInDirection(const char& dir) {
case 'b':
case 'd':
if (STICKS(POSA.y + SIZEA.y, POSB.y)) {
const auto INTERSECTLEN = std::max((double)0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
const auto INTERSECTLEN = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
if (INTERSECTLEN > longestIntersect) {
longestIntersect = INTERSECTLEN;
longestIntersectMonitor = m.get();
@@ -1398,6 +1488,17 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB)
}
}
// fix pinned windows
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_iWorkspaceID == pMonitorA->activeWorkspace && w->m_bPinned) {
w->m_iWorkspaceID = PWORKSPACEB->m_iID;
}
if (w->m_iWorkspaceID == pMonitorB->activeWorkspace && w->m_bPinned) {
w->m_iWorkspaceID = PWORKSPACEA->m_iID;
}
}
pMonitorA->activeWorkspace = PWORKSPACEB->m_iID;
pMonitorB->activeWorkspace = PWORKSPACEA->m_iID;
@@ -1430,6 +1531,9 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) {
return nullptr;
}
} else {
if (name == "current")
return g_pCompositor->m_pLastMonitor;
if (isDirection(name)) {
const auto PMONITOR = g_pCompositor->getMonitorInDirection(name[0]);
return PMONITOR;
@@ -1472,7 +1576,7 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni
if (nextWorkspaceOnMonitorID == -1) {
nextWorkspaceOnMonitorID = 1;
while (getWorkspaceByID(nextWorkspaceOnMonitorID))
while (getWorkspaceByID(nextWorkspaceOnMonitorID) || [&]() -> bool { const auto B = g_pConfigManager->getBoundMonitorForWS(std::to_string(nextWorkspaceOnMonitorID)); return B && B != POLDMON; }())
nextWorkspaceOnMonitorID++;
Debug::log(LOG, "moveWorkspaceToMonitor: Plugging gap with new %d", nextWorkspaceOnMonitorID);
@@ -1493,7 +1597,7 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni
w->m_iMonitorID = pMonitor->ID;
// additionally, move floating and fs windows manually
if (w->m_bIsMapped && !w->m_bHidden) {
if (w->m_bIsMapped && !w->isHidden()) {
if (w->m_bIsFloating)
w->m_vRealPosition = w->m_vRealPosition.vec() - POLDMON->vecPosition + pMonitor->vecPosition;
@@ -1535,6 +1639,9 @@ bool CCompositor::workspaceIDOutOfBounds(const int& id) {
int highestID = -99999;
for (auto& w : m_vWorkspaces) {
if (w->m_iID == SPECIAL_WORKSPACE_ID)
continue;
if (w->m_iID < lowestID)
lowestID = w->m_iID;
@@ -1549,7 +1656,19 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode
if (!windowValidMapped(pWindow))
return;
focusWindow(pWindow);
if (pWindow->m_bPinned) {
Debug::log(LOG, "Pinned windows cannot be fullscreen'd");
return;
}
const auto PMONITOR = getMonitorFromID(pWindow->m_iMonitorID);
const auto PWORKSPACE = getWorkspaceByID(pWindow->m_iWorkspaceID);
if (PWORKSPACE->m_bHasFullscreenWindow && on) {
Debug::log(LOG, "Rejecting fullscreen ON on a fullscreen workspace");
return;
}
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(pWindow, mode, on);
@@ -1557,8 +1676,16 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode
// make all windows on the same workspace under the fullscreen window
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID)
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID) {
w->m_bCreatedOverFullscreen = false;
if (w.get() != pWindow && !w->m_bFadingOut && !w->m_bPinned)
w->m_fAlpha = pWindow->m_bIsFullscreen ? 0.f : 255.f;
}
}
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
if (!ls->fadingOut)
ls->alpha = pWindow->m_bIsFullscreen && mode == FULLSCREEN_FULL ? 0.f : 255.f;
}
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv(), true);
@@ -1624,7 +1751,7 @@ CWindow* CCompositor::getWindowByRegex(const std::string& regexp) {
}
for (auto& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped || w->m_bHidden)
if (!w->m_bIsMapped || w->isHidden())
continue;
switch (mode) {
@@ -1662,25 +1789,6 @@ CWindow* CCompositor::getWindowByRegex(const std::string& regexp) {
return nullptr;
}
wl_event_source* hyprCtlTickSource = nullptr;
int hyprCtlTick(void* data) {
HyprCtl::tickHyprCtl(); // so that we dont get that race condition multithread bullshit
wl_event_source_timer_update(hyprCtlTickSource, 16); // tick it 60/s, should be enough.
return 0;
}
void CCompositor::startHyprCtlTick() {
if (hyprCtlTickSource)
return;
hyprCtlTickSource = wl_event_loop_add_timer(m_sWLEventLoop, hyprCtlTick, nullptr);
wl_event_source_timer_update(hyprCtlTickSource, 16);
}
void CCompositor::warpCursorTo(const Vector2D& pos) {
// warpCursorTo should only be used for warps that
@@ -1692,6 +1800,10 @@ void CCompositor::warpCursorTo(const Vector2D& pos) {
return;
wlr_cursor_warp(m_sWLRCursor, m_sSeat.mouse->mouse, pos.x, pos.y);
const auto PMONITORNEW = getMonitorFromVector(pos);
if (PMONITORNEW != m_pLastMonitor)
m_pLastMonitor = PMONITORNEW;
}
SLayerSurface* CCompositor::getLayerSurfaceFromWlr(wlr_layer_surface_v1* pLS) {
@@ -1767,8 +1879,40 @@ Vector2D CCompositor::parseWindowVectorArgsRelative(const std::string& args, con
void CCompositor::forceReportSizesToWindowsOnWorkspace(const int& wid) {
for (auto& w : m_vWindows) {
if (w->m_iWorkspaceID == wid && w->m_bIsMapped && !w->m_bHidden) {
if (w->m_iWorkspaceID == wid && w->m_bIsMapped && !w->isHidden()) {
g_pXWaylandManager->setWindowSize(w.get(), w->m_vRealSize.vec(), true);
}
}
}
bool CCompositor::cursorOnReservedArea() {
const auto PMONITOR = getMonitorFromCursor();
const auto XY1 = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
const auto XY2 = PMONITOR->vecPosition + PMONITOR->vecSize - PMONITOR->vecReservedBottomRight;
const auto CURSORPOS = g_pInputManager->getMouseCoordsInternal();
return !VECINRECT(CURSORPOS, XY1.x, XY1.y, XY2.x, XY2.y);
}
CWorkspace* CCompositor::createNewWorkspace(const int& id, const int& monid, const std::string& name) {
const auto NAME = name == "" ? std::to_string(id) : name;
auto monID = monid;
// check if bound
if (const auto PMONITOR = g_pConfigManager->getBoundMonitorForWS(NAME); PMONITOR) {
monID = PMONITOR->ID;
}
const auto PWORKSPACE = m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(monID, NAME, id == SPECIAL_WORKSPACE_ID)).get();
// We are required to set the name here immediately
if (id != SPECIAL_WORKSPACE_ID)
wlr_ext_workspace_handle_v1_set_name(PWORKSPACE->m_pWlrHandle, NAME.c_str());
PWORKSPACE->m_iID = id;
PWORKSPACE->m_iMonitorID = monID;
return PWORKSPACE;
}

View File

@@ -69,6 +69,7 @@ public:
wlr_output_power_manager_v1* m_sWLROutputPowerMgr;
wlr_input_method_manager_v2* m_sWLRIMEMgr;
wlr_text_input_manager_v3* m_sWLRTextInputMgr;
wlr_xdg_activation_v1* m_sWLRActivation;
// ------------------------------------------------- //
@@ -138,8 +139,8 @@ public:
void cleanupFadingOut(const int& monid);
CWindow* getWindowInDirection(CWindow*, char);
void deactivateAllWLRWorkspaces(wlr_ext_workspace_handle_v1* exclude = nullptr);
CWindow* getNextWindowOnWorkspace(CWindow*);
CWindow* getPrevWindowOnWorkspace(CWindow*);
CWindow* getNextWindowOnWorkspace(CWindow*, bool focusableOnly = false);
CWindow* getPrevWindowOnWorkspace(CWindow*, bool focusableOnly = false);
int getNextAvailableNamedWorkspace();
bool isPointOnAnyMonitor(const Vector2D&);
CWindow* getConstraintWindow(SMouse*);
@@ -164,12 +165,11 @@ public:
void closeWindow(CWindow*);
Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&);
void forceReportSizesToWindowsOnWorkspace(const int&);
bool cursorOnReservedArea();
CWorkspace* createNewWorkspace(const int&, const int&, const std::string& name = ""); // will be deleted next frame if left empty and unfocused!
std::string explicitConfigPath;
void startHyprCtlTick();
private:
void initAllSignals();
void setRandomSplash();

View File

@@ -97,8 +97,7 @@ void CWindow::updateWindowDecos() {
pid_t CWindow::getPID() {
pid_t PID = -1;
if (!m_bIsX11) {
const auto CLIENT = wl_resource_get_client(m_uSurface.xdg->resource);
wl_client_get_credentials(CLIENT, &PID, nullptr, nullptr);
wl_client_get_credentials(wl_resource_get_client(m_uSurface.xdg->resource), &PID, nullptr, nullptr);
} else {
PID = m_uSurface.xwayland->pid;
}
@@ -212,8 +211,7 @@ void CWindow::moveToWorkspace(int workspaceID) {
if (m_iWorkspaceID != workspaceID) {
m_iWorkspaceID = workspaceID;
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
if (PWORKSPACE) {
if (const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID); PWORKSPACE) {
g_pEventManager->postEvent(SHyprIPCEvent{"movewindow", getFormat("%x,%s", this, PWORKSPACE->m_szName.c_str())});
}
}
@@ -228,10 +226,13 @@ CWindow* CWindow::X11TransientFor() {
auto PPARENT = g_pCompositor->getWindowFromSurface(m_uSurface.xwayland->parent->surface);
while (PPARENT->m_uSurface.xwayland->parent) {
while (g_pCompositor->windowValidMapped(PPARENT) && PPARENT->m_uSurface.xwayland->parent) {
PPARENT = g_pCompositor->getWindowFromSurface(PPARENT->m_uSurface.xwayland->parent->surface);
}
if (!g_pCompositor->windowValidMapped(PPARENT))
return nullptr;
return PPARENT;
}
@@ -243,3 +244,20 @@ void CWindow::removeDecorationByType(eDecorationType type) {
updateWindowDecos();
}
void CWindow::onUnmap() {
if (g_pCompositor->m_pLastWindow == this)
g_pCompositor->m_pLastWindow = nullptr;
}
void CWindow::setHidden(bool hidden) {
m_bHidden = hidden;
if (hidden) {
onUnmap();
}
}
bool CWindow::isHidden() {
return m_bHidden;
}

View File

@@ -14,6 +14,7 @@ struct SWindowSpecialRenderData {
// set by the layout
bool rounding = true;
bool border = true;
bool decorate = true;
};
struct SWindowAdditionalConfigData {
@@ -22,6 +23,10 @@ struct SWindowAdditionalConfigData {
bool forceNoBlur = false;
bool forceOpaque = false;
bool forceAllowsInput = false;
bool forceNoAnims = false;
bool forceNoBorder = false;
bool forceNoShadow = false;
bool windowDanceCompat = false;
};
class CWindow {
@@ -116,8 +121,8 @@ public:
Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in
Vector2D m_vOriginalClosedSize; // drawing the closing animations
// For hidden windows and stuff
bool m_bHidden = false;
// For pinned (sticky) windows
bool m_bPinned = false;
// for proper cycling. While cycling we can't just move the pointers, so we need to keep track of the last cycled window.
CWindow* m_pLastCycledWindow = nullptr;
@@ -142,6 +147,9 @@ public:
// animated tint
CAnimatedVariable m_fDimPercent;
// swallowing
CWindow* m_pSwallowed = nullptr;
// for toplevel monitor events
uint64_t m_iLastToplevelMonitorID = -1;
uint64_t m_iLastSurfaceMonitorID = -1;
@@ -164,4 +172,12 @@ public:
void updateSurfaceOutputs();
void moveToWorkspace(int);
CWindow* X11TransientFor();
void onUnmap();
void setHidden(bool hidden);
bool isHidden();
private:
// For hidden windows and stuff
bool m_bHidden = false;
};

View File

@@ -57,6 +57,10 @@ void CConfigManager::setDefaultVars() {
configValues["misc:always_follow_on_dnd"].intValue = 1;
configValues["misc:layers_hog_keyboard_focus"].intValue = 1;
configValues["misc:animate_manual_resizes"].intValue = 0;
configValues["misc:disable_autoreload"].intValue = 0;
configValues["misc:enable_swallow"].intValue = 0;
configValues["misc:swallow_regex"].strValue = STRVAL_EMPTY;
configValues["misc:focus_on_activate"].intValue = 0;
configValues["debug:int"].intValue = 0;
configValues["debug:log_damage"].intValue = 0;
@@ -65,7 +69,7 @@ void CConfigManager::setDefaultVars() {
configValues["debug:disable_logs"].intValue = 0;
configValues["debug:disable_time"].intValue = 1;
configValues["decoration:rounding"].intValue = 1;
configValues["decoration:rounding"].intValue = 0;
configValues["decoration:blur"].intValue = 1;
configValues["decoration:blur_size"].intValue = 8;
configValues["decoration:blur_passes"].intValue = 1;
@@ -80,7 +84,7 @@ void CConfigManager::setDefaultVars() {
configValues["decoration:shadow_range"].intValue = 4;
configValues["decoration:shadow_render_power"].intValue = 3;
configValues["decoration:shadow_ignore_window"].intValue = 1;
configValues["decoration:shadow_offset"].strValue = "0 0";
configValues["decoration:shadow_offset"].vecValue = Vector2D();
configValues["decoration:col.shadow"].intValue = 0xee1a1a1a;
configValues["decoration:col.shadow_inactive"].intValue = INT_MAX;
configValues["decoration:dim_inactive"].intValue = 0;
@@ -122,6 +126,7 @@ void CConfigManager::setDefaultVars() {
configValues["animations:workspaces"].intValue = 1;
configValues["input:sensitivity"].floatValue = 0.f;
configValues["input:accel_profile"].strValue = STRVAL_EMPTY;
configValues["input:kb_file"].strValue = STRVAL_EMPTY;
configValues["input:kb_layout"].strValue = "us";
configValues["input:kb_variant"].strValue = STRVAL_EMPTY;
@@ -134,14 +139,19 @@ void CConfigManager::setDefaultVars() {
configValues["input:numlock_by_default"].intValue = 0;
configValues["input:force_no_accel"].intValue = 0;
configValues["input:float_switch_override_focus"].intValue = 1;
configValues["input:left_handed"].intValue = 0;
configValues["input:scroll_method"].strValue = STRVAL_EMPTY;
configValues["input:touchpad:natural_scroll"].intValue = 0;
configValues["input:touchpad:disable_while_typing"].intValue = 1;
configValues["input:touchpad:clickfinger_behavior"].intValue = 0;
configValues["input:touchpad:middle_button_emulation"].intValue = 0;
configValues["input:touchpad:tap-to-click"].intValue = 1;
configValues["input:touchpad:drag_lock"].intValue = 0;
configValues["input:touchpad:scroll_factor"].floatValue = 1.f;
configValues["input:touchdevice:transform"].intValue = 0;
configValues["input:touchdevice:output"].strValue = STRVAL_EMPTY;
configValues["binds:pass_mouse_when_bound"].intValue = 1;
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;
@@ -152,6 +162,7 @@ void CConfigManager::setDefaultVars() {
configValues["gestures:workspace_swipe_invert"].intValue = 1;
configValues["gestures:workspace_swipe_min_speed_to_force"].intValue = 30;
configValues["gestures:workspace_swipe_cancel_ratio"].floatValue = 0.5f;
configValues["gestures:workspace_swipe_create_new"].intValue = 1;
configValues["input:follow_mouse"].intValue = 1;
@@ -162,6 +173,7 @@ void CConfigManager::setDeviceDefaultVars(const std::string& dev) {
auto& cfgValues = deviceConfigs[dev];
cfgValues["sensitivity"].floatValue = 0.f;
cfgValues["accel_profile"].strValue = STRVAL_EMPTY;
cfgValues["kb_file"].strValue = STRVAL_EMPTY;
cfgValues["kb_layout"].strValue = "us";
cfgValues["kb_variant"].strValue = STRVAL_EMPTY;
@@ -177,6 +189,11 @@ void CConfigManager::setDeviceDefaultVars(const std::string& dev) {
cfgValues["middle_button_emulation"].intValue = 0;
cfgValues["tap-to-click"].intValue = 1;
cfgValues["drag_lock"].intValue = 0;
cfgValues["left_handed"].intValue = 0;
cfgValues["scroll_method"].strValue = STRVAL_EMPTY;
cfgValues["touch_transform"].intValue = 0;
cfgValues["touch_output"].strValue = STRVAL_EMPTY;
cfgValues["enabled"].intValue = 1; // only for mice / touchpads
}
void CConfigManager::setDefaultAnimationVars() {
@@ -291,12 +308,37 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s
CONFIGENTRY->set = true;
if (CONFIGENTRY->intValue != -1) {
if (CONFIGENTRY->intValue != -INT64_MAX) {
try {
if (VALUE.find("0x") == 0) {
// Values with 0x are hex
const auto VALUEWITHOUTHEX = VALUE.substr(2);
CONFIGENTRY->intValue = stol(VALUEWITHOUTHEX, nullptr, 16);
} else if (VALUE.find("rgba(") == 0 && VALUE.find(")") == VALUE.length() - 1) {
const auto VALUEWITHOUTFUNC = VALUE.substr(5, VALUE.length() - 6);
if (removeBeginEndSpacesTabs(VALUEWITHOUTFUNC).length() != 8) {
Debug::log(WARN, "invalid length %i for rgba", VALUEWITHOUTFUNC.length());
parseError = "rgba() expects length of 8 characters (4 bytes)";
return;
}
const auto RGBA = std::stol(VALUEWITHOUTFUNC, nullptr, 16);
// now we need to RGBA -> ARGB. The config holds ARGB only.
CONFIGENTRY->intValue = (RGBA >> 8) + 0x1000000 * (RGBA & 0xFF);
} else if (VALUE.find("rgb(") == 0 && VALUE.find(")") == VALUE.length() - 1) {
const auto VALUEWITHOUTFUNC = VALUE.substr(4, VALUE.length() - 5);
if (removeBeginEndSpacesTabs(VALUEWITHOUTFUNC).length() != 6) {
Debug::log(WARN, "invalid length %i for rgb", VALUEWITHOUTFUNC.length());
parseError = "rgb() expects length of 6 characters (3 bytes)";
return;
}
const auto RGB = std::stol(VALUEWITHOUTFUNC, nullptr, 16);
CONFIGENTRY->intValue = RGB + 0xFF000000; // 0xFF for opaque
} else if (VALUE.find("true") == 0 || VALUE.find("on") == 0 || VALUE.find("yes") == 0) {
CONFIGENTRY->intValue = 1;
} else if (VALUE.find("false") == 0 || VALUE.find("off") == 0 || VALUE.find("no") == 0) {
@@ -308,7 +350,7 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
}
} else if (CONFIGENTRY->floatValue != -1) {
} else if (CONFIGENTRY->floatValue != -__FLT_MAX__) {
try {
CONFIGENTRY->floatValue = stof(VALUE);
} catch (...) {
@@ -322,6 +364,23 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
}
} else if (CONFIGENTRY->vecValue != Vector2D(-__FLT_MAX__, -__FLT_MAX__)) {
try {
if (const auto SPACEPOS = VALUE.find(' '); SPACEPOS != std::string::npos) {
const auto X = VALUE.substr(0, SPACEPOS);
const auto Y = VALUE.substr(SPACEPOS + 1);
if (isNumber(X, true) && isNumber(Y, true)) {
CONFIGENTRY->vecValue = Vector2D(std::stof(X), std::stof(Y));
}
} else {
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
}
} catch (...) {
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
}
}
}
@@ -353,6 +412,11 @@ void CConfigManager::handleRawExec(const std::string& command, const std::string
if (child == 0) {
// run in child
grandchild = fork();
sigset_t set;
sigemptyset(&set);
sigprocmask(SIG_SETMASK, &set, NULL);
if (grandchild == 0) {
// run in grandchild
close(socket[0]);
@@ -385,35 +449,15 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
// get the monitor config
SMonitorRule newrule;
std::string curitem = "";
const auto ARGS = CVarList(args);
std::string argZ = args;
newrule.name = ARGS[0];
auto nextItem = [&]() {
auto idx = argZ.find_first_of(',');
if (idx != std::string::npos) {
curitem = argZ.substr(0, idx);
argZ = argZ.substr(idx + 1);
} else {
curitem = argZ;
argZ = "";
}
};
nextItem();
newrule.name = curitem;
nextItem();
if (curitem == "disable" || curitem == "disabled" || curitem == "addreserved" || curitem == "transform") {
if (curitem == "disable" || curitem == "disabled")
if (ARGS[1] == "disable" || ARGS[1] == "disabled" || ARGS[1] == "addreserved" || ARGS[1] == "transform") {
if (ARGS[1] == "disable" || ARGS[1] == "disabled")
newrule.disabled = true;
else if (curitem == "transform") {
nextItem();
wl_output_transform transform = (wl_output_transform)std::stoi(curitem);
else if (ARGS[1] == "transform") {
wl_output_transform transform = (wl_output_transform)std::stoi(ARGS[2]);
// overwrite if exists
for (auto& r : m_dMonitorRules) {
@@ -424,22 +468,14 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
}
return;
} else if (curitem == "addreserved") {
nextItem();
} else if (ARGS[1] == "addreserved") {
int top = std::stoi(ARGS[2]);
int top = std::stoi(curitem);
int bottom = std::stoi(ARGS[3]);
nextItem();
int left = std::stoi(ARGS[4]);
int bottom = std::stoi(curitem);
nextItem();
int left = std::stoi(curitem);
nextItem();
int right = std::stoi(curitem);
int right = std::stoi(ARGS[5]);
m_mAdditionalReservedAreas[newrule.name] = {top, bottom, left, right};
@@ -457,23 +493,25 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
return;
}
if (curitem.find("pref") == 0) {
if (ARGS[1].find("pref") == 0) {
newrule.resolution = Vector2D();
} else if (ARGS[1].find("highrr") == 0) {
newrule.resolution = Vector2D(-1,-1);
} else if (ARGS[1].find("highres") == 0) {
newrule.resolution = Vector2D(-1,-2);
} else {
newrule.resolution.x = stoi(curitem.substr(0, curitem.find_first_of('x')));
newrule.resolution.y = stoi(curitem.substr(curitem.find_first_of('x') + 1, curitem.find_first_of('@')));
newrule.resolution.x = stoi(ARGS[1].substr(0, ARGS[1].find_first_of('x')));
newrule.resolution.y = stoi(ARGS[1].substr(ARGS[1].find_first_of('x') + 1, ARGS[1].find_first_of('@')));
if (curitem.contains("@"))
newrule.refreshRate = stof(curitem.substr(curitem.find_first_of('@') + 1));
if (ARGS[1].contains("@"))
newrule.refreshRate = stof(ARGS[1].substr(ARGS[1].find_first_of('@') + 1));
}
nextItem();
if (curitem.find("auto") == 0) {
if (ARGS[2].find("auto") == 0) {
newrule.offset = Vector2D(-1, -1);
} else {
newrule.offset.x = stoi(curitem.substr(0, curitem.find_first_of('x')));
newrule.offset.y = stoi(curitem.substr(curitem.find_first_of('x') + 1));
newrule.offset.x = stoi(ARGS[2].substr(0, ARGS[2].find_first_of('x')));
newrule.offset.y = stoi(ARGS[2].substr(ARGS[2].find_first_of('x') + 1));
if (newrule.offset.x < 0 || newrule.offset.y < 0) {
parseError = "invalid offset. Offset cannot be negative.";
@@ -481,24 +519,31 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
}
}
nextItem();
newrule.scale = stof(curitem);
newrule.scale = stof(ARGS[3]);
if (newrule.scale < 0.25f) {
parseError = "not a valid scale.";
newrule.scale = 1;
}
nextItem();
int argno = 4;
if (curitem != "") {
// warning for old cfg
Debug::log(ERR, "Error in parsing rule for %s, possibly old config!", newrule.name.c_str());
parseError = "Error in setting monitor rule. Are you using the old syntax? Confront the wiki.";
while (ARGS[argno] != "") {
if (ARGS[argno] == "mirror") {
newrule.mirrorOf = ARGS[argno + 1];
argno++;
} else if (ARGS[argno] == "bitdepth") {
newrule.enable10bit = ARGS[argno + 1] == "10";
argno++;
} else {
Debug::log(ERR, "Config error: invalid monitor syntax");
parseError = "invalid syntax at \"" + ARGS[argno] + "\"";
return;
}
argno++;
}
if (std::find_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }) != m_dMonitorRules.end())
m_dMonitorRules.erase(std::remove_if(m_dMonitorRules.begin(), m_dMonitorRules.end(), [&](const auto& other) { return other.name == newrule.name; }));
@@ -506,44 +551,27 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
}
void CConfigManager::handleBezier(const std::string& command, const std::string& args) {
std::string curitem = "";
const auto ARGS = CVarList(args);
std::string argZ = args;
std::string bezierName = ARGS[0];
auto nextItem = [&]() {
auto idx = argZ.find_first_of(',');
if (idx != std::string::npos) {
curitem = argZ.substr(0, idx);
argZ = argZ.substr(idx + 1);
} else {
curitem = argZ;
argZ = "";
}
};
nextItem();
std::string bezierName = curitem;
nextItem();
if (curitem == "")
if (ARGS[1] == "")
parseError = "too few arguments";
float p1x = std::stof(curitem);
nextItem();
if (curitem == "")
float p1x = std::stof(ARGS[1]);
if (ARGS[2] == "")
parseError = "too few arguments";
float p1y = std::stof(curitem);
nextItem();
if (curitem == "")
float p1y = std::stof(ARGS[2]);
if (ARGS[3] == "")
parseError = "too few arguments";
float p2x = std::stof(curitem);
nextItem();
if (curitem == "")
float p2x = std::stof(ARGS[3]);
if (ARGS[4] == "")
parseError = "too few arguments";
float p2y = std::stof(curitem);
nextItem();
if (curitem != "")
float p2y = std::stof(ARGS[4]);
if (ARGS[5] != "")
parseError = "too many arguments";
g_pAnimationManager->addBezierWithName(bezierName, Vector2D(p1x, p1y), Vector2D(p2x, p2y));
@@ -561,28 +589,12 @@ void CConfigManager::setAnimForChildren(SAnimationPropertyConfig *const ANIM) {
};
void CConfigManager::handleAnimation(const std::string& command, const std::string& args) {
std::string curitem = "";
std::string argZ = args;
auto nextItem = [&]() {
auto idx = argZ.find_first_of(',');
if (idx != std::string::npos) {
curitem = argZ.substr(0, idx);
argZ = argZ.substr(idx + 1);
} else {
curitem = argZ;
argZ = "";
}
};
nextItem();
const auto ARGS = CVarList(args);
// Master on/off
// anim name
const auto ANIMNAME = curitem;
const auto ANIMNAME = ARGS[0];
const auto PANIM = animationConfig.find(ANIMNAME);
@@ -594,20 +606,16 @@ void CConfigManager::handleAnimation(const std::string& command, const std::stri
PANIM->second.overriden = true;
PANIM->second.pValues = &PANIM->second;
nextItem();
// on/off
PANIM->second.internalEnabled = curitem == "1";
PANIM->second.internalEnabled = ARGS[1] == "1";
if (curitem != "0" && curitem != "1") {
if (ARGS[1] != "0" && ARGS[1] != "1") {
parseError = "invalid animation on/off state";
}
nextItem();
// speed
if (isNumber(curitem, true)) {
PANIM->second.internalSpeed = std::stof(curitem);
if (isNumber(ARGS[2], true)) {
PANIM->second.internalSpeed = std::stof(ARGS[2]);
if (PANIM->second.internalSpeed <= 0) {
parseError = "invalid speed";
@@ -618,23 +626,19 @@ void CConfigManager::handleAnimation(const std::string& command, const std::stri
parseError = "invalid speed";
}
nextItem();
// curve
PANIM->second.internalBezier = curitem;
PANIM->second.internalBezier = ARGS[3];
if (!g_pAnimationManager->bezierExists(curitem)) {
if (!g_pAnimationManager->bezierExists(ARGS[3])) {
parseError = "no such bezier";
PANIM->second.internalBezier = "default";
}
nextItem();
// style
PANIM->second.internalStyle = curitem;
PANIM->second.internalStyle = ARGS[4];
if (curitem != "") {
const auto ERR = g_pAnimationManager->styleValidInConfigVar(ANIMNAME, curitem);
if (ARGS[4] != "") {
const auto ERR = g_pAnimationManager->styleValidInConfigVar(ANIMNAME, ARGS[4]);
if (ERR != "")
parseError = ERR;
@@ -652,15 +656,18 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
bool locked = false;
bool release = false;
bool repeat = false;
const auto ARGS = command.substr(4);
bool mouse = false;
const auto BINDARGS = command.substr(4);
for (auto& arg : ARGS) {
for (auto& arg : BINDARGS) {
if (arg == 'l') {
locked = true;
} else if (arg == 'r') {
release = true;
} else if (arg == 'e') {
repeat = true;
} else if (arg == 'm') {
mouse = true;
} else {
parseError = "bind: invalid flag";
return;
@@ -672,19 +679,35 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
return;
}
auto valueCopy = value;
if (mouse && (repeat || release || locked)) {
parseError = "flag m is exclusive";
return;
}
const auto MOD = g_pKeybindManager->stringToModMask(valueCopy.substr(0, valueCopy.find_first_of(",")));
const auto MODSTR = valueCopy.substr(0, valueCopy.find_first_of(","));
valueCopy = valueCopy.substr(valueCopy.find_first_of(",") + 1);
const auto ARGS = CVarList(value, 4);
const auto KEY = valueCopy.substr(0, valueCopy.find_first_of(","));
valueCopy = valueCopy.substr(valueCopy.find_first_of(",") + 1);
if ((ARGS.size() < 3 && !mouse) || (ARGS.size() < 3 && mouse)) {
parseError = "bind: too few args";
return;
} else if ((ARGS.size() > 4 && !mouse) || (ARGS.size() > 3 && mouse)) {
parseError = "bind: too many args";
return;
}
const auto HANDLER = valueCopy.substr(0, valueCopy.find_first_of(","));
valueCopy = valueCopy.substr(valueCopy.find_first_of(",") + 1);
const auto MOD = g_pKeybindManager->stringToModMask(ARGS[0]);
const auto MODSTR = ARGS[0];
const auto COMMAND = valueCopy;
const auto KEY = ARGS[1];
auto HANDLER = ARGS[2];
const auto COMMAND = mouse ? HANDLER : ARGS[3];
if (mouse)
HANDLER = "mouse";
// to lower
std::transform(HANDLER.begin(), HANDLER.end(), HANDLER.begin(), ::tolower);
const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find(HANDLER);
@@ -707,27 +730,51 @@ 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});
g_pKeybindManager->addKeybind(SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse});
else
g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat});
g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse});
}
}
void CConfigManager::handleUnbind(const std::string& command, const std::string& value) {
auto valueCopy = value;
const auto ARGS = CVarList(value);
const auto MOD = g_pKeybindManager->stringToModMask(valueCopy.substr(0, valueCopy.find_first_of(",")));
valueCopy = valueCopy.substr(valueCopy.find_first_of(",") + 1);
const auto MOD = g_pKeybindManager->stringToModMask(ARGS[0]);
const auto KEY = valueCopy;
const auto KEY = ARGS[1];
g_pKeybindManager->removeKeybind(MOD, KEY);
}
bool windowRuleValid(const std::string& RULE) {
return !(RULE != "float"
&& RULE != "tile"
&& RULE.find("opacity") != 0
&& RULE.find("move") != 0
&& RULE.find("size") != 0
&& RULE.find("minsize") != 0
&& RULE.find("maxsize") != 0
&& RULE.find("pseudo") != 0
&& RULE.find("monitor") != 0
&& RULE != "nofocus"
&& RULE != "noblur"
&& RULE != "noshadow"
&& RULE != "noborder"
&& RULE != "center"
&& RULE != "opaque"
&& RULE != "forceinput"
&& RULE != "fullscreen"
&& RULE != "pin"
&& RULE != "noanim"
&& RULE != "windowdance"
&& RULE.find("animation") != 0
&& RULE.find("rounding") != 0
&& RULE.find("workspace") != 0);
}
void CConfigManager::handleWindowRule(const std::string& command, const std::string& value) {
const auto RULE = value.substr(0, value.find_first_of(","));
const auto VALUE = value.substr(value.find_first_of(",") + 1);
const auto RULE = removeBeginEndSpacesTabs(value.substr(0, value.find_first_of(",")));
const auto VALUE = removeBeginEndSpacesTabs(value.substr(value.find_first_of(",") + 1));
// check rule and value
if (RULE == "" || VALUE == "") {
@@ -735,34 +782,84 @@ void CConfigManager::handleWindowRule(const std::string& command, const std::str
}
// verify we support a rule
if (RULE != "float"
&& RULE != "tile"
&& RULE.find("opacity") != 0
&& RULE.find("move") != 0
&& RULE.find("size") != 0
&& RULE.find("pseudo") != 0
&& RULE.find("monitor") != 0
&& RULE != "nofocus"
&& RULE != "noblur"
&& RULE != "center"
&& RULE != "opaque"
&& RULE != "forceinput"
&& RULE != "fullscreen"
&& RULE.find("animation") != 0
&& RULE.find("rounding") != 0
&& RULE.find("workspace") != 0) {
if (!windowRuleValid(RULE)) {
Debug::log(ERR, "Invalid rule found: %s", RULE.c_str());
parseError = "Invalid rule found: " + RULE;
return;
}
m_dWindowRules.push_back({RULE, VALUE});
}
void CConfigManager::handleWindowRuleV2(const std::string& command, const std::string& value) {
const auto RULE = value.substr(0, value.find_first_of(","));
const auto VALUE = value.substr(value.find_first_of(",") + 1);
if (!windowRuleValid(RULE)) {
Debug::log(ERR, "Invalid rulev2 found: %s", RULE.c_str());
parseError = "Invalid rulev2 found: " + RULE;
return;
}
// now we estract shit from the value
SWindowRule rule;
rule.v2 = true;
rule.szRule = RULE;
rule.szValue = VALUE;
const auto TITLEPOS = VALUE.find("title:");
const auto CLASSPOS = VALUE.find("class:");
const auto X11POS = VALUE.find("xwayland:");
const auto FLOATPOS = VALUE.find("floating:");
if (TITLEPOS == std::string::npos && CLASSPOS == std::string::npos && X11POS == std::string::npos && FLOATPOS == std::string::npos) {
Debug::log(ERR, "Invalid rulev2 syntax: %s", VALUE.c_str());
parseError = "Invalid rulev2 syntax: " + VALUE;
return;
}
auto extract = [&](size_t pos) -> std::string {
std::string result;
result = VALUE.substr(pos);
size_t min = 999999;
if (TITLEPOS > pos && TITLEPOS < min) min = TITLEPOS;
if (CLASSPOS > pos && CLASSPOS < min) min = CLASSPOS;
if (X11POS > pos && X11POS < min) min = X11POS;
if (FLOATPOS > pos && FLOATPOS < min) min = FLOATPOS;
result = result.substr(0, min - pos);
result = removeBeginEndSpacesTabs(result);
if (result.back() == ',')
result.pop_back();
return result;
};
if (CLASSPOS != std::string::npos) {
rule.szClass = extract(CLASSPOS + 6);
}
if (TITLEPOS != std::string::npos) {
rule.szTitle = extract(TITLEPOS + 6);
}
if (X11POS != std::string::npos) {
rule.bX11 = extract(X11POS + 9) == "1" ? 1 : 0;
}
if (FLOATPOS != std::string::npos) {
rule.bFloating = extract(FLOATPOS + 9) == "1" ? 1 : 0;
}
m_dWindowRules.push_back(rule);
}
void CConfigManager::handleBlurLS(const std::string& command, const std::string& value) {
if (value.find("remove,") == 0) {
const auto TOREMOVE = value.substr(7);
const auto TOREMOVE = removeBeginEndSpacesTabs(value.substr(7));
m_dBlurLSNamespaces.erase(std::remove(m_dBlurLSNamespaces.begin(), m_dBlurLSNamespaces.end(), TOREMOVE));
return;
}
@@ -771,13 +868,11 @@ void CConfigManager::handleBlurLS(const std::string& command, const std::string&
}
void CConfigManager::handleDefaultWorkspace(const std::string& command, const std::string& value) {
const auto DISPLAY = value.substr(0, value.find_first_of(','));
const auto WORKSPACE = value.substr(value.find_first_of(',') + 1);
const auto ARGS = CVarList(value);
for (auto& mr : m_dMonitorRules) {
if (mr.name == DISPLAY) {
mr.defaultWorkspace = WORKSPACE;
if (mr.name == ARGS[0]) {
mr.defaultWorkspace = ARGS[1];
break;
}
}
@@ -844,6 +939,19 @@ void CConfigManager::handleSource(const std::string& command, const std::string&
}
}
void CConfigManager::handleBindWS(const std::string& command, const std::string& value) {
const auto ARGS = CVarList(value);
const auto FOUND = std::find_if(boundWorkspaces.begin(), boundWorkspaces.end(), [&](const auto& other) { return other.first == ARGS[0]; });
if (FOUND != boundWorkspaces.end()) {
FOUND->second = ARGS[1];
return;
}
boundWorkspaces.push_back({ARGS[0], ARGS[1]});
}
std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::string& VALUE, bool dynamic) {
if (dynamic) {
parseError = "";
@@ -866,11 +974,13 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
else if (COMMAND == "unbind") handleUnbind(COMMAND, VALUE);
else if (COMMAND == "workspace") handleDefaultWorkspace(COMMAND, VALUE);
else if (COMMAND == "windowrule") handleWindowRule(COMMAND, VALUE);
else if (COMMAND == "windowrulev2") handleWindowRuleV2(COMMAND, VALUE);
else if (COMMAND == "bezier") handleBezier(COMMAND, VALUE);
else if (COMMAND == "animation") handleAnimation(COMMAND, VALUE);
else if (COMMAND == "source") handleSource(COMMAND, VALUE);
else if (COMMAND == "submap") handleSubmap(COMMAND, VALUE);
else if (COMMAND == "blurls") handleBlurLS(COMMAND, VALUE);
else if (COMMAND == "wsbind") handleBindWS(COMMAND, VALUE);
else
configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE);
@@ -910,13 +1020,26 @@ void CConfigManager::applyUserDefinedVars(std::string& line, const size_t equals
void CConfigManager::parseLine(std::string& line) {
// first check if its not a comment
const auto COMMENTSTART = line.find_first_of('#');
if (COMMENTSTART == 0)
if (line[0] == '#')
return;
// now, cut the comment off
if (COMMENTSTART != std::string::npos)
line = line.substr(0, COMMENTSTART);
// now, cut the comment off. ## is an escape.
for (long unsigned int i = 1; i < line.length(); ++i) {
if (line[i] == '#') {
if (i + 1 < line.length() && line[i + 1] != '#') {
line = line.substr(0, i);
break; // no need to parse more
}
i++;
}
}
size_t startPos = 0;
while ((startPos = line.find("##", startPos)) != std::string::npos) {
line.replace(startPos, 2, "#");
startPos++;
}
// remove shit at the beginning
while (line[0] == ' ' || line[0] == '\t') {
@@ -982,6 +1105,7 @@ void CConfigManager::loadConfigLoadVars() {
configDynamicVars.clear();
deviceConfigs.clear();
m_dBlurLSNamespaces.clear();
boundWorkspaces.clear();
setDefaultAnimationVars(); // reset anims
// paths
@@ -1066,7 +1190,8 @@ void CConfigManager::loadConfigLoadVars() {
// Update the keyboard layout to the cfg'd one if this is not the first launch
if (!isFirstLaunch) {
g_pInputManager->setKeyboardLayout();
g_pInputManager->setMouseConfigs();
g_pInputManager->setPointerConfigs();
g_pInputManager->setTouchDeviceConfigs();
}
// Calculate the internal vars
@@ -1096,6 +1221,7 @@ void CConfigManager::loadConfigLoadVars() {
// check
ensureDPMS();
ensureVRR();
}
// Update window border colors
@@ -1104,13 +1230,13 @@ void CConfigManager::loadConfigLoadVars() {
// update layout
g_pLayoutManager->switchToLayout(configValues["general:layout"].strValue);
for (auto& m : g_pCompositor->m_vMonitors) {
// mark blur dirty
for (auto& m : g_pCompositor->m_vMonitors)
g_pHyprOpenGL->markBlurDirtyForMonitor(m.get());
// Force the compositor to fully re-render all monitors
for (auto& m : g_pCompositor->m_vMonitors)
m->forceFullFrames = 2;
}
// Reset no monitor reload
m_bNoMonitorReload = false;
@@ -1236,11 +1362,11 @@ void CConfigManager::setString(std::string v, std::string val) {
configValues[v].strValue = val;
}
SMonitorRule CConfigManager::getMonitorRuleFor(std::string name) {
SMonitorRule CConfigManager::getMonitorRuleFor(std::string name, std::string displayName) {
SMonitorRule* found = nullptr;
for (auto& r : m_dMonitorRules) {
if (r.name == name) {
if (r.name == name || (r.name.find("desc:") == 0 && (r.name.substr(5) == displayName || r.name.substr(5) == removeBeginEndSpacesTabs(displayName.substr(0, displayName.find_first_of('(')))))) {
found = &r;
break;
}
@@ -1279,6 +1405,7 @@ std::vector<SWindowRule> CConfigManager::getMatchingRules(CWindow* pWindow) {
for (auto& rule : m_dWindowRules) {
// check if we have a matching rule
if (!rule.v2) {
try {
if (rule.szValue.find("title:") == 0) {
// we have a title rule.
@@ -1296,6 +1423,36 @@ std::vector<SWindowRule> CConfigManager::getMatchingRules(CWindow* pWindow) {
Debug::log(ERR, "Regex error at %s", rule.szValue.c_str());
continue;
}
} else {
try {
if (rule.szClass != "") {
std::regex RULECHECK(rule.szClass);
if (!std::regex_search(appidclass, RULECHECK))
continue;
}
if (rule.szTitle != "") {
std::regex RULECHECK(rule.szTitle);
if (!std::regex_search(title, RULECHECK))
continue;
}
if (rule.bX11 != -1) {
if (pWindow->m_bIsX11 != rule.bX11)
continue;
}
if (rule.bFloating != -1) {
if (pWindow->m_bIsFloating != rule.bFloating)
continue;
}
} catch (...) {
Debug::log(ERR, "Regex error at %s", rule.szValue.c_str());
continue;
}
}
// applies. Read the rule and behave accordingly
Debug::log(LOG, "Window rule %s -> %s matched %x [%s]", rule.szRule.c_str(), rule.szValue.c_str(), pWindow, pWindow->m_szTitle.c_str());
@@ -1320,7 +1477,8 @@ void CConfigManager::dispatchExecOnce() {
// set input, fixes some certain issues
g_pInputManager->setKeyboardLayout();
g_pInputManager->setMouseConfigs();
g_pInputManager->setPointerConfigs();
g_pInputManager->setTouchDeviceConfigs();
// set ws names again
for (auto& ws : g_pCompositor->m_vWorkspaces) {
@@ -1333,11 +1491,17 @@ void CConfigManager::performMonitorReload() {
bool overAgain = false;
for (auto& m : g_pCompositor->m_vRealMonitors) {
auto rule = getMonitorRuleFor(m->szName);
auto rule = getMonitorRuleFor(m->szName, m->output->description ? m->output->description : "");
// ensure mirror
m->setMirror(rule.mirrorOf);
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) {
overAgain = true;
break;
}
g_pHyprRenderer->arrangeLayersForMonitor(m->ID);
}
if (overAgain)
@@ -1380,7 +1544,7 @@ bool CConfigManager::shouldBlurLS(const std::string& ns) {
void CConfigManager::ensureDPMS() {
for (auto& rm : g_pCompositor->m_vRealMonitors) {
auto rule = getMonitorRuleFor(rm->szName);
auto rule = getMonitorRuleFor(rm->szName, rm->output->description ? rm->output->description : "");
if (rule.disabled == rm->m_bEnabled) {
rm->m_pThisWrap = &rm;
@@ -1389,6 +1553,49 @@ void CConfigManager::ensureDPMS() {
}
}
void CConfigManager::ensureVRR(CMonitor* pMonitor) {
static auto *const PNOVRR = &getConfigValuePtr("misc:no_vfr")->intValue;
auto ensureVRRForDisplay = [&](CMonitor* m) -> void {
if (!*PNOVRR && !m->vrrActive) {
// Adaptive sync (VRR)
wlr_output_enable_adaptive_sync(m->output, 1);
if (!wlr_output_test(m->output)) {
Debug::log(LOG, "Pending output %s does not accept VRR.", m->output->name);
wlr_output_enable_adaptive_sync(m->output, 0);
}
if (!wlr_output_commit(m->output)) {
Debug::log(ERR, "Couldn't commit output %s in ensureVRR -> true", m->output->name);
}
m->vrrActive = true;
Debug::log(LOG, "VRR ensured on %s -> true", m->output->name);
} else if (*PNOVRR && m->vrrActive) {
wlr_output_enable_adaptive_sync(m->output, 0);
if (!wlr_output_commit(m->output)) {
Debug::log(ERR, "Couldn't commit output %s in ensureVRR -> false", m->output->name);
}
m->vrrActive = false;
Debug::log(LOG, "VRR ensured on %s -> false", m->output->name);
}
};
if (pMonitor) {
ensureVRRForDisplay(pMonitor);
return;
}
for (auto& m : g_pCompositor->m_vMonitors) {
ensureVRRForDisplay(m.get());
}
}
SAnimationPropertyConfig* CConfigManager::getAnimationPropertyConfig(const std::string& name) {
return &animationConfig[name];
}
@@ -1397,3 +1604,15 @@ void CConfigManager::addParseError(const std::string& err) {
if (parseError == "")
parseError = err;
}
CMonitor* CConfigManager::getBoundMonitorForWS(std::string wsname) {
for (auto&[ws, mon] : boundWorkspaces) {
const auto WSNAME = ws.find("name:") == 0 ? ws.substr(5) : ws;
if (WSNAME == wsname) {
return g_pCompositor->getMonitorFromString(mon);
}
}
return nullptr;
}

View File

@@ -20,9 +20,10 @@
#define CREATEANIMCFG(name, parent) animationConfig[name] = {false, "", "", 0.f, -1, &animationConfig["global"], &animationConfig[parent]}
struct SConfigValue {
int64_t intValue = -1;
float floatValue = -1;
int64_t intValue = -INT64_MAX;
float floatValue = -__FLT_MAX__;
std::string strValue = "";
Vector2D vecValue = Vector2D(-__FLT_MAX__, -__FLT_MAX__);
bool set = false; // used for device configs
};
@@ -36,6 +37,8 @@ struct SMonitorRule {
std::string defaultWorkspace = "";
bool disabled = false;
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
std::string mirrorOf = "";
bool enable10bit = false;
};
struct SMonitorAdditionalReservedArea {
@@ -48,6 +51,12 @@ struct SMonitorAdditionalReservedArea {
struct SWindowRule {
std::string szRule;
std::string szValue;
bool v2 = false;
std::string szTitle;
std::string szClass;
int bX11 = -1; // -1 means "ANY"
int bFloating = -1;
};
struct SAnimationPropertyConfig {
@@ -62,6 +71,48 @@ struct SAnimationPropertyConfig {
SAnimationPropertyConfig* pParentAnimation = nullptr;
};
class CVarList {
public:
CVarList(const std::string& in, long unsigned int lastArgNo = 0) {
std::string curitem = "";
std::string argZ = in;
auto nextItem = [&]() {
auto idx = lastArgNo != 0 && m_vArgs.size() >= lastArgNo - 1 ? std::string::npos : argZ.find_first_of(',');
if (idx != std::string::npos) {
curitem = argZ.substr(0, idx);
argZ = argZ.substr(idx + 1);
} else {
curitem = argZ;
argZ = STRVAL_EMPTY;
}
};
nextItem();
while (curitem != STRVAL_EMPTY) {
m_vArgs.push_back(removeBeginEndSpacesTabs(curitem));
nextItem();
}
};
~CVarList() = default;
int size() const {
return m_vArgs.size();
}
std::string operator[](const long unsigned int& idx) const {
if (idx >= m_vArgs.size())
return "";
return m_vArgs[idx];
}
private:
std::vector<std::string> m_vArgs;
};
class CConfigManager {
public:
CConfigManager();
@@ -85,7 +136,9 @@ public:
SConfigValue* getConfigValuePtr(std::string);
SConfigValue* getConfigValuePtrSafe(std::string);
SMonitorRule getMonitorRuleFor(std::string);
SMonitorRule getMonitorRuleFor(std::string, std::string displayName = "");
CMonitor* getBoundMonitorForWS(std::string);
std::vector<SWindowRule> getMatchingRules(CWindow*);
@@ -99,6 +152,7 @@ public:
bool m_bForceReload = false;
bool m_bNoMonitorReload = false;
void ensureDPMS();
void ensureVRR(CMonitor* pMonitor = nullptr);
std::string parseKeyword(const std::string&, const std::string&, bool dynamic = false);
@@ -123,6 +177,8 @@ private:
std::string m_szCurrentSubmap = ""; // For storing the current keybind submap
std::vector<std::pair<std::string, std::string>> boundWorkspaces;
bool isFirstLaunch = true; // For exec-once
std::deque<SMonitorRule> m_dMonitorRules;
@@ -151,12 +207,14 @@ private:
void handleBind(const std::string&, const std::string&);
void handleUnbind(const std::string&, const std::string&);
void handleWindowRule(const std::string&, const std::string&);
void handleWindowRuleV2(const std::string&, const std::string&);
void handleDefaultWorkspace(const std::string&, const std::string&);
void handleBezier(const std::string&, const std::string&);
void handleAnimation(const std::string&, const std::string&);
void handleSource(const std::string&, const std::string&);
void handleSubmap(const std::string&, const std::string&);
void handleBlurLS(const std::string&, const std::string&);
void handleBindWS(const std::string&, const std::string&);
};
inline std::unique_ptr<CConfigManager> g_pConfigManager;

View File

@@ -9,19 +9,28 @@ PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hypr.conf AND EDIT IT,
OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
########################################################################################
#
# Please note not all available settings / options are set here.
# For a full list, see the wiki (basic and advanced configuring)
# For a full list, see the wiki
#
autogenerated=1 # remove this line to get rid of the warning on top.
autogenerated = 1 # remove this line to remove the warning
# See https://wiki.hyprland.org/Configuring/Monitors/
monitor=,preferred,auto,1
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
# Execute your favorite apps at launch
# exec-once = waybar & hyprpaper & firefox
# Source a file (multi-file configs)
# source = ~/.config/hypr/myColors.conf
# For all categories, see https://wiki.hyprland.org/Configuring/Variables/
input {
kb_file=
kb_layout=
kb_layout = us
kb_variant =
kb_model =
kb_options =
@@ -37,89 +46,123 @@ input {
}
general {
main_mod=SUPER
# See https://wiki.hyprland.org/Configuring/Variables/ for more
gaps_in = 5
gaps_out = 20
border_size = 2
col.active_border=0x66ee1111
col.inactive_border=0x66333333
col.active_border = rgba(1affffee)
col.inactive_border = rgba(595959aa)
apply_sens_to_raw=0 # whether to apply the sensitivity to raw input (e.g. used by games where you aim using your mouse)
damage_tracking=full # leave it on full unless you hate your GPU and want to make it suffer
layout = dwindle
}
decoration {
# See https://wiki.hyprland.org/Configuring/Variables/ for more
rounding = 10
blur=1
blur_size=3 # minimum 1
blur_passes=1 # minimum 1
blur_new_optimizations=1
blur = yes
blur_size = 3
blur_passes = 1
blur_new_optimizations = on
drop_shadow = yes
shadow_range = 4
shadow_render_power = 3
col.shadow = rgba(1a1a1aee)
}
animations {
enabled=1
animation=windows,1,7,default
enabled = yes
# Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
bezier = myBezier, 0.05, 0.9, 0.1, 1.05
animation = windows, 1, 7, myBezier
animation = windowsOut, 1, 7, default, popin 80%
animation = border, 1, 10, default
animation=fade,1,10,default
animation = fade, 1, 7, default
animation = workspaces, 1, 6, default
}
dwindle {
pseudotile=0 # enable pseudotiling on dwindle
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
pseudotile = yes # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
preserve_split = yes # you probably want this
}
master {
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
new_is_master = true
}
gestures {
workspace_swipe=no
# See https://wiki.hyprland.org/Configuring/Variables/ for more
workspace_swipe = off
}
# example window rules
# for windows named/classed as abc and xyz
#windowrule=move 69 420,abc
#windowrule=size 420 69,abc
#windowrule=tile,xyz
#windowrule=float,abc
#windowrule=pseudo,abc
#windowrule=monitor 0,xyz
# Example per-device config
# See https://wiki.hyprland.org/Configuring/Keywords/#executing for more
device:epic mouse V1 {
sensitivity = -0.5
}
# example binds
bind=SUPER,Q,exec,kitty
bind=SUPER,RETURN,exec,alacritty
bind=SUPER,C,killactive,
bind=SUPER,M,exit,
bind=SUPER,E,exec,dolphin
bind=SUPER,V,togglefloating,
bind=SUPER,R,exec,wofi --show drun -o DP-3
bind=SUPER,P,pseudo,
# Example windowrule v1
# windowrule = float, ^(kitty)$
# Example windowrule v2
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
bind=SUPER,left,movefocus,l
bind=SUPER,right,movefocus,r
bind=SUPER,up,movefocus,u
bind=SUPER,down,movefocus,d
bind=SUPER,1,workspace,1
bind=SUPER,2,workspace,2
bind=SUPER,3,workspace,3
bind=SUPER,4,workspace,4
bind=SUPER,5,workspace,5
bind=SUPER,6,workspace,6
bind=SUPER,7,workspace,7
bind=SUPER,8,workspace,8
bind=SUPER,9,workspace,9
bind=SUPER,0,workspace,10
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
$mainMod = SUPER
bind=ALT,1,movetoworkspace,1
bind=ALT,2,movetoworkspace,2
bind=ALT,3,movetoworkspace,3
bind=ALT,4,movetoworkspace,4
bind=ALT,5,movetoworkspace,5
bind=ALT,6,movetoworkspace,6
bind=ALT,7,movetoworkspace,7
bind=ALT,8,movetoworkspace,8
bind=ALT,9,movetoworkspace,9
bind=ALT,0,movetoworkspace,10
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
bind = $mainMod, Q, exec, kitty
bind = $mainMod, C, killactive,
bind = $mainMod, M, exit,
bind = $mainMod, E, exec, dolphin
bind = $mainMod, V, togglefloating,
bind = $mainMod, R, exec, wofi --show drun
bind = $mainMod, P, pseudo, # dwindle
bind = $mainMod, J, togglesplit, # dwindle
bind=SUPER,mouse_down,workspace,e+1
bind=SUPER,mouse_up,workspace,e-1
# Move focus with mainMod + arrow keys
bind = $mainMod, left, movefocus, l
bind = $mainMod, right, movefocus, r
bind = $mainMod, up, movefocus, u
bind = $mainMod, down, movefocus, d
# Switch workspaces with mainMod + [0-9]
bind = $mainMod, 1, workspace, 1
bind = $mainMod, 2, workspace, 2
bind = $mainMod, 3, workspace, 3
bind = $mainMod, 4, workspace, 4
bind = $mainMod, 5, workspace, 5
bind = $mainMod, 6, workspace, 6
bind = $mainMod, 7, workspace, 7
bind = $mainMod, 8, workspace, 8
bind = $mainMod, 9, workspace, 9
bind = $mainMod, 0, workspace, 10
# Move active window to a workspace with mainMod + SHIFT + [0-9]
bind = $mainMod SHIFT, 1, movetoworkspace, 1
bind = $mainMod SHIFT, 2, movetoworkspace, 2
bind = $mainMod SHIFT, 3, movetoworkspace, 3
bind = $mainMod SHIFT, 4, movetoworkspace, 4
bind = $mainMod SHIFT, 5, movetoworkspace, 5
bind = $mainMod SHIFT, 6, movetoworkspace, 6
bind = $mainMod SHIFT, 7, movetoworkspace, 7
bind = $mainMod SHIFT, 8, movetoworkspace, 8
bind = $mainMod SHIFT, 9, movetoworkspace, 9
bind = $mainMod SHIFT, 0, movetoworkspace, 10
# Scroll through existing workspaces with mainMod + scroll
bind = $mainMod, mouse_down, workspace, e+1
bind = $mainMod, mouse_up, workspace, e-1
# Move/resize windows with mainMod + LMB/RMB and dragging
bindm = $mainMod, mouse:272, movewindow
bindm = $mainMod, mouse:273, resizewindow
)#";

View File

@@ -23,6 +23,7 @@ std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) {
R"#({
"id": %i,
"name": "%s",
"description": "%s",
"width": %i,
"height": %i,
"refreshRate": %f,
@@ -35,10 +36,12 @@ R"#({
"reserved": [%i, %i, %i, %i],
"scale": %.2f,
"transform": %i,
"focused": %s
"focused": %s,
"dpmsStatus": %s
},)#",
m->ID,
escapeJSONStrings(m->szName).c_str(),
escapeJSONStrings(m->output->description ? m->output->description : "").c_str(),
(int)m->vecPixelSize.x, (int)m->vecPixelSize.y,
m->refreshRate,
(int)m->vecPosition.x, (int)m->vecPosition.y,
@@ -46,7 +49,8 @@ R"#({
(int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y,
m->scale,
(int)m->transform,
(m.get() == g_pCompositor->m_pLastMonitor ? "true" : "false")
(m.get() == g_pCompositor->m_pLastMonitor ? "true" : "false"),
(m->dpmsStatus ? "true" : "false")
);
}
@@ -56,8 +60,8 @@ R"#({
result += "]";
} else {
for (auto& m : g_pCompositor->m_vMonitors) {
result += getFormat("Monitor %s (ID %i):\n\t%ix%i@%f at %ix%i\n\tactive workspace: %i (%s)\n\treserved: %i %i %i %i\n\tscale: %.2f\n\ttransform: %i\n\tfocused: %s\n\n",
m->szName.c_str(), m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName.c_str(), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"));
result += getFormat("Monitor %s (ID %i):\n\t%ix%i@%f at %ix%i\n\tdescription: %s\n\tactive workspace: %i (%s)\n\treserved: %i %i %i %i\n\tscale: %.2f\n\ttransform: %i\n\tfocused: %s\n\tdpmsStatus: %i\n\n",
m->szName.c_str(), m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, (m->output->description ? m->output->description : ""), m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName.c_str(), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus);
}
}
@@ -85,18 +89,24 @@ R"#({
"class": "%s",
"title": "%s",
"pid": %i,
"xwayland": %s
"xwayland": %s,
"pinned": %s,
"fullscreen": %s,
"fullscreenMode": %i
},)#",
w.get(),
(int)w->m_vRealPosition.vec().x, (int)w->m_vRealPosition.vec().y,
(int)w->m_vRealSize.vec().x, (int)w->m_vRealSize.vec().y,
(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, escapeJSONStrings(w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID))).c_str(),
((int)w->m_bIsFloating == 1 ? "true" : "false"),
w->m_iMonitorID,
escapeJSONStrings(g_pXWaylandManager->getAppIDClass(w.get())).c_str(),
escapeJSONStrings(g_pXWaylandManager->getTitle(w.get())).c_str(),
w->getPID(),
((int)w->m_bIsX11 == 1 ? "true" : "false")
((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) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_efFullscreenMode : 0) : 0)
);
}
}
@@ -109,8 +119,8 @@ R"#({
} else {
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsMapped) {
result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\txwayland: %i\n\n",
w.get(), w->m_szTitle.c_str(), (int)w->m_vRealPosition.vec().x, (int)w->m_vRealPosition.vec().y, (int)w->m_vRealSize.vec().x, (int)w->m_vRealSize.vec().y, w->m_iWorkspaceID, (w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)).c_str()), (int)w->m_bIsFloating, w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w.get()).c_str(), g_pXWaylandManager->getTitle(w.get()).c_str(), w->getPID(), (int)w->m_bIsX11);
result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\txwayland: %i\n\tpinned: %i\n\tfullscreen: %i\n\tfullscreenmode: %i\n\n",
w.get(), w->m_szTitle.c_str(), (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 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)).c_str()), (int)w->m_bIsFloating, w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w.get()).c_str(), g_pXWaylandManager->getTitle(w.get()).c_str(), w->getPID(), (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));
}
}
@@ -124,19 +134,25 @@ std::string workspacesRequest(HyprCtl::eHyprCtlOutputFormat format) {
result += "[";
for (auto& w : g_pCompositor->m_vWorkspaces) {
const auto PLASTW = w->getLastFocusedWindow();
result += getFormat(
R"#({
"id": %i,
"name": "%s",
"monitor": "%s",
"windows": %i,
"hasfullscreen": %s
"hasfullscreen": %s,
"lastwindow": "0x%x",
"lastwindowtitle": "%s"
},)#",
w->m_iID,
escapeJSONStrings(w->m_szName).c_str(),
escapeJSONStrings(g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName).c_str(),
g_pCompositor->getWindowsOnWorkspace(w->m_iID),
((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false")
((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false"),
PLASTW,
PLASTW ? escapeJSONStrings(PLASTW->m_szTitle).c_str() : ""
);
}
@@ -146,8 +162,9 @@ R"#({
result += "]";
} else {
for (auto& w : g_pCompositor->m_vWorkspaces) {
result += getFormat("workspace ID %i (%s) on monitor %s:\n\twindows: %i\n\thasfullscreen: %i\n\n",
w->m_iID, w->m_szName.c_str(), g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName.c_str(), g_pCompositor->getWindowsOnWorkspace(w->m_iID), (int)w->m_bHasFullscreenWindow);
const auto PLASTW = w->getLastFocusedWindow();
result += getFormat("workspace ID %i (%s) on monitor %s:\n\twindows: %i\n\thasfullscreen: %i\n\tlastwindow: 0x%x\n\tlastwindowtitle: %s\n\n",
w->m_iID, w->m_szName.c_str(), g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName.c_str(), g_pCompositor->getWindowsOnWorkspace(w->m_iID), (int)w->m_bHasFullscreenWindow, PLASTW, PLASTW ? PLASTW->m_szTitle.c_str() : "");
}
}
return result;
@@ -287,10 +304,12 @@ std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
result += getFormat(
R"#( {
"address": "0x%x",
"name": "%s"
"name": "%s",
"defaultSpeed": %f
},)#",
&m,
escapeJSONStrings(m.mouse->name).c_str()
escapeJSONStrings(m.mouse->name).c_str(),
wlr_input_device_is_libinput(m.mouse) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(m.mouse)) : 0.f
);
}
@@ -370,6 +389,41 @@ R"#( {
);
}
// remove trailing comma
result.pop_back();
result += "\n],\n";
result += "\"touch\": [\n";
for (auto& d : g_pInputManager->m_lTouchDevices) {
result += getFormat(
R"#( {
"address": "0x%x",
"name": "%s"
},)#",
&d,
d.pWlrDevice ? d.pWlrDevice->name : ""
);
}
// remove trailing comma
if (result[result.size() - 1] == ',')
result.pop_back();
result += "\n],\n";
result += "\"switches\": [\n";
for (auto& d : g_pInputManager->m_lSwitches) {
result += getFormat(
R"#( {
"address": "0x%x",
"name": "%s"
},)#",
&d,
d.pWlrDevice ? d.pWlrDevice->name : ""
);
}
// remove trailing comma
if (result[result.size() - 1] == ',')
result.pop_back();
@@ -381,7 +435,7 @@ R"#( {
result += "mice:\n";
for (auto& m : g_pInputManager->m_lMice) {
result += getFormat("\tMouse at %x:\n\t\t%s\n", &m, m.mouse->name);
result += getFormat("\tMouse at %x:\n\t\t%s\n\t\t\tdefault speed: %f\n", &m, m.mouse->name, (wlr_input_device_is_libinput(m.mouse) ? libinput_device_config_accel_get_default_speed((libinput_device*)wlr_libinput_get_device_handle(m.mouse)) : 0.f));
}
result += "\n\nKeyboards:\n";
@@ -404,6 +458,18 @@ R"#( {
for (auto& d : g_pInputManager->m_lTabletTools) {
result += getFormat("\tTablet Tool at %x (belongs to %x)\n", &d, d.wlrTabletTool ? d.wlrTabletTool->data : 0);
}
result += "\n\nTouch:\n";
for (auto& d : g_pInputManager->m_lTouchDevices) {
result += getFormat("\tTouch Device at %x:\n\t\t%s\n", &d, d.pWlrDevice ? d.pWlrDevice->name : "");
}
result += "\n\nSwitches:\n";
for (auto& d : g_pInputManager->m_lSwitches) {
result += getFormat("\tSwitch Device at %x:\n\t\t%s\n", &d, d.pWlrDevice ? d.pWlrDevice->name : "");
}
}
return result;
@@ -433,7 +499,7 @@ std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) {
R"#({
"branch": "%s",
"commit": "%s",
"dirty": %s
"dirty": %s,
"commit_message": "%s",
"flags": [)#", GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE).c_str());
@@ -495,7 +561,8 @@ std::string dispatchKeyword(std::string in) {
if (COMMAND.contains("input") || COMMAND.contains("device:")) {
g_pInputManager->setKeyboardLayout(); // update kb layout
g_pInputManager->setMouseConfigs(); // update mouse cfgs
g_pInputManager->setPointerConfigs(); // update mouse cfgs
g_pInputManager->setTouchDeviceConfigs(); // update touch device cfgs
}
if (COMMAND.contains("general:layout"))
@@ -519,6 +586,8 @@ std::string reloadRequest(std::string request) {
g_pConfigManager->m_bNoMonitorReload = true;
}
g_pConfigManager->tick();
return "ok";
}
@@ -532,6 +601,23 @@ std::string splashRequest() {
return g_pCompositor->m_szCurrentSplash;
}
std::string cursorPosRequest(HyprCtl::eHyprCtlOutputFormat format) {
const auto CURSORPOS = g_pInputManager->getMouseCoordsInternal().floor();
if (format == HyprCtl::FORMAT_NORMAL) {
return getFormat("%i, %i", (int)CURSORPOS.x, (int)CURSORPOS.y);
} else {
return getFormat(R"#(
{
"x": %i,
"y": %i
}
)#", (int)CURSORPOS.x, (int)CURSORPOS.y);
}
return "error";
}
std::string getReply(std::string);
std::string dispatchBatch(std::string request) {
@@ -698,6 +784,8 @@ std::string getReply(std::string request) {
return devicesRequest(format);
else if (request == "splash")
return splashRequest();
else if (request == "cursorpos")
return cursorPosRequest(format);
else if (request.find("dispatch") == 0)
return dispatchRequest(request);
else if (request.find("keyword") == 0)
@@ -712,9 +800,21 @@ std::string getReply(std::string request) {
return "unknown request";
}
void HyprCtl::tickHyprCtl() {
if (!requestMade)
return;
int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP)
return 0;
sockaddr_in clientAddress;
socklen_t clientSize = sizeof(clientAddress);
const auto ACCEPTEDCONNECTION = accept(HyprCtl::iSocketFD, (sockaddr*)&clientAddress, &clientSize);
char readBuffer[1024];
auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024);
readBuffer[messageSize == 1024 ? 1023 : messageSize] = '\0';
std::string request(readBuffer);
std::string reply = "";
@@ -725,44 +825,22 @@ void HyprCtl::tickHyprCtl() {
reply = "Err: " + std::string(e.what());
}
request = reply;
write(ACCEPTEDCONNECTION, reply.c_str(), reply.length());
requestMade = false;
requestReady = true;
close(ACCEPTEDCONNECTION);
if (g_pConfigManager->m_bWantsMonitorReload) {
g_pConfigManager->ensureDPMS();
}
}
std::string getRequestFromThread(std::string rq) {
while (HyprCtl::request != "" || HyprCtl::requestMade || HyprCtl::requestReady) {
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
HyprCtl::request = rq;
HyprCtl::requestMade = true;
while (!HyprCtl::requestReady) {
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
HyprCtl::requestReady = false;
HyprCtl::requestMade = false;
std::string toReturn = HyprCtl::request;
HyprCtl::request = "";
return toReturn;
return 0;
}
void HyprCtl::startHyprCtlSocket() {
tThread = std::thread([&]() {
const auto SOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
if (SOCKET < 0) {
iSocketFD = socket(AF_UNIX, SOCK_STREAM, 0);
if (iSocketFD < 0) {
Debug::log(ERR, "Couldn't start the Hyprland Socket. (1) IPC will not work.");
return;
}
@@ -773,40 +851,12 @@ void HyprCtl::startHyprCtlSocket() {
strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
bind(SOCKET, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS));
bind(iSocketFD, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS));
// 10 max queued.
listen(SOCKET, 10);
sockaddr_in clientAddress;
socklen_t clientSize = sizeof(clientAddress);
char readBuffer[1024] = {0};
listen(iSocketFD, 10);
Debug::log(LOG, "Hypr socket started at %s", socketPath.c_str());
while(1) {
const auto ACCEPTEDCONNECTION = accept(SOCKET, (sockaddr*)&clientAddress, &clientSize);
if (ACCEPTEDCONNECTION < 0) {
Debug::log(ERR, "Couldn't listen on the Hyprland Socket. (3) IPC will not work.");
break;
}
auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024);
readBuffer[messageSize == 1024 ? 1023 : messageSize] = '\0';
std::string request(readBuffer);
std::string reply = getRequestFromThread(request);
write(ACCEPTEDCONNECTION, reply.c_str(), reply.length());
close(ACCEPTEDCONNECTION);
}
close(SOCKET);
});
tThread.detach();
wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, iSocketFD, WL_EVENT_READABLE, hyprCtlFDTick, nullptr);
}

View File

@@ -6,7 +6,6 @@
namespace HyprCtl {
void startHyprCtlSocket();
void tickHyprCtl();
// very simple thread-safe request method
inline bool requestMade = false;
@@ -15,7 +14,9 @@ namespace HyprCtl {
inline std::ifstream requestStream;
inline std::thread tThread;
inline wl_event_source* hyprCtlTickSource = nullptr;
inline int iSocketFD = -1;
enum eHyprCtlOutputFormat {
FORMAT_NORMAL = 0,

View File

@@ -72,7 +72,7 @@ void Events::listener_newInput(wl_listener* listener, void* data) {
break;
case WLR_INPUT_DEVICE_TOUCH:
Debug::log(LOG, "Attached a touch device with name %s", DEVICE->name);
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, DEVICE);
g_pInputManager->newTouchDevice(DEVICE);
break;
case WLR_INPUT_DEVICE_TABLET_TOOL:
Debug::log(LOG, "Attached a tablet tool with name %s", DEVICE->name);
@@ -82,6 +82,10 @@ void Events::listener_newInput(wl_listener* listener, void* data) {
Debug::log(LOG, "Attached a tablet pad with name %s", DEVICE->name);
g_pInputManager->newTabletPad(DEVICE);
break;
case WLR_INPUT_DEVICE_SWITCH:
Debug::log(LOG, "Attached a switch device with name %s", DEVICE->name);
g_pInputManager->newSwitch(DEVICE);
break;
default:
Debug::log(WARN, "Unrecognized input device plugged in: %s", DEVICE->name);
break;
@@ -207,3 +211,15 @@ void Events::listener_touchEnd(wl_listener* listener, void* data) {
void Events::listener_touchUpdate(wl_listener* listener, void* data) {
g_pInputManager->onTouchMove((wlr_touch_motion_event*)data);
}
void Events::listener_touchFrame(wl_listener* listener, void* data) {
wlr_seat_touch_notify_frame(g_pCompositor->m_sSeat.seat);
}
void Events::listener_holdBegin(wl_listener* listener, void* data) {
g_pInputManager->onPointerHoldBegin((wlr_pointer_hold_begin_event*)data);
}
void Events::listener_holdEnd(wl_listener* listener, void* data) {
g_pInputManager->onPointerHoldEnd((wlr_pointer_hold_end_event*)data);
}

View File

@@ -42,6 +42,7 @@ namespace Events {
// Surface XDG (window)
LISTENER(newXDGSurface);
LISTENER(activateXDG);
// Window events
DYNLISTENFUNC(commitWindow);
@@ -87,7 +88,6 @@ namespace Events {
LISTENER(requestMouse);
LISTENER(requestSetSel);
LISTENER(requestSetPrimarySel);
DYNLISTENFUNC(activate);
// outputMgr
LISTENER(outputMgrApply);
@@ -152,4 +152,8 @@ namespace Events {
LISTENER(touchBegin);
LISTENER(touchEnd);
LISTENER(touchUpdate);
LISTENER(touchFrame);
LISTENER(holdBegin);
LISTENER(holdEnd);
};

View File

@@ -133,8 +133,9 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
if (layersurface->layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint)) { // don't focus if constrained
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
if (layersurface->layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint)) { // don't focus if constrained
g_pCompositor->focusSurface(layersurface->layerSurface->surface);
const auto LOCAL = g_pInputManager->getMouseCoordsInternal() - Vector2D(layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y);
@@ -151,6 +152,8 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
layersurface->alpha = 255.f;
layersurface->readyToDelete = false;
layersurface->fadingOut = false;
g_pEventManager->postEvent(SHyprIPCEvent{"openlayer", std::string(layersurface->layerSurface->_namespace ? layersurface->layerSurface->_namespace : "")});
}
void Events::listener_unmapLayerSurface(void* owner, void* data) {
@@ -158,7 +161,9 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
Debug::log(LOG, "LayerSurface %x unmapped", layersurface->layerSurface);
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID)) {
g_pEventManager->postEvent(SHyprIPCEvent{"closelayer", std::string(layersurface->layerSurface->_namespace ? layersurface->layerSurface->_namespace : "")});
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID) || g_pCompositor->m_bUnsafeState) {
Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring.");
g_pCompositor->addToFadingOutSafe(layersurface);
@@ -194,9 +199,30 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
// refocus if needed
if (layersurface->layerSurface->surface == g_pCompositor->m_pLastFocus) {
Vector2D surfaceCoords;
SLayerSurface* pFoundLayerSurface = nullptr;
wlr_surface* foundSurface = nullptr;
g_pCompositor->m_pLastFocus = nullptr;
// find LS-es to focus
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &surfaceCoords, &pFoundLayerSurface);
if (!foundSurface)
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface);
if (!foundSurface) {
// if there isn't any, focus the last window
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow;
g_pCompositor->focusWindow(nullptr);
g_pCompositor->focusWindow(PLASTWINDOW);
} else {
// otherwise, full refocus
g_pInputManager->refocus();
}
}
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};
g_pHyprRenderer->damageBox(&geomFixed);

View File

@@ -45,6 +45,7 @@ void Events::listener_requestSetSel(wl_listener* listener, void* data) {
}
void Events::listener_readyXWayland(wl_listener* listener, void* data) {
#ifndef NO_XWAYLAND
const auto XCBCONNECTION = xcb_connect(g_pXWaylandManager->m_sWLRXWayland->display_name, NULL);
const auto ERR = xcb_connection_has_error(XCBCONNECTION);
if (ERR) {
@@ -72,6 +73,7 @@ void Events::listener_readyXWayland(wl_listener* listener, void* data) {
}
xcb_disconnect(XCBCONNECTION);
#endif
}
void Events::listener_requestDrag(wl_listener* listener, void* data) {
@@ -124,6 +126,9 @@ void Events::listener_startDrag(wl_listener* listener, void* data) {
void Events::listener_destroyDrag(void* owner, void* data) {
Debug::log(LOG, "Drag destroyed.");
if (g_pInputManager->m_sDrag.drag && g_pInputManager->m_sDrag.dragIcon && g_pInputManager->m_sDrag.dragIcon->surface)
g_pHyprRenderer->damageBox(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_pInputManager->m_sDrag.drag = nullptr;
g_pInputManager->m_sDrag.dragIcon = nullptr;
g_pInputManager->m_sDrag.hyprListener_destroy.removeCallback();

View File

@@ -37,8 +37,6 @@ void Events::listener_change(wl_listener* listener, void* data) {
CONFIGHEAD->state.mode = m->output->current_mode;
CONFIGHEAD->state.x = m->vecPosition.x;
CONFIGHEAD->state.y = m->vecPosition.y;
wlr_output_set_custom_mode(m->output, m->vecPixelSize.x, m->vecPixelSize.y, (int)(round(m->refreshRate * 1000)));
}
wlr_output_manager_v1_set_configuration(g_pCompositor->m_sWLROutputMgr, CONFIG);
@@ -190,7 +188,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
}
// if we have no tracking or full tracking, invalidate the entire monitor
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0 || damageBlinkCleanup > 0) {
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0 || damageBlinkCleanup > 0 || PMONITOR->isMirror() /* why??? */) {
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x * 10, (int)PMONITOR->vecTransformedSize.y * 10); // wot?
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
@@ -224,6 +222,10 @@ void Events::listener_monitorFrame(void* owner, void* data) {
// potentially can save on resources.
g_pHyprOpenGL->begin(PMONITOR, &damage);
if (PMONITOR->isMirror()) {
g_pHyprOpenGL->renderMirrored();
} else {
g_pHyprOpenGL->clear(CColor(17, 17, 17, 255));
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
@@ -255,6 +257,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
wlr_output_render_software_cursors(PMONITOR->output, NULL);
wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
}
g_pHyprOpenGL->end();
@@ -272,10 +275,15 @@ void Events::listener_monitorFrame(void* owner, void* data) {
pixman_region32_union(&frameDamage, &frameDamage, &damage);
wlr_output_set_damage(PMONITOR->output, &frameDamage);
if (!PMONITOR->mirrors.empty())
g_pHyprRenderer->damageMirrorsWith(PMONITOR, &frameDamage);
pixman_region32_fini(&frameDamage);
pixman_region32_fini(&damage);
wlr_output_commit(PMONITOR->output);
if (!wlr_output_commit(PMONITOR->output))
return;
if (*PDAMAGEBLINK || *PNOVFR)
g_pCompositor->scheduleFrameForMonitor(PMONITOR);

View File

@@ -32,8 +32,8 @@ void addPopupGlobalCoords(void* pPopup, int* x, int* y) {
py -= curPopup->popup->base->current.geometry.y;
}
if (curPopup->pSurfaceTree && curPopup->pSurfaceTree->pSurface && !curPopup->parentPopup && !curPopup->parentWindow) {
const auto EXTENTSSURFACE = pixman_region32_extents(&curPopup->pSurfaceTree->pSurface->input_region);
if (curPopup->popup && !curPopup->parentPopup && !curPopup->parentWindow) {
const auto EXTENTSSURFACE = pixman_region32_extents(&curPopup->popup->base->surface->input_region);
px -= EXTENTSSURFACE->x1;
py -= EXTENTSSURFACE->y1;
}

View File

@@ -49,8 +49,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
static auto *const PINACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity")->floatValue;
static auto *const PACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:active_opacity")->floatValue;
static auto *const PDIMSTRENGTH = &g_pConfigManager->getConfigValuePtr("decoration:dim_strength")->floatValue;
static auto *const PSWALLOW = &g_pConfigManager->getConfigValuePtr("misc:enable_swallow")->intValue;
static auto *const PSWALLOWREGEX = &g_pConfigManager->getConfigValuePtr("misc:swallow_regex")->strValue;
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
const auto PWORKSPACE = PMONITOR->specialWorkspaceOpen ? g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
PWINDOW->m_iMonitorID = PMONITOR->ID;
PWINDOW->m_bMappedX11 = true;
@@ -112,6 +114,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
bool workspaceSilent = false;
bool requestsFullscreen = PWINDOW->m_bWantsInitialFullscreen || (!PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xdg->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL && PWINDOW->m_uSurface.xdg->toplevel->requested.fullscreen);
bool shouldFocus = true;
bool workspaceSpecial = false;
for (auto& r : WINDOWRULES) {
if (r.szRule.find("monitor") == 0) {
@@ -145,6 +148,9 @@ void Events::listener_mapWindow(void* owner, void* data) {
requestedWorkspace = WORKSPACERQ;
}
if (requestedWorkspace == PWORKSPACE->m_szName || requestedWorkspace == "name:" + PWORKSPACE->m_szName)
requestedWorkspace = "";
Debug::log(LOG, "Rule workspace matched by window %x, %s applied.", PWINDOW, r.szValue.c_str());
} else if (r.szRule.find("float") == 0) {
PWINDOW->m_bIsFloating = true;
@@ -156,12 +162,22 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_bNoFocus = true;
} else if (r.szRule == "noblur") {
PWINDOW->m_sAdditionalConfigData.forceNoBlur = true;
} else if (r.szRule == "noborder") {
PWINDOW->m_sAdditionalConfigData.forceNoBorder = true;
} else if (r.szRule == "noshadow") {
PWINDOW->m_sAdditionalConfigData.forceNoShadow = true;
} else if (r.szRule == "fullscreen") {
requestsFullscreen = true;
} else if (r.szRule == "opaque") {
PWINDOW->m_sAdditionalConfigData.forceOpaque = true;
} else if (r.szRule == "windowdance") {
PWINDOW->m_sAdditionalConfigData.windowDanceCompat = true;
} else if (r.szRule == "forceinput") {
PWINDOW->m_sAdditionalConfigData.forceAllowsInput = true;
} else if (r.szRule == "pin") {
PWINDOW->m_bPinned = true;
} else if (r.szRule == "noanim") {
PWINDOW->m_sAdditionalConfigData.forceNoAnims = true;
} else if (r.szRule.find("rounding") == 0) {
try {
PWINDOW->m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
@@ -188,6 +204,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
}
}
// disallow tiled pinned
if (PWINDOW->m_bPinned && !PWINDOW->m_bIsFloating)
PWINDOW->m_bPinned = false;
if (requestedWorkspace != "") {
// process requested workspace
if (requestedWorkspace.contains(' ')) {
@@ -195,17 +215,18 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (requestedWorkspace.contains("silent")) {
workspaceSilent = true;
shouldFocus = false;
}
requestedWorkspace = requestedWorkspace.substr(0, requestedWorkspace.find_first_of(' '));
}
if (!shouldFocus && requestedWorkspace == std::to_string(PMONITOR->activeWorkspace))
shouldFocus = true;
}
if (requestedWorkspace == "special") {
workspaceSpecial = true;
workspaceSilent = true;
}
}
if (!workspaceSilent) {
g_pKeybindManager->m_mDispatchers["workspace"](requestedWorkspace);
@@ -215,6 +236,44 @@ void Events::listener_mapWindow(void* owner, void* data) {
}
}
if (workspaceSilent) {
// get the workspace
auto PWORKSPACE = g_pCompositor->getWorkspaceByString(requestedWorkspace);
if (!PWORKSPACE) {
std::string workspaceName = "";
int workspaceID = 0;
if (requestedWorkspace.find("name:") == 0) {
workspaceName = requestedWorkspace.substr(5);
workspaceID = g_pCompositor->getNextAvailableNamedWorkspace();
} else if (workspaceSpecial) {
workspaceName = "";
workspaceID = SPECIAL_WORKSPACE_ID;
} else {
try {
workspaceID = std::stoi(requestedWorkspace);
} catch (...) {
workspaceID = -1;
Debug::log(ERR, "Invalid workspace requested in workspace silent rule!");
}
if (workspaceID < 1) {
workspaceID = -1; // means invalid
}
}
if (workspaceID != -1)
PWORKSPACE = g_pCompositor->createNewWorkspace(workspaceID, PWINDOW->m_iMonitorID, workspaceName);
}
if (PWORKSPACE) {
PWINDOW->m_iWorkspaceID = PWORKSPACE->m_iID;
PWINDOW->m_iMonitorID = PWORKSPACE->m_iMonitorID;
}
}
if (PWINDOW->m_bIsFloating) {
g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(PWINDOW);
PWINDOW->m_bCreatedOverFullscreen = true;
@@ -227,32 +286,80 @@ void Events::listener_mapWindow(void* owner, void* data) {
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(" "));
const auto SIZEYSTR = VALUE.substr(VALUE.find(" ") + 1);
const auto SIZEX = !SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stoi(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.x;
const auto SIZEY = !SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stoi(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.y;
const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(PWINDOW);
const auto SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, 20.0, PMONITOR->vecSize.x) : (!SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stoi(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x);
const auto SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, 20.0, PMONITOR->vecSize.y) : (!SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stoi(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y);
Debug::log(LOG, "Rule size, applying to window %x", PWINDOW);
PWINDOW->m_vRealSize = Vector2D(SIZEX, SIZEY);
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
PWINDOW->m_bHidden = false;
PWINDOW->setHidden(false);
} catch (...) {
Debug::log(LOG, "Rule size failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str());
}
} else if (r.szRule.find("minsize") == 0) {
try {
const auto VALUE = r.szRule.substr(r.szRule.find(" ") + 1);
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(" "));
const auto SIZEYSTR = VALUE.substr(VALUE.find(" ") + 1);
const auto SIZE = Vector2D(std::max((double)std::stoll(SIZEXSTR), PWINDOW->m_vRealSize.goalv().x), std::max((double)std::stoll(SIZEYSTR), PWINDOW->m_vRealSize.goalv().y));
PWINDOW->m_vRealSize = SIZE;
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
PWINDOW->setHidden(false);
} catch (...) {
Debug::log(LOG, "Rule minsize failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str());
}
} else if (r.szRule.find("maxsize") == 0) {
try {
const auto VALUE = r.szRule.substr(r.szRule.find(" ") + 1);
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(" "));
const auto SIZEYSTR = VALUE.substr(VALUE.find(" ") + 1);
const auto SIZE = Vector2D(std::min((double)std::stoll(SIZEXSTR), PWINDOW->m_vRealSize.goalv().x), std::min((double)std::stoll(SIZEYSTR), PWINDOW->m_vRealSize.goalv().y));
PWINDOW->m_vRealSize = SIZE;
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
PWINDOW->setHidden(false);
} catch (...) {
Debug::log(LOG, "Rule maxsize failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str());
}
} else if (r.szRule.find("move") == 0) {
try {
const auto VALUE = r.szRule.substr(r.szRule.find(" ") + 1);
const auto POSXSTR = VALUE.substr(0, VALUE.find(" "));
const auto POSYSTR = VALUE.substr(VALUE.find(" ") + 1);
const auto POSX = !POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stoi(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.x;
const auto POSY = !POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stoi(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.y;
int posX = 0;
int posY = 0;
if (POSXSTR.find("100%-") == 0) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
const auto POSXRAW = POSXSTR.substr(5);
posX = PMONITOR->vecSize.x - (!POSXRAW.contains('%') ? std::stoi(POSXRAW) : std::stoi(POSXRAW.substr(0, POSXRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.x);
} else {
posX = !POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stoi(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x;
}
if (POSYSTR.find("100%-") == 0) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
const auto POSYRAW = POSYSTR.substr(5);
posY = PMONITOR->vecSize.y - (!POSYRAW.contains('%') ? std::stoi(POSYRAW) : std::stoi(POSYRAW.substr(0, POSYRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.y);
} else {
posY = !POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stoi(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y;
}
Debug::log(LOG, "Rule move, applying to window %x", PWINDOW);
PWINDOW->m_vRealPosition = Vector2D(POSX, POSY) + PMONITOR->vecPosition;
PWINDOW->m_vRealPosition = Vector2D(posX, posY) + PMONITOR->vecPosition;
PWINDOW->m_bHidden = false;
PWINDOW->setHidden(false);
} catch (...) {
Debug::log(LOG, "Rule move failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str());
}
@@ -264,8 +371,9 @@ void Events::listener_mapWindow(void* owner, void* data) {
// set the pseudo size to the GOAL of our current size
// because the windows are animated on RealSize
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv();
}
else {
g_pCompositor->moveWindowToTop(PWINDOW);
} else {
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
// Set the pseudo size here too so that it doesnt end up being 0x0
@@ -280,7 +388,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_bX11ShouldntFocus = false;
}
if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus && PWINDOW->m_iX11Type != 2) {
if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus && PWINDOW->m_iX11Type != 2 && !workspaceSilent) {
g_pCompositor->focusWindow(PWINDOW);
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA);
PWINDOW->m_fDimPercent.setValueAndWarp(*PDIMSTRENGTH);
@@ -305,6 +413,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->hyprListener_activateX11.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_activate, &Events::listener_activateX11, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_configureX11.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_configure, &Events::listener_configureX11, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.set_title, &Events::listener_setTitleWindow, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_minimize, &Events::listener_requestMinimize, PWINDOW, "Xwayland Window Late");
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_maximize, &Events::listener_requestMaximize, PWINDOW, "Xwayland Window Late");
if (PWINDOW->m_iX11Type == 2)
PWINDOW->hyprListener_setGeometryX11U.initCallback(&PWINDOW->m_uSurface.xwayland->events.set_geometry, &Events::listener_unmanagedSetGeometry, PWINDOW, "XWayland Window Late");
@@ -318,24 +428,11 @@ void Events::listener_mapWindow(void* owner, void* data) {
const auto TIMER = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, setAnimToMove, PWINDOW);
wl_event_source_timer_update(TIMER, PWINDOW->m_vRealPosition.getDurationLeftMs() + 5);
if (workspaceSilent) {
// move the window
if (g_pCompositor->m_pLastWindow == PWINDOW) {
if (requestedWorkspace != "special")
g_pKeybindManager->m_mDispatchers["movetoworkspacesilent"](requestedWorkspace);
else
g_pKeybindManager->m_mDispatchers["movetoworkspace"]("special");
} else {
Debug::log(ERR, "Tried to set workspace silent rule to a nofocus window!");
}
}
if (requestsFullscreen) {
// fix fullscreen on requested (basically do a switcheroo)
if (PWORKSPACE->m_bHasFullscreenWindow) {
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PFULLWINDOW, FULLSCREEN_FULL, false);
g_pXWaylandManager->setWindowFullscreen(PFULLWINDOW, PFULLWINDOW->m_bIsFullscreen);
g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, FULLSCREEN_FULL);
}
PWINDOW->m_vRealPosition.warp();
@@ -363,6 +460,66 @@ void Events::listener_mapWindow(void* owner, void* data) {
g_pCompositor->focusWindow(nullptr);
}
// verify swallowing
if (*PSWALLOW) {
// don't swallow ourselves
std::regex rgx(*PSWALLOWREGEX);
if (!std::regex_match(g_pXWaylandManager->getAppIDClass(PWINDOW), rgx)) {
// check parent
int ppid = getPPIDof(PWINDOW->getPID());
int curppid = 0;
for (int i = 0; i < 5; ++i) {
curppid = getPPIDof(ppid);
if (curppid < 10) {
break;
}
ppid = curppid;
}
if (ppid) {
// get window by pid
std::vector<CWindow*> found;
CWindow* finalFound = nullptr;
for (auto& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped || w->isHidden())
continue;
if (w->getPID() == ppid) {
found.push_back(w.get());
}
}
if (found.size() > 1) {
for (auto& w : found) {
// try get the focus, otherwise we'll ignore to avoid swallowing incorrect windows
if (w == PFOCUSEDWINDOWPREV) {
finalFound = w;
break;
}
}
} else if (found.size() == 1) {
finalFound = found[0];
}
if (finalFound) {
// check if it's the window we want
if (std::regex_match(g_pXWaylandManager->getAppIDClass(finalFound), rgx)) {
// swallow
PWINDOW->m_pSwallowed = finalFound;
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(finalFound);
finalFound->setHidden(true);
}
}
}
}
}
Debug::log(LOG, "Map request dispatched, monitor %s, xywh: %f %f %f %f", PMONITOR->szName.c_str(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, PWINDOW->m_vRealSize.goalv().x, PWINDOW->m_vRealSize.goalv().y);
auto workspaceID = requestedWorkspace != "" ? requestedWorkspace : PWORKSPACE->m_szName;
@@ -393,16 +550,24 @@ void Events::listener_unmapWindow(void* owner, void* data) {
PWINDOW->hyprListener_configureX11.removeCallback();
PWINDOW->hyprListener_setTitleWindow.removeCallback();
PWINDOW->hyprListener_setGeometryX11U.removeCallback();
PWINDOW->hyprListener_requestMaximize.removeCallback();
PWINDOW->hyprListener_requestMinimize.removeCallback();
}
if (PWINDOW->m_bIsFullscreen) {
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, false);
g_pXWaylandManager->setWindowFullscreen(PWINDOW, PWINDOW->m_bIsFullscreen);
g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL);
}
// Allow the renderer to catch the last frame.
g_pHyprOpenGL->makeWindowSnapshot(PWINDOW);
// swallowing
if (PWINDOW->m_pSwallowed && g_pCompositor->windowExists(PWINDOW->m_pSwallowed)) {
PWINDOW->m_pSwallowed->setHidden(false);
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW->m_pSwallowed);
PWINDOW->m_pSwallowed = nullptr;
}
bool wasLastWindow = false;
if (PWINDOW == g_pCompositor->m_pLastWindow) {
@@ -426,13 +591,7 @@ void Events::listener_unmapWindow(void* owner, void* data) {
// refocus on a new window if needed
if (wasLastWindow) {
auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(PWINDOW->m_vRealPosition.goalv() + PWINDOW->m_vRealSize.goalv() / 2.f);
if (PWORKSPACE->m_bHasFullscreenWindow && ((!PWINDOWCANDIDATE || !PWINDOWCANDIDATE->m_bCreatedOverFullscreen) || !PWINDOW->m_bIsFloating))
PWINDOWCANDIDATE = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
if (!PWINDOWCANDIDATE || PWINDOW == PWINDOWCANDIDATE || !PWINDOWCANDIDATE->m_bIsMapped || PWINDOWCANDIDATE->m_bHidden || PWINDOWCANDIDATE->m_bX11ShouldntFocus || PWINDOWCANDIDATE->m_iX11Type == 2 || PWINDOWCANDIDATE->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID)
PWINDOWCANDIDATE = nullptr;
const auto PWINDOWCANDIDATE = g_pLayoutManager->getCurrentLayout()->getNextWindowCandidate(PWINDOW);
Debug::log(LOG, "On closed window, new focused candidate is %x", PWINDOWCANDIDATE);
@@ -441,11 +600,16 @@ void Events::listener_unmapWindow(void* owner, void* data) {
g_pInputManager->refocus();
else
g_pCompositor->focusWindow(PWINDOWCANDIDATE);
} else {
g_pInputManager->refocus();
}
} else {
Debug::log(LOG, "Unmapped was not focused, ignoring a refocus.");
}
// update lastwindow after focus
PWINDOW->onUnmap();
Debug::log(LOG, "Destroying the SubSurface tree of unmapped window %x", PWINDOW);
SubsurfaceTree::destroySurfaceTree(PWINDOW->m_pSurfaceTree);
@@ -475,12 +639,15 @@ void Events::listener_unmapWindow(void* owner, void* data) {
// recheck idle inhibitors
g_pInputManager->recheckIdleInhibitorStatus();
// force report all sizes (QT sometimes has an issue with this)
g_pCompositor->forceReportSizesToWindowsOnWorkspace(PWINDOW->m_iWorkspaceID);
}
void Events::listener_commitWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
if (!PWINDOW->m_bMappedX11 || PWINDOW->m_bHidden || (PWINDOW->m_bIsX11 && !PWINDOW->m_bMappedX11))
if (!PWINDOW->m_bMappedX11 || PWINDOW->isHidden() || (PWINDOW->m_bIsX11 && !PWINDOW->m_bMappedX11))
return;
g_pHyprRenderer->damageSurface(g_pXWaylandManager->getWindowSurface(PWINDOW), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y);
@@ -540,7 +707,7 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
return;
}
if (PWINDOW->m_bHidden)
if (PWINDOW->isHidden())
return;
if (!PWINDOW->m_bIsX11) {
@@ -551,26 +718,50 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
} else {
g_pCompositor->setWindowFullscreen(PWINDOW, !PWINDOW->m_bIsFullscreen, FULLSCREEN_FULL);
if (!PWINDOW->m_uSurface.xwayland->mapped)
return;
g_pCompositor->setWindowFullscreen(PWINDOW, PWINDOW->m_uSurface.xwayland->fullscreen, FULLSCREEN_FULL);
}
PWINDOW->updateToplevel();
Debug::log(LOG, "Window %x fullscreen to %i", PWINDOW, PWINDOW->m_bIsFullscreen);
g_pXWaylandManager->setWindowFullscreen(PWINDOW, PWINDOW->m_bIsFullscreen);
}
void Events::listener_activate(void* owner, void* data) {
// TODO
void Events::listener_activateXDG(wl_listener* listener, void* data) {
const auto E = (wlr_xdg_activation_v1_request_activate_event*)data;
static auto *const PFOCUSONACTIVATE = &g_pConfigManager->getConfigValuePtr("misc:focus_on_activate")->intValue;
Debug::log(LOG, "Activate request for surface at %x", E->surface);
if (!*PFOCUSONACTIVATE || !wlr_surface_is_xdg_surface(E->surface))
return;
const auto PWINDOW = g_pCompositor->getWindowFromSurface(E->surface);
if (!PWINDOW || PWINDOW == g_pCompositor->m_pLastWindow)
return;
g_pCompositor->focusWindow(PWINDOW);
Vector2D middle = PWINDOW->m_vRealPosition.goalv() + PWINDOW->m_vRealSize.goalv() / 2.f;
g_pCompositor->warpCursorTo(middle);
}
void Events::listener_activateX11(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
const auto PWINDOW = (CWindow*)owner;
if (PWINDOW->m_iX11Type == 1 /* Managed */) {
wlr_xwayland_surface_activate(PWINDOW->m_uSurface.xwayland, 1);
}
static auto *const PFOCUSONACTIVATE = &g_pConfigManager->getConfigValuePtr("misc:focus_on_activate")->intValue;
Debug::log(LOG, "X11 Activate request for window %x", PWINDOW);
if (!*PFOCUSONACTIVATE || PWINDOW->m_iX11Type != 1 || PWINDOW == g_pCompositor->m_pLastWindow)
return;
g_pCompositor->focusWindow(PWINDOW);
Vector2D middle = PWINDOW->m_vRealPosition.goalv() + PWINDOW->m_vRealSize.goalv() / 2.f;
g_pCompositor->warpCursorTo(middle);
}
void Events::listener_configureX11(void* owner, void* data) {
@@ -589,15 +780,15 @@ void Events::listener_configureX11(void* owner, void* data) {
return;
}
if (!PWINDOW->m_uSurface.xwayland->mapped) {
if (!PWINDOW->m_uSurface.xwayland->mapped || !PWINDOW->m_bMappedX11) {
wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height);
return;
}
if (E->width > 1 && E->height > 1)
PWINDOW->m_bHidden = false;
PWINDOW->setHidden(false);
else
PWINDOW->m_bHidden = true;
PWINDOW->setHidden(true);
PWINDOW->m_vRealPosition.setValueAndWarp(Vector2D(E->x, E->y));
PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(E->width, E->height));
@@ -612,6 +803,7 @@ void Events::listener_configureX11(void* owner, void* data) {
PWINDOW->m_bCreatedOverFullscreen = true;
if (!PWINDOW->m_sAdditionalConfigData.windowDanceCompat)
g_pInputManager->refocus();
g_pHyprRenderer->damageWindow(PWINDOW);
@@ -622,16 +814,16 @@ void Events::listener_configureX11(void* owner, void* data) {
void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
if (!PWINDOW->m_bMappedX11 || PWINDOW->m_bHidden)
if (!PWINDOW->m_bMappedX11)
return;
const auto POS = PWINDOW->m_vRealPosition.goalv();
const auto SIZ = PWINDOW->m_vRealSize.goalv();
if (PWINDOW->m_uSurface.xwayland->width > 1 && PWINDOW->m_uSurface.xwayland->height > 1)
PWINDOW->m_bHidden = false;
PWINDOW->setHidden(false);
else
PWINDOW->m_bHidden = true;
PWINDOW->setHidden(true);
if (abs(std::floor(POS.x) - PWINDOW->m_uSurface.xwayland->x) > 2 || abs(std::floor(POS.y) - PWINDOW->m_uSurface.xwayland->y) > 2 || abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2) {
Debug::log(LOG, "Unmanaged window %x requests geometry update to %i %i %i %i", PWINDOW, (int)PWINDOW->m_uSurface.xwayland->x, (int)PWINDOW->m_uSurface.xwayland->y, (int)PWINDOW->m_uSurface.xwayland->width, (int)PWINDOW->m_uSurface.xwayland->height);
@@ -695,12 +887,35 @@ void Events::listener_NewXDGDeco(wl_listener* listener, void* data) {
void Events::listener_requestMaximize(void* owner, void* data) {
const auto PWINDOW = (CWindow*)owner;
// ignore
Debug::log(LOG, "Maximize request for %x", PWINDOW);
if (!PWINDOW->m_bIsX11) {
const auto EV = (wlr_foreign_toplevel_handle_v1_maximized_event*)data;
g_pCompositor->setWindowFullscreen(PWINDOW, EV ? EV->maximized : !PWINDOW->m_bIsFullscreen, FULLSCREEN_MAXIMIZED); // this will be rejected if there already is a fullscreen window
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
} else {
if (!PWINDOW->m_bMappedX11 || PWINDOW->m_iX11Type != 1)
return;
g_pCompositor->setWindowFullscreen(PWINDOW, !PWINDOW->m_bIsFullscreen, FULLSCREEN_MAXIMIZED);
}
}
void Events::listener_requestMinimize(void* owner, void* data) {
// ignore
const auto PWINDOW = (CWindow*)owner;
Debug::log(LOG, "Minimize request for %x", PWINDOW);
// if (PWINDOW->m_bIsX11) {
// if (!PWINDOW->m_bMappedX11 || PWINDOW->m_iX11Type != 1)
// return;
// const auto E = (wlr_xwayland_minimize_event*)data;
// wlr_xwayland_surface_set_minimized(PWINDOW->m_uSurface.xwayland, E->minimize && g_pCompositor->m_pLastWindow != PWINDOW); // fucking DXVK
// }
}
void Events::listener_requestMove(void* owner, void* data) {

View File

@@ -59,5 +59,5 @@ void CAnimatedVariable::unregister() {
}
int CAnimatedVariable::getDurationLeftMs() {
return std::clamp((int)(m_pConfig->pValues->internalSpeed * 100) - (int)std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - animationBegin).count(), 0, INT_MAX);
return std::max((int)(m_pConfig->pValues->internalSpeed * 100) - (int)std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - animationBegin).count(), 0);
}

View File

@@ -1,9 +1,7 @@
#include "Color.hpp"
#include "../defines.hpp"
CColor::CColor() {
}
CColor::CColor() { }
CColor::CColor(float r, float g, float b, float a) {
this->r = r;

View File

@@ -120,14 +120,18 @@ void scaleBox(wlr_box* box, float scale) {
}
std::string removeBeginEndSpacesTabs(std::string str) {
while (str[0] == ' ' || str[0] == '\t') {
str = str.substr(1);
int countBefore = 0;
while (str[countBefore] == ' ' || str[countBefore] == '\t') {
countBefore++;
}
while (str.length() != 0 && (str[str.length() - 1] == ' ' || str[str.length() - 1] == '\t')) {
str = str.substr(0, str.length() - 1);
int countAfter = 0;
while (str.length() != 0 && (str[str.length() - countAfter - 1] == ' ' || str[str.length() - 1 - countAfter] == '\t')) {
countAfter++;
}
str = str.substr(countBefore, str.length() - countBefore - countAfter);
return str;
}
@@ -170,7 +174,28 @@ float getPlusMinusKeywordResult(std::string source, float relative) {
}
bool isNumber(const std::string& str, bool allowfloat) {
return std::ranges::all_of(str.begin(), str.end(), [&](char c) { return isdigit(c) != 0 || c == '-' || (allowfloat && c == '.'); });
std::string copy = str;
if (*copy.begin() == '-')
copy = copy.substr(1);
if (copy.empty())
return false;
bool point = !allowfloat;
for (auto& c : copy) {
if (c == '.') {
if (point)
return false;
point = true;
break;
}
if (!std::isdigit(c))
return false;
}
return true;
}
bool isDirection(const std::string& arg) {
@@ -192,7 +217,7 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
}
outName = WORKSPACENAME;
} else {
if (in[0] == 'm' || in[0] == 'e') {
if ((in[0] == 'm' || in[0] == 'e') && (in[1] == '-' || in[1] == '+') && isNumber(in.substr(2))) {
bool onAllMonitors = in[0] == 'e';
if (!g_pCompositor->m_pLastMonitor) {
@@ -221,6 +246,9 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
int highestID = -99999;
for (auto& w : g_pCompositor->m_vWorkspaces) {
if (w->m_iID == SPECIAL_WORKSPACE_ID)
continue;
if (w->m_iID < lowestID)
lowestID = w->m_iID;
@@ -250,14 +278,22 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
outName = g_pCompositor->getWorkspaceByID(currentID)->m_szName;
} else {
if (in[0] == '+' || in[0] == '-') {
if (g_pCompositor->m_pLastMonitor)
result = std::clamp((int)getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspace), 1, INT_MAX);
else if (isNumber(in))
result = std::clamp(std::stoi(in), 1, INT_MAX);
result = std::max((int)getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspace), 1);
else {
Debug::log(ERR, "Relative workspace on no mon!");
result = INT_MAX;
}
} else if (isNumber(in))
result = std::max(std::stoi(in), 1);
else {
// maybe name
const auto PWORKSPACE = g_pCompositor->getWorkspaceByName(in);
if (PWORKSPACE)
result = PWORKSPACE->m_iID;
}
outName = std::to_string(result);
}
}
@@ -266,8 +302,8 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
}
float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2) {
const float DX = std::max((double)0, std::max(p1.x - vec.x, vec.x - p2.x));
const float DY = std::max((double)0, std::max(p1.y - vec.y, vec.y - p2.y));
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});
return DX * DX + DY * DY;
}
@@ -296,6 +332,15 @@ void logSystemInfo() {
Debug::log(LOG, "Release: %s", unameInfo.release);
Debug::log(LOG, "Version: %s", unameInfo.version);
Debug::log(NONE, "\n");
const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA");
Debug::log(LOG, "GPU information:\n%s\n", GPUINFO.c_str());
if (GPUINFO.contains("NVIDIA")) {
Debug::log(WARN, "Warning: you're using an NVIDIA GPU. Make sure you follow the instructions on the wiki if anything is amiss.\n");
}
// log etc
Debug::log(LOG, "os-release:");
@@ -312,8 +357,8 @@ void matrixProjection(float mat[9], int w, int h, wl_output_transform tr) {
// Rotation + reflection
mat[0] = x * t[0];
mat[1] = x * t[1];
mat[3] = y * -t[3];
mat[4] = y * -t[4];
mat[3] = y * t[3];
mat[4] = y * t[4];
// Translation
mat[2] = -copysign(1.0f, mat[0] + mat[1]);
@@ -322,3 +367,38 @@ void matrixProjection(float mat[9], int w, int h, wl_output_transform tr) {
// Identity
mat[8] = 1.0f;
}
int64_t getPPIDof(int64_t pid) {
std::string dir = "/proc/" + std::to_string(pid) + "/status";
FILE* infile;
infile = fopen(dir.c_str(), "r");
if (!infile)
return 0;
char* line = nullptr;
size_t len = 0;
ssize_t len2 = 0;
std::string pidstr;
while ((len2 = getline(&line, &len, infile)) != -1) {
if (strstr(line, "PPid:")) {
pidstr = std::string(line, len2);
const auto tabpos = pidstr.find_last_of('\t');
if (tabpos != std::string::npos)
pidstr = pidstr.substr(tabpos);
break;
}
}
fclose(infile);
if (line)
free(line);
try {
return std::stoll(pidstr);
} catch (std::exception& e) {
return 0;
}
}

View File

@@ -14,6 +14,7 @@ int getWorkspaceIDFromString(const std::string&, std::string&);
float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2);
void logSystemInfo();
std::string execAndGet(const char*);
int64_t getPPIDof(int64_t pid);
float getPlusMinusKeywordResult(std::string in, float relative);

View File

@@ -9,7 +9,7 @@ void CMonitor::onConnect(bool noRule) {
szName = output->name;
// get monitor rule that matches
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(output->name);
SMonitorRule monitorRule = g_pConfigManager->getMonitorRuleFor(output->name, output->description ? output->description : "");
hyprListener_monitorFrame.initCallback(&output->events.frame, &Events::listener_monitorFrame, this);
hyprListener_monitorDestroy.initCallback(&output->events.destroy, &Events::listener_monitorDestroy, this);
@@ -65,6 +65,8 @@ void CMonitor::onConnect(bool noRule) {
}
if (!m_bRenderingInitPassed) {
output->allocator = nullptr;
output->renderer = nullptr;
wlr_output_init_render(output, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer);
m_bRenderingInitPassed = true;
}
@@ -90,8 +92,6 @@ void CMonitor::onConnect(bool noRule) {
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, monitorRule.scale);
wlr_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL); // TODO: support other transforms
wlr_output_enable_adaptive_sync(output, 1);
// create it in the arr
vecPosition = monitorRule.offset;
vecSize = monitorRule.resolution;
@@ -99,10 +99,6 @@ void CMonitor::onConnect(bool noRule) {
wlr_output_enable(output, 1);
// TODO: this doesn't seem to set the X and Y correctly,
// wlr_output_layout_output_coords returns invalid values, I think...
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, output, monitorRule.offset.x, monitorRule.offset.y);
// set mode, also applies
if (!noRule)
g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true);
@@ -118,49 +114,13 @@ void CMonitor::onConnect(bool noRule) {
wlr_ext_workspace_group_handle_v1_output_enter(pWLRWorkspaceGroupHandle, output);
// Workspace
std::string newDefaultWorkspaceName = "";
auto WORKSPACEID = monitorRule.defaultWorkspace == "" ? g_pCompositor->m_vWorkspaces.size() + 1 : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
setupDefaultWS(monitorRule);
if (WORKSPACEID == INT_MAX || WORKSPACEID == (long unsigned int)SPECIAL_WORKSPACE_ID) {
WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1;
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"%s\" is invalid.", monitorRule.defaultWorkspace.c_str());
}
auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
Debug::log(LOG, "New monitor: WORKSPACEID %d, exists: %d", WORKSPACEID, (int)(PNEWWORKSPACE != nullptr));
if (PNEWWORKSPACE) {
// workspace exists, move it to the newly connected monitor
g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, this);
activeWorkspace = PNEWWORKSPACE->m_iID;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
PNEWWORKSPACE->startAnim(true, true, true);
} else {
if (newDefaultWorkspaceName == "")
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(ID, newDefaultWorkspaceName)).get();
// We are required to set the name here immediately
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, newDefaultWorkspaceName.c_str());
PNEWWORKSPACE->m_iID = WORKSPACEID;
}
activeWorkspace = PNEWWORKSPACE->m_iID;
scale = monitorRule.scale;
m_pThisWrap = nullptr;
forceFullFrames = 3; // force 3 full frames to make sure there is no blinking due to double-buffering.
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
PNEWWORKSPACE->setActive(true);
//
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
@@ -172,11 +132,14 @@ void CMonitor::onConnect(bool noRule) {
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName});
// ensure VRR (will enable if necessary)
g_pConfigManager->ensureVRR(this);
}
void CMonitor::onDisconnect() {
if (!m_bEnabled)
if (!m_bEnabled || g_pCompositor->m_bIsShuttingDown)
return;
// Cleanup everything. Move windows back, snap cursor, shit.
@@ -188,6 +151,23 @@ void CMonitor::onDisconnect() {
}
}
if (g_pCompositor->m_pLastMonitor == this)
g_pCompositor->m_pLastMonitor = BACKUPMON;
// remove mirror
if (pMirrorOf) {
pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == this; }));
pMirrorOf = nullptr;
}
if (!mirrors.empty()) {
for (auto& m : mirrors) {
m->setMirror("");
}
g_pConfigManager->m_bWantsMonitorReload = true;
}
m_bEnabled = false;
m_bRenderingInitPassed = false;
@@ -248,3 +228,136 @@ void CMonitor::addDamage(pixman_region32_t* rg) {
void CMonitor::addDamage(wlr_box* box) {
wlr_output_damage_add_box(damage, box);
}
bool CMonitor::isMirror() {
return pMirrorOf != nullptr;
}
void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) {
// Workspace
std::string newDefaultWorkspaceName = "";
auto WORKSPACEID = monitorRule.defaultWorkspace == "" ? g_pCompositor->m_vWorkspaces.size() + 1 : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
if (WORKSPACEID == INT_MAX || WORKSPACEID == (long unsigned int)SPECIAL_WORKSPACE_ID) {
WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1;
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"%s\" is invalid.", monitorRule.defaultWorkspace.c_str());
}
auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
Debug::log(LOG, "New monitor: WORKSPACEID %d, exists: %d", WORKSPACEID, (int)(PNEWWORKSPACE != nullptr));
if (PNEWWORKSPACE) {
// workspace exists, move it to the newly connected monitor
g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, this);
activeWorkspace = PNEWWORKSPACE->m_iID;
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
PNEWWORKSPACE->startAnim(true, true, true);
} else {
if (newDefaultWorkspaceName == "")
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(ID, newDefaultWorkspaceName)).get();
// We are required to set the name here immediately
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, newDefaultWorkspaceName.c_str());
PNEWWORKSPACE->m_iID = WORKSPACEID;
}
activeWorkspace = PNEWWORKSPACE->m_iID;
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
PNEWWORKSPACE->setActive(true);
}
void CMonitor::setMirror(const std::string& mirrorOf) {
const auto PMIRRORMON = g_pCompositor->getMonitorFromString(mirrorOf);
if (PMIRRORMON == pMirrorOf)
return;
if (PMIRRORMON && PMIRRORMON->isMirror()) {
Debug::log(ERR, "Cannot mirror a mirror!");
return;
}
if (PMIRRORMON == this) {
Debug::log(ERR, "Cannot mirror self!");
return;
}
if (!PMIRRORMON) {
// disable mirroring
if (pMirrorOf) {
pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == this; }));
}
pMirrorOf = nullptr;
// set rule
const auto RULE = g_pConfigManager->getMonitorRuleFor(this->szName, this->output->description ? this->output->description : "");
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;
}
}
}
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);
}
setupDefaultWS(RULE);
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, output, (int)vecPosition.x, (int)vecPosition.y);
} else {
CMonitor* BACKUPMON = nullptr;
for (auto& m : g_pCompositor->m_vMonitors) {
if (m.get() != this) {
BACKUPMON = m.get();
break;
}
}
// move all the WS
std::deque<CWorkspace*> wspToMove;
for (auto& w : g_pCompositor->m_vWorkspaces) {
if (w->m_iMonitorID == ID) {
wspToMove.push_back(w.get());
}
}
for (auto& w : wspToMove) {
g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON);
w->startAnim(true, true, true);
}
activeWorkspace = -1;
wlr_output_layout_remove(g_pCompositor->m_sWLROutputLayout, output);
vecPosition = Vector2D(-1337420, -1337420);
pMirrorOf = PMIRRORMON;
pMirrorOf->mirrors.push_back(this);
// remove from mvmonitors
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.erase(std::remove_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](const auto& other) { return other.get() == this; }));
}
g_pCompositor->m_pLastMonitor = g_pCompositor->m_vMonitors.front().get();
}
}

View File

@@ -7,9 +7,11 @@
#include <array>
#include <memory>
struct SMonitorRule;
class CMonitor {
public:
Vector2D vecPosition = Vector2D(0,0);
Vector2D vecPosition = Vector2D(-1,-1); // means unset
Vector2D vecSize = Vector2D(0,0);
Vector2D vecPixelSize = Vector2D(0,0);
Vector2D vecTransformedSize = Vector2D(0,0);
@@ -35,6 +37,14 @@ public:
bool scheduledRecalc = false;
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
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.
// mirroring
CMonitor* pMirrorOf = nullptr;
std::vector<CMonitor*> mirrors;
// for the special workspace
bool specialWorkspaceOpen = false;
@@ -57,6 +67,8 @@ public:
void onDisconnect();
void addDamage(pixman_region32_t* rg);
void addDamage(wlr_box* box);
void setMirror(const std::string&);
bool isMirror();
std::shared_ptr<CMonitor>* m_pThisWrap = nullptr;
bool m_bEnabled = false;
@@ -67,4 +79,7 @@ public:
bool operator==(const CMonitor& rhs) {
return vecPosition == rhs.vecPosition && vecSize == rhs.vecSize && szName == rhs.szName;
}
private:
void setupDefaultWS(const SMonitorRule&);
};

View File

@@ -101,6 +101,14 @@ void SubsurfaceTree::destroySurfaceTree(SSurfaceTreeNode* pNode) {
g_pHyprRenderer->damageBox(&extents);
}
// remove references to this node
for (auto& tn : surfaceTreeNodes) {
for (auto& cs : tn.childSubsurfaces) {
if (cs.pChild == pNode)
cs.pChild = nullptr;
}
}
surfaceTreeNodes.remove(*pNode);
Debug::log(LOG, "SurfaceTree Node removed");
@@ -154,6 +162,9 @@ void Events::listener_newSubsurfaceNode(void* owner, void* data) {
void Events::listener_mapSubsurface(void* owner, void* data) {
SSubsurface* subsurface = (SSubsurface*)owner;
if (subsurface->pChild)
return;
Debug::log(LOG, "Subsurface %x mapped", subsurface->pSubsurface);
subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface, subsurface->pWindowOwner);
@@ -167,21 +178,23 @@ void Events::listener_unmapSubsurface(void* owner, void* data) {
if (subsurface->pChild) {
const auto PNODE = subsurface->pChild;
const auto IT = std::find_if(SubsurfaceTree::surfaceTreeNodes.begin(), SubsurfaceTree::surfaceTreeNodes.end(), [&](const SSurfaceTreeNode& other) { return &other == PNODE; });
if (IT != SubsurfaceTree::surfaceTreeNodes.end()) {
int lx = 0, ly = 0;
addSurfaceGlobalOffset(PNODE, &lx, &ly);
wlr_box extents = {0};
wlr_box extents = {lx, ly, 0, 0};
if (PNODE->pSurface) {
wlr_surface_get_extends(PNODE->pSurface, &extents);
extents.x += lx;
extents.y += ly;
extents.width = PNODE->pSurface->current.width;
extents.height = PNODE->pSurface->current.height;
g_pHyprRenderer->damageBox(&extents);
}
SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
subsurface->pChild = nullptr;
// SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
// subsurface->pChild = nullptr;
}
}
}
@@ -217,8 +230,9 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
void Events::listener_destroySubsurface(void* owner, void* data) {
SSubsurface* subsurface = (SSubsurface*)owner;
if (subsurface->pChild)
listener_destroySubsurfaceNode(subsurface->pChild, nullptr);
if (subsurface->pChild) {
SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
}
Debug::log(LOG, "Subsurface %x destroyed", subsurface);

View File

@@ -131,6 +131,8 @@ struct SMouse {
bool virt = false;
bool connected = false; // means connected to the cursor
DYNLISTENER(commitConstraint);
DYNLISTENER(destroyMouse);
@@ -322,3 +324,28 @@ struct SIMEPopup {
return pSurface == other.pSurface;
}
};
struct STouchDevice {
wlr_input_device* pWlrDevice = nullptr;
std::string name = "";
std::string boundOutput = "";
DYNLISTENER(destroy);
bool operator==(const STouchDevice& other) {
return pWlrDevice == other.pWlrDevice;
}
};
struct SSwitchDevice {
wlr_input_device* pWlrDevice = nullptr;
DYNLISTENER(destroy);
DYNLISTENER(toggle);
bool operator==(const SSwitchDevice& other) {
return pWlrDevice == other.pWlrDevice;
}
};

View File

@@ -91,6 +91,15 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
m_vRenderOffset.warp();
m_fAlpha.warp();
}
// check LS-es
if (in) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
if (!ls->fadingOut)
ls->alpha = m_bHasFullscreenWindow && m_efFullscreenMode == FULLSCREEN_FULL ? 0.f : 255.f;
}
}
}
void CWorkspace::setActive(bool on) {
@@ -120,3 +129,10 @@ void CWorkspace::moveToMonitor(const int& id) {
wlr_ext_workspace_handle_v1_set_name(m_pWlrHandle, m_szName.c_str());
}
CWindow* CWorkspace::getLastFocusedWindow() {
if (!g_pCompositor->windowValidMapped(m_pLastFocusedWindow) || m_pLastFocusedWindow->m_iWorkspaceID != m_iID)
return nullptr;
return m_pLastFocusedWindow;
}

View File

@@ -8,6 +8,8 @@ enum eFullscreenMode : uint8_t {
FULLSCREEN_MAXIMIZED
};
class CWindow;
class CWorkspace {
public:
CWorkspace(int monitorID, std::string name, bool special = false);
@@ -36,6 +38,9 @@ public:
// "scratchpad"
bool m_bIsSpecialWorkspace = false;
// last window
CWindow* m_pLastFocusedWindow = nullptr;
// user-set
bool m_bDefaultFloating = false;
bool m_bDefaultPseudo = false;
@@ -44,4 +49,6 @@ public:
void setActive(bool on);
void moveToMonitor(const int&);
CWindow* getLastFocusedWindow();
};

View File

@@ -0,0 +1,152 @@
#pragma once
#include <wayland-server.h>
typedef unsigned int xcb_atom_t;
struct xcb_icccm_wm_hints_t;
typedef struct {
/** User specified flags */
uint32_t flags;
/** User-specified position */
int32_t x, y;
/** User-specified size */
int32_t width, height;
/** Program-specified minimum size */
int32_t min_width, min_height;
/** Program-specified maximum size */
int32_t max_width, max_height;
/** Program-specified resize increments */
int32_t width_inc, height_inc;
/** Program-specified minimum aspect ratios */
int32_t min_aspect_num, min_aspect_den;
/** Program-specified maximum aspect ratios */
int32_t max_aspect_num, max_aspect_den;
/** Program-specified base size */
int32_t base_width, base_height;
/** Program-specified window gravity */
uint32_t win_gravity;
} xcb_size_hints_t;
typedef unsigned int xcb_window_t;
typedef enum xcb_stack_mode_t {
XCB_STACK_MODE_ABOVE = 0,
XCB_STACK_MODE_BELOW = 1,
XCB_STACK_MODE_TOP_IF = 2,
XCB_STACK_MODE_BOTTOM_IF = 3,
XCB_STACK_MODE_OPPOSITE = 4
} xcb_stack_mode_t;
struct wlr_xwayland {
struct wlr_xwayland_server *server;
struct wlr_xwm *xwm;
struct wlr_xwayland_cursor *cursor;
const char *display_name;
struct wl_display *wl_display;
struct wlr_compositor *compositor;
struct wlr_seat *seat;
void *data;
};
struct wlr_xwayland_surface {
xcb_window_t window_id;
struct wlr_xwm *xwm;
uint32_t surface_id;
struct wl_list link;
struct wl_list stack_link;
struct wl_list unpaired_link;
struct wlr_surface *surface;
int16_t x, y;
uint16_t width, height;
uint16_t saved_width, saved_height;
bool override_redirect;
bool mapped;
char *title;
char *_class;
char *instance;
char *role;
char *startup_id;
pid_t pid;
bool has_utf8_title;
struct wl_list children; // wlr_xwayland_surface::parent_link
struct wlr_xwayland_surface *parent;
struct wl_list parent_link; // wlr_xwayland_surface::children
xcb_atom_t *window_type;
size_t window_type_len;
xcb_atom_t *protocols;
size_t protocols_len;
uint32_t decorations;
xcb_icccm_wm_hints_t *hints;
xcb_size_hints_t *size_hints;
bool pinging;
struct wl_event_source *ping_timer;
// _NET_WM_STATE
bool modal;
bool fullscreen;
bool maximized_vert, maximized_horz;
bool minimized;
bool has_alpha;
struct {
struct wl_signal destroy;
struct wl_signal request_configure;
struct wl_signal request_move;
struct wl_signal request_resize;
struct wl_signal request_minimize;
struct wl_signal request_maximize;
struct wl_signal request_fullscreen;
struct wl_signal request_activate;
struct wl_signal map;
struct wl_signal unmap;
struct wl_signal set_title;
struct wl_signal set_class;
struct wl_signal set_role;
struct wl_signal set_parent;
struct wl_signal set_pid;
struct wl_signal set_startup_id;
struct wl_signal set_window_type;
struct wl_signal set_hints;
struct wl_signal set_decorations;
struct wl_signal set_override_redirect;
struct wl_signal set_geometry;
struct wl_signal ping_timeout;
} events;
};
struct wlr_xwayland_surface_configure_event {
struct wlr_xwayland_surface *surface;
int16_t x, y;
uint16_t width, height;
uint16_t mask; // xcb_config_window_t
};
inline void wlr_xwayland_destroy(wlr_xwayland*) { }
inline void wlr_xwayland_surface_configure(wlr_xwayland_surface*, int, int, int, int) { }
inline bool wlr_surface_is_xwayland_surface(void*) { return false; }
inline void wlr_xwayland_surface_activate(wlr_xwayland_surface*, bool) { }
inline void wlr_xwayland_surface_restack(wlr_xwayland_surface*, int, xcb_stack_mode_t) { }
inline wlr_xwayland_surface* wlr_xwayland_surface_from_wlr_surface(void*) { return nullptr; }
inline void wlr_xwayland_surface_close(wlr_xwayland_surface*) { }
inline void wlr_xwayland_surface_set_fullscreen(wlr_xwayland_surface*, bool) { }
inline void wlr_xwayland_surface_set_minimized(wlr_xwayland_surface *, bool) {}

View File

@@ -22,7 +22,6 @@
#include <filesystem>
#include <climits>
#if true
// wlroots uses dumb-ass shit that makes it not compile on C++, let's fix that.
// https://github.com/swaywm/wlroots/issues/682
@@ -80,13 +79,11 @@ extern "C" {
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
#include <wlr/types/wlr_idle_inhibit_v1.h>
#include <wlr/util/log.h>
#include <wlr/xwayland.h>
#include <wlr/util/region.h>
#include <wlr/types/wlr_tablet_pad.h>
#include <wlr/types/wlr_tablet_tool.h>
#include <wlr/types/wlr_tablet_v2.h>
#include <xkbcommon/xkbcommon.h>
#include <X11/Xproto.h>
#include <wlr/render/egl.h>
#include <wlr/render/gles2.h>
#include <wlr/render/wlr_texture.h>
@@ -101,6 +98,14 @@ extern "C" {
#include <wlr/types/wlr_input_method_v2.h>
#include <wlr/types/wlr_text_input_v3.h>
#include <wlr/types/wlr_touch.h>
#include <wlr/types/wlr_switch.h>
#include <drm_fourcc.h>
#ifndef NO_XWAYLAND
#include <wlr/xwayland.h>
#include <X11/Xproto.h>
#endif
}
#undef delete
@@ -121,6 +126,7 @@ extern "C" {
#ifdef NO_XWAYLAND
#define XWAYLAND false
#include "helpers/XWaylandStubs.hpp"
#else
#define XWAYLAND true
#endif

View File

@@ -69,7 +69,7 @@ SDwindleNodeData* SDwindleNodeData::getGroupVisible() {
SDwindleNodeData* current = this->pNextGroupMember;
while (current != this) {
if (!current->pWindow->m_bHidden) {
if (!current->pWindow->isHidden()) {
return current;
}
@@ -83,11 +83,24 @@ void SDwindleNodeData::setGroupFocusedNode(SDwindleNodeData* pMember) {
SDwindleNodeData* current = this->pNextGroupMember;
while (current != this) {
current->pWindow->m_bHidden = current != pMember;
current->pWindow->setHidden(current != pMember);
current = current->pNextGroupMember;
}
this->pWindow->m_bHidden = pMember != this;
this->pWindow->setHidden(pMember != this);
}
int SDwindleNodeData::getGroupMemberCount() {
SDwindleNodeData* current = this->pNextGroupMember;
int no = 1;
while (current != this) {
current = current->pNextGroupMember;
no++;
}
return no;
}
int CHyprDwindleLayout::getNodesOnWorkspace(const int& id) {
@@ -153,14 +166,15 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
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 auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
const auto GAPSIN = g_pConfigManager->getInt("general:gaps_in");
const auto GAPSOUT = g_pConfigManager->getInt("general:gaps_out");
const auto PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
const auto PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue;
const auto PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue;
const auto PWINDOW = pNode->pWindow;
if (!g_pCompositor->windowExists(PWINDOW) || !PWINDOW->m_bIsMapped) {
Debug::log(ERR, "Node %x holding invalid window %x!!", pNode, PWINDOW);
onWindowRemovedTiling(PWINDOW);
return;
}
@@ -169,29 +183,33 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
static auto *const PNOGAPSWHENONLY = &g_pConfigManager->getConfigValuePtr("dwindle:no_gaps_when_only")->intValue;
auto calcPos = PWINDOW->m_vPosition + Vector2D(BORDERSIZE, BORDERSIZE);
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE);
auto calcPos = PWINDOW->m_vPosition + Vector2D(*PBORDERSIZE, *PBORDERSIZE);
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
if (*PNOGAPSWHENONLY && PWINDOW->m_iWorkspaceID != SPECIAL_WORKSPACE_ID && getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1) {
PWINDOW->m_vRealPosition = calcPos - Vector2D(BORDERSIZE, BORDERSIZE);
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE);
const auto NODESONWORKSPACE = getNodesOnWorkspace(PWINDOW->m_iWorkspaceID);
if (*PNOGAPSWHENONLY && PWINDOW->m_iWorkspaceID != SPECIAL_WORKSPACE_ID && (NODESONWORKSPACE == 1 || (pNode->isGroupMember() && pNode->getGroupMemberCount() == NODESONWORKSPACE))) {
PWINDOW->m_vRealPosition = calcPos - Vector2D(*PBORDERSIZE, *PBORDERSIZE);
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
PWINDOW->updateWindowDecos();
PWINDOW->m_sSpecialRenderData.rounding = false;
PWINDOW->m_sSpecialRenderData.border = false;
PWINDOW->m_sSpecialRenderData.decorate = false;
return;
}
PWINDOW->m_sSpecialRenderData.rounding = true;
PWINDOW->m_sSpecialRenderData.border = true;
PWINDOW->m_sSpecialRenderData.decorate = true;
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? GAPSOUT : GAPSIN,
DISPLAYTOP ? GAPSOUT : GAPSIN);
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? *PGAPSOUT : *PGAPSIN,
DISPLAYTOP ? *PGAPSOUT : *PGAPSIN);
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? GAPSOUT : GAPSIN,
DISPLAYBOTTOM ? GAPSOUT : GAPSIN);
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? *PGAPSOUT : *PGAPSIN,
DISPLAYBOTTOM ? *PGAPSOUT : *PGAPSIN);
calcPos = calcPos + OFFSETTOPLEFT;
calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT;
@@ -283,7 +301,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace);
} else if (*PUSEACTIVE) {
if (g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) && !g_pCompositor->m_pLastWindow->m_bIsFloating && g_pCompositor->m_pLastWindow != pWindow && g_pCompositor->m_pLastWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID && g_pCompositor->m_pLastWindow->m_bIsMapped) {
if (g_pCompositor->m_pLastWindow && !g_pCompositor->m_pLastWindow->m_bIsFloating && g_pCompositor->m_pLastWindow != pWindow && g_pCompositor->m_pLastWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID && g_pCompositor->m_pLastWindow->m_bIsMapped) {
OPENINGON = getNodeFromWindow(g_pCompositor->m_pLastWindow);
} else {
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(g_pInputManager->getMouseCoordsInternal()));
@@ -311,6 +329,13 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
return;
}
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
if (PWORKSPACE->m_bHasFullscreenWindow) {
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, FULLSCREEN_FULL);
}
// if it's the first, it's easy. Make it fullscreen.
if (!OPENINGON || OPENINGON->pWindow == pWindow) {
PNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
@@ -340,6 +365,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
applyNodeDataToWindow(PNODE);
pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(pWindow));
return;
}
@@ -355,19 +382,19 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
NEWPARENT->pParent = OPENINGON->pParent;
NEWPARENT->isNode = true; // it is a node
const auto WIDTHMULTIPLIER = g_pConfigManager->getFloat("dwindle:split_width_multiplier");
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 * WIDTHMULTIPLIER;
const auto SIDEBYSIDE = NEWPARENT->size.x > NEWPARENT->size.y * *PWIDTHMULTIPLIER;
NEWPARENT->splitTop = !SIDEBYSIDE;
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
const auto FORCESPLIT = g_pConfigManager->getInt("dwindle:force_split");
const auto PFORCESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:force_split")->intValue;
if (FORCESPLIT == 0) {
if ((SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / WIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x / 2.f, NEWPARENT->position.y + NEWPARENT->size.y))
|| (!SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / WIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x, NEWPARENT->position.y + NEWPARENT->size.y / 2.f))) {
if (*PFORCESPLIT == 0) {
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))
|| (!SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / *PWIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x, NEWPARENT->position.y + NEWPARENT->size.y / 2.f))) {
// we are hovering over the first node, make PNODE first.
NEWPARENT->children[1] = OPENINGON;
NEWPARENT->children[0] = PNODE;
@@ -377,7 +404,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
NEWPARENT->children[1] = PNODE;
}
} else {
if (FORCESPLIT == 1) {
if (*PFORCESPLIT == 1) {
NEWPARENT->children[1] = OPENINGON;
NEWPARENT->children[0] = PNODE;
} else {
@@ -398,7 +425,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
// Update the children
if (NEWPARENT->size.x * WIDTHMULTIPLIER > NEWPARENT->size.y) {
if (NEWPARENT->size.x * *PWIDTHMULTIPLIER > NEWPARENT->size.y) {
// split left/right
OPENINGON->position = NEWPARENT->position;
OPENINGON->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y);
@@ -430,6 +457,9 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
return;
}
if (pWindow->m_bIsFullscreen)
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
// check if it was grouped
if (PNODE->isGroupMember()) {
// get shit
@@ -453,21 +483,25 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
PNEXT->position = PNODE->position;
PNEXT->size = PNODE->size;
applyNodeDataToWindow(PNEXT);
} else {
const auto PHEAD = PNODE->getGroupHead();
PNEXT->position = PHEAD->position;
PNEXT->size = PHEAD->size;
applyNodeDataToWindow(PNEXT);
}
PNEXT->setGroupFocusedNode(PNEXT);
PNEXT->pWindow->m_bHidden = false;
PNEXT->pWindow->setHidden(false);
m_lDwindleNodesData.remove(*PNODE);
applyNodeDataToWindow(PNEXT);
if (!PNEXT->isGroupMember()) {
// means we dissolved the group
recalculateMonitor(PNEXT->pWindow->m_iMonitorID);
}
return;
}
@@ -485,6 +519,17 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
PSIBLING->size = PPARENT->size;
PSIBLING->pParent = PPARENT->pParent;
if (PSIBLING->isGroupMember()) {
// apply to all group members
SDwindleNodeData* current = PSIBLING->pNextGroupMember;
while (current != PSIBLING) {
current->position = PPARENT->position;
current->size = PPARENT->size;
current = current->pNextGroupMember;
}
}
if (PPARENT->pParent != nullptr) {
if (PPARENT->pParent->children[0] == PPARENT) {
PPARENT->pParent->children[0] = PSIBLING;
@@ -576,7 +621,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
const auto PNODE = getNodeFromWindow(PWINDOW);
if (!PNODE) {
PWINDOW->m_vRealSize = Vector2D(std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).x, (double)20, (double)999999), std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).y, (double)20, (double)999999));
PWINDOW->m_vRealSize = Vector2D(std::max((PWINDOW->m_vRealSize.goalv() + pixResize).x, 20.0), std::max((PWINDOW->m_vRealSize.goalv() + pixResize).y, 20.0));
PWINDOW->updateWindowDecos();
return;
}
@@ -613,11 +658,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
if (!PPARENT2) {
if (PARENTSIDEBYSIDE) {
allowedMovement.x *= 2.f / PPARENT->size.x;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
} else {
allowedMovement.y *= 2.f / PPARENT->size.y;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
}
@@ -632,11 +677,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
if (!PPARENT2) {
if (PARENTSIDEBYSIDE) {
allowedMovement.x *= 2.f / PPARENT->size.x;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
} else {
allowedMovement.y *= 2.f / PPARENT->size.y;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
}
@@ -650,8 +695,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
allowedMovement.x *= 2.f / SIDECONTAINER->size.x;
allowedMovement.y *= 2.f / TOPCONTAINER->size.y;
SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, (double)0.1f, (double)1.9f);
TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, (double)0.1f, (double)1.9f);
SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, 0.1, 1.9);
TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, 0.1, 1.9);
SIDECONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
TOPCONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
}
@@ -660,10 +705,7 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
if (!g_pCompositor->windowValidMapped(pWindow))
return;
if (!g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
return;
if (on == pWindow->m_bIsFullscreen)
if (on == pWindow->m_bIsFullscreen || pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
return; // ignore
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
@@ -763,12 +805,13 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PNODE->workspaceID);
if (PWORKSPACE->m_bHasFullscreenWindow)
fullscreenRequestForWindow(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), FULLSCREEN_FULL, false);
if (PWORKSPACE->m_bHasFullscreenWindow && !PNODE->isGroupMember()) {
Debug::log(ERR, "Cannot enable group on fullscreen window");
return;
}
if (PNODE->isGroupMember()) {
// dissolve group
const auto PHEAD = PNODE->getGroupHead();
SDwindleNodeData* current = PNODE->pNextGroupMember;
@@ -786,11 +829,18 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
toAddWindows.push_back(PWINDOW);
PWINDOW->m_bHidden = false;
PWINDOW->setHidden(false);
}
if (PHEAD->pPreviousGroupMember)
PHEAD->pPreviousGroupMember->pNextGroupMember = PHEAD->pNextGroupMember;
if (PHEAD->pNextGroupMember)
PHEAD->pNextGroupMember->pPreviousGroupMember = PHEAD->pPreviousGroupMember;
PHEAD->pPreviousGroupMember = nullptr;
PHEAD->pNextGroupMember = nullptr;
onWindowRemoved(PHEAD->pWindow);
for (auto& pw : toAddWindows) {
@@ -870,6 +920,9 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
// focus
PNODE->setGroupFocusedNode(PNODE);
// required for no_gaps_when_only to work
applyNodeDataToWindow(PNODE);
}
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
@@ -903,7 +956,7 @@ std::deque<CWindow*> CHyprDwindleLayout::getGroupMembers(CWindow* pWindow) {
return result;
}
void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward) {
void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward, CWindow* forceTo) {
if (!g_pCompositor->windowValidMapped(pWindow))
return; // reject
@@ -921,10 +974,18 @@ void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward) {
else
pNewNode = PNODE->pPreviousGroupMember;
if (forceTo) {
const auto NODETO = getNodeFromWindow(forceTo);
if (NODETO)
pNewNode = NODETO;
}
PNODE->setGroupFocusedNode(pNewNode);
pNewNode->position = PNODE->position;
pNewNode->size = PNODE->size;
pNewNode->workspaceID = PNODE->workspaceID;
applyNodeDataToWindow(pNewNode);
@@ -936,9 +997,9 @@ void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward) {
pNewNode->pWindow->m_bIsFloating = PNODE->pWindow->m_bIsFloating;
if (PNODE->pWindow->m_bIsFullscreen) {
PNODE->pWindow->m_bHidden = false;
PNODE->pWindow->setHidden(false);
g_pCompositor->setWindowFullscreen(PNODE->pWindow, false, PWORKSPACE->m_efFullscreenMode);
PNODE->pWindow->m_bHidden = true;
PNODE->pWindow->setHidden(true);
g_pCompositor->setWindowFullscreen(pNewNode->pWindow, true, PWORKSPACE->m_efFullscreenMode);
pNewNode->pWindow->m_vRealSize.warp();
@@ -954,6 +1015,9 @@ SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(CWindow* pWindow
SWindowRenderLayoutHints hints;
static auto *const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:col.group_border_active")->intValue;
static auto *const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:col.group_border")->intValue;
const auto PNODE = getNodeFromWindow(pWindow);
if (!PNODE)
return hints; // left for the future, maybe floating funkiness
@@ -962,9 +1026,9 @@ SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(CWindow* pWindow
hints.isBorderColor = true;
if (pWindow == g_pCompositor->m_pLastWindow)
hints.borderColor = CColor(g_pConfigManager->getInt("dwindle:col.group_border_active"));
hints.borderColor = CColor(*PGROUPCOLACTIVE);
else
hints.borderColor = CColor(g_pConfigManager->getInt("dwindle:col.group_border"));
hints.borderColor = CColor(*PGROUPCOLINACTIVE);
}
return hints;
@@ -973,18 +1037,33 @@ SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(CWindow* pWindow
void CHyprDwindleLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
// windows should be valid, insallah
const auto PNODE = getNodeFromWindow(pWindow);
const auto PNODE2 = getNodeFromWindow(pWindow2);
auto PNODE = getNodeFromWindow(pWindow);
auto PNODE2 = getNodeFromWindow(pWindow2);
if (!PNODE2 || !PNODE)
return;
if (PNODE->workspaceID != PNODE2->workspaceID) {
Debug::log(ERR, "Dwindle: Rejecting a swap between workspaces");
if (!PNODE2 || !PNODE) {
return;
}
// we will not delete the nodes, just fix the tree
SDwindleNodeData* ACTIVE1 = nullptr;
SDwindleNodeData* ACTIVE2 = nullptr;
if (PNODE2->isGroupMember() || PNODE->isGroupMember()) {
if (PNODE->workspaceID != PNODE2->workspaceID) {
Debug::log(ERR, "Groups are confined to a monitor");
return;
}
if (PNODE->isGroupMember()) {
ACTIVE1 = PNODE;
PNODE = PNODE->getGroupHead();
}
if (PNODE2->isGroupMember()) {
ACTIVE2 = PNODE2;
PNODE2 = PNODE2->getGroupHead();
}
if (PNODE2->pParent == PNODE->pParent) {
const auto PPARENT = PNODE->pParent;
@@ -1021,10 +1100,38 @@ void CHyprDwindleLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
PNODE2->pParent = PNODE->pParent;
PNODE->pParent = PPARENTNODE2;
// these are window nodes, so no children.
std::swap(PNODE2->workspaceID, PNODE->workspaceID);
} else {
// swap the windows and recalc
PNODE2->pWindow = pWindow;
PNODE->pWindow = pWindow2;
}
if (PNODE->workspaceID != PNODE2->workspaceID) {
std::swap(pWindow2->m_iMonitorID, pWindow->m_iMonitorID);
std::swap(pWindow2->m_iWorkspaceID, pWindow->m_iWorkspaceID);
}
// recalc the workspace
getMasterNodeOnWorkspace(PNODE->workspaceID)->recalcSizePosRecursive();
if (PNODE2->workspaceID != PNODE->workspaceID) {
getMasterNodeOnWorkspace(PNODE2->workspaceID)->recalcSizePosRecursive();
}
if (ACTIVE1) {
ACTIVE1->position = PNODE->position;
ACTIVE1->size = PNODE->size;
ACTIVE1->pWindow->m_vPosition = ACTIVE1->position;
ACTIVE1->pWindow->m_vSize = ACTIVE1->size;
}
if (ACTIVE2) {
ACTIVE2->position = PNODE2->position;
ACTIVE2->size = PNODE2->size;
ACTIVE2->pWindow->m_vPosition = ACTIVE2->position;
ACTIVE2->pWindow->m_vSize = ACTIVE2->size;
}
}
void CHyprDwindleLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
@@ -1032,7 +1139,7 @@ void CHyprDwindleLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
const auto PNODE = getNodeFromWindow(pWindow);
if (!PNODE || !PNODE->pParent)
if (!PNODE || !PNODE->pParent || (PNODE->isGroupMember() && PNODE->getGroupMemberCount() == g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID)))
return;
PNODE->pParent->splitRatio = std::clamp(PNODE->pParent->splitRatio + ratio, 0.1f, 1.9f);
@@ -1050,7 +1157,7 @@ std::any CHyprDwindleLayout::layoutMessage(SLayoutMessageHeader header, std::str
else if (message == "togglesplit")
toggleSplit(header.pWindow);
else if (message == "groupinfo") {
auto res = getGroupMembers(g_pCompositor->m_pLastWindow);
auto res = getGroupMembers(header.pWindow ? header.pWindow : g_pCompositor->m_pLastWindow);
return res;
}
@@ -1074,7 +1181,7 @@ std::string CHyprDwindleLayout::getLayoutName() {
void CHyprDwindleLayout::onEnable() {
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsFloating || !w->m_bMappedX11 || !w->m_bIsMapped || w->m_bHidden)
if (w->m_bIsFloating || !w->m_bMappedX11 || !w->m_bIsMapped || w->isHidden())
continue;
onWindowCreatedTiling(w.get());

View File

@@ -41,6 +41,7 @@ struct SDwindleNodeData {
bool isGroupMember();
SDwindleNodeData* getGroupHead();
SDwindleNodeData* getGroupVisible();
int getGroupMemberCount();
void setGroupFocusedNode(SDwindleNodeData*);
CHyprDwindleLayout* layout = nullptr;
};
@@ -74,7 +75,7 @@ private:
SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
void toggleWindowGroup(CWindow*);
void switchGroupWindow(CWindow*, bool forward);
void switchGroupWindow(CWindow*, bool forward, CWindow* to = nullptr);
void toggleSplit(CWindow*);
std::deque<CWindow*> getGroupMembers(CWindow*);

View File

@@ -26,6 +26,9 @@ void IHyprLayout::onWindowRemoved(CWindow* pWindow) {
} else {
onWindowRemovedTiling(pWindow);
}
if (pWindow == m_pLastTiledWindow)
m_pLastTiledWindow = nullptr;
}
void IHyprLayout::onWindowRemovedFloating(CWindow* pWindow) {
@@ -47,7 +50,7 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
pWindow->m_vRealSize = Vector2D(PWINDOWSURFACE->current.width, PWINDOWSURFACE->current.height);
if ((desiredGeometry.width <= 1 || desiredGeometry.height <= 1) && pWindow->m_bIsX11 && pWindow->m_iX11Type == 2) { // XDG windows should be fine. TODO: check for weird atoms?
pWindow->m_bHidden = true;
pWindow->setHidden(true);
return;
}
@@ -64,8 +67,24 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
// check if it's on the correct monitor!
Vector2D middlePoint = Vector2D(desiredGeometry.x, desiredGeometry.y) + Vector2D(desiredGeometry.width, desiredGeometry.height) / 2.f;
// check if it's visible on any monitor (only for XDG)
bool visible = pWindow->m_bIsX11;
if (!pWindow->m_bIsX11) {
for (auto& m : g_pCompositor->m_vMonitors) {
if (VECINRECT(Vector2D(desiredGeometry.x, desiredGeometry.y), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)
|| VECINRECT(Vector2D(desiredGeometry.x + desiredGeometry.width, desiredGeometry.y), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)
|| VECINRECT(Vector2D(desiredGeometry.x, desiredGeometry.y + desiredGeometry.height), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)
|| VECINRECT(Vector2D(desiredGeometry.x + desiredGeometry.width, desiredGeometry.y + desiredGeometry.height), m->vecPosition.x, m->vecPosition.y, m->vecPosition.x + m->vecSize.x, m->vecPosition.y + m->vecPosition.y)) {
visible = true;
break;
}
}
}
// TODO: detect a popup in a more consistent way.
if ((desiredGeometry.x == 0 && desiredGeometry.y == 0)) {
if ((desiredGeometry.x == 0 && desiredGeometry.y == 0) || !visible) {
// if it's not, fall back to the center placement
pWindow->m_vRealPosition = PMONITOR->vecPosition + Vector2D((PMONITOR->vecSize.x - desiredGeometry.width) / 2.f, (PMONITOR->vecSize.y - desiredGeometry.height) / 2.f);
} else {
@@ -121,7 +140,7 @@ void IHyprLayout::onBeginDragWindow() {
DRAGGINGWINDOW->m_bDraggingTiled = false;
if (!DRAGGINGWINDOW->m_bIsFloating) {
if (g_pInputManager->dragButton == BTN_LEFT) {
if (g_pInputManager->dragMode == MBIND_MOVE) {
changeWindowFloatingMode(DRAGGINGWINDOW);
DRAGGINGWINDOW->m_bIsFloating = true;
DRAGGINGWINDOW->m_bDraggingTiled = true;
@@ -135,6 +154,21 @@ void IHyprLayout::onBeginDragWindow() {
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.goalv();
m_vLastDragXY = m_vBeginDragXY;
// get the grab corner
if (m_vBeginDragXY.x < m_vBeginDragPositionXY.x + m_vBeginDragSizeXY.x / 2.0) {
// left
if (m_vBeginDragXY.y < m_vBeginDragPositionXY.y + m_vBeginDragSizeXY.y / 2.0)
m_iGrabbedCorner = 0;
else
m_iGrabbedCorner = 4;
} else {
// right
if (m_vBeginDragXY.y < m_vBeginDragPositionXY.y + m_vBeginDragSizeXY.y / 2.0)
m_iGrabbedCorner = 1;
else
m_iGrabbedCorner = 3;
}
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
// shadow to ignore any bound to MAIN_MOD
@@ -176,20 +210,46 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
if (g_pInputManager->dragButton == BTN_LEFT) {
if (g_pInputManager->dragMode == MBIND_MOVE) {
if (*PANIMATE) {
DRAGGINGWINDOW->m_vRealPosition = m_vBeginDragPositionXY + DELTA;
} else {
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(m_vBeginDragPositionXY + DELTA);
}
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
} else {
} else if (g_pInputManager->dragMode == MBIND_RESIZE) {
if (DRAGGINGWINDOW->m_bIsFloating) {
const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(DRAGGINGWINDOW);
// calc the new size and pos
Vector2D newSize = m_vBeginDragSizeXY;
Vector2D newPos = m_vBeginDragPositionXY;
if (m_iGrabbedCorner == 3) {
newSize = newSize + DELTA;
} else if (m_iGrabbedCorner == 0) {
newSize = newSize - DELTA;
newPos = newPos + DELTA;
} else if (m_iGrabbedCorner == 1) {
newSize = newSize + Vector2D(DELTA.x, -DELTA.y);
newPos = newPos + Vector2D(0, DELTA.y);
} else if (m_iGrabbedCorner == 4) {
newSize = newSize + Vector2D(-DELTA.x, DELTA.y);
newPos = newPos + Vector2D(DELTA.x, 0);
}
newSize = newSize.clamp(Vector2D(20,20), MAXSIZE);
if (*PANIMATE) {
DRAGGINGWINDOW->m_vRealSize = Vector2D(std::clamp(m_vBeginDragSizeXY.x + DELTA.x, (double)20, (double)MAXSIZE.x), std::clamp(m_vBeginDragSizeXY.y + DELTA.y, (double)20, (double)MAXSIZE.y));
DRAGGINGWINDOW->m_vRealSize = newSize;
DRAGGINGWINDOW->m_vRealPosition = newPos;
} else {
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(m_vBeginDragSizeXY + DELTA);
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(Vector2D(std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().x, (double)20, (double)MAXSIZE.x), std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().y, (double)20, (double)MAXSIZE.y)));
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(newSize);
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(newPos);
}
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
@@ -226,6 +286,8 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
return;
}
pWindow->m_bPinned = false;
const auto TILED = isWindowTiled(pWindow);
if (!TILED) {
@@ -242,6 +304,9 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
pWindow->m_vLastFloatingSize = PSAVEDSIZE;
// move to narnia because we don't wanna find our own node. onWindowCreatedTiling should apply the coords back.
pWindow->m_vPosition = Vector2D(-999999, -999999);
onWindowCreatedTiling(pWindow);
pWindow->m_vRealPosition.setValue(PSAVEDPOS);
@@ -249,6 +314,9 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
// fix pseudo leaving artifacts
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
if (pWindow == g_pCompositor->m_pLastWindow)
m_pLastTiledWindow = pWindow;
} else {
pWindow->m_vSize = pWindow->m_vRealSize.vec();
pWindow->m_vPosition = pWindow->m_vRealPosition.vec();
@@ -263,6 +331,9 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
pWindow->m_sSpecialRenderData.rounding = true;
if (pWindow == m_pLastTiledWindow)
m_pLastTiledWindow = nullptr;
}
g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
@@ -285,3 +356,47 @@ void IHyprLayout::moveActiveWindow(const Vector2D& delta, CWindow* pWindow) {
g_pHyprRenderer->damageWindow(PWINDOW);
}
void IHyprLayout::onWindowFocusChange(CWindow* pNewFocus) {
m_pLastTiledWindow = pNewFocus && !pNewFocus->m_bIsFloating ? pNewFocus : m_pLastTiledWindow;
}
CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) {
// although we don't expect nullptrs here, let's verify jic
if (!pWindow)
return nullptr;
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
// first of all, if this is a fullscreen workspace,
if (PWORKSPACE->m_bHasFullscreenWindow)
return g_pCompositor->getFullscreenWindowOnWorkspace(pWindow->m_iWorkspaceID);
if (pWindow->m_bIsFloating) {
// the window was floating, let's try the last tiled window.
if (m_pLastTiledWindow && m_pLastTiledWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID)
return m_pLastTiledWindow;
// if we don't, let's try to find any window that is in the middle
if (const auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(pWindow->m_vRealPosition.goalv() + pWindow->m_vRealSize.goalv() / 2.f); PWINDOWCANDIDATE)
return PWINDOWCANDIDATE;
// if not, floating window
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && !w->m_bX11ShouldntFocus && !w->m_bNoFocus)
return w.get();
}
// if there is no candidate, too bad
return nullptr;
}
// if it was a tiled window, we first try to find the window that will replace it.
const auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(pWindow->m_vRealPosition.goalv() + pWindow->m_vRealSize.goalv() / 2.f);
if (!PWINDOWCANDIDATE || pWindow == PWINDOWCANDIDATE || !PWINDOWCANDIDATE->m_bIsMapped || PWINDOWCANDIDATE->isHidden() || PWINDOWCANDIDATE->m_bX11ShouldntFocus || PWINDOWCANDIDATE->m_iX11Type == 2 || PWINDOWCANDIDATE->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID)
return nullptr;
return PWINDOWCANDIDATE;
}

View File

@@ -123,9 +123,22 @@ public:
*/
virtual std::string getLayoutName() = 0;
/*
Called for getting the next candidate for a focus
*/
virtual CWindow* getNextWindowCandidate(CWindow*);
/*
Internal: called when window focus changes
*/
virtual void onWindowFocusChange(CWindow*);
private:
Vector2D m_vBeginDragXY;
Vector2D m_vLastDragXY;
Vector2D m_vBeginDragPositionXY;
Vector2D m_vBeginDragSizeXY;
int m_iGrabbedCorner = 0;
CWindow* m_pLastTiledWindow = nullptr;
};

View File

@@ -84,6 +84,13 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow) {
}
}
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
if (PWORKSPACE->m_bHasFullscreenWindow) {
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, FULLSCREEN_FULL);
}
// recalc
recalculateMonitor(pWindow->m_iMonitorID);
}
@@ -94,6 +101,9 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {
if (!PNODE)
return;
if (pWindow->m_bIsFullscreen)
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
if (PNODE->isMaster) {
// find new one
for (auto& nd : m_lMasterNodesData) {
@@ -215,9 +225,9 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
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 auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
const auto GAPSIN = g_pConfigManager->getInt("general:gaps_in");
const auto GAPSOUT = g_pConfigManager->getInt("general:gaps_out");
const auto PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
const auto PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue;
const auto PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue;
const auto PWINDOW = pNode->pWindow;
@@ -231,29 +241,31 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
PWINDOW->m_vSize = pNode->size;
PWINDOW->m_vPosition = pNode->position;
auto calcPos = PWINDOW->m_vPosition + Vector2D(BORDERSIZE, BORDERSIZE);
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE);
auto calcPos = PWINDOW->m_vPosition + Vector2D(*PBORDERSIZE, *PBORDERSIZE);
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
if (*PNOGAPSWHENONLY && PWINDOW->m_iWorkspaceID != SPECIAL_WORKSPACE_ID && getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1) {
PWINDOW->m_vRealPosition = calcPos - Vector2D(BORDERSIZE, BORDERSIZE);
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE);
PWINDOW->m_vRealPosition = calcPos - Vector2D(*PBORDERSIZE, *PBORDERSIZE);
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
PWINDOW->updateWindowDecos();
PWINDOW->m_sSpecialRenderData.rounding = false;
PWINDOW->m_sSpecialRenderData.border = false;
PWINDOW->m_sSpecialRenderData.decorate = false;
return;
}
PWINDOW->m_sSpecialRenderData.rounding = true;
PWINDOW->m_sSpecialRenderData.border = true;
PWINDOW->m_sSpecialRenderData.decorate = true;
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? GAPSOUT : GAPSIN,
DISPLAYTOP ? GAPSOUT : GAPSIN);
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? *PGAPSOUT : *PGAPSIN,
DISPLAYTOP ? *PGAPSOUT : *PGAPSIN);
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? GAPSOUT : GAPSIN,
DISPLAYBOTTOM ? GAPSOUT : GAPSIN);
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? *PGAPSOUT : *PGAPSIN,
DISPLAYBOTTOM ? *PGAPSOUT : *PGAPSIN);
calcPos = calcPos + OFFSETTOPLEFT;
calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT;
@@ -297,7 +309,7 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* p
const auto PNODE = getNodeFromWindow(PWINDOW);
if (!PNODE) {
PWINDOW->m_vRealSize = Vector2D(std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).x, (double)20, (double)999999), std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).y, (double)20, (double)999999));
PWINDOW->m_vRealSize = Vector2D(std::max((PWINDOW->m_vRealSize.goalv() + pixResize).x, 20.0), std::max((PWINDOW->m_vRealSize.goalv() + pixResize).y, 20.0));
PWINDOW->updateWindowDecos();
return;
}
@@ -326,10 +338,7 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
if (!g_pCompositor->windowValidMapped(pWindow))
return;
if (!g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
return;
if (on == pWindow->m_bIsFullscreen)
if (on == pWindow->m_bIsFullscreen || pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
return; // ignore
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
@@ -425,16 +434,17 @@ void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
return;
if (PNODE->workspaceID != PNODE2->workspaceID) {
Debug::log(ERR, "Master: Rejecting a swap between workspaces");
return;
std::swap(pWindow2->m_iMonitorID, pWindow->m_iMonitorID);
std::swap(pWindow2->m_iWorkspaceID, pWindow->m_iWorkspaceID);
}
// massive hack: just swap window pointers, lol
const auto PWINDOW1 = PNODE->pWindow;
PNODE->pWindow = PNODE2->pWindow;
PNODE2->pWindow = PWINDOW1;
PNODE->pWindow = pWindow2;
PNODE2->pWindow = pWindow;
recalculateMonitor(PWINDOW1->m_iMonitorID);
recalculateMonitor(pWindow->m_iMonitorID);
if (PNODE2->workspaceID != PNODE->workspaceID)
recalculateMonitor(pWindow2->m_iMonitorID);
}
void CHyprMasterLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
@@ -593,7 +603,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
void CHyprMasterLayout::onEnable() {
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsFloating || !w->m_bMappedX11 || !w->m_bIsMapped || w->m_bHidden)
if (w->m_bIsFloating || !w->m_bMappedX11 || !w->m_bIsMapped || w->isHidden())
continue;
onWindowCreatedTiling(w.get());

View File

@@ -14,6 +14,12 @@ int main(int argc, char** argv) {
if (!getenv("XDG_RUNTIME_DIR"))
throw std::runtime_error("XDG_RUNTIME_DIR is not set!");
// export HYPRLAND_CMD
std::string cmd = "";
for (auto i = 0; i < argc; ++i)
cmd += std::string(i == 0 ? "" : " ") + argv[i];
setenv("HYPRLAND_CMD", cmd.c_str(), 1);
// parse some args
std::string configPath;
for (int i = 1; i < argc; ++i) {

View File

@@ -21,12 +21,12 @@ void CAnimationManager::addBezierWithName(std::string name, const Vector2D& p1,
void CAnimationManager::tick() {
bool animationsDisabled = false;
bool animGlobalDisabled = false;
static auto *const PANIMENABLED = &g_pConfigManager->getConfigValuePtr("animations:enabled")->intValue;
if (!*PANIMENABLED)
animationsDisabled = true;
animGlobalDisabled = true;
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
static auto *const PSHADOWSENABLED = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
@@ -56,11 +56,13 @@ void CAnimationManager::tick() {
const auto PWORKSPACE = (CWorkspace*)av->m_pWorkspace;
const auto PLAYER = (SLayerSurface*)av->m_pLayer;
CMonitor* PMONITOR = nullptr;
bool animationsDisabled = animGlobalDisabled;
wlr_box WLRBOXPREV = {0,0,0,0};
if (PWINDOW) {
WLRBOXPREV = PWINDOW->getFullWindowBoundingBox();
PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
animationsDisabled = animationsDisabled || PWINDOW->m_sAdditionalConfigData.forceNoAnims;
} else if (PWORKSPACE) {
PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
WLRBOXPREV = {(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y};
@@ -151,7 +153,7 @@ void CAnimationManager::tick() {
g_pHyprRenderer->damageWindow(PWINDOW);
} else if (PWORKSPACE) {
for (auto& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped || w->m_bHidden)
if (!w->m_bIsMapped || w->isHidden())
continue;
if (w->m_iWorkspaceID != PWORKSPACE->m_iID)
@@ -359,6 +361,10 @@ void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) {
if (!pWindow->m_vRealPosition.isBeingAnimated() && !pWindow->m_vRealSize.isBeingAnimated())
return;
// if the animation is disabled and we are leaving, ignore the anim to prevent the snapshot being fucked
if (!pWindow->m_vRealPosition.m_pConfig->pValues->internalEnabled)
return;
if (pWindow->m_sAdditionalConfigData.animationStyle != "") {
// the window has config'd special anim
if (pWindow->m_sAdditionalConfigData.animationStyle.find("slide") == 0) {

View File

@@ -18,6 +18,23 @@
CEventManager::CEventManager() {
}
int fdHandleWrite(int fd, uint32_t mask, void* data) {
if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP) {
// remove, hanged up
const auto ACCEPTEDFDS = (std::deque<std::pair<int, wl_event_source*>>*)data;
for (auto it = ACCEPTEDFDS->begin(); it != ACCEPTEDFDS->end(); ) {
if (it->first == fd) {
wl_event_source_remove(it->second); // remove this fd listener
it = ACCEPTEDFDS->erase(it);
} else {
it++;
}
}
}
return 0;
}
void CEventManager::startThread() {
m_tThread = std::thread([&]() {
const auto SOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
@@ -36,34 +53,41 @@ void CEventManager::startThread() {
// 10 max queued.
listen(SOCKET, 10);
char readBuf[1024] = {0};
sockaddr_in clientAddress;
socklen_t clientSize = sizeof(clientAddress);
Debug::log(LOG, "Hypr socket 2 started at %s", socketPath.c_str());
// set the socket nonblock
int flags = fcntl(SOCKET, F_GETFL, 0);
fcntl(SOCKET, F_SETFL, flags | O_NONBLOCK);
while (1) {
const auto ACCEPTEDCONNECTION = accept(SOCKET, (sockaddr*)&clientAddress, &clientSize);
if (ACCEPTEDCONNECTION > 0) {
// new connection!
m_dAcceptedSocketFDs.push_back(ACCEPTEDCONNECTION);
int flagsNew = fcntl(ACCEPTEDCONNECTION, F_GETFL, 0);
fcntl(ACCEPTEDCONNECTION, F_SETFL, flagsNew | O_NONBLOCK);
Debug::log(LOG, "Socket 2 accepted a new client at FD %d", ACCEPTEDCONNECTION);
// add to event loop so we can close it when we need to
m_dAcceptedSocketFDs.push_back({ACCEPTEDCONNECTION, wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, ACCEPTEDCONNECTION, WL_EVENT_READABLE, fdHandleWrite, &m_dAcceptedSocketFDs)});
}
ensureFDsValid();
}
close(SOCKET);
});
m_tThread.detach();
}
void CEventManager::ensureFDsValid() {
static char readBuf[1024] = {0};
// pong if all FDs valid
for (auto it = m_dAcceptedSocketFDs.begin(); it != m_dAcceptedSocketFDs.end();) {
auto sizeRead = recv(*it, &readBuf, 1024, 0);
auto sizeRead = recv(it->first, &readBuf, 1024, 0);
if (sizeRead != 0) {
it++;
@@ -74,36 +98,24 @@ void CEventManager::startThread() {
Debug::log(LOG, "Removed invalid socket (2) FD: %d", *it);
it = m_dAcceptedSocketFDs.erase(it);
}
// valid FDs, check the queue
// don't do anything if main thread is writing to the eventqueue
eventQueueMutex.lock();
if (m_dQueuedEvents.empty()){ // if queue empty, sleep and ignore
eventQueueMutex.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
continue;
}
// write all queued events
void CEventManager::flushEvents() {
ensureFDsValid();
eventQueueMutex.lock();
for (auto& ev : m_dQueuedEvents) {
std::string eventString = (ev.event + ">>" + ev.data).substr(0, 1022) + "\n";
for (auto& fd : m_dAcceptedSocketFDs) {
write(fd, eventString.c_str(), eventString.length());
write(fd.first, eventString.c_str(), eventString.length());
}
}
m_dQueuedEvents.clear();
eventQueueMutex.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
close(SOCKET);
});
m_tThread.detach();
}
void CEventManager::postEvent(const SHyprIPCEvent event, bool force) {
@@ -117,5 +129,7 @@ void CEventManager::postEvent(const SHyprIPCEvent event, bool force) {
eventQueueMutex.lock();
m_dQueuedEvents.push_back(ev);
eventQueueMutex.unlock();
flushEvents();
}, event).detach();
}

View File

@@ -25,10 +25,13 @@ public:
private:
void flushEvents();
void ensureFDsValid();
std::mutex eventQueueMutex;
std::deque<SHyprIPCEvent> m_dQueuedEvents;
std::deque<int> m_dAcceptedSocketFDs;
std::deque<std::pair<int, wl_event_source*>> m_dAcceptedSocketFDs;
};
inline std::unique_ptr<CEventManager> g_pEventManager;

View File

@@ -7,6 +7,7 @@ CKeybindManager::CKeybindManager() {
m_mDispatchers["exec"] = spawn;
m_mDispatchers["killactive"] = killActive;
m_mDispatchers["closewindow"] = kill;
m_mDispatchers["togglefloating"] = toggleActiveFloating;
m_mDispatchers["workspace"] = changeworkspace;
m_mDispatchers["fullscreen"] = fullscreenActive;
@@ -41,6 +42,9 @@ CKeybindManager::CKeybindManager() {
m_mDispatchers["resizewindowpixel"] = resizeWindow;
m_mDispatchers["swapnext"] = swapnext;
m_mDispatchers["swapactiveworkspaces"] = swapActiveWorkspaces;
m_mDispatchers["pin"] = pinActive;
m_mDispatchers["mouse"] = mouse;
m_mDispatchers["bringactivetotop"] = bringActiveToTop;
m_tScrollTimer.reset();
}
@@ -120,12 +124,39 @@ void CKeybindManager::updateXKBTranslationState() {
const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
const auto PKEYMAP = FILEPATH == "" ? xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS) : xkb_keymap_new_from_file(PCONTEXT, fopen(FILEPATH.c_str(), "r"), XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
auto PKEYMAP = FILEPATH == "" ? xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS) : xkb_keymap_new_from_file(PCONTEXT, fopen(FILEPATH.c_str(), "r"), XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
if (!PKEYMAP) {
g_pHyprError->queueCreate("[Runtime Error] Invalid keyboard layout passed. ( rules: " + RULES + ", model: " + MODEL + ", variant: " + VARIANT + ", options: " + OPTIONS + ", layout: " + LAYOUT + " )", CColor(255, 50, 50, 255));
Debug::log(ERR, "[XKBTranslationState] Keyboard layout %s with variant %s (rules: %s, model: %s, options: %s) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model, rules.options);
memset(&rules, 0, sizeof(rules));
PKEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
}
xkb_context_unref(PCONTEXT);
m_pXKBTranslationState = xkb_state_new(PKEYMAP);
}
bool CKeybindManager::ensureMouseBindState() {
if (!m_bIsMouseBindActive)
return false;
if (g_pInputManager->currentlyDraggedWindow) {
m_bIsMouseBindActive = false;
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
g_pInputManager->currentlyDraggedWindow = nullptr;
g_pInputManager->dragMode = MBIND_INVALID;
return true;
}
m_bIsMouseBindActive = false;
return false;
}
bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) {
if (!g_pCompositor->m_bSessionActive) {
m_dPressedKeycodes.clear();
@@ -158,6 +189,8 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
m_uLastCode = KEYCODE;
m_uLastMouseCode = 0;
bool mouseBindWasActive = ensureMouseBindState();
bool found = false;
if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
// clean repeat
@@ -170,9 +203,9 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
m_dPressedKeycodes.push_back(KEYCODE);
m_dPressedKeysyms.push_back(keysym);
found = g_pKeybindManager->handleKeybinds(MODS, "", keysym, 0, true, e->time_msec) || found;
found = handleKeybinds(MODS, "", keysym, 0, true, e->time_msec) || found;
found = g_pKeybindManager->handleKeybinds(MODS, "", 0, KEYCODE, true, e->time_msec) || found;
found = handleKeybinds(MODS, "", 0, KEYCODE, true, e->time_msec) || found;
if (found)
shadowKeybinds(keysym, KEYCODE);
@@ -184,17 +217,17 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard
m_pActiveKeybind = nullptr;
}
m_dPressedKeycodes.erase(std::remove(m_dPressedKeycodes.begin(), m_dPressedKeycodes.end(), KEYCODE));
m_dPressedKeysyms.erase(std::remove(m_dPressedKeysyms.begin(), m_dPressedKeysyms.end(), keysym));
m_dPressedKeycodes.erase(std::remove(m_dPressedKeycodes.begin(), m_dPressedKeycodes.end(), KEYCODE), m_dPressedKeycodes.end());
m_dPressedKeysyms.erase(std::remove(m_dPressedKeysyms.begin(), m_dPressedKeysyms.end(), keysym), m_dPressedKeysyms.end());
found = g_pKeybindManager->handleKeybinds(MODS, "", keysym, 0, false, e->time_msec) || found;
found = handleKeybinds(MODS, "", keysym, 0, false, e->time_msec) || found;
found = g_pKeybindManager->handleKeybinds(MODS, "", 0, KEYCODE, false, e->time_msec) || found;
found = handleKeybinds(MODS, "", 0, KEYCODE, false, e->time_msec) || found;
shadowKeybinds();
}
return !found;
return !found && !mouseBindWasActive;
}
bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) {
@@ -212,9 +245,9 @@ bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) {
bool found = false;
if (e->source == WLR_AXIS_SOURCE_WHEEL && e->orientation == WLR_AXIS_ORIENTATION_VERTICAL) {
if (e->delta < 0) {
found = g_pKeybindManager->handleKeybinds(MODS, "mouse_down", 0, 0, true, 0);
found = handleKeybinds(MODS, "mouse_down", 0, 0, true, 0);
} else {
found = g_pKeybindManager->handleKeybinds(MODS, "mouse_up", 0, 0, true, 0);
found = handleKeybinds(MODS, "mouse_up", 0, 0, true, 0);
}
if (found)
@@ -233,18 +266,24 @@ bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) {
m_uLastCode = 0;
m_uTimeLastMs = e->time_msec;
bool mouseBindWasActive = ensureMouseBindState();
if (e->state == WLR_BUTTON_PRESSED) {
found = g_pKeybindManager->handleKeybinds(MODS, "mouse:" + std::to_string(e->button), 0, 0, true, 0);
found = handleKeybinds(MODS, "mouse:" + std::to_string(e->button), 0, 0, true, 0);
if (found)
shadowKeybinds();
} else {
found = g_pKeybindManager->handleKeybinds(MODS, "mouse:" + std::to_string(e->button), 0, 0, false, 0);
found = handleKeybinds(MODS, "mouse:" + std::to_string(e->button), 0, 0, false, 0);
shadowKeybinds();
}
return !found;
return !found && !mouseBindWasActive;
}
void CKeybindManager::onSwitchEvent(const std::string& switchName) {
handleKeybinds(0, "switch:" + switchName, 0, 0, true, 0);
}
int repeatKeyHandler(void* data) {
@@ -276,7 +315,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
}
for (auto& k : m_lKeybinds) {
if (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || (!pressed && !k.release && k.handler != "pass") || k.shadowed)
if (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || (!pressed && !k.release && k.handler != "pass" && k.handler != "mouse") || k.shadowed)
continue;
if (!key.empty()) {
@@ -305,7 +344,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
return true;
}
const auto DISPATCHER = m_mDispatchers.find(k.handler);
const auto DISPATCHER = m_mDispatchers.find(k.mouse ? "mouse" : k.handler);
// Should never happen, as we check in the ConfigManager, but oh well
if (DISPATCHER == m_mDispatchers.end()) {
@@ -316,6 +355,9 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
m_iPassPressed = (int)pressed;
if (k.handler == "mouse")
DISPATCHER->second((pressed ? "1" : "0") + k.arg);
else
DISPATCHER->second(k.arg);
m_iPassPressed = -1;
@@ -382,10 +424,29 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
if (!(keysym >= XKB_KEY_XF86Switch_VT_1 && keysym <= XKB_KEY_XF86Switch_VT_12))
return false;
const auto PSESSION = wlr_backend_get_session(g_pCompositor->m_sWLRBackend);
if (PSESSION) {
const int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
wlr_session_change_vt(PSESSION, TTY);
// beyond this point, return true to not handle anything else.
// we'll avoid printing shit to active windows.
if (g_pCompositor->m_sWLRSession) {
const unsigned int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
// vtnr is bugged for some reason.
const std::string TTYSTR = execAndGet("head -n 1 /sys/devices/virtual/tty/tty0/active").substr(3);
unsigned int ttynum = 0;
try {
ttynum = std::stoll(TTYSTR);
} catch (std::exception &e) {
; // oops?
}
if (ttynum == TTY)
return true;
Debug::log(LOG, "Switching from VT %i to VT %i", ttynum, TTY);
if (!wlr_session_change_vt(g_pCompositor->m_sWLRSession, TTY))
return true; // probably same session
g_pCompositor->m_bSessionActive = false;
for (auto& m : g_pCompositor->m_vMonitors) {
@@ -398,7 +459,7 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
return true;
}
return false;
return true;
}
bool CKeybindManager::handleInternalKeybinds(xkb_keysym_t keysym) {
@@ -443,6 +504,11 @@ void CKeybindManager::spawn(std::string args) {
}
if (child == 0) {
// run in child
sigset_t set;
sigemptyset(&set);
sigprocmask(SIG_SETMASK, &set, NULL);
grandchild = fork();
if (grandchild == 0) {
// run in grandchild
@@ -475,6 +541,17 @@ void CKeybindManager::killActive(std::string args) {
g_pCompositor->closeWindow(g_pCompositor->m_pLastWindow);
}
void CKeybindManager::kill(std::string args) {
const auto PWINDOW = g_pCompositor->getWindowByRegex(args);
if (!PWINDOW) {
Debug::log(ERR, "kill: no window found");
return;
}
g_pCompositor->closeWindow(PWINDOW);
}
void CKeybindManager::clearKeybinds() {
m_lKeybinds.clear();
}
@@ -491,7 +568,6 @@ void CKeybindManager::toggleActiveFloating(std::string args) {
if (!PWINDOW)
return;
if (g_pCompositor->windowValidMapped(PWINDOW)) {
// remove drag status
g_pInputManager->currentlyDraggedWindow = nullptr;
@@ -502,16 +578,16 @@ void CKeybindManager::toggleActiveFloating(std::string args) {
g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(PWINDOW);
}
}
void CKeybindManager::toggleActivePseudo(std::string args) {
const auto ACTIVEWINDOW = g_pCompositor->m_pLastWindow;
if (!g_pCompositor->windowValidMapped(ACTIVEWINDOW))
if (!ACTIVEWINDOW)
return;
ACTIVEWINDOW->m_bIsPseudotiled = !ACTIVEWINDOW->m_bIsPseudotiled;
if (!ACTIVEWINDOW->m_bIsFullscreen)
g_pLayoutManager->getCurrentLayout()->recalculateWindow(ACTIVEWINDOW);
}
@@ -533,16 +609,20 @@ void CKeybindManager::changeworkspace(std::string args) {
internal = true;
} else if (args.find("previous") == 0) {
const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(
g_pCompositor->m_pLastMonitor->activeWorkspace);
const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
// Do nothing if there's no previous workspace, otherwise switch to it.
if (PCURRENTWORKSPACE->m_iPrevWorkspaceID == -1) {
Debug::log(LOG, "No previous workspace to change to");
return;
}
else {
} else {
workspaceToChangeTo = PCURRENTWORKSPACE->m_iPrevWorkspaceID;
if (const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(workspaceToChangeTo); PWORKSPACETOCHANGETO)
workspaceName = PWORKSPACETOCHANGETO->m_szName;
else
workspaceName = std::to_string(workspaceToChangeTo);
isSwitchingToPrevious = true;
// If the previous workspace ID isn't reset, cycles can form when continually going
@@ -562,15 +642,20 @@ void CKeybindManager::changeworkspace(std::string args) {
// Workspace_back_and_forth being enabled means that an attempt to switch to
// the current workspace will instead switch to the previous.
const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(
g_pCompositor->m_pLastMonitor->activeWorkspace);
const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
static auto *const PBACKANDFORTH = &g_pConfigManager->getConfigValuePtr("binds:workspace_back_and_forth")->intValue;
if (*PBACKANDFORTH
&& PCURRENTWORKSPACE->m_iID == workspaceToChangeTo
&& PCURRENTWORKSPACE->m_iPrevWorkspaceID != -1
&& !internal) {
if (*PBACKANDFORTH && PCURRENTWORKSPACE->m_iID == workspaceToChangeTo && PCURRENTWORKSPACE->m_iPrevWorkspaceID != -1 && !internal) {
const auto PPREVWORKSPACE = g_pCompositor->getWorkspaceByID(PCURRENTWORKSPACE->m_iPrevWorkspaceID);
workspaceToChangeTo = PCURRENTWORKSPACE->m_iPrevWorkspaceID;
if (PPREVWORKSPACE)
workspaceName = PPREVWORKSPACE->m_szName;
else
workspaceName = std::to_string(workspaceToChangeTo);
isSwitchingToPrevious = true;
// If the previous workspace ID isn't reset, cycles can form when continually going
@@ -578,7 +663,9 @@ void CKeybindManager::changeworkspace(std::string args) {
static auto* const PALLOWWORKSPACECYCLES = &g_pConfigManager->getConfigValuePtr("binds:allow_workspace_cycles")->intValue;
if (!*PALLOWWORKSPACECYCLES)
PCURRENTWORKSPACE->m_iPrevWorkspaceID = -1;
}
} else if (PCURRENTWORKSPACE->m_iID == workspaceToChangeTo && !internal)
return;
// remove constraints
g_pInputManager->unconstrainMouse();
@@ -604,6 +691,13 @@ void CKeybindManager::changeworkspace(std::string args) {
if (!g_pCompositor->isWorkspaceVisible(workspaceToChangeTo)) {
const auto OLDWORKSPACEID = PMONITOR->activeWorkspace;
// fix pinned windows
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_iWorkspaceID == PMONITOR->activeWorkspace && w->m_bPinned) {
w->m_iWorkspaceID = workspaceToChangeTo;
}
}
// change it
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
PMONITOR->activeWorkspace = workspaceToChangeTo;
@@ -624,7 +718,8 @@ void CKeybindManager::changeworkspace(std::string args) {
}
// If the monitor is not the one our cursor's at, warp to it.
if (PMONITOR != g_pCompositor->getMonitorFromCursor()) {
const bool anotherMonitor = PMONITOR != g_pCompositor->getMonitorFromCursor();
if (anotherMonitor) {
Vector2D middle = PMONITOR->vecPosition + PMONITOR->vecSize / 2.f;
g_pCompositor->warpCursorTo(middle);
}
@@ -639,7 +734,20 @@ void CKeybindManager::changeworkspace(std::string args) {
Debug::log(LOG, "Changed to workspace %i", workspaceToChangeTo);
// focus
if (const auto PWINDOW = PWORKSPACETOCHANGETO->getLastFocusedWindow(); PWINDOW) {
// warp and focus
if (anotherMonitor)
g_pCompositor->warpCursorTo(PWINDOW->m_vRealPosition.vec() + PWINDOW->m_vRealSize.vec() / 2.f);
g_pCompositor->focusWindow(PWINDOW, g_pXWaylandManager->getWindowSurface(PWINDOW));
if (g_pCompositor->cursorOnReservedArea()) // fix focus on bars etc
g_pInputManager->refocus();
} else if (g_pCompositor->getWindowsOnWorkspace(PWORKSPACETOCHANGETO->m_iID) > 0)
g_pInputManager->refocus();
// set the new monitor as the last (no warps would bug otherwise)
g_pCompositor->m_pLastMonitor = g_pCompositor->getMonitorFromID(PWORKSPACETOCHANGETO->m_iMonitorID);
// mark the monitor dirty
g_pHyprRenderer->damageMonitor(PMONITOR);
@@ -648,7 +756,9 @@ void CKeybindManager::changeworkspace(std::string args) {
}
// Workspace doesn't exist, create and switch
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
const auto BOUNDMON = g_pConfigManager->getBoundMonitorForWS(workspaceName);
const auto PMONITOR = BOUNDMON ? BOUNDMON : g_pCompositor->getMonitorFromCursor();
const auto OLDWORKSPACE = PMONITOR->activeWorkspace;
@@ -659,7 +769,7 @@ void CKeybindManager::changeworkspace(std::string args) {
if (const auto POLDWORKSPACE = g_pCompositor->getWorkspaceByID(OLDWORKSPACE); POLDWORKSPACE)
POLDWORKSPACE->startAnim(false, ANIMTOLEFT);
const auto PWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(PMONITOR->ID, workspaceName, workspaceToChangeTo == SPECIAL_WORKSPACE_ID)).get();
const auto PWORKSPACE = g_pCompositor->createNewWorkspace(workspaceToChangeTo, PMONITOR->ID, workspaceName);
if (!isSwitchingToPrevious)
// Remember previous workspace.
@@ -668,15 +778,15 @@ void CKeybindManager::changeworkspace(std::string args) {
// start anim on new workspace
PWORKSPACE->startAnim(true, ANIMTOLEFT);
// We are required to set the name here immediately
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
wlr_ext_workspace_handle_v1_set_name(PWORKSPACE->m_pWlrHandle, workspaceName.c_str());
PWORKSPACE->m_iID = workspaceToChangeTo;
PWORKSPACE->m_iMonitorID = PMONITOR->ID;
PMONITOR->specialWorkspaceOpen = false;
// fix pinned windows
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_iWorkspaceID == PMONITOR->activeWorkspace && w->m_bPinned) {
w->m_iWorkspaceID = workspaceToChangeTo;
}
}
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
PMONITOR->activeWorkspace = workspaceToChangeTo;
else
@@ -689,6 +799,12 @@ void CKeybindManager::changeworkspace(std::string args) {
// mark the monitor dirty
g_pHyprRenderer->damageMonitor(PMONITOR);
// some stuf with the cursor and focus
if (g_pCompositor->m_pLastMonitor != PMONITOR)
g_pCompositor->warpCursorTo(PMONITOR->vecPosition + PMONITOR->vecSize / 2.f);
g_pCompositor->m_pLastMonitor = PMONITOR;
// focus (clears the last)
g_pInputManager->refocus();
@@ -701,7 +817,7 @@ void CKeybindManager::changeworkspace(std::string args) {
void CKeybindManager::fullscreenActive(std::string args) {
const auto PWINDOW = g_pCompositor->m_pLastWindow;
if (!g_pCompositor->windowValidMapped(PWINDOW))
if (!PWINDOW)
return;
if (PWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
@@ -721,7 +837,7 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
PWINDOW = g_pCompositor->m_pLastWindow;
}
if (!g_pCompositor->windowValidMapped(PWINDOW))
if (!PWINDOW)
return;
const auto OLDWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
@@ -735,8 +851,8 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
return;
}
auto PSAVEDSIZE = PWINDOW->m_vRealSize.vec();
auto PSAVEDPOS = PWINDOW->m_vRealPosition.vec();
auto PSAVEDSIZE = PWINDOW->m_vRealSize.goalv();
auto PSAVEDPOS = PWINDOW->m_vRealPosition.goalv();
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
@@ -758,17 +874,13 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
PWINDOW->moveToWorkspace(PWORKSPACE->m_iID);
PWINDOW->m_iMonitorID = PWORKSPACE->m_iMonitorID;
PWINDOW->m_bIsFullscreen = false;
if (PWORKSPACE->m_bHasFullscreenWindow) {
g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID)->m_bIsFullscreen = false;
PWORKSPACE->m_bHasFullscreenWindow = false;
}
if (PWINDOW->m_bIsFullscreen) {
PWINDOW->m_bIsFullscreen = false;
PSAVEDPOS = PSAVEDPOS + Vector2D(10, 10);
PSAVEDSIZE = PSAVEDSIZE - Vector2D(20, 20);
g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL);
}
if (PWORKSPACE->m_bHasFullscreenWindow) {
g_pCompositor->setWindowFullscreen(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), false, FULLSCREEN_FULL);
}
// Hack: So that the layout doesnt find our window at the cursor
@@ -778,7 +890,7 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
// and restore it
if (PWINDOW->m_bIsFloating) {
PWINDOW->m_vRealSize.setValue(PSAVEDSIZE);
PWINDOW->m_vRealSize.setValueAndWarp(PSAVEDSIZE);
PWINDOW->m_vRealPosition.setValueAndWarp(PSAVEDPOS - g_pCompositor->getMonitorFromID(OLDWORKSPACE->m_iMonitorID)->vecPosition + g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID)->vecPosition);
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
}
@@ -792,10 +904,10 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
for (auto& m : g_pCompositor->m_vMonitors)
m->specialWorkspaceOpen = false;
} else {
g_pCompositor->focusWindow(PWINDOW);
}
g_pInputManager->refocus();
PWINDOW->updateToplevel();
}
@@ -813,7 +925,7 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
PWINDOW = g_pCompositor->m_pLastWindow;
}
if (!g_pCompositor->windowValidMapped(PWINDOW))
if (!PWINDOW)
return;
int workspaceToMoveTo = 0;
@@ -834,7 +946,12 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
// may be null until later!
auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceToMoveTo);
const auto PMONITORNEW = PWORKSPACE ? g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID) : PMONITOR;
auto PMONITORNEW = PWORKSPACE ? g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID) : PMONITOR;
if (!PWORKSPACE) {
const auto BOUNDMON = g_pConfigManager->getBoundMonitorForWS(workspaceName);
if (BOUNDMON)
PMONITORNEW = BOUNDMON;
}
const auto OLDWORKSPACEIDONMONITOR = PMONITORNEW->activeWorkspace;
const auto OLDWORKSPACEIDRETURN = PMONITOR->activeWorkspace;
@@ -863,6 +980,9 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
g_pEventManager->m_bIgnoreEvents = false;
// manually post event cuz it got ignored above
g_pEventManager->postEvent(SHyprIPCEvent{"movewindow", getFormat("%x,%s", PWINDOW, PWORKSPACE->m_szName.c_str())});
g_pInputManager->refocus();
}
@@ -887,35 +1007,36 @@ void CKeybindManager::moveFocusTo(std::string args) {
if (PLASTWINDOW->m_iWorkspaceID == PWINDOWTOCHANGETO->m_iWorkspaceID && PLASTWINDOW->m_bIsFullscreen) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PLASTWINDOW->m_iWorkspaceID);
const auto FSMODE = PWORKSPACE->m_efFullscreenMode;
if (!PWINDOWTOCHANGETO->m_bPinned)
g_pCompositor->setWindowFullscreen(PLASTWINDOW, false, FULLSCREEN_FULL);
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
if (!PWINDOWTOCHANGETO->m_bPinned)
g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE);
} else {
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
Vector2D middle = PWINDOWTOCHANGETO->m_vRealPosition.goalv() + PWINDOWTOCHANGETO->m_vRealSize.goalv() / 2.f;
g_pCompositor->warpCursorTo(middle);
g_pCompositor->m_pLastMonitor = g_pCompositor->getMonitorFromID(PWINDOWTOCHANGETO->m_iMonitorID); // update last monitor
if (PLASTWINDOW->m_iMonitorID != PWINDOWTOCHANGETO->m_iMonitorID) {
// event
const auto PNEWMON = g_pCompositor->getMonitorFromID(PWINDOWTOCHANGETO->m_iMonitorID);
const auto PNEWWS = g_pCompositor->getWorkspaceByID(PNEWMON->activeWorkspace);
g_pEventManager->postEvent(SHyprIPCEvent{"focusedmon", PNEWMON->szName + "," + PNEWWS->m_szName});
g_pCompositor->m_pLastMonitor = PNEWMON;
}
}
};
if (!g_pCompositor->windowValidMapped(PLASTWINDOW)) {
const auto PWINDOWTOCHANGETO = g_pCompositor->getFirstWindowOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace);
if (!PWINDOWTOCHANGETO)
return;
switchToWindow(PWINDOWTOCHANGETO);
return;
}
const auto PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
if (PWINDOWTOCHANGETO) {
switchToWindow(PWINDOWTOCHANGETO);
} else {
const auto PWINDOWNEXT = g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW);
const auto PWINDOWNEXT = g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true);
if (PWINDOWNEXT) {
switchToWindow(PWINDOWNEXT);
}
@@ -954,12 +1075,12 @@ void CKeybindManager::moveActiveTo(std::string args) {
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow;
if (!g_pCompositor->windowValidMapped(PLASTWINDOW) || PLASTWINDOW->m_bIsFullscreen)
if (!PLASTWINDOW || PLASTWINDOW->m_bIsFullscreen)
return;
const auto PWINDOWTOCHANGETO = g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
if (!g_pCompositor->windowValidMapped(PWINDOWTOCHANGETO))
if (!PWINDOWTOCHANGETO)
return;
g_pLayoutManager->getCurrentLayout()->switchWindows(PLASTWINDOW, PWINDOWTOCHANGETO);
@@ -1005,7 +1126,7 @@ void CKeybindManager::alterSplitRatio(std::string args) {
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow;
if (!g_pCompositor->windowValidMapped(PLASTWINDOW))
if (!PLASTWINDOW)
return;
g_pLayoutManager->getCurrentLayout()->alterSplitRatioBy(PLASTWINDOW, splitratio);
@@ -1035,7 +1156,7 @@ void CKeybindManager::moveCursorToCorner(std::string arg) {
const auto PWINDOW = g_pCompositor->m_pLastWindow;
if (!g_pCompositor->windowValidMapped(PWINDOW))
if (!PWINDOW)
return;
switch (CORNER) {
@@ -1119,18 +1240,7 @@ void CKeybindManager::exitHyprland(std::string argz) {
}
void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) {
CMonitor* PMONITOR = nullptr;
try {
if (!isNumber(args) && !isDirection(args)) {
PMONITOR = g_pCompositor->getMonitorFromName(args);
} else {
PMONITOR = isDirection(args) ? g_pCompositor->getMonitorInDirection(args[0]) : g_pCompositor->getMonitorFromID(std::stoi(args));
}
} catch (std::exception& e) {
Debug::log(LOG, "moveCurrentWorkspaceToMonitor: caught exception in monitor", e.what());
return;
}
CMonitor* PMONITOR = g_pCompositor->getMonitorFromString(args);
if (!PMONITOR)
return;
@@ -1151,19 +1261,7 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
std::string workspace = args.substr(0, args.find_first_of(' '));
std::string monitor = args.substr(args.find_first_of(' ') + 1);
CMonitor* PMONITOR = nullptr;
try {
if (!isNumber(monitor) && !isDirection(monitor)) {
PMONITOR = g_pCompositor->getMonitorFromName(monitor);
} else {
PMONITOR = isDirection(monitor) ? g_pCompositor->getMonitorInDirection(monitor[0]) : g_pCompositor->getMonitorFromID(std::stoi(monitor));
}
} catch (std::exception& e) {
Debug::log(LOG, "moveWorkspaceToMonitor: caught exception in monitor", e.what());
return;
}
const auto PMONITOR = g_pCompositor->getMonitorFromString(monitor);
if (!PMONITOR){
Debug::log(ERR, "Ignoring moveWorkspaceToMonitor: monitor doesnt exist");
@@ -1218,6 +1316,11 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false);
}
}
if (const auto PWINDOW = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace)->getLastFocusedWindow(); PWINDOW)
g_pCompositor->focusWindow(PWINDOW);
else
g_pInputManager->refocus();
} else {
auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID);
@@ -1231,16 +1334,19 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
PSPECIALWORKSPACE->startAnim(true, true);
PSPECIALWORKSPACE->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
}
if (const auto PWINDOW = PSPECIALWORKSPACE->getLastFocusedWindow(); PWINDOW)
g_pCompositor->focusWindow(PWINDOW);
else
g_pInputManager->refocus();
}
}
void CKeybindManager::forceRendererReload(std::string args) {
bool overAgain = false;
for (auto& m : g_pCompositor->m_vMonitors) {
auto rule = g_pConfigManager->getMonitorRuleFor(m->szName);
auto rule = g_pConfigManager->getMonitorRuleFor(m->szName, m->output->description ? m->output->description : "");
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule, true)) {
overAgain = true;
break;
@@ -1252,7 +1358,7 @@ void CKeybindManager::forceRendererReload(std::string args) {
}
void CKeybindManager::resizeActive(std::string args) {
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
if (!g_pCompositor->m_pLastWindow || g_pCompositor->m_pLastWindow->m_bIsFullscreen)
return;
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, g_pCompositor->m_pLastWindow->m_vRealSize.goalv());
@@ -1260,11 +1366,11 @@ void CKeybindManager::resizeActive(std::string args) {
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - g_pCompositor->m_pLastWindow->m_vRealSize.goalv());
if (g_pCompositor->m_pLastWindow->m_vRealSize.goalv().x > 1 && g_pCompositor->m_pLastWindow->m_vRealSize.goalv().y > 1)
g_pCompositor->m_pLastWindow->m_bHidden = false;
g_pCompositor->m_pLastWindow->setHidden(false);
}
void CKeybindManager::moveActive(std::string args) {
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
if (!g_pCompositor->m_pLastWindow || g_pCompositor->m_pLastWindow->m_bIsFullscreen)
return;
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, g_pCompositor->m_pLastWindow->m_vRealPosition.goalv());
@@ -1284,6 +1390,9 @@ void CKeybindManager::moveWindow(std::string args) {
return;
}
if (PWINDOW->m_bIsFullscreen)
return;
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealPosition.goalv());
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PWINDOW->m_vRealPosition.goalv(), PWINDOW);
@@ -1301,18 +1410,18 @@ void CKeybindManager::resizeWindow(std::string args) {
return;
}
if (PWINDOW->m_bIsFullscreen)
return;
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize.goalv());
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize.goalv(), PWINDOW);
if (PWINDOW->m_vRealSize.goalv().x > 1 && PWINDOW->m_vRealSize.goalv().y > 1)
PWINDOW->m_bHidden = false;
PWINDOW->setHidden(false);
}
void CKeybindManager::circleNext(std::string arg) {
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
return;
auto switchToWindow = [&](CWindow* PWINDOWTOCHANGETO) {
if (PWINDOWTOCHANGETO == g_pCompositor->m_pLastWindow || !PWINDOWTOCHANGETO)
return;
@@ -1320,10 +1429,13 @@ void CKeybindManager::circleNext(std::string arg) {
if (g_pCompositor->m_pLastWindow->m_iWorkspaceID == PWINDOWTOCHANGETO->m_iWorkspaceID && g_pCompositor->m_pLastWindow->m_bIsFullscreen) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastWindow->m_iWorkspaceID);
const auto FSMODE = PWORKSPACE->m_efFullscreenMode;
if (!PWINDOWTOCHANGETO->m_bPinned)
g_pCompositor->setWindowFullscreen(g_pCompositor->m_pLastWindow, false, FULLSCREEN_FULL);
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
if (!PWINDOWTOCHANGETO->m_bPinned)
g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE);
} else {
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
@@ -1332,10 +1444,21 @@ void CKeybindManager::circleNext(std::string arg) {
}
};
if (!g_pCompositor->m_pLastWindow) {
// if we have a clear focus, find the first window and get the next focusable.
if (g_pCompositor->getWindowsOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace) > 0) {
const auto PWINDOW = g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->getFirstWindowOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace), true);
switchToWindow(PWINDOW);
}
return;
}
if (arg == "last" || arg == "l" || arg == "prev" || arg == "p")
switchToWindow(g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow));
switchToWindow(g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow, true));
else
switchToWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow));
switchToWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow, true));
}
void CKeybindManager::focusWindow(std::string regexp) {
@@ -1346,8 +1469,6 @@ void CKeybindManager::focusWindow(std::string regexp) {
Debug::log(LOG, "Focusing to window name: %s", PWINDOW->m_szTitle.c_str());
changeworkspace("[internal]" + std::to_string(PWINDOW->m_iWorkspaceID));
g_pCompositor->focusWindow(PWINDOW);
const auto MIDPOINT = PWINDOW->m_vRealPosition.goalv() + PWINDOW->m_vRealSize.goalv() / 2.f;
@@ -1359,6 +1480,7 @@ void CKeybindManager::setSubmap(std::string submap) {
if (submap == "reset" || submap == "") {
m_szCurrentSelectedSubmap = "";
Debug::log(LOG, "Reset active submap to the default one.");
g_pEventManager->postEvent(SHyprIPCEvent{"submap", ""});
return;
}
@@ -1366,6 +1488,7 @@ void CKeybindManager::setSubmap(std::string submap) {
if (k.submap == submap) {
m_szCurrentSelectedSubmap = submap;
Debug::log(LOG, "Changed keybind submap to %s", submap.c_str());
g_pEventManager->postEvent(SHyprIPCEvent{"submap", submap});
return;
}
}
@@ -1458,7 +1581,7 @@ void CKeybindManager::layoutmsg(std::string msg) {
void CKeybindManager::toggleOpaque(std::string unused) {
const auto PWINDOW = g_pCompositor->m_pLastWindow;
if (!g_pCompositor->windowValidMapped(PWINDOW))
if (!PWINDOW)
return;
PWINDOW->m_sAdditionalConfigData.forceOpaque = !PWINDOW->m_sAdditionalConfigData.forceOpaque;
@@ -1467,11 +1590,22 @@ void CKeybindManager::toggleOpaque(std::string unused) {
}
void CKeybindManager::dpms(std::string arg) {
bool enable = arg == "on";
bool enable = arg.find("on") == 0;
std::string port = "";
if (arg.find_first_of(' ') != std::string::npos) {
port = arg.substr(arg.find_first_of(' ') + 1);
}
for (auto& m : g_pCompositor->m_vMonitors) {
if (!port.empty() && m->szName != port)
continue;
wlr_output_enable(m->output, enable);
m->dpmsStatus = enable;
if (!wlr_output_commit(m->output)) {
Debug::log(ERR, "Couldn't commit output %s", m->szName.c_str());
}
@@ -1487,7 +1621,7 @@ void CKeybindManager::swapnext(std::string arg) {
CWindow* toSwap = nullptr;
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
if (!g_pCompositor->m_pLastWindow)
return;
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow;
@@ -1495,16 +1629,16 @@ void CKeybindManager::swapnext(std::string arg) {
const auto PLASTCYCLED = g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow->m_pLastCycledWindow) && g_pCompositor->m_pLastWindow->m_pLastCycledWindow->m_iWorkspaceID == PLASTWINDOW->m_iWorkspaceID ? g_pCompositor->m_pLastWindow->m_pLastCycledWindow : nullptr;
if (arg == "last" || arg == "l" || arg == "prev" || arg == "p")
toSwap = g_pCompositor->getPrevWindowOnWorkspace(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW);
toSwap = g_pCompositor->getPrevWindowOnWorkspace(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW, true);
else
toSwap = g_pCompositor->getNextWindowOnWorkspace(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW);
toSwap = g_pCompositor->getNextWindowOnWorkspace(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW, true);
// sometimes we may come back to ourselves.
if (toSwap == PLASTWINDOW) {
if (arg == "last" || arg == "l" || arg == "prev" || arg == "p")
toSwap = g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW);
toSwap = g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW), true;
else
toSwap = g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW);
toSwap = g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true);
}
g_pLayoutManager->getCurrentLayout()->switchWindows(PLASTWINDOW, toSwap);
@@ -1526,3 +1660,61 @@ void CKeybindManager::swapActiveWorkspaces(std::string args) {
g_pCompositor->swapActiveWorkspaces(PMON1, PMON2);
}
void CKeybindManager::pinActive(std::string args) {
if (!g_pCompositor->m_pLastWindow || !g_pCompositor->m_pLastWindow->m_bIsFloating || g_pCompositor->m_pLastWindow->m_bIsFullscreen)
return;
g_pCompositor->m_pLastWindow->m_bPinned = !g_pCompositor->m_pLastWindow->m_bPinned;
g_pCompositor->m_pLastWindow->m_iWorkspaceID = g_pCompositor->getMonitorFromID(g_pCompositor->m_pLastWindow->m_iMonitorID)->activeWorkspace;
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastWindow->m_iWorkspaceID);
PWORKSPACE->m_pLastFocusedWindow = g_pCompositor->vectorToWindowTiled(g_pInputManager->getMouseCoordsInternal());
}
void CKeybindManager::mouse(std::string args) {
const auto TRUEARG = args.substr(1);
const auto PRESSED = args[0] == '1';
if (TRUEARG == "movewindow") {
if (PRESSED) {
g_pKeybindManager->m_bIsMouseBindActive = true;
g_pInputManager->currentlyDraggedWindow = g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal());
g_pInputManager->dragMode = MBIND_MOVE;
g_pLayoutManager->getCurrentLayout()->onBeginDragWindow();
} else {
g_pKeybindManager->m_bIsMouseBindActive = false;
if (g_pInputManager->currentlyDraggedWindow) {
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
g_pInputManager->currentlyDraggedWindow = nullptr;
g_pInputManager->dragMode = MBIND_INVALID;
}
}
} else if (TRUEARG == "resizewindow") {
if (PRESSED) {
g_pKeybindManager->m_bIsMouseBindActive = true;
g_pInputManager->currentlyDraggedWindow = g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal());
g_pInputManager->dragMode = MBIND_RESIZE;
g_pLayoutManager->getCurrentLayout()->onBeginDragWindow();
} else {
g_pKeybindManager->m_bIsMouseBindActive = false;
if (g_pInputManager->currentlyDraggedWindow) {
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
g_pInputManager->currentlyDraggedWindow = nullptr;
g_pInputManager->dragMode = MBIND_INVALID;
}
}
}
}
void CKeybindManager::bringActiveToTop(std::string args) {
if (g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow->m_bIsFloating)
g_pCompositor->moveWindowToTop(g_pCompositor->m_pLastWindow);
}

View File

@@ -18,6 +18,7 @@ struct SKeybind {
std::string submap = "";
bool release = false;
bool repeat = false;
bool mouse = false;
// DO NOT INITIALIZE
bool shadowed = false;
@@ -37,6 +38,7 @@ public:
bool onKeyEvent(wlr_keyboard_key_event*, SKeyboard*);
bool onAxisEvent(wlr_pointer_axis_event*);
bool onMouseEvent(wlr_pointer_button_event*);
void onSwitchEvent(const std::string&);
void addKeybind(SKeybind);
void removeKeybind(uint32_t, const std::string&);
@@ -63,6 +65,8 @@ private:
uint32_t m_uLastCode = 0;
uint32_t m_uLastMouseCode = 0;
bool m_bIsMouseBindActive = false;
int m_iPassPressed = -1; // used for pass
CTimer m_tScrollTimer;
@@ -75,9 +79,11 @@ private:
xkb_state* m_pXKBTranslationState = nullptr;
void updateXKBTranslationState();
bool ensureMouseBindState();
// -------------- Dispatchers -------------- //
static void killActive(std::string);
static void kill(std::string);
static void spawn(std::string);
static void toggleActiveFloating(std::string);
static void toggleActivePseudo(std::string);
@@ -112,6 +118,9 @@ private:
static void dpms(std::string);
static void swapnext(std::string);
static void swapActiveWorkspaces(std::string);
static void pinActive(std::string);
static void mouse(std::string);
static void bringActiveToTop(std::string);
friend class CCompositor;
friend class CInputManager;

View File

@@ -7,6 +7,9 @@ int slowUpdate = 0;
int handleTimer(void* data) {
const auto PTM = (CThreadManager*)data;
static auto *const PDISABLECFGRELOAD = &g_pConfigManager->getConfigValuePtr("misc:disable_autoreload")->intValue;
if (*PDISABLECFGRELOAD != 1)
g_pConfigManager->tick();
wl_event_source_timer_update(PTM->m_esConfigTimer, 1000);
@@ -19,8 +22,6 @@ CThreadManager::CThreadManager() {
HyprCtl::startHyprCtlSocket();
g_pCompositor->startHyprCtlTick();
m_esConfigTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, handleTimer, this);
wl_event_source_timer_update(m_esConfigTimer, 1000);

View File

@@ -3,7 +3,7 @@
#include "../events/Events.hpp"
CHyprXWaylandManager::CHyprXWaylandManager() {
if (XWAYLAND) {
#ifndef NO_XWAYLAND
m_sWLRXWayland = wlr_xwayland_create(g_pCompositor->m_sWLDisplay, g_pCompositor->m_sWLRCompositor, 1);
if (!m_sWLRXWayland) {
@@ -17,7 +17,9 @@ CHyprXWaylandManager::CHyprXWaylandManager() {
setenv("DISPLAY", m_sWLRXWayland->display_name, 1);
Debug::log(LOG, "CHyprXWaylandManager started on display %s", m_sWLRXWayland->display_name);
}
#else
unsetenv("DISPLAY"); // unset DISPLAY so that X11 apps do not try to start on a different/invalid DISPLAY
#endif
}
CHyprXWaylandManager::~CHyprXWaylandManager() {
@@ -32,9 +34,12 @@ wlr_surface* CHyprXWaylandManager::getWindowSurface(CWindow* pWindow) {
}
void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate) {
if (!pSurface)
return;
if (wlr_surface_is_xdg_surface(pSurface)) {
const auto PSURF = wlr_xdg_surface_from_wlr_surface(pSurface);
if (PSURF->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
if (PSURF && PSURF->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
wlr_xdg_toplevel_set_activated(PSURF->toplevel, activate);
}
} else if (wlr_surface_is_xwayland_surface(pSurface)) {
@@ -48,25 +53,41 @@ void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate)
void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) {
if (pWindow->m_bIsX11) {
if (pWindow->m_uSurface.xwayland->minimized)
if (activate) {
wlr_xwayland_surface_set_minimized(pWindow->m_uSurface.xwayland, false);
wlr_xwayland_surface_restack(pWindow->m_uSurface.xwayland, NULL, XCB_STACK_MODE_ABOVE);
}
wlr_xwayland_surface_activate(pWindow->m_uSurface.xwayland, activate);
wlr_xwayland_surface_restack(pWindow->m_uSurface.xwayland, NULL, XCB_STACK_MODE_ABOVE);
}
else
wlr_xdg_toplevel_set_activated(pWindow->m_uSurface.xdg->toplevel, activate);
if (activate) {
g_pCompositor->m_pLastFocus = getWindowSurface(pWindow);
g_pCompositor->m_pLastWindow = pWindow;
}
if (!pWindow->m_bPinned)
g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID)->m_pLastFocusedWindow = pWindow;
}
void CHyprXWaylandManager::getGeometryForWindow(CWindow* pWindow, wlr_box* pbox) {
if (pWindow->m_bIsX11) {
const auto SIZEHINTS = pWindow->m_uSurface.xwayland->size_hints;
if (SIZEHINTS && pWindow->m_iX11Type != 2) {
pbox->x = SIZEHINTS->x;
pbox->y = SIZEHINTS->y;
pbox->width = SIZEHINTS->width;
pbox->height = SIZEHINTS->height;
} else {
pbox->x = pWindow->m_uSurface.xwayland->x;
pbox->y = pWindow->m_uSurface.xwayland->y;
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);
}

View File

@@ -2,16 +2,18 @@
#include "../../Compositor.hpp"
void CInputManager::onMouseMoved(wlr_pointer_motion_event* e) {
float sensitivity = g_pConfigManager->getFloat("general:sensitivity");
static auto *const PSENS = &g_pConfigManager->getConfigValuePtr("general:sensitivity")->floatValue;
static auto *const PNOACCEL = &g_pConfigManager->getConfigValuePtr("input:force_no_accel")->intValue;
static auto* const PSENSTORAW = &g_pConfigManager->getConfigValuePtr("general:apply_sens_to_raw")->intValue;
const auto DELTA = g_pConfigManager->getInt("input:force_no_accel") == 1 ? Vector2D(e->unaccel_dx, e->unaccel_dy) : Vector2D(e->delta_x, e->delta_y);
const auto DELTA = *PNOACCEL == 1 ? Vector2D(e->unaccel_dx, e->unaccel_dy) : Vector2D(e->delta_x, e->delta_y);
if (g_pConfigManager->getInt("general:apply_sens_to_raw") == 1)
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x * sensitivity, DELTA.y * sensitivity, e->unaccel_dx * sensitivity, e->unaccel_dy * sensitivity);
if (*PSENSTORAW == 1)
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x * *PSENS, DELTA.y * *PSENS, e->unaccel_dx * *PSENS, e->unaccel_dy * *PSENS);
else
wlr_relative_pointer_manager_v1_send_relative_motion(g_pCompositor->m_sWLRRelPointerMgr, g_pCompositor->m_sSeat.seat, (uint64_t)e->time_msec * 1000, DELTA.x, DELTA.y, e->unaccel_dx, e->unaccel_dy);
wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, DELTA.x * sensitivity, DELTA.y * sensitivity);
wlr_cursor_move(g_pCompositor->m_sWLRCursor, &e->pointer->base, DELTA.x * *PSENS, DELTA.y * *PSENS);
mouseMoveUnified(e->time_msec);
@@ -27,14 +29,17 @@ void CInputManager::onMouseWarp(wlr_pointer_motion_absolute_event* e) {
}
void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
static auto *const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->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;
if (!g_pCompositor->m_bReadyToProcess)
m_pFoundSurfaceToFocus = nullptr;
m_pFoundLSToFocus = nullptr;
m_pFoundWindowToFocus = nullptr;
if (!g_pCompositor->m_bReadyToProcess || g_pCompositor->m_bIsShuttingDown)
return;
if (!g_pCompositor->m_sSeat.mouse) {
@@ -138,18 +143,28 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
if (!foundSurface)
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &surfaceCoords, &pFoundLayerSurface);
if (!foundSurface)
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface);
// then, we check if the workspace doesnt have a fullscreen window
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) {
pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow);
surfacePos = pFoundWindow->m_vRealPosition.vec();
if (!pFoundWindow) {
// what the fuck, somehow happens occasionally??
PWORKSPACE->m_bHasFullscreenWindow = false;
return;
}
// only check floating because tiled cant be over fullscreen
for (auto w = g_pCompositor->m_vWindows.rbegin(); w != g_pCompositor->m_vWindows.rend(); w++) {
wlr_box box = {(*w)->m_vRealPosition.vec().x, (*w)->m_vRealPosition.vec().y, (*w)->m_vRealSize.vec().x, (*w)->m_vRealSize.vec().y};
if ((((*w)->m_bIsFloating && (*w)->m_bIsMapped && (*w)->m_bCreatedOverFullscreen) || ((*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden) {
if ((((*w)->m_bIsFloating && (*w)->m_bIsMapped && ((*w)->m_bCreatedOverFullscreen || (*w)->m_bPinned)) || ((*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->isHidden()) {
pFoundWindow = (*w).get();
break;
}
}
if (!pFoundWindow->m_bIsX11) {
foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords);
@@ -158,14 +173,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow);
surfacePos = pFoundWindow->m_vRealPosition.vec();
}
break;
}
}
}
if (!foundSurface)
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface);
// then windows
if (!foundSurface) {
@@ -256,9 +264,16 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
}
}
// set the values for use
if (refocus) {
m_pFoundLSToFocus = pFoundLayerSurface;
m_pFoundWindowToFocus = pFoundWindow;
m_pFoundSurfaceToFocus = foundSurface;
}
if (pFoundWindow) {
if (*PFOLLOWMOUSE != 1 && !refocus) {
if (pFoundWindow != g_pCompositor->m_pLastWindow && g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) && g_pCompositor->m_pLastWindow->m_bIsFloating != pFoundWindow->m_bIsFloating && *PFLOATBEHAVIOR) {
if (pFoundWindow != g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow && ((pFoundWindow->m_bIsFloating && *PFLOATBEHAVIOR == 2) || (g_pCompositor->m_pLastWindow->m_bIsFloating != pFoundWindow->m_bIsFloating && *PFLOATBEHAVIOR != 0))) {
// enter if change floating style
if (*PFOLLOWMOUSE != 3 && allowKeyboardRefocus)
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
@@ -267,26 +282,35 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
}
if (pFoundWindow == g_pCompositor->m_pLastWindow && foundSurface != g_pCompositor->m_pLastFocus) {
// we changed the subsurface
if (pFoundWindow == g_pCompositor->m_pLastWindow) {
if (foundSurface != g_pCompositor->m_pLastFocus || m_bLastFocusOnLS) {
// ^^^ changed the subsurface ^^^ came back from a LS
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
}
}
if (*PFOLLOWONDND && m_sDrag.dragIcon) {
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
}
if (*PFOLLOWMOUSE != 0 || pFoundWindow == g_pCompositor->m_pLastWindow)
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, time, surfaceLocal.x, surfaceLocal.y);
m_bLastFocusOnLS = false;
return; // don't enter any new surfaces
} else {
if ((*PFOLLOWMOUSE != 3 && allowKeyboardRefocus) || refocus)
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
}
m_bLastFocusOnLS = false;
} else {
if (pFoundLayerSurface && pFoundLayerSurface->layerSurface->current.keyboard_interactive && *PFOLLOWMOUSE != 3 && allowKeyboardRefocus) {
g_pCompositor->focusSurface(foundSurface);
g_pCompositor->m_pLastWindow = nullptr; // reset last window as we have a full focus on a LS
}
if (pFoundLayerSurface)
m_bLastFocusOnLS = true;
}
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
@@ -378,25 +402,11 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
refocus();
// if clicked on a floating window make it top
if (g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) && g_pCompositor->m_pLastWindow->m_bIsFloating)
if (g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow->m_bIsFloating)
g_pCompositor->moveWindowToTop(g_pCompositor->m_pLastWindow);
if ((e->button == BTN_LEFT || e->button == BTN_RIGHT) && wlr_keyboard_get_modifiers(PKEYBOARD) == (uint32_t)g_pConfigManager->getInt("general:main_mod_internal")) {
currentlyDraggedWindow = g_pCompositor->windowFromCursor();
dragButton = e->button;
g_pLayoutManager->getCurrentLayout()->onBeginDragWindow();
return;
}
break;
case WLR_BUTTON_RELEASED:
if (currentlyDraggedWindow) {
g_pLayoutManager->getCurrentLayout()->onEndDragWindow();
currentlyDraggedWindow = nullptr;
dragButton = -1;
}
break;
}
@@ -411,7 +421,7 @@ void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) {
case WLR_BUTTON_PRESSED: {
const auto PWINDOW = g_pCompositor->m_pLastWindow;
if (!g_pCompositor->windowValidMapped(PWINDOW)){
if (!PWINDOW) {
Debug::log(ERR, "Cannot kill invalid window!");
break;
}
@@ -431,12 +441,17 @@ void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) {
}
void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
static auto *const PSCROLLFACTOR = &g_pConfigManager->getConfigValuePtr("input:touchpad:scroll_factor")->floatValue;
auto factor = (*PSCROLLFACTOR <= 0.f || e->source != WLR_AXIS_SOURCE_FINGER ? 1.f : *PSCROLLFACTOR);
bool passEvent = g_pKeybindManager->onAxisEvent(e);
wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
if (passEvent) {
wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e->time_msec, e->orientation, e->delta, e->delta_discrete, e->source);
wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e->time_msec, e->orientation, factor * e->delta,
std::round(factor * e->delta_discrete), e->source);
}
}
@@ -658,12 +673,14 @@ void CInputManager::newMouse(wlr_input_device* mouse, bool virt) {
Debug::log(LOG, "New mouse has libinput sens %.2f (%.2f) with accel profile %i (%i)", libinput_device_config_accel_get_speed(LIBINPUTDEV), libinput_device_config_accel_get_default_speed(LIBINPUTDEV), libinput_device_config_accel_get_profile(LIBINPUTDEV), libinput_device_config_accel_get_default_profile(LIBINPUTDEV));
}
setMouseConfigs();
setPointerConfigs();
PMOUSE->hyprListener_destroyMouse.initCallback(&mouse->events.destroy, &Events::listener_destroyMouse, PMOUSE, "Mouse");
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, mouse);
PMOUSE->connected = true;
g_pCompositor->m_sSeat.mouse = PMOUSE;
m_tmrLastCursorMovement.reset();
@@ -671,15 +688,26 @@ void CInputManager::newMouse(wlr_input_device* mouse, bool virt) {
Debug::log(LOG, "New mouse created, pointer WLR: %x", mouse);
}
void CInputManager::setMouseConfigs() {
void CInputManager::setPointerConfigs() {
for (auto& m : m_lMice) {
const auto PMOUSE = &m;
const auto PPOINTER = &m;
auto devname = PMOUSE->name;
auto devname = PPOINTER->name;
transform(devname.begin(), devname.end(), devname.begin(), ::tolower);
const auto HASCONFIG = g_pConfigManager->deviceConfigExists(devname);
if (HASCONFIG) {
const auto ENABLED = g_pConfigManager->getDeviceInt(devname, "enabled");
if (ENABLED && !m.connected) {
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, m.mouse);
m.connected = true;
} else if (!ENABLED && m.connected) {
wlr_cursor_detach_input_device(g_pCompositor->m_sWLRCursor, m.mouse);
m.connected = false;
}
}
if (wlr_input_device_is_libinput(m.mouse)) {
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(m.mouse);
@@ -688,6 +716,11 @@ void CInputManager::setMouseConfigs() {
else
libinput_device_config_click_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "left_handed") : g_pConfigManager->getInt("input:left_handed")) == 0)
libinput_device_config_left_handed_set(LIBINPUTDEV, 0);
else
libinput_device_config_left_handed_set(LIBINPUTDEV, 1);
if (libinput_device_config_middle_emulation_is_available(LIBINPUTDEV)) { // middleclick on r+l mouse button pressed
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "middle_button_emulation") : g_pConfigManager->getInt("input:touchpad:middle_button_emulation")) == 1)
libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED);
@@ -695,6 +728,21 @@ void CInputManager::setMouseConfigs() {
libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
}
const auto SCROLLMETHOD = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "scroll_method") : g_pConfigManager->getString("input:scroll_method");
if (SCROLLMETHOD == "" || SCROLLMETHOD == STRVAL_EMPTY) {
libinput_device_config_scroll_set_method(LIBINPUTDEV, libinput_device_config_scroll_get_default_method(LIBINPUTDEV));
} else if (SCROLLMETHOD == "no_scroll") {
libinput_device_config_scroll_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_SCROLL_NO_SCROLL);
} else if (SCROLLMETHOD == "2fg") {
libinput_device_config_scroll_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_SCROLL_2FG);
} else if (SCROLLMETHOD == "edge") {
libinput_device_config_scroll_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_SCROLL_EDGE);
} else if (SCROLLMETHOD == "on_button_down") {
libinput_device_config_scroll_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN);
} else {
Debug::log(WARN, "Scroll method unknown");
}
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "drag_lock") : g_pConfigManager->getInt("input:touchpad:drag_lock")) == 0)
libinput_device_config_tap_set_drag_lock_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_DRAG_LOCK_DISABLED);
else
@@ -719,10 +767,20 @@ void CInputManager::setMouseConfigs() {
}
const auto LIBINPUTSENS = std::clamp((HASCONFIG ? g_pConfigManager->getDeviceFloat(devname, "sensitivity") : g_pConfigManager->getFloat("input:sensitivity")), -1.f, 1.f);
libinput_device_config_accel_set_profile(LIBINPUTDEV, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
libinput_device_config_accel_set_speed(LIBINPUTDEV, LIBINPUTSENS);
const auto ACCELPROFILE = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "accel_profile") : g_pConfigManager->getString("input:accel_profile");
if (ACCELPROFILE == "" || ACCELPROFILE == STRVAL_EMPTY) {
libinput_device_config_accel_set_profile(LIBINPUTDEV, libinput_device_config_accel_get_default_profile(LIBINPUTDEV));
} else if (ACCELPROFILE == "adaptive") {
libinput_device_config_accel_set_profile(LIBINPUTDEV, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE);
} else if (ACCELPROFILE == "flat") {
libinput_device_config_accel_set_profile(LIBINPUTDEV, LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT);
} else {
Debug::log(WARN, "Unknown acceleration profile, falling back to default");
}
Debug::log(LOG, "Applied config to mouse %s, sens %.2f", m.name.c_str(), LIBINPUTSENS);
}
}
@@ -783,12 +841,17 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar
void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) {
const auto PIMEGRAB = m_sIMERelay.getIMEKeyboardGrab(pKeyboard);
const auto ALLMODS = accumulateModsFromAllKBs();
auto MODS = wlr_keyboard_from_input_device(pKeyboard->keyboard)->modifiers;
MODS.depressed = ALLMODS;
if (PIMEGRAB && PIMEGRAB->pWlrKbGrab && PIMEGRAB->pWlrKbGrab->input_method) {
wlr_input_method_keyboard_grab_v2_set_keyboard(PIMEGRAB->pWlrKbGrab, wlr_keyboard_from_input_device(pKeyboard->keyboard));
wlr_input_method_keyboard_grab_v2_send_modifiers(PIMEGRAB->pWlrKbGrab, &wlr_keyboard_from_input_device(pKeyboard->keyboard)->modifiers);
wlr_input_method_keyboard_grab_v2_send_modifiers(PIMEGRAB->pWlrKbGrab, &MODS);
} else {
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(pKeyboard->keyboard));
wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &wlr_keyboard_from_input_device(pKeyboard->keyboard)->modifiers);
wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &MODS);
}
const auto PWLRKB = wlr_keyboard_from_input_device(pKeyboard->keyboard);
@@ -900,11 +963,7 @@ void CInputManager::unconstrainMouse() {
const auto CONSTRAINTWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
if (CONSTRAINTWINDOW) {
if (CONSTRAINTWINDOW->m_bIsX11) {
wlr_xwayland_surface_activate(CONSTRAINTWINDOW->m_uSurface.xwayland, false);
} else {
wlr_xdg_toplevel_set_activated(CONSTRAINTWINDOW->m_uSurface.xdg->toplevel, false);
}
g_pXWaylandManager->activateSurface(g_pXWaylandManager->getWindowSurface(CONSTRAINTWINDOW), false);
}
wlr_pointer_constraint_v1_send_deactivated(g_pCompositor->m_sSeat.mouse->currentConstraint);
@@ -945,6 +1004,9 @@ uint32_t CInputManager::accumulateModsFromAllKBs() {
uint32_t finalMask = 0;
for (auto& kb : m_lKeyboards) {
if (kb.isVirtual)
continue;
finalMask |= wlr_keyboard_get_modifiers(wlr_keyboard_from_input_device(kb.keyboard));
}
@@ -979,3 +1041,114 @@ void CInputManager::disableAllKeyboards(bool virt) {
k.active = false;
}
}
void CInputManager::newTouchDevice(wlr_input_device* pDevice) {
const auto PNEWDEV = &m_lTouchDevices.emplace_back();
PNEWDEV->pWlrDevice = pDevice;
try {
PNEWDEV->name = std::string(pDevice->name);
} catch(std::exception& e) {
Debug::log(ERR, "Touch Device had no name???"); // logic error
}
setTouchDeviceConfigs();
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, pDevice);
Debug::log(LOG, "New touch device added at %x", PNEWDEV);
PNEWDEV->hyprListener_destroy.initCallback(&pDevice->events.destroy, [&](void* owner, void* data) {
destroyTouchDevice((STouchDevice*)data);
}, PNEWDEV, "TouchDevice");
}
void CInputManager::setTouchDeviceConfigs() {
// The third row is always 0 0 1 and is not expected by `libinput_device_config_calibration_set_matrix`
static const float MATRICES[8][6] = {
{ // normal
1, 0, 0,
0, 1, 0
},
{ // rotation 90°
0, -1, 1,
1, 0, 0
},
{ // rotation 180°
-1, 0, 1,
0, -1, 1
},
{ // rotation 270°
0, 1, 0,
-1, 0, 1
},
{ // flipped
-1, 0, 1,
0, 1, 0
},
{ // flipped + rotation 90°
0, 1, 0,
1, 0, 0
},
{ // flipped + rotation 180°
1, 0, 0,
0, -1, 1
},
{ // flipped + rotation 270°
0, -1, 1,
-1, 0, 1
}
};
for (auto& m : m_lTouchDevices) {
const auto PTOUCHDEV = &m;
auto devname = PTOUCHDEV->name;
transform(devname.begin(), devname.end(), devname.begin(), ::tolower);
const auto HASCONFIG = g_pConfigManager->deviceConfigExists(devname);
if (wlr_input_device_is_libinput(m.pWlrDevice)) {
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(m.pWlrDevice);
const int ROTATION = std::clamp(HASCONFIG ? g_pConfigManager->getDeviceInt(devname, "touch_transform") : g_pConfigManager->getInt("input:touchdevice:transform"), 0, 7);
libinput_device_config_calibration_set_matrix(LIBINPUTDEV, MATRICES[ROTATION]);
const auto OUTPUT = HASCONFIG ? g_pConfigManager->getDeviceString(devname, "touch_output") : g_pConfigManager->getString("input:touchdevice:output");
if (!OUTPUT.empty() && OUTPUT != STRVAL_EMPTY)
PTOUCHDEV->boundOutput = OUTPUT;
else
PTOUCHDEV->boundOutput = "";
}
}
}
void CInputManager::destroyTouchDevice(STouchDevice* pDevice) {
Debug::log(LOG, "Touch device at %x removed", pDevice);
m_lTouchDevices.remove(*pDevice);
}
void CInputManager::newSwitch(wlr_input_device* pDevice) {
const auto PNEWDEV = &m_lSwitches.emplace_back();
PNEWDEV->pWlrDevice = pDevice;
Debug::log(LOG, "New switch with name \"%s\" added", pDevice->name);
PNEWDEV->hyprListener_destroy.initCallback(&pDevice->events.destroy, [&](void* owner, void* data) {
destroySwitch((SSwitchDevice*)owner);
}, PNEWDEV, "SwitchDevice");
const auto PSWITCH = wlr_switch_from_input_device(pDevice);
PNEWDEV->hyprListener_toggle.initCallback(&PSWITCH->events.toggle, [&](void* owner, void* data) {
const auto PDEVICE = (SSwitchDevice*)owner;
const auto NAME = std::string(PDEVICE->pWlrDevice->name);
Debug::log(LOG, "Switch %s fired, triggering binds.", NAME.c_str());
g_pKeybindManager->onSwitchEvent(NAME);
}, PNEWDEV, "SwitchDevice");
}
void CInputManager::destroySwitch(SSwitchDevice* pDevice) {
m_lSwitches.remove(*pDevice);
}

View File

@@ -12,8 +12,16 @@ enum eClickBehaviorMode {
CLICKMODE_KILL
};
enum eMouseBindMode {
MBIND_INVALID = -1,
MBIND_MOVE = 0,
MBIND_RESIZE
};
struct STouchData {
CWindow* touchFocusWindow = nullptr;
SLayerSurface* touchFocusLS = nullptr;
wlr_surface* touchFocusSurface = nullptr;
Vector2D touchSurfaceOrigin;
};
@@ -30,8 +38,12 @@ public:
void newKeyboard(wlr_input_device*);
void newVirtualKeyboard(wlr_input_device*);
void newMouse(wlr_input_device*, bool virt = false);
void newTouchDevice(wlr_input_device*);
void newSwitch(wlr_input_device*);
void destroyTouchDevice(STouchDevice*);
void destroyKeyboard(SKeyboard*);
void destroyMouse(wlr_input_device*);
void destroySwitch(SSwitchDevice*);
void constrainMouse(SMouse*, wlr_pointer_constraint_v1*);
void recheckConstraint(SMouse*);
@@ -42,7 +54,8 @@ public:
void refocus();
void setKeyboardLayout();
void setMouseConfigs();
void setPointerConfigs();
void setTouchDeviceConfigs();
void updateDragIcon();
void updateCapabilities(wlr_input_device*);
@@ -55,11 +68,14 @@ public:
void onTouchUp(wlr_touch_up_event*);
void onTouchMove(wlr_touch_motion_event*);
void onPointerHoldBegin(wlr_pointer_hold_begin_event*);
void onPointerHoldEnd(wlr_pointer_hold_end_event*);
STouchData m_sTouchData;
// for dragging floating windows
CWindow* currentlyDraggedWindow = nullptr;
int dragButton = -1;
eMouseBindMode dragMode = MBIND_INVALID;
SDrag m_sDrag;
@@ -75,6 +91,12 @@ public:
// idle inhibitors
std::list<SIdleInhibitor> m_lIdleInhibitors;
// Touch devices
std::list<STouchDevice> m_lTouchDevices;
// Switches
std::list<SSwitchDevice> m_lSwitches;
void newTabletTool(wlr_input_device*);
void newTabletPad(wlr_input_device*);
void focusTablet(STablet*, wlr_tablet_tool*, bool motion = false);
@@ -105,6 +127,9 @@ private:
bool m_bEmptyFocusCursorSet = false;
Vector2D m_vLastCursorPosFloored = Vector2D();
// for some bugs in follow mouse 0
bool m_bLastFocusOnLS = false;
void processMouseDownNormal(wlr_pointer_button_event* e);
void processMouseDownKill(wlr_pointer_button_event* e);
@@ -117,6 +142,11 @@ private:
STabletTool* ensureTabletToolPresent(wlr_tablet_tool*);
void applyConfigToKeyboard(SKeyboard*);
// this will be set after a refocus()
wlr_surface* m_pFoundSurfaceToFocus = nullptr;
SLayerSurface* m_pFoundLSToFocus = nullptr;
CWindow* m_pFoundWindowToFocus = nullptr;
};
inline std::unique_ptr<CInputManager> g_pInputManager;

View File

@@ -2,9 +2,7 @@
#include "InputManager.hpp"
#include "../../Compositor.hpp"
CInputMethodRelay::CInputMethodRelay() {
}
CInputMethodRelay::CInputMethodRelay() { }
void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
if (m_pWLRIME) {
@@ -303,7 +301,7 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) {
const auto PINPUT = (STextInput*)owner;
if (!g_pInputManager->m_sIMERelay.m_pWLRIME) {
Debug::log(ERR, "Enabling TextInput on no IME!");
Debug::log(WARN, "Enabling TextInput on no IME!");
return;
}
@@ -319,12 +317,12 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) {
const auto PINPUT = (STextInput*)owner;
if (!g_pInputManager->m_sIMERelay.m_pWLRIME) {
Debug::log(ERR, "Committing TextInput on no IME!");
Debug::log(WARN, "Committing TextInput on no IME!");
return;
}
if (!PINPUT->pWlrInput->current_enabled) {
Debug::log(ERR, "Disabled TextInput commit?");
Debug::log(WARN, "Disabled TextInput commit?");
return;
}
@@ -337,7 +335,7 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) {
const auto PINPUT = (STextInput*)owner;
if (!g_pInputManager->m_sIMERelay.m_pWLRIME) {
Debug::log(ERR, "Disabling TextInput on no IME!");
Debug::log(WARN, "Disabling TextInput on no IME!");
return;
}
@@ -354,7 +352,7 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) {
const auto PINPUT = (STextInput*)owner;
if (!g_pInputManager->m_sIMERelay.m_pWLRIME) {
Debug::log(ERR, "Disabling TextInput on no IME!");
Debug::log(WARN, "Disabling TextInput on no IME!");
return;
}

View File

@@ -2,21 +2,21 @@
#include "../../Compositor.hpp"
void CInputManager::onSwipeBegin(wlr_pointer_swipe_begin_event* e) {
static auto *const PSWIPE = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe")->intValue;
static auto *const PSWIPEFINGERS = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_fingers")->intValue;
static auto *const PSWIPENEW = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_create_new")->intValue;
if (e->fingers != *PSWIPEFINGERS || *PSWIPE == 0)
return;
int onMonitor = 0;
for (auto& w : g_pCompositor->m_vWorkspaces) {
if (w->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID) {
if (w->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID && w->m_iID != SPECIAL_WORKSPACE_ID) {
onMonitor++;
}
}
if (onMonitor < 2)
if (onMonitor < 2 && !*PSWIPENEW)
return; // disallow swiping when there's 1 workspace on a monitor
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
@@ -28,44 +28,66 @@ void CInputManager::onSwipeBegin(wlr_pointer_swipe_begin_event* e) {
m_sActiveSwipe.pMonitor = g_pCompositor->m_pLastMonitor;
m_sActiveSwipe.avgSpeed = 0;
m_sActiveSwipe.speedPoints = 0;
if (PWORKSPACE->m_bHasFullscreenWindow) {
for (auto& ls : g_pCompositor->m_pLastMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
ls->alpha = 255.f;
}
}
}
void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
if (!m_sActiveSwipe.pWorkspaceBegin)
return; // no valid swipe
static auto *const PSWIPEPERC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_cancel_ratio")->floatValue;
static auto *const PSWIPEDIST = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_distance")->intValue;
static auto *const PSWIPEFORC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_min_speed_to_force")->intValue;
static auto *const PSWIPENEW = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_create_new")->intValue;
const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert";
// commit
std::string wsname = "";
auto workspaceIDLeft = getWorkspaceIDFromString("m-1", wsname);
auto workspaceIDRight = getWorkspaceIDFromString("m+1", wsname);
const auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight);
if ((workspaceIDRight <= m_sActiveSwipe.pWorkspaceBegin->m_iID || workspaceIDRight == workspaceIDLeft) && *PSWIPENEW) {
workspaceIDRight = m_sActiveSwipe.pWorkspaceBegin->m_iID > 0 ? m_sActiveSwipe.pWorkspaceBegin->m_iID + 1 : 1;
}
auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); // not guaranteed if PSWIPENEW
const auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft);
const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.vec();
CWorkspace* pSwitchedTo = nullptr;
if ((abs(m_sActiveSwipe.delta) < *PSWIPEDIST * *PSWIPEPERC && (*PSWIPEFORC == 0 || (*PSWIPEFORC != 0 && m_sActiveSwipe.avgSpeed < *PSWIPEFORC))) || abs(m_sActiveSwipe.delta) < 2) {
// revert
if (abs(m_sActiveSwipe.delta) < 2) {
PWORKSPACEL->m_vRenderOffset.setValueAndWarp(Vector2D(0,0));
if (PWORKSPACER)
PWORKSPACER->m_vRenderOffset.setValueAndWarp(Vector2D(0,0));
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0,0));
} else {
if (m_sActiveSwipe.delta < 0) {
// to left
if (VERTANIMS)
PWORKSPACEL->m_vRenderOffset = Vector2D({0, -m_sActiveSwipe.pMonitor->vecSize.y});
else
PWORKSPACEL->m_vRenderOffset = Vector2D({-m_sActiveSwipe.pMonitor->vecSize.x, 0});
} else {
} else if (PWORKSPACER) {
// to right
if (VERTANIMS)
PWORKSPACER->m_vRenderOffset = Vector2D({0, m_sActiveSwipe.pMonitor->vecSize.y});
else
PWORKSPACER->m_vRenderOffset = Vector2D({m_sActiveSwipe.pMonitor->vecSize.x, 0});
}
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D();
}
pSwitchedTo = m_sActiveSwipe.pWorkspaceBegin;
} else if (m_sActiveSwipe.delta < 0) {
// switch to left
const auto RENDEROFFSET = PWORKSPACEL->m_vRenderOffset.vec();
@@ -76,39 +98,61 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
PWORKSPACEL->m_fAlpha.setValueAndWarp(255.f);
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE);
if (VERTANIMS)
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0, m_sActiveSwipe.pMonitor->vecSize.y);
else
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(m_sActiveSwipe.pMonitor->vecSize.x, 0);
m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(255.f);
g_pInputManager->unconstrainMouse();
Debug::log(LOG, "Ended swipe to the left");
pSwitchedTo = PWORKSPACEL;
} else {
// switch to right
const auto RENDEROFFSET = PWORKSPACER->m_vRenderOffset.vec();
const auto RENDEROFFSET = PWORKSPACER ? PWORKSPACER->m_vRenderOffset.vec() : Vector2D();
if (PWORKSPACER)
g_pKeybindManager->m_mDispatchers["workspace"]("[internal]" + std::to_string(workspaceIDRight));
else
g_pKeybindManager->m_mDispatchers["workspace"](std::to_string(workspaceIDRight)); // so that the ID is created properly
if (!PWORKSPACER)
PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); // not guaranteed on PSWIPENEW
PWORKSPACER->m_vRenderOffset.setValue(RENDEROFFSET);
PWORKSPACER->m_fAlpha.setValueAndWarp(255.f);
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE);
if (VERTANIMS)
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0, -m_sActiveSwipe.pMonitor->vecSize.y);
else
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(-m_sActiveSwipe.pMonitor->vecSize.x, 0);
m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(255.f);
g_pInputManager->unconstrainMouse();
Debug::log(LOG, "Ended swipe to the right");
pSwitchedTo = PWORKSPACER;
}
g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor);
PWORKSPACEL->m_bForceRendering = false;
if (PWORKSPACER)
PWORKSPACER->m_bForceRendering = false;
m_sActiveSwipe.pWorkspaceBegin->m_bForceRendering = false;
m_sActiveSwipe.pWorkspaceBegin = nullptr;
g_pInputManager->refocus();
// apply alpha
for (auto& ls : g_pCompositor->m_pLastMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
ls->alpha = pSwitchedTo->m_bHasFullscreenWindow && pSwitchedTo->m_efFullscreenMode == FULLSCREEN_FULL ? 0.f : 255.f;
}
}
void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
@@ -117,8 +161,11 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
static auto *const PSWIPEDIST = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_distance")->intValue;
static auto *const PSWIPEINVR = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_invert")->intValue;
static auto *const PSWIPENEW = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_create_new")->intValue;
m_sActiveSwipe.delta += *PSWIPEINVR ? -e->dx : e->dx;
const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert";
m_sActiveSwipe.delta += VERTANIMS ? (*PSWIPEINVR ? -e->dy : e->dy) : (*PSWIPEINVR ? -e->dx : e->dx);
m_sActiveSwipe.avgSpeed = (m_sActiveSwipe.avgSpeed * m_sActiveSwipe.speedPoints + abs(e->dx)) / (m_sActiveSwipe.speedPoints + 1);
m_sActiveSwipe.speedPoints++;
@@ -127,15 +174,22 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
auto workspaceIDLeft = getWorkspaceIDFromString("m-1", wsname);
auto workspaceIDRight = getWorkspaceIDFromString("m+1", wsname);
if (workspaceIDLeft == INT_MAX || workspaceIDRight == INT_MAX || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID)
if ((workspaceIDLeft == INT_MAX || workspaceIDRight == INT_MAX || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID) && !*PSWIPENEW) {
m_sActiveSwipe.pWorkspaceBegin = nullptr; // invalidate the swipe
return;
}
m_sActiveSwipe.pWorkspaceBegin->m_bForceRendering = true;
m_sActiveSwipe.delta = std::clamp(m_sActiveSwipe.delta, (double)-*PSWIPEDIST, (double)*PSWIPEDIST);
if (((m_sActiveSwipe.pWorkspaceBegin->m_iID == workspaceIDLeft || m_sActiveSwipe.pWorkspaceBegin->m_iID == workspaceIDRight) && *PSWIPENEW && (m_sActiveSwipe.delta < 0)) || (m_sActiveSwipe.delta > 0 && g_pCompositor->getWindowsOnWorkspace(m_sActiveSwipe.pWorkspaceBegin->m_iID) == 0 && workspaceIDRight <= m_sActiveSwipe.pWorkspaceBegin->m_iID)) {
m_sActiveSwipe.delta = 0;
return;
}
if (m_sActiveSwipe.delta < 0) {
if (workspaceIDLeft > m_sActiveSwipe.pWorkspaceBegin->m_iID){
if (workspaceIDLeft > m_sActiveSwipe.pWorkspaceBegin->m_iID && !*PSWIPENEW){
m_sActiveSwipe.delta = 0;
return;
}
@@ -152,12 +206,28 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
PWORKSPACER->m_fAlpha.setValueAndWarp(0.f);
}
if (VERTANIMS) {
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.y - m_sActiveSwipe.pMonitor->vecSize.y));
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.y));
} else {
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x - m_sActiveSwipe.pMonitor->vecSize.x, 0));
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0));
}
g_pCompositor->updateWorkspaceWindowDecos(workspaceIDLeft);
} else {
if (workspaceIDRight < m_sActiveSwipe.pWorkspaceBegin->m_iID) {
if (*PSWIPENEW) {
g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor);
if (VERTANIMS)
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.y));
else
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0));
g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID);
return;
}
m_sActiveSwipe.delta = 0;
return;
}
@@ -174,8 +244,13 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
PWORKSPACEL->m_fAlpha.setValueAndWarp(0.f);
}
if (VERTANIMS) {
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.y + m_sActiveSwipe.pMonitor->vecSize.y));
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.y));
} else {
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x + m_sActiveSwipe.pMonitor->vecSize.x, 0));
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0));
}
g_pCompositor->updateWorkspaceWindowDecos(workspaceIDRight);
}

View File

@@ -219,7 +219,7 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) {
void CInputManager::focusTablet(STablet* pTab, wlr_tablet_tool* pTool, bool motion) {
const auto PTOOL = g_pInputManager->ensureTabletToolPresent(pTool);
if (const auto PWINDOW = g_pCompositor->m_pLastWindow; g_pCompositor->windowValidMapped(PWINDOW)) {
if (const auto PWINDOW = g_pCompositor->m_pLastWindow; PWINDOW) {
const auto CURSORPOS = g_pInputManager->getMouseCoordsInternal();
const auto LOCAL = CURSORPOS - PWINDOW->m_vRealPosition.goalv();

View File

@@ -2,44 +2,74 @@
#include "../../Compositor.hpp"
void CInputManager::onTouchDown(wlr_touch_down_event* e) {
auto PMONITOR = g_pCompositor->getMonitorFromName(e->touch->output_name ? e->touch->output_name : "");
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, g_pCompositor->m_pLastMonitor->vecPosition.x + e->x * g_pCompositor->m_pLastMonitor->vecSize.x, g_pCompositor->m_pLastMonitor->vecPosition.y + e->y * g_pCompositor->m_pLastMonitor->vecSize.y);
const auto PDEVIT = std::find_if(m_lTouchDevices.begin(), m_lTouchDevices.end(), [&](const STouchDevice& other) { return other.pWlrDevice == &e->touch->base; });
if (PDEVIT != m_lTouchDevices.end() && !PDEVIT->boundOutput.empty())
PMONITOR = g_pCompositor->getMonitorFromName(PDEVIT->boundOutput);
PMONITOR = PMONITOR ? PMONITOR : g_pCompositor->m_pLastMonitor;
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PMONITOR->vecPosition.x + e->x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e->y * PMONITOR->vecSize.y);
refocus();
m_sTouchData.touchFocusWindow = nullptr;
m_sTouchData.touchFocusWindow = m_pFoundWindowToFocus;
m_sTouchData.touchFocusSurface = m_pFoundSurfaceToFocus;
m_sTouchData.touchFocusLS = m_pFoundLSToFocus;
if (g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow)) {
Vector2D local;
if (g_pCompositor->m_pLastWindow->m_bIsX11) {
local = g_pInputManager->getMouseCoordsInternal() - g_pCompositor->m_pLastWindow->m_vRealPosition.goalv();
if (m_sTouchData.touchFocusWindow) {
if (m_sTouchData.touchFocusWindow->m_bIsX11) {
local = g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchFocusWindow->m_vRealPosition.goalv();
} else {
g_pCompositor->vectorWindowToSurface(g_pInputManager->getMouseCoordsInternal(), g_pCompositor->m_pLastWindow, local);
g_pCompositor->vectorWindowToSurface(g_pInputManager->getMouseCoordsInternal(), m_sTouchData.touchFocusWindow, 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) - g_pCompositor->m_pLastMonitor->vecPosition;
wlr_seat_touch_notify_down(g_pCompositor->m_sSeat.seat, g_pCompositor->m_pLastFocus, e->time_msec, e->touch_id, local.x, local.y);
m_sTouchData.touchFocusWindow = g_pCompositor->m_pLastWindow;
m_sTouchData.touchSurfaceOrigin = g_pInputManager->getMouseCoordsInternal() - local;
} else {
return; // oops, nothing found.
}
wlr_seat_touch_notify_down(g_pCompositor->m_sSeat.seat, m_sTouchData.touchFocusSurface, e->time_msec, e->touch_id, local.x, local.y);
}
void CInputManager::onTouchUp(wlr_touch_up_event* e){
if (m_sTouchData.touchFocusWindow) {
if (m_sTouchData.touchFocusSurface) {
wlr_seat_touch_notify_up(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id);
}
}
void CInputManager::onTouchMove(wlr_touch_motion_event* e){
if (g_pCompositor->windowValidMapped(m_sTouchData.touchFocusWindow)) {
if (m_sTouchData.touchFocusWindow && g_pCompositor->windowValidMapped(m_sTouchData.touchFocusWindow)) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_sTouchData.touchFocusWindow->m_iMonitorID);
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, 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;
wlr_seat_touch_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id, local.x, local.y);
} else if (m_sTouchData.touchFocusLS) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_sTouchData.touchFocusLS->monitorID);
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, 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;
wlr_seat_touch_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id, local.x, local.y);
}
}
void CInputManager::onPointerHoldBegin(wlr_pointer_hold_begin_event* e) {
wlr_pointer_gestures_v1_send_hold_begin(g_pCompositor->m_sWLRPointerGestures, g_pCompositor->m_sSeat.seat, e->time_msec, e->fingers);
}
void CInputManager::onPointerHoldEnd(wlr_pointer_hold_end_event* e) {
wlr_pointer_gestures_v1_send_hold_end(g_pCompositor->m_sWLRPointerGestures, g_pCompositor->m_sSeat.seat, e->time_msec, e->cancelled);
}

View File

@@ -18,7 +18,7 @@ executable('Hyprland', src,
xcb_dep,
dependency('pixman-1'),
dependency('GL'),
dependency('GL', 'opengl'),
dependency('threads')
],
install : true

View File

@@ -3,6 +3,7 @@
bool CFramebuffer::alloc(int w, int h) {
bool firstAlloc = false;
RASSERT((w > 1 && h > 1), "cannot alloc a FB with negative / zero size! (attempted %ix%i)", w, h);
if (m_iFb == (uint32_t)-1) {
firstAlloc = true;
@@ -73,6 +74,7 @@ void CFramebuffer::release() {
m_cTex.m_iTexID = 0;
m_iFb = -1;
m_Size = Vector2D();
}
CFramebuffer::~CFramebuffer() {

View File

@@ -1,6 +1,8 @@
#include "Shaders.hpp"
#include "OpenGL.hpp"
#include "../Compositor.hpp"
#include "../helpers/MiscFunctions.hpp"
#include "Shaders.hpp"
CHyprOpenGLImpl::CHyprOpenGLImpl() {
RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)), "Couldn't unset current EGL!");
@@ -102,6 +104,7 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool
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->monitorMirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
createBGTextureForMonitor(pMonitor);
}
@@ -120,11 +123,14 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool
void CHyprOpenGLImpl::end() {
// end the render, copy the data to the WLR framebuffer
if (!m_bFakeFrame) {
pixman_region32_copy(m_RenderData.pDamage, &m_rOriginalDamageRegion);
if (!m_RenderData.pMonitor->mirrors.empty())
g_pHyprOpenGL->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};
pixman_region32_copy(m_RenderData.pDamage, &m_rOriginalDamageRegion);
clear(CColor(11, 11, 11, 255));
m_bEndFrame = true;
@@ -145,9 +151,7 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shQUAD.proj = glGetUniformLocation(prog, "proj");
m_RenderData.pCurrentMonData->m_shQUAD.color = glGetUniformLocation(prog, "color");
m_RenderData.pCurrentMonData->m_shQUAD.posAttrib = glGetAttribLocation(prog, "pos");
m_RenderData.pCurrentMonData->m_shQUAD.texAttrib = glGetAttribLocation(prog, "texcoord");
m_RenderData.pCurrentMonData->m_shQUAD.topLeft = glGetUniformLocation(prog, "topLeft");
m_RenderData.pCurrentMonData->m_shQUAD.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_RenderData.pCurrentMonData->m_shQUAD.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shQUAD.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shQUAD.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
@@ -161,7 +165,6 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shRGBA.posAttrib = glGetAttribLocation(prog, "pos");
m_RenderData.pCurrentMonData->m_shRGBA.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
m_RenderData.pCurrentMonData->m_shRGBA.topLeft = glGetUniformLocation(prog, "topLeft");
m_RenderData.pCurrentMonData->m_shRGBA.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_RenderData.pCurrentMonData->m_shRGBA.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shRGBA.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shRGBA.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
@@ -177,7 +180,6 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shRGBX.posAttrib = glGetAttribLocation(prog, "pos");
m_RenderData.pCurrentMonData->m_shRGBX.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
m_RenderData.pCurrentMonData->m_shRGBX.topLeft = glGetUniformLocation(prog, "topLeft");
m_RenderData.pCurrentMonData->m_shRGBX.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_RenderData.pCurrentMonData->m_shRGBX.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shRGBX.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shRGBX.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
@@ -193,7 +195,6 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shEXT.texAttrib = glGetAttribLocation(prog, "texcoord");
m_RenderData.pCurrentMonData->m_shEXT.discardOpaque = glGetUniformLocation(prog, "discardOpaque");
m_RenderData.pCurrentMonData->m_shEXT.topLeft = glGetUniformLocation(prog, "topLeft");
m_RenderData.pCurrentMonData->m_shEXT.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_RenderData.pCurrentMonData->m_shEXT.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shEXT.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shEXT.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample");
@@ -268,7 +269,7 @@ void CHyprOpenGLImpl::clear(const CColor& color) {
scissor((wlr_box*)nullptr);
}
void CHyprOpenGLImpl::scissor(const wlr_box* pBox) {
void CHyprOpenGLImpl::scissor(const wlr_box* pBox, bool transform) {
RASSERT(m_RenderData.pMonitor, "Tried to scissor without begin()!");
if (!pBox) {
@@ -278,17 +279,19 @@ void CHyprOpenGLImpl::scissor(const wlr_box* pBox) {
wlr_box 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);
}
glScissor(newBox.x, newBox.y, newBox.width, newBox.height);
glEnable(GL_SCISSOR_TEST);
}
void CHyprOpenGLImpl::scissor(const pixman_box32* pBox) {
void CHyprOpenGLImpl::scissor(const pixman_box32* pBox, bool transform) {
RASSERT(m_RenderData.pMonitor, "Tried to scissor without begin()!");
if (!pBox) {
@@ -298,15 +301,16 @@ void CHyprOpenGLImpl::scissor(const pixman_box32* pBox) {
wlr_box newBox = {pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1};
scissor(&newBox);
scissor(&newBox, transform);
}
void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h) {
void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h, bool transform) {
wlr_box box = {x,y,w,h};
scissor(&box);
scissor(&box, transform);
}
void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) {
if(pixman_region32_not_empty(m_RenderData.pDamage))
renderRectWithDamage(box, col, m_RenderData.pDamage, round);
}
@@ -319,27 +323,31 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm
float glMatrix[9];
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
wlr_matrix_multiply(glMatrix, matrixFlip180, glMatrix);
wlr_matrix_transpose(glMatrix, glMatrix);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(m_RenderData.pCurrentMonData->m_shQUAD.program);
#ifndef GLES2
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shQUAD.proj, 1, GL_TRUE, glMatrix);
#else
wlr_matrix_transpose(glMatrix, glMatrix);
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shQUAD.proj, 1, GL_FALSE, glMatrix);
#endif
glUniform4f(m_RenderData.pCurrentMonData->m_shQUAD.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
const auto TOPLEFT = Vector2D(round, round);
const auto BOTTOMRIGHT = Vector2D(box->width - round, box->height - round);
const auto FULLSIZE = Vector2D(box->width, box->height);
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);
const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y);
const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height);
static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
// Rounded corners
glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(m_RenderData.pCurrentMonData->m_shQUAD.radius, round);
glUniform1i(m_RenderData.pCurrentMonData->m_shQUAD.primitiveMultisample, (int)(*PMULTISAMPLEEDGES == 1 && round != 0));
@@ -350,7 +358,21 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib);
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shQUAD.texAttrib);
if (pixman_region32_not_empty(damage)) {
if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) {
pixman_region32_t damageClip;
pixman_region32_init(&damageClip);
pixman_region32_intersect_rect(&damageClip, damage, m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height);
if (pixman_region32_not_empty(&damageClip)) {
PIXMAN_DAMAGE_FOREACH(&damageClip) {
const auto RECT = RECTSARR[i];
scissor(&RECT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
pixman_region32_fini(&damageClip);
} else {
PIXMAN_DAMAGE_FOREACH(damage) {
const auto RECT = RECTSARR[i];
scissor(&RECT);
@@ -382,6 +404,9 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
if (!pixman_region32_not_empty(m_RenderData.pDamage))
return;
static auto *const PDIMINACTIVE = &g_pConfigManager->getConfigValuePtr("decoration:dim_inactive")->intValue;
// get transform
@@ -391,9 +416,6 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
float glMatrix[9];
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
wlr_matrix_multiply(glMatrix, matrixFlip180, glMatrix);
wlr_matrix_transpose(glMatrix, glMatrix);
CShader* shader = nullptr;
@@ -421,23 +443,27 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
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);
glUniform1f(shader->alpha, alpha / 255.f);
glUniform1i(shader->discardOpaque, (int)discardOpaque);
// round is in px
// so we need to do some maf
wlr_box transformedBox;
wlr_box_transform(&transformedBox, pBox, wlr_output_transform_invert(m_RenderData.pMonitor->transform),
m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y);
const auto TOPLEFT = Vector2D(round, round);
const auto BOTTOMRIGHT = Vector2D(pBox->width - round, pBox->height - round);
const auto FULLSIZE = Vector2D(pBox->width, pBox->height);
const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y);
const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height);
static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
// Rounded corners
glUniform2f(shader->topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(shader->bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(shader->fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform2f(shader->topLeft, TOPLEFT.x, TOPLEFT.y);
glUniform2f(shader->fullSize, FULLSIZE.x ,FULLSIZE.y);
glUniform1f(shader->radius, round);
glUniform1i(shader->primitiveMultisample, (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !noAA));
@@ -449,8 +475,6 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
glUniform1i(shader->applyTint, 0);
}
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
const float verts[] = {
m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVTopLeft.y, // top right
m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVTopLeft.y, // top left
@@ -458,6 +482,8 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom left
};
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
if (allowCustomUV && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) {
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, verts);
} else {
@@ -467,8 +493,22 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
glEnableVertexAttribArray(shader->posAttrib);
glEnableVertexAttribArray(shader->texAttrib);
if (pixman_region32_not_empty(m_RenderData.pDamage)) {
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) {
pixman_region32_t damageClip;
pixman_region32_init(&damageClip);
pixman_region32_intersect_rect(&damageClip, damage, m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height);
if (pixman_region32_not_empty(&damageClip)) {
PIXMAN_DAMAGE_FOREACH(&damageClip) {
const auto RECT = RECTSARR[i];
scissor(&RECT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
pixman_region32_fini(&damageClip);
} else {
PIXMAN_DAMAGE_FOREACH(damage) {
const auto RECT = RECTSARR[i];
scissor(&RECT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
@@ -491,15 +531,13 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
glDisable(GL_STENCIL_TEST);
// get transforms for the full monitor
const auto TRANSFORM = wlr_output_transform_invert(WL_OUTPUT_TRANSFORM_NORMAL);
const auto TRANSFORM = wlr_output_transform_invert(m_RenderData.pMonitor->transform);
float matrix[9];
wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
wlr_matrix_project_box(matrix, &MONITORBOX, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
float glMatrix[9];
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
wlr_matrix_multiply(glMatrix, matrixFlip180, glMatrix);
wlr_matrix_transpose(glMatrix, glMatrix);
// get the config settings
static auto *const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur_size")->intValue;
@@ -509,6 +547,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
pixman_region32_t damage;
pixman_region32_init(&damage);
pixman_region32_copy(&damage, originalDamage);
wlr_region_transform(&damage, &damage, wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y);
wlr_region_expand(&damage, &damage, pow(2, *PBLURPASSES) * *PBLURSIZE);
// helper
@@ -533,7 +572,12 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
glUseProgram(pShader->program);
// prep two shaders
#ifndef GLES2
glUniformMatrix3fv(pShader->proj, 1, GL_TRUE, glMatrix);
#else
wlr_matrix_transpose(glMatrix, glMatrix);
glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix);
#endif
glUniform1f(pShader->radius, *PBLURSIZE * (a / 255.f)); // this makes the blursize change with a
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));
@@ -550,7 +594,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
if (pixman_region32_not_empty(pDamage)) {
PIXMAN_DAMAGE_FOREACH(pDamage) {
const auto RECT = RECTSARR[i];
scissor(&RECT);
scissor(&RECT, false /* this region is already transformed */);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
@@ -613,7 +657,7 @@ void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) {
bool has = false;
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_iWorkspaceID == pMonitor->activeWorkspace && w->m_bIsMapped && !w->m_bHidden && !w->m_bIsFloating) {
if (w->m_iWorkspaceID == pMonitor->activeWorkspace && w->m_bIsMapped && !w->isHidden() && !w->m_bIsFloating) {
has = true;
break;
}
@@ -637,7 +681,11 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() {
clear(CColor(0,0,0,0));
m_bEndFrame = true; // fix transformed
renderTextureInternalWithDamage(POUTFB->m_cTex, &wholeMonitor, 255, &fakeDamage, 0, false, true, false);
m_bEndFrame = false;
pixman_region32_fini(&fakeDamage);
m_RenderData.pCurrentMonData->primaryFB.bind();
@@ -652,7 +700,7 @@ void CHyprOpenGLImpl::preWindowPass() {
bool hasWindows = false;
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_iWorkspaceID == m_RenderData.pMonitor->activeWorkspace && !w->m_bHidden && w->m_bIsMapped && !w->m_bIsFloating) {
if (w->m_iWorkspaceID == m_RenderData.pMonitor->activeWorkspace && !w->isHidden() && w->m_bIsMapped && !w->m_bIsFloating) {
hasWindows = true;
break;
}
@@ -672,16 +720,19 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
static auto *const PNOBLUROVERSIZED = &g_pConfigManager->getConfigValuePtr("decoration:no_blur_on_oversized")->intValue;
static auto *const PBLURNEWOPTIMIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur_new_optimizations")->intValue;
if (*PBLURENABLED == 0 || (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) || (m_pCurrentWindow && m_pCurrentWindow->m_sAdditionalConfigData.forceNoBlur)) {
renderTexture(tex, pBox, a, round, false, true);
return;
}
// make a damage region for this window
pixman_region32_t damage;
pixman_region32_init(&damage);
pixman_region32_intersect_rect(&damage, m_RenderData.pDamage, pBox->x, pBox->y, pBox->width, pBox->height); // clip it to the box
if(!pixman_region32_not_empty(&damage))
return;
if (*PBLURENABLED == 0 || (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) || (m_pCurrentWindow && m_pCurrentWindow->m_sAdditionalConfigData.forceNoBlur)) {
renderTexture(tex, pBox, a, round, false, true);
return;
}
// amazing hack: the surface has an opaque region!
pixman_region32_t inverseOpaque;
pixman_region32_init(&inverseOpaque);
@@ -732,10 +783,11 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
// stencil done. Render everything.
wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
if (pixman_region32_not_empty(&damage)) {
// render our great blurred FB
static auto *const PBLURIGNOREOPACITY = &g_pConfigManager->getConfigValuePtr("decoration:blur_ignore_opacity")->intValue;
m_bEndFrame = true; // fix transformed
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 255.f : a, &damage, 0, false, false, false);
m_bEndFrame = false;
// render the window, but clear stencil
glClearStencil(0);
@@ -744,7 +796,6 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
// draw window
glDisable(GL_STENCIL_TEST);
renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true, true);
}
glStencilMask(-1);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
@@ -763,49 +814,56 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
if (!pixman_region32_not_empty(m_RenderData.pDamage) || (m_pCurrentWindow && m_pCurrentWindow->m_sAdditionalConfigData.forceNoBorder))
return;
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
static auto *const PMULTISAMPLE = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
if (*PBORDERSIZE < 1)
return;
int scaledBorderSize = *PBORDERSIZE * m_RenderData.pMonitor->scale;
if (round < 1) {
// zero rounding, just lines
wlr_box borderbox = {box->x - *PBORDERSIZE, box->y - *PBORDERSIZE, *PBORDERSIZE, box->height + 2 * *PBORDERSIZE};
wlr_box borderbox = {box->x - scaledBorderSize, box->y - scaledBorderSize, scaledBorderSize, box->height + 2 * scaledBorderSize};
renderRect(&borderbox, col, 0); // left
borderbox = {box->x, box->y - (int)*PBORDERSIZE, box->width + (int)*PBORDERSIZE, (int)*PBORDERSIZE};
borderbox = {box->x, box->y - (int)scaledBorderSize, box->width + (int)scaledBorderSize, (int)scaledBorderSize};
renderRect(&borderbox, col, 0); // top
borderbox = {box->x + box->width, box->y, (int)*PBORDERSIZE, box->height + (int)*PBORDERSIZE};
borderbox = {box->x + box->width, box->y, (int)scaledBorderSize, box->height + (int)scaledBorderSize};
renderRect(&borderbox, col, 0); // right
borderbox = {box->x, box->y + box->height, box->width, (int)*PBORDERSIZE};
borderbox = {box->x, box->y + box->height, box->width, (int)scaledBorderSize};
renderRect(&borderbox, col, 0); // bottom
return;
}
// adjust box
box->x -= *PBORDERSIZE;
box->y -= *PBORDERSIZE;
box->width += 2 * *PBORDERSIZE;
box->height += 2 * *PBORDERSIZE;
box->x -= scaledBorderSize;
box->y -= scaledBorderSize;
box->width += 2 * scaledBorderSize;
box->height += 2 * scaledBorderSize;
round += *PBORDERSIZE;
round += 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, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here
float glMatrix[9];
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
wlr_matrix_multiply(glMatrix, matrixFlip180, glMatrix);
wlr_matrix_transpose(glMatrix, glMatrix);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(m_RenderData.pCurrentMonData->m_shBORDER1.program);
#ifndef GLES2
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_TRUE, glMatrix);
#else
wlr_matrix_transpose(glMatrix, glMatrix);
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_FALSE, glMatrix);
#endif
glUniform4f(m_RenderData.pCurrentMonData->m_shBORDER1.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
const auto TOPLEFT = Vector2D(round, round);
@@ -816,7 +874,7 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, *PBORDERSIZE);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, scaledBorderSize);
glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.primitiveMultisample, *PMULTISAMPLE);
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@@ -825,7 +883,21 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib);
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib);
if (pixman_region32_not_empty(m_RenderData.pDamage)) {
if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) {
pixman_region32_t damageClip;
pixman_region32_init(&damageClip);
pixman_region32_intersect_rect(&damageClip, m_RenderData.pDamage, m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height);
if (pixman_region32_not_empty(&damageClip)) {
PIXMAN_DAMAGE_FOREACH(&damageClip) {
const auto RECT = RECTSARR[i];
scissor(&RECT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
pixman_region32_fini(&damageClip);
} else {
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
const auto RECT = RECTSARR[i];
scissor(&RECT);
@@ -923,9 +995,14 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) {
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
const auto BLURLSSTATUS = pLayer->forceBlur;
pLayer->forceBlur = false;
// draw the layer
g_pHyprRenderer->renderLayer(pLayer, PMONITOR, &now);
pLayer->forceBlur = BLURLSSTATUS;
// TODO: WARN:
// revise if any stencil-requiring rendering is done to the layers.
@@ -1026,6 +1103,9 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
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!");
if (!pixman_region32_not_empty(m_RenderData.pDamage))
return;
static auto *const PSHADOWPOWER = &g_pConfigManager->getConfigValuePtr("decoration:shadow_render_power")->intValue;
const auto SHADOWPOWER = std::clamp((int)*PSHADOWPOWER, 1, 4);
@@ -1037,16 +1117,18 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
float glMatrix[9];
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
wlr_matrix_multiply(glMatrix, matrixFlip180, glMatrix);
wlr_matrix_transpose(glMatrix, glMatrix);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(m_RenderData.pCurrentMonData->m_shSHADOW.program);
#ifndef GLES2
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_TRUE, glMatrix);
#else
wlr_matrix_transpose(glMatrix, glMatrix);
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_FALSE, glMatrix);
#endif
glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f * a);
const auto TOPLEFT = Vector2D(range + round, range + round);
@@ -1067,7 +1149,21 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib);
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib);
if (pixman_region32_not_empty(m_RenderData.pDamage)) {
if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) {
pixman_region32_t damageClip;
pixman_region32_init(&damageClip);
pixman_region32_intersect_rect(&damageClip, m_RenderData.pDamage, m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height);
if (pixman_region32_not_empty(&damageClip)) {
PIXMAN_DAMAGE_FOREACH(&damageClip) {
const auto RECT = RECTSARR[i];
scissor(&RECT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
pixman_region32_fini(&damageClip);
} else {
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
const auto RECT = RECTSARR[i];
scissor(&RECT);
@@ -1081,18 +1177,40 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
void CHyprOpenGLImpl::renderSplash(cairo_t *const CAIRO, cairo_surface_t *const CAIROSURFACE) {
void CHyprOpenGLImpl::saveBufferForMirror() {
m_RenderData.pCurrentMonData->monitorMirrorFB.bind();
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 255.f, 0, false, false);
m_RenderData.pCurrentMonData->primaryFB.bind();
}
void CHyprOpenGLImpl::renderMirrored() {
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
const auto PFB = &m_mMonitorRenderResources[m_RenderData.pMonitor->pMirrorOf].monitorMirrorFB;
if (PFB->m_cTex.m_iTexID <= 0)
return;
renderTexture(PFB->m_cTex, &monbox, 255.f, 0, false, false);
}
void CHyprOpenGLImpl::renderSplash(cairo_t *const CAIRO, cairo_surface_t *const CAIROSURFACE, double offsetY) {
cairo_select_font_face(CAIRO, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
const auto FONTSIZE = (int)(m_RenderData.pMonitor->vecPixelSize.y / 76);
cairo_set_font_size(CAIRO, FONTSIZE);
cairo_set_source_rgba(CAIRO, 1.f, 1.f, 1.f, 0.32f);
cairo_set_source_rgba(CAIRO, 1.0, 1.0, 1.0, 0.32);
cairo_text_extents_t textExtents;
cairo_text_extents(CAIRO, g_pCompositor->m_szCurrentSplash.c_str(), &textExtents);
cairo_move_to(CAIRO, m_RenderData.pMonitor->vecTransformedSize.x / 2.f - textExtents.width / 2.f, m_RenderData.pMonitor->vecTransformedSize.y - textExtents.height - 1);
cairo_move_to(CAIRO, (m_RenderData.pMonitor->vecPixelSize.x - textExtents.width) / 2.0, m_RenderData.pMonitor->vecPixelSize.y - textExtents.height + offsetY);
cairo_show_text(CAIRO, g_pCompositor->m_szCurrentSplash.c_str());
cairo_surface_flush(CAIROSURFACE);
@@ -1134,13 +1252,37 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
PTEX->m_vSize = textureSize;
// calc the target box
const double MONRATIO = m_RenderData.pMonitor->vecTransformedSize.x / m_RenderData.pMonitor->vecTransformedSize.y;
const double WPRATIO = 1.77;
Vector2D origin;
double scale;
if (MONRATIO > WPRATIO) {
scale = m_RenderData.pMonitor->vecTransformedSize.x / PTEX->m_vSize.x;
origin.y = (m_RenderData.pMonitor->vecTransformedSize.y - PTEX->m_vSize.y * scale) / 2.0;
} else {
scale = m_RenderData.pMonitor->vecTransformedSize.y / PTEX->m_vSize.y;
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};
m_mMonitorRenderResources[pMonitor].backgroundTexBox = box;
// create a new one with cairo
const auto CAIROSURFACE = cairo_image_surface_create_from_png(texPath.c_str());
const auto CAIRO = cairo_create(CAIROSURFACE);
// scale it to fit the current monitor
cairo_scale(CAIRO, textureSize.x / pMonitor->vecTransformedSize.x, textureSize.y / pMonitor->vecTransformedSize.y);
// render splash on wallpaper
if (!*PNOSPLASH)
renderSplash(CAIRO, CAIROSURFACE);
renderSplash(CAIRO, CAIROSURFACE, origin.y * WPRATIO / MONRATIO);
// copy the data to an OpenGL texture we have
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
@@ -1156,28 +1298,6 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
cairo_surface_destroy(CAIROSURFACE);
cairo_destroy(CAIRO);
// calc the target box
const float MONRATIO = m_RenderData.pMonitor->vecTransformedSize.x / m_RenderData.pMonitor->vecTransformedSize.y;
const float WPRATIO = 1.77f;
Vector2D origin;
float scale;
if (MONRATIO > WPRATIO) {
scale = m_RenderData.pMonitor->vecTransformedSize.x / PTEX->m_vSize.x;
origin.y = -(PTEX->m_vSize.y * scale - m_RenderData.pMonitor->vecTransformedSize.y) / 2.f / scale;
} else {
scale = m_RenderData.pMonitor->vecTransformedSize.y / PTEX->m_vSize.y;
origin.x = -(PTEX->m_vSize.x * scale - m_RenderData.pMonitor->vecTransformedSize.x) / 2.f / scale;
}
wlr_box box = {origin.x * scale, origin.y * scale, PTEX->m_vSize.x * scale, PTEX->m_vSize.y * scale};
m_mMonitorRenderResources[pMonitor].backgroundTexBox = box;
Debug::log(LOG, "Background created for monitor %s", pMonitor->szName.c_str());
}
@@ -1187,17 +1307,32 @@ void CHyprOpenGLImpl::clearWithTex() {
static auto *const PRENDERTEX = &g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo")->intValue;
if (!*PRENDERTEX) {
renderTexture(m_mMonitorBGTextures[m_RenderData.pMonitor], &m_mMonitorRenderResources[m_RenderData.pMonitor].backgroundTexBox, 255, 0);
auto TEXIT = m_mMonitorBGTextures.find(m_RenderData.pMonitor);
if (TEXIT == m_mMonitorBGTextures.end()) {
createBGTextureForMonitor(m_RenderData.pMonitor);
TEXIT = m_mMonitorBGTextures.find(m_RenderData.pMonitor);
}
if (TEXIT != m_mMonitorBGTextures.end())
renderTexture(TEXIT->second, &m_mMonitorRenderResources[m_RenderData.pMonitor].backgroundTexBox, 255, 0);
}
}
void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) {
wlr_output_attach_render(pMonitor->output, nullptr);
g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].mirrorFB.release();
g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].primaryFB.release();
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].stencilTex.destroyTexture();
g_pHyprOpenGL->m_mMonitorBGTextures[pMonitor].destroyTexture();
g_pHyprOpenGL->m_mMonitorRenderResources.erase(pMonitor);
g_pHyprOpenGL->m_mMonitorBGTextures.erase(pMonitor);
Debug::log(LOG, "Monitor %s -> destroyed all render data", pMonitor->szName.c_str());
wlr_output_rollback(pMonitor->output);
}

View File

@@ -8,16 +8,10 @@
#include <cairo/cairo.h>
#include "Shaders.hpp"
#include "Shader.hpp"
#include "Texture.hpp"
#include "Framebuffer.hpp"
inline const float matrixFlip180[] = {
1.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
};
inline const float fullVerts[] = {
1, 0, // top right
0, 0, // top left
@@ -33,8 +27,10 @@ inline const float fanVertsFull[] = {
struct SMonitorRenderData {
CFramebuffer primaryFB;
CFramebuffer mirrorFB;
CFramebuffer mirrorSwapFB;
CFramebuffer mirrorFB; // these are used for some effects,
CFramebuffer mirrorSwapFB; // etc
CFramebuffer monitorMirrorFB; // used for mirroring outputs
CTexture stencilTex;
@@ -66,6 +62,8 @@ struct SCurrentRenderData {
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
wlr_box clipBox = {};
};
class CHyprOpenGLImpl {
@@ -91,9 +89,9 @@ public:
void clear(const CColor&);
void clearWithTex();
void scissor(const wlr_box*);
void scissor(const pixman_box32*);
void scissor(const int x, const int y, const int w, const int h);
void scissor(const wlr_box*, 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);
void destroyMonitorResources(CMonitor*);
@@ -102,6 +100,9 @@ public:
void preWindowPass();
void preRender(CMonitor*);
void saveBufferForMirror();
void renderMirrored();
SCurrentRenderData m_RenderData;
GLint m_iCurrentOutputFb = 0;
@@ -135,8 +136,7 @@ private:
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage);
void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowCustomUV = false, bool allowDim = false);
void renderSplash(cairo_t *const, cairo_surface_t *const);
void renderSplash(cairo_t *const, cairo_surface_t *const, double);
void preBlurForCurrentMonitor();
};

View File

@@ -15,7 +15,7 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
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
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, std::clamp(surface->current.width, 2, 1337420), std::clamp(surface->current.height, 2, 1337420)};
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->squishOversized) {
if (x + windowBox.width > RDATA->w)
@@ -65,11 +65,14 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, CMonitor* pMonitor) {
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, &geometry))
return false;
if (pWindow->m_bPinned)
return true;
// now check if it has the same workspace
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
if (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID) {
if (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()) {
if (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated() || PWORKSPACE->m_bForceRendering) {
return true;
} else {
if (!(!PWORKSPACE->m_bHasFullscreenWindow || pWindow->m_bIsFullscreen || (pWindow->m_bIsFloating && pWindow->m_bCreatedOverFullscreen)))
@@ -81,9 +84,7 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, CMonitor* pMonitor) {
return true;
// if not, check if it maybe is active on a different monitor.
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) ||
(PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && PWORKSPACE->m_bForceRendering) || // vvvv might be in animation progress vvvvv
(PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) && pWindow->m_bIsFloating /* tiled windows can't be multi-ws */)
return !pWindow->m_bIsFullscreen; // Do not draw fullscreen windows on other monitors
if (pMonitor->specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
@@ -99,6 +100,9 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
if (pWindow->m_bPinned || PWORKSPACE->m_bForceRendering)
return true;
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
return true;
@@ -116,11 +120,39 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) {
void CHyprRenderer::renderWorkspaceWithFullscreenWindow(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* time) {
CWindow* pWorkspaceWindow = nullptr;
// loop over the tiled windows that are fading out
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_iWorkspaceID != pMonitor->activeWorkspace)
continue;
if (w->m_fAlpha.fl() == 0.f)
continue;
if (w->m_bIsFullscreen || w->m_bIsFloating)
continue;
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
}
// and floating ones too
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_iWorkspaceID != pMonitor->activeWorkspace)
continue;
if (w->m_fAlpha.fl() == 0.f)
continue;
if (w->m_bIsFullscreen || !w->m_bIsFloating)
continue;
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
}
for (auto& w : g_pCompositor->m_vWindows) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID);
if (w->m_iWorkspaceID != pWorkspace->m_iID || !w->m_bIsFullscreen){
if (!(PWORKSPACE && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
if (!(PWORKSPACE && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated() || PWORKSPACE->m_bForceRendering)))
continue;
if (w->m_iMonitorID != pMonitor->ID)
@@ -135,9 +167,15 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(CMonitor* pMonitor, CWor
pWorkspaceWindow = w.get();
}
// then render windows over fullscreen
if (!pWorkspaceWindow) {
// ?? happens sometimes...
pWorkspace->m_bHasFullscreenWindow = false;
return; // this will produce one blank frame. Oh well.
}
// then render windows over fullscreen.
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || !w->m_bCreatedOverFullscreen || !w->m_bIsMapped)
if (w->m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || (!w->m_bCreatedOverFullscreen && !w->m_bPinned) || !w->m_bIsMapped)
continue;
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
@@ -159,12 +197,11 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(CMonitor* pMonitor, CWor
}
// and the overlay layers
if (pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL) {
// on non-full we draw the bar and shit
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
if (ls->alpha.fl() != 0.f)
renderLayer(ls.get(), pMonitor, time);
}
}
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) {
renderLayer(ls.get(), pMonitor, time);
@@ -178,7 +215,7 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(CMonitor* pMonitor, CWor
}
void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* time, bool decorate, eRenderPassMode mode) {
if (pWindow->m_bHidden)
if (pWindow->isHidden())
return;
if (pWindow->m_bFadingOut) {
@@ -188,15 +225,15 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
}
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
const auto REALPOS = pWindow->m_vRealPosition.vec() + PWORKSPACE->m_vRenderOffset.vec();
const auto REALPOS = pWindow->m_vRealPosition.vec() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset.vec());
static const auto PNOFLOATINGBORDERS = &g_pConfigManager->getConfigValuePtr("general:no_border_on_floating")->intValue;
SRenderData renderdata = {pMonitor->output, time, REALPOS.x, REALPOS.y};
renderdata.surface = g_pXWaylandManager->getWindowSurface(pWindow);
renderdata.w = std::clamp(pWindow->m_vRealSize.vec().x, (double)5, (double)1337420); // clamp the size to min 5,
renderdata.h = std::clamp(pWindow->m_vRealSize.vec().y, (double)5, (double)1337420); // otherwise we'll have issues later with invalid boxes
renderdata.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() * (PWORKSPACE->m_fAlpha.fl() / 255.f);
renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (pWindow->m_bPinned ? 1.f : (PWORKSPACE->m_fAlpha.fl() / 255.f));
renderdata.alpha = pWindow->m_fActiveInactiveAlpha.fl();
renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (pWindow->m_bIsFloating ? *PNOFLOATINGBORDERS == 0 : true) && (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL);
renderdata.rounding = pWindow->m_sAdditionalConfigData.rounding;
@@ -215,11 +252,38 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
g_pHyprOpenGL->m_pCurrentWindow = pWindow;
// clip box for animated offsets
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;
const auto WINBB = pWindow->getFullWindowBoundingBox();
if (WINBB.x < PWSMON->vecPosition.x) {
offset.x = (PWSMON->vecPosition.x - WINBB.x) * PROGRESS;
} else if (WINBB.x > PWSMON->vecPosition.x + PWSMON->vecSize.x) {
offset.x = (WINBB.x - PWSMON->vecPosition.x + PWSMON->vecSize.x) * PROGRESS;
}
} else if (PWORKSPACE->m_vRenderOffset.vec().y) {
const auto PWSMON = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
const auto PROGRESS = PWORKSPACE->m_vRenderOffset.vec().y / PWSMON->vecSize.y;
const auto WINBB = pWindow->getFullWindowBoundingBox();
if (WINBB.y < PWSMON->vecPosition.y) {
offset.y = (PWSMON->vecPosition.y - WINBB.y) * PROGRESS;
} else if (WINBB.y > PWSMON->vecPosition.y + PWSMON->vecSize.y) {
offset.y = (WINBB.y - PWSMON->vecPosition.y + PWSMON->vecSize.y) * PROGRESS;
}
}
renderdata.x += offset.x;
renderdata.y += offset.y;
// 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 / 255.f);
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha / 255.f, offset);
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata);
@@ -256,6 +320,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
}
g_pHyprOpenGL->m_pCurrentWindow = nullptr;
g_pHyprOpenGL->m_RenderData.clipBox = { 0, 0, 0, 0 };
}
void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, timespec* time) {
@@ -318,7 +383,7 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
// Non-floating main
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
if (w->isHidden() && !w->m_bIsMapped && !w->m_bFadingOut)
continue;
if (w->m_bIsFloating)
@@ -336,7 +401,7 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
// Non-floating popup
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
if (w->isHidden() && !w->m_bIsMapped && !w->m_bFadingOut)
continue;
if (w->m_bIsFloating)
@@ -354,7 +419,7 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
// floating on top
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
if (w->isHidden() && !w->m_bIsMapped && !w->m_bFadingOut)
continue;
if (!w->m_bIsFloating)
@@ -372,7 +437,7 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
// and then special
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
if (w->isHidden() && !w->m_bIsMapped && !w->m_bFadingOut)
continue;
if (w->m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
@@ -459,8 +524,8 @@ void CHyprRenderer::calculateUVForWindowSurface(CWindow* pWindow, wlr_surface* p
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(0, 0);
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.x * ((double)pWindow->m_vRealSize.vec().x / ((double)geom.width / g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.x)),
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.y * ((double)pWindow->m_vRealSize.vec().y / ((double)geom.height / g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.y)));
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.x * (pWindow->m_vRealSize.vec().x / ((double)geom.width / g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.x)),
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.y * (pWindow->m_vRealSize.vec().y / ((double)geom.height / g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.y)));
}
} else {
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
@@ -695,14 +760,22 @@ void CHyprRenderer::arrangeLayersForMonitor(const int& monitor) {
PMONITOR->vecReservedTopLeft = Vector2D(usableArea.x, usableArea.y) - PMONITOR->vecPosition;
PMONITOR->vecReservedBottomRight = PMONITOR->vecSize - Vector2D(usableArea.width, usableArea.height) - PMONITOR->vecReservedTopLeft;
const auto ENTRY = g_pConfigManager->m_mAdditionalReservedAreas[PMONITOR->szName];
PMONITOR->vecReservedTopLeft = PMONITOR->vecReservedTopLeft + Vector2D(ENTRY.left, ENTRY.top);
PMONITOR->vecReservedBottomRight = PMONITOR->vecReservedBottomRight + Vector2D(ENTRY.right, ENTRY.bottom);
auto ADDITIONALRESERVED = g_pConfigManager->m_mAdditionalReservedAreas.find(PMONITOR->szName);
if (ADDITIONALRESERVED == g_pConfigManager->m_mAdditionalReservedAreas.end()) {
ADDITIONALRESERVED = g_pConfigManager->m_mAdditionalReservedAreas.find(""); // glob wildcard
}
if (ADDITIONALRESERVED != g_pConfigManager->m_mAdditionalReservedAreas.end()) {
PMONITOR->vecReservedTopLeft = PMONITOR->vecReservedTopLeft + Vector2D(ADDITIONALRESERVED->second.left, ADDITIONALRESERVED->second.top);
PMONITOR->vecReservedBottomRight = PMONITOR->vecReservedBottomRight + Vector2D(ADDITIONALRESERVED->second.right, ADDITIONALRESERVED->second.bottom);
}
// damage the monitor if can
if (PMONITOR->damage)
damageMonitor(PMONITOR);
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitor);
Debug::log(LOG, "Monitor %s layers arranged: reserved: %f %f %f %f", PMONITOR->szName.c_str(), PMONITOR->vecReservedTopLeft.x, PMONITOR->vecReservedTopLeft.y, PMONITOR->vecReservedBottomRight.x, PMONITOR->vecReservedBottomRight.y);
}
@@ -770,7 +843,7 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) {
}
void CHyprRenderer::damageMonitor(CMonitor* pMonitor) {
if (g_pCompositor->m_bUnsafeState)
if (g_pCompositor->m_bUnsafeState || pMonitor->isMirror())
return;
wlr_box damageBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
@@ -787,6 +860,9 @@ void CHyprRenderer::damageBox(wlr_box* pBox) {
return;
for (auto& m : g_pCompositor->m_vMonitors) {
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);
m->addDamage(&damageBox);
@@ -810,6 +886,19 @@ void CHyprRenderer::damageRegion(pixman_region32_t* rg) {
}
}
void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, pixman_region32_t* pRegion) {
for (auto& mirror : pMonitor->mirrors) {
Vector2D scale = {mirror->vecSize.x / pMonitor->vecSize.x, mirror->vecSize.y / pMonitor->vecSize.y};
pixman_region32_t rg;
pixman_region32_init(&rg);
pixman_region32_copy(&rg, pRegion);
wlr_region_scale_xy(&rg, &rg, scale.x, scale.y);
pMonitor->addDamage(&rg);
pixman_region32_fini(&rg);
}
}
void CHyprRenderer::renderDragIcon(CMonitor* pMonitor, timespec* time) {
if (!(g_pInputManager->m_sDrag.dragIcon && g_pInputManager->m_sDrag.iconMapped && g_pInputManager->m_sDrag.dragIcon->surface))
return;
@@ -861,7 +950,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
&& DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1)
&& pMonitor->scale == pMonitorRule->scale
&& ((DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1)) || pMonitorRule->offset == Vector2D(-1, -1))
&& pMonitor->transform == pMonitorRule->transform) {
&& pMonitor->transform == pMonitorRule->transform
&& pMonitorRule->enable10bit == pMonitor->enabled10bit) {
Debug::log(LOG, "Not applying a new rule to %s because it's already applied!", pMonitor->szName.c_str());
return true;
@@ -870,10 +960,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
wlr_output_set_scale(pMonitor->output, pMonitorRule->scale);
pMonitor->scale = pMonitorRule->scale;
pMonitor->vecPosition = pMonitorRule->offset;
// loop over modes and choose an appropriate one.
if (pMonitorRule->resolution != Vector2D()) {
if (pMonitorRule->resolution != Vector2D() && pMonitorRule->resolution != Vector2D(-1,-1) && pMonitorRule->resolution != Vector2D(-1,-2)) {
if (!wl_list_empty(&pMonitor->output->modes)) {
wlr_output_mode* mode;
bool found = false;
@@ -906,6 +994,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
if (!found) {
wlr_output_set_custom_mode(pMonitor->output, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (int)pMonitorRule->refreshRate * 1000);
pMonitor->vecSize = pMonitorRule->resolution;
pMonitor->refreshRate = pMonitorRule->refreshRate;
if (!wlr_output_test(pMonitor->output)) {
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
@@ -934,8 +1023,95 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
} else {
wlr_output_set_custom_mode(pMonitor->output, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (int)pMonitorRule->refreshRate * 1000);
pMonitor->vecSize = pMonitorRule->resolution;
pMonitor->refreshRate = pMonitorRule->refreshRate;
Debug::log(LOG, "Setting custom mode for %s", pMonitor->output->name);
if (!wlr_output_test(pMonitor->output)) {
Debug::log(ERR, "Custom resolution FAILED, falling back to preferred");
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
if (!PREFERREDMODE) {
Debug::log(ERR, "Monitor %s has NO PREFERRED MODE, and an INVALID one was requested: %ix%i@%2f", (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate);
return true;
}
// Preferred is valid
wlr_output_set_mode(pMonitor->output, PREFERREDMODE);
Debug::log(ERR, "Monitor %s got an invalid requested mode: %ix%i@%2f, using the preferred one instead: %ix%i@%2f", pMonitor->output->name, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate, PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
} else {
Debug::log(LOG, "Set a custom mode %ix%i@%2f (mode not found in monitor modes)", (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate);
}
}
} else if (pMonitorRule->resolution != Vector2D()) {
if (!wl_list_empty(&pMonitor->output->modes)) {
wlr_output_mode* mode;
float currentWidth = 0;
float currentHeight = 0;
float currentRefresh = 0;
bool success = false;
//(-1,-1) indicates a preference to refreshrate over resolution, (-1,-2) preference to resolution
if(pMonitorRule->resolution == Vector2D(-1,-1)) {
wl_list_for_each(mode, &pMonitor->output->modes, link) {
if( ( mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= ( currentRefresh - 1000.f ) ) || mode->refresh > ( currentRefresh + 3000.f ) ) {
wlr_output_set_mode(pMonitor->output, mode);
if (wlr_output_test(pMonitor->output)) {
currentWidth = mode->width;
currentHeight = mode->height;
currentRefresh = mode->refresh;
success = true;
}
}
}
} else {
wl_list_for_each(mode, &pMonitor->output->modes, link) {
if( ( mode->width >= currentWidth && mode->height >= currentHeight && mode->refresh >= ( currentRefresh - 1000.f ) ) || ( mode->width > currentWidth && mode->height > currentHeight ) ) {
wlr_output_set_mode(pMonitor->output, mode);
if (wlr_output_test(pMonitor->output)) {
currentWidth = mode->width;
currentHeight = mode->height;
currentRefresh = mode->refresh;
success = true;
}
}
}
}
if (!success) {
Debug::log(LOG, "Monitor %s: REJECTED mode: %ix%i@%2f! Falling back to preferred.",
pMonitor->output->name, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate,
mode->width, mode->height, mode->refresh / 1000.f);
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
if (!PREFERREDMODE) {
Debug::log(ERR, "Monitor %s has NO PREFERRED MODE, and an INVALID one was requested: %ix%i@%2f",
(int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate);
return true;
}
// Preferred is valid
wlr_output_set_mode(pMonitor->output, PREFERREDMODE);
Debug::log(ERR, "Monitor %s got an invalid requested mode: %ix%i@%2f, using the preferred one instead: %ix%i@%2f",
pMonitor->output->name, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate,
PREFERREDMODE->width, PREFERREDMODE->height, PREFERREDMODE->refresh / 1000.f);
pMonitor->refreshRate = PREFERREDMODE->refresh / 1000.f;
pMonitor->vecSize = Vector2D(PREFERREDMODE->width, PREFERREDMODE->height);
} else {
Debug::log(LOG, "Monitor %s: Applying highest mode %ix%i@%2f.",
pMonitor->output->name, (int)currentWidth, (int)currentHeight, (int)currentRefresh / 1000.f,
mode->width, mode->height, mode->refresh / 1000.f);
pMonitor->refreshRate = currentRefresh / 1000.f;
pMonitor->vecSize = Vector2D(currentWidth, currentHeight);
}
}
} else {
const auto PREFERREDMODE = wlr_output_preferred_mode(pMonitor->output);
@@ -978,14 +1154,37 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
}
}
pMonitor->vrrActive = pMonitor->output->pending.adaptive_sync_enabled; // disabled here, will be tested in CConfigManager::ensureVRR()
wlr_output_set_transform(pMonitor->output, pMonitorRule->transform);
pMonitor->transform = pMonitorRule->transform;
pMonitor->vecPixelSize = pMonitor->vecSize;
// update renderer
g_pHyprOpenGL->destroyMonitorResources(pMonitor);
if (pMonitorRule->enable10bit) {
// try 10b RGB
wlr_output_set_render_format(pMonitor->output, DRM_FORMAT_XRGB2101010);
pMonitor->enabled10bit = true;
if (!wlr_output_test(pMonitor->output)) {
Debug::log(ERR, "Output %s -> 10 bit enabled, but failed format DRM_FORMAT_XRGB2101010. Trying BGR.", pMonitor->output->name);
wlr_output_set_render_format(pMonitor->output, DRM_FORMAT_XBGR2101010);
if (!wlr_output_test(pMonitor->output)) {
Debug::log(ERR, "Output %s -> 10 bit enabled, but failed format DRM_FORMAT_XBGR2101010. Falling back to 8 bit.", pMonitor->output->name);
wlr_output_set_render_format(pMonitor->output, DRM_FORMAT_XRGB8888);
} else {
Debug::log(LOG, "10bit format DRM_FORMAT_XBGR2101010 succeeded for output %s", pMonitor->output->name);
}
} else {
Debug::log(LOG, "10bit format DRM_FORMAT_XRGB2101010 succeeded for output %s", pMonitor->output->name);
}
} else {
wlr_output_set_render_format(pMonitor->output, DRM_FORMAT_XRGB8888);
pMonitor->enabled10bit = false;
}
if (!wlr_output_commit(pMonitor->output)) {
Debug::log(ERR, "Couldn't commit output named %s", pMonitor->output->name);
@@ -997,7 +1196,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
pMonitor->vecSize = (Vector2D(x, y) / pMonitor->scale).floor();
pMonitor->vecTransformedSize = Vector2D(x,y);
if (pMonitorRule->offset == Vector2D(-1, -1)) {
if (pMonitorRule->offset == Vector2D(-1, -1) && pMonitor->vecPosition == Vector2D(-1, -1)) {
// let's find manually a sensible position for it, to the right.
Vector2D finalPos;
@@ -1011,13 +1210,17 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
}
pMonitor->vecPosition = finalPos;
} else if (pMonitorRule->offset != Vector2D(-1, -1)) {
pMonitor->vecPosition = pMonitorRule->offset;
}
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitor->vecPosition.x, (int)pMonitor->vecPosition.y);
wlr_output_enable(pMonitor->output, true);
// update renderer (here because it will call rollback, so we cannot do this before committing)
g_pHyprOpenGL->destroyMonitorResources(pMonitor);
// updato wlroots
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitor->vecPosition.x, (int)pMonitor->vecPosition.y);
Events::listener_change(nullptr, nullptr);
// updato us
@@ -1026,6 +1229,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
// frame skip
pMonitor->framesToSkip = 1;
// reload to fix mirrors
g_pConfigManager->m_bWantsMonitorReload = true;
return true;
}

View File

@@ -35,6 +35,7 @@ public:
void damageBox(const int& x, const int& y, const int& w, const int& h);
void damageRegion(pixman_region32_t*);
void damageMonitor(CMonitor*);
void damageMirrorsWith(CMonitor*, pixman_region32_t*);
bool applyMonitorRule(CMonitor*, SMonitorRule*, bool force = false);
bool shouldRenderWindow(CWindow*, CMonitor*);
bool shouldRenderWindow(CWindow*);

View File

@@ -38,7 +38,7 @@ void CHyprDropShadowDecoration::updateWindow(CWindow* pWindow) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
const auto WORKSPACEOFFSET = PWORKSPACE ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D();
const auto WORKSPACEOFFSET = PWORKSPACE && !pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D();
if (pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) {
m_vLastWindowPos = pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET;
@@ -48,7 +48,7 @@ void CHyprDropShadowDecoration::updateWindow(CWindow* pWindow) {
}
}
void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a) {
void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& offset) {
if (!g_pCompositor->windowValidMapped(m_pWindow))
return;
@@ -56,34 +56,25 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a) {
if (m_pWindow->m_cRealShadowColor.col() == CColor(0, 0, 0, 0))
return; // don't draw invisible shadows
if (!m_pWindow->m_sSpecialRenderData.decorate)
return;
if (m_pWindow->m_sAdditionalConfigData.forceNoShadow)
return;
static auto *const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
static auto *const PSHADOWSIZE = &g_pConfigManager->getConfigValuePtr("decoration:shadow_range")->intValue;
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
static auto *const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue;
static auto *const PSHADOWOFFSET = &g_pConfigManager->getConfigValuePtr("decoration:shadow_offset")->strValue;
static auto *const PSHADOWOFFSET = &g_pConfigManager->getConfigValuePtr("decoration:shadow_offset")->vecValue;
if (*PSHADOWS != 1)
return; // disabled
// get the real offset
Vector2D offset;
try {
if (const auto SPACEPOS = PSHADOWOFFSET->find(' '); SPACEPOS != std::string::npos) {
const auto X = PSHADOWOFFSET->substr(0, SPACEPOS);
const auto Y = PSHADOWOFFSET->substr(SPACEPOS + 1);
if (isNumber(X, true) && isNumber(Y, true)) {
offset = Vector2D(std::stof(X), std::stof(Y));
}
}
} catch (std::exception& e) {
return; // cannot parse
}
const auto ROUNDING = !m_pWindow->m_sSpecialRenderData.rounding ? 0 : (m_pWindow->m_sAdditionalConfigData.rounding == -1 ? *PROUNDING : m_pWindow->m_sAdditionalConfigData.rounding);
// update the extents
m_seExtents = {{*PSHADOWSIZE + 2 - offset.x, *PSHADOWSIZE + 2 - offset.y}, {*PSHADOWSIZE + 2 + offset.x, *PSHADOWSIZE + 2 + offset.y}};
m_seExtents = {{*PSHADOWSIZE + 2 - PSHADOWOFFSET->x, *PSHADOWSIZE + 2 - PSHADOWOFFSET->y}, {*PSHADOWSIZE + 2 + PSHADOWOFFSET->x, *PSHADOWSIZE + 2 + PSHADOWOFFSET->y}};
// draw the shadow
wlr_box fullBox = {m_vLastWindowPos.x - m_seExtents.topLeft.x + 2, m_vLastWindowPos.y - m_seExtents.topLeft.y + 2, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x - 4, m_vLastWindowSize.y + m_seExtents.topLeft.y + m_seExtents.bottomRight.y - 4};
@@ -91,6 +82,9 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a) {
fullBox.x -= pMonitor->vecPosition.x;
fullBox.y -= pMonitor->vecPosition.y;
fullBox.x += offset.x;
fullBox.y += offset.y;
if (fullBox.width < 1 || fullBox.height < 1)
return; // don't draw invisible shadows

View File

@@ -9,7 +9,7 @@ public:
virtual SWindowDecorationExtents getWindowDecorationExtents();
virtual void draw(CMonitor*, float a);
virtual void draw(CMonitor*, float a, const Vector2D& offset);
virtual eDecorationType getDecorationType();

View File

@@ -22,13 +22,13 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
const auto WORKSPACEOFFSET = PWORKSPACE ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D();
const auto WORKSPACEOFFSET = PWORKSPACE && !pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D();
if (pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) {
// we draw 3px above the window's border with 3px
const auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
const auto PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
m_seExtents.topLeft = Vector2D(0, BORDERSIZE + 3 + 3);
m_seExtents.topLeft = Vector2D(0, *PBORDERSIZE + 3 + 3);
m_seExtents.bottomRight = Vector2D();
m_vLastWindowPos = pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET;
@@ -45,7 +45,7 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
// get the group info
SLayoutMessageHeader header;
header.pWindow = g_pCompositor->m_pLastWindow;
header.pWindow = m_pWindow;
m_dwGroupMembers = std::any_cast<std::deque<CWindow*>>(g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "groupinfo"));
@@ -63,11 +63,14 @@ void CHyprGroupBarDecoration::damageEntire() {
g_pHyprRenderer->damageBox(&dm);
}
void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a) {
void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& offset) {
// get how many bars we will draw
int barsToDraw = m_dwGroupMembers.size();
if (barsToDraw < 1 || m_pWindow->m_bHidden || !g_pCompositor->windowValidMapped(m_pWindow))
if (barsToDraw < 1 || m_pWindow->isHidden() || !g_pCompositor->windowValidMapped(m_pWindow))
return;
if (!m_pWindow->m_sSpecialRenderData.decorate)
return;
const int PAD = 2; //2px
@@ -77,12 +80,17 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a) {
int xoff = 0;
for (int i = 0; i < barsToDraw; ++i) {
wlr_box rect = {m_vLastWindowPos.x + xoff - pMonitor->vecPosition.x, m_vLastWindowPos.y - m_seExtents.topLeft.y - pMonitor->vecPosition.y, BARW, 3};
wlr_box rect = {m_vLastWindowPos.x + xoff - pMonitor->vecPosition.x + offset.x, m_vLastWindowPos.y - m_seExtents.topLeft.y - pMonitor->vecPosition.y + offset.y, BARW, 3};
if (rect.width <= 0 || rect.height <= 0)
break;
CColor color = m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? CColor(g_pConfigManager->getInt("dwindle:col.group_border_active")) : CColor(g_pConfigManager->getInt("dwindle:col.group_border"));
scaleBox(&rect, pMonitor->scale);
static auto *const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:col.group_border_active")->intValue;
static auto *const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:col.group_border")->intValue;
CColor color = m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? CColor(*PGROUPCOLACTIVE) : CColor(*PGROUPCOLINACTIVE);
color.a *= a;
g_pHyprOpenGL->renderRect(&rect, color);

View File

@@ -10,7 +10,7 @@ public:
virtual SWindowDecorationExtents getWindowDecorationExtents();
virtual void draw(CMonitor*, float a);
virtual void draw(CMonitor*, float a, const Vector2D& offset);
virtual eDecorationType getDecorationType();

View File

@@ -22,7 +22,7 @@ public:
virtual SWindowDecorationExtents getWindowDecorationExtents() = 0;
virtual void draw(CMonitor*, float a) = 0;
virtual void draw(CMonitor*, float a, const Vector2D& offset = Vector2D()) = 0;
virtual eDecorationType getDecorationType() = 0;

View File

@@ -4,137 +4,35 @@
inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVarName) -> std::string {
return R"#(
if (pixCoord[0] < topLeft[0]) {
// we're close left
if (pixCoord[1] < topLeft[1]) {
// top
if (ignoreCorners == 1) {
// branchless baby!
highp vec2 pixCoord = vec2(gl_FragCoord);
pixCoord -= topLeft + fullSize * 0.5;
pixCoord *= vec2(lessThan(pixCoord, vec2(0.0))) * -2.0 + 1.0;
pixCoord -= fullSize * 0.5 - radius;
if (pixCoord.x + pixCoord.y > radius) {
float dist = length(pixCoord);
if (dist > radius)
discard;
return;
}
float topLeftDistance = distance(topLeft, pixCoord);
if (topLeftDistance > radius - 1.0) {
if (primitiveMultisample == 0 && topLeftDistance > radius) {
discard;
return;
} else if (primitiveMultisample == 1) {
if (primitiveMultisample == 1 && dist > radius - 1.0) {
float distances = 0.0;
if (distance(topLeft, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(topLeft, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(topLeft, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
if (distance(topLeft, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
distances += float(length(pixCoord + vec2(0.25, 0.25)) < radius);
distances += float(length(pixCoord + vec2(0.75, 0.25)) < radius);
distances += float(length(pixCoord + vec2(0.25, 0.75)) < radius);
distances += float(length(pixCoord + vec2(0.75, 0.75)) < radius);
if (distances == 0.0) {
if (distances == 0.0)
discard;
return;
}
distances = distances / 4.0;
distances /= 4.0;
)#" + colorVarName + R"#( = )#" + colorVarName + R"#( * distances;
}
}
} else if (pixCoord[1] > bottomRight[1]) {
// bottom
if (ignoreCorners == 1) {
discard;
return;
}
float topLeftDistance = distance(vec2(topLeft[0], bottomRight[1]), pixCoord);
if (topLeftDistance > radius - 1.0) {
if (primitiveMultisample == 0 && topLeftDistance > radius) {
discard;
return;
} else if (primitiveMultisample == 1) {
float distances = 0.0;
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
if (distances == 0.0) {
discard;
return;
}
distances = distances / 4.0;
)#" + colorVarName + R"#( = )#" + colorVarName + R"#( * distances;
}
}
}
}
else if (pixCoord[0] > bottomRight[0]) {
// we're close right
if (pixCoord[1] < topLeft[1]) {
// top
if (ignoreCorners == 1) {
discard;
return;
}
float topLeftDistance = distance(vec2(bottomRight[0], topLeft[1]), pixCoord);
if (topLeftDistance > radius - 1.0) {
if (primitiveMultisample == 0 && topLeftDistance > radius) {
discard;
return;
} else if (primitiveMultisample == 1) {
float distances = 0.0;
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
if (distances == 0.0) {
discard;
return;
}
distances = distances / 4.0;
)#" + colorVarName + R"#( = )#" + colorVarName + R"#( * distances;
}
}
} else if (pixCoord[1] > bottomRight[1]) {
// bottom
if (ignoreCorners == 1) {
discard;
return;
}
float topLeftDistance = distance(bottomRight, pixCoord);
if (topLeftDistance > radius - 1.0) {
if (primitiveMultisample == 0 && topLeftDistance > radius) {
discard;
return;
} else if (primitiveMultisample == 1) {
float distances = 0.0;
if (distance(bottomRight, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(bottomRight, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
if (distance(bottomRight, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
if (distance(bottomRight, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
if (distances == 0.0) {
discard;
return;
}
distances = distances / 4.0;
)#" + colorVarName + R"#( = )#" + colorVarName + R"#( * distances;
}
}
}
}
)#";
};
@@ -156,27 +54,20 @@ void main() {
inline const std::string QUADFRAGSRC = R"#(
precision mediump float;
varying vec4 v_color;
varying vec2 v_texcoord;
uniform vec2 topLeft;
uniform vec2 bottomRight;
uniform vec2 fullSize;
uniform float radius;
uniform int primitiveMultisample;
uniform int ignoreCorners;
void main() {
if (radius == 0.0) {
gl_FragColor = v_color;
return;
}
vec4 pixColor = v_color;
vec2 pixCoord = fullSize * v_texcoord;
if (radius > 0.0) {
)#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
}
gl_FragColor = pixColor;
})#";
@@ -199,7 +90,6 @@ uniform sampler2D tex;
uniform float alpha;
uniform vec2 topLeft;
uniform vec2 bottomRight;
uniform vec2 fullSize;
uniform float radius;
@@ -209,16 +99,14 @@ uniform int applyTint;
uniform vec3 tint;
uniform int primitiveMultisample;
uniform int ignoreCorners;
void main() {
vec4 pixColor = texture2D(tex, v_texcoord);
if (discardOpaque == 1 && pixColor[3] * alpha == 1.0) {
if (discardOpaque == 1 && pixColor[3] * alpha == 1.0)
discard;
return;
}
if (applyTint == 1) {
pixColor[0] = pixColor[0] * tint[0];
@@ -226,10 +114,7 @@ void main() {
pixColor[2] = pixColor[2] * tint[2];
}
vec2 pixCoord = fullSize * v_texcoord;
)#" + ROUNDED_SHADER_FUNC("pixColor") +
R"#(
)#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
gl_FragColor = pixColor * alpha;
})#";
@@ -241,7 +126,6 @@ uniform sampler2D tex;
uniform float alpha;
uniform vec2 topLeft;
uniform vec2 bottomRight;
uniform vec2 fullSize;
uniform float radius;
@@ -251,14 +135,11 @@ uniform int applyTint;
uniform vec3 tint;
uniform int primitiveMultisample;
uniform int ignoreCorners;
void main() {
if (discardOpaque == 1 && alpha == 1.0) {
if (discardOpaque == 1 && alpha == 1.0)
discard;
return;
}
vec4 pixColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);
@@ -268,10 +149,7 @@ void main() {
pixColor[2] = pixColor[2] * tint[2];
}
vec2 pixCoord = fullSize * v_texcoord;
)#" + ROUNDED_SHADER_FUNC("pixColor") +
R"#(
)#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
gl_FragColor = pixColor * alpha;
})#";
@@ -293,6 +171,7 @@ void main() {
sum += texture2D(tex, uv + halfpixel.xy * radius);
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;
}
)#";
@@ -332,7 +211,6 @@ uniform samplerExternalOES texture0;
uniform float alpha;
uniform vec2 topLeft;
uniform vec2 bottomRight;
uniform vec2 fullSize;
uniform float radius;
@@ -342,16 +220,13 @@ uniform int applyTint;
uniform vec3 tint;
uniform int primitiveMultisample;
uniform int ignoreCorners;
void main() {
vec4 pixColor = texture2D(texture0, v_texcoord);
if (discardOpaque == 1 && pixColor[3] * alpha == 1.0) {
if (discardOpaque == 1 && pixColor[3] * alpha == 1.0)
discard;
return;
}
if (applyTint == 1) {
pixColor[0] = pixColor[0] * tint[0];
@@ -359,10 +234,8 @@ void main() {
pixColor[2] = pixColor[2] * tint[2];
}
vec2 pixCoord = fullSize * v_texcoord;
)#" + ROUNDED_SHADER_FUNC("pixColor") +
R"#(
)#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
gl_FragColor = pixColor * alpha;
})#";
}
)#";