Compare commits

..

181 Commits
v0.42.0 ... nix

Author SHA1 Message Date
Mihai Fufezan
48f2f490d0 Nix: drop ninja for CMake build 2024-09-22 12:43:17 +03:00
Mihai Fufezan
94c7996b87 Revert "nix: use meson"
This reverts commit d505b33665.
2024-09-22 12:43:17 +03:00
Mihai Fufezan
674e7df000 Revert "nix: adapt cmake options"
This reverts commit c35ed8363f.
2024-09-22 12:43:17 +03:00
Mihai Fufezan
cb7f9140da CMake: print pch messages based on var 2024-09-22 12:30:18 +03:00
Mihai Fufezan
8579066c7a Nix: clean up derivation 2024-09-21 14:27:13 +03:00
Vaxry
9232bc2c00 internal: move to hyprutils' scopeguard
bumps hyprutils dep to 0.2.2
2024-09-21 00:37:17 +01:00
Vaxry
db0b764a5a shm: send a static list of shm formats
fixes #7733
2024-09-20 22:56:15 +01:00
Mihai Fufezan
278583b8a1 flake.lock: update 2024-09-20 20:16:13 +03:00
Jasson
4414cd07e2 xwm: Minor cleanup, add wrappers for basic types (#7856) 2024-09-20 12:32:04 +01:00
Vaxry
9e98fb0167 dmabuffer: attempt importing failed dmabufs as implicit
don't ask me why, vulkan doesn't like this.

funny note, broken on wlroots :P

fixes #7037
2024-09-20 10:47:41 +01:00
Mihai Fufezan
9856378384 Nix: use mold linker 2024-09-19 18:53:34 +03:00
Mihai Fufezan
dfa1bd0cd4 Meson: pass AQUAMARINE_VERSION argument 2024-09-19 13:48:31 +00:00
vaxerski
92df6b0dce version: log build aquamarine version
log the built against aq version, might be useful when it's mismatched to identify the problem
2024-09-19 11:40:00 +01:00
vaxerski
71963972bf args: add --version to binary args 2024-09-19 11:40:00 +01:00
Arisa Snowbell
1bc05b1f9f xwayland: use proper path for the XWayland sockets (#7852)
fixes #7849
2024-09-19 11:08:02 +01:00
Vaxry
e6cf643f5a pointermgr: Hide hardware cursor on leave (#7806) 2024-09-18 18:47:53 +01:00
Jasson
94140e886e xwayland: Some readability improvements (#7807)
* Readability improvements xwayland server

* Made requested changes

* removed braces

* fix

* Ok this time is fixed

* Formatting
2024-09-18 18:12:26 +01:00
Mihai Fufezan
b248d59713 Nix: fix meson PCH flag 2024-09-18 19:43:56 +03:00
Mihai Fufezan
cbc0ff6ec0 Nix: disable PCH 2024-09-18 18:54:00 +03:00
Mihai Fufezan
6b6554adb8 flake.nix: inherit stdenv from package
Means we no longer have to change the base stdenv in two places.
2024-09-18 18:43:39 +03:00
Mihai Fufezan
d936eb437b flake.lock: update aquamarine 2024-09-18 17:26:51 +03:00
vaxerski
883d01084c userchecks: add an xdg_current_desktop check
ref https://github.com/hyprwm/xdg-desktop-portal-hyprland/issues/251

if the XDG_CURRENT_DESKTOP is externally managed (e.g. DE, DM, etc) Hyprland will not overwrite it. In those cases, if that's undesired, portals and other apps depending on it might break.
2024-09-18 11:22:12 +01:00
Aqa-Ib
0564b46a5e dispatchers: allow moveintogroup when floating (#7818)
This allows to use the moveintogroup dispatcher when windows are floating. I don't know why was this disabled in the first place though.

Cheers!
2024-09-18 11:05:17 +01:00
André Silva
3c9716acfd gammactrl: fix potential crash on monitor removed (#7828) 2024-09-17 14:37:20 +01:00
vaxerski
581f6659f8 data-device: conform to reported source actions
fixes #7815
2024-09-17 12:55:48 +01:00
vaxerski
e72ae6b25f hyprctl: allow parsing empty value
fixes #7821
2024-09-17 11:24:54 +01:00
Leiser Fernández Gallo
9e35656244 internal: Delay monitor events/hooks (#7797)
* Delay monitor messages

* Format
2024-09-15 21:03:42 +01:00
AlvinaNancy
e87758529e internal: Fix change group current fullscreen state query (#7802) 2024-09-15 18:25:06 +01:00
Sungyoon Cho
eb97d949aa textinput: don't reset if ti isn't enabled (#7798) 2024-09-15 17:31:38 +01:00
Ikalco
e74efd87e5 internal: fix initial cursor warping (#7793) 2024-09-14 23:37:18 +01:00
Vaxry
4dbdb556fe data-device: don't send default action of move
gtk doesn't like it?
2024-09-14 23:36:06 +01:00
Vaxry
5ee4b19691 data-device: send clock time in motion events
remove hack
2024-09-14 23:35:45 +01:00
Vaxry
d35e70a8c6 cmake: drop ninja dep 2024-09-13 17:56:44 +01:00
diniamo
c35ed8363f nix: adapt cmake options 2024-09-13 19:44:38 +03:00
diniamo
d505b33665 nix: use meson 2024-09-13 17:54:49 +03:00
Sungyoon Cho
118be4dea0 textinput: fix tiv3 leave (#7761) 2024-09-12 17:41:24 +01:00
trianta
73b9756b8d xwayland: remove extra x11 deactivation (#7755) 2024-09-12 10:15:01 +01:00
fufexan
8b9e385943 [gha] Nix: update inputs 2024-09-11 16:10:51 +00:00
Mihai Fufezan
e01da1fd7a Meson: format 2024-09-11 19:09:17 +03:00
Mihai Fufezan
7a8c013edc Meson: fix protocols, clean up 2024-09-11 19:09:16 +03:00
Vaxry
518399a95b pointermgr: avoid derefing null outputs 2024-09-11 09:30:21 +01:00
Sungyoon Cho
155d44016d textinput: handle IME resetting (#7731) 2024-09-10 14:49:10 +01:00
Alexandre Acebedo
13f90bb87a update xdph commit in flake.lock 2024-09-10 16:38:47 +03:00
davc0n
c67b257e51 build: Set cmake_minimum_required to version 3.30 (#7709)
* build: Set cmake_minimum_required to version 3.30

* Nix: add patch for CMake min ver

---------

Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
2024-09-10 11:06:37 +01:00
Maximilian Seidler
8237d7e1a4 input: move dmps activation to input listeners (#7721) 2024-09-09 21:29:00 +01:00
vaxerski
85da1a17d8 [gha] build man pages 2024-09-09 15:19:44 +00:00
justmessingaround
9609b04ff9 man: Fixed the man page to show the new information (#7713)
* Update Hyprland.1.rst

* Update Hyprland.1
2024-09-09 16:19:17 +01:00
darkwater
04421063af config: add order rule for layers (#7697) 2024-09-09 10:10:08 +01:00
davc0n
43e1415e71 assets: Remove execute permission from lockdead.png (#7715) 2024-09-09 10:01:26 +01:00
Sungyoon Cho
e1448732b3 tiv1: fix deleting first character (#7716) 2024-09-09 09:58:44 +01:00
Richard Ayotte
7c4c402bd7 config: include XF86Audio* key bindings to default cfg (#7695) 2024-09-08 22:04:07 +01:00
Aqa-Ib
6179b17903 github: improve issue template (#7699)
* github: improve issue template

Require to check that you have searched through open and closed issues before committing.

* fix yaml syntax

* clarify text

* validation

* revert validation

* markdown

* done
2024-09-08 21:12:01 +01:00
Davide Conti
05b48d48d9 config: Limit max volume to 100% 2024-09-08 22:53:28 +03:00
diniamo
07a21fdfa9 github(nix-build): switch to better nix installer, attempt at fixing hash mismatch (#7701)
* github(nix-build): switch to DeterminateSystems/nix-installer-action

* github(nix-build): switch to a direct git reference instead of cloning

* github(nix-ci): attempt to fix CI for pull requests
2024-09-08 21:20:45 +03:00
Vaxry
0f594732b0 props: bump version to 0.43.0 2024-09-08 17:48:21 +01:00
Vaxry
312411fc70 windows: support size with pseudo tiled
fixes #7690
2024-09-08 00:46:46 +01:00
trianta
70add904c4 config: add exec-shutdown for running commands on shutdown (#7683)
* config: add exec-shutdown for running commands on shutdown

* compositor: delay stopping until after exec-shutdown
2024-09-07 20:54:33 +01:00
Darth ŠČ!
5ca4823128 config: Added default button mapping for xf86 keys (#7672)
* Added default button mapping for laptop multimedia keys for volume and brightness

* Added default button mapping for laptop multimedia keys for volume and brightness into example config
2024-09-07 16:14:23 +01:00
outfoxxed
0500213086 input: try to refocus a focusable window when seat grabs are reset (#7669) 2024-09-07 01:06:55 +01:00
outfoxxed
b0fca6eaf0 input: kb focus mouse focused window if unset (#7666)
Normally it shouldn't be possible to have mouse focus with no kb
focus, but it does happen, and when it does this makes it considerably
less annoying.
2024-09-06 01:03:12 +01:00
Maximilian Seidler
4988e00b1d input: move idle notify to input handlers (#7659)
* Revert "input: don't emit idle activity when calling simulateMouseMovement (#7649)"

This reverts commit ea10592ad3.

* input: move idle notify calls to input event listeners

* input: don't post idle activity when keyboard is not enabled
2024-09-06 00:58:57 +01:00
Sungyoon Cho
0fad7a0bb0 workspacerules: fix on-created-empty window focus (#7657) 2024-09-06 00:54:01 +01:00
Sungyoon Cho
727f1b54cd textinput: fix ime activation in some edge cases (#7660)
* textinput: clear ti3 state when focused surface gets destroyed

* textinput: send enter to newly created ti in focus
2024-09-05 20:04:23 +01:00
Mihai Fufezan
c80457be02 nix: add COMMITS var 2024-09-05 21:26:12 +03:00
Parola Marco
4a42c5ed20 config: Add a variable to prevent groups from merging after being dragged (#7650)
* config: Add a variable to prevent groups from merging after being dragged

* Fixed code style for [f777f028]
2024-09-05 17:29:33 +01:00
trianta
bd6d6e7f33 xwayland: add option to enable/disable xwayland (#7633)
* config: add xwayland enabled option to config

* xwayland: use DISPLAY env variable for enable/disable of new launches

* xwayland: close X11 windows when turning of XWayland

* clang: format fix

* config: add better description for xwayland:enabled

* xwayland: close X11 windows on disable without crashes

* xwayland: better method of informing CXWayland if xwayland enabled

* xwayland: prevent closing non-xwayland windows on disable

* misc: loop formatting
2024-09-05 17:26:46 +01:00
Maximilian Seidler
027140b731 sessionLock: ensure sls focus in some edge cases (#7647)
* input: return early in mouseMoveUnified when the session is locked

* sessionLock: make make a commit an opportunity to focus session lock surfaces

* compositor: allow resetting focus when session is locked

* input: remove redundant PMONITOR checks

PMONITOR is checked above

* input: check isSessionLocked earlier in mouseMoveUnified

A bit of reordering, so that we don't call some stuff that is irrelevant
when the session is locked
2024-09-04 16:59:00 +01:00
Maximilian Seidler
ea10592ad3 input: don't emit idle activity when calling simulateMouseMovement (#7649) 2024-09-04 11:23:29 +01:00
vaxerski
9b54342baa Revert "syncobj: wait for deadline instead of available"
This reverts commit cf6a1716ae.

Fixes #7628
2024-09-03 14:47:34 +02:00
Mihai Fufezan
8f9887b0c9 Nix: remove unused dependencies 2024-09-02 23:48:58 +03:00
Jan Beich
fa39df4731 CMake: drop unused deps after 016da234d0
Found via LDFLAGS += -Wl,--as-needed (default in Meson).
Some dependencies are only used by aquamarine.
2024-09-02 23:48:58 +03:00
Jan Beich
f7249bd331 CMake: drop duplicate -luuid after 5262292abc 2024-09-02 23:48:58 +03:00
Sungyoon Cho
6934e7aa2b textinput: don't deactivate ime if another ti is focused (#7617) 2024-09-01 21:33:31 +02:00
Sungyoon Cho
8bbeee2041 textinput: send deactivate to ime on destory ti (#7614) 2024-09-01 18:44:33 +02:00
Mihai Fufezan
7a24e564f4 flake.lock: update xdph again 2024-09-01 19:37:25 +03:00
Mihai Fufezan
4b5b8a7630 flake.lock: update xdph 2024-09-01 18:14:14 +03:00
Mihai Fufezan
5b1375141b flake.lock: update 2024-09-01 17:18:57 +03:00
Tom Englund
4af9410dc2 xwm: read atom name from xcb (#7546)
expand the debug trace logging by actually reading the atom name from
xcb if not found in HYPRATOMS, will also print the proper atom for xcb
internal ones and not just the HYPRATOMS ones.
2024-09-01 12:04:28 +02:00
Ikalco
a6315b0af4 core: fix crash on monitor removed with gammaControl (#7601)
* fix crash on monitor removed with gammaControl

* Update GammaControl.cpp
2024-08-31 21:55:08 +02:00
TheMical
cac59fefec data-device: Fix selection mismatch when wlr resets primary selection (#7598) 2024-08-31 21:43:02 +02:00
Ikalco
1ac2fc3f7e protocols: destroy new xdgDialog protocol at right time (#7600) 2024-08-31 21:07:23 +02:00
Vaxry
cf6a1716ae syncobj: wait for deadline instead of available
avoids slow apps from lagging the desktop
2024-08-31 18:33:04 +02:00
NotAShelf
10d7219807 CI: clarify Nix CI jobs; disable on forked repositories 2024-08-31 17:17:36 +03:00
Ikalco
838ed87d6f renderer: minor direct scanout fixes (#7594) 2024-08-31 15:07:52 +02:00
Jan Beich
76b82fdde7 meson: explicitly specify path for find(1) (#7590)
assets/install/meson.build:1:10: ERROR: Command `/bin/sh -c 'find -type f -not -name "*.build"'` failed with status 1.
2024-08-31 11:01:02 +02:00
Vaxry
c5fd577181 config: Add a window rule to render while unfocused (#7582) 2024-08-30 17:37:52 +02:00
Vaxry
fbd6354393 presentation-feedback: minor fixups 2024-08-30 15:53:45 +02:00
Vaxry
fd8d8e122e keybinds: fixup misused kb state
fixes #7369
2024-08-30 15:53:45 +02:00
Vaxry
1c9d56998d xdg-dialog: implement new protocol 2024-08-30 15:53:44 +02:00
darkwater
242e06b242 keybinds: release mods after sendshortcut (#7581) 2024-08-30 15:06:49 +02:00
Vaxry
25e72949a1 window/xwayland: minor property cleanup
fixes #6921
2024-08-30 14:12:23 +02:00
trianta
259dcd838e xwayland: update overrideRedirect on map and configure (#7575) 2024-08-30 14:04:09 +02:00
Mihai Fufezan
ef33198e8f flake.lock: update aquamarine and hyprutils 2024-08-30 14:10:46 +03:00
Vaxry
604eb21a7e renderer: better lockscreen dead behavior (#7574)
---------

Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
2024-08-29 23:30:12 +02:00
Mihai Fufezan
92a0dd164e flake.lock: update 2024-08-29 13:41:03 +00:00
Vaxry
b9b8e6220f renderer: fade out windows on silent moves 2024-08-28 21:54:49 +02:00
Vaxry
a95df6b57e xwm: don't mark selection events as succeeded
fixes #7401
2024-08-28 20:37:07 +02:00
Vaxry
9642311ac2 window: don't focus on activate if window isn't mapped yet
ref #7089
2024-08-28 20:33:38 +02:00
Ikalco
98e99cd03d renderer: ensure buffer format on commit (#7556) 2024-08-28 15:07:13 +02:00
diniamo
8210a1d7ac nix(flake): update aquamarine 2024-08-28 15:28:01 +03:00
Vaxry
d105c7403c hyprctl: add next and all to switchxkblayout
fixes #7555
2024-08-28 14:05:31 +02:00
Vaxry
00ee1cf98e data-device: send dndFinished when dnd offer is destroyed while unfinished
fixes #7496

see 711c5bb43f

see https://bugs.kde.org/show_bug.cgi\?id\=482142
2024-08-28 13:45:13 +02:00
Ikalco
7dd0f76e5a logs: don't get timezone every time logging (#7550)
its expensive cause cpp dum
2024-08-28 13:19:06 +02:00
Tom Englund
17ed4fc04c hyprctl: avoid parsing string::npos on invalid cmd (#7544)
* hyprctl: avoid parsing string::npos on invalid cmd

invalid lines passed to hyprctl keyword made the string parsing try to
parse std::string::npos, avoid that and return an error text instead.

* style

---------

Co-authored-by: Vaxry <vaxry@vaxry.net>
2024-08-27 20:42:30 +02:00
Nick H
6a8824253c build: Fix NO_XWAYLAND compilation (#7538) 2024-08-27 20:41:46 +02:00
Serenity Braesch
eb42adc4c0 Fix missing include needed by clang 2024-08-26 22:36:43 +03:00
raf
09dbcabcc7 CI: disable stale workflow on forks (#7535)
The stale workflow will run unconditionally, but will fail on forks due to
`STALEBOT_PAT` not being set. Trigger the workflow *only* if we are on the
main repo, where we can guarantee the PAT. Also formats the YML syntax to be
slightly more readable.
2024-08-26 20:24:57 +02:00
Tom Englund
72c7818ae6 misc: constify the remaining for loops (#7534)
now we roll loops at blazing constified speed.
2024-08-26 20:24:30 +02:00
Tom Englund
1ea47950f4 misc: fix some minor typos (#7530)
* keybindmgr: fix typo in swap prev

seems a suspicious extra ) got added, remove it.

* configmgr: dont dereference invalid iterator

i think the idea here was to print the key and not the iterator at or
past .end()
2024-08-26 18:02:44 +02:00
Tom Englund
8d6c18076f core: make most for loops use const references (#7527)
why not let the compiler optimise things for us at hyprspeeds when we
can.
2024-08-26 17:25:39 +02:00
Tom Englund
9c5a37a797 build: fix 32bit builds (#7510)
ensure the correct type is passed to std::clamp and std::max int64_t is
different on 64bit compared to 32bit, also in presentationtime
tv_sec is __time_t and on 32bit its a 32bit type so right shift count >= width
of type. so only bit shift on 64bit. and avoid potential nullptr deref
in the for loops, check for .end() before *it <= endID.
2024-08-26 14:08:30 +02:00
Adithya Ajith
ca85455a8e misc: Rename all instances of "emtpy" to "empty" (#7522) 2024-08-26 12:25:52 +02:00
Maximilian Seidler
28f6c2df59 sessionLock: fix misc:allow_session_lock_restore (#7511)
* Revert "sessionLock: fix the check for locking a locked session (#6843)"

This reverts commit 9ff83f4aa9.

* sessionLock: remove early check for session beeing locked

It is checked in the `onNewSessionLock` handler, which also respects the
`misc:allow_session_lock_restore` option.
2024-08-26 10:27:34 +02:00
Vaxry
83ab3ae0af xwaylandmgr: minor refactor to activateSurface
Make it more efficient now that we can + fix possible nullptr deref

fixes #7514
2024-08-26 10:24:45 +02:00
trianta
b672118f92 xwayland: deactivate xwayland focus if wayland is focused (#7458)
* xwayland: deactivate xwayland focus if wayland is focused

* xwayland: deactivate last xwayland surface after focusing wayland
2024-08-25 16:37:03 +02:00
Nelo-T. Wallus
aac90d9279 hyprpm: Fix checking dependencies (#7504)
* hyprpm: Fix checking dependencies

* hyprpm: Check for dependency "pkg-config"

---------

Co-authored-by: Nelo-T. Wallus <nelo@wallus.de>
2024-08-25 13:13:48 +02:00
Ikalco
66586c38f5 keybinds: refactor dispatchers to be better (#7331) 2024-08-24 18:45:53 +02:00
Vaxry
82c67e61a9 config: fix uninitialized values with mode parsing 2024-08-24 15:24:55 +02:00
Vaxry
e45e606fbd layersurface: don't unref from monitor until dtor
reee
2024-08-24 15:22:10 +02:00
Sungyoon Cho
688fe5c147 windowrules: add fullscreenstate field (#7466)
* windowrules: add fullscreenstate field

* fix typo
2024-08-23 20:42:14 +01:00
MahouShoujoMivutilde
a3b75559b3 input: Fix modifier keys getting stuck if depressed during config reload (#7486)
The problem:
    If `input:numlock_by_default = true`, depressed mods will get stuck
    on config reload; this takes effect after some other mod is pressed.

This restores 0.41.2 behavior, with the exception that selected keyboard
layout is preserved.

918d8340af/src/managers/input/InputManager.cpp (L993-L1002)
2024-08-23 20:35:52 +01:00
Tom Englund
df4f222482 layersurface: remove layer on destroy from monitor (#7457)
remove destroyed layer weakptrs on destroy, we can hit multiple
null ptr derefs in renderering on mirroring and unmirroring displays
otherwise.
2024-08-23 14:06:52 +01:00
vaxerski
3b663f4afc screencopy: fixup 10-bit sharing via shm on nvidia 2024-08-23 14:13:49 +02:00
Red
f634b9e61a Fix crash reports having execute permission 2024-08-22 15:28:01 +03:00
Mihai Fufezan
bdb296a83c flake.lock: update 2024-08-22 14:30:17 +03:00
Mihai Fufezan
4fa63104c9 Nix: exclude wayland-scanner until next staging merge 2024-08-22 14:30:10 +03:00
Florian Klink
a437e44a6a CMakeLists: wayland.xml is in wayland-scanner pkgdatadir
See 6c4a695045/meson.build (L129-136)

Similar fix as https://github.com/hyprwm/aquamarine/pull/55.
2024-08-22 13:50:00 +03:00
Tom Englund
cae937c51b layersurface: dont rollover on size_t (#7451)
unneded rollover on size_t if force equals -1
2024-08-21 22:05:03 +01:00
James R Larrowe
8162fae377 Fix Makefile too
... did this ever work?
2024-08-21 23:09:13 +03:00
James R Larrowe
c5786be695 Fix static asan patch 2024-08-21 23:09:13 +03:00
Mihai Fufezan
1b1ecf77e0 Nix: include xcursor regardless of xwayland 2024-08-21 22:37:28 +03:00
vaxerski
883463f9dd animations: add workspace in/out configs 2024-08-21 14:38:07 +02:00
Tom Englund
3e7325af57 output: dont cast enum out of range (#7448)
avoid casting non typed enum out of range, looks like
WL_OUTPUT_MODE_CURRENT was the intention here.
2024-08-21 11:52:40 +01:00
ParaN3xus
946ed1f32a core: add option to control which window to focus on close (#7368) 2024-08-21 11:24:42 +01:00
Ali Atashrooz
4eff224a7f example/config: fix typo in default config (#7446)
* Update hyprland.conf

* Update defaultConfig.hpp
2024-08-21 11:24:02 +01:00
vaxerski
c86db7bbb0 monitor: avoid dangling references to old monitors being undestroyed
ref #7414
2024-08-19 18:44:22 +02:00
vaxerski
272d904870 monitors: avoid crash on wayland output removal 2024-08-19 18:36:14 +02:00
JL2210
01e3da4d51 examples: more systemd examples (#7409)
These allow launching hyprland with a systemd service. They provide
graphical-session.target which allows enabling services such as the
ones for Waybar and Mako.
2024-08-19 14:02:09 +01:00
Jan Beich
33015546c6 config: add missing header for libc++ after 92744b5b9a (#7403)
In file included from src/pch/pch.hpp:1:
In file included from src/Compositor.hpp:11:
src/config/ConfigManager.hpp:147:10: error: no template named 'variant' in namespace 'std'
  147 |     std::variant<SBoolData, SRangeData, SFloatData, SStringData, SColorData, SChoiceData, SGradientData, SVectorData> data;
      |     ~~~~~^
2024-08-19 13:46:36 +01:00
loseardes77
83d88fa564 hyprpm, hyprctl: update shell completions 2024-08-19 00:21:59 +03:00
diniamo
11dfb8397b flake: update aquamarine 2024-08-19 00:18:26 +03:00
vaxerski
f4045ab8d0 screencopy: fix 10b format r/b flip 2024-08-18 22:57:21 +02:00
vaxerski
fa12efdd2a protocol: fix logm template checks 2024-08-18 22:54:47 +02:00
vaxerski
bf611fbbf3 screencopy: nuke unused stuff 2024-08-18 22:40:21 +02:00
Tom Englund
5afc4dc42e compositor: update suspendstate on window move (#7396)
hyprctl dispatch -- movetoworkspacesilent x,"^kitty$" where X is the
current workspace makes kitty stops updating until current workspace is
changed while it is on the screen. update the suspend state after it has
been moved.
2024-08-18 20:02:46 +01:00
vaxerski
50348a3ddb renderer: pass custom modelines to aq
ref #7390
2024-08-18 20:19:13 +02:00
vaxerski
279ec1c291 linux-dmabuf: allow on split-node systems
ref #7364
2024-08-18 19:52:01 +02:00
Tom Englund
1006663b6e shm: align size to stride (#7383)
calculate the size to the stride we got to better align it.
2024-08-18 09:23:27 +01:00
Sami Liedes
b2a18aa80a input: Fix disabling tap-to-click (#7304)
* Allow disabling tap-to-click

* Style fix
2024-08-18 08:14:42 +01:00
leiserfg
d21a6b12b8 Update aquamarine input in flake 2024-08-18 09:47:39 +03:00
vaxerski
912e7ba82d render: fixup format mismatch after leaving DS
fixes #7373
2024-08-17 19:27:20 +02:00
Vaxry
92744b5b9a IPC: Add config descriptions (#7377)
Thanks @gulafaran for the work

---

Co-authored-by: @gulafaran
2024-08-17 17:33:16 +01:00
Tom Englund
c5feee1e35 xcursormgr: dont apply scale on gsettings (#7316)
gtk scales the cursor size itself since its CSD so if we scale the size
its gonna get double scaled. incorporate the scale into xcursormanager
to keep track of it.
2024-08-16 17:00:59 +01:00
Tom Englund
1840a907a8 renderbuffer: ensure framebuffer gets deleted (#7363)
after commit 4b4971c it uses m_iFbAllocated and deletes if upon calling
release() but Renderbuffer generates directly on m_iFb without calling
alloc() meaning it wont be deleted on release(), set m_iFbAllocated to
true after generating the buffer.
2024-08-16 10:09:01 +01:00
Vladimir-csp
682b30fba8 env: Add HYPRLAND_NO_SD_VARS env condition (#7358)
* Add HYPRLAND_NO_SD_VARS env condition

wip #7083

* Formatting shuffle

* Formatting
2024-08-16 08:19:08 +01:00
Tom Englund
12d9901472 protocols: refactor protocol logging to a macro (#7324)
this avoids the usage of the unique_ptr PROTO::protocol before it has
been constructed incase one wants to log something inside the
constructor itself, move the logging to macros and print file:linenumber
on ERR,CRIT,WARN and classname on the rest of the levels.
2024-08-15 17:16:18 +01:00
Vladimir-csp
15f942000e core: Preserve existing XDG_CURRENT_DESKTOP (#7347)
* Preserve existing XDG_CURRENT_DESKTOP

* fix

---------

Co-authored-by: vaxerski <vaxry@vaxry.net>
2024-08-15 17:14:48 +01:00
Maximilian Seidler
520e91238f gamma-control: fix crash on monitor disconnect (#7353) 2024-08-15 17:08:54 +01:00
Kyle
0c56be74a3 keybinds: Fix syncFullscreen inconsistent with state when set by fullscreenState (#7343)
* Set syncFullscreen to true on synced non -1 states

* Fix syncFullscreen value in fullscreenState
2024-08-15 17:04:24 +01:00
Mirkwood
069faa4027 helpers: fix: revert to signed arithmetic for cycling through workspaces (#7339)
The code clearly expects signed types there.
Fixes #7329
2024-08-15 13:03:23 +01:00
vaxerski
c30dfe92ee [gha] Nix: update inputs 2024-08-15 11:39:29 +00:00
Ikalco
d85ae306c5 xcursor: handle file errors when loading xcursor themes (#7326) 2024-08-15 12:37:56 +01:00
davc0n
197f880790 logs: Add file path to asset ERR log (#7336) 2024-08-14 18:35:07 +01:00
MightyPlaza
3b4aabe04c decorations: fix manual resize not recalculating decos (#7323)
modified:   src/layout/DwindleLayout.cpp
modified:   src/layout/MasterLayout.cpp
2024-08-13 21:00:31 +01:00
Mihai Fufezan
c5ec079c6f hyprpm, hyprctl: remove Makefiles 2024-08-13 22:14:58 +03:00
Patrick Ulbricht
4aec237ec0 README: Change image sources from vaxerski/Hyprland to hyprwm/Hyprland (#7315)
* readme: Change image sources from vaxerski/Hyprland to hyprwm/Hyprland

* readme: Remove unused image
2024-08-13 19:14:52 +01:00
Ikalco
39df1f4dbf cursormgr: fix cursor gsettings on session change (#7295) 2024-08-13 18:27:00 +01:00
Tom Englund
77cf651825 protocols: avoid crashing in drmlease (#7290)
instead of potentially causing wonky behaviour from destructing in the
constructor add the unique_ptr reset to doLater and dont use the not
done constructed protolog in the constructor, call Debug::log directly.

see issue #7240
2024-08-12 19:49:52 +01:00
Kyle
c7b72790bd keybinds: Fix fullscreenState toggling behaviour (#7288)
* Update fullscreen state dispatcher behaviour

* Change syncFullscreen default to false

* Revert all changes

* Modify fullscreenstate dispatcher toggle behaviour

* Update syncFullscreen according to state

* Update syncFullscreen before setting fullscreen state
2024-08-12 18:41:26 +01:00
Tom Englund
3fa6db1e7a core: fix data race and a unsigned int rollover (#7278)
* keybindmgr: avoid uint rollover on mouse keycode

mouse keycode is 0, and the switch case checks for 0 - 8 and rolls over,
just return early if keycode is 0.

* watchdog: avoid data races in watchdog

asan thread sanitizer reported data races in the watchdog from reading
and setting the bool variables make them std::atomic bools. also add a
atomic bool for the main thread to wait for to avoid data race when
reading the config values.

* hyprdebug: change non unicode character to name

asan created false positives and didnt like this bit, so for the sake of
easier debugging rename it to something unicode.
2024-08-12 18:19:03 +01:00
Ikalco
d361fcbd85 config: fix explicit sync option warning (#7293) 2024-08-12 17:16:00 +01:00
Mihai Fufezan
df9d830117 flake.lock: update 2024-08-12 18:18:03 +03:00
Yang, Ying-chao
118d4e1001 install: Prepend ${DESTDIR} when creating hyprland symbolic link (fixes #7280). (#7281) 2024-08-11 20:38:16 +01:00
Tom Englund
511eea71c6 pointermgr: fix initial cursorwarp (#7286)
change the hook to monitorAdded instead of newMonitor so its finalized
in the compositor and added to vMonitors, move the
checkDefaultCursorWarp to PointerManager and check for it upon mode
change. and also ensure it doesnt go out of bounds by replacing it in
the middle again on resolution changes.
2024-08-11 19:42:18 +01:00
Walt Bringenberg
01ff5fdf6a cursor: make inactive_timeout setting a float (#7268) 2024-08-10 21:42:45 +01:00
Zach DeCook
0bf9ceb53b core: Include cstring whenever strncpy is used (#7267)
Fixes ppc64le build in alpine
2024-08-10 21:09:12 +01:00
Vaxry
4fdc0d55e4 eventloop: don't dispatch in enterLoop
ref #6842, BSD blocks in udev on no event apparently
2024-08-10 00:04:26 +02:00
Tom Englund
8b37e81374 cursormgr: add a new setting to sync gsettings (#7253)
cursor:sync_gsettings_theme is set to default true and if enabled it
will now sync xcursor theme loading with gsettings if it can, meaning
CSD clients will now also change to the appropiate theme upon start and
hyprctl setcursor THEME SIZE .
2024-08-09 19:33:20 +02:00
Mathis H.
fd1d4e288e headers: set correct paths to header files (#7245) 2024-08-09 16:51:21 +02:00
Tom Englund
4b4971c06f internal: introduce new types to avoid unsigned int rollover and signed int overflow (#7216)
* framebuffer: avoid gluint overflow

GLuint was being initialized to -1 and rolling over to unsigned int max,
its defined behaviour but very unnecessery. add a bool and use it for
checking if allocated or not.

* opengl: avoid gluint rollover

-1 rolls over to unsigned int max, use 0xFF instead.

* core: big uint64_t to int type conversion

there were a few uint64_t to int implicit conversions overflowing int
and causing UB, make all monitor/workspaces/windows use the new
typedefs. also fix the various related 64 to 32 implicit conversions
going around found with -Wshorten-64-to-32
2024-08-08 21:01:50 +02:00
Vaxry
83a334f97d core: Move to C++26 and use native_handle to CLOEXEC the debug fd (#7219)
Requires GCC >= 14 / Clang >= 18

---------

Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
2024-08-08 11:54:41 +02:00
212 changed files with 5689 additions and 2797 deletions

View File

@@ -2,12 +2,13 @@ name: Bug Report
description: Something is not working right description: Something is not working right
labels: ["bug"] labels: ["bug"]
body: body:
- type: markdown - type: checkboxes
attributes: attributes:
value: | label: Already reported ? *
## Before opening a new issue, please take a moment to search through the current open and closed issues to check if it already exists. description: Before opening a new bug report, please take a moment to search through the current open and closed issues to check if it already exists.
options:
--- - label: I have searched the existing open and closed issues.
required: true
- type: dropdown - type: dropdown
id: type id: type

View File

@@ -1,3 +1,5 @@
name: Nix (Build)
on: on:
workflow_call: workflow_call:
secrets: secrets:
@@ -14,17 +16,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Clone repository - uses: DeterminateSystems/nix-installer-action@main
uses: actions/checkout@v4
with:
ref: ${{ github.ref }}
submodules: recursive
- uses: cachix/install-nix-action@v27
- uses: DeterminateSystems/magic-nix-cache-action@main - uses: DeterminateSystems/magic-nix-cache-action@main
- uses: cachix/cachix-action@v15 - uses: cachix/cachix-action@v15
with: with:
name: hyprland name: hyprland
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
- run: nix build '.?submodules=1#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org" - run: nix build 'git+https://github.com/hyprwm/Hyprland?ref=${{ github.ref }}&submodules=1#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org"

View File

@@ -1,15 +1,14 @@
name: Nix name: Nix (CI)
on: [push, pull_request, workflow_dispatch] on: [push, pull_request, workflow_dispatch]
jobs: jobs:
update-inputs: update-inputs:
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
uses: ./.github/workflows/nix-update-inputs.yml uses: ./.github/workflows/nix-update-inputs.yml
secrets: inherit secrets: inherit
build: build:
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork) && !contains(needs.*.result, 'failure') if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork)
needs: update-inputs
uses: ./.github/workflows/nix-build.yml uses: ./.github/workflows/nix-build.yml
secrets: inherit secrets: inherit

View File

@@ -1,4 +1,4 @@
name: Nix name: Nix (Update Inputs)
on: on:
workflow_call: workflow_call:
@@ -8,6 +8,7 @@ on:
jobs: jobs:
update: update:
if: github.repository == 'hyprwm/Hyprland'
name: inputs name: inputs
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:

View File

@@ -7,22 +7,22 @@ name: Mark stale issues and pull requests
on: on:
schedule: schedule:
- cron: '7 */4 * * *' - cron: "7 */4 * * *"
workflow_dispatch: workflow_dispatch:
jobs: jobs:
stale: stale:
if: github.repository == 'hyprwm/Hyprland'
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
issues: write issues: write
pull-requests: write pull-requests: write
steps: steps:
- uses: actions/stale@v5 - uses: actions/stale@v5
with: with:
repo-token: ${{ secrets.STALEBOT_PAT }} repo-token: ${{ secrets.STALEBOT_PAT }}
stale-issue-label: 'stale' stale-issue-label: "stale"
stale-pr-label: 'stale' stale-pr-label: "stale"
operations-per-run: 40 operations-per-run: 40
days-before-close: -1 days-before-close: -1

2
.gitignore vendored
View File

@@ -37,3 +37,5 @@ gmon.out
PKGBUILD PKGBUILD
src/version.h src/version.h
hyprpm/Makefile
hyprctl/Makefile

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.27) cmake_minimum_required(VERSION 3.30)
# Get version # Get version
file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW) file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW)
@@ -51,7 +51,9 @@ find_package(PkgConfig REQUIRED)
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir) pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}") message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}")
pkg_get_variable(WAYLAND_SERVER_DIR wayland-server pkgdatadir) pkg_get_variable(WAYLAND_SCANNER_PKGDATA_DIR wayland-scanner pkgdatadir)
message(
STATUS "Found wayland-scanner pkgdatadir at ${WAYLAND_SCANNER_PKGDATA_DIR}")
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "Configuring Hyprland in Debug with CMake") message(STATUS "Configuring Hyprland in Debug with CMake")
@@ -62,7 +64,7 @@ else()
endif() endif()
include_directories(. "src/" "subprojects/udis86/" "protocols/") include_directories(. "src/" "subprojects/udis86/" "protocols/")
set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD 26)
add_compile_options( add_compile_options(
-Wall -Wall
-Wextra -Wextra
@@ -87,22 +89,19 @@ else()
endif() endif()
find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
pkg_check_modules( pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.1)
hyprctl_deps
REQUIRED pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine)
IMPORTED_TARGET
hyprutils>=0.2.1) add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}")
pkg_check_modules( pkg_check_modules(
deps deps
REQUIRED REQUIRED
IMPORTED_TARGET IMPORTED_TARGET
aquamarine
xkbcommon xkbcommon
uuid uuid
wayland-server wayland-server
wayland-client
wayland-cursor
wayland-protocols wayland-protocols
cairo cairo
pango pango
@@ -111,15 +110,11 @@ pkg_check_modules(
xcursor xcursor
libdrm libdrm
libinput libinput
hwdata
libseat
libdisplay-info
libliftoff
libudev
gbm gbm
gio-2.0
hyprlang>=0.3.2 hyprlang>=0.3.2
hyprcursor>=0.1.7 hyprcursor>=0.1.7
hyprutils>=0.2.1) hyprutils>=0.2.2)
find_package(hyprwayland-scanner 0.3.10 REQUIRED) find_package(hyprwayland-scanner 0.3.10 REQUIRED)
@@ -201,14 +196,11 @@ else()
REQUIRED REQUIRED
IMPORTED_TARGET IMPORTED_TARGET
xcb xcb
xwayland
xcb-util
xcb-render xcb-render
xcb-xfixes xcb-xfixes
xcb-icccm xcb-icccm
xcb-composite xcb-composite
xcb-res xcb-res
xcb-ewmh
xcb-errors) xcb-errors)
target_link_libraries(Hyprland PkgConfig::xdeps) target_link_libraries(Hyprland PkgConfig::xdeps)
endif() endif()
@@ -224,14 +216,17 @@ set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack) include(CPack)
message(STATUS "Setting precompiled headers") if(CMAKE_DISABLE_PRECOMPILE_HEADERS)
message(STATUS "Not using precompiled headers")
target_precompile_headers(Hyprland PRIVATE else()
$<$<COMPILE_LANGUAGE:CXX>:src/pch/pch.hpp>) message(STATUS "Setting precompiled headers")
target_precompile_headers(Hyprland PRIVATE
$<$<COMPILE_LANGUAGE:CXX>:src/pch/pch.hpp>)
endif()
message(STATUS "Setting link libraries") message(STATUS "Setting link libraries")
target_link_libraries(Hyprland rt PkgConfig::deps) target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::deps)
# used by `make installheaders`, to ensure the headers are generated # used by `make installheaders`, to ensure the headers are generated
add_custom_target(generate-protocol-headers) add_custom_target(generate-protocol-headers)
@@ -257,8 +252,9 @@ function(protocolWayland)
add_custom_command( add_custom_command(
OUTPUT ${CMAKE_SOURCE_DIR}/protocols/wayland.cpp OUTPUT ${CMAKE_SOURCE_DIR}/protocols/wayland.cpp
${CMAKE_SOURCE_DIR}/protocols/wayland.hpp ${CMAKE_SOURCE_DIR}/protocols/wayland.hpp
COMMAND hyprwayland-scanner --wayland-enums COMMAND
${WAYLAND_SERVER_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/ hyprwayland-scanner --wayland-enums
${WAYLAND_SCANNER_PKGDATA_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
target_sources(Hyprland PRIVATE protocols/wayland.cpp protocols/wayland.hpp) target_sources(Hyprland PRIVATE protocols/wayland.cpp protocols/wayland.hpp)
target_sources(generate-protocol-headers target_sources(generate-protocol-headers
@@ -266,7 +262,7 @@ function(protocolWayland)
endfunction() endfunction()
target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads
libudis86 uuid) libudis86)
protocolnew("subprojects/hyprland-protocols/protocols" protocolnew("subprojects/hyprland-protocols/protocols"
"hyprland-global-shortcuts-v1" true) "hyprland-global-shortcuts-v1" true)
@@ -315,6 +311,7 @@ protocolnew("stable/viewporter" "viewporter" false)
protocolnew("stable/linux-dmabuf" "linux-dmabuf-v1" false) protocolnew("stable/linux-dmabuf" "linux-dmabuf-v1" false)
protocolnew("staging/drm-lease" "drm-lease-v1" false) protocolnew("staging/drm-lease" "drm-lease-v1" false)
protocolnew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false) protocolnew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false)
protocolnew("staging/xdg-dialog" "xdg-dialog-v1" false)
protocolwayland() protocolwayland()
@@ -329,19 +326,21 @@ install(
CODE "execute_process( \ CODE "execute_process( \
COMMAND ${CMAKE_COMMAND} -E create_symlink \ COMMAND ${CMAKE_COMMAND} -E create_symlink \
${CMAKE_INSTALL_FULL_BINDIR}/Hyprland \ ${CMAKE_INSTALL_FULL_BINDIR}/Hyprland \
${CMAKE_INSTALL_FULL_BINDIR}/hyprland \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/hyprland\" \
)") )")
# session file # session file
install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.desktop install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.desktop
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions)
# allow Hyprland to find wallpapers # allow Hyprland to find assets
add_compile_definitions(DATAROOTDIR="${CMAKE_INSTALL_FULL_DATAROOTDIR}") add_compile_definitions(DATAROOTDIR="${CMAKE_INSTALL_FULL_DATAROOTDIR}")
# wallpapers # installable assets
file(GLOB_RECURSE WALLPAPERS "assets/wall*") file(GLOB_RECURSE INSTALLABLE_ASSETS "assets/install/*")
install(FILES ${WALLPAPERS} DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr) list(FILTER INSTALLABLE_ASSETS EXCLUDE REGEX "meson.build")
install(FILES ${INSTALLABLE_ASSETS}
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr)
# default config # default config
install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.conf install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.conf

View File

@@ -1,28 +1,24 @@
PREFIX = /usr/local PREFIX = /usr/local
legacyrenderer: legacyrenderer:
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./buildZ
cmake --build ./build --config Release --target all cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
chmod -R 777 ./build
legacyrendererdebug: legacyrendererdebug:
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build
cmake --build ./build --config Release --target all cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
chmod -R 777 ./build
release: release:
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build
cmake --build ./build --config Release --target all cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
chmod -R 777 ./build
debug: debug:
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build
cmake --build ./build --config Debug --target all cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
chmod -R 777 ./build
nopch: nopch:
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -S . -B ./build -G Ninja cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -S . -B ./build
cmake --build ./build --config Release --target all cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
clear: clear:
rm -rf build rm -rf build
@@ -87,8 +83,8 @@ asan:
#git reset --hard #git reset --hard
@echo -en "If you want to apply a patch, input its path (leave empty for none):\n" @echo -en "If you want to apply a patch, input its path (leave empty for none):\n"
@read patchvar @read patchvar; \
@if [-n "$patchvar"]; then patch -p1 < $patchvar || echo ""; else echo "No patch specified"; fi if [ -n "$$patchvar" ]; then patch -p1 < "$$patchvar" || echo ""; else echo "No patch specified"; fi
git clone --recursive https://gitlab.freedesktop.org/wayland/wayland git clone --recursive https://gitlab.freedesktop.org/wayland/wayland
cd wayland && patch -p1 < ../scripts/waylandStatic.diff && meson setup build --buildtype=debug -Db_sanitize=address -Ddocumentation=false && ninja -C build && cd .. cd wayland && patch -p1 < ../scripts/waylandStatic.diff && meson setup build --buildtype=debug -Db_sanitize=address -Ddocumentation=false && ninja -C build && cd ..

View File

@@ -1,6 +1,6 @@
<div align = center> <div align = center>
<img src="https://raw.githubusercontent.com/vaxerski/Hyprland/main/assets/header.svg" width="750" height="300" alt="banner"> <img src="https://raw.githubusercontent.com/hyprwm/Hyprland/main/assets/header.svg" width="750" height="300" alt="banner">
<br> <br>
@@ -125,7 +125,6 @@ easy IPC, much more QoL stuff than other compositors and more...
<!----------------------------------{ Images }---------------------------------> <!----------------------------------{ Images }--------------------------------->
[Stars Preview]: https://starchart.cc/vaxerski/Hyprland.svg
[Preview A]: https://i.ibb.co/C1yTb0r/falf.png [Preview A]: https://i.ibb.co/C1yTb0r/falf.png
[Preview B]: https://linfindel.github.io/cdn/hyprland-preview-b.png [Preview B]: https://linfindel.github.io/cdn/hyprland-preview-b.png
[Preview C]: https://i.ibb.co/B3GJg28/20221126-20h53m26s-grim.png [Preview C]: https://i.ibb.co/B3GJg28/20221126-20h53m26s-grim.png

View File

@@ -1 +1 @@
0.42.0 0.43.0

BIN
assets/install/lockdead.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@@ -0,0 +1,10 @@
globber = run_command('sh', '-c', 'find . -type f -not -name "*.build"', check: true)
files = globber.stdout().strip().split('\n')
foreach file : files
install_data(
file,
install_dir: join_paths(get_option('datadir'), 'hypr'),
install_tag: 'runtime',
)
endforeach

View File

Before

Width:  |  Height:  |  Size: 14 MiB

After

Width:  |  Height:  |  Size: 14 MiB

View File

Before

Width:  |  Height:  |  Size: 5.9 MiB

After

Width:  |  Height:  |  Size: 5.9 MiB

View File

Before

Width:  |  Height:  |  Size: 27 MiB

After

Width:  |  Height:  |  Size: 27 MiB

View File

@@ -1,7 +1,7 @@
wallpapers = ['0', '1', '2'] install_data(
'hyprland-portals.conf',
install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'),
install_tag: 'runtime',
)
foreach type : wallpapers subdir('install')
install_data(f'wall@type@.png', install_dir: join_paths(get_option('datadir'), 'hypr'), install_tag: 'runtime')
endforeach
install_data('hyprland-portals.conf', install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'), install_tag: 'runtime')

View File

@@ -10,8 +10,8 @@ Hyprland - Dynamic tiling Wayland compositor
\f[B]Hyprland\f[R] [\f[I]arg [...]\f[R]]. \f[B]Hyprland\f[R] [\f[I]arg [...]\f[R]].
.SH DESCRIPTION .SH DESCRIPTION
.PP .PP
\f[B]Hyprland\f[R] is a dynamic tiling Wayland compositor based on \f[B]Hyprland\f[R] is an independent, highly customizable, dynamic
wlroots that doesn\[aq]t sacrifice on its looks. tiling Wayland compositor that doesn\[aq]t sacrifice on its looks.
.PP .PP
You can launch Hyprland by either going into a TTY and executing You can launch Hyprland by either going into a TTY and executing
\f[B]Hyprland\f[R], or with a login manager. \f[B]Hyprland\f[R], or with a login manager.

View File

@@ -14,8 +14,8 @@ SYNOPSIS
DESCRIPTION DESCRIPTION
=========== ===========
**Hyprland** is a dynamic tiling Wayland compositor based on **Hyprland** is an independent, highly customizable,
wlroots that doesn't sacrifice on its looks. dynamic tiling Wayland compositor that doesn't sacrifice on its looks.
You can launch Hyprland by either going into a TTY and You can launch Hyprland by either going into a TTY and
executing **Hyprland**, or with a login manager. executing **Hyprland**, or with a login manager.

View File

@@ -1,2 +1,2 @@
install_man ('Hyprland.1') install_man('Hyprland.1')
install_man ('hyprctl.1') install_man('hyprctl.1')

View File

@@ -0,0 +1,14 @@
[Unit]
Description=Hyprland - Tiling compositor with the looks
Documentation=man:Hyprland(1)
BindsTo=graphical-session.target
Before=graphical-session.target
Wants=graphical-session-pre.target
After=graphical-session-pre.target
[Service]
Type=notify
ExecStart=/usr/bin/Hyprland
ExecStop=/usr/bin/hyprctl dispatch exit
Restart=on-failure
Slice=session.slice

View File

@@ -0,0 +1,5 @@
[Desktop Entry]
Name=Hyprland
Comment=An intelligent dynamic tiling Wayland compositor
Exec=systemctl --user start --wait hyprland-session
Type=Application

View File

@@ -59,7 +59,7 @@ env = HYPRCURSOR_SIZE,24
# Refer to https://wiki.hyprland.org/Configuring/Variables/ # Refer to https://wiki.hyprland.org/Configuring/Variables/
# https://wiki.hyprland.org/Configuring/Variables/#general # https://wiki.hyprland.org/Configuring/Variables/#general
general { general {
gaps_in = 5 gaps_in = 5
gaps_out = 20 gaps_out = 20
@@ -70,7 +70,7 @@ general {
col.inactive_border = rgba(595959aa) col.inactive_border = rgba(595959aa)
# Set to true enable resizing windows by clicking and dragging on borders and gaps # Set to true enable resizing windows by clicking and dragging on borders and gaps
resize_on_border = false resize_on_border = false
# Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on # Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
allow_tearing = false allow_tearing = false
@@ -96,7 +96,7 @@ decoration {
enabled = true enabled = true
size = 3 size = 3
passes = 1 passes = 1
vibrancy = 0.1696 vibrancy = 0.1696
} }
} }
@@ -129,7 +129,7 @@ master {
} }
# https://wiki.hyprland.org/Configuring/Variables/#misc # https://wiki.hyprland.org/Configuring/Variables/#misc
misc { misc {
force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers
disable_hyprland_logo = false # If true disables the random hyprland logo / anime girl background. :( disable_hyprland_logo = false # If true disables the random hyprland logo / anime girl background. :(
} }
@@ -169,9 +169,9 @@ device {
} }
#################### ###################
### KEYBINDINGSS ### ### KEYBINDINGS ###
#################### ###################
# See https://wiki.hyprland.org/Configuring/Keywords/ # See https://wiki.hyprland.org/Configuring/Keywords/
$mainMod = SUPER # Sets "Windows" key as main modifier $mainMod = SUPER # Sets "Windows" key as main modifier
@@ -228,6 +228,19 @@ bind = $mainMod, mouse_up, workspace, e-1
bindm = $mainMod, mouse:272, movewindow bindm = $mainMod, mouse:272, movewindow
bindm = $mainMod, mouse:273, resizewindow bindm = $mainMod, mouse:273, resizewindow
# Laptop multimedia keys for volume and LCD brightness
bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+
bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+
bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%-
# Requires playerctl
bindl = , XF86AudioNext, exec, playerctl next
bindl = , XF86AudioPause, exec, playerctl play-pause
bindl = , XF86AudioPlay, exec, playerctl play-pause
bindl = , XF86AudioPrev, exec, playerctl previous
############################## ##############################
### WINDOWS AND WORKSPACES ### ### WINDOWS AND WORKSPACES ###

View File

@@ -1,2 +1,10 @@
install_data('hyprland.conf', install_dir: join_paths(get_option('datadir'), 'hypr'), install_tag: 'runtime') install_data(
install_data('hyprland.desktop', install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), install_tag: 'runtime') 'hyprland.conf',
install_dir: join_paths(get_option('datadir'), 'hypr'),
install_tag: 'runtime',
)
install_data(
'hyprland.desktop',
install_dir: join_paths(get_option('datadir'), 'wayland-sessions'),
install_tag: 'runtime',
)

48
flake.lock generated
View File

@@ -16,11 +16,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1722347739, "lastModified": 1726665257,
"narHash": "sha256-rAoh+K6KG+b1DwSWtqRVocdojnH6nGk6q07mNltoUSM=", "narHash": "sha256-rEzEZtd3iyVo5RJ1OGujOlnywNf3gsrOnjAn1NLciD4=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "aquamarine", "repo": "aquamarine",
"rev": "7c3565f9bedc7cb601cc0baa14792247e4dc1d5a", "rev": "752d0fbd141fabb5a1e7f865199b80e6e76f8d8e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -42,11 +42,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1721330371, "lastModified": 1722623071,
"narHash": "sha256-aYlHTWylczLt6ERJyg6E66Y/XSCbVL7leVcRuJmVbpI=", "narHash": "sha256-sLADpVgebpCBFXkA1FlCXtvEPu1tdEsTfqK1hfeHySE=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprcursor", "repo": "hyprcursor",
"rev": "4493a972b48f9c3014befbbf381ed5fff91a65dc", "rev": "912d56025f03d41b1ad29510c423757b4379eb1c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -93,11 +93,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1721324361, "lastModified": 1725997860,
"narHash": "sha256-BiJKO0IIdnSwHQBSrEJlKlFr753urkLE48wtt0UhNG4=", "narHash": "sha256-d/rZ/fHR5l1n7PeyLw0StWMNLXVU9c4HFyfskw568so=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprlang", "repo": "hyprlang",
"rev": "adbefbf49664a6c2c8bf36b6487fd31e3eb68086", "rev": "dfeb5811dd6485490cce18d6cc1e38a055eea876",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -116,11 +116,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1722098849, "lastModified": 1726874949,
"narHash": "sha256-D3wIZlBNh7LuZ0NaoCpY/Pvu+xHxIVtSN+KkWZYvvVs=", "narHash": "sha256-PNnIpwGqpTvMU3N2r0wMQwK1E+t4Bb5fbJwblQvr+80=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprutils", "repo": "hyprutils",
"rev": "5dcbbc1e3de40b2cecfd2007434d86e924468f1f", "rev": "d97af4f6bd068c03a518b597675e598f57ea2291",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -139,11 +139,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1721324119, "lastModified": 1726840673,
"narHash": "sha256-SOOqIT27/X792+vsLSeFdrNTF+OSRp5qXv6Te+fb2Qg=", "narHash": "sha256-HIPEXyRRVZoqD6U+lFS1B0tsIU7p83FaB9m7KT/x6mQ=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprwayland-scanner", "repo": "hyprwayland-scanner",
"rev": "a048a6cb015340bd82f97c1f40a4b595ca85cc30", "rev": "b68dab23fc922eae99306988133ee80a40b39ca5",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -154,11 +154,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1722185531, "lastModified": 1726755586,
"narHash": "sha256-veKR07psFoJjINLC8RK4DiLniGGMgF3QMlS4tb74S6k=", "narHash": "sha256-PmUr/2GQGvFTIJ6/Tvsins7Q43KTMvMFhvG6oaYK+Wk=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "52ec9ac3b12395ad677e8b62106f0b98c1f8569d", "rev": "c04d5652cfa9742b1d519688f65d1bbccea9eb7e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -201,6 +201,12 @@
"hyprlang": [ "hyprlang": [
"hyprlang" "hyprlang"
], ],
"hyprutils": [
"hyprutils"
],
"hyprwayland-scanner": [
"hyprwayland-scanner"
],
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
], ],
@@ -209,11 +215,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1722365976, "lastModified": 1726851729,
"narHash": "sha256-Khdm+mDzYA//XaU0M+hftod+rKr5q9SSHSEuiQ0/9ow=", "narHash": "sha256-1z0esr5lBeUMlrPZ9gZmqZT8oTQekxJi53HAW4cH0Ms=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "xdg-desktop-portal-hyprland", "repo": "xdg-desktop-portal-hyprland",
"rev": "7f2a77ddf60390248e2a3de2261d7102a13e5341", "rev": "73b8c4f1150040644cf678aa8bbf2cec48a433cf",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@@ -46,6 +46,8 @@
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
inputs.systems.follows = "systems"; inputs.systems.follows = "systems";
inputs.hyprlang.follows = "hyprlang"; inputs.hyprlang.follows = "hyprlang";
inputs.hyprutils.follows = "hyprutils";
inputs.hyprwayland-scanner.follows = "hyprwayland-scanner";
}; };
}; };
@@ -95,13 +97,9 @@
devShells = eachSystem (system: { devShells = eachSystem (system: {
default = default =
pkgsFor.${system}.mkShell.override { pkgsFor.${system}.mkShell.override {
stdenv = pkgsFor.${system}.gcc13Stdenv; inherit (self.packages.${system}.default) stdenv;
} { } {
name = "hyprland-shell"; name = "hyprland-shell";
nativeBuildInputs = with pkgsFor.${system}; [
expat
libxml2
];
hardeningDisable = ["fortify"]; hardeningDisable = ["fortify"];
inputsFrom = [pkgsFor.${system}.hyprland]; inputsFrom = [pkgsFor.${system}.hyprland];
packages = [pkgsFor.${system}.clang-tools]; packages = [pkgsFor.${system}.clang-tools];

View File

@@ -1,4 +0,0 @@
all:
$(CXX) $(CXXFLAGS) -std=c++2b ./main.cpp -o ./hyprctl
clean:
rm ./hyprctl

View File

@@ -1,17 +1,17 @@
_hyprctl_cmd_2 () { _hyprctl_cmd_1 () {
hyprctl monitors | awk '/Monitor/{ print $2 }' hyprctl monitors | awk '/Monitor/{ print $2 }'
} }
_hyprctl_cmd_3 () { _hyprctl_cmd_3 () {
hyprpm list | awk '/Plugin/{ print $4 }' hyprctl clients | awk '/class/{print $2}'
}
_hyprctl_cmd_2 () {
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
} }
_hyprctl_cmd_0 () { _hyprctl_cmd_0 () {
hyprctl clients | awk '/class/{ print $2 }' hyprpm list | awk '/Plugin/{print $4}'
}
_hyprctl_cmd_1 () {
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
} }
_hyprctl () { _hyprctl () {
@@ -23,25 +23,25 @@ _hyprctl () {
local words cword local words cword
_get_comp_words_by_ref -n "$COMP_WORDBREAKS" words cword _get_comp_words_by_ref -n "$COMP_WORDBREAKS" words cword
local -a literals=("cyclenext" "globalshortcuts" "cursorpos" "bordersize" "renameworkspace" "animationstyle" "focuswindow" "0" "auto" "swapnext" "forceallowsinput" "moveactive" "activebordercolor" "alphafullscreen" "wayland" "layers" "minsize" "monitors" "1" "kill" "settiled" "3" "focusmonitor" "swapwindow" "moveoutofgroup" "notify" "movecursor" "setcursor" "seterror" "movecurrentworkspacetomonitor" "4" "nomaxsize" "forcenoanims" "setprop" "-i" "-q" "togglefloating" "workspacerules" "movetoworkspace" "disable" "setignoregrouplock" "workspaces" "movegroupwindow" "closewindow" "0" "--instance" "binds" "movewindow" "splitratio" "alpha" "denywindowfromgroup" "workspace" "configerrors" "togglegroup" "getoption" "forceopaque" "keepaspectratio" "killactive" "pass" "decorations" "devices" "focuscurrentorlast" "submap" "global" "alphafullscreenoverride" "forcerendererreload" "movewindowpixel" "headless" "version" "dpms" "resizeactive" "moveintogroup" "5" "alphaoverride" "setfloating" "rollinglog" "::=" "rounding" "layouts" "moveworkspacetomonitor" "exec" "alphainactiveoverride" "alterzorder" "fakefullscreen" "nofocus" "keyword" "forcenoborder" "forcenodim" "--quiet" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "tagwindow" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "sendshortcut" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow") declare -a literals=(resizeactive 2 changegroupactive -r moveintogroup forceallowsinput 4 ::= systeminfo all layouts setprop animationstyle switchxkblayout create denywindowfromgroup headless activebordercolor exec setcursor wayland focusurgentorlast workspacerules movecurrentworkspacetomonitor movetoworkspacesilent hyprpaper alpha inactivebordercolor movegroupwindow movecursortocorner movewindowpixel prev movewindow globalshortcuts clients dimaround setignoregrouplock splash execr monitors 0 forcenoborder -q animations 1 nomaxsize splitratio moveactive pass swapnext devices layers rounding lockactivegroup 5 moveworkspacetomonitor -f -i --quiet forcenodim pin 0 1 forceopaque forcenoshadow setfloating minsize alphaoverride sendshortcut workspaces cyclenext alterzorder togglegroup lockgroups bordersize dpms focuscurrentorlast -1 --batch notify remove instances 1 3 moveoutofgroup killactive 2 movetoworkspace movecursor configerrors closewindow swapwindow tagwindow forcerendererreload centerwindow auto focuswindow seterror nofocus alphafullscreen binds version -h togglespecialworkspace fullscreen windowdancecompat 0 keyword toggleopaque 3 --instance togglefloating renameworkspace alphafullscreenoverride activeworkspace x11 kill forceopaqueoverriden output global dispatch reload forcenoblur -j event --help disable -1 activewindow keepaspectratio dismissnotify focusmonitor movefocus plugin exit workspace fullscreenstate getoption alphainactiveoverride alphainactive decorations settiled config-only descriptions resizewindowpixel fakefullscreen rollinglog swapactiveworkspaces submap next movewindoworgroup cursorpos forcenoanims focusworkspaceoncurrentmonitor maxsize)
declare -A literal_transitions declare -A literal_transitions
literal_transitions[0]="([105]=1 [75]=2 [33]=3 [35]=4 [1]=2 [2]=2 [78]=2 [107]=5 [37]=2 [111]=4 [41]=2 [46]=2 [115]=2 [85]=6 [116]=8 [52]=2 [88]=4 [54]=2 [90]=9 [120]=2 [122]=2 [124]=2 [15]=2 [59]=10 [60]=2 [17]=11 [125]=12 [19]=2 [127]=2 [129]=2 [25]=13 [68]=2 [98]=4 [99]=2 [27]=2 [28]=14 [102]=2 [104]=4)" literal_transitions[0]="([120]=14 [43]=2 [125]=21 [81]=2 [3]=21 [51]=2 [50]=2 [128]=2 [89]=2 [58]=21 [8]=2 [10]=2 [11]=3 [130]=4 [13]=5 [97]=6 [101]=2 [102]=21 [133]=7 [100]=2 [137]=2 [22]=2 [19]=2 [140]=8 [25]=2 [143]=2 [107]=9 [146]=10 [69]=2 [33]=2 [34]=2 [78]=21 [114]=2 [37]=2 [151]=2 [116]=2 [121]=13 [123]=21 [39]=11 [42]=21 [79]=15 [118]=12)"
literal_transitions[3]="([73]=17 [13]=2 [32]=17 [55]=17 [56]=17 [91]=17 [106]=2 [123]=2 [77]=1 [16]=2 [126]=17 [3]=1 [5]=2 [64]=17 [131]=2 [133]=17 [81]=17 [134]=17 [84]=17 [31]=17 [49]=2 [12]=2 [86]=17 [10]=17 [87]=17 [141]=17)" literal_transitions[1]="([81]=2 [51]=2 [50]=2 [128]=2 [8]=2 [89]=2 [10]=2 [11]=3 [130]=4 [13]=5 [97]=6 [101]=2 [133]=7 [100]=2 [22]=2 [19]=2 [137]=2 [140]=8 [25]=2 [143]=2 [107]=9 [146]=10 [69]=2 [33]=2 [34]=2 [114]=2 [37]=2 [151]=2 [116]=2 [39]=11 [118]=12 [121]=13 [120]=14 [79]=15 [43]=2)"
literal_transitions[7]="([105]=1 [75]=2 [33]=3 [1]=2 [2]=2 [78]=2 [107]=5 [37]=2 [41]=2 [46]=2 [115]=2 [85]=6 [116]=8 [52]=2 [54]=2 [90]=9 [120]=2 [122]=2 [124]=2 [15]=2 [59]=10 [60]=2 [17]=11 [125]=12 [19]=2 [127]=2 [129]=2 [25]=13 [68]=2 [99]=2 [27]=2 [28]=14 [102]=2)" literal_transitions[3]="([139]=2 [63]=16 [64]=16 [45]=16 [105]=16 [27]=2 [26]=2 [52]=4 [5]=16 [66]=2 [67]=16 [129]=16 [113]=16 [12]=2 [74]=4 [99]=2 [35]=16 [152]=16 [98]=16 [59]=16 [117]=16 [41]=16 [17]=2 [138]=16 [154]=2 [122]=16)"
literal_transitions[8]="([101]=2 [130]=2 [132]=2 [0]=2 [74]=2 [36]=2 [108]=2 [109]=2 [38]=2 [110]=2 [4]=2 [79]=2 [40]=2 [80]=2 [113]=2 [6]=2 [42]=2 [43]=2 [82]=2 [83]=2 [47]=2 [48]=2 [9]=2 [50]=2 [51]=2 [53]=2 [11]=2 [112]=2 [89]=2 [118]=2 [57]=2 [92]=2 [58]=2 [93]=2 [94]=2 [61]=2 [62]=2 [128]=2 [95]=2 [63]=2 [20]=2 [97]=2 [22]=2 [23]=2 [65]=2 [66]=2 [135]=2 [136]=2 [24]=2 [26]=2 [69]=2 [100]=2 [70]=2 [140]=2 [29]=2 [71]=2)" literal_transitions[6]="([126]=2)"
literal_transitions[9]="([117]=20 [114]=16)" literal_transitions[10]="([56]=2)"
literal_transitions[11]="([103]=2)" literal_transitions[11]="([9]=2)"
literal_transitions[13]="([21]=1 [119]=1 [30]=1 [139]=1 [121]=1 [44]=1 [72]=1)" literal_transitions[12]="([14]=19 [80]=22)"
literal_transitions[14]="([39]=2)" literal_transitions[13]="([142]=2)"
literal_transitions[15]="([138]=2 [96]=2)" literal_transitions[14]="([0]=2 [84]=2 [2]=2 [85]=2 [4]=2 [87]=2 [88]=2 [90]=2 [91]=2 [92]=2 [93]=2 [94]=2 [96]=2 [15]=2 [18]=2 [103]=2 [21]=2 [104]=2 [23]=2 [24]=2 [28]=2 [29]=2 [30]=2 [108]=2 [111]=2 [32]=2 [112]=2 [36]=2 [38]=2 [119]=2 [124]=2 [46]=2 [47]=2 [48]=2 [49]=2 [53]=2 [55]=2 [131]=2 [132]=2 [134]=2 [135]=2 [60]=2 [136]=20 [141]=2 [65]=2 [144]=2 [145]=2 [68]=2 [147]=2 [70]=2 [71]=2 [72]=2 [73]=2 [148]=2 [75]=2 [76]=2 [150]=2 [153]=2)"
literal_transitions[17]="([18]=2 [7]=2)" literal_transitions[15]="([86]=4 [6]=4 [109]=4 [61]=4 [77]=4 [54]=4 [62]=4)"
literal_transitions[18]="([76]=19)" literal_transitions[16]="([40]=2 [44]=2)"
literal_transitions[19]="([34]=4 [45]=4)" literal_transitions[17]="([7]=23)"
literal_transitions[20]="([8]=2 [67]=2 [14]=2 [137]=2)" literal_transitions[18]="([31]=2 [149]=2)"
literal_transitions[19]="([95]=2 [16]=2 [115]=2 [20]=2)"
declare -A match_anything_transitions literal_transitions[20]="([106]=2 [82]=2 [127]=2 [1]=2 [83]=2)"
match_anything_transitions=([1]=2 [0]=7 [6]=2 [15]=2 [10]=2 [5]=15 [14]=18 [7]=7 [2]=18 [16]=2 [12]=2 [11]=18) literal_transitions[23]="([57]=21 [110]=21)"
declare -A match_anything_transitions=([6]=17 [7]=2 [0]=1 [22]=2 [5]=18 [4]=2 [2]=17 [18]=2 [11]=17 [8]=2 [9]=2 [13]=17 [10]=17 [1]=1)
declare -A subword_transitions declare -A subword_transitions
local state=0 local state=0
@@ -79,21 +79,9 @@ _hyprctl () {
done done
local -a matches=()
local prefix="${words[$cword]}" local prefix="${words[$cword]}"
local shortest_suffix="$word"
for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do
local char="${COMP_WORDBREAKS:$i:1}"
local candidate="${word##*$char}"
if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then
shortest_suffix=$candidate
fi
done
local superfluous_prefix=""
if [[ "$shortest_suffix" != "$word" ]]; then
local superfluous_prefix=${word%$shortest_suffix}
fi
if [[ -v "literal_transitions[$state]" ]]; then if [[ -v "literal_transitions[$state]" ]]; then
local state_transitions_initializer=${literal_transitions[$state]} local state_transitions_initializer=${literal_transitions[$state]}
declare -A state_transitions declare -A state_transitions
@@ -102,25 +90,38 @@ _hyprctl () {
for literal_id in "${!state_transitions[@]}"; do for literal_id in "${!state_transitions[@]}"; do
local literal="${literals[$literal_id]}" local literal="${literals[$literal_id]}"
if [[ $literal = "${prefix}"* ]]; then if [[ $literal = "${prefix}"* ]]; then
local completion=${literal#"$superfluous_prefix"} matches+=("$literal ")
COMPREPLY+=("$completion ")
fi fi
done done
fi fi
declare -A commands declare -A commands
commands=([5]=1 [16]=2 [12]=3 [10]=0) commands=([7]=0 [22]=1 [8]=3 [5]=2)
if [[ -v "commands[$state]" ]]; then if [[ -v "commands[$state]" ]]; then
local command_id=${commands[$state]} local command_id=${commands[$state]}
local completions=() local completions=()
mapfile -t completions < <(_hyprctl_cmd_${command_id} "$prefix" | cut -f1) readarray -t completions < <(_hyprctl_cmd_${command_id} "$prefix" | cut -f1)
for item in "${completions[@]}"; do for item in "${completions[@]}"; do
if [[ $item = "${prefix}"* ]]; then if [[ $item = "${prefix}"* ]]; then
COMPREPLY+=("$item") matches+=("$item")
fi fi
done done
fi fi
local shortest_suffix="$prefix"
for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do
local char="${COMP_WORDBREAKS:$i:1}"
local candidate=${prefix##*$char}
if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then
shortest_suffix=$candidate
fi
done
local superfluous_prefix=""
if [[ "$shortest_suffix" != "$prefix" ]]; then
local superfluous_prefix=${prefix%$shortest_suffix}
fi
COMPREPLY=("${matches[@]#$superfluous_prefix}")
return 0 return 0
} }

View File

@@ -1,21 +1,21 @@
function _hyprctl_3 function _hyprctl_2
set 1 $argv[1] set 1 $argv[1]
hyprctl monitors | awk '/Monitor/{ print $2 }' hyprctl monitors | awk '/Monitor/{ print $2 }'
end end
function _hyprctl_4 function _hyprctl_4
set 1 $argv[1] set 1 $argv[1]
hyprpm list | awk '/Plugin/{ print $4 }' hyprctl clients | awk '/class/{print $2}'
end
function _hyprctl_3
set 1 $argv[1]
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
end end
function _hyprctl_1 function _hyprctl_1
set 1 $argv[1] set 1 $argv[1]
hyprctl clients | awk '/class/{ print $2 }' hyprpm list | awk '/Plugin/{print $4}'
end
function _hyprctl_2
set 1 $argv[1]
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
end end
function _hyprctl function _hyprctl
@@ -29,145 +29,160 @@ function _hyprctl
set COMP_CWORD (count $COMP_WORDS) set COMP_CWORD (count $COMP_WORDS)
end end
set --local literals "cyclenext" "globalshortcuts" "cursorpos" "bordersize" "renameworkspace" "animationstyle" "focuswindow" "0" "auto" "swapnext" "forceallowsinput" "moveactive" "activebordercolor" "alphafullscreen" "wayland" "layers" "minsize" "monitors" "1" "kill" "settiled" "3" "focusmonitor" "swapwindow" "moveoutofgroup" "notify" "movecursor" "setcursor" "seterror" "movecurrentworkspacetomonitor" "4" "nomaxsize" "forcenoanims" "setprop" "-i" "-q" "togglefloating" "workspacerules" "movetoworkspace" "disable" "setignoregrouplock" "workspaces" "movegroupwindow" "closewindow" "0" "--instance" "binds" "movewindow" "splitratio" "alpha" "denywindowfromgroup" "workspace" "configerrors" "togglegroup" "getoption" "forceopaque" "keepaspectratio" "killactive" "pass" "decorations" "devices" "focuscurrentorlast" "submap" "global" "alphafullscreenoverride" "forcerendererreload" "movewindowpixel" "headless" "version" "dpms" "resizeactive" "moveintogroup" "5" "alphaoverride" "setfloating" "rollinglog" "::=" "rounding" "layouts" "moveworkspacetomonitor" "exec" "alphainactiveoverride" "alterzorder" "fakefullscreen" "nofocus" "keyword" "forcenoborder" "forcenodim" "--quiet" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "tagwindow" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "sendshortcut" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow" set literals "resizeactive" "2" "changegroupactive" "-r" "moveintogroup" "forceallowsinput" "4" "::=" "systeminfo" "all" "layouts" "setprop" "animationstyle" "switchxkblayout" "create" "denywindowfromgroup" "headless" "activebordercolor" "exec" "setcursor" "wayland" "focusurgentorlast" "workspacerules" "movecurrentworkspacetomonitor" "movetoworkspacesilent" "hyprpaper" "alpha" "inactivebordercolor" "movegroupwindow" "movecursortocorner" "movewindowpixel" "prev" "movewindow" "globalshortcuts" "clients" "dimaround" "setignoregrouplock" "splash" "execr" "monitors" "0" "forcenoborder" "-q" "animations" "1" "nomaxsize" "splitratio" "moveactive" "pass" "swapnext" "devices" "layers" "rounding" "lockactivegroup" "5" "moveworkspacetomonitor" "-f" "-i" "--quiet" "forcenodim" "pin" "0" "1" "forceopaque" "forcenoshadow" "setfloating" "minsize" "alphaoverride" "sendshortcut" "workspaces" "cyclenext" "alterzorder" "togglegroup" "lockgroups" "bordersize" "dpms" "focuscurrentorlast" "-1" "--batch" "notify" "remove" "instances" "1" "3" "moveoutofgroup" "killactive" "2" "movetoworkspace" "movecursor" "configerrors" "closewindow" "swapwindow" "tagwindow" "forcerendererreload" "centerwindow" "auto" "focuswindow" "seterror" "nofocus" "alphafullscreen" "binds" "version" "-h" "togglespecialworkspace" "fullscreen" "windowdancecompat" "0" "keyword" "toggleopaque" "3" "--instance" "togglefloating" "renameworkspace" "alphafullscreenoverride" "activeworkspace" "x11" "kill" "forceopaqueoverriden" "output" "global" "dispatch" "reload" "forcenoblur" "-j" "event" "--help" "disable" "-1" "activewindow" "keepaspectratio" "dismissnotify" "focusmonitor" "movefocus" "plugin" "exit" "workspace" "fullscreenstate" "getoption" "alphainactiveoverride" "alphainactive" "decorations" "settiled" "config-only" "descriptions" "resizewindowpixel" "fakefullscreen" "rollinglog" "swapactiveworkspaces" "submap" "next" "movewindoworgroup" "cursorpos" "forcenoanims" "focusworkspaceoncurrentmonitor" "maxsize"
set --local descriptions set descriptions
set descriptions[1] "Focus the next window on a workspace" set descriptions[1] "Resize the active window"
set descriptions[3] "Get the current cursor pos in global layout coordinates" set descriptions[2] "Fullscreen"
set descriptions[5] "Rename a workspace" set descriptions[3] "Switch to the next window in a group"
set descriptions[7] "Focus the first window matching" set descriptions[4] "Refresh state after issuing the command"
set descriptions[10] "Swap the focused window with the next window" set descriptions[5] "Move the active window into a group"
set descriptions[12] "Move the active window" set descriptions[7] "CONFUSED"
set descriptions[16] "List the layers" set descriptions[9] "Print system info"
set descriptions[18] "List active outputs with their properties" set descriptions[11] "List all layouts available (including plugin ones)"
set descriptions[20] "Get into a kill mode, where you can kill an app by clicking on it" set descriptions[12] "Set a property of a window"
set descriptions[21] "Set the current window's floating state to false" set descriptions[14] "Set the xkb layout index for a keyboard"
set descriptions[22] "ERROR" set descriptions[16] "Prohibit the active window from becoming or being inserted into group"
set descriptions[23] "Focus a monitor" set descriptions[19] "Execute a shell command"
set descriptions[24] "Swap the active window with another window" set descriptions[20] "Set the cursor theme and reloads the cursor manager"
set descriptions[25] "Move the active window out of a group" set descriptions[22] "Focus the urgent window or the last window"
set descriptions[26] "Send a notification using the built-in Hyprland notification system" set descriptions[23] "Get the list of defined workspace rules"
set descriptions[27] "Move the cursor to a specified position" set descriptions[24] "Move the active workspace to a monitor"
set descriptions[28] "Set the cursor theme and reloads the cursor manager" set descriptions[25] "Move window doesnt switch to the workspace"
set descriptions[29] "Set the hyprctl error string" set descriptions[26] "Interact with hyprpaper if present"
set descriptions[30] "Move the active workspace to a monitor" set descriptions[29] "Swap the active window with the next or previous in a group"
set descriptions[31] "CONFUSED" set descriptions[30] "Move the cursor to the corner of the active window"
set descriptions[34] "Set a property of a window" set descriptions[31] "Move a selected window"
set descriptions[35] "Specify the Hyprland instance" set descriptions[33] "Move the active window in a direction or to a monitor"
set descriptions[36] "Disable output" set descriptions[34] "Lists all global shortcuts"
set descriptions[37] "Toggle the current window's floating state" set descriptions[35] "List all windows with their properties"
set descriptions[38] "Get the list of defined workspace rules" set descriptions[37] "Temporarily enable or disable binds:ignore_group_lock"
set descriptions[39] "Move the focused window to a workspace" set descriptions[38] "Print the current random splash"
set descriptions[41] "Temporarily enable or disable binds:ignore_group_lock" set descriptions[39] "Execute a raw shell command"
set descriptions[42] "List all workspaces with their properties" set descriptions[40] "List active outputs with their properties"
set descriptions[43] "Swap the active window with the next or previous in a group" set descriptions[43] "Disable output"
set descriptions[44] "Close a specified window" set descriptions[44] "Gets the current config info about animations and beziers"
set descriptions[45] "WARNING" set descriptions[47] "Change the split ratio"
set descriptions[46] "Specify the Hyprland instance" set descriptions[48] "Move the active window"
set descriptions[47] "List all registered binds" set descriptions[49] "Pass the key to a specified window"
set descriptions[48] "Move the active window in a direction or to a monitor" set descriptions[50] "Swap the focused window with the next window"
set descriptions[49] "Change the split ratio" set descriptions[51] "List all connected keyboards and mice"
set descriptions[51] "Prohibit the active window from becoming or being inserted into group" set descriptions[52] "List the layers"
set descriptions[52] "Change the workspace" set descriptions[54] "Lock the focused group"
set descriptions[53] "List all current config parsing errors" set descriptions[55] "OK"
set descriptions[54] "Toggle the current active window into a group" set descriptions[56] "Move a workspace to a monitor"
set descriptions[55] "Get the config option status (values)" set descriptions[58] "Specify the Hyprland instance"
set descriptions[58] "Close the active window" set descriptions[59] "Disable output"
set descriptions[59] "Pass the key to a specified window" set descriptions[61] "Pin a window"
set descriptions[60] "List all decorations and their info" set descriptions[62] "WARNING"
set descriptions[61] "List all connected keyboards and mice" set descriptions[63] "INFO"
set descriptions[62] "Switch focus from current to previously focused window" set descriptions[66] "Set the current window's floating state to true"
set descriptions[63] "Change the current mapping group" set descriptions[69] "On shortcut X sends shortcut Y to a specified window"
set descriptions[64] "Execute a Global Shortcut using the GlobalShortcuts portal" set descriptions[70] "List all workspaces with their properties"
set descriptions[66] "Force the renderer to reload all resources and outputs" set descriptions[71] "Focus the next window on a workspace"
set descriptions[67] "Move a selected window" set descriptions[72] "Modify the window stack order of the active or specified window"
set descriptions[69] "Print the Hyprland version: flags, commit and branch of build" set descriptions[73] "Toggle the current active window into a group"
set descriptions[70] "Set all monitors' DPMS status" set descriptions[74] "Lock the groups"
set descriptions[71] "Resize the active window" set descriptions[76] "Set all monitors' DPMS status"
set descriptions[72] "Move the active window into a group" set descriptions[77] "Switch focus from current to previously focused window"
set descriptions[73] "OK" set descriptions[78] "No Icon"
set descriptions[75] "Set the current window's floating state to true" set descriptions[79] "Execute a batch of commands separated by ;"
set descriptions[76] "Print tail of the log" set descriptions[80] "Send a notification using the built-in Hyprland notification system"
set descriptions[79] "List all layouts available (including plugin ones)" set descriptions[82] "List all running Hyprland instances and their info"
set descriptions[80] "Move a workspace to a monitor" set descriptions[83] "Maximize no fullscreen"
set descriptions[81] "Execute a shell command" set descriptions[84] "Maximize and fullscreen"
set descriptions[83] "Modify the window stack order of the active or specified window" set descriptions[85] "Move the active window out of a group"
set descriptions[84] "Toggle the focused window's internal fullscreen state" set descriptions[86] "Close the active window"
set descriptions[86] "Issue a keyword to call a config keyword dynamically" set descriptions[87] "HINT"
set descriptions[89] "Disable output" set descriptions[88] "Move the focused window to a workspace"
set descriptions[90] "Pin a window" set descriptions[89] "Move the cursor to a specified position"
set descriptions[91] "Allows adding/removing fake outputs to a specific backend" set descriptions[90] "List all current config parsing errors"
set descriptions[93] "Toggle a special workspace on/off" set descriptions[91] "Close a specified window"
set descriptions[94] "Toggle the focused window's fullscreen state" set descriptions[92] "Swap the active window with another window"
set descriptions[95] "Toggle the current window to always be opaque" set descriptions[93] "Apply a tag to the window"
set descriptions[96] "Focus the requested workspace" set descriptions[94] "Force the renderer to reload all resources and outputs"
set descriptions[98] "Switch to the next window in a group" set descriptions[95] "Center the active window"
set descriptions[99] "Output in JSON format" set descriptions[97] "Focus the first window matching"
set descriptions[100] "List all running Hyprland instances and their info" set descriptions[98] "Set the hyprctl error string"
set descriptions[101] "Execute a raw shell command" set descriptions[101] "List all registered binds"
set descriptions[102] "Exit the compositor with no questions asked" set descriptions[102] "Print the Hyprland version: flags, commit and branch of build"
set descriptions[103] "List all windows with their properties" set descriptions[103] "Prints the help message"
set descriptions[105] "Execute a batch of commands separated by ;" set descriptions[104] "Toggle a special workspace on/off"
set descriptions[106] "Dismiss all or up to amount of notifications" set descriptions[105] "Toggle the focused window's fullscreen state"
set descriptions[108] "Set the xkb layout index for a keyboard" set descriptions[107] "None"
set descriptions[109] "Move window doesnt switch to the workspace" set descriptions[108] "Issue a keyword to call a config keyword dynamically"
set descriptions[110] "Apply a tag to the window" set descriptions[109] "Toggle the current window to always be opaque"
set descriptions[111] "Behave as moveintogroup" set descriptions[110] "ERROR"
set descriptions[112] "Refresh state after issuing the command" set descriptions[111] "Specify the Hyprland instance"
set descriptions[113] "Move the focus in a direction" set descriptions[112] "Toggle the current window's floating state"
set descriptions[114] "Focus the urgent window or the last window" set descriptions[113] "Rename a workspace"
set descriptions[116] "Get the active workspace name and its properties" set descriptions[115] "Get the active workspace name and its properties"
set descriptions[117] "Issue a dispatch to call a keybind dispatcher with an arg" set descriptions[117] "Get into a kill mode, where you can kill an app by clicking on it"
set descriptions[119] "Center the active window" set descriptions[119] "Allows adding/removing fake outputs to a specific backend"
set descriptions[120] "HINT" set descriptions[120] "Execute a Global Shortcut using the GlobalShortcuts portal"
set descriptions[121] "Interact with hyprpaper if present" set descriptions[121] "Issue a dispatch to call a keybind dispatcher with an arg"
set descriptions[122] "No Icon" set descriptions[122] "Force reload the config"
set descriptions[123] "Force reload the config" set descriptions[124] "Output in JSON format"
set descriptions[125] "Print system info" set descriptions[125] "Emits a custom event to socket2"
set descriptions[126] "Interact with a plugin" set descriptions[126] "Prints the help message"
set descriptions[128] "Get the active window name and its properties" set descriptions[128] "Current"
set descriptions[129] "Swap the active workspaces between two monitors" set descriptions[129] "Get the active window name and its properties"
set descriptions[130] "Print the current random splash" set descriptions[131] "Dismiss all or up to amount of notifications"
set descriptions[131] "On shortcut X sends shortcut Y to a specified window" set descriptions[132] "Focus a monitor"
set descriptions[133] "Lock the focused group" set descriptions[133] "Move the focus in a direction"
set descriptions[136] "Lock the groups" set descriptions[134] "Interact with a plugin"
set descriptions[137] "Move the cursor to the corner of the active window" set descriptions[135] "Exit the compositor with no questions asked"
set descriptions[140] "INFO" set descriptions[136] "Change the workspace"
set descriptions[141] "Resize a selected window" set descriptions[137] "Sets the focused windows fullscreen mode and the one sent to the client"
set descriptions[138] "Get the config option status (values)"
set descriptions[141] "List all decorations and their info"
set descriptions[142] "Set the current window's floating state to false"
set descriptions[144] "Return a parsable JSON with all the config options, descriptions, value types and ranges"
set descriptions[145] "Resize a selected window"
set descriptions[146] "Toggle the focused window's internal fullscreen state"
set descriptions[147] "Print tail of the log"
set descriptions[148] "Swap the active workspaces between two monitors"
set descriptions[149] "Change the current mapping group"
set descriptions[151] "Behave as moveintogroup"
set descriptions[152] "Get the current cursor pos in global layout coordinates"
set descriptions[154] "Focus the requested workspace"
set --local literal_transitions set literal_transitions
set literal_transitions[1] "set inputs 106 76 34 36 2 3 79 108 38 112 42 47 116 86 117 53 89 55 91 121 123 125 16 60 61 18 126 20 128 130 26 69 99 100 28 29 103 105; set tos 2 3 4 5 3 3 3 6 3 5 3 3 3 7 9 3 5 3 10 3 3 3 3 11 3 12 13 3 3 3 14 3 5 3 3 15 3 5" set literal_transitions[1] "set inputs 121 44 126 82 4 52 51 129 90 59 9 11 12 131 14 98 102 103 134 101 138 23 20 141 26 144 108 147 70 34 35 79 115 38 152 117 122 124 40 43 80 119; set tos 15 3 22 3 22 3 3 3 3 22 3 3 4 5 6 7 3 22 8 3 3 3 3 9 3 3 10 11 3 3 3 22 3 3 3 3 14 22 12 22 16 13"
set literal_transitions[4] "set inputs 74 14 33 56 57 92 107 124 78 17 127 4 6 65 132 134 82 135 85 32 50 13 87 11 88 142; set tos 18 3 18 18 18 18 3 3 2 3 18 2 3 18 3 18 18 18 18 18 3 3 18 18 18 18" set literal_transitions[2] "set inputs 82 52 51 129 9 90 11 12 131 14 98 102 134 101 23 20 138 141 26 144 108 147 70 34 35 115 38 152 117 40 119 122 121 80 44; set tos 3 3 3 3 3 3 3 4 5 6 7 3 8 3 3 3 3 9 3 3 10 11 3 3 3 3 3 3 3 12 13 14 15 16 3"
set literal_transitions[8] "set inputs 106 76 34 2 3 79 108 38 42 47 116 86 117 53 55 91 121 123 125 16 60 61 18 126 20 128 130 26 69 100 28 29 103; set tos 2 3 4 3 3 3 6 3 3 3 3 7 9 3 3 10 3 3 3 3 11 3 12 13 3 3 3 14 3 3 3 15 3" set literal_transitions[4] "set inputs 140 64 65 46 106 28 27 53 6 67 68 130 114 13 75 100 36 153 99 60 118 42 18 139 155 123; set tos 3 17 17 17 17 3 3 5 17 3 17 17 17 3 5 3 17 17 17 17 17 17 3 17 3 17"
set literal_transitions[9] "set inputs 102 131 133 1 75 37 109 110 39 111 5 80 41 81 114 7 43 44 83 84 48 49 10 51 52 54 12 113 90 119 58 93 59 94 95 62 63 129 96 64 21 98 23 24 66 67 136 137 25 27 70 101 71 141 30 72; set tos 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3" set literal_transitions[7] "set inputs 127; set tos 3"
set literal_transitions[10] "set inputs 118 115; set tos 21 17" set literal_transitions[11] "set inputs 57; set tos 3"
set literal_transitions[12] "set inputs 104; set tos 3" set literal_transitions[12] "set inputs 10; set tos 3"
set literal_transitions[14] "set inputs 22 120 31 140 122 45 73; set tos 2 2 2 2 2 2 2" set literal_transitions[13] "set inputs 15 81; set tos 20 23"
set literal_transitions[15] "set inputs 40; set tos 3" set literal_transitions[14] "set inputs 143; set tos 3"
set literal_transitions[16] "set inputs 139 97; set tos 3 3" set literal_transitions[15] "set inputs 1 85 3 86 5 88 89 91 92 93 94 95 97 16 19 104 22 105 24 25 29 30 31 109 112 33 113 37 39 120 125 47 48 49 50 54 56 132 133 135 136 61 137 142 66 145 146 69 148 71 72 73 74 149 76 77 151 154; set tos 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 21 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3"
set literal_transitions[18] "set inputs 19 8; set tos 3 3" set literal_transitions[16] "set inputs 87 7 110 62 78 55 63; set tos 5 5 5 5 5 5 5"
set literal_transitions[19] "set inputs 77; set tos 20" set literal_transitions[17] "set inputs 41 45; set tos 3 3"
set literal_transitions[20] "set inputs 35 46; set tos 5 5" set literal_transitions[18] "set inputs 8; set tos 24"
set literal_transitions[21] "set inputs 9 68 15 138; set tos 3 3 3 3" set literal_transitions[19] "set inputs 32 150; set tos 3 3"
set literal_transitions[20] "set inputs 96 17 116 21; set tos 3 3 3 3"
set literal_transitions[21] "set inputs 107 83 128 2 84; set tos 3 3 3 3 3"
set literal_transitions[24] "set inputs 58 111; set tos 22 22"
set --local match_anything_transitions_from 2 1 7 16 11 6 15 8 3 17 13 12 set match_anything_transitions_from 7 8 1 23 6 5 3 19 12 9 10 14 11 2
set --local match_anything_transitions_to 3 8 3 3 3 16 19 8 19 3 3 19 set match_anything_transitions_to 18 3 2 3 19 3 18 3 18 3 3 18 18 2
set --local state 1 set state 1
set --local word_index 2 set word_index 2
while test $word_index -lt $COMP_CWORD while test $word_index -lt $COMP_CWORD
set --local -- word $COMP_WORDS[$word_index] set -- word $COMP_WORDS[$word_index]
if set --query literal_transitions[$state] && test -n $literal_transitions[$state] if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
set --local --erase inputs set --erase inputs
set --local --erase tos set --erase tos
eval $literal_transitions[$state] eval $literal_transitions[$state]
if contains -- $word $literals if contains -- $word $literals
set --local literal_matched 0 set literal_matched 0
for literal_id in (seq 1 (count $literals)) for literal_id in (seq 1 (count $literals))
if test $literals[$literal_id] = $word if test $literals[$literal_id] = $word
set --local index (contains --index -- $literal_id $inputs) set index (contains --index -- $literal_id $inputs)
set state $tos[$index] set state $tos[$index]
set word_index (math $word_index + 1) set word_index (math $word_index + 1)
set literal_matched 1 set literal_matched 1
@@ -181,7 +196,7 @@ function _hyprctl
end end
if set --query match_anything_transitions_from[$state] && test -n $match_anything_transitions_from[$state] if set --query match_anything_transitions_from[$state] && test -n $match_anything_transitions_from[$state]
set --local index (contains --index -- $state $match_anything_transitions_from) set index (contains --index -- $state $match_anything_transitions_from)
set state $match_anything_transitions_to[$index] set state $match_anything_transitions_to[$index]
set word_index (math $word_index + 1) set word_index (math $word_index + 1)
continue continue
@@ -191,8 +206,8 @@ function _hyprctl
end end
if set --query literal_transitions[$state] && test -n $literal_transitions[$state] if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
set --local --erase inputs set --erase inputs
set --local --erase tos set --erase tos
eval $literal_transitions[$state] eval $literal_transitions[$state]
for literal_id in $inputs for literal_id in $inputs
if test -n $descriptions[$literal_id] if test -n $descriptions[$literal_id]
@@ -203,14 +218,14 @@ function _hyprctl
end end
end end
set command_states 6 17 13 11 set command_states 8 23 9 6
set command_ids 2 3 4 1 set command_ids 1 2 4 3
if contains $state $command_states if contains $state $command_states
set --local index (contains --index $state $command_states) set index (contains --index $state $command_states)
set --local function_id $command_ids[$index] set function_id $command_ids[$index]
set --local function_name _hyprctl_$function_id set function_name _hyprctl_$function_id
set --local --erase inputs set --erase inputs
set --local --erase tos set --erase tos
$function_name "$COMP_WORDS[$COMP_CWORD]" $function_name "$COMP_WORDS[$COMP_CWORD]"
end end

View File

@@ -2,13 +2,14 @@
# Repo: https://github.com/adaszko/complgen # Repo: https://github.com/adaszko/complgen
# Generate completion scripts: "complgen aot --bash-script hyprctl.bash --fish-script hyprctl.fish --zsh-script hyprctl.zsh ./hyprctl.usage" # Generate completion scripts: "complgen aot --bash-script hyprctl.bash --fish-script hyprctl.fish --zsh-script hyprctl.zsh ./hyprctl.usage"
hyprctl [<OPTIONS>]... <ARGUMENTS> hyprctl [<OPTIONS>]... <ARGUMENTS>
<OPTIONS> ::= (-i | --instance) "Specify the Hyprland instance" <OPTIONS> ::= (-i | --instance) "Specify the Hyprland instance"
| (-j) "Output in JSON format" | (-j) "Output in JSON format"
| (-r) "Refresh state after issuing the command" | (-r) "Refresh state after issuing the command"
| (--batch) "Execute a batch of commands separated by ;" | (--batch) "Execute a batch of commands separated by ;"
| (-q | --quiet) "Disable output" | (-q | --quiet) "Disable output"
| (-h | --help) "Prints the help message"
; ;
<WINDOWS> ::= {{{ hyprctl clients | awk '/class/{print $2}' }}}; <WINDOWS> ::= {{{ hyprctl clients | awk '/class/{print $2}' }}};
@@ -59,16 +60,18 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
<ARGUMENTS> ::= (activewindow) "Get the active window name and its properties" <ARGUMENTS> ::= (activewindow) "Get the active window name and its properties"
| (activeworkspace) "Get the active workspace name and its properties" | (activeworkspace) "Get the active workspace name and its properties"
| (animations) "Gets the current config info about animations and beziers"
| (binds) "List all registered binds" | (binds) "List all registered binds"
| (clients) "List all windows with their properties" | (clients) "List all windows with their properties"
| (configerrors) "List all current config parsing errors" | (configerrors) "List all current config parsing errors"
| (cursorpos) "Get the current cursor pos in global layout coordinates" | (cursorpos) "Get the current cursor pos in global layout coordinates"
| (decorations <WINDOWS>) "List all decorations and their info" | (decorations <WINDOWS>) "List all decorations and their info"
| (descriptions) "Return a parsable JSON with all the config options, descriptions, value types and ranges"
| (devices) "List all connected keyboards and mice" | (devices) "List all connected keyboards and mice"
| (dismissnotify <NUM>) "Dismiss all or up to amount of notifications" | (dismissnotify <NUM>) "Dismiss all or up to amount of notifications"
| (dispatch <DISPATCHERS>) "Issue a dispatch to call a keybind dispatcher with an arg" | (dispatch <DISPATCHERS>) "Issue a dispatch to call a keybind dispatcher with an arg"
| (getoption) "Get the config option status (values)" | (getoption) "Get the config option status (values)"
| (globalshortcuts) "" | (globalshortcuts) "Lists all global shortcuts"
| (hyprpaper) "Interact with hyprpaper if present" | (hyprpaper) "Interact with hyprpaper if present"
| (instances) "List all running Hyprland instances and their info" | (instances) "List all running Hyprland instances and their info"
| (keyword <KEYWORDS>) "Issue a keyword to call a config keyword dynamically" | (keyword <KEYWORDS>) "Issue a keyword to call a config keyword dynamically"
@@ -79,8 +82,8 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
| (notify <NOTIFICATION_TYPES> <NUM>) "Send a notification using the built-in Hyprland notification system" | (notify <NOTIFICATION_TYPES> <NUM>) "Send a notification using the built-in Hyprland notification system"
| (output (create (wayland | x11 | headless | auto) | remove <MONITORS>)) "Allows adding/removing fake outputs to a specific backend" | (output (create (wayland | x11 | headless | auto) | remove <MONITORS>)) "Allows adding/removing fake outputs to a specific backend"
| (plugin <AVAILABLE_PLUGINS>) "Interact with a plugin" | (plugin <AVAILABLE_PLUGINS>) "Interact with a plugin"
| (reload) "Force reload the config" | (reload [config-only]) "Force reload the config"
| (rollinglog) "Print tail of the log" | (rollinglog [-f]) "Print tail of the log"
| (setcursor) "Set the cursor theme and reloads the cursor manager" | (setcursor) "Set the cursor theme and reloads the cursor manager"
| (seterror [disable]) "Set the hyprctl error string" | (seterror [disable]) "Set the hyprctl error string"
| (setprop <PROPS>) "Set a property of a window" | (setprop <PROPS>) "Set a property of a window"
@@ -92,6 +95,13 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
| (workspaces) "List all workspaces with their properties" | (workspaces) "List all workspaces with their properties"
; ;
<WINDOW_STATE> ::= (-1) "Current"
| (0) "None"
| (1) "Maximize no fullscreen"
| (2) "Fullscreen"
| (3) "Maximize and fullscreen"
;
<DISPATCHERS> ::= (exec) "Execute a shell command" <DISPATCHERS> ::= (exec) "Execute a shell command"
| (execr) "Execute a raw shell command" | (execr) "Execute a raw shell command"
| (pass) "Pass the key to a specified window" | (pass) "Pass the key to a specified window"
@@ -106,6 +116,7 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
| (settiled) "Set the current window's floating state to false" | (settiled) "Set the current window's floating state to false"
| (fullscreen) "Toggle the focused window's fullscreen state" | (fullscreen) "Toggle the focused window's fullscreen state"
| (fakefullscreen) "Toggle the focused window's internal fullscreen state" | (fakefullscreen) "Toggle the focused window's internal fullscreen state"
| (fullscreenstate <WINDOW_STATE>) "Sets the focused windows fullscreen mode and the one sent to the client"
| (dpms) "Set all monitors' DPMS status" | (dpms) "Set all monitors' DPMS status"
| (pin) "Pin a window" | (pin) "Pin a window"
| (movefocus) "Move the focus in a direction" | (movefocus) "Move the focus in a direction"
@@ -148,4 +159,5 @@ hyprctl [<OPTIONS>]... <ARGUMENTS>
| (setignoregrouplock) "Temporarily enable or disable binds:ignore_group_lock" | (setignoregrouplock) "Temporarily enable or disable binds:ignore_group_lock"
| (global) "Execute a Global Shortcut using the GlobalShortcuts portal" | (global) "Execute a Global Shortcut using the GlobalShortcuts portal"
| (submap) "Change the current mapping group" | (submap) "Change the current mapping group"
| (event) "Emits a custom event to socket2"
; ;

View File

@@ -1,145 +1,160 @@
#compdef hyprctl #compdef hyprctl
_hyprctl_cmd_2 () { _hyprctl_cmd_1 () {
hyprctl monitors | awk '/Monitor/{ print $2 }' hyprctl monitors | awk '/Monitor/{ print $2 }'
} }
_hyprctl_cmd_3 () { _hyprctl_cmd_3 () {
hyprpm list | awk '/Plugin/{ print $4 }' hyprctl clients | awk '/class/{print $2}'
} }
_hyprctl_cmd_0 () { _hyprctl_cmd_2 () {
hyprctl clients | awk '/class/{ print $2 }'
}
_hyprctl_cmd_1 () {
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}' hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
} }
_hyprctl_cmd_0 () {
hyprpm list | awk '/Plugin/{print $4}'
}
_hyprctl () { _hyprctl () {
local -a literals=("cyclenext" "globalshortcuts" "cursorpos" "bordersize" "renameworkspace" "animationstyle" "focuswindow" "0" "auto" "swapnext" "forceallowsinput" "moveactive" "activebordercolor" "alphafullscreen" "wayland" "layers" "minsize" "monitors" "1" "kill" "settiled" "3" "focusmonitor" "swapwindow" "moveoutofgroup" "notify" "movecursor" "setcursor" "seterror" "movecurrentworkspacetomonitor" "4" "nomaxsize" "forcenoanims" "setprop" "-i" "-q" "togglefloating" "workspacerules" "movetoworkspace" "disable" "setignoregrouplock" "workspaces" "movegroupwindow" "closewindow" "0" "--instance" "binds" "movewindow" "splitratio" "alpha" "denywindowfromgroup" "workspace" "configerrors" "togglegroup" "getoption" "forceopaque" "keepaspectratio" "killactive" "pass" "decorations" "devices" "focuscurrentorlast" "submap" "global" "alphafullscreenoverride" "forcerendererreload" "movewindowpixel" "headless" "version" "dpms" "resizeactive" "moveintogroup" "5" "alphaoverride" "setfloating" "rollinglog" "::=" "rounding" "layouts" "moveworkspacetomonitor" "exec" "alphainactiveoverride" "alterzorder" "fakefullscreen" "nofocus" "keyword" "forcenoborder" "forcenodim" "--quiet" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "tagwindow" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "sendshortcut" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow") local -a literals=("resizeactive" "2" "changegroupactive" "-r" "moveintogroup" "forceallowsinput" "4" "::=" "systeminfo" "all" "layouts" "setprop" "animationstyle" "switchxkblayout" "create" "denywindowfromgroup" "headless" "activebordercolor" "exec" "setcursor" "wayland" "focusurgentorlast" "workspacerules" "movecurrentworkspacetomonitor" "movetoworkspacesilent" "hyprpaper" "alpha" "inactivebordercolor" "movegroupwindow" "movecursortocorner" "movewindowpixel" "prev" "movewindow" "globalshortcuts" "clients" "dimaround" "setignoregrouplock" "splash" "execr" "monitors" "0" "forcenoborder" "-q" "animations" "1" "nomaxsize" "splitratio" "moveactive" "pass" "swapnext" "devices" "layers" "rounding" "lockactivegroup" "5" "moveworkspacetomonitor" "-f" "-i" "--quiet" "forcenodim" "pin" "0" "1" "forceopaque" "forcenoshadow" "setfloating" "minsize" "alphaoverride" "sendshortcut" "workspaces" "cyclenext" "alterzorder" "togglegroup" "lockgroups" "bordersize" "dpms" "focuscurrentorlast" "-1" "--batch" "notify" "remove" "instances" "1" "3" "moveoutofgroup" "killactive" "2" "movetoworkspace" "movecursor" "configerrors" "closewindow" "swapwindow" "tagwindow" "forcerendererreload" "centerwindow" "auto" "focuswindow" "seterror" "nofocus" "alphafullscreen" "binds" "version" "-h" "togglespecialworkspace" "fullscreen" "windowdancecompat" "0" "keyword" "toggleopaque" "3" "--instance" "togglefloating" "renameworkspace" "alphafullscreenoverride" "activeworkspace" "x11" "kill" "forceopaqueoverriden" "output" "global" "dispatch" "reload" "forcenoblur" "-j" "event" "--help" "disable" "-1" "activewindow" "keepaspectratio" "dismissnotify" "focusmonitor" "movefocus" "plugin" "exit" "workspace" "fullscreenstate" "getoption" "alphainactiveoverride" "alphainactive" "decorations" "settiled" "config-only" "descriptions" "resizewindowpixel" "fakefullscreen" "rollinglog" "swapactiveworkspaces" "submap" "next" "movewindoworgroup" "cursorpos" "forcenoanims" "focusworkspaceoncurrentmonitor" "maxsize")
local -A descriptions local -A descriptions
descriptions[1]="Focus the next window on a workspace" descriptions[1]="Resize the active window"
descriptions[3]="Get the current cursor pos in global layout coordinates" descriptions[2]="Fullscreen"
descriptions[5]="Rename a workspace" descriptions[3]="Switch to the next window in a group"
descriptions[7]="Focus the first window matching" descriptions[4]="Refresh state after issuing the command"
descriptions[10]="Swap the focused window with the next window" descriptions[5]="Move the active window into a group"
descriptions[12]="Move the active window" descriptions[7]="CONFUSED"
descriptions[16]="List the layers" descriptions[9]="Print system info"
descriptions[18]="List active outputs with their properties" descriptions[11]="List all layouts available (including plugin ones)"
descriptions[20]="Get into a kill mode, where you can kill an app by clicking on it" descriptions[12]="Set a property of a window"
descriptions[21]="Set the current window's floating state to false" descriptions[14]="Set the xkb layout index for a keyboard"
descriptions[22]="ERROR" descriptions[16]="Prohibit the active window from becoming or being inserted into group"
descriptions[23]="Focus a monitor" descriptions[19]="Execute a shell command"
descriptions[24]="Swap the active window with another window" descriptions[20]="Set the cursor theme and reloads the cursor manager"
descriptions[25]="Move the active window out of a group" descriptions[22]="Focus the urgent window or the last window"
descriptions[26]="Send a notification using the built-in Hyprland notification system" descriptions[23]="Get the list of defined workspace rules"
descriptions[27]="Move the cursor to a specified position" descriptions[24]="Move the active workspace to a monitor"
descriptions[28]="Set the cursor theme and reloads the cursor manager" descriptions[25]="Move window doesnt switch to the workspace"
descriptions[29]="Set the hyprctl error string" descriptions[26]="Interact with hyprpaper if present"
descriptions[30]="Move the active workspace to a monitor" descriptions[29]="Swap the active window with the next or previous in a group"
descriptions[31]="CONFUSED" descriptions[30]="Move the cursor to the corner of the active window"
descriptions[34]="Set a property of a window" descriptions[31]="Move a selected window"
descriptions[35]="Specify the Hyprland instance" descriptions[33]="Move the active window in a direction or to a monitor"
descriptions[36]="Disable output" descriptions[34]="Lists all global shortcuts"
descriptions[37]="Toggle the current window's floating state" descriptions[35]="List all windows with their properties"
descriptions[38]="Get the list of defined workspace rules" descriptions[37]="Temporarily enable or disable binds:ignore_group_lock"
descriptions[39]="Move the focused window to a workspace" descriptions[38]="Print the current random splash"
descriptions[41]="Temporarily enable or disable binds:ignore_group_lock" descriptions[39]="Execute a raw shell command"
descriptions[42]="List all workspaces with their properties" descriptions[40]="List active outputs with their properties"
descriptions[43]="Swap the active window with the next or previous in a group" descriptions[43]="Disable output"
descriptions[44]="Close a specified window" descriptions[44]="Gets the current config info about animations and beziers"
descriptions[45]="WARNING" descriptions[47]="Change the split ratio"
descriptions[46]="Specify the Hyprland instance" descriptions[48]="Move the active window"
descriptions[47]="List all registered binds" descriptions[49]="Pass the key to a specified window"
descriptions[48]="Move the active window in a direction or to a monitor" descriptions[50]="Swap the focused window with the next window"
descriptions[49]="Change the split ratio" descriptions[51]="List all connected keyboards and mice"
descriptions[51]="Prohibit the active window from becoming or being inserted into group" descriptions[52]="List the layers"
descriptions[52]="Change the workspace" descriptions[54]="Lock the focused group"
descriptions[53]="List all current config parsing errors" descriptions[55]="OK"
descriptions[54]="Toggle the current active window into a group" descriptions[56]="Move a workspace to a monitor"
descriptions[55]="Get the config option status (values)" descriptions[58]="Specify the Hyprland instance"
descriptions[58]="Close the active window" descriptions[59]="Disable output"
descriptions[59]="Pass the key to a specified window" descriptions[61]="Pin a window"
descriptions[60]="List all decorations and their info" descriptions[62]="WARNING"
descriptions[61]="List all connected keyboards and mice" descriptions[63]="INFO"
descriptions[62]="Switch focus from current to previously focused window" descriptions[66]="Set the current window's floating state to true"
descriptions[63]="Change the current mapping group" descriptions[69]="On shortcut X sends shortcut Y to a specified window"
descriptions[64]="Execute a Global Shortcut using the GlobalShortcuts portal" descriptions[70]="List all workspaces with their properties"
descriptions[66]="Force the renderer to reload all resources and outputs" descriptions[71]="Focus the next window on a workspace"
descriptions[67]="Move a selected window" descriptions[72]="Modify the window stack order of the active or specified window"
descriptions[69]="Print the Hyprland version: flags, commit and branch of build" descriptions[73]="Toggle the current active window into a group"
descriptions[70]="Set all monitors' DPMS status" descriptions[74]="Lock the groups"
descriptions[71]="Resize the active window" descriptions[76]="Set all monitors' DPMS status"
descriptions[72]="Move the active window into a group" descriptions[77]="Switch focus from current to previously focused window"
descriptions[73]="OK" descriptions[78]="No Icon"
descriptions[75]="Set the current window's floating state to true" descriptions[79]="Execute a batch of commands separated by ;"
descriptions[76]="Print tail of the log" descriptions[80]="Send a notification using the built-in Hyprland notification system"
descriptions[79]="List all layouts available (including plugin ones)" descriptions[82]="List all running Hyprland instances and their info"
descriptions[80]="Move a workspace to a monitor" descriptions[83]="Maximize no fullscreen"
descriptions[81]="Execute a shell command" descriptions[84]="Maximize and fullscreen"
descriptions[83]="Modify the window stack order of the active or specified window" descriptions[85]="Move the active window out of a group"
descriptions[84]="Toggle the focused window's internal fullscreen state" descriptions[86]="Close the active window"
descriptions[86]="Issue a keyword to call a config keyword dynamically" descriptions[87]="HINT"
descriptions[89]="Disable output" descriptions[88]="Move the focused window to a workspace"
descriptions[90]="Pin a window" descriptions[89]="Move the cursor to a specified position"
descriptions[91]="Allows adding/removing fake outputs to a specific backend" descriptions[90]="List all current config parsing errors"
descriptions[93]="Toggle a special workspace on/off" descriptions[91]="Close a specified window"
descriptions[94]="Toggle the focused window's fullscreen state" descriptions[92]="Swap the active window with another window"
descriptions[95]="Toggle the current window to always be opaque" descriptions[93]="Apply a tag to the window"
descriptions[96]="Focus the requested workspace" descriptions[94]="Force the renderer to reload all resources and outputs"
descriptions[98]="Switch to the next window in a group" descriptions[95]="Center the active window"
descriptions[99]="Output in JSON format" descriptions[97]="Focus the first window matching"
descriptions[100]="List all running Hyprland instances and their info" descriptions[98]="Set the hyprctl error string"
descriptions[101]="Execute a raw shell command" descriptions[101]="List all registered binds"
descriptions[102]="Exit the compositor with no questions asked" descriptions[102]="Print the Hyprland version: flags, commit and branch of build"
descriptions[103]="List all windows with their properties" descriptions[103]="Prints the help message"
descriptions[105]="Execute a batch of commands separated by ;" descriptions[104]="Toggle a special workspace on/off"
descriptions[106]="Dismiss all or up to amount of notifications" descriptions[105]="Toggle the focused window's fullscreen state"
descriptions[108]="Set the xkb layout index for a keyboard" descriptions[107]="None"
descriptions[109]="Move window doesnt switch to the workspace" descriptions[108]="Issue a keyword to call a config keyword dynamically"
descriptions[110]="Apply a tag to the window" descriptions[109]="Toggle the current window to always be opaque"
descriptions[111]="Behave as moveintogroup" descriptions[110]="ERROR"
descriptions[112]="Refresh state after issuing the command" descriptions[111]="Specify the Hyprland instance"
descriptions[113]="Move the focus in a direction" descriptions[112]="Toggle the current window's floating state"
descriptions[114]="Focus the urgent window or the last window" descriptions[113]="Rename a workspace"
descriptions[116]="Get the active workspace name and its properties" descriptions[115]="Get the active workspace name and its properties"
descriptions[117]="Issue a dispatch to call a keybind dispatcher with an arg" descriptions[117]="Get into a kill mode, where you can kill an app by clicking on it"
descriptions[119]="Center the active window" descriptions[119]="Allows adding/removing fake outputs to a specific backend"
descriptions[120]="HINT" descriptions[120]="Execute a Global Shortcut using the GlobalShortcuts portal"
descriptions[121]="Interact with hyprpaper if present" descriptions[121]="Issue a dispatch to call a keybind dispatcher with an arg"
descriptions[122]="No Icon" descriptions[122]="Force reload the config"
descriptions[123]="Force reload the config" descriptions[124]="Output in JSON format"
descriptions[125]="Print system info" descriptions[125]="Emits a custom event to socket2"
descriptions[126]="Interact with a plugin" descriptions[126]="Prints the help message"
descriptions[128]="Get the active window name and its properties" descriptions[128]="Current"
descriptions[129]="Swap the active workspaces between two monitors" descriptions[129]="Get the active window name and its properties"
descriptions[130]="Print the current random splash" descriptions[131]="Dismiss all or up to amount of notifications"
descriptions[131]="On shortcut X sends shortcut Y to a specified window" descriptions[132]="Focus a monitor"
descriptions[133]="Lock the focused group" descriptions[133]="Move the focus in a direction"
descriptions[136]="Lock the groups" descriptions[134]="Interact with a plugin"
descriptions[137]="Move the cursor to the corner of the active window" descriptions[135]="Exit the compositor with no questions asked"
descriptions[140]="INFO" descriptions[136]="Change the workspace"
descriptions[141]="Resize a selected window" descriptions[137]="Sets the focused windows fullscreen mode and the one sent to the client"
descriptions[138]="Get the config option status (values)"
descriptions[141]="List all decorations and their info"
descriptions[142]="Set the current window's floating state to false"
descriptions[144]="Return a parsable JSON with all the config options, descriptions, value types and ranges"
descriptions[145]="Resize a selected window"
descriptions[146]="Toggle the focused window's internal fullscreen state"
descriptions[147]="Print tail of the log"
descriptions[148]="Swap the active workspaces between two monitors"
descriptions[149]="Change the current mapping group"
descriptions[151]="Behave as moveintogroup"
descriptions[152]="Get the current cursor pos in global layout coordinates"
descriptions[154]="Focus the requested workspace"
local -A literal_transitions local -A literal_transitions
literal_transitions[1]="([106]=2 [76]=3 [34]=4 [36]=5 [2]=3 [3]=3 [79]=3 [108]=6 [38]=3 [112]=5 [42]=3 [47]=3 [116]=3 [86]=7 [117]=9 [53]=3 [89]=5 [55]=3 [91]=10 [121]=3 [123]=3 [125]=3 [16]=3 [60]=11 [61]=3 [18]=12 [126]=13 [20]=3 [128]=3 [130]=3 [26]=14 [69]=3 [99]=5 [100]=3 [28]=3 [29]=15 [103]=3 [105]=5)" literal_transitions[1]="([121]=15 [44]=3 [126]=22 [82]=3 [4]=22 [52]=3 [51]=3 [129]=3 [90]=3 [59]=22 [9]=3 [11]=3 [12]=4 [131]=5 [14]=6 [98]=7 [102]=3 [103]=22 [134]=8 [101]=3 [138]=3 [23]=3 [20]=3 [141]=9 [26]=3 [144]=3 [108]=10 [147]=11 [70]=3 [34]=3 [35]=3 [79]=22 [115]=3 [38]=3 [152]=3 [117]=3 [122]=14 [124]=22 [40]=12 [43]=22 [80]=16 [119]=13)"
literal_transitions[4]="([74]=18 [14]=3 [33]=18 [56]=18 [57]=18 [92]=18 [107]=3 [124]=3 [78]=2 [17]=3 [127]=18 [4]=2 [6]=3 [65]=18 [132]=3 [134]=18 [82]=18 [135]=18 [85]=18 [32]=18 [50]=3 [13]=3 [87]=18 [11]=18 [88]=18 [142]=18)" literal_transitions[2]="([82]=3 [52]=3 [51]=3 [129]=3 [9]=3 [90]=3 [11]=3 [12]=4 [131]=5 [14]=6 [98]=7 [102]=3 [134]=8 [101]=3 [23]=3 [20]=3 [138]=3 [141]=9 [26]=3 [144]=3 [108]=10 [147]=11 [70]=3 [34]=3 [35]=3 [115]=3 [38]=3 [152]=3 [117]=3 [40]=12 [119]=13 [122]=14 [121]=15 [80]=16 [44]=3)"
literal_transitions[8]="([106]=2 [76]=3 [34]=4 [2]=3 [3]=3 [79]=3 [108]=6 [38]=3 [42]=3 [47]=3 [116]=3 [86]=7 [117]=9 [53]=3 [55]=3 [91]=10 [121]=3 [123]=3 [125]=3 [16]=3 [60]=11 [61]=3 [18]=12 [126]=13 [20]=3 [128]=3 [130]=3 [26]=14 [69]=3 [100]=3 [28]=3 [29]=15 [103]=3)" literal_transitions[4]="([140]=3 [64]=17 [65]=17 [46]=17 [106]=17 [28]=3 [27]=3 [53]=5 [6]=17 [67]=3 [68]=17 [130]=17 [114]=17 [13]=3 [75]=5 [100]=3 [36]=17 [153]=17 [99]=17 [60]=17 [118]=17 [42]=17 [18]=3 [139]=17 [155]=3 [123]=17)"
literal_transitions[9]="([102]=3 [131]=3 [133]=3 [1]=3 [75]=3 [37]=3 [109]=3 [110]=3 [39]=3 [111]=3 [5]=3 [80]=3 [41]=3 [81]=3 [114]=3 [7]=3 [43]=3 [44]=3 [83]=3 [84]=3 [48]=3 [49]=3 [10]=3 [51]=3 [52]=3 [54]=3 [12]=3 [113]=3 [90]=3 [119]=3 [58]=3 [93]=3 [59]=3 [94]=3 [95]=3 [62]=3 [63]=3 [129]=3 [96]=3 [64]=3 [21]=3 [98]=3 [23]=3 [24]=3 [66]=3 [67]=3 [136]=3 [137]=3 [25]=3 [27]=3 [70]=3 [101]=3 [71]=3 [141]=3 [30]=3 [72]=3)" literal_transitions[7]="([127]=3)"
literal_transitions[10]="([118]=21 [115]=17)" literal_transitions[11]="([57]=3)"
literal_transitions[12]="([104]=3)" literal_transitions[12]="([10]=3)"
literal_transitions[14]="([22]=2 [120]=2 [31]=2 [140]=2 [122]=2 [45]=2 [73]=2)" literal_transitions[13]="([15]=20 [81]=23)"
literal_transitions[15]="([40]=3)" literal_transitions[14]="([143]=3)"
literal_transitions[16]="([139]=3 [97]=3)" literal_transitions[15]="([1]=3 [85]=3 [3]=3 [86]=3 [5]=3 [88]=3 [89]=3 [91]=3 [92]=3 [93]=3 [94]=3 [95]=3 [97]=3 [16]=3 [19]=3 [104]=3 [22]=3 [105]=3 [24]=3 [25]=3 [29]=3 [30]=3 [31]=3 [109]=3 [112]=3 [33]=3 [113]=3 [37]=3 [39]=3 [120]=3 [125]=3 [47]=3 [48]=3 [49]=3 [50]=3 [54]=3 [56]=3 [132]=3 [133]=3 [135]=3 [136]=3 [61]=3 [137]=21 [142]=3 [66]=3 [145]=3 [146]=3 [69]=3 [148]=3 [71]=3 [72]=3 [73]=3 [74]=3 [149]=3 [76]=3 [77]=3 [151]=3 [154]=3)"
literal_transitions[18]="([19]=3 [8]=3)" literal_transitions[16]="([87]=5 [7]=5 [110]=5 [62]=5 [78]=5 [55]=5 [63]=5)"
literal_transitions[19]="([77]=20)" literal_transitions[17]="([41]=3 [45]=3)"
literal_transitions[20]="([35]=5 [46]=5)" literal_transitions[18]="([8]=24)"
literal_transitions[21]="([9]=3 [68]=3 [15]=3 [138]=3)" literal_transitions[19]="([32]=3 [150]=3)"
literal_transitions[20]="([96]=3 [17]=3 [116]=3 [21]=3)"
literal_transitions[21]="([107]=3 [83]=3 [128]=3 [2]=3 [84]=3)"
literal_transitions[24]="([58]=22 [111]=22)"
local -A match_anything_transitions local -A match_anything_transitions
match_anything_transitions=([2]=3 [1]=8 [7]=3 [16]=3 [11]=3 [6]=16 [15]=19 [8]=8 [3]=19 [17]=3 [13]=3 [12]=19) match_anything_transitions=([7]=18 [8]=3 [1]=2 [23]=3 [6]=19 [5]=3 [3]=18 [19]=3 [12]=18 [9]=3 [10]=3 [14]=18 [11]=18 [2]=2)
declare -A subword_transitions declare -A subword_transitions
@@ -199,7 +214,7 @@ _hyprctl () {
fi fi
done done
fi fi
local -A commands=([6]=1 [17]=2 [13]=3 [11]=0) local -A commands=([8]=0 [23]=1 [9]=3 [6]=2)
if [[ -v "commands[$state]" ]]; then if [[ -v "commands[$state]" ]]; then
local command_id=${commands[$state]} local command_id=${commands[$state]}
@@ -252,4 +267,8 @@ _hyprctl () {
return 0 return 0
} }
compdef _hyprctl hyprctl if [[ $ZSH_EVAL_CONTEXT =~ :file$ ]]; then
compdef _hyprctl hyprctl
else
_hyprctl
fi

View File

@@ -26,6 +26,7 @@
#include <regex> #include <regex>
#include <sys/socket.h> #include <sys/socket.h>
#include <hyprutils/string/String.hpp> #include <hyprutils/string/String.hpp>
#include <cstring>
using namespace Hyprutils::String; using namespace Hyprutils::String;
#include "Strings.hpp" #include "Strings.hpp"
@@ -113,7 +114,7 @@ int rollingRead(const int socket) {
constexpr size_t BUFFER_SIZE = 8192; constexpr size_t BUFFER_SIZE = 8192;
std::array<char, BUFFER_SIZE> buffer = {0}; std::array<char, BUFFER_SIZE> buffer = {0};
int sizeWritten = 0; long sizeWritten = 0;
std::cout << "[hyprctl] reading from socket following up log:" << std::endl; std::cout << "[hyprctl] reading from socket following up log:" << std::endl;
while (!sigintReceived) { while (!sigintReceived) {
sizeWritten = read(socket, buffer.data(), BUFFER_SIZE); sizeWritten = read(socket, buffer.data(), BUFFER_SIZE);
@@ -286,12 +287,12 @@ void instancesRequest(bool json) {
std::vector<SInstanceData> inst = instances(); std::vector<SInstanceData> inst = instances();
if (!json) { if (!json) {
for (auto& el : inst) { for (auto const& el : inst) {
result += std::format("instance {}:\n\ttime: {}\n\tpid: {}\n\twl socket: {}\n\n", el.id, el.time, el.pid, el.wlSocket); result += std::format("instance {}:\n\ttime: {}\n\tpid: {}\n\twl socket: {}\n\n", el.id, el.time, el.pid, el.wlSocket);
} }
} else { } else {
result += '['; result += '[';
for (auto& el : inst) { for (auto const& el : inst) {
result += std::format(R"#( result += std::format(R"#(
{{ {{
"instance": "{}", "instance": "{}",

View File

@@ -1,10 +1,26 @@
executable('hyprctl', 'main.cpp', executable(
'hyprctl',
'main.cpp',
dependencies: [ dependencies: [
dependency('hyprutils', version: '>= 0.1.1'), dependency('hyprutils', version: '>= 0.1.1'),
], ],
install: true install: true,
) )
install_data('hyprctl.bash', install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), install_tag: 'runtime', rename: 'hyprctl') install_data(
install_data('hyprctl.fish', install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), install_tag: 'runtime') 'hyprctl.bash',
install_data('hyprctl.zsh', install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), install_tag: 'runtime', rename: '_hyprctl') install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'),
install_tag: 'runtime',
rename: 'hyprctl',
)
install_data(
'hyprctl.fish',
install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'),
install_tag: 'runtime',
)
install_data(
'hyprctl.zsh',
install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'),
install_tag: 'runtime',
rename: '_hyprctl',
)

View File

@@ -2,6 +2,10 @@ _hyprpm_cmd_0 () {
hyprpm list | awk '/Plugin/{print $4}' hyprpm list | awk '/Plugin/{print $4}'
} }
_hyprpm_cmd_1 () {
hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//'
}
_hyprpm () { _hyprpm () {
if [[ $(type -t _get_comp_words_by_ref) != function ]]; then if [[ $(type -t _get_comp_words_by_ref) != function ]]; then
echo _get_comp_words_by_ref: function not defined. Make sure the bash-completions system package is installed echo _get_comp_words_by_ref: function not defined. Make sure the bash-completions system package is installed
@@ -11,16 +15,13 @@ _hyprpm () {
local words cword local words cword
_get_comp_words_by_ref -n "$COMP_WORDBREAKS" words cword _get_comp_words_by_ref -n "$COMP_WORDBREAKS" words cword
local -a literals=("-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f") declare -a literals=(--no-shallow -n ::= disable list --help update add --verbose -v --force -s remove enable --notify -h reload -f)
declare -A literal_transitions declare -A literal_transitions
literal_transitions[0]="([9]=6 [2]=2 [7]=6 [8]=6 [4]=6 [10]=2 [11]=3 [5]=2 [13]=6 [3]=3 [14]=2 [15]=6 [6]=2)" literal_transitions[0]="([0]=7 [3]=3 [4]=4 [8]=7 [9]=7 [6]=4 [7]=4 [11]=7 [5]=7 [10]=7 [12]=2 [13]=3 [15]=7 [16]=4 [17]=7)"
literal_transitions[1]="([10]=2 [11]=3 [3]=3 [2]=2 [14]=2 [5]=2 [6]=2)" literal_transitions[1]="([12]=2 [13]=3 [3]=3 [4]=4 [16]=4 [6]=4 [7]=4)"
literal_transitions[4]="([1]=5)" literal_transitions[5]="([2]=6)"
literal_transitions[5]="([0]=6 [12]=6)" literal_transitions[6]="([1]=7 [14]=7)"
declare -A match_anything_transitions=([1]=1 [4]=5 [3]=4 [2]=4 [0]=1)
declare -A match_anything_transitions
match_anything_transitions=([3]=2 [2]=4 [0]=1 [1]=1)
declare -A subword_transitions declare -A subword_transitions
local state=0 local state=0
@@ -58,21 +59,9 @@ _hyprpm () {
done done
local -a matches=()
local prefix="${words[$cword]}" local prefix="${words[$cword]}"
local shortest_suffix="$word"
for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do
local char="${COMP_WORDBREAKS:$i:1}"
local candidate="${word##*$char}"
if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then
shortest_suffix=$candidate
fi
done
local superfluous_prefix=""
if [[ "$shortest_suffix" != "$word" ]]; then
local superfluous_prefix=${word%$shortest_suffix}
fi
if [[ -v "literal_transitions[$state]" ]]; then if [[ -v "literal_transitions[$state]" ]]; then
local state_transitions_initializer=${literal_transitions[$state]} local state_transitions_initializer=${literal_transitions[$state]}
declare -A state_transitions declare -A state_transitions
@@ -81,25 +70,38 @@ _hyprpm () {
for literal_id in "${!state_transitions[@]}"; do for literal_id in "${!state_transitions[@]}"; do
local literal="${literals[$literal_id]}" local literal="${literals[$literal_id]}"
if [[ $literal = "${prefix}"* ]]; then if [[ $literal = "${prefix}"* ]]; then
local completion=${literal#"$superfluous_prefix"} matches+=("$literal ")
COMPREPLY+=("$completion ")
fi fi
done done
fi fi
declare -A commands declare -A commands
commands=([3]=0) commands=([3]=0 [2]=1)
if [[ -v "commands[$state]" ]]; then if [[ -v "commands[$state]" ]]; then
local command_id=${commands[$state]} local command_id=${commands[$state]}
local completions=() local completions=()
mapfile -t completions < <(_hyprpm_cmd_${command_id} "$prefix" | cut -f1) readarray -t completions < <(_hyprpm_cmd_${command_id} "$prefix" | cut -f1)
for item in "${completions[@]}"; do for item in "${completions[@]}"; do
if [[ $item = "${prefix}"* ]]; then if [[ $item = "${prefix}"* ]]; then
COMPREPLY+=("$item") matches+=("$item")
fi fi
done done
fi fi
local shortest_suffix="$prefix"
for ((i=0; i < ${#COMP_WORDBREAKS}; i++)); do
local char="${COMP_WORDBREAKS:$i:1}"
local candidate=${prefix##*$char}
if [[ ${#candidate} -lt ${#shortest_suffix} ]]; then
shortest_suffix=$candidate
fi
done
local superfluous_prefix=""
if [[ "$shortest_suffix" != "$prefix" ]]; then
local superfluous_prefix=${prefix%$shortest_suffix}
fi
COMPREPLY=("${matches[@]#$superfluous_prefix}")
return 0 return 0
} }

View File

@@ -3,6 +3,11 @@ function _hyprpm_1
hyprpm list | awk '/Plugin/{print $4}' hyprpm list | awk '/Plugin/{print $4}'
end end
function _hyprpm_2
set 1 $argv[1]
hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//'
end
function _hyprpm function _hyprpm
set COMP_LINE (commandline --cut-at-cursor) set COMP_LINE (commandline --cut-at-cursor)
@@ -14,49 +19,51 @@ function _hyprpm
set COMP_CWORD (count $COMP_WORDS) set COMP_CWORD (count $COMP_WORDS)
end end
set --local literals "-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f" set literals "--no-shallow" "-n" "::=" "disable" "list" "--help" "update" "add" "--verbose" "-v" "--force" "-s" "remove" "enable" "--notify" "-h" "reload" "-f"
set --local descriptions set descriptions
set descriptions[1] "Send a hyprland notification for important events (e.g. load fail)" set descriptions[1] "Disable shallow cloning of Hyprland sources"
set descriptions[3] "List all installed plugins" set descriptions[2] "Send a hyprland notification for important events (e.g. load fail)"
set descriptions[4] "Unload a plugin" set descriptions[4] "Unload a plugin"
set descriptions[5] "Show help menu" set descriptions[5] "List all installed plugins"
set descriptions[6] "Check and update all plugins if needed" set descriptions[6] "Show help menu"
set descriptions[7] "Install a new plugin repository from git" set descriptions[7] "Check and update all plugins if needed"
set descriptions[8] "Enable too much loggin" set descriptions[8] "Install a new plugin repository from git"
set descriptions[9] "Enable too much loggin" set descriptions[9] "Enable too much loggin"
set descriptions[10] "Force an operation ignoring checks (e.g. update -f)" set descriptions[10] "Enable too much loggin"
set descriptions[11] "Remove a plugin repository" set descriptions[11] "Force an operation ignoring checks (e.g. update -f)"
set descriptions[12] "Load a plugin" set descriptions[12] "Disable shallow cloning of Hyprland sources"
set descriptions[13] "Send a hyprland notification for important events (e.g. load fail)" set descriptions[13] "Remove a plugin repository"
set descriptions[14] "Show help menu" set descriptions[14] "Load a plugin"
set descriptions[15] "Reload all plugins" set descriptions[15] "Send a hyprland notification for important events (e.g. load fail)"
set descriptions[16] "Force an operation ignoring checks (e.g. update -f)" set descriptions[16] "Show help menu"
set descriptions[17] "Reload all plugins"
set descriptions[18] "Force an operation ignoring checks (e.g. update -f)"
set --local literal_transitions set literal_transitions
set literal_transitions[1] "set inputs 10 3 8 9 5 11 12 6 14 4 15 16 7; set tos 7 3 7 7 7 3 4 3 7 4 3 7 3" set literal_transitions[1] "set inputs 1 4 5 9 10 7 8 12 6 11 13 14 16 17 18; set tos 8 4 5 8 8 5 5 8 8 8 3 4 8 5 8"
set literal_transitions[2] "set inputs 11 12 4 3 15 6 7; set tos 3 4 4 3 3 3 3" set literal_transitions[2] "set inputs 13 14 4 5 17 7 8; set tos 3 4 4 5 5 5 5"
set literal_transitions[5] "set inputs 2; set tos 6" set literal_transitions[6] "set inputs 3; set tos 7"
set literal_transitions[6] "set inputs 1 13; set tos 7 7" set literal_transitions[7] "set inputs 2 15; set tos 8 8"
set --local match_anything_transitions_from 4 3 1 2 set match_anything_transitions_from 2 5 4 3 1
set --local match_anything_transitions_to 3 5 2 2 set match_anything_transitions_to 2 6 5 5 2
set --local state 1 set state 1
set --local word_index 2 set word_index 2
while test $word_index -lt $COMP_CWORD while test $word_index -lt $COMP_CWORD
set --local -- word $COMP_WORDS[$word_index] set -- word $COMP_WORDS[$word_index]
if set --query literal_transitions[$state] && test -n $literal_transitions[$state] if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
set --local --erase inputs set --erase inputs
set --local --erase tos set --erase tos
eval $literal_transitions[$state] eval $literal_transitions[$state]
if contains -- $word $literals if contains -- $word $literals
set --local literal_matched 0 set literal_matched 0
for literal_id in (seq 1 (count $literals)) for literal_id in (seq 1 (count $literals))
if test $literals[$literal_id] = $word if test $literals[$literal_id] = $word
set --local index (contains --index -- $literal_id $inputs) set index (contains --index -- $literal_id $inputs)
set state $tos[$index] set state $tos[$index]
set word_index (math $word_index + 1) set word_index (math $word_index + 1)
set literal_matched 1 set literal_matched 1
@@ -70,7 +77,7 @@ function _hyprpm
end end
if set --query match_anything_transitions_from[$state] && test -n $match_anything_transitions_from[$state] if set --query match_anything_transitions_from[$state] && test -n $match_anything_transitions_from[$state]
set --local index (contains --index -- $state $match_anything_transitions_from) set index (contains --index -- $state $match_anything_transitions_from)
set state $match_anything_transitions_to[$index] set state $match_anything_transitions_to[$index]
set word_index (math $word_index + 1) set word_index (math $word_index + 1)
continue continue
@@ -80,8 +87,8 @@ function _hyprpm
end end
if set --query literal_transitions[$state] && test -n $literal_transitions[$state] if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
set --local --erase inputs set --erase inputs
set --local --erase tos set --erase tos
eval $literal_transitions[$state] eval $literal_transitions[$state]
for literal_id in $inputs for literal_id in $inputs
if test -n $descriptions[$literal_id] if test -n $descriptions[$literal_id]
@@ -92,14 +99,14 @@ function _hyprpm
end end
end end
set command_states 4 set command_states 4 3
set command_ids 1 set command_ids 1 2
if contains $state $command_states if contains $state $command_states
set --local index (contains --index $state $command_states) set index (contains --index $state $command_states)
set --local function_id $command_ids[$index] set function_id $command_ids[$index]
set --local function_name _hyprpm_$function_id set function_name _hyprpm_$function_id
set --local --erase inputs set --erase inputs
set --local --erase tos set --erase tos
$function_name "$COMP_WORDS[$COMP_CWORD]" $function_name "$COMP_WORDS[$COMP_CWORD]"
end end

View File

@@ -5,10 +5,11 @@ hyprpm [<FLAGS>]... <ARGUMENT>
| (--help | -h) "Show help menu" | (--help | -h) "Show help menu"
| (--verbose | -v) "Enable too much loggin" | (--verbose | -v) "Enable too much loggin"
| (--force | -f) "Force an operation ignoring checks (e.g. update -f)" | (--force | -f) "Force an operation ignoring checks (e.g. update -f)"
| (--no-shallow | -s) "Disable shallow cloning of Hyprland sources"
; ;
<ARGUMENT> ::= (add) "Install a new plugin repository from git" <ARGUMENT> ::= (add) "Install a new plugin repository from git"
| (remove) "Remove a plugin repository" | (remove <PLUGIN_REPOS>) "Remove a plugin repository"
| (update) "Check and update all plugins if needed" | (update) "Check and update all plugins if needed"
| (list) "List all installed plugins" | (list) "List all installed plugins"
| (enable <PLUGINS>) "Load a plugin" | (enable <PLUGINS>) "Load a plugin"
@@ -17,3 +18,4 @@ hyprpm [<FLAGS>]... <ARGUMENT>
; ;
<PLUGINS> ::= {{{ hyprpm list | awk '/Plugin/{print $4}' }}}; <PLUGINS> ::= {{{ hyprpm list | awk '/Plugin/{print $4}' }}};
<PLUGIN_REPOS> ::= {{{ hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//' }}};

View File

@@ -4,34 +4,40 @@ _hyprpm_cmd_0 () {
hyprpm list | awk '/Plugin/{print $4}' hyprpm list | awk '/Plugin/{print $4}'
} }
_hyprpm_cmd_1 () {
hyprpm list | awk '/Repository/{print $4}' | sed 's/:$//'
}
_hyprpm () { _hyprpm () {
local -a literals=("-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f") local -a literals=("--no-shallow" "-n" "::=" "disable" "list" "--help" "update" "add" "--verbose" "-v" "--force" "-s" "remove" "enable" "--notify" "-h" "reload" "-f")
local -A descriptions local -A descriptions
descriptions[1]="Send a hyprland notification for important events (e.g. load fail)" descriptions[1]="Disable shallow cloning of Hyprland sources"
descriptions[3]="List all installed plugins" descriptions[2]="Send a hyprland notification for important events (e.g. load fail)"
descriptions[4]="Unload a plugin" descriptions[4]="Unload a plugin"
descriptions[5]="Show help menu" descriptions[5]="List all installed plugins"
descriptions[6]="Check and update all plugins if needed" descriptions[6]="Show help menu"
descriptions[7]="Install a new plugin repository from git" descriptions[7]="Check and update all plugins if needed"
descriptions[8]="Enable too much loggin" descriptions[8]="Install a new plugin repository from git"
descriptions[9]="Enable too much loggin" descriptions[9]="Enable too much loggin"
descriptions[10]="Force an operation ignoring checks (e.g. update -f)" descriptions[10]="Enable too much loggin"
descriptions[11]="Remove a plugin repository" descriptions[11]="Force an operation ignoring checks (e.g. update -f)"
descriptions[12]="Load a plugin" descriptions[12]="Disable shallow cloning of Hyprland sources"
descriptions[13]="Send a hyprland notification for important events (e.g. load fail)" descriptions[13]="Remove a plugin repository"
descriptions[14]="Show help menu" descriptions[14]="Load a plugin"
descriptions[15]="Reload all plugins" descriptions[15]="Send a hyprland notification for important events (e.g. load fail)"
descriptions[16]="Force an operation ignoring checks (e.g. update -f)" descriptions[16]="Show help menu"
descriptions[17]="Reload all plugins"
descriptions[18]="Force an operation ignoring checks (e.g. update -f)"
local -A literal_transitions local -A literal_transitions
literal_transitions[1]="([10]=7 [3]=3 [8]=7 [9]=7 [5]=7 [11]=3 [12]=4 [6]=3 [14]=7 [4]=4 [15]=3 [16]=7 [7]=3)" literal_transitions[1]="([1]=8 [4]=4 [5]=5 [9]=8 [10]=8 [7]=5 [8]=5 [12]=8 [6]=8 [11]=8 [13]=3 [14]=4 [16]=8 [17]=5 [18]=8)"
literal_transitions[2]="([11]=3 [12]=4 [4]=4 [3]=3 [15]=3 [6]=3 [7]=3)" literal_transitions[2]="([13]=3 [14]=4 [4]=4 [5]=5 [17]=5 [7]=5 [8]=5)"
literal_transitions[5]="([2]=6)" literal_transitions[6]="([3]=7)"
literal_transitions[6]="([1]=7 [13]=7)" literal_transitions[7]="([2]=8 [15]=8)"
local -A match_anything_transitions local -A match_anything_transitions
match_anything_transitions=([4]=3 [3]=5 [1]=2 [2]=2) match_anything_transitions=([2]=2 [5]=6 [4]=5 [3]=5 [1]=2)
declare -A subword_transitions declare -A subword_transitions
@@ -91,7 +97,7 @@ _hyprpm () {
fi fi
done done
fi fi
local -A commands=([4]=0) local -A commands=([4]=0 [3]=1)
if [[ -v "commands[$state]" ]]; then if [[ -v "commands[$state]" ]]; then
local command_id=${commands[$state]} local command_id=${commands[$state]}

View File

@@ -49,7 +49,7 @@ void DataState::addNewPluginRepo(const SPluginRepository& repo) {
{"rev", repo.rev} {"rev", repo.rev}
}} }}
}; };
for (auto& p : repo.plugins) { for (auto const& p : repo.plugins) {
// copy .so to the good place // copy .so to the good place
if (std::filesystem::exists(p.filename)) if (std::filesystem::exists(p.filename))
std::filesystem::copy_file(p.filename, PATH + "/" + p.name + ".so"); std::filesystem::copy_file(p.filename, PATH + "/" + p.name + ".so");

View File

@@ -6,7 +6,7 @@ CManifest::CManifest(const eManifestType type, const std::string& path) {
auto manifest = toml::parse_file(path); auto manifest = toml::parse_file(path);
if (type == MANIFEST_HYPRLOAD) { if (type == MANIFEST_HYPRLOAD) {
for (auto& [key, val] : manifest) { for (auto const& [key, val] : manifest) {
if (key.str().ends_with(".build")) if (key.str().ends_with(".build"))
continue; continue;
@@ -63,7 +63,7 @@ CManifest::CManifest(const eManifestType type, const std::string& path) {
} }
} }
for (auto& [key, val] : manifest) { for (auto const& [key, val] : manifest) {
if (key.str() == "repository") if (key.str() == "repository")
continue; continue;

View File

@@ -204,9 +204,9 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
progress.m_iSteps = 2; progress.m_iSteps = 2;
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " parsed manifest, found " + std::to_string(pManifest->m_vPlugins.size()) + " plugins:"); progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " parsed manifest, found " + std::to_string(pManifest->m_vPlugins.size()) + " plugins:");
for (auto& pl : pManifest->m_vPlugins) { for (auto const& pl : pManifest->m_vPlugins) {
std::string message = std::string{Colors::RESET} + "" + pl.name + " by "; std::string message = std::string{Colors::RESET} + "" + pl.name + " by ";
for (auto& a : pl.authors) { for (auto const& a : pl.authors) {
message += a + ", "; message += a + ", ";
} }
if (pl.authors.size() > 0) { if (pl.authors.size() > 0) {
@@ -222,7 +222,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking"); progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking");
for (auto& [hl, plugin] : pManifest->m_sRepository.commitPins) { for (auto const& [hl, plugin] : pManifest->m_sRepository.commitPins) {
if (hl != HLVER.hash) if (hl != HLVER.hash)
continue; continue;
@@ -264,7 +264,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name); progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
for (auto& bs : p.buildSteps) { for (auto const& bs : p.buildSteps) {
std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs); std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs);
out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n"; out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n";
} }
@@ -299,7 +299,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string&
repo.url = url; repo.url = url;
repo.rev = rev; repo.rev = rev;
repo.hash = repohash; repo.hash = repohash;
for (auto& p : pManifest->m_vPlugins) { for (auto const& p : pManifest->m_vPlugins) {
repo.plugins.push_back(SPlugin{p.name, m_szWorkingPluginDirectory + "/" + p.output, false, p.failed}); repo.plugins.push_back(SPlugin{p.name, m_szWorkingPluginDirectory + "/" + p.output, false, p.failed});
} }
DataState::addNewPluginRepo(repo); DataState::addNewPluginRepo(repo);
@@ -579,7 +579,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
const std::string USERNAME = getpwuid(getuid())->pw_name; const std::string USERNAME = getpwuid(getuid())->pw_name;
m_szWorkingPluginDirectory = "/tmp/hyprpm/" + USERNAME; m_szWorkingPluginDirectory = "/tmp/hyprpm/" + USERNAME;
for (auto& repo : REPOS) { for (auto const& repo : REPOS) {
bool update = forceUpdateAll; bool update = forceUpdateAll;
progress.m_iSteps++; progress.m_iSteps++;
@@ -658,7 +658,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking"); progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking");
for (auto& [hl, plugin] : pManifest->m_sRepository.commitPins) { for (auto const& [hl, plugin] : pManifest->m_sRepository.commitPins) {
if (hl != HLVER.hash) if (hl != HLVER.hash)
continue; continue;
@@ -679,7 +679,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name); progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
for (auto& bs : p.buildSteps) { for (auto const& bs : p.buildSteps) {
std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs); std::string cmd = std::format("cd {} && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", m_szWorkingPluginDirectory, DataState::getHeadersPath(), bs);
out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n"; out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n";
} }
@@ -709,7 +709,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) {
if (repohash.length() > 0) if (repohash.length() > 0)
repohash.pop_back(); repohash.pop_back();
newrepo.hash = repohash; newrepo.hash = repohash;
for (auto& p : pManifest->m_vPlugins) { for (auto const& p : pManifest->m_vPlugins) {
const auto OLDPLUGINIT = std::find_if(repo.plugins.begin(), repo.plugins.end(), [&](const auto& other) { return other.name == p.name; }); const auto OLDPLUGINIT = std::find_if(repo.plugins.begin(), repo.plugins.end(), [&](const auto& other) { return other.name == p.name; });
newrepo.plugins.push_back(SPlugin{p.name, m_szWorkingPluginDirectory + "/" + p.output, OLDPLUGINIT != repo.plugins.end() ? OLDPLUGINIT->enabled : false}); newrepo.plugins.push_back(SPlugin{p.name, m_szWorkingPluginDirectory + "/" + p.output, OLDPLUGINIT != repo.plugins.end() ? OLDPLUGINIT->enabled : false});
} }
@@ -794,8 +794,8 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
const auto REPOS = DataState::getAllRepositories(); const auto REPOS = DataState::getAllRepositories();
auto enabled = [REPOS](const std::string& plugin) -> bool { auto enabled = [REPOS](const std::string& plugin) -> bool {
for (auto& r : REPOS) { for (auto const& r : REPOS) {
for (auto& p : r.plugins) { for (auto const& p : r.plugins) {
if (p.name == plugin && p.enabled) if (p.name == plugin && p.enabled)
return true; return true;
} }
@@ -805,8 +805,8 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
}; };
auto repoForName = [REPOS](const std::string& name) -> std::string { auto repoForName = [REPOS](const std::string& name) -> std::string {
for (auto& r : REPOS) { for (auto const& r : REPOS) {
for (auto& p : r.plugins) { for (auto const& p : r.plugins) {
if (p.name == name) if (p.name == name)
return r.name; return r.name;
} }
@@ -816,7 +816,7 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
}; };
// unload disabled plugins // unload disabled plugins
for (auto& p : loadedPlugins) { for (auto const& p : loadedPlugins) {
if (!enabled(p)) { if (!enabled(p)) {
// unload // unload
loadUnloadPlugin(HYPRPMPATH + repoForName(p) + "/" + p + ".so", false); loadUnloadPlugin(HYPRPMPATH + repoForName(p) + "/" + p + ".so", false);
@@ -825,8 +825,8 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
} }
// load enabled plugins // load enabled plugins
for (auto& r : REPOS) { for (auto const& r : REPOS) {
for (auto& p : r.plugins) { for (auto const& p : r.plugins) {
if (!p.enabled) if (!p.enabled)
continue; continue;
@@ -855,10 +855,10 @@ bool CPluginManager::loadUnloadPlugin(const std::string& path, bool load) {
void CPluginManager::listAllPlugins() { void CPluginManager::listAllPlugins() {
const auto REPOS = DataState::getAllRepositories(); const auto REPOS = DataState::getAllRepositories();
for (auto& r : REPOS) { for (auto const& r : REPOS) {
std::cout << std::string{Colors::RESET} + " → Repository " + r.name + ":\n"; std::cout << std::string{Colors::RESET} + " → Repository " + r.name + ":\n";
for (auto& p : r.plugins) { for (auto const& p : r.plugins) {
std::cout << std::string{Colors::RESET} + " │ Plugin " + p.name; std::cout << std::string{Colors::RESET} + " │ Plugin " + p.name;
@@ -904,9 +904,9 @@ std::string CPluginManager::headerErrorShort(const eHeadersErrors err) {
} }
bool CPluginManager::hasDeps() { bool CPluginManager::hasDeps() {
std::vector<std::string> deps = {"meson", "cpio", "cmake"}; std::vector<std::string> deps = {"meson", "cpio", "cmake", "pkg-config"};
for (auto& d : deps) { for (auto const& d : deps) {
if (!execAndGet("which " + d + " 2>&1").contains("/")) if (!execAndGet("command -v " + d).contains("/"))
return false; return false;
} }

View File

@@ -1,15 +1,31 @@
globber = run_command('sh', '-c', 'find . -name "*.cpp" | sort', check: true) globber = run_command('sh', '-c', 'find . -name "*.cpp" | sort', check: true)
src = globber.stdout().strip().split('\n') src = globber.stdout().strip().split('\n')
executable('hyprpm', src, executable(
'hyprpm',
src,
dependencies: [ dependencies: [
dependency('hyprutils', version: '>= 0.1.1'), dependency('hyprutils', version: '>= 0.1.1'),
dependency('threads'), dependency('threads'),
dependency('tomlplusplus') dependency('tomlplusplus'),
], ],
install : true install: true,
) )
install_data('../hyprpm.bash', install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), install_tag: 'runtime', rename: 'hyprpm') install_data(
install_data('../hyprpm.fish', install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), install_tag: 'runtime') '../hyprpm.bash',
install_data('../hyprpm.zsh', install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), install_tag: 'runtime', rename: '_hyprpm') install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'),
install_tag: 'runtime',
rename: 'hyprpm',
)
install_data(
'../hyprpm.fish',
install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'),
install_tag: 'runtime',
)
install_data(
'../hyprpm.zsh',
install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'),
install_tag: 'runtime',
rename: '_hyprpm',
)

View File

@@ -1,13 +1,17 @@
project('Hyprland', 'cpp', 'c', project(
version : run_command('cat', join_paths(meson.source_root(), 'VERSION'), check: true).stdout().strip(), 'Hyprland',
default_options : [ 'cpp',
'c',
version: run_command('cat', join_paths(meson.project_source_root(), 'VERSION'), check: true).stdout().strip(),
default_options: [
'warning_level=2', 'warning_level=2',
'default_library=static', 'default_library=static',
'optimization=3', 'optimization=3',
'buildtype=release', 'buildtype=release',
'debug=false', 'debug=false',
'cpp_std=c++23', 'cpp_std=c++26',
]) ],
)
datarootdir = '-DDATAROOTDIR="' + get_option('prefix') / get_option('datadir') + '"' datarootdir = '-DDATAROOTDIR="' + get_option('prefix') / get_option('datadir') + '"'
add_project_arguments( add_project_arguments(
@@ -16,16 +20,19 @@ add_project_arguments(
'-Wno-unused-value', '-Wno-unused-value',
'-Wno-missing-field-initializers', '-Wno-missing-field-initializers',
'-Wno-narrowing', '-Wno-narrowing',
'-Wno-pointer-arith', '-Wno-pointer-arith', datarootdir,
datarootdir,
], ],
language: 'cpp') language: 'cpp',
)
cpp_compiler = meson.get_compiler('cpp') cpp_compiler = meson.get_compiler('cpp')
if cpp_compiler.check_header('execinfo.h') if cpp_compiler.check_header('execinfo.h')
add_project_arguments('-DHAS_EXECINFO', language: 'cpp') add_project_arguments('-DHAS_EXECINFO', language: 'cpp')
endif endif
aquamarine = dependency('aquamarine')
add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp')
xcb_dep = dependency('xcb', required: get_option('xwayland')) xcb_dep = dependency('xcb', required: get_option('xwayland'))
xcb_composite_dep = dependency('xcb-composite', required: get_option('xwayland')) xcb_composite_dep = dependency('xcb-composite', required: get_option('xwayland'))
xcb_errors_dep = dependency('xcb-errors', required: get_option('xwayland')) xcb_errors_dep = dependency('xcb-errors', required: get_option('xwayland'))
@@ -34,6 +41,8 @@ xcb_render_dep = dependency('xcb-render', required: get_option('xwayland'))
xcb_res_dep = dependency('xcb-res', required: get_option('xwayland')) xcb_res_dep = dependency('xcb-res', required: get_option('xwayland'))
xcb_xfixes_dep = dependency('xcb-xfixes', required: get_option('xwayland')) xcb_xfixes_dep = dependency('xcb-xfixes', required: get_option('xwayland'))
gio_dep = dependency('gio-2.0', required: true)
cmake = import('cmake') cmake = import('cmake')
udis = cmake.subproject('udis86') udis = cmake.subproject('udis86')
udis86 = udis.dependency('libudis86') udis86 = udis.dependency('libudis86')
@@ -45,6 +54,7 @@ endif
backtrace_dep = cpp_compiler.find_library('execinfo', required: false) backtrace_dep = cpp_compiler.find_library('execinfo', required: false)
epoll_dep = dependency('epoll-shim', required: false) # timerfd on BSDs epoll_dep = dependency('epoll-shim', required: false) # timerfd on BSDs
# Handle options
if get_option('systemd').enabled() if get_option('systemd').enabled()
add_project_arguments('-DUSES_SYSTEMD', language: 'cpp') add_project_arguments('-DUSES_SYSTEMD', language: 'cpp')
endif endif
@@ -57,8 +67,10 @@ if get_option('buildtype') == 'debug'
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp') add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
endif endif
version_h = run_command('sh', '-c', 'scripts/generateVersion.sh', check: true) # Generate hyprland version and populate version.h
run_command('sh', '-c', 'scripts/generateVersion.sh', check: true)
# Install headers
globber = run_command('find', 'src', '-name', '*.h*', check: true) globber = run_command('find', 'src', '-name', '*.h*', check: true)
headers = globber.stdout().strip().split('\n') headers = globber.stdout().strip().split('\n')
foreach file : headers foreach file : headers
@@ -73,6 +85,7 @@ subdir('assets')
subdir('example') subdir('example')
subdir('docs') subdir('docs')
# Generate hyprland.pc
pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig') pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig')
import('pkgconfig').generate( import('pkgconfig').generate(

10
nix/cmake-version.patch Normal file
View File

@@ -0,0 +1,10 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6fdf98db..d8424d91 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.30)
+cmake_minimum_required(VERSION 3.27)
# Get version
file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW)

View File

@@ -1,41 +1,30 @@
{ {
lib, lib,
stdenv, stdenv,
stdenvAdapters,
pkg-config, pkg-config,
pkgconf, pkgconf,
makeWrapper, makeWrapper,
cmake, cmake,
ninja,
aquamarine, aquamarine,
binutils, binutils,
cairo, cairo,
expat,
fribidi,
git, git,
hwdata,
hyprcursor, hyprcursor,
hyprlang, hyprlang,
hyprutils, hyprutils,
hyprwayland-scanner, hyprwayland-scanner,
jq, jq,
libGL, libGL,
libdatrie,
libdisplay-info,
libdrm, libdrm,
libexecinfo, libexecinfo,
libinput, libinput,
libliftoff,
libselinux,
libsepol,
libthai,
libuuid,
libxkbcommon, libxkbcommon,
libuuid,
mesa, mesa,
pango, pango,
pciutils, pciutils,
pcre2,
python3, python3,
seatd,
systemd, systemd,
tomlplusplus, tomlplusplus,
wayland, wayland,
@@ -50,134 +39,148 @@
wrapRuntimeDeps ? true, wrapRuntimeDeps ? true,
version ? "git", version ? "git",
commit, commit,
revCount,
date, date,
# deprecated flags # deprecated flags
enableNvidiaPatches ? false, enableNvidiaPatches ? false,
nvidiaPatches ? false, nvidiaPatches ? false,
hidpiXWayland ? false, hidpiXWayland ? false,
}: }: let
assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed."; inherit (builtins) baseNameOf foldl';
assert lib.assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed."; inherit (lib.asserts) assertMsg;
assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland"; inherit (lib.attrsets) mapAttrsToList;
stdenv.mkDerivation { inherit (lib.lists) flatten concatLists optional optionals;
pname = "hyprland${lib.optionalString debug "-debug"}"; inherit (lib.sources) cleanSourceWith cleanSource;
inherit version; inherit (lib.strings) cmakeBool hasSuffix makeBinPath optionalString;
src = lib.cleanSourceWith { adapters = flatten [
filter = name: type: let stdenvAdapters.useMoldLinker
baseName = baseNameOf (toString name); ];
in
! (lib.hasSuffix ".nix" baseName);
src = lib.cleanSource ../.;
};
postPatch = '' customStdenv = foldl' (acc: adapter: adapter acc) stdenv adapters;
# Fix hardcoded paths to /usr installation in
sed -i "s#/usr#$out#" src/render/OpenGL.cpp assert assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed.";
assert assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed.";
assert assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland";
customStdenv.mkDerivation {
pname = "hyprland${optionalString debug "-debug"}";
inherit version;
# Remove extra @PREFIX@ to fix pkg-config paths src = cleanSourceWith {
sed -i "s#@PREFIX@/##g" hyprland.pc.in filter = name: type: let
''; baseName = baseNameOf (toString name);
in
! (hasSuffix ".nix" baseName);
src = cleanSource ../.;
};
COMMITS = commit; patches = [
DATE = date; # forces GCC to use -std=c++26
DIRTY = lib.optionalString (commit == "") "dirty"; ./stdcxx.patch
HASH = commit;
nativeBuildInputs = [ # Nix does not have CMake 3.30 yet, so override the minimum version
hyprwayland-scanner ./cmake-version.patch
jq ];
makeWrapper
cmake
ninja
pkg-config
python3 # for udis86
wayland-scanner
];
outputs = [ postPatch = ''
"out" # Fix hardcoded paths to /usr installation
"man" sed -i "s#/usr#$out#" src/render/OpenGL.cpp
"dev"
];
buildInputs = lib.concatLists [ # Remove extra @PREFIX@ to fix pkg-config paths
[ sed -i "s#@PREFIX@/##g" hyprland.pc.in
aquamarine '';
cairo
expat
fribidi
git
hwdata
hyprcursor
hyprlang
hyprutils
libdatrie
libdisplay-info
libdrm
libGL
libinput
libliftoff
libselinux
libsepol
libthai
libuuid
libxkbcommon
mesa
pango
pciutils
pcre2
seatd
tomlplusplus
wayland
wayland-protocols
]
(lib.optionals stdenv.hostPlatform.isMusl [libexecinfo])
(lib.optionals enableXWayland [
xorg.libxcb
xorg.libXcursor
xorg.libXdmcp
xorg.xcbutil
xorg.xcbutilerrors
xorg.xcbutilrenderutil
xorg.xcbutilwm
xwayland
])
(lib.optionals withSystemd [systemd])
];
cmakeBuildType = COMMITS = revCount;
if debug DATE = date;
then "Debug" DIRTY = optionalString (commit == "") "dirty";
else "RelWithDebInfo"; HASH = commit;
# we want as much debug info as possible depsBuildBuild = [
dontStrip = debug; pkg-config
];
cmakeFlags = [ nativeBuildInputs = [
(lib.cmakeBool "NO_XWAYLAND" (!enableXWayland)) hyprwayland-scanner
(lib.cmakeBool "LEGACY_RENDERER" legacyRenderer) jq
(lib.cmakeBool "NO_SYSTEMD" (!withSystemd)) makeWrapper
]; cmake
pkg-config
python3 # for udis86
wayland-scanner
];
postInstall = '' outputs = [
${lib.optionalString wrapRuntimeDeps '' "out"
wrapProgram $out/bin/Hyprland \ "man"
--suffix PATH : ${lib.makeBinPath [ "dev"
binutils ];
buildInputs = concatLists [
[
aquamarine
cairo
git
hyprcursor
hyprlang
hyprutils
libdrm
libGL
libinput
libuuid
libxkbcommon
mesa
pango
pciutils pciutils
pkgconf tomlplusplus
]} wayland
''} wayland-protocols
''; xorg.libXcursor
]
(optionals customStdenv.hostPlatform.isMusl [libexecinfo])
(optionals enableXWayland [
xorg.libxcb
xorg.libXdmcp
xorg.xcbutilerrors
xorg.xcbutilrenderutil
xorg.xcbutilwm
xwayland
])
(optional withSystemd systemd)
];
passthru.providedSessions = ["hyprland"]; cmakeBuildType =
if debug
then "Debug"
else "RelWithDebInfo";
meta = { # we want as much debug info as possible
homepage = "https://github.com/hyprwm/Hyprland"; dontStrip = debug;
description = "Dynamic tiling Wayland compositor that doesn't sacrifice on its looks";
license = lib.licenses.bsd3; cmakeFlags = mapAttrsToList cmakeBool {
platforms = lib.platforms.linux; "NO_XWAYLAND" = !enableXWayland;
mainProgram = "Hyprland"; "LEGACY_RENDERER" = legacyRenderer;
}; "NO_SYSTEMD" = !withSystemd;
} "CMAKE_DISABLE_PRECOMPILE_HEADERS" = true;
};
postInstall = ''
${optionalString wrapRuntimeDeps ''
wrapProgram $out/bin/Hyprland \
--suffix PATH : ${makeBinPath [
binutils
pciutils
pkgconf
]}
''}
'';
passthru.providedSessions = ["hyprland"];
meta = {
homepage = "https://github.com/hyprwm/Hyprland";
description = "Dynamic tiling Wayland compositor that doesn't sacrifice on its looks";
license = lib.licenses.bsd3;
platforms = lib.platforms.linux;
mainProgram = "Hyprland";
};
}

View File

@@ -31,9 +31,10 @@ in {
date = mkDate (self.lastModifiedDate or "19700101"); date = mkDate (self.lastModifiedDate or "19700101");
in { in {
hyprland = final.callPackage ./default.nix { hyprland = final.callPackage ./default.nix {
stdenv = final.gcc13Stdenv; stdenv = final.gcc14Stdenv;
version = "${version}+date=${date}_${self.shortRev or "dirty"}"; version = "${version}+date=${date}_${self.shortRev or "dirty"}";
commit = self.rev or ""; commit = self.rev or "";
revCount = self.sourceInfo.revCount or "";
inherit date; inherit date;
}; };
hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;}; hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;};

12
nix/stdcxx.patch Normal file
View File

@@ -0,0 +1,12 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cfbd431f..73e8e0c2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -64,6 +64,7 @@ endif()
include_directories(. "src/" "subprojects/udis86/" "protocols/")
set(CMAKE_CXX_STANDARD 26)
add_compile_options(
+ -std=c++26
-Wall
-Wextra
-Wno-unused-parameter

View File

@@ -1,76 +1,75 @@
wayland_protos = dependency('wayland-protocols', wayland_protos = dependency(
'wayland-protocols',
version: '>=1.32', version: '>=1.32',
fallback: 'wayland-protocols', fallback: 'wayland-protocols',
default_options: ['tests=false'], default_options: ['tests=false'],
) )
hyprland_protos = dependency('hyprland-protocols', hyprland_protos = dependency(
'hyprland-protocols',
version: '>=0.2', version: '>=0.2',
fallback: 'hyprland-protocols', fallback: 'hyprland-protocols',
) )
wl_protocol_dir = wayland_protos.get_variable('pkgdatadir') wayland_protocol_dir = wayland_protos.get_variable('pkgdatadir')
hl_protocol_dir = hyprland_protos.get_variable('pkgdatadir') hyprland_protocol_dir = hyprland_protos.get_variable('pkgdatadir')
hyprwayland_scanner_dep = dependency('hyprwayland-scanner', version: '>=0.3.8', native: true) hyprwayland_scanner_dep = dependency('hyprwayland-scanner', version: '>=0.3.10', native: true)
hyprwayland_scanner = find_program( hyprwayland_scanner = find_program(
hyprwayland_scanner_dep.get_variable('hyprwayland_scanner'), hyprwayland_scanner_dep.get_variable('hyprwayland_scanner'),
native: true, native: true,
) )
new_protocols = [ protocols = [
['wlr-gamma-control-unstable-v1.xml'], 'wlr-gamma-control-unstable-v1.xml',
['wlr-foreign-toplevel-management-unstable-v1.xml'], 'wlr-foreign-toplevel-management-unstable-v1.xml',
['wlr-output-power-management-unstable-v1.xml'], 'wlr-output-power-management-unstable-v1.xml',
['input-method-unstable-v2.xml'], 'input-method-unstable-v2.xml',
['virtual-keyboard-unstable-v1.xml'], 'virtual-keyboard-unstable-v1.xml',
['wlr-virtual-pointer-unstable-v1.xml'], 'wlr-virtual-pointer-unstable-v1.xml',
['wlr-output-management-unstable-v1.xml'], 'wlr-output-management-unstable-v1.xml',
['kde-server-decoration.xml'], 'kde-server-decoration.xml',
['wlr-layer-shell-unstable-v1.xml'], 'wlr-layer-shell-unstable-v1.xml',
['wayland-drm.xml'], 'wayland-drm.xml',
['wlr-data-control-unstable-v1.xml'], 'wlr-data-control-unstable-v1.xml',
['wlr-screencopy-unstable-v1.xml'], 'wlr-screencopy-unstable-v1.xml',
[hl_protocol_dir, 'protocols/hyprland-global-shortcuts-v1.xml'], hyprland_protocol_dir / 'protocols/hyprland-global-shortcuts-v1.xml',
[hl_protocol_dir, 'protocols/hyprland-toplevel-export-v1.xml'], hyprland_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml',
[hl_protocol_dir, 'protocols/hyprland-focus-grab-v1.xml'], hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml',
[wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'], wayland_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml',
[wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'], wayland_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml',
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'], wayland_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
[wl_protocol_dir, 'staging/cursor-shape/cursor-shape-v1.xml'], wayland_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
[wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'], wayland_protocol_dir / 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml',
[wl_protocol_dir, 'unstable/relative-pointer/relative-pointer-unstable-v1.xml'], wayland_protocol_dir / 'unstable/relative-pointer/relative-pointer-unstable-v1.xml',
[wl_protocol_dir, 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml'], wayland_protocol_dir / 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml',
[wl_protocol_dir, 'staging/alpha-modifier/alpha-modifier-v1.xml'], wayland_protocol_dir / 'staging/alpha-modifier/alpha-modifier-v1.xml',
[wl_protocol_dir, 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml'], wayland_protocol_dir / 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml',
[wl_protocol_dir, 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml'], wayland_protocol_dir / 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml',
[wl_protocol_dir, 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml'], wayland_protocol_dir / 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml',
[wl_protocol_dir, 'unstable/text-input/text-input-unstable-v3.xml'], wayland_protocol_dir / 'unstable/text-input/text-input-unstable-v3.xml',
[wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'], wayland_protocol_dir / 'unstable/text-input/text-input-unstable-v1.xml',
[wl_protocol_dir, 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'], wayland_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml',
[wl_protocol_dir, 'staging/xdg-activation/xdg-activation-v1.xml'], wayland_protocol_dir / 'staging/xdg-activation/xdg-activation-v1.xml',
[wl_protocol_dir, 'staging/ext-idle-notify/ext-idle-notify-v1.xml'], wayland_protocol_dir / 'staging/ext-idle-notify/ext-idle-notify-v1.xml',
[wl_protocol_dir, 'staging/ext-session-lock/ext-session-lock-v1.xml'], wayland_protocol_dir / 'staging/ext-session-lock/ext-session-lock-v1.xml',
[wl_protocol_dir, 'stable/tablet/tablet-v2.xml'], wayland_protocol_dir / 'stable/tablet/tablet-v2.xml',
[wl_protocol_dir, 'stable/presentation-time/presentation-time.xml'], wayland_protocol_dir / 'stable/presentation-time/presentation-time.xml',
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], wayland_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
[wl_protocol_dir, 'unstable/primary-selection/primary-selection-unstable-v1.xml'], wayland_protocol_dir / 'unstable/primary-selection/primary-selection-unstable-v1.xml',
[wl_protocol_dir, 'staging/xwayland-shell/xwayland-shell-v1.xml'], wayland_protocol_dir / 'staging/xwayland-shell/xwayland-shell-v1.xml',
[wl_protocol_dir, 'stable/viewporter/viewporter.xml'], wayland_protocol_dir / 'stable/viewporter/viewporter.xml',
[wl_protocol_dir, 'stable/linux-dmabuf/linux-dmabuf-v1.xml'], wayland_protocol_dir / 'stable/linux-dmabuf/linux-dmabuf-v1.xml',
[wl_protocol_dir, 'staging/drm-lease/drm-lease-v1.xml'], wayland_protocol_dir / 'staging/drm-lease/drm-lease-v1.xml',
[wl_protocol_dir, 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml'], wayland_protocol_dir / 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml',
wayland_protocol_dir / 'staging/xdg-dialog/xdg-dialog-v1.xml',
] ]
wl_protos_src = [] wl_protocols = []
wl_protos_headers = [] foreach protocol : protocols
wl_protocols += custom_target(
new_wl_protos = [] protocol.underscorify(),
foreach p : new_protocols input: protocol,
xml = join_paths(p)
new_wl_protos += custom_target(
xml.underscorify(),
input: xml,
install: true, install: true,
install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')], install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')],
output: ['@BASENAME@.cpp', '@BASENAME@.hpp'], output: ['@BASENAME@.cpp', '@BASENAME@.hpp'],
@@ -78,31 +77,26 @@ foreach p : new_protocols
) )
endforeach endforeach
wayland_server_dep = dependency('wayland-server', version: '>=1.20.0') # wayland.xml generation
wayland_server_dir = wayland_server_dep.get_variable('pkgdatadir') wayland_scanner = dependency('wayland-scanner')
wayland_scanner_datadir = wayland_scanner.get_variable('pkgdatadir')
wl_server_protos = [ wayland_xml = wayland_scanner_datadir / 'wayland.xml'
wayland_server_dir / 'wayland.xml' wayland_protocol = custom_target(
] wayland_xml.underscorify(),
wl_server_protos_gen = [] input: wayland_xml,
foreach p : wl_server_protos install: true,
wl_server_protos_gen += custom_target( install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')],
p.underscorify(), output: ['@BASENAME@.cpp', '@BASENAME@.hpp'],
input: p, command: [hyprwayland_scanner, '--wayland-enums', '@INPUT@', '@OUTDIR@'],
install: true, )
install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')],
output: ['@BASENAME@.cpp', '@BASENAME@.hpp'],
command: [hyprwayland_scanner, '--wayland-enums', '@INPUT@', '@OUTDIR@'],
)
endforeach
lib_server_protos = static_library( lib_server_protos = static_library(
'server_protos', 'server_protos',
wl_protos_src + wl_protos_headers + new_wl_protos + wl_server_protos_gen, wl_protocols + wayland_protocol,
dependencies: wayland_server_dep.partial_dependency(compile_args: true),
) )
server_protos = declare_dependency( server_protos = declare_dependency(
link_with: lib_server_protos, link_with: lib_server_protos,
sources: wl_protos_headers + new_wl_protos, sources: wl_protocols + wayland_protocol,
) )

View File

@@ -1,13 +1,13 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt
index f54cdf5d..ad7c3e73 100755 index f26a5c3c..3dfef333 100644
--- a/CMakeLists.txt --- a/CMakeLists.txt
+++ b/CMakeLists.txt +++ b/CMakeLists.txt
@@ -130,6 +130,8 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) @@ -143,6 +143,8 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "Enabling ASan") message(STATUS "Enabling ASan")
target_link_libraries(Hyprland asan) target_link_libraries(Hyprland asan)
+ pkg_check_modules(ffidep REQUIRED IMPORTED_TARGET libffi) + pkg_check_modules(ffidep REQUIRED IMPORTED_TARGET libffi)
+ target_link_libraries(Hyprland ${CMAKE_SOURCE_DIR}/libwayland-server.a PkgConfig::ffidep) + target_link_libraries(Hyprland ${CMAKE_SOURCE_DIR}/libwayland-server.a PkgConfig::ffidep)
target_compile_options(Hyprland PUBLIC -fsanitize=address) target_compile_options(Hyprland PUBLIC -fsanitize=address)
endif() endif()

View File

@@ -305,12 +305,16 @@ void CCompositor::initServer(std::string socketName, int socketFd) {
setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket.c_str(), 1); setenv("WAYLAND_DISPLAY", m_szWLDisplaySocket.c_str(), 1);
setenv("XDG_SESSION_TYPE", "wayland", 1); setenv("XDG_SESSION_TYPE", "wayland", 1);
if (!getenv("XDG_CURRENT_DESKTOP")) {
setenv("XDG_CURRENT_DESKTOP", "Hyprland", 1);
m_bDesktopEnvSet = true;
}
initManagers(STAGE_BASICINIT); initManagers(STAGE_BASICINIT);
initManagers(STAGE_LATE); initManagers(STAGE_LATE);
for (auto& o : pendingOutputs) { for (auto const& o : pendingOutputs) {
onNewMonitor(o); onNewMonitor(o);
} }
pendingOutputs.clear(); pendingOutputs.clear();
@@ -387,18 +391,19 @@ void CCompositor::initAllSignals() {
m_bSessionActive = true; m_bSessionActive = true;
for (auto& m : m_vMonitors) { for (auto const& m : m_vMonitors) {
scheduleFrameForMonitor(m.get()); scheduleFrameForMonitor(m.get());
g_pHyprRenderer->applyMonitorRule(m.get(), &m->activeMonitorRule, true); g_pHyprRenderer->applyMonitorRule(m.get(), &m->activeMonitorRule, true);
} }
g_pConfigManager->m_bWantsMonitorReload = true; g_pConfigManager->m_bWantsMonitorReload = true;
g_pCursorManager->syncGsettings();
} else { } else {
Debug::log(LOG, "Session got deactivated!"); Debug::log(LOG, "Session got deactivated!");
m_bSessionActive = false; m_bSessionActive = false;
for (auto& m : m_vMonitors) { for (auto const& m : m_vMonitors) {
m->noFrameSchedule = true; m->noFrameSchedule = true;
m->framesToSkip = 1; m->framesToSkip = 1;
} }
@@ -421,9 +426,10 @@ void CCompositor::cleanEnvironment() {
// in main // in main
unsetenv("HYPRLAND_CMD"); unsetenv("HYPRLAND_CMD");
unsetenv("XDG_BACKEND"); unsetenv("XDG_BACKEND");
unsetenv("XDG_CURRENT_DESKTOP"); if (m_bDesktopEnvSet)
unsetenv("XDG_CURRENT_DESKTOP");
if (m_pAqBackend->hasSession()) { if (m_pAqBackend->hasSession() && !envEnabled("HYPRLAND_NO_SD_VARS")) {
const auto CMD = const auto CMD =
#ifdef USES_SYSTEMD #ifdef USES_SYSTEMD
"systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash " "systemctl --user unset-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash "
@@ -471,7 +477,7 @@ void CCompositor::cleanup() {
m_vWorkspaces.clear(); m_vWorkspaces.clear();
m_vWindows.clear(); m_vWindows.clear();
for (auto& m : m_vMonitors) { for (auto const& m : m_vMonitors) {
g_pHyprOpenGL->destroyMonitorResources(m.get()); g_pHyprOpenGL->destroyMonitorResources(m.get());
m->output->state->setEnabled(false); m->output->state->setEnabled(false);
@@ -552,6 +558,10 @@ void CCompositor::initManagers(eManagersInitStage stage) {
g_pConfigManager->init(); g_pConfigManager->init();
g_pWatchdog = std::make_unique<CWatchdog>(); // requires config g_pWatchdog = std::make_unique<CWatchdog>(); // requires config
// wait for watchdog to initialize to not hit data races in reading config values.
while (!g_pWatchdog->m_bWatchdogInitialized) {
std::this_thread::yield();
}
Debug::log(LOG, "Creating the PointerManager!"); Debug::log(LOG, "Creating the PointerManager!");
g_pPointerManager = std::make_unique<CPointerManager>(); g_pPointerManager = std::make_unique<CPointerManager>();
@@ -605,7 +615,7 @@ void CCompositor::initManagers(eManagersInitStage stage) {
g_pCursorManager = std::make_unique<CCursorManager>(); g_pCursorManager = std::make_unique<CCursorManager>();
Debug::log(LOG, "Starting XWayland"); Debug::log(LOG, "Starting XWayland");
g_pXWayland = std::make_unique<CXWayland>(); g_pXWayland = std::make_unique<CXWayland>(g_pCompositor->m_bEnableXwayland);
} break; } break;
default: UNREACHABLE(); default: UNREACHABLE();
} }
@@ -631,7 +641,7 @@ void CCompositor::removeLockFile() {
void CCompositor::prepareFallbackOutput() { void CCompositor::prepareFallbackOutput() {
// create a backup monitor // create a backup monitor
SP<Aquamarine::IBackendImplementation> headless; SP<Aquamarine::IBackendImplementation> headless;
for (auto& impl : m_pAqBackend->getImplementations()) { for (auto const& impl : m_pAqBackend->getImplementations()) {
if (impl->type() == Aquamarine::AQ_BACKEND_HEADLESS) { if (impl->type() == Aquamarine::AQ_BACKEND_HEADLESS) {
headless = impl; headless = impl;
break; break;
@@ -649,7 +659,11 @@ void CCompositor::prepareFallbackOutput() {
void CCompositor::startCompositor() { void CCompositor::startCompositor() {
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
if (m_pAqBackend->hasSession() /* Session-less Hyprland usually means a nest, don't update the env in that case */) { if (
/* Session-less Hyprland usually means a nest, don't update the env in that case */
m_pAqBackend->hasSession() &&
/* Activation environment management is not disabled */
!envEnabled("HYPRLAND_NO_SD_VARS")) {
const auto CMD = const auto CMD =
#ifdef USES_SYSTEMD #ifdef USES_SYSTEMD
"systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash " "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME PATH XDG_DATA_DIRS && hash "
@@ -683,9 +697,9 @@ void CCompositor::startCompositor() {
g_pEventLoopManager->enterLoop(); g_pEventLoopManager->enterLoop();
} }
CMonitor* CCompositor::getMonitorFromID(const int& id) { CMonitor* CCompositor::getMonitorFromID(const MONITORID& id) {
for (auto& m : m_vMonitors) { for (auto const& m : m_vMonitors) {
if (m->ID == (uint64_t)id) { if (m->ID == id) {
return m.get(); return m.get();
} }
} }
@@ -694,7 +708,7 @@ CMonitor* CCompositor::getMonitorFromID(const int& id) {
} }
CMonitor* CCompositor::getMonitorFromName(const std::string& name) { CMonitor* CCompositor::getMonitorFromName(const std::string& name) {
for (auto& m : m_vMonitors) { for (auto const& m : m_vMonitors) {
if (m->szName == name) { if (m->szName == name) {
return m.get(); return m.get();
} }
@@ -703,7 +717,7 @@ CMonitor* CCompositor::getMonitorFromName(const std::string& name) {
} }
CMonitor* CCompositor::getMonitorFromDesc(const std::string& desc) { CMonitor* CCompositor::getMonitorFromDesc(const std::string& desc) {
for (auto& m : m_vMonitors) { for (auto const& m : m_vMonitors) {
if (m->szDescription.starts_with(desc)) if (m->szDescription.starts_with(desc))
return m.get(); return m.get();
} }
@@ -716,7 +730,7 @@ CMonitor* CCompositor::getMonitorFromCursor() {
CMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) { CMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) {
SP<CMonitor> mon; SP<CMonitor> mon;
for (auto& m : m_vMonitors) { for (auto const& m : m_vMonitors) {
if (CBox{m->vecPosition, m->vecSize}.containsPoint(point)) { if (CBox{m->vecPosition, m->vecSize}.containsPoint(point)) {
mon = m; mon = m;
break; break;
@@ -727,7 +741,7 @@ CMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) {
float bestDistance = 0.f; float bestDistance = 0.f;
SP<CMonitor> pBestMon; SP<CMonitor> pBestMon;
for (auto& m : m_vMonitors) { for (auto const& m : m_vMonitors) {
float dist = vecToRectDistanceSquared(point, m->vecPosition, m->vecPosition + m->vecSize); float dist = vecToRectDistanceSquared(point, m->vecPosition, m->vecPosition + m->vecSize);
if (dist < bestDistance || !pBestMon) { if (dist < bestDistance || !pBestMon) {
@@ -757,7 +771,7 @@ void CCompositor::removeWindowFromVectorSafe(PHLWINDOW pWindow) {
} }
bool CCompositor::monitorExists(CMonitor* pMonitor) { bool CCompositor::monitorExists(CMonitor* pMonitor) {
for (auto& m : m_vRealMonitors) { for (auto const& m : m_vRealMonitors) {
if (m.get() == pMonitor) if (m.get() == pMonitor)
return true; return true;
} }
@@ -775,9 +789,9 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
// pinned windows on top of floating regardless // pinned windows on top of floating regardless
if (properties & ALLOW_FLOATING) { if (properties & ALLOW_FLOATING) {
for (auto& w : m_vWindows | std::views::reverse) { for (auto const& w : m_vWindows | std::views::reverse) {
const auto BB = w->getWindowBoxUnified(properties); const auto BB = w->getWindowBoxUnified(properties);
CBox box = BB.copy().expand(w->m_iX11Type != 2 ? BORDER_GRAB_AREA : 0); CBox box = BB.copy().expand(!w->isX11OverrideRedirect() ? BORDER_GRAB_AREA : 0);
if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() && if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() &&
w != pIgnoreWindow) { w != pIgnoreWindow) {
if (box.containsPoint(g_pPointerManager->position())) if (box.containsPoint(g_pPointerManager->position()))
@@ -793,7 +807,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
auto windowForWorkspace = [&](bool special) -> PHLWINDOW { auto windowForWorkspace = [&](bool special) -> PHLWINDOW {
auto floating = [&](bool aboveFullscreen) -> PHLWINDOW { auto floating = [&](bool aboveFullscreen) -> PHLWINDOW {
for (auto& w : m_vWindows | std::views::reverse) { for (auto const& w : m_vWindows | std::views::reverse) {
if (special && !w->onSpecialWorkspace()) // because special floating may creep up into regular if (special && !w->onSpecialWorkspace()) // because special floating may creep up into regular
continue; continue;
@@ -807,16 +821,16 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
BB.x + BB.width <= PWINDOWMONITOR->vecPosition.x + PWINDOWMONITOR->vecSize.x && BB.y + BB.height <= PWINDOWMONITOR->vecPosition.y + PWINDOWMONITOR->vecSize.y) BB.x + BB.width <= PWINDOWMONITOR->vecPosition.x + PWINDOWMONITOR->vecSize.x && BB.y + BB.height <= PWINDOWMONITOR->vecPosition.y + PWINDOWMONITOR->vecSize.y)
continue; continue;
CBox box = BB.copy().expand(w->m_iX11Type != 2 ? BORDER_GRAB_AREA : 0); CBox box = BB.copy().expand(!w->isX11OverrideRedirect() ? BORDER_GRAB_AREA : 0);
if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_pWorkspace) && !w->isHidden() && !w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() && if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_pWorkspace) && !w->isHidden() && !w->m_bPinned && !w->m_sWindowData.noFocus.valueOrDefault() &&
w != pIgnoreWindow && (!aboveFullscreen || w->m_bCreatedOverFullscreen)) { w != pIgnoreWindow && (!aboveFullscreen || w->m_bCreatedOverFullscreen)) {
// OR windows should add focus to parent // OR windows should add focus to parent
if (w->m_bX11ShouldntFocus && w->m_iX11Type != 2) if (w->m_bX11ShouldntFocus && !w->isX11OverrideRedirect())
continue; continue;
if (box.containsPoint(g_pPointerManager->position())) { if (box.containsPoint(g_pPointerManager->position())) {
if (w->m_bIsX11 && w->m_iX11Type == 2 && !w->m_pXWaylandSurface->wantsFocus()) { if (w->m_bIsX11 && w->isX11OverrideRedirect() && !w->m_pXWaylandSurface->wantsFocus()) {
// Override Redirect // Override Redirect
return g_pCompositor->m_pLastWindow.lock(); // we kinda trick everything here. return g_pCompositor->m_pLastWindow.lock(); // 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. // TODO: this is wrong, we should focus the parent, but idk how to get it considering it's nullptr in most cases.
@@ -845,8 +859,8 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
if (properties & FLOATING_ONLY) if (properties & FLOATING_ONLY)
return floating(false); return floating(false);
const int64_t WORKSPACEID = special ? PMONITOR->activeSpecialWorkspaceID() : PMONITOR->activeWorkspaceID(); const WORKSPACEID WSPID = special ? PMONITOR->activeSpecialWorkspaceID() : PMONITOR->activeWorkspaceID();
const auto PWORKSPACE = getWorkspaceByID(WORKSPACEID); const auto PWORKSPACE = getWorkspaceByID(WSPID);
if (PWORKSPACE->m_bHasFullscreenWindow) if (PWORKSPACE->m_bHasFullscreenWindow)
return getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); return getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
@@ -856,23 +870,23 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
return found; return found;
// for windows, we need to check their extensions too, first. // for windows, we need to check their extensions too, first.
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (special != w->onSpecialWorkspace()) if (special != w->onSpecialWorkspace())
continue; continue;
if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->workspaceID() == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->workspaceID() == WSPID && !w->isHidden() && !w->m_bX11ShouldntFocus &&
!w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) { !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) {
if (w->hasPopupAt(pos)) if (w->hasPopupAt(pos))
return w; return w;
} }
} }
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (special != w->onSpecialWorkspace()) if (special != w->onSpecialWorkspace())
continue; continue;
CBox box = (properties & USE_PROP_TILED) ? w->getWindowBoxUnified(properties) : CBox{w->m_vPosition, w->m_vSize}; CBox box = (properties & USE_PROP_TILED) ? w->getWindowBoxUnified(properties) : CBox{w->m_vPosition, w->m_vSize};
if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->workspaceID() == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->workspaceID() == WSPID && !w->isHidden() && !w->m_bX11ShouldntFocus &&
!w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow) !w->m_sWindowData.noFocus.valueOrDefault() && w != pIgnoreWindow)
return w; return w;
} }
@@ -949,7 +963,7 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindo
} }
CMonitor* CCompositor::getMonitorFromOutput(SP<Aquamarine::IOutput> out) { CMonitor* CCompositor::getMonitorFromOutput(SP<Aquamarine::IOutput> out) {
for (auto& m : m_vMonitors) { for (auto const& m : m_vMonitors) {
if (m->output == out) { if (m->output == out) {
return m.get(); return m.get();
} }
@@ -959,7 +973,7 @@ CMonitor* CCompositor::getMonitorFromOutput(SP<Aquamarine::IOutput> out) {
} }
CMonitor* CCompositor::getRealMonitorFromOutput(SP<Aquamarine::IOutput> out) { CMonitor* CCompositor::getRealMonitorFromOutput(SP<Aquamarine::IOutput> out) {
for (auto& m : m_vRealMonitors) { for (auto const& m : m_vRealMonitors) {
if (m->output == out) { if (m->output == out) {
return m.get(); return m.get();
} }
@@ -983,7 +997,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface
return; return;
} }
if (pWindow && pWindow->m_bIsX11 && pWindow->m_iX11Type == 2 && !pWindow->m_pXWaylandSurface->wantsFocus()) if (pWindow && pWindow->m_bIsX11 && pWindow->isX11OverrideRedirect() && !pWindow->m_pXWaylandSurface->wantsFocus())
return; return;
g_pLayoutManager->getCurrentLayout()->bringWindowToTop(pWindow); g_pLayoutManager->getCurrentLayout()->bringWindowToTop(pWindow);
@@ -1057,7 +1071,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface
updateWindowAnimatedDecorationValues(PLASTWINDOW); updateWindowAnimatedDecorationValues(PLASTWINDOW);
if (!pWindow->m_bIsX11 || pWindow->m_iX11Type == 1) if (!pWindow->m_bIsX11 || !pWindow->isX11OverrideRedirect())
g_pXWaylandManager->activateWindow(PLASTWINDOW, false); g_pXWaylandManager->activateWindow(PLASTWINDOW, false);
} }
@@ -1103,7 +1117,7 @@ void CCompositor::focusSurface(SP<CWLSurfaceResource> pSurface, PHLWINDOW pWindo
if (g_pSeatManager->state.keyboardFocus == pSurface || (pWindowOwner && g_pSeatManager->state.keyboardFocus == pWindowOwner->m_pWLSurface->resource())) if (g_pSeatManager->state.keyboardFocus == pSurface || (pWindowOwner && g_pSeatManager->state.keyboardFocus == pWindowOwner->m_pWLSurface->resource()))
return; // Don't focus when already focused on this. return; // Don't focus when already focused on this.
if (g_pSessionLockManager->isSessionLocked() && !g_pSessionLockManager->isSurfaceSessionLock(pSurface)) if (g_pSessionLockManager->isSessionLocked() && pSurface && !g_pSessionLockManager->isSurfaceSessionLock(pSurface))
return; return;
if (g_pSeatManager->seatGrab && !g_pSeatManager->seatGrab->accepts(pSurface)) { if (g_pSeatManager->seatGrab && !g_pSeatManager->seatGrab->accepts(pSurface)) {
@@ -1150,8 +1164,8 @@ void CCompositor::focusSurface(SP<CWLSurfaceResource> pSurface, PHLWINDOW pWindo
} }
SP<CWLSurfaceResource> CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, CMonitor* monitor, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { SP<CWLSurfaceResource> CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, CMonitor* monitor, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) {
for (auto& lsl : monitor->m_aLayerSurfaceLayers | std::views::reverse) { for (auto const& lsl : monitor->m_aLayerSurfaceLayers | std::views::reverse) {
for (auto& ls : lsl | std::views::reverse) { for (auto const& ls : lsl | std::views::reverse) {
if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->mapped) || ls->alpha.value() == 0.f) if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->mapped) || ls->alpha.value() == 0.f)
continue; continue;
@@ -1169,7 +1183,7 @@ SP<CWLSurfaceResource> CCompositor::vectorToLayerPopupSurface(const Vector2D& po
} }
SP<CWLSurfaceResource> CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<PHLLSREF>* layerSurfaces, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { SP<CWLSurfaceResource> CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<PHLLSREF>* layerSurfaces, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) {
for (auto& ls : *layerSurfaces | std::views::reverse) { for (auto const& ls : *layerSurfaces | std::views::reverse) {
if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha.value() == 0.f) if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha.value() == 0.f)
continue; continue;
@@ -1198,7 +1212,7 @@ PHLWINDOW CCompositor::getWindowFromSurface(SP<CWLSurfaceResource> pSurface) {
} }
PHLWINDOW CCompositor::getWindowFromHandle(uint32_t handle) { PHLWINDOW CCompositor::getWindowFromHandle(uint32_t handle) {
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if ((uint32_t)(((uint64_t)w.get()) & 0xFFFFFFFF) == handle) { if ((uint32_t)(((uint64_t)w.get()) & 0xFFFFFFFF) == handle) {
return w; return w;
} }
@@ -1207,8 +1221,8 @@ PHLWINDOW CCompositor::getWindowFromHandle(uint32_t handle) {
return nullptr; return nullptr;
} }
PHLWINDOW CCompositor::getFullscreenWindowOnWorkspace(const int& ID) { PHLWINDOW CCompositor::getFullscreenWindowOnWorkspace(const WORKSPACEID& ID) {
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w->workspaceID() == ID && w->isFullscreen()) if (w->workspaceID() == ID && w->isFullscreen())
return w; return w;
} }
@@ -1231,8 +1245,8 @@ bool CCompositor::isWorkspaceVisibleNotCovered(PHLWORKSPACE w) {
return PMONITOR->activeWorkspace->m_iID == w->m_iID; return PMONITOR->activeWorkspace->m_iID == w->m_iID;
} }
PHLWORKSPACE CCompositor::getWorkspaceByID(const int& id) { PHLWORKSPACE CCompositor::getWorkspaceByID(const WORKSPACEID& id) {
for (auto& w : m_vWorkspaces) { for (auto const& w : m_vWorkspaces) {
if (w->m_iID == id && !w->inert()) if (w->m_iID == id && !w->inert())
return w; return w;
} }
@@ -1255,9 +1269,9 @@ void CCompositor::sanityCheckWorkspaces() {
} }
} }
int CCompositor::getWindowsOnWorkspace(const int& id, std::optional<bool> onlyTiled, std::optional<bool> onlyVisible) { int CCompositor::getWindowsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled, std::optional<bool> onlyVisible) {
int no = 0; int no = 0;
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w->workspaceID() != id || !w->m_bIsMapped) if (w->workspaceID() != id || !w->m_bIsMapped)
continue; continue;
if (onlyTiled.has_value() && w->m_bIsFloating == onlyTiled.value()) if (onlyTiled.has_value() && w->m_bIsFloating == onlyTiled.value())
@@ -1270,9 +1284,9 @@ int CCompositor::getWindowsOnWorkspace(const int& id, std::optional<bool> onlyTi
return no; return no;
} }
int CCompositor::getGroupsOnWorkspace(const int& id, std::optional<bool> onlyTiled, std::optional<bool> onlyVisible) { int CCompositor::getGroupsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled, std::optional<bool> onlyVisible) {
int no = 0; int no = 0;
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w->workspaceID() != id || !w->m_bIsMapped) if (w->workspaceID() != id || !w->m_bIsMapped)
continue; continue;
if (!w->m_sGroupData.head) if (!w->m_sGroupData.head)
@@ -1287,7 +1301,7 @@ int CCompositor::getGroupsOnWorkspace(const int& id, std::optional<bool> onlyTil
} }
PHLWINDOW CCompositor::getUrgentWindow() { PHLWINDOW CCompositor::getUrgentWindow() {
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w->m_bIsMapped && w->m_bIsUrgent) if (w->m_bIsMapped && w->m_bIsUrgent)
return w; return w;
} }
@@ -1295,8 +1309,8 @@ PHLWINDOW CCompositor::getUrgentWindow() {
return nullptr; return nullptr;
} }
bool CCompositor::hasUrgentWindowOnWorkspace(const int& id) { bool CCompositor::hasUrgentWindowOnWorkspace(const WORKSPACEID& id) {
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w->workspaceID() == id && w->m_bIsMapped && w->m_bIsUrgent) if (w->workspaceID() == id && w->m_bIsMapped && w->m_bIsUrgent)
return true; return true;
} }
@@ -1304,8 +1318,8 @@ bool CCompositor::hasUrgentWindowOnWorkspace(const int& id) {
return false; return false;
} }
PHLWINDOW CCompositor::getFirstWindowOnWorkspace(const int& id) { PHLWINDOW CCompositor::getFirstWindowOnWorkspace(const WORKSPACEID& id) {
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w->workspaceID() == id && w->m_bIsMapped && !w->isHidden()) if (w->workspaceID() == id && w->m_bIsMapped && !w->isHidden())
return w; return w;
} }
@@ -1313,7 +1327,7 @@ PHLWINDOW CCompositor::getFirstWindowOnWorkspace(const int& id) {
return nullptr; return nullptr;
} }
PHLWINDOW CCompositor::getTopLeftWindowOnWorkspace(const int& id) { PHLWINDOW CCompositor::getTopLeftWindowOnWorkspace(const WORKSPACEID& id) {
const auto PWORKSPACE = getWorkspaceByID(id); const auto PWORKSPACE = getWorkspaceByID(id);
if (!PWORKSPACE) if (!PWORKSPACE)
@@ -1321,7 +1335,7 @@ PHLWINDOW CCompositor::getTopLeftWindowOnWorkspace(const int& id) {
const auto PMONITOR = getMonitorFromID(PWORKSPACE->m_iMonitorID); const auto PMONITOR = getMonitorFromID(PWORKSPACE->m_iMonitorID);
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w->workspaceID() != id || !w->m_bIsMapped || w->isHidden()) if (w->workspaceID() != id || !w->m_bIsMapped || w->isHidden())
continue; continue;
@@ -1386,7 +1400,7 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) {
else else
toMove.emplace_front(pw); toMove.emplace_front(pw);
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsX11 && w->X11TransientFor() == pw && w != pw && std::find(toMove.begin(), toMove.end(), w) == toMove.end()) { if (w->m_bIsMapped && !w->isHidden() && w->m_bIsX11 && w->X11TransientFor() == pw && w != pw && std::find(toMove.begin(), toMove.end(), w) == toMove.end()) {
x11Stack(w, top, x11Stack); x11Stack(w, top, x11Stack);
} }
@@ -1401,12 +1415,12 @@ void CCompositor::changeWindowZOrder(PHLWINDOW pWindow, bool top) {
} }
} }
void CCompositor::cleanupFadingOut(const int& monid) { void CCompositor::cleanupFadingOut(const MONITORID& monid) {
for (auto& ww : m_vWindowsFadingOut) { for (auto const& ww : m_vWindowsFadingOut) {
auto w = ww.lock(); auto w = ww.lock();
if (w->m_iMonitorID != (long unsigned int)monid) if (w->m_iMonitorID != monid)
continue; continue;
if (!w->m_bFadingOut || w->m_fAlpha.value() == 0.f) { if (!w->m_bFadingOut || w->m_fAlpha.value() == 0.f) {
@@ -1427,7 +1441,7 @@ void CCompositor::cleanupFadingOut(const int& monid) {
bool layersDirty = false; bool layersDirty = false;
for (auto& lsr : m_vSurfacesFadingOut) { for (auto const& lsr : m_vSurfacesFadingOut) {
auto ls = lsr.lock(); auto ls = lsr.lock();
@@ -1444,7 +1458,7 @@ void CCompositor::cleanupFadingOut(const int& monid) {
g_pHyprOpenGL->markBlurDirtyForMonitor(getMonitorFromID(monid)); g_pHyprOpenGL->markBlurDirtyForMonitor(getMonitorFromID(monid));
if (ls->fadingOut && ls->readyToDelete && ls->isFadedOut()) { if (ls->fadingOut && ls->readyToDelete && ls->isFadedOut()) {
for (auto& m : m_vMonitors) { for (auto const& m : m_vMonitors) {
for (auto& lsl : m->m_aLayerSurfaceLayers) { for (auto& lsl : m->m_aLayerSurfaceLayers) {
if (!lsl.empty() && std::find_if(lsl.begin(), lsl.end(), [&](auto& other) { return other == ls; }) != lsl.end()) { if (!lsl.empty() && std::find_if(lsl.begin(), lsl.end(), [&](auto& other) { return other == ls; }) != lsl.end()) {
std::erase_if(lsl, [&](auto& other) { return other == ls || !other; }); std::erase_if(lsl, [&](auto& other) { return other == ls || !other; });
@@ -1516,7 +1530,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
if (!pWindow->m_bIsFloating) { if (!pWindow->m_bIsFloating) {
// for tiled windows, we calc edges // for tiled windows, we calc edges
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace)) if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace))
continue; continue;
@@ -1608,7 +1622,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
float bestAngleAbs = 2.0 * M_PI; float bestAngleAbs = 2.0 * M_PI;
constexpr float THRESHOLD = 0.3 * M_PI; constexpr float THRESHOLD = 0.3 * M_PI;
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && !w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace)) if (w == pWindow || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && !w->m_bIsFloating) || !isWorkspaceVisible(w->m_pWorkspace))
continue; continue;
@@ -1646,7 +1660,7 @@ PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
PHLWINDOW CCompositor::getNextWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional<bool> floating) { PHLWINDOW CCompositor::getNextWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional<bool> floating) {
bool gotToWindow = false; bool gotToWindow = false;
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w != pWindow && !gotToWindow) if (w != pWindow && !gotToWindow)
continue; continue;
@@ -1662,7 +1676,7 @@ PHLWINDOW CCompositor::getNextWindowOnWorkspace(PHLWINDOW pWindow, bool focusabl
return w; return w;
} }
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (floating.has_value() && w->m_bIsFloating != floating.value()) if (floating.has_value() && w->m_bIsFloating != floating.value())
continue; continue;
@@ -1675,7 +1689,7 @@ PHLWINDOW CCompositor::getNextWindowOnWorkspace(PHLWINDOW pWindow, bool focusabl
PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional<bool> floating) { PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional<bool> floating) {
bool gotToWindow = false; bool gotToWindow = false;
for (auto& w : m_vWindows | std::views::reverse) { for (auto const& w : m_vWindows | std::views::reverse) {
if (w != pWindow && !gotToWindow) if (w != pWindow && !gotToWindow)
continue; continue;
@@ -1691,7 +1705,7 @@ PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusabl
return w; return w;
} }
for (auto& w : m_vWindows | std::views::reverse) { for (auto const& w : m_vWindows | std::views::reverse) {
if (floating.has_value() && w->m_bIsFloating != floating.value()) if (floating.has_value() && w->m_bIsFloating != floating.value())
continue; continue;
@@ -1702,9 +1716,9 @@ PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusabl
return nullptr; return nullptr;
} }
int CCompositor::getNextAvailableNamedWorkspace() { WORKSPACEID CCompositor::getNextAvailableNamedWorkspace() {
int lowest = -1337 + 1; WORKSPACEID lowest = -1337 + 1;
for (auto& w : m_vWorkspaces) { for (auto const& w : m_vWorkspaces) {
if (w->m_iID < -1 && w->m_iID < lowest) if (w->m_iID < -1 && w->m_iID < lowest)
lowest = w->m_iID; lowest = w->m_iID;
} }
@@ -1713,7 +1727,7 @@ int CCompositor::getNextAvailableNamedWorkspace() {
} }
PHLWORKSPACE CCompositor::getWorkspaceByName(const std::string& name) { PHLWORKSPACE CCompositor::getWorkspaceByName(const std::string& name) {
for (auto& w : m_vWorkspaces) { for (auto const& w : m_vWorkspaces) {
if (w->m_szName == name && !w->inert()) if (w->m_szName == name && !w->inert())
return w; return w;
} }
@@ -1734,7 +1748,7 @@ PHLWORKSPACE CCompositor::getWorkspaceByString(const std::string& str) {
} }
bool CCompositor::isPointOnAnyMonitor(const Vector2D& point) { bool CCompositor::isPointOnAnyMonitor(const Vector2D& point) {
for (auto& m : m_vMonitors) { for (auto const& m : m_vMonitors) {
if (VECINRECT(point, m->vecPosition.x, m->vecPosition.y, m->vecSize.x + m->vecPosition.x, m->vecSize.y + m->vecPosition.y)) if (VECINRECT(point, m->vecPosition.x, m->vecPosition.y, m->vecSize.x + m->vecPosition.x, m->vecSize.y + m->vecPosition.y))
return true; return true;
} }
@@ -1765,7 +1779,7 @@ CMonitor* CCompositor::getMonitorInDirection(CMonitor* pSourceMonitor, const cha
auto longestIntersect = -1; auto longestIntersect = -1;
CMonitor* longestIntersectMonitor = nullptr; CMonitor* longestIntersectMonitor = nullptr;
for (auto& m : m_vMonitors) { for (auto const& m : m_vMonitors) {
if (m == m_pLastMonitor) if (m == m_pLastMonitor)
continue; continue;
@@ -1820,7 +1834,7 @@ CMonitor* CCompositor::getMonitorInDirection(CMonitor* pSourceMonitor, const cha
} }
void CCompositor::updateAllWindowsAnimatedDecorationValues() { void CCompositor::updateAllWindowsAnimatedDecorationValues() {
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (!w->m_bIsMapped) if (!w->m_bIsMapped)
continue; continue;
@@ -1829,7 +1843,7 @@ void CCompositor::updateAllWindowsAnimatedDecorationValues() {
} }
void CCompositor::updateWorkspaceWindows(const int64_t& id) { void CCompositor::updateWorkspaceWindows(const int64_t& id) {
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (!w->m_bIsMapped || w->workspaceID() != id) if (!w->m_bIsMapped || w->workspaceID() != id)
continue; continue;
@@ -1874,6 +1888,8 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) {
pWindow->m_fBorderFadeAnimationProgress = 1.f; pWindow->m_fBorderFadeAnimationProgress = 1.f;
}; };
const bool IS_SHADOWED_BY_MODAL = pWindow->m_pXDGSurface && pWindow->m_pXDGSurface->toplevel && pWindow->m_pXDGSurface->toplevel->anyChildModal();
// border // border
const auto RENDERDATA = g_pLayoutManager->getCurrentLayout()->requestRenderHints(pWindow); const auto RENDERDATA = g_pLayoutManager->getCurrentLayout()->requestRenderHints(pWindow);
if (RENDERDATA.isBorderGradient) if (RENDERDATA.isBorderGradient)
@@ -1907,14 +1923,19 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) {
} }
// dim // dim
if (pWindow == m_pLastWindow.lock() || pWindow->m_sWindowData.noDim.valueOrDefault() || !*PDIMENABLED) { float goalDim = 1.F;
pWindow->m_fDimPercent = 0; if (pWindow == m_pLastWindow.lock() || pWindow->m_sWindowData.noDim.valueOrDefault() || !*PDIMENABLED)
} else { goalDim = 0;
pWindow->m_fDimPercent = *PDIMSTRENGTH; else
} goalDim = *PDIMSTRENGTH;
if (IS_SHADOWED_BY_MODAL)
goalDim += (1.F - goalDim) / 2.F;
pWindow->m_fDimPercent = goalDim;
// shadow // shadow
if (pWindow->m_iX11Type != 2 && !pWindow->m_bX11DoesntWantBorders) { if (!pWindow->isX11OverrideRedirect() && !pWindow->m_bX11DoesntWantBorders) {
if (pWindow == m_pLastWindow) { if (pWindow == m_pLastWindow) {
pWindow->m_cRealShadowColor = CColor(*PSHADOWCOL); pWindow->m_cRealShadowColor = CColor(*PSHADOWCOL);
} else { } else {
@@ -1927,18 +1948,18 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) {
pWindow->updateWindowDecos(); pWindow->updateWindowDecos();
} }
int CCompositor::getNextAvailableMonitorID(std::string const& name) { MONITORID CCompositor::getNextAvailableMonitorID(std::string const& name) {
// reuse ID if it's already in the map, and the monitor with that ID is not being used by another monitor // reuse ID if it's already in the map, and the monitor with that ID is not being used by another monitor
if (m_mMonitorIDMap.contains(name) && !std::any_of(m_vRealMonitors.begin(), m_vRealMonitors.end(), [&](auto m) { return m->ID == m_mMonitorIDMap[name]; })) if (m_mMonitorIDMap.contains(name) && !std::any_of(m_vRealMonitors.begin(), m_vRealMonitors.end(), [&](auto m) { return m->ID == m_mMonitorIDMap[name]; }))
return m_mMonitorIDMap[name]; return m_mMonitorIDMap[name];
// otherwise, find minimum available ID that is not in the map // otherwise, find minimum available ID that is not in the map
std::unordered_set<uint64_t> usedIDs; std::unordered_set<MONITORID> usedIDs;
for (auto const& monitor : m_vRealMonitors) { for (auto const& monitor : m_vRealMonitors) {
usedIDs.insert(monitor->ID); usedIDs.insert(monitor->ID);
} }
uint64_t nextID = 0; MONITORID nextID = 0;
while (usedIDs.count(nextID) > 0) { while (usedIDs.count(nextID) > 0) {
nextID++; nextID++;
} }
@@ -1954,7 +1975,7 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB)
PWORKSPACEA->m_iMonitorID = pMonitorB->ID; PWORKSPACEA->m_iMonitorID = pMonitorB->ID;
PWORKSPACEA->moveToMonitor(pMonitorB->ID); PWORKSPACEA->moveToMonitor(pMonitorB->ID);
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w->m_pWorkspace == PWORKSPACEA) { if (w->m_pWorkspace == PWORKSPACEA) {
if (w->m_bPinned) { if (w->m_bPinned) {
w->m_pWorkspace = PWORKSPACEB; w->m_pWorkspace = PWORKSPACEB;
@@ -1979,7 +2000,7 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB)
PWORKSPACEB->m_iMonitorID = pMonitorA->ID; PWORKSPACEB->m_iMonitorID = pMonitorA->ID;
PWORKSPACEB->moveToMonitor(pMonitorA->ID); PWORKSPACEB->moveToMonitor(pMonitorA->ID);
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w->m_pWorkspace == PWORKSPACEB) { if (w->m_pWorkspace == PWORKSPACEB) {
if (w->m_bPinned) { if (w->m_bPinned) {
w->m_pWorkspace = PWORKSPACEA; w->m_pWorkspace = PWORKSPACEA;
@@ -2078,7 +2099,7 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) {
return m_vMonitors[currentPlace].get(); return m_vMonitors[currentPlace].get();
} else if (isNumber(name)) { } else if (isNumber(name)) {
// change by ID // change by ID
int monID = -1; MONITORID monID = MONITOR_INVALID;
try { try {
monID = std::stoi(name); monID = std::stoi(name);
} catch (std::exception& e) { } catch (std::exception& e) {
@@ -2087,14 +2108,14 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) {
return nullptr; return nullptr;
} }
if (monID > -1 && monID < (int)m_vMonitors.size()) { if (monID > -1 && monID < (MONITORID)m_vMonitors.size()) {
return getMonitorFromID(monID); return getMonitorFromID(monID);
} else { } else {
Debug::log(ERR, "Error in getMonitorFromString: invalid arg 1"); Debug::log(ERR, "Error in getMonitorFromString: invalid arg 1");
return nullptr; return nullptr;
} }
} else { } else {
for (auto& m : m_vMonitors) { for (auto const& m : m_vMonitors) {
if (!m->output) if (!m->output)
continue; continue;
@@ -2121,18 +2142,18 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMon
const bool SWITCHINGISACTIVE = POLDMON ? POLDMON->activeWorkspace == pWorkspace : false; const bool SWITCHINGISACTIVE = POLDMON ? POLDMON->activeWorkspace == pWorkspace : false;
// fix old mon // fix old mon
int nextWorkspaceOnMonitorID = -1; WORKSPACEID nextWorkspaceOnMonitorID = WORKSPACE_INVALID;
if (!SWITCHINGISACTIVE) if (!SWITCHINGISACTIVE)
nextWorkspaceOnMonitorID = pWorkspace->m_iID; nextWorkspaceOnMonitorID = pWorkspace->m_iID;
else { else {
for (auto& w : m_vWorkspaces) { for (auto const& w : m_vWorkspaces) {
if (w->m_iMonitorID == POLDMON->ID && w->m_iID != pWorkspace->m_iID && !w->m_bIsSpecialWorkspace) { if (w->m_iMonitorID == POLDMON->ID && w->m_iID != pWorkspace->m_iID && !w->m_bIsSpecialWorkspace) {
nextWorkspaceOnMonitorID = w->m_iID; nextWorkspaceOnMonitorID = w->m_iID;
break; break;
} }
} }
if (nextWorkspaceOnMonitorID == -1) { if (nextWorkspaceOnMonitorID == WORKSPACE_INVALID) {
nextWorkspaceOnMonitorID = 1; nextWorkspaceOnMonitorID = 1;
while (getWorkspaceByID(nextWorkspaceOnMonitorID) || [&]() -> bool { while (getWorkspaceByID(nextWorkspaceOnMonitorID) || [&]() -> bool {
@@ -2154,7 +2175,7 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMon
pWorkspace->m_iMonitorID = pMonitor->ID; pWorkspace->m_iMonitorID = pMonitor->ID;
pWorkspace->moveToMonitor(pMonitor->ID); pWorkspace->moveToMonitor(pMonitor->ID);
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w->m_pWorkspace == pWorkspace) { if (w->m_pWorkspace == pWorkspace) {
if (w->m_bPinned) { if (w->m_bPinned) {
w->m_pWorkspace = g_pCompositor->getWorkspaceByID(nextWorkspaceOnMonitorID); w->m_pWorkspace = g_pCompositor->getWorkspaceByID(nextWorkspaceOnMonitorID);
@@ -2219,11 +2240,11 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, CMonitor* pMon
EMIT_HOOK_EVENT("moveWorkspace", (std::vector<std::any>{pWorkspace, pMonitor})); EMIT_HOOK_EVENT("moveWorkspace", (std::vector<std::any>{pWorkspace, pMonitor}));
} }
bool CCompositor::workspaceIDOutOfBounds(const int64_t& id) { bool CCompositor::workspaceIDOutOfBounds(const WORKSPACEID& id) {
int64_t lowestID = INT64_MAX; WORKSPACEID lowestID = INT64_MAX;
int64_t highestID = INT64_MIN; WORKSPACEID highestID = INT64_MIN;
for (auto& w : m_vWorkspaces) { for (auto const& w : m_vWorkspaces) {
if (w->m_bIsSpecialWorkspace) if (w->m_bIsSpecialWorkspace)
continue; continue;
@@ -2241,7 +2262,7 @@ void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) {
const auto FULLSCREEN = pWorkspace->m_bHasFullscreenWindow; const auto FULLSCREEN = pWorkspace->m_bHasFullscreenWindow;
for (auto& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (w->m_pWorkspace == pWorkspace) { if (w->m_pWorkspace == pWorkspace) {
if (w->m_bFadingOut || w->m_bPinned || w->isFullscreen()) if (w->m_bFadingOut || w->m_bPinned || w->isFullscreen())
@@ -2257,7 +2278,7 @@ void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) {
const auto PMONITOR = getMonitorFromID(pWorkspace->m_iMonitorID); const auto PMONITOR = getMonitorFromID(pWorkspace->m_iMonitorID);
if (pWorkspace->m_iID == PMONITOR->activeWorkspaceID() || pWorkspace->m_iID == PMONITOR->activeSpecialWorkspaceID()) { if (pWorkspace->m_iID == PMONITOR->activeWorkspaceID() || pWorkspace->m_iID == PMONITOR->activeSpecialWorkspaceID()) {
for (auto& ls : PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { for (auto const& ls : PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
if (!ls->fadingOut) if (!ls->fadingOut)
ls->alpha = FULLSCREEN && pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f; ls->alpha = FULLSCREEN && pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f;
} }
@@ -2312,8 +2333,12 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenS
PWINDOW->m_sFullscreenState.client = state.client; PWINDOW->m_sFullscreenState.client = state.client;
g_pXWaylandManager->setWindowFullscreen(PWINDOW, state.client & FSMODE_FULLSCREEN); g_pXWaylandManager->setWindowFullscreen(PWINDOW, state.client & FSMODE_FULLSCREEN);
if (!CHANGEINTERNAL) if (!CHANGEINTERNAL) {
PWINDOW->updateDynamicRules();
updateWindowAnimatedDecorationValues(PWINDOW);
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID);
return; return;
}
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, CURRENT_EFFECTIVE_MODE, EFFECTIVE_MODE); g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, CURRENT_EFFECTIVE_MODE, EFFECTIVE_MODE);
@@ -2325,12 +2350,11 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, sFullscreenS
EMIT_HOOK_EVENT("fullscreen", PWINDOW); EMIT_HOOK_EVENT("fullscreen", PWINDOW);
PWINDOW->updateDynamicRules(); PWINDOW->updateDynamicRules();
PWINDOW->updateWindowDecos();
updateWindowAnimatedDecorationValues(PWINDOW); updateWindowAnimatedDecorationValues(PWINDOW);
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->m_iMonitorID);
// make all windows on the same workspace under the fullscreen window // make all windows on the same workspace under the fullscreen window
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w->m_pWorkspace == PWORKSPACE && !w->isFullscreen() && !w->m_bFadingOut && !w->m_bPinned) if (w->m_pWorkspace == PWORKSPACE && !w->isFullscreen() && !w->m_bFadingOut && !w->m_bPinned)
w->m_bCreatedOverFullscreen = false; w->m_bCreatedOverFullscreen = false;
} }
@@ -2359,7 +2383,7 @@ PHLWINDOW CCompositor::getX11Parent(PHLWINDOW pWindow) {
if (!pWindow->m_bIsX11) if (!pWindow->m_bIsX11)
return nullptr; return nullptr;
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (!w->m_bIsX11) if (!w->m_bIsX11)
continue; continue;
@@ -2370,8 +2394,8 @@ PHLWINDOW CCompositor::getX11Parent(PHLWINDOW pWindow) {
return nullptr; return nullptr;
} }
void CCompositor::updateWorkspaceWindowDecos(const int& id) { void CCompositor::updateWorkspaceWindowDecos(const WORKSPACEID& id) {
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w->workspaceID() != id) if (w->workspaceID() != id)
continue; continue;
@@ -2379,11 +2403,11 @@ void CCompositor::updateWorkspaceWindowDecos(const int& id) {
} }
} }
void CCompositor::updateWorkspaceWindowData(const int& id) { void CCompositor::updateWorkspaceWindowData(const WORKSPACEID& id) {
const auto PWORKSPACE = getWorkspaceByID(id); const auto PWORKSPACE = getWorkspaceByID(id);
const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{}; const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{};
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w->workspaceID() != id) if (w->workspaceID() != id)
continue; continue;
@@ -2436,7 +2460,7 @@ PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp) {
const bool FLOAT = regexp.starts_with("floating"); const bool FLOAT = regexp.starts_with("floating");
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (!w->m_bIsMapped || w->m_bIsFloating != FLOAT || w->m_pWorkspace != m_pLastWindow->m_pWorkspace || w->isHidden()) if (!w->m_bIsMapped || w->m_bIsFloating != FLOAT || w->m_pWorkspace != m_pLastWindow->m_pWorkspace || w->isHidden())
continue; continue;
@@ -2446,7 +2470,7 @@ PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp) {
return nullptr; return nullptr;
} }
for (auto& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped || (w->isHidden() && !g_pLayoutManager->getCurrentLayout()->isWindowReachable(w))) if (!w->m_bIsMapped || (w->isHidden() && !g_pLayoutManager->getCurrentLayout()->isWindowReachable(w)))
continue; continue;
@@ -2526,7 +2550,7 @@ void CCompositor::closeWindow(PHLWINDOW pWindow) {
PHLLS CCompositor::getLayerSurfaceFromSurface(SP<CWLSurfaceResource> pSurface) { PHLLS CCompositor::getLayerSurfaceFromSurface(SP<CWLSurfaceResource> pSurface) {
std::pair<SP<CWLSurfaceResource>, bool> result = {pSurface, false}; std::pair<SP<CWLSurfaceResource>, bool> result = {pSurface, false};
for (auto& ls : m_vLayers) { for (auto const& ls : m_vLayers) {
if (ls->layerSurface && ls->layerSurface->surface == pSurface) if (ls->layerSurface && ls->layerSurface->surface == pSurface)
return ls; return ls;
@@ -2599,15 +2623,15 @@ Vector2D CCompositor::parseWindowVectorArgsRelative(const std::string& args, con
return Vector2D(X, Y); return Vector2D(X, Y);
} }
void CCompositor::forceReportSizesToWindowsOnWorkspace(const int& wid) { void CCompositor::forceReportSizesToWindowsOnWorkspace(const WORKSPACEID& wid) {
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w->workspaceID() == wid && w->m_bIsMapped && !w->isHidden()) { if (w->workspaceID() == wid && w->m_bIsMapped && !w->isHidden()) {
g_pXWaylandManager->setWindowSize(w, w->m_vRealSize.value(), true); g_pXWaylandManager->setWindowSize(w, w->m_vRealSize.value(), true);
} }
} }
} }
PHLWORKSPACE CCompositor::createNewWorkspace(const int& id, const int& monid, const std::string& name, bool isEmtpy) { PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITORID& monid, const std::string& name, bool isEmpty) {
const auto NAME = name == "" ? std::to_string(id) : name; const auto NAME = name == "" ? std::to_string(id) : name;
auto monID = monid; auto monID = monid;
@@ -2618,14 +2642,14 @@ PHLWORKSPACE CCompositor::createNewWorkspace(const int& id, const int& monid, co
const bool SPECIAL = id >= SPECIAL_WORKSPACE_START && id <= -2; const bool SPECIAL = id >= SPECIAL_WORKSPACE_START && id <= -2;
const auto PWORKSPACE = m_vWorkspaces.emplace_back(CWorkspace::create(id, monID, NAME, SPECIAL, isEmtpy)); const auto PWORKSPACE = m_vWorkspaces.emplace_back(CWorkspace::create(id, monID, NAME, SPECIAL, isEmpty));
PWORKSPACE->m_fAlpha.setValueAndWarp(0); PWORKSPACE->m_fAlpha.setValueAndWarp(0);
return PWORKSPACE; return PWORKSPACE;
} }
void CCompositor::renameWorkspace(const int& id, const std::string& name) { void CCompositor::renameWorkspace(const WORKSPACEID& id, const std::string& name) {
const auto PWORKSPACE = getWorkspaceByID(id); const auto PWORKSPACE = getWorkspaceByID(id);
if (!PWORKSPACE) if (!PWORKSPACE)
@@ -2656,13 +2680,13 @@ void CCompositor::setActiveMonitor(CMonitor* pMonitor) {
m_pLastMonitor = pMonitor->self; m_pLastMonitor = pMonitor->self;
} }
bool CCompositor::isWorkspaceSpecial(const int& id) { bool CCompositor::isWorkspaceSpecial(const WORKSPACEID& id) {
return id >= SPECIAL_WORKSPACE_START && id <= -2; return id >= SPECIAL_WORKSPACE_START && id <= -2;
} }
int CCompositor::getNewSpecialID() { WORKSPACEID CCompositor::getNewSpecialID() {
int highest = SPECIAL_WORKSPACE_START; WORKSPACEID highest = SPECIAL_WORKSPACE_START;
for (auto& ws : m_vWorkspaces) { for (auto const& ws : m_vWorkspaces) {
if (ws->m_bIsSpecialWorkspace && ws->m_iID > highest) { if (ws->m_bIsSpecialWorkspace && ws->m_iID > highest) {
highest = ws->m_iID; highest = ws->m_iID;
} }
@@ -2672,7 +2696,17 @@ int CCompositor::getNewSpecialID() {
} }
void CCompositor::performUserChecks() { void CCompositor::performUserChecks() {
; // intentional static auto PNOCHECKXDG = CConfigValue<Hyprlang::INT>("misc:disable_xdg_env_checks");
if (!*PNOCHECKXDG) {
const auto CURRENT_DESKTOP_ENV = getenv("XDG_CURRENT_DESKTOP");
if (!CURRENT_DESKTOP_ENV || std::string{CURRENT_DESKTOP_ENV} != "Hyprland") {
g_pHyprNotificationOverlay->addNotification(
std::format("Your XDG_CURRENT_DESKTOP environment seems to be managed externally, and the current value is {}.\nThis might cause issues unless it's intentional.",
CURRENT_DESKTOP_ENV ? CURRENT_DESKTOP_ENV : "unset"),
CColor{}, 15000, ICON_WARNING);
}
}
} }
void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace) { void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace) {
@@ -2723,10 +2757,11 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor
g_pCompositor->updateWorkspaceWindows(pWorkspace->m_iID); g_pCompositor->updateWorkspaceWindows(pWorkspace->m_iID);
g_pCompositor->updateWorkspaceWindows(pWindow->workspaceID()); g_pCompositor->updateWorkspaceWindows(pWindow->workspaceID());
g_pCompositor->updateSuspendedStates();
} }
PHLWINDOW CCompositor::getForceFocus() { PHLWINDOW CCompositor::getForceFocus() {
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (!w->m_bIsMapped || w->isHidden() || !isWorkspaceVisible(w->m_pWorkspace)) if (!w->m_bIsMapped || w->isHidden() || !isWorkspaceVisible(w->m_pWorkspace))
continue; continue;
@@ -2745,7 +2780,7 @@ void CCompositor::arrangeMonitors() {
std::vector<CMonitor*> toArrange; std::vector<CMonitor*> toArrange;
std::vector<CMonitor*> arranged; std::vector<CMonitor*> arranged;
for (auto& m : m_vMonitors) for (auto const& m : m_vMonitors)
toArrange.push_back(m.get()); toArrange.push_back(m.get());
Debug::log(LOG, "arrangeMonitors: {} to arrange", toArrange.size()); Debug::log(LOG, "arrangeMonitors: {} to arrange", toArrange.size());
@@ -2777,7 +2812,7 @@ void CCompositor::arrangeMonitors() {
int maxYOffsetDown = 0; int maxYOffsetDown = 0;
// Finds the max and min values of explicitely placed monitors. // Finds the max and min values of explicitely placed monitors.
for (auto& m : arranged) { for (auto const& m : arranged) {
if (m->vecPosition.x + m->vecSize.x > maxXOffsetRight) if (m->vecPosition.x + m->vecSize.x > maxXOffsetRight)
maxXOffsetRight = m->vecPosition.x + m->vecSize.x; maxXOffsetRight = m->vecPosition.x + m->vecSize.x;
if (m->vecPosition.x < maxXOffsetLeft) if (m->vecPosition.x < maxXOffsetLeft)
@@ -2789,7 +2824,7 @@ void CCompositor::arrangeMonitors() {
} }
// Iterates through all non-explicitly placed monitors. // Iterates through all non-explicitly placed monitors.
for (auto& m : toArrange) { for (auto const& m : toArrange) {
// Moves the monitor to their appropriate position on the x/y axis and // Moves the monitor to their appropriate position on the x/y axis and
// increments/decrements the corresponding max offset. // increments/decrements the corresponding max offset.
Vector2D newPosition = {0, 0}; Vector2D newPosition = {0, 0};
@@ -2820,7 +2855,7 @@ void CCompositor::arrangeMonitors() {
// reset maxXOffsetRight (reuse) // reset maxXOffsetRight (reuse)
// and set xwayland positions aka auto for all // and set xwayland positions aka auto for all
maxXOffsetRight = 0; maxXOffsetRight = 0;
for (auto& m : m_vMonitors) { for (auto const& m : m_vMonitors) {
Debug::log(LOG, "arrangeMonitors: {} xwayland [{}, {}]", m->szName, maxXOffsetRight, 0); Debug::log(LOG, "arrangeMonitors: {} xwayland [{}, {}]", m->szName, maxXOffsetRight, 0);
m->vecXWaylandPosition = {maxXOffsetRight, 0}; m->vecXWaylandPosition = {maxXOffsetRight, 0};
maxXOffsetRight += (*PXWLFORCESCALEZERO ? m->vecTransformedSize.x : m->vecSize.x); maxXOffsetRight += (*PXWLFORCESCALEZERO ? m->vecTransformedSize.x : m->vecSize.x);
@@ -2855,7 +2890,7 @@ void CCompositor::leaveUnsafeState() {
m_bUnsafeState = false; m_bUnsafeState = false;
CMonitor* pNewMonitor = nullptr; CMonitor* pNewMonitor = nullptr;
for (auto& pMonitor : m_vMonitors) { for (auto const& pMonitor : m_vMonitors) {
if (pMonitor->output != m_pUnsafeOutput->output) { if (pMonitor->output != m_pUnsafeOutput->output) {
pNewMonitor = pMonitor.get(); pNewMonitor = pMonitor.get();
break; break;
@@ -2867,7 +2902,7 @@ void CCompositor::leaveUnsafeState() {
if (m_pUnsafeOutput->m_bEnabled) if (m_pUnsafeOutput->m_bEnabled)
m_pUnsafeOutput->onDisconnect(); m_pUnsafeOutput->onDisconnect();
for (auto& m : m_vMonitors) { for (auto const& m : m_vMonitors) {
scheduleFrameForMonitor(m.get()); scheduleFrameForMonitor(m.get());
} }
} }
@@ -2899,7 +2934,7 @@ void CCompositor::setPreferredTransformForSurface(SP<CWLSurfaceResource> pSurfac
} }
void CCompositor::updateSuspendedStates() { void CCompositor::updateSuspendedStates() {
for (auto& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped) if (!w->m_bIsMapped)
continue; continue;
@@ -2908,7 +2943,7 @@ void CCompositor::updateSuspendedStates() {
} }
PHLWINDOW CCompositor::windowForCPointer(CWindow* pWindow) { PHLWINDOW CCompositor::windowForCPointer(CWindow* pWindow) {
for (auto& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w.get() != pWindow) if (w.get() != pWindow)
continue; continue;
@@ -2918,13 +2953,12 @@ PHLWINDOW CCompositor::windowForCPointer(CWindow* pWindow) {
return {}; return {};
} }
static void checkDefaultCursorWarp(SP<CMonitor> PNEWMONITOR, std::string monitorName) { static void checkDefaultCursorWarp(SP<CMonitor> monitor) {
static auto PCURSORMONITOR = CConfigValue<std::string>("cursor:default_monitor"); static auto PCURSORMONITOR = CConfigValue<std::string>("cursor:default_monitor");
static auto firstMonitorAdded = std::chrono::system_clock::now();
static bool cursorDefaultDone = false; static bool cursorDefaultDone = false;
static bool firstLaunch = true; static bool firstLaunch = true;
const auto POS = PNEWMONITOR->middle(); const auto POS = monitor->middle();
// by default, cursor should be set to first monitor detected // by default, cursor should be set to first monitor detected
// this is needed as a default if the monitor given in config above doesn't exist // this is needed as a default if the monitor given in config above doesn't exist
@@ -2932,20 +2966,20 @@ static void checkDefaultCursorWarp(SP<CMonitor> PNEWMONITOR, std::string monitor
firstLaunch = false; firstLaunch = false;
g_pCompositor->warpCursorTo(POS, true); g_pCompositor->warpCursorTo(POS, true);
g_pInputManager->refocus(); g_pInputManager->refocus();
}
if (cursorDefaultDone || *PCURSORMONITOR == STRVAL_EMPTY)
return;
// after 10s, don't set cursor to default monitor
auto timePassedSec = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() - firstMonitorAdded);
if (timePassedSec.count() > 10) {
cursorDefaultDone = true;
return; return;
} }
if (*PCURSORMONITOR == monitorName) { if (!cursorDefaultDone && *PCURSORMONITOR != STRVAL_EMPTY) {
cursorDefaultDone = true; if (*PCURSORMONITOR == monitor->szName) {
cursorDefaultDone = true;
g_pCompositor->warpCursorTo(POS, true);
g_pInputManager->refocus();
return;
}
}
// modechange happend check if cursor is on that monitor and warp it to middle to not place it out of bounds if resolution changed.
if (g_pCompositor->getMonitorFromCursor() == monitor.get()) {
g_pCompositor->warpCursorTo(POS, true); g_pCompositor->warpCursorTo(POS, true);
g_pInputManager->refocus(); g_pInputManager->refocus();
} }
@@ -2953,7 +2987,7 @@ static void checkDefaultCursorWarp(SP<CMonitor> PNEWMONITOR, std::string monitor
void CCompositor::onNewMonitor(SP<Aquamarine::IOutput> output) { void CCompositor::onNewMonitor(SP<Aquamarine::IOutput> output) {
// add it to real // add it to real
auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared<CMonitor>()); auto PNEWMONITOR = g_pCompositor->m_vRealMonitors.emplace_back(makeShared<CMonitor>(output));
if (std::string("HEADLESS-1") == output->name) { if (std::string("HEADLESS-1") == output->name) {
g_pCompositor->m_pUnsafeOutput = PNEWMONITOR.get(); g_pCompositor->m_pUnsafeOutput = PNEWMONITOR.get();
output->name = "FALLBACK"; // we are allowed to do this :) output->name = "FALLBACK"; // we are allowed to do this :)
@@ -2962,10 +2996,9 @@ void CCompositor::onNewMonitor(SP<Aquamarine::IOutput> output) {
Debug::log(LOG, "New output with name {}", output->name); Debug::log(LOG, "New output with name {}", output->name);
PNEWMONITOR->szName = output->name; PNEWMONITOR->szName = output->name;
PNEWMONITOR->output = output;
PNEWMONITOR->self = PNEWMONITOR; PNEWMONITOR->self = PNEWMONITOR;
const bool FALLBACK = g_pCompositor->m_pUnsafeOutput ? output == g_pCompositor->m_pUnsafeOutput->output : false; const bool FALLBACK = g_pCompositor->m_pUnsafeOutput ? output == g_pCompositor->m_pUnsafeOutput->output : false;
PNEWMONITOR->ID = FALLBACK ? -1 : g_pCompositor->getNextAvailableMonitorID(output->name); PNEWMONITOR->ID = FALLBACK ? MONITOR_INVALID : g_pCompositor->getNextAvailableMonitorID(output->name);
PNEWMONITOR->isUnsafeFallback = FALLBACK; PNEWMONITOR->isUnsafeFallback = FALLBACK;
EMIT_HOOK_EVENT("newMonitor", PNEWMONITOR); EMIT_HOOK_EVENT("newMonitor", PNEWMONITOR);
@@ -2986,11 +3019,11 @@ void CCompositor::onNewMonitor(SP<Aquamarine::IOutput> output) {
g_pConfigManager->m_bWantsMonitorReload = true; g_pConfigManager->m_bWantsMonitorReload = true;
g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get(), IOutput::AQ_SCHEDULE_NEW_MONITOR); g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR.get(), IOutput::AQ_SCHEDULE_NEW_MONITOR);
checkDefaultCursorWarp(PNEWMONITOR, output->name); checkDefaultCursorWarp(PNEWMONITOR);
for (auto& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (w->m_iMonitorID == PNEWMONITOR->ID) { if (w->m_iMonitorID == PNEWMONITOR->ID) {
w->m_iLastSurfaceMonitorID = -1; w->m_iLastSurfaceMonitorID = MONITOR_INVALID;
w->updateSurfaceScaleTransformDetails(); w->updateSurfaceScaleTransformDetails();
} }
} }

View File

@@ -46,55 +46,58 @@ class CCompositor {
CCompositor(); CCompositor();
~CCompositor(); ~CCompositor();
wl_display* m_sWLDisplay; wl_display* m_sWLDisplay;
wl_event_loop* m_sWLEventLoop; wl_event_loop* m_sWLEventLoop;
int m_iDRMFD = -1; int m_iDRMFD = -1;
bool m_bInitialized = false; bool m_bInitialized = false;
SP<Aquamarine::CBackend> m_pAqBackend; SP<Aquamarine::CBackend> m_pAqBackend;
std::string m_szHyprTempDataRoot = ""; std::string m_szHyprTempDataRoot = "";
std::string m_szWLDisplaySocket = ""; std::string m_szWLDisplaySocket = "";
std::string m_szInstanceSignature = ""; std::string m_szInstanceSignature = "";
std::string m_szInstancePath = ""; std::string m_szInstancePath = "";
std::string m_szCurrentSplash = "error"; std::string m_szCurrentSplash = "error";
std::vector<SP<CMonitor>> m_vMonitors; std::vector<SP<CMonitor>> m_vMonitors;
std::vector<SP<CMonitor>> m_vRealMonitors; // for all monitors, even those turned off std::vector<SP<CMonitor>> m_vRealMonitors; // for all monitors, even those turned off
std::vector<PHLWINDOW> m_vWindows; std::vector<PHLWINDOW> m_vWindows;
std::vector<PHLLS> m_vLayers; std::vector<PHLLS> m_vLayers;
std::vector<PHLWORKSPACE> m_vWorkspaces; std::vector<PHLWORKSPACE> m_vWorkspaces;
std::vector<PHLWINDOWREF> m_vWindowsFadingOut; std::vector<PHLWINDOWREF> m_vWindowsFadingOut;
std::vector<PHLLSREF> m_vSurfacesFadingOut; std::vector<PHLLSREF> m_vSurfacesFadingOut;
std::unordered_map<std::string, uint64_t> m_mMonitorIDMap; std::unordered_map<std::string, MONITORID> m_mMonitorIDMap;
void initServer(std::string socketName, int socketFd); void initServer(std::string socketName, int socketFd);
void startCompositor(); void startCompositor();
void stopCompositor(); void stopCompositor();
void cleanup(); void cleanup();
void createLockFile(); void createLockFile();
void removeLockFile(); void removeLockFile();
void bumpNofile(); void bumpNofile();
void restoreNofile(); void restoreNofile();
WP<CWLSurfaceResource> m_pLastFocus; WP<CWLSurfaceResource> m_pLastFocus;
PHLWINDOWREF m_pLastWindow; PHLWINDOWREF m_pLastWindow;
WP<CMonitor> m_pLastMonitor; WP<CMonitor> m_pLastMonitor;
std::vector<PHLWINDOWREF> m_vWindowFocusHistory; // first element is the most recently focused. std::vector<PHLWINDOWREF> m_vWindowFocusHistory; // first element is the most recently focused.
bool m_bReadyToProcess = false; bool m_bReadyToProcess = false;
bool m_bSessionActive = true; bool m_bSessionActive = true;
bool m_bDPMSStateON = true; bool m_bDPMSStateON = true;
bool m_bUnsafeState = false; // unsafe state is when there is no monitors. bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
bool m_bNextIsUnsafe = false; bool m_bNextIsUnsafe = false;
CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state
bool m_bIsShuttingDown = false; bool m_bIsShuttingDown = false;
bool m_bFinalRequests = false;
bool m_bDesktopEnvSet = false;
bool m_bEnableXwayland = true;
// ------------------------------------------------- // // ------------------------------------------------- //
CMonitor* getMonitorFromID(const int&); CMonitor* getMonitorFromID(const MONITORID&);
CMonitor* getMonitorFromName(const std::string&); CMonitor* getMonitorFromName(const std::string&);
CMonitor* getMonitorFromDesc(const std::string&); CMonitor* getMonitorFromDesc(const std::string&);
CMonitor* getMonitorFromCursor(); CMonitor* getMonitorFromCursor();
@@ -114,38 +117,38 @@ class CCompositor {
PHLWINDOW getWindowFromHandle(uint32_t); PHLWINDOW getWindowFromHandle(uint32_t);
bool isWorkspaceVisible(PHLWORKSPACE); bool isWorkspaceVisible(PHLWORKSPACE);
bool isWorkspaceVisibleNotCovered(PHLWORKSPACE); bool isWorkspaceVisibleNotCovered(PHLWORKSPACE);
PHLWORKSPACE getWorkspaceByID(const int&); PHLWORKSPACE getWorkspaceByID(const WORKSPACEID&);
PHLWORKSPACE getWorkspaceByName(const std::string&); PHLWORKSPACE getWorkspaceByName(const std::string&);
PHLWORKSPACE getWorkspaceByString(const std::string&); PHLWORKSPACE getWorkspaceByString(const std::string&);
void sanityCheckWorkspaces(); void sanityCheckWorkspaces();
void updateWorkspaceWindowDecos(const int&); void updateWorkspaceWindowDecos(const WORKSPACEID&);
void updateWorkspaceWindowData(const int&); void updateWorkspaceWindowData(const WORKSPACEID&);
int getWindowsOnWorkspace(const int& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {}); int getWindowsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
int getGroupsOnWorkspace(const int& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {}); int getGroupsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
PHLWINDOW getUrgentWindow(); PHLWINDOW getUrgentWindow();
bool hasUrgentWindowOnWorkspace(const int&); bool hasUrgentWindowOnWorkspace(const WORKSPACEID&);
PHLWINDOW getFirstWindowOnWorkspace(const int&); PHLWINDOW getFirstWindowOnWorkspace(const WORKSPACEID&);
PHLWINDOW getTopLeftWindowOnWorkspace(const int&); PHLWINDOW getTopLeftWindowOnWorkspace(const WORKSPACEID&);
PHLWINDOW getFullscreenWindowOnWorkspace(const int&); PHLWINDOW getFullscreenWindowOnWorkspace(const WORKSPACEID&);
bool isWindowActive(PHLWINDOW); bool isWindowActive(PHLWINDOW);
void changeWindowZOrder(PHLWINDOW, bool); void changeWindowZOrder(PHLWINDOW, bool);
void cleanupFadingOut(const int& monid); void cleanupFadingOut(const MONITORID& monid);
PHLWINDOW getWindowInDirection(PHLWINDOW, char); PHLWINDOW getWindowInDirection(PHLWINDOW, char);
PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {}); PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {}); PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
int getNextAvailableNamedWorkspace(); WORKSPACEID getNextAvailableNamedWorkspace();
bool isPointOnAnyMonitor(const Vector2D&); bool isPointOnAnyMonitor(const Vector2D&);
bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr); bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr);
CMonitor* getMonitorInDirection(const char&); CMonitor* getMonitorInDirection(const char&);
CMonitor* getMonitorInDirection(CMonitor*, const char&); CMonitor* getMonitorInDirection(CMonitor*, const char&);
void updateAllWindowsAnimatedDecorationValues(); void updateAllWindowsAnimatedDecorationValues();
void updateWorkspaceWindows(const int64_t& id); void updateWorkspaceWindows(const WORKSPACEID& id);
void updateWindowAnimatedDecorationValues(PHLWINDOW); void updateWindowAnimatedDecorationValues(PHLWINDOW);
int getNextAvailableMonitorID(std::string const& name); MONITORID getNextAvailableMonitorID(std::string const& name);
void moveWorkspaceToMonitor(PHLWORKSPACE, CMonitor*, bool noWarpCursor = false); void moveWorkspaceToMonitor(PHLWORKSPACE, CMonitor*, bool noWarpCursor = false);
void swapActiveWorkspaces(CMonitor*, CMonitor*); void swapActiveWorkspaces(CMonitor*, CMonitor*);
CMonitor* getMonitorFromString(const std::string&); CMonitor* getMonitorFromString(const std::string&);
bool workspaceIDOutOfBounds(const int64_t&); bool workspaceIDOutOfBounds(const WORKSPACEID&);
void setWindowFullscreenInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE); void setWindowFullscreenInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE);
void setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE); void setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE);
void setWindowFullscreenState(const PHLWINDOW PWINDOW, const sFullscreenState state); void setWindowFullscreenState(const PHLWINDOW PWINDOW, const sFullscreenState state);
@@ -162,12 +165,13 @@ class CCompositor {
PHLLS getLayerSurfaceFromSurface(SP<CWLSurfaceResource>); PHLLS getLayerSurfaceFromSurface(SP<CWLSurfaceResource>);
void closeWindow(PHLWINDOW); void closeWindow(PHLWINDOW);
Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&); Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&);
void forceReportSizesToWindowsOnWorkspace(const int&); void forceReportSizesToWindowsOnWorkspace(const WORKSPACEID&);
PHLWORKSPACE createNewWorkspace(const int&, const int&, const std::string& name = "", bool isEmtpy = true); // will be deleted next frame if left empty and unfocused! PHLWORKSPACE createNewWorkspace(const WORKSPACEID&, const MONITORID&, const std::string& name = "",
void renameWorkspace(const int&, const std::string& name = ""); bool isEmpty = true); // will be deleted next frame if left empty and unfocused!
void renameWorkspace(const WORKSPACEID&, const std::string& name = "");
void setActiveMonitor(CMonitor*); void setActiveMonitor(CMonitor*);
bool isWorkspaceSpecial(const int&); bool isWorkspaceSpecial(const WORKSPACEID&);
int getNewSpecialID(); WORKSPACEID getNewSpecialID();
void performUserChecks(); void performUserChecks();
void moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace); void moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace);
PHLWINDOW getForceFocus(); PHLWINDOW getForceFocus();

View File

@@ -52,4 +52,8 @@ struct SHyprCtlCommand {
std::function<std::string(eHyprCtlOutputFormat, std::string)> fn; std::function<std::string(eHyprCtlOutputFormat, std::string)> fn;
}; };
typedef int64_t WINDOWID;
typedef int64_t MONITORID;
typedef int64_t WORKSPACEID;
typedef std::function<void(void*, SCallbackInfo&, std::any)> HOOK_CALLBACK_FN; typedef std::function<void(void*, SCallbackInfo&, std::any)> HOOK_CALLBACK_FN;

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,7 @@
#include "config/ConfigValue.hpp" #include "config/ConfigValue.hpp"
#include "helpers/varlist/VarList.hpp" #include "helpers/varlist/VarList.hpp"
#include "../protocols/LayerShell.hpp" #include "../protocols/LayerShell.hpp"
#include "../xwayland/XWayland.hpp"
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
@@ -28,7 +29,9 @@
#include <filesystem> #include <filesystem>
using namespace Hyprutils::String; using namespace Hyprutils::String;
extern "C" char** environ; extern "C" char** environ;
#include "ConfigDescriptions.hpp"
static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** data) { static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** data) {
std::string V = VALUE; std::string V = VALUE;
@@ -43,7 +46,7 @@ static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void**
std::string parseError = ""; std::string parseError = "";
for (auto& var : varlist) { for (auto const& var : varlist) {
if (var.find("deg") != std::string::npos) { if (var.find("deg") != std::string::npos) {
// last arg // last arg
try { try {
@@ -138,6 +141,18 @@ static Hyprlang::CParseResult handleExecOnce(const char* c, const char* v) {
return result; return result;
} }
static Hyprlang::CParseResult handleExecShutdown(const char* c, const char* v) {
const std::string VALUE = v;
const std::string COMMAND = c;
const auto RESULT = g_pConfigManager->handleExecShutdown(COMMAND, VALUE);
Hyprlang::CParseResult result;
if (RESULT.has_value())
result.setError(RESULT.value().c_str());
return result;
}
static Hyprlang::CParseResult handleMonitor(const char* c, const char* v) { static Hyprlang::CParseResult handleMonitor(const char* c, const char* v) {
const std::string VALUE = v; const std::string VALUE = v;
const std::string COMMAND = c; const std::string COMMAND = c;
@@ -312,8 +327,6 @@ CConfigManager::CConfigManager() {
configPaths.emplace_back(getMainConfigPath()); configPaths.emplace_back(getMainConfigPath());
m_pConfig = std::make_unique<Hyprlang::CConfig>(configPaths.begin()->c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = true}); m_pConfig = std::make_unique<Hyprlang::CConfig>(configPaths.begin()->c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = true});
m_pConfig->addConfigValue("general:sensitivity", {1.0f});
m_pConfig->addConfigValue("general:apply_sens_to_raw", Hyprlang::INT{0});
m_pConfig->addConfigValue("general:border_size", Hyprlang::INT{1}); m_pConfig->addConfigValue("general:border_size", Hyprlang::INT{1});
m_pConfig->addConfigValue("general:no_border_on_floating", Hyprlang::INT{0}); m_pConfig->addConfigValue("general:no_border_on_floating", Hyprlang::INT{0});
m_pConfig->addConfigValue("general:border_part_of_window", Hyprlang::INT{1}); m_pConfig->addConfigValue("general:border_part_of_window", Hyprlang::INT{1});
@@ -357,9 +370,12 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("misc:exit_window_retains_fullscreen", Hyprlang::INT{0}); m_pConfig->addConfigValue("misc:exit_window_retains_fullscreen", Hyprlang::INT{0});
m_pConfig->addConfigValue("misc:initial_workspace_tracking", Hyprlang::INT{1}); m_pConfig->addConfigValue("misc:initial_workspace_tracking", Hyprlang::INT{1});
m_pConfig->addConfigValue("misc:middle_click_paste", Hyprlang::INT{1}); m_pConfig->addConfigValue("misc:middle_click_paste", Hyprlang::INT{1});
m_pConfig->addConfigValue("misc:render_unfocused_fps", Hyprlang::INT{15});
m_pConfig->addConfigValue("misc:disable_xdg_env_checks", Hyprlang::INT{0});
m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1});
m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1});
m_pConfig->addConfigValue("group:merge_groups_on_drag", Hyprlang::INT{1});
m_pConfig->addConfigValue("group:groupbar:enabled", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:enabled", Hyprlang::INT{1});
m_pConfig->addConfigValue("group:groupbar:font_family", {STRVAL_EMPTY}); m_pConfig->addConfigValue("group:groupbar:font_family", {STRVAL_EMPTY});
m_pConfig->addConfigValue("group:groupbar:font_size", Hyprlang::INT{8}); m_pConfig->addConfigValue("group:groupbar:font_size", Hyprlang::INT{8});
@@ -449,6 +465,7 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("animations:first_launch_animation", Hyprlang::INT{1}); m_pConfig->addConfigValue("animations:first_launch_animation", Hyprlang::INT{1});
m_pConfig->addConfigValue("input:follow_mouse", Hyprlang::INT{1}); m_pConfig->addConfigValue("input:follow_mouse", Hyprlang::INT{1});
m_pConfig->addConfigValue("input:focus_on_close", Hyprlang::INT{0});
m_pConfig->addConfigValue("input:mouse_refocus", Hyprlang::INT{1}); m_pConfig->addConfigValue("input:mouse_refocus", Hyprlang::INT{1});
m_pConfig->addConfigValue("input:special_fallthrough", Hyprlang::INT{0}); m_pConfig->addConfigValue("input:special_fallthrough", Hyprlang::INT{0});
m_pConfig->addConfigValue("input:off_window_axis_events", Hyprlang::INT{1}); m_pConfig->addConfigValue("input:off_window_axis_events", Hyprlang::INT{1});
@@ -521,6 +538,7 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("gestures:workspace_swipe_touch", Hyprlang::INT{0}); m_pConfig->addConfigValue("gestures:workspace_swipe_touch", Hyprlang::INT{0});
m_pConfig->addConfigValue("gestures:workspace_swipe_touch_invert", Hyprlang::INT{0}); m_pConfig->addConfigValue("gestures:workspace_swipe_touch_invert", Hyprlang::INT{0});
m_pConfig->addConfigValue("xwayland:enabled", Hyprlang::INT{1});
m_pConfig->addConfigValue("xwayland:use_nearest_neighbor", Hyprlang::INT{1}); m_pConfig->addConfigValue("xwayland:use_nearest_neighbor", Hyprlang::INT{1});
m_pConfig->addConfigValue("xwayland:force_zero_scaling", Hyprlang::INT{0}); m_pConfig->addConfigValue("xwayland:force_zero_scaling", Hyprlang::INT{0});
@@ -531,7 +549,7 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{0});
m_pConfig->addConfigValue("cursor:min_refresh_rate", Hyprlang::INT{24}); m_pConfig->addConfigValue("cursor:min_refresh_rate", Hyprlang::INT{24});
m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{0});
m_pConfig->addConfigValue("cursor:inactive_timeout", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:inactive_timeout", {0.f});
m_pConfig->addConfigValue("cursor:no_warps", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:no_warps", Hyprlang::INT{0});
m_pConfig->addConfigValue("cursor:persistent_warps", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:persistent_warps", Hyprlang::INT{0});
m_pConfig->addConfigValue("cursor:warp_on_change_workspace", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:warp_on_change_workspace", Hyprlang::INT{0});
@@ -539,6 +557,7 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("cursor:zoom_factor", {1.f}); m_pConfig->addConfigValue("cursor:zoom_factor", {1.f});
m_pConfig->addConfigValue("cursor:zoom_rigid", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:zoom_rigid", Hyprlang::INT{0});
m_pConfig->addConfigValue("cursor:enable_hyprcursor", Hyprlang::INT{1}); m_pConfig->addConfigValue("cursor:enable_hyprcursor", Hyprlang::INT{1});
m_pConfig->addConfigValue("cursor:sync_gsettings_theme", Hyprlang::INT{1});
m_pConfig->addConfigValue("cursor:hide_on_key_press", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:hide_on_key_press", Hyprlang::INT{0});
m_pConfig->addConfigValue("cursor:hide_on_touch", Hyprlang::INT{1}); m_pConfig->addConfigValue("cursor:hide_on_touch", Hyprlang::INT{1});
m_pConfig->addConfigValue("cursor:allow_dumb_copy", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:allow_dumb_copy", Hyprlang::INT{0});
@@ -603,6 +622,7 @@ CConfigManager::CConfigManager() {
// keywords // keywords
m_pConfig->registerHandler(&::handleRawExec, "exec", {false}); m_pConfig->registerHandler(&::handleRawExec, "exec", {false});
m_pConfig->registerHandler(&::handleExecOnce, "exec-once", {false}); m_pConfig->registerHandler(&::handleExecOnce, "exec-once", {false});
m_pConfig->registerHandler(&::handleExecShutdown, "exec-shutdown", {false});
m_pConfig->registerHandler(&::handleMonitor, "monitor", {false}); m_pConfig->registerHandler(&::handleMonitor, "monitor", {false});
m_pConfig->registerHandler(&::handleBind, "bind", {true}); m_pConfig->registerHandler(&::handleBind, "bind", {true});
m_pConfig->registerHandler(&::handleUnbind, "unbind", {false}); m_pConfig->registerHandler(&::handleUnbind, "unbind", {false});
@@ -722,7 +742,6 @@ void CConfigManager::setDefaultAnimationVars() {
INITANIMCFG("fade"); INITANIMCFG("fade");
INITANIMCFG("border"); INITANIMCFG("border");
INITANIMCFG("borderangle"); INITANIMCFG("borderangle");
INITANIMCFG("workspaces");
// windows // windows
INITANIMCFG("windowsIn"); INITANIMCFG("windowsIn");
@@ -743,7 +762,12 @@ void CConfigManager::setDefaultAnimationVars() {
// border // border
// workspaces // workspaces
INITANIMCFG("workspaces");
INITANIMCFG("workspacesIn");
INITANIMCFG("workspacesOut");
INITANIMCFG("specialWorkspace"); INITANIMCFG("specialWorkspace");
INITANIMCFG("specialWorkspaceIn");
INITANIMCFG("specialWorkspaceOut");
} }
// init the values // init the values
@@ -772,7 +796,11 @@ void CConfigManager::setDefaultAnimationVars() {
CREATEANIMCFG("fadeLayersIn", "fadeLayers"); CREATEANIMCFG("fadeLayersIn", "fadeLayers");
CREATEANIMCFG("fadeLayersOut", "fadeLayers"); CREATEANIMCFG("fadeLayersOut", "fadeLayers");
CREATEANIMCFG("workspacesIn", "workspaces");
CREATEANIMCFG("workspacesOut", "workspaces");
CREATEANIMCFG("specialWorkspace", "workspaces"); CREATEANIMCFG("specialWorkspace", "workspaces");
CREATEANIMCFG("specialWorkspaceIn", "specialWorkspace");
CREATEANIMCFG("specialWorkspaceOut", "specialWorkspace");
} }
std::optional<std::string> CConfigManager::resetHLConfig() { std::optional<std::string> CConfigManager::resetHLConfig() {
@@ -787,6 +815,7 @@ std::optional<std::string> CConfigManager::resetHLConfig() {
m_vDeclaredPlugins.clear(); m_vDeclaredPlugins.clear();
m_dLayerRules.clear(); m_dLayerRules.clear();
m_vFailedPluginConfigValues.clear(); m_vFailedPluginConfigValues.clear();
finalExecRequests.clear();
// paths // paths
configPaths.clear(); configPaths.clear();
@@ -803,11 +832,11 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
static const auto PENABLEEXPLICIT = CConfigValue<Hyprlang::INT>("render:explicit_sync"); static const auto PENABLEEXPLICIT = CConfigValue<Hyprlang::INT>("render:explicit_sync");
static int prevEnabledExplicit = *PENABLEEXPLICIT; static int prevEnabledExplicit = *PENABLEEXPLICIT;
for (auto& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
w->uncacheWindowDecos(); w->uncacheWindowDecos();
} }
for (auto& m : g_pCompositor->m_vMonitors) for (auto const& m : g_pCompositor->m_vMonitors)
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
// Update the keyboard layout to the cfg'd one if this is not the first launch // Update the keyboard layout to the cfg'd one if this is not the first launch
@@ -821,9 +850,6 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
if (!isFirstLaunch) if (!isFirstLaunch)
g_pHyprOpenGL->m_bReloadScreenShader = true; g_pHyprOpenGL->m_bReloadScreenShader = true;
if (!isFirstLaunch && *PENABLEEXPLICIT != prevEnabledExplicit)
g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0));
// parseError will be displayed next frame // parseError will be displayed next frame
if (result.error) if (result.error)
@@ -836,6 +862,8 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
else if (std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("autogenerated")) == 1) else if (std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("autogenerated")) == 1)
g_pHyprError->queueCreate("Warning: You're using an autogenerated config! (config file: " + getMainConfigPath() + " )\nSUPER+Q -> kitty\nSUPER+M -> exit Hyprland", g_pHyprError->queueCreate("Warning: You're using an autogenerated config! (config file: " + getMainConfigPath() + " )\nSUPER+Q -> kitty\nSUPER+M -> exit Hyprland",
CColor(1.0, 1.0, 70.0 / 255.0, 1.0)); CColor(1.0, 1.0, 70.0 / 255.0, 1.0));
else if (*PENABLEEXPLICIT != prevEnabledExplicit)
g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0));
else else
g_pHyprError->destroy(); g_pHyprError->destroy();
@@ -850,11 +878,34 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
ensureVRR(); ensureVRR();
} }
#ifndef NO_XWAYLAND
const auto PENABLEXWAYLAND = std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("xwayland:enabled"));
// enable/disable xwayland usage
if (!isFirstLaunch) {
bool prevEnabledXwayland = g_pCompositor->m_bEnableXwayland;
if (PENABLEXWAYLAND != prevEnabledXwayland) {
g_pCompositor->m_bEnableXwayland = PENABLEXWAYLAND;
if (PENABLEXWAYLAND) {
Debug::log(LOG, "xwayland has been enabled");
} else {
Debug::log(LOG, "xwayland has been disabled, cleaning up...");
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_pXDGSurface || !w->m_bIsX11)
continue;
g_pCompositor->closeWindow(w);
}
}
g_pXWayland = std::make_unique<CXWayland>(g_pCompositor->m_bEnableXwayland);
}
} else
g_pCompositor->m_bEnableXwayland = PENABLEXWAYLAND;
#endif
if (!isFirstLaunch && !g_pCompositor->m_bUnsafeState) if (!isFirstLaunch && !g_pCompositor->m_bUnsafeState)
refreshGroupBarGradients(); refreshGroupBarGradients();
// Updates dynamic window and workspace rules // Updates dynamic window and workspace rules
for (auto& w : g_pCompositor->m_vWorkspaces) { for (auto const& w : g_pCompositor->m_vWorkspaces) {
if (w->inert()) if (w->inert())
continue; continue;
g_pCompositor->updateWorkspaceWindows(w->m_iID); g_pCompositor->updateWorkspaceWindows(w->m_iID);
@@ -882,7 +933,7 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
Debug::coloredLogs = reinterpret_cast<int64_t* const*>(m_pConfig->getConfigValuePtr("debug:colored_stdout_logs")->getDataStaticPtr()); Debug::coloredLogs = reinterpret_cast<int64_t* const*>(m_pConfig->getConfigValuePtr("debug:colored_stdout_logs")->getDataStaticPtr());
for (auto& m : g_pCompositor->m_vMonitors) { for (auto const& m : g_pCompositor->m_vMonitors) {
// mark blur dirty // mark blur dirty
g_pHyprOpenGL->markBlurDirtyForMonitor(m.get()); g_pHyprOpenGL->markBlurDirtyForMonitor(m.get());
@@ -892,7 +943,7 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
m->forceFullFrames = 2; m->forceFullFrames = 2;
// also force mirrors, as the aspect ratio could've changed // also force mirrors, as the aspect ratio could've changed
for (auto& mirror : m->mirrors) for (auto const& mirror : m->mirrors)
mirror->forceFullFrames = 3; mirror->forceFullFrames = 3;
} }
@@ -924,14 +975,24 @@ void CConfigManager::init() {
} }
std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::string& VALUE) { std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::string& VALUE) {
const auto RET = m_pConfig->parseDynamic(COMMAND.c_str(), VALUE.c_str()); static const auto PENABLEEXPLICIT = CConfigValue<Hyprlang::INT>("render:explicit_sync");
static int prevEnabledExplicit = *PENABLEEXPLICIT;
const auto RET = m_pConfig->parseDynamic(COMMAND.c_str(), VALUE.c_str());
// invalidate layouts if they changed // invalidate layouts if they changed
if (COMMAND == "monitor" || COMMAND.contains("gaps_") || COMMAND.starts_with("dwindle:") || COMMAND.starts_with("master:")) { if (COMMAND == "monitor" || COMMAND.contains("gaps_") || COMMAND.starts_with("dwindle:") || COMMAND.starts_with("master:")) {
for (auto& m : g_pCompositor->m_vMonitors) for (auto const& m : g_pCompositor->m_vMonitors)
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
} }
if (COMMAND.contains("explicit")) {
if (*PENABLEEXPLICIT != prevEnabledExplicit)
g_pHyprError->queueCreate("Warning: You changed the render:explicit_sync option, this requires you to restart Hyprland.", CColor(0.9, 0.76, 0.221, 1.0));
else
g_pHyprError->destroy();
}
// Update window border colors // Update window border colors
g_pCompositor->updateAllWindowsAnimatedDecorationValues(); g_pCompositor->updateAllWindowsAnimatedDecorationValues();
@@ -959,7 +1020,7 @@ void CConfigManager::tick() {
bool parse = false; bool parse = false;
for (auto& cf : configPaths) { for (auto const& cf : configPaths) {
struct stat fileStat; struct stat fileStat;
int err = stat(cf.c_str(), &fileStat); int err = stat(cf.c_str(), &fileStat);
if (err != 0) { if (err != 0) {
@@ -1015,7 +1076,7 @@ std::string CConfigManager::getDeviceString(const std::string& dev, const std::s
} }
SMonitorRule CConfigManager::getMonitorRuleFor(const CMonitor& PMONITOR) { SMonitorRule CConfigManager::getMonitorRuleFor(const CMonitor& PMONITOR) {
for (auto& r : m_dMonitorRules | std::views::reverse) { for (auto const& r : m_dMonitorRules | std::views::reverse) {
if (PMONITOR.matchesStaticSelector(r.name)) { if (PMONITOR.matchesStaticSelector(r.name)) {
return r; return r;
} }
@@ -1023,7 +1084,7 @@ SMonitorRule CConfigManager::getMonitorRuleFor(const CMonitor& PMONITOR) {
Debug::log(WARN, "No rule found for {}, trying to use the first.", PMONITOR.szName); Debug::log(WARN, "No rule found for {}, trying to use the first.", PMONITOR.szName);
for (auto& r : m_dMonitorRules) { for (auto const& r : m_dMonitorRules) {
if (r.name.empty()) { if (r.name.empty()) {
return r; return r;
} }
@@ -1040,7 +1101,7 @@ SMonitorRule CConfigManager::getMonitorRuleFor(const CMonitor& PMONITOR) {
SWorkspaceRule CConfigManager::getWorkspaceRuleFor(PHLWORKSPACE pWorkspace) { SWorkspaceRule CConfigManager::getWorkspaceRuleFor(PHLWORKSPACE pWorkspace) {
SWorkspaceRule mergedRule{}; SWorkspaceRule mergedRule{};
for (auto& rule : m_dWorkspaceRules) { for (auto const& rule : m_dWorkspaceRules) {
if (!pWorkspace->matchesStaticSelector(rule.workspaceString)) if (!pWorkspace->matchesStaticSelector(rule.workspaceString))
continue; continue;
@@ -1113,7 +1174,7 @@ std::vector<SWindowRule> CConfigManager::getMatchingRules(PHLWINDOW pWindow, boo
// local tags for dynamic tag rule match // local tags for dynamic tag rule match
auto tags = pWindow->m_tags; auto tags = pWindow->m_tags;
for (auto& rule : m_dWindowRules) { for (auto const& rule : m_dWindowRules) {
// check if we have a matching rule // check if we have a matching rule
if (!rule.v2) { if (!rule.v2) {
try { try {
@@ -1193,6 +1254,32 @@ std::vector<SWindowRule> CConfigManager::getMatchingRules(PHLWINDOW pWindow, boo
continue; continue;
} }
if (!rule.szFullscreenState.empty()) {
const auto ARGS = CVarList(rule.szFullscreenState, 2, ' ');
//
std::optional<eFullscreenMode> internalMode, clientMode;
if (ARGS[0] == "*")
internalMode = std::nullopt;
else if (isNumber(ARGS[0]))
internalMode = (eFullscreenMode)std::stoi(ARGS[0]);
else
throw std::runtime_error("szFullscreenState internal mode not valid");
if (ARGS[1] == "*")
clientMode = std::nullopt;
else if (isNumber(ARGS[1]))
clientMode = (eFullscreenMode)std::stoi(ARGS[1]);
else
throw std::runtime_error("szFullscreenState client mode not valid");
if (internalMode.has_value() && pWindow->m_sFullscreenState.internal != internalMode)
continue;
if (clientMode.has_value() && pWindow->m_sFullscreenState.client != clientMode)
continue;
}
if (!rule.szOnWorkspace.empty()) { if (!rule.szOnWorkspace.empty()) {
const auto PWORKSPACE = pWindow->m_pWorkspace; const auto PWORKSPACE = pWindow->m_pWorkspace;
if (!PWORKSPACE || !PWORKSPACE->matchesStaticSelector(rule.szOnWorkspace)) if (!PWORKSPACE || !PWORKSPACE->matchesStaticSelector(rule.szOnWorkspace))
@@ -1252,7 +1339,7 @@ std::vector<SWindowRule> CConfigManager::getMatchingRules(PHLWINDOW pWindow, boo
bool anyExecFound = false; bool anyExecFound = false;
for (auto& er : execRequestedRules) { for (auto const& er : execRequestedRules) {
if (std::ranges::any_of(PIDs, [&](const auto& pid) { return pid == er.iPid; })) { if (std::ranges::any_of(PIDs, [&](const auto& pid) { return pid == er.iPid; })) {
returns.push_back({er.szRule, "execRule"}); returns.push_back({er.szRule, "execRule"});
anyExecFound = true; anyExecFound = true;
@@ -1272,7 +1359,7 @@ std::vector<SLayerRule> CConfigManager::getMatchingRules(PHLLS pLS) {
if (!pLS->layerSurface || pLS->fadingOut) if (!pLS->layerSurface || pLS->fadingOut)
return returns; return returns;
for (auto& lr : m_dLayerRules) { for (auto const& lr : m_dLayerRules) {
if (lr.targetNamespace.starts_with("address:0x")) { if (lr.targetNamespace.starts_with("address:0x")) {
if (std::format("address:0x{:x}", (uintptr_t)pLS.get()) != lr.targetNamespace) if (std::format("address:0x{:x}", (uintptr_t)pLS.get()) != lr.targetNamespace)
continue; continue;
@@ -1309,7 +1396,7 @@ void CConfigManager::dispatchExecOnce() {
firstExecDispatched = true; firstExecDispatched = true;
isLaunchingExecOnce = true; isLaunchingExecOnce = true;
for (auto& c : firstExecRequests) { for (auto const& c : firstExecRequests) {
handleRawExec("", c); handleRawExec("", c);
} }
@@ -1326,6 +1413,24 @@ void CConfigManager::dispatchExecOnce() {
g_pCompositor->performUserChecks(); g_pCompositor->performUserChecks();
} }
void CConfigManager::dispatchExecShutdown() {
if (finalExecRequests.empty()) {
g_pCompositor->m_bFinalRequests = false;
return;
}
g_pCompositor->m_bFinalRequests = true;
for (auto const& c : finalExecRequests) {
handleExecShutdown("", c);
}
finalExecRequests.clear();
// Actually exit now
handleExecShutdown("", "hyprctl dispatch exit");
}
void CConfigManager::appendMonitorRule(const SMonitorRule& r) { void CConfigManager::appendMonitorRule(const SMonitorRule& r) {
m_dMonitorRules.emplace_back(r); m_dMonitorRules.emplace_back(r);
} }
@@ -1346,7 +1451,7 @@ void CConfigManager::performMonitorReload() {
bool overAgain = false; bool overAgain = false;
for (auto& m : g_pCompositor->m_vRealMonitors) { for (auto const& m : g_pCompositor->m_vRealMonitors) {
if (!m->output || m->isUnsafeFallback) if (!m->output || m->isUnsafeFallback)
continue; continue;
@@ -1393,7 +1498,7 @@ bool CConfigManager::deviceConfigExists(const std::string& dev) {
} }
bool CConfigManager::shouldBlurLS(const std::string& ns) { bool CConfigManager::shouldBlurLS(const std::string& ns) {
for (auto& bls : m_dBlurLSNamespaces) { for (auto const& bls : m_dBlurLSNamespaces) {
if (bls == ns) { if (bls == ns) {
return true; return true;
} }
@@ -1403,7 +1508,7 @@ bool CConfigManager::shouldBlurLS(const std::string& ns) {
} }
void CConfigManager::ensureMonitorStatus() { void CConfigManager::ensureMonitorStatus() {
for (auto& rm : g_pCompositor->m_vRealMonitors) { for (auto const& rm : g_pCompositor->m_vRealMonitors) {
if (!rm->output || rm->isUnsafeFallback) if (!rm->output || rm->isUnsafeFallback)
continue; continue;
@@ -1486,7 +1591,7 @@ void CConfigManager::ensureVRR(CMonitor* pMonitor) {
return; return;
} }
for (auto& m : g_pCompositor->m_vMonitors) { for (auto const& m : g_pCompositor->m_vMonitors) {
ensureVRRForDisplay(m.get()); ensureVRRForDisplay(m.get());
} }
} }
@@ -1508,7 +1613,7 @@ CMonitor* CConfigManager::getBoundMonitorForWS(const std::string& wsname) {
} }
std::string CConfigManager::getBoundMonitorStringForWS(const std::string& wsname) { std::string CConfigManager::getBoundMonitorStringForWS(const std::string& wsname) {
for (auto& wr : m_dWorkspaceRules) { for (auto const& wr : m_dWorkspaceRules) {
const auto WSNAME = wr.workspaceName.starts_with("name:") ? wr.workspaceName.substr(5) : wr.workspaceName; const auto WSNAME = wr.workspaceName.starts_with("name:") ? wr.workspaceName.substr(5) : wr.workspaceName;
if (WSNAME == wsname) if (WSNAME == wsname)
@@ -1579,7 +1684,7 @@ void CConfigManager::addPluginKeyword(HANDLE handle, const std::string& name, Hy
} }
void CConfigManager::removePluginConfig(HANDLE handle) { void CConfigManager::removePluginConfig(HANDLE handle) {
for (auto& k : pluginKeywords) { for (auto const& k : pluginKeywords) {
if (k.handle != handle) if (k.handle != handle)
continue; continue;
@@ -1587,7 +1692,7 @@ void CConfigManager::removePluginConfig(HANDLE handle) {
} }
std::erase_if(pluginKeywords, [&](const auto& other) { return other.handle == handle; }); std::erase_if(pluginKeywords, [&](const auto& other) { return other.handle == handle; });
for (auto& [h, n] : pluginVariables) { for (auto const& [h, n] : pluginVariables) {
if (h != handle) if (h != handle)
continue; continue;
@@ -1602,7 +1707,7 @@ std::string CConfigManager::getDefaultWorkspaceFor(const std::string& name) {
if (other->monitor == name) if (other->monitor == name)
return other->workspaceString; return other->workspaceString;
if (other->monitor.substr(0, 5) == "desc:") { if (other->monitor.substr(0, 5) == "desc:") {
auto monitor = g_pCompositor->getMonitorFromDesc(other->monitor.substr(5)); auto const monitor = g_pCompositor->getMonitorFromDesc(other->monitor.substr(5));
if (monitor && monitor->szName == name) if (monitor && monitor->szName == name)
return other->workspaceString; return other->workspaceString;
} }
@@ -1628,6 +1733,16 @@ std::optional<std::string> CConfigManager::handleExecOnce(const std::string& com
return {}; return {};
} }
std::optional<std::string> CConfigManager::handleExecShutdown(const std::string& command, const std::string& args) {
if (g_pCompositor->m_bFinalRequests) {
g_pKeybindManager->spawn(args);
return {};
}
finalExecRequests.push_back(args);
return {};
}
static bool parseModeLine(const std::string& modeline, drmModeModeInfo& mode) { static bool parseModeLine(const std::string& modeline, drmModeModeInfo& mode) {
auto args = CVarList(modeline, 0, 's'); auto args = CVarList(modeline, 0, 's');
@@ -1675,7 +1790,7 @@ static bool parseModeLine(const std::string& modeline, drmModeModeInfo& mode) {
if (it != flagsmap.end()) if (it != flagsmap.end())
mode.flags |= it->second; mode.flags |= it->second;
else else
Debug::log(ERR, "invalid flag {} in modeline", it->first); Debug::log(ERR, "invalid flag {} in modeline", key);
} }
snprintf(mode.name, sizeof(mode.name), "%dx%d@%d", mode.hdisplay, mode.vdisplay, mode.vrefresh / 1000); snprintf(mode.name, sizeof(mode.name), "%dx%d@%d", mode.hdisplay, mode.vdisplay, mode.vrefresh / 1000);
@@ -1999,7 +2114,7 @@ std::optional<std::string> CConfigManager::handleBind(const std::string& command
bool dontInhibit = false; bool dontInhibit = false;
const auto BINDARGS = command.substr(4); const auto BINDARGS = command.substr(4);
for (auto& arg : BINDARGS) { for (auto const& arg : BINDARGS) {
if (arg == 'l') { if (arg == 'l') {
locked = true; locked = true;
} else if (arg == 'r') { } else if (arg == 'r') {
@@ -2110,7 +2225,7 @@ std::optional<std::string> CConfigManager::handleUnbind(const std::string& comma
bool windowRuleValid(const std::string& RULE) { bool windowRuleValid(const std::string& RULE) {
static const auto rules = std::unordered_set<std::string>{ static const auto rules = std::unordered_set<std::string>{
"float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", "float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", "renderunfocused",
}; };
static const auto rulesPrefix = std::vector<std::string>{ static const auto rulesPrefix = std::vector<std::string>{
"animation", "bordercolor", "bordersize", "center", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor", "animation", "bordercolor", "bordersize", "center", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor",
@@ -2125,7 +2240,7 @@ bool windowRuleValid(const std::string& RULE) {
bool layerRuleValid(const std::string& RULE) { bool layerRuleValid(const std::string& RULE) {
static const auto rules = std::unordered_set<std::string>{"noanim", "blur", "blurpopups", "dimaround"}; static const auto rules = std::unordered_set<std::string>{"noanim", "blur", "blurpopups", "dimaround"};
static const auto rulesPrefix = std::vector<std::string>{"ignorealpha", "ignorezero", "xray", "animation"}; static const auto rulesPrefix = std::vector<std::string>{"ignorealpha", "ignorezero", "xray", "animation", "order"};
return rules.contains(RULE) || std::any_of(rulesPrefix.begin(), rulesPrefix.end(), [&RULE](auto prefix) { return RULE.starts_with(prefix); }); return rules.contains(RULE) || std::any_of(rulesPrefix.begin(), rulesPrefix.end(), [&RULE](auto prefix) { return RULE.starts_with(prefix); });
} }
@@ -2177,9 +2292,9 @@ std::optional<std::string> CConfigManager::handleLayerRule(const std::string& co
m_dLayerRules.push_back({VALUE, RULE}); m_dLayerRules.push_back({VALUE, RULE});
for (auto& m : g_pCompositor->m_vMonitors) for (auto const& m : g_pCompositor->m_vMonitors)
for (auto& lsl : m->m_aLayerSurfaceLayers) for (auto const& lsl : m->m_aLayerSurfaceLayers)
for (auto& ls : lsl) for (auto const& ls : lsl)
ls->applyRules(); ls->applyRules();
return {}; return {};
@@ -2200,17 +2315,18 @@ std::optional<std::string> CConfigManager::handleWindowRuleV2(const std::string&
rule.szRule = RULE; rule.szRule = RULE;
rule.szValue = VALUE; rule.szValue = VALUE;
const auto TAGPOS = VALUE.find("tag:"); const auto TAGPOS = VALUE.find("tag:");
const auto TITLEPOS = VALUE.find("title:"); const auto TITLEPOS = VALUE.find("title:");
const auto CLASSPOS = VALUE.find("class:"); const auto CLASSPOS = VALUE.find("class:");
const auto INITIALTITLEPOS = VALUE.find("initialTitle:"); const auto INITIALTITLEPOS = VALUE.find("initialTitle:");
const auto INITIALCLASSPOS = VALUE.find("initialClass:"); const auto INITIALCLASSPOS = VALUE.find("initialClass:");
const auto X11POS = VALUE.find("xwayland:"); const auto X11POS = VALUE.find("xwayland:");
const auto FLOATPOS = VALUE.find("floating:"); const auto FLOATPOS = VALUE.find("floating:");
const auto FULLSCREENPOS = VALUE.find("fullscreen:"); const auto FULLSCREENPOS = VALUE.find("fullscreen:");
const auto PINNEDPOS = VALUE.find("pinned:"); const auto PINNEDPOS = VALUE.find("pinned:");
const auto FOCUSPOS = VALUE.find("focus:"); const auto FOCUSPOS = VALUE.find("focus:");
const auto ONWORKSPACEPOS = VALUE.find("onworkspace:"); const auto FULLSCREENSTATEPOS = VALUE.find("fullscreenstate:");
const auto ONWORKSPACEPOS = VALUE.find("onworkspace:");
// find workspacepos that isn't onworkspacepos // find workspacepos that isn't onworkspacepos
size_t WORKSPACEPOS = std::string::npos; size_t WORKSPACEPOS = std::string::npos;
@@ -2223,9 +2339,8 @@ std::optional<std::string> CConfigManager::handleWindowRuleV2(const std::string&
currentPos = VALUE.find("workspace:", currentPos + 1); currentPos = VALUE.find("workspace:", currentPos + 1);
} }
const auto checkPos = std::unordered_set{ const auto checkPos = std::unordered_set{TAGPOS, TITLEPOS, CLASSPOS, INITIALTITLEPOS, INITIALCLASSPOS, X11POS, FLOATPOS,
TAGPOS, TITLEPOS, CLASSPOS, INITIALTITLEPOS, INITIALCLASSPOS, X11POS, FLOATPOS, FULLSCREENPOS, PINNEDPOS, WORKSPACEPOS, FOCUSPOS, ONWORKSPACEPOS, FULLSCREENPOS, PINNEDPOS, FULLSCREENSTATEPOS, WORKSPACEPOS, FOCUSPOS, ONWORKSPACEPOS};
};
if (checkPos.size() == 1 && checkPos.contains(std::string::npos)) { if (checkPos.size() == 1 && checkPos.contains(std::string::npos)) {
Debug::log(ERR, "Invalid rulev2 syntax: {}", VALUE); Debug::log(ERR, "Invalid rulev2 syntax: {}", VALUE);
return "Invalid rulev2 syntax: " + VALUE; return "Invalid rulev2 syntax: " + VALUE;
@@ -2254,6 +2369,8 @@ std::optional<std::string> CConfigManager::handleWindowRuleV2(const std::string&
min = FULLSCREENPOS; min = FULLSCREENPOS;
if (PINNEDPOS > pos && PINNEDPOS < min) if (PINNEDPOS > pos && PINNEDPOS < min)
min = PINNEDPOS; min = PINNEDPOS;
if (FULLSCREENSTATEPOS > pos && FULLSCREENSTATEPOS < min)
min = FULLSCREENSTATEPOS;
if (ONWORKSPACEPOS > pos && ONWORKSPACEPOS < min) if (ONWORKSPACEPOS > pos && ONWORKSPACEPOS < min)
min = ONWORKSPACEPOS; min = ONWORKSPACEPOS;
if (WORKSPACEPOS > pos && WORKSPACEPOS < min) if (WORKSPACEPOS > pos && WORKSPACEPOS < min)
@@ -2298,6 +2415,9 @@ std::optional<std::string> CConfigManager::handleWindowRuleV2(const std::string&
if (PINNEDPOS != std::string::npos) if (PINNEDPOS != std::string::npos)
rule.bPinned = extract(PINNEDPOS + 7) == "1" ? 1 : 0; rule.bPinned = extract(PINNEDPOS + 7) == "1" ? 1 : 0;
if (FULLSCREENSTATEPOS != std::string::npos)
rule.szFullscreenState = extract(FULLSCREENSTATEPOS + 16);
if (WORKSPACEPOS != std::string::npos) if (WORKSPACEPOS != std::string::npos)
rule.szWorkspace = extract(WORKSPACEPOS + 10); rule.szWorkspace = extract(WORKSPACEPOS + 10);
@@ -2339,6 +2459,9 @@ std::optional<std::string> CConfigManager::handleWindowRuleV2(const std::string&
if (rule.bPinned != -1 && rule.bPinned != other.bPinned) if (rule.bPinned != -1 && rule.bPinned != other.bPinned)
return false; return false;
if (!rule.szFullscreenState.empty() && rule.szFullscreenState != other.szFullscreenState)
return false;
if (!rule.szWorkspace.empty() && rule.szWorkspace != other.szWorkspace) if (!rule.szWorkspace.empty() && rule.szWorkspace != other.szWorkspace)
return false; return false;
@@ -2370,9 +2493,9 @@ void CConfigManager::updateBlurredLS(const std::string& name, const bool forceBl
matchName = matchName.substr(8); matchName = matchName.substr(8);
} }
for (auto& m : g_pCompositor->m_vMonitors) { for (auto const& m : g_pCompositor->m_vMonitors) {
for (auto& lsl : m->m_aLayerSurfaceLayers) { for (auto const& lsl : m->m_aLayerSurfaceLayers) {
for (auto& ls : lsl) { for (auto const& ls : lsl) {
if (BYADDRESS) { if (BYADDRESS) {
if (std::format("0x{:x}", (uintptr_t)ls.get()) == matchName) if (std::format("0x{:x}", (uintptr_t)ls.get()) == matchName)
ls->forceBlur = forceBlur; ls->forceBlur = forceBlur;
@@ -2425,7 +2548,7 @@ std::optional<std::string> CConfigManager::handleWorkspaceRules(const std::strin
// } // }
const static std::string ruleOnCreatedEmpty = "on-created-empty:"; const static std::string ruleOnCreatedEmpty = "on-created-empty:";
const static int ruleOnCreatedEmptyLen = ruleOnCreatedEmpty.length(); const static auto ruleOnCreatedEmptyLen = ruleOnCreatedEmpty.length();
auto assignRule = [&](std::string rule) -> std::optional<std::string> { auto assignRule = [&](std::string rule) -> std::optional<std::string> {
size_t delim = std::string::npos; size_t delim = std::string::npos;
@@ -2481,7 +2604,7 @@ std::optional<std::string> CConfigManager::handleWorkspaceRules(const std::strin
}; };
CVarList rulesList{rules, 0, ',', true}; CVarList rulesList{rules, 0, ',', true};
for (auto& r : rulesList) { for (auto const& r : rulesList) {
const auto R = assignRule(r); const auto R = assignRule(r);
if (R.has_value()) if (R.has_value())
return R; return R;
@@ -2597,3 +2720,60 @@ std::optional<std::string> CConfigManager::handlePlugin(const std::string& comma
return {}; return {};
} }
const std::vector<SConfigOptionDescription>& CConfigManager::getAllDescriptions() {
return CONFIG_OPTIONS;
}
std::string SConfigOptionDescription::jsonify() const {
auto parseData = [this]() -> std::string {
return std::visit(
[](auto&& val) {
using T = std::decay_t<decltype(val)>;
if constexpr (std::is_same_v<T, SStringData>) {
return std::format(R"#( "value": "{}")#", val.value);
} else if constexpr (std::is_same_v<T, SRangeData>) {
return std::format(R"#( "value": {},
"min": {},
"max": {})#",
val.value, val.min, val.max);
} else if constexpr (std::is_same_v<T, SFloatData>) {
return std::format(R"#( "value": {},
"min": {},
"max": {})#",
val.value, val.min, val.max);
} else if constexpr (std::is_same_v<T, SColorData>) {
return std::format(R"#( "value": {})#", val.color.getAsHex());
} else if constexpr (std::is_same_v<T, SBoolData>) {
return std::format(R"#( "value": {})#", val.value);
} else if constexpr (std::is_same_v<T, SChoiceData>) {
return std::format(R"#( "value": {})#", val.choices);
} else if constexpr (std::is_same_v<T, SVectorData>) {
return std::format(R"#( "x": {},
"y": {},
"min_x": {},
"min_y": {},
"max_x": {},
"max_y": {})#",
val.vec.x, val.vec.y, val.min.x, val.min.y, val.max.x, val.max.y);
} else if constexpr (std::is_same_v<T, SGradientData>) {
return std::format(R"#( "value": "{}")#", val.gradient);
}
return std::string{""};
},
data);
};
std::string json = std::format(R"#({{
"value": "{}",
"description": "{}",
"type": {},
"flags": {},
"data": {{
{}
}}
}})#",
value, description, (uint16_t)type, (uint32_t)flags, parseData());
return json;
}

View File

@@ -6,6 +6,7 @@
#include "../debug/Log.hpp" #include "../debug/Log.hpp"
#include <unordered_map> #include <unordered_map>
#include "../defines.hpp" #include "../defines.hpp"
#include <variant>
#include <vector> #include <vector>
#include <deque> #include <deque>
#include <algorithm> #include <algorithm>
@@ -33,7 +34,7 @@ struct SWorkspaceRule {
std::string monitor = ""; std::string monitor = "";
std::string workspaceString = ""; std::string workspaceString = "";
std::string workspaceName = ""; std::string workspaceName = "";
int workspaceId = -1; WORKSPACEID workspaceId = -1;
bool isDefault = false; bool isDefault = false;
bool isPersistent = false; bool isPersistent = false;
std::optional<CCssGapData> gapsIn; std::optional<CCssGapData> gapsIn;
@@ -83,6 +84,70 @@ struct SExecRequestedRule {
uint64_t iPid = 0; uint64_t iPid = 0;
}; };
enum eConfigOptionType : uint16_t {
CONFIG_OPTION_BOOL = 0,
CONFIG_OPTION_INT = 1, /* e.g. 0/1/2*/
CONFIG_OPTION_FLOAT = 2,
CONFIG_OPTION_STRING_SHORT = 3, /* e.g. "auto" */
CONFIG_OPTION_STRING_LONG = 4, /* e.g. a command */
CONFIG_OPTION_COLOR = 5,
CONFIG_OPTION_CHOICE = 6, /* e.g. "one", "two", "three" */
CONFIG_OPTION_GRADIENT = 7,
CONFIG_OPTION_VECTOR = 8,
};
enum eConfigOptionFlags : uint32_t {
CONFIG_OPTION_FLAG_PERCENTAGE = (1 << 0),
};
struct SConfigOptionDescription {
struct SBoolData {
bool value = false;
};
struct SRangeData {
int value = 0, min = 0, max = 2;
};
struct SFloatData {
float value = 0, min = 0, max = 100;
};
struct SStringData {
std::string value;
};
struct SColorData {
CColor color;
};
struct SChoiceData {
int firstIndex = 0;
std::string choices; // comma-separated
};
struct SGradientData {
std::string gradient;
};
struct SVectorData {
Vector2D vec, min, max;
};
std::string value; // e.g. general:gaps_in
std::string description;
std::string specialCategory; // if value is special (e.g. device:abc) value will be abc and special device
bool specialKey = false;
eConfigOptionType type = CONFIG_OPTION_BOOL;
uint32_t flags = 0; // eConfigOptionFlags
std::string jsonify() const;
//
std::variant<SBoolData, SRangeData, SFloatData, SStringData, SColorData, SChoiceData, SGradientData, SVectorData> data;
};
class CConfigManager { class CConfigManager {
public: public:
CConfigManager(); CConfigManager();
@@ -115,6 +180,8 @@ class CConfigManager {
std::vector<SWindowRule> getMatchingRules(PHLWINDOW, bool dynamic = true, bool shadowExec = false); std::vector<SWindowRule> getMatchingRules(PHLWINDOW, bool dynamic = true, bool shadowExec = false);
std::vector<SLayerRule> getMatchingRules(PHLLS); std::vector<SLayerRule> getMatchingRules(PHLLS);
const std::vector<SConfigOptionDescription>& getAllDescriptions();
std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas; std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas;
std::unordered_map<std::string, SAnimationPropertyConfig> getAnimationConfig(); std::unordered_map<std::string, SAnimationPropertyConfig> getAnimationConfig();
@@ -125,6 +192,7 @@ class CConfigManager {
// no-op when done. // no-op when done.
void dispatchExecOnce(); void dispatchExecOnce();
void dispatchExecShutdown();
void performMonitorReload(); void performMonitorReload();
void appendMonitorRule(const SMonitorRule&); void appendMonitorRule(const SMonitorRule&);
@@ -146,6 +214,7 @@ class CConfigManager {
// keywords // keywords
std::optional<std::string> handleRawExec(const std::string&, const std::string&); std::optional<std::string> handleRawExec(const std::string&, const std::string&);
std::optional<std::string> handleExecOnce(const std::string&, const std::string&); std::optional<std::string> handleExecOnce(const std::string&, const std::string&);
std::optional<std::string> handleExecShutdown(const std::string&, const std::string&);
std::optional<std::string> handleMonitor(const std::string&, const std::string&); std::optional<std::string> handleMonitor(const std::string&, const std::string&);
std::optional<std::string> handleBind(const std::string&, const std::string&); std::optional<std::string> handleBind(const std::string&, const std::string&);
std::optional<std::string> handleUnbind(const std::string&, const std::string&); std::optional<std::string> handleUnbind(const std::string&, const std::string&);
@@ -222,6 +291,7 @@ class CConfigManager {
bool firstExecDispatched = false; bool firstExecDispatched = false;
bool m_bManualCrashInitiated = false; bool m_bManualCrashInitiated = false;
std::deque<std::string> firstExecRequests; std::deque<std::string> firstExecRequests;
std::deque<std::string> finalExecRequests;
std::vector<std::pair<std::string, std::string>> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins std::vector<std::pair<std::string, std::string>> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins
std::string m_szConfigErrors = ""; std::string m_szConfigErrors = "";

View File

@@ -72,7 +72,7 @@ env = HYPRCURSOR_SIZE,24
# Refer to https://wiki.hyprland.org/Configuring/Variables/ # Refer to https://wiki.hyprland.org/Configuring/Variables/
# https://wiki.hyprland.org/Configuring/Variables/#general # https://wiki.hyprland.org/Configuring/Variables/#general
general { general {
gaps_in = 5 gaps_in = 5
gaps_out = 20 gaps_out = 20
@@ -83,7 +83,7 @@ general {
col.inactive_border = rgba(595959aa) col.inactive_border = rgba(595959aa)
# Set to true enable resizing windows by clicking and dragging on borders and gaps # Set to true enable resizing windows by clicking and dragging on borders and gaps
resize_on_border = false resize_on_border = false
# Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on # Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
allow_tearing = false allow_tearing = false
@@ -109,7 +109,7 @@ decoration {
enabled = true enabled = true
size = 3 size = 3
passes = 1 passes = 1
vibrancy = 0.1696 vibrancy = 0.1696
} }
} }
@@ -142,7 +142,7 @@ master {
} }
# https://wiki.hyprland.org/Configuring/Variables/#misc # https://wiki.hyprland.org/Configuring/Variables/#misc
misc { misc {
force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers
disable_hyprland_logo = false # If true disables the random hyprland logo / anime girl background. :( disable_hyprland_logo = false # If true disables the random hyprland logo / anime girl background. :(
} }
@@ -182,9 +182,9 @@ device {
} }
#################### ###################
### KEYBINDINGSS ### ### KEYBINDINGS ###
#################### ###################
# See https://wiki.hyprland.org/Configuring/Keywords/ # See https://wiki.hyprland.org/Configuring/Keywords/
$mainMod = SUPER # Sets "Windows" key as main modifier $mainMod = SUPER # Sets "Windows" key as main modifier
@@ -241,6 +241,19 @@ bind = $mainMod, mouse_up, workspace, e-1
bindm = $mainMod, mouse:272, movewindow bindm = $mainMod, mouse:272, movewindow
bindm = $mainMod, mouse:273, resizewindow bindm = $mainMod, mouse:273, resizewindow
# Laptop multimedia keys for volume and LCD brightness
bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+
bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+
bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%-
# Requires playerctl
bindl = , XF86AudioNext, exec, playerctl next
bindl = , XF86AudioPause, exec, playerctl play-pause
bindl = , XF86AudioPlay, exec, playerctl play-pause
bindl = , XF86AudioPrev, exec, playerctl previous
############################## ##############################
### WINDOWS AND WORKSPACES ### ### WINDOWS AND WORKSPACES ###

View File

@@ -86,7 +86,7 @@ void CrashReporter::createAndSaveCrash(int sig) {
stderr.flush(); stderr.flush();
} }
reportFd = open(reportPath.get_str(), O_WRONLY | O_CREAT, S_IRWXU); reportFd = open(reportPath.get_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
if (reportFd < 0) { if (reportFd < 0) {
exit_with_error("Failed to open crash report path for writing"); exit_with_error("Failed to open crash report path for writing");
} }

View File

@@ -57,7 +57,7 @@ static std::string formatToString(uint32_t drmFormat) {
static std::string availableModesForOutput(CMonitor* pMonitor, eHyprCtlOutputFormat format) { static std::string availableModesForOutput(CMonitor* pMonitor, eHyprCtlOutputFormat format) {
std::string result; std::string result;
for (auto& m : pMonitor->output->modes) { for (auto const& m : pMonitor->output->modes) {
if (format == FORMAT_NORMAL) if (format == FORMAT_NORMAL)
result += std::format("{}x{}@{:.2f}Hz ", m->pixelSize.x, m->pixelSize.y, m->refreshRate / 1000.0); result += std::format("{}x{}@{:.2f}Hz ", m->pixelSize.x, m->pixelSize.y, m->refreshRate / 1000.0);
else else
@@ -71,7 +71,7 @@ static std::string availableModesForOutput(CMonitor* pMonitor, eHyprCtlOutputFor
std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer<CMonitor> m, eHyprCtlOutputFormat format) { std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer<CMonitor> m, eHyprCtlOutputFormat format) {
std::string result; std::string result;
if (!m->output || m->ID == -1ull) if (!m->output || m->ID == -1)
return ""; return "";
if (format == eHyprCtlOutputFormat::FORMAT_JSON) { if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
@@ -146,7 +146,7 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) {
if (format == eHyprCtlOutputFormat::FORMAT_JSON) { if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
result += "["; result += "[";
for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) { for (auto const& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) {
result += CHyprCtl::getMonitorData(m, format); result += CHyprCtl::getMonitorData(m, format);
} }
@@ -154,20 +154,20 @@ std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) {
result += "]"; result += "]";
} else { } else {
for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) { for (auto const& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) {
if (!m->output || m->ID == -1ull) if (!m->output || m->ID == -1)
continue; continue;
result += result += std::format(
std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t" "Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\t"
"special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t" "special workspace: {} ({})\n\treserved: {} {} {} {}\n\tscale: {:.2f}\n\ttransform: {}\n\tfocused: {}\n\t"
"dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: {}\n\tavailableModes: {}\n\n", "dpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\tdisabled: {}\n\tcurrentFormat: A {} H {}\n\tavailableModes: {}\n\n",
m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription, m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szShortDescription,
m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName), m->output->make, m->output->model, m->output->serial, m->activeWorkspaceID(), (!m->activeWorkspace ? "" : m->activeWorkspace->m_szName),
m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, m->activeSpecialWorkspaceID(), (m->activeSpecialWorkspace ? m->activeSpecialWorkspace->m_szName : ""), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y,
(int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m == g_pCompositor->m_pLastMonitor ? "yes" : "no"),
(m == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, (int)(m->output->state ? m->output->state->state().adaptiveSync : false), (int)m->dpmsStatus, (int)(m->output->state ? m->output->state->state().adaptiveSync : false), m->tearingState.activelyTearing, !m->m_bEnabled,
m->tearingState.activelyTearing, !m->m_bEnabled, formatToString(m->output->state->state().drmFormat), availableModesForOutput(m.get(), format)); formatToString(m->output->state->state().drmFormat), formatToString(m->drmFormat), availableModesForOutput(m.get(), format));
} }
} }
@@ -272,7 +272,7 @@ std::string clientsRequest(eHyprCtlOutputFormat format, std::string request) {
if (format == eHyprCtlOutputFormat::FORMAT_JSON) { if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
result += "["; result += "[";
for (auto& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped && !g_pHyprCtl->m_sCurrentRequestParams.all) if (!w->m_bIsMapped && !g_pHyprCtl->m_sCurrentRequestParams.all)
continue; continue;
@@ -283,7 +283,7 @@ std::string clientsRequest(eHyprCtlOutputFormat format, std::string request) {
result += "]"; result += "]";
} else { } else {
for (auto& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped && !g_pHyprCtl->m_sCurrentRequestParams.all) if (!w->m_bIsMapped && !g_pHyprCtl->m_sCurrentRequestParams.all)
continue; continue;
@@ -381,7 +381,7 @@ std::string workspacesRequest(eHyprCtlOutputFormat format, std::string request)
if (format == eHyprCtlOutputFormat::FORMAT_JSON) { if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
result += "["; result += "[";
for (auto& w : g_pCompositor->m_vWorkspaces) { for (auto const& w : g_pCompositor->m_vWorkspaces) {
result += CHyprCtl::getWorkspaceData(w, format); result += CHyprCtl::getWorkspaceData(w, format);
result += ","; result += ",";
} }
@@ -389,7 +389,7 @@ std::string workspacesRequest(eHyprCtlOutputFormat format, std::string request)
trimTrailingComma(result); trimTrailingComma(result);
result += "]"; result += "]";
} else { } else {
for (auto& w : g_pCompositor->m_vWorkspaces) { for (auto const& w : g_pCompositor->m_vWorkspaces) {
result += CHyprCtl::getWorkspaceData(w, format); result += CHyprCtl::getWorkspaceData(w, format);
} }
} }
@@ -401,7 +401,7 @@ std::string workspaceRulesRequest(eHyprCtlOutputFormat format, std::string reque
std::string result = ""; std::string result = "";
if (format == eHyprCtlOutputFormat::FORMAT_JSON) { if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
result += "["; result += "[";
for (auto& r : g_pConfigManager->getAllWorkspaceRules()) { for (auto const& r : g_pConfigManager->getAllWorkspaceRules()) {
result += getWorkspaceRuleData(r, format); result += getWorkspaceRuleData(r, format);
result += ","; result += ",";
} }
@@ -409,7 +409,7 @@ std::string workspaceRulesRequest(eHyprCtlOutputFormat format, std::string reque
trimTrailingComma(result); trimTrailingComma(result);
result += "]"; result += "]";
} else { } else {
for (auto& r : g_pConfigManager->getAllWorkspaceRules()) { for (auto const& r : g_pConfigManager->getAllWorkspaceRules()) {
result += getWorkspaceRuleData(r, format); result += getWorkspaceRuleData(r, format);
} }
} }
@@ -437,7 +437,7 @@ std::string layersRequest(eHyprCtlOutputFormat format, std::string request) {
if (format == eHyprCtlOutputFormat::FORMAT_JSON) { if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
result += "{\n"; result += "{\n";
for (auto& mon : g_pCompositor->m_vMonitors) { for (auto const& mon : g_pCompositor->m_vMonitors) {
result += std::format( result += std::format(
R"#("{}": {{ R"#("{}": {{
"levels": {{ "levels": {{
@@ -445,13 +445,13 @@ std::string layersRequest(eHyprCtlOutputFormat format, std::string request) {
escapeJSONStrings(mon->szName)); escapeJSONStrings(mon->szName));
int layerLevel = 0; int layerLevel = 0;
for (auto& level : mon->m_aLayerSurfaceLayers) { for (auto const& level : mon->m_aLayerSurfaceLayers) {
result += std::format( result += std::format(
R"#( R"#(
"{}": [ "{}": [
)#", )#",
layerLevel); layerLevel);
for (auto& layer : level) { for (auto const& layer : level) {
result += std::format( result += std::format(
R"#( {{ R"#( {{
"address": "0x{:x}", "address": "0x{:x}",
@@ -484,14 +484,14 @@ std::string layersRequest(eHyprCtlOutputFormat format, std::string request) {
result += "\n}\n"; result += "\n}\n";
} else { } else {
for (auto& mon : g_pCompositor->m_vMonitors) { for (auto const& mon : g_pCompositor->m_vMonitors) {
result += std::format("Monitor {}:\n", mon->szName); result += std::format("Monitor {}:\n", mon->szName);
int layerLevel = 0; int layerLevel = 0;
static const std::array<std::string, 4> levelNames = {"background", "bottom", "top", "overlay"}; static const std::array<std::string, 4> levelNames = {"background", "bottom", "top", "overlay"};
for (auto& level : mon->m_aLayerSurfaceLayers) { for (auto const& level : mon->m_aLayerSurfaceLayers) {
result += std::format("\tLayer level {} ({}):\n", layerLevel, levelNames[layerLevel]); result += std::format("\tLayer level {} ({}):\n", layerLevel, levelNames[layerLevel]);
for (auto& layer : level) { for (auto const& layer : level) {
result += std::format("\t\tLayer {:x}: xywh: {} {} {} {}, namespace: {}\n", (uintptr_t)layer.get(), layer->geometry.x, layer->geometry.y, layer->geometry.width, result += std::format("\t\tLayer {:x}: xywh: {} {} {} {}, namespace: {}\n", (uintptr_t)layer.get(), layer->geometry.x, layer->geometry.y, layer->geometry.width,
layer->geometry.height, layer->szNamespace); layer->geometry.height, layer->szNamespace);
} }
@@ -510,7 +510,7 @@ std::string layoutsRequest(eHyprCtlOutputFormat format, std::string request) {
if (format == eHyprCtlOutputFormat::FORMAT_JSON) { if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
result += "["; result += "[";
for (auto& m : g_pLayoutManager->getAllLayoutNames()) { for (auto const& m : g_pLayoutManager->getAllLayoutNames()) {
result += std::format( result += std::format(
R"#( R"#(
"{}",)#", "{}",)#",
@@ -520,7 +520,7 @@ std::string layoutsRequest(eHyprCtlOutputFormat format, std::string request) {
result += "\n]\n"; result += "\n]\n";
} else { } else {
for (auto& m : g_pLayoutManager->getAllLayoutNames()) { for (auto const& m : g_pLayoutManager->getAllLayoutNames()) {
result += std::format("{}\n", m); result += std::format("{}\n", m);
} }
} }
@@ -557,7 +557,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
result += "{\n"; result += "{\n";
result += "\"mice\": [\n"; result += "\"mice\": [\n";
for (auto& m : g_pInputManager->m_vPointers) { for (auto const& m : g_pInputManager->m_vPointers) {
result += std::format( result += std::format(
R"#( {{ R"#( {{
"address": "0x{:x}", "address": "0x{:x}",
@@ -572,7 +572,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
result += "\n],\n"; result += "\n],\n";
result += "\"keyboards\": [\n"; result += "\"keyboards\": [\n";
for (auto& k : g_pInputManager->m_vKeyboards) { for (auto const& k : g_pInputManager->m_vKeyboards) {
const auto KM = k->getActiveLayout(); const auto KM = k->getActiveLayout();
result += std::format( result += std::format(
R"#( {{ R"#( {{
@@ -596,7 +596,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
result += "\"tablets\": [\n"; result += "\"tablets\": [\n";
for (auto& d : g_pInputManager->m_vTabletPads) { for (auto const& d : g_pInputManager->m_vTabletPads) {
result += std::format( result += std::format(
R"#( {{ R"#( {{
"address": "0x{:x}", "address": "0x{:x}",
@@ -609,7 +609,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
(uintptr_t)d.get(), (uintptr_t)d->parent.get(), escapeJSONStrings(d->parent ? d->parent->hlName : "")); (uintptr_t)d.get(), (uintptr_t)d->parent.get(), escapeJSONStrings(d->parent ? d->parent->hlName : ""));
} }
for (auto& d : g_pInputManager->m_vTablets) { for (auto const& d : g_pInputManager->m_vTablets) {
result += std::format( result += std::format(
R"#( {{ R"#( {{
"address": "0x{:x}", "address": "0x{:x}",
@@ -618,7 +618,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
(uintptr_t)d.get(), escapeJSONStrings(d->hlName)); (uintptr_t)d.get(), escapeJSONStrings(d->hlName));
} }
for (auto& d : g_pInputManager->m_vTabletTools) { for (auto const& d : g_pInputManager->m_vTabletTools) {
result += std::format( result += std::format(
R"#( {{ R"#( {{
"address": "0x{:x}", "address": "0x{:x}",
@@ -632,7 +632,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
result += "\"touch\": [\n"; result += "\"touch\": [\n";
for (auto& d : g_pInputManager->m_vTouches) { for (auto const& d : g_pInputManager->m_vTouches) {
result += std::format( result += std::format(
R"#( {{ R"#( {{
"address": "0x{:x}", "address": "0x{:x}",
@@ -646,7 +646,7 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
result += "\"switches\": [\n"; result += "\"switches\": [\n";
for (auto& d : g_pInputManager->m_lSwitches) { for (auto const& d : g_pInputManager->m_lSwitches) {
result += std::format( result += std::format(
R"#( {{ R"#( {{
"address": "0x{:x}", "address": "0x{:x}",
@@ -663,14 +663,14 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
} else { } else {
result += "mice:\n"; result += "mice:\n";
for (auto& m : g_pInputManager->m_vPointers) { for (auto const& m : g_pInputManager->m_vPointers) {
result += std::format("\tMouse at {:x}:\n\t\t{}\n\t\t\tdefault speed: {:.5f}\n", (uintptr_t)m.get(), m->hlName, result += std::format("\tMouse at {:x}:\n\t\t{}\n\t\t\tdefault speed: {:.5f}\n", (uintptr_t)m.get(), m->hlName,
(m->aq() && m->aq()->getLibinputHandle() ? libinput_device_config_accel_get_default_speed(m->aq()->getLibinputHandle()) : 0.f)); (m->aq() && m->aq()->getLibinputHandle() ? libinput_device_config_accel_get_default_speed(m->aq()->getLibinputHandle()) : 0.f));
} }
result += "\n\nKeyboards:\n"; result += "\n\nKeyboards:\n";
for (auto& k : g_pInputManager->m_vKeyboards) { for (auto const& k : g_pInputManager->m_vKeyboards) {
const auto KM = k->getActiveLayout(); const auto KM = k->getActiveLayout();
result += std::format("\tKeyboard at {:x}:\n\t\t{}\n\t\t\trules: r \"{}\", m \"{}\", l \"{}\", v \"{}\", o \"{}\"\n\t\t\tactive keymap: {}\n\t\t\tmain: {}\n", result += std::format("\tKeyboard at {:x}:\n\t\t{}\n\t\t\trules: r \"{}\", m \"{}\", l \"{}\", v \"{}\", o \"{}\"\n\t\t\tactive keymap: {}\n\t\t\tmain: {}\n",
(uintptr_t)k.get(), k->hlName, k->currentRules.rules, k->currentRules.model, k->currentRules.layout, k->currentRules.variant, (uintptr_t)k.get(), k->hlName, k->currentRules.rules, k->currentRules.model, k->currentRules.layout, k->currentRules.variant,
@@ -679,27 +679,27 @@ std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
result += "\n\nTablets:\n"; result += "\n\nTablets:\n";
for (auto& d : g_pInputManager->m_vTabletPads) { for (auto const& d : g_pInputManager->m_vTabletPads) {
result += std::format("\tTablet Pad at {:x} (belongs to {:x} -> {})\n", (uintptr_t)d.get(), (uintptr_t)d->parent.get(), d->parent ? d->parent->hlName : ""); result += std::format("\tTablet Pad at {:x} (belongs to {:x} -> {})\n", (uintptr_t)d.get(), (uintptr_t)d->parent.get(), d->parent ? d->parent->hlName : "");
} }
for (auto& d : g_pInputManager->m_vTablets) { for (auto const& d : g_pInputManager->m_vTablets) {
result += std::format("\tTablet at {:x}:\n\t\t{}\n\t\t\tsize: {}x{}mm\n", (uintptr_t)d.get(), d->hlName, d->aq()->physicalSize.x, d->aq()->physicalSize.y); result += std::format("\tTablet at {:x}:\n\t\t{}\n\t\t\tsize: {}x{}mm\n", (uintptr_t)d.get(), d->hlName, d->aq()->physicalSize.x, d->aq()->physicalSize.y);
} }
for (auto& d : g_pInputManager->m_vTabletTools) { for (auto const& d : g_pInputManager->m_vTabletTools) {
result += std::format("\tTablet Tool at {:x}\n", (uintptr_t)d.get()); result += std::format("\tTablet Tool at {:x}\n", (uintptr_t)d.get());
} }
result += "\n\nTouch:\n"; result += "\n\nTouch:\n";
for (auto& d : g_pInputManager->m_vTouches) { for (auto const& d : g_pInputManager->m_vTouches) {
result += std::format("\tTouch Device at {:x}:\n\t\t{}\n", (uintptr_t)d.get(), d->hlName); result += std::format("\tTouch Device at {:x}:\n\t\t{}\n", (uintptr_t)d.get(), d->hlName);
} }
result += "\n\nSwitches:\n"; result += "\n\nSwitches:\n";
for (auto& d : g_pInputManager->m_lSwitches) { for (auto const& d : g_pInputManager->m_lSwitches) {
result += std::format("\tSwitch Device at {:x}:\n\t\t{}\n", (uintptr_t)&d, d.pDevice ? d.pDevice->getName() : ""); result += std::format("\tSwitch Device at {:x}:\n\t\t{}\n", (uintptr_t)&d, d.pDevice ? d.pDevice->getName() : "");
} }
} }
@@ -712,21 +712,21 @@ std::string animationsRequest(eHyprCtlOutputFormat format, std::string request)
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
ret += "animations:\n"; ret += "animations:\n";
for (auto& ac : g_pConfigManager->getAnimationConfig()) { for (auto const& ac : g_pConfigManager->getAnimationConfig()) {
ret += std::format("\n\tname: {}\n\t\toverriden: {}\n\t\tbezier: {}\n\t\tenabled: {}\n\t\tspeed: {:.2f}\n\t\tstyle: {}\n", ac.first, (int)ac.second.overridden, ret += std::format("\n\tname: {}\n\t\toverriden: {}\n\t\tbezier: {}\n\t\tenabled: {}\n\t\tspeed: {:.2f}\n\t\tstyle: {}\n", ac.first, (int)ac.second.overridden,
ac.second.internalBezier, ac.second.internalEnabled, ac.second.internalSpeed, ac.second.internalStyle); ac.second.internalBezier, ac.second.internalEnabled, ac.second.internalSpeed, ac.second.internalStyle);
} }
ret += "beziers:\n"; ret += "beziers:\n";
for (auto& bz : g_pAnimationManager->getAllBeziers()) { for (auto const& bz : g_pAnimationManager->getAllBeziers()) {
ret += std::format("\n\tname: {}\n", bz.first); ret += std::format("\n\tname: {}\n", bz.first);
} }
} else { } else {
// json // json
ret += "[["; ret += "[[";
for (auto& ac : g_pConfigManager->getAnimationConfig()) { for (auto const& ac : g_pConfigManager->getAnimationConfig()) {
ret += std::format(R"#( ret += std::format(R"#(
{{ {{
"name": "{}", "name": "{}",
@@ -744,7 +744,7 @@ std::string animationsRequest(eHyprCtlOutputFormat format, std::string request)
ret += ",\n["; ret += ",\n[";
for (auto& bz : g_pAnimationManager->getAllBeziers()) { for (auto const& bz : g_pAnimationManager->getAllBeziers()) {
ret += std::format(R"#( ret += std::format(R"#(
{{ {{
"name": "{}" "name": "{}"
@@ -778,11 +778,11 @@ std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::string requ
std::string ret = ""; std::string ret = "";
const auto SHORTCUTS = PROTO::globalShortcuts->getAllShortcuts(); const auto SHORTCUTS = PROTO::globalShortcuts->getAllShortcuts();
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
for (auto& sh : SHORTCUTS) for (auto const& sh : SHORTCUTS)
ret += std::format("{}:{} -> {}\n", sh.appid, sh.id, sh.description); ret += std::format("{}:{} -> {}\n", sh.appid, sh.id, sh.description);
} else { } else {
ret += "["; ret += "[";
for (auto& sh : SHORTCUTS) { for (auto const& sh : SHORTCUTS) {
ret += std::format(R"#( ret += std::format(R"#(
{{ {{
"name": "{}", "name": "{}",
@@ -800,7 +800,7 @@ std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::string requ
std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) { std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) {
std::string ret = ""; std::string ret = "";
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
for (auto& kb : g_pKeybindManager->m_lKeybinds) { for (auto const& kb : g_pKeybindManager->m_lKeybinds) {
ret += "bind"; ret += "bind";
if (kb.locked) if (kb.locked)
ret += "l"; ret += "l";
@@ -821,7 +821,7 @@ std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) {
} else { } else {
// json // json
ret += "["; ret += "[";
for (auto& kb : g_pKeybindManager->m_lKeybinds) { for (auto const& kb : g_pKeybindManager->m_lKeybinds) {
ret += std::format( ret += std::format(
R"#( R"#(
{{ {{
@@ -858,7 +858,8 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) {
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg + std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg +
").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + "\n\nflags: (if any)\n"; ").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + std::string{"\nbuilt against aquamarine "} + AQUAMARINE_VERSION + "\n" +
"\n\nflags: (if any)\n";
#ifdef LEGACY_RENDERER #ifdef LEGACY_RENDERER
result += "legacyrenderer\n"; result += "legacyrenderer\n";
@@ -881,8 +882,10 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) {
"commit_date": "{}", "commit_date": "{}",
"tag": "{}", "tag": "{}",
"commits": "{}", "commits": "{}",
"buildAquamarine": "{}",
"flags": [)#", "flags": [)#",
GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS); GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS,
AQUAMARINE_VERSION);
#ifdef LEGACY_RENDERER #ifdef LEGACY_RENDERER
result += "\"legacyrenderer\","; result += "\"legacyrenderer\",";
@@ -935,7 +938,7 @@ std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request)
result += "os-release: " + execAndGet("cat /etc/os-release") + "\n\n"; result += "os-release: " + execAndGet("cat /etc/os-release") + "\n\n";
result += "plugins:\n"; result += "plugins:\n";
for (auto& pl : g_pPluginSystem->getAllPlugins()) { for (auto const& pl : g_pPluginSystem->getAllPlugins()) {
result += std::format(" {} by {} ver {}\n", pl->name, pl->author, pl->version); result += std::format(" {} by {} ver {}\n", pl->name, pl->author, pl->version);
} }
@@ -962,20 +965,34 @@ std::string dispatchRequest(eHyprCtlOutputFormat format, std::string in) {
if (DISPATCHER == g_pKeybindManager->m_mDispatchers.end()) if (DISPATCHER == g_pKeybindManager->m_mDispatchers.end())
return "Invalid dispatcher"; return "Invalid dispatcher";
DISPATCHER->second(DISPATCHARG); SDispatchResult res = DISPATCHER->second(DISPATCHARG);
Debug::log(LOG, "Hyprctl: dispatcher {} : {}", DISPATCHSTR, DISPATCHARG); Debug::log(LOG, "Hyprctl: dispatcher {} : {}{}", DISPATCHSTR, DISPATCHARG, res.success ? "" : " -> " + res.error);
return "ok"; return res.success ? "ok" : res.error;
} }
std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) { std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) {
// get rid of the keyword keyword // Find the first space to strip the keyword keyword
in = in.substr(in.find_first_of(' ') + 1); auto const firstSpacePos = in.find_first_of(' ');
if (firstSpacePos == std::string::npos) // Handle the case where there's no space found (invalid input)
return "Invalid input: no space found";
const auto COMMAND = in.substr(0, in.find_first_of(' ')); // Strip the keyword
in = in.substr(firstSpacePos + 1);
const auto VALUE = in.substr(in.find_first_of(' ') + 1); // Find the next space for the COMMAND and VALUE
auto const secondSpacePos = in.find_first_of(' ');
if (secondSpacePos == std::string::npos) // Handle the case where there's no second space (invalid input)
return "Invalid input: command and value not properly formatted";
// Extract COMMAND and VALUE
const auto COMMAND = in.substr(0, secondSpacePos);
const auto VALUE = in.substr(secondSpacePos + 1);
// If COMMAND is empty, handle accordingly
if (COMMAND.empty())
return "Invalid input: command is empty";
std::string retval = g_pConfigManager->parseKeyword(COMMAND, VALUE); std::string retval = g_pConfigManager->parseKeyword(COMMAND, VALUE);
@@ -1006,7 +1023,7 @@ std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) {
// decorations will probably need a repaint // decorations will probably need a repaint
if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("zoom_factor") || COMMAND == "source") { if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("zoom_factor") || COMMAND == "source") {
for (auto& m : g_pCompositor->m_vMonitors) { for (auto const& m : g_pCompositor->m_vMonitors) {
g_pHyprRenderer->damageMonitor(m.get()); g_pHyprRenderer->damageMonitor(m.get());
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
} }
@@ -1122,46 +1139,77 @@ std::string dispatchSetCursor(eHyprCtlOutputFormat format, std::string request)
} }
std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::string request) { std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::string request) {
CVarList vars(request, 0, ' '); CVarList vars(request, 0, ' ');
const auto KB = vars[1]; const auto KB = vars[1];
const auto CMD = vars[2]; const auto CMD = vars[2];
// get kb SP<IKeyboard> pKeyboard;
const auto PKEYBOARD = std::find_if(g_pInputManager->m_vKeyboards.begin(), g_pInputManager->m_vKeyboards.end(),
[&](const auto& other) { return other->hlName == g_pInputManager->deviceNameToInternalString(KB); });
if (PKEYBOARD == g_pInputManager->m_vKeyboards.end()) auto updateKeyboard = [](const SP<IKeyboard> KEEB, const std::string& CMD) -> std::optional<std::string> {
return "device not found"; const auto LAYOUTS = xkb_keymap_num_layouts(KEEB->xkbKeymap);
xkb_layout_index_t activeLayout = 0;
while (activeLayout < LAYOUTS) {
if (xkb_state_layout_index_is_active(KEEB->xkbState, activeLayout, XKB_STATE_LAYOUT_EFFECTIVE) == 1)
break;
const auto KEEB = *PKEYBOARD; activeLayout++;
const auto LAYOUTS = xkb_keymap_num_layouts(KEEB->xkbKeymap);
xkb_layout_index_t activeLayout = 0;
while (activeLayout < LAYOUTS) {
if (xkb_state_layout_index_is_active(KEEB->xkbState, activeLayout, XKB_STATE_LAYOUT_EFFECTIVE) == 1)
break;
activeLayout++;
}
if (CMD == "next")
KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, activeLayout > LAYOUTS ? 0 : activeLayout + 1);
else if (CMD == "prev")
KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, activeLayout == 0 ? LAYOUTS - 1 : activeLayout - 1);
else {
int requestedLayout = 0;
try {
requestedLayout = std::stoi(CMD);
} catch (std::exception& e) { return "invalid arg 2"; }
if (requestedLayout < 0 || (uint64_t)requestedLayout > LAYOUTS - 1) {
return "layout idx out of range of " + std::to_string(LAYOUTS);
} }
KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, requestedLayout); if (CMD == "next")
KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, activeLayout > LAYOUTS ? 0 : activeLayout + 1);
else if (CMD == "prev")
KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, activeLayout == 0 ? LAYOUTS - 1 : activeLayout - 1);
else {
int requestedLayout = 0;
try {
requestedLayout = std::stoi(CMD);
} catch (std::exception& e) { return "invalid arg 2"; }
if (requestedLayout < 0 || (uint64_t)requestedLayout > LAYOUTS - 1) {
return "layout idx out of range of " + std::to_string(LAYOUTS);
}
KEEB->updateModifiers(KEEB->modifiersState.depressed, KEEB->modifiersState.latched, KEEB->modifiersState.locked, requestedLayout);
}
return std::nullopt;
};
if (KB == "main" || KB == "active" || KB == "current") {
for (auto const& k : g_pInputManager->m_vKeyboards) {
if (!k->active)
continue;
pKeyboard = k;
break;
}
} else if (KB == "all") {
std::string result = "";
for (auto const& k : g_pInputManager->m_vKeyboards) {
auto res = updateKeyboard(k, CMD);
if (res.has_value())
result += *res + "\n";
}
return result.empty() ? "ok" : result;
} else {
auto k = std::find_if(g_pInputManager->m_vKeyboards.begin(), g_pInputManager->m_vKeyboards.end(),
[&](const auto& other) { return other->hlName == g_pInputManager->deviceNameToInternalString(KB); });
if (k == g_pInputManager->m_vKeyboards.end())
return "device not found";
pKeyboard = *k;
} }
if (!pKeyboard)
return "no device";
auto result = updateKeyboard(pKeyboard, CMD);
if (result.has_value())
return *result;
return "ok"; return "ok";
} }
@@ -1286,7 +1334,7 @@ std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) {
g_pCompositor->focusWindow(PLASTWINDOW); g_pCompositor->focusWindow(PLASTWINDOW);
} }
for (auto& m : g_pCompositor->m_vMonitors) for (auto const& m : g_pCompositor->m_vMonitors)
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
return "ok"; return "ok";
@@ -1359,7 +1407,7 @@ std::string decorationRequest(eHyprCtlOutputFormat format, std::string request)
std::string result = ""; std::string result = "";
if (format == eHyprCtlOutputFormat::FORMAT_JSON) { if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
result += "["; result += "[";
for (auto& wd : PWINDOW->m_dWindowDecorations) { for (auto const& wd : PWINDOW->m_dWindowDecorations) {
result += "{\n\"decorationName\": \"" + wd->getDisplayName() + "\",\n\"priority\": " + std::to_string(wd->getPositioningInfo().priority) + "\n},"; result += "{\n\"decorationName\": \"" + wd->getDisplayName() + "\",\n\"priority\": " + std::to_string(wd->getPositioningInfo().priority) + "\n},";
} }
@@ -1367,7 +1415,7 @@ std::string decorationRequest(eHyprCtlOutputFormat format, std::string request)
result += "]"; result += "]";
} else { } else {
result = +"Decoration\tPriority\n"; result = +"Decoration\tPriority\n";
for (auto& wd : PWINDOW->m_dWindowDecorations) { for (auto const& wd : PWINDOW->m_dWindowDecorations) {
result += wd->getDisplayName() + "\t" + std::to_string(wd->getPositioningInfo().priority) + "\n"; result += wd->getDisplayName() + "\t" + std::to_string(wd->getPositioningInfo().priority) + "\n";
} }
} }
@@ -1386,7 +1434,7 @@ std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) {
bool added = false; bool added = false;
if (!vars[3].empty()) { if (!vars[3].empty()) {
for (auto& m : g_pCompositor->m_vRealMonitors) { for (auto const& m : g_pCompositor->m_vRealMonitors) {
if (m->szName == vars[3]) if (m->szName == vars[3])
return "Name already taken"; return "Name already taken";
} }
@@ -1396,7 +1444,7 @@ std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) {
if (g_pCompositor->getMonitorFromName(vars[3])) if (g_pCompositor->getMonitorFromName(vars[3]))
return "A real monitor already uses that name."; return "A real monitor already uses that name.";
for (auto& impl : g_pCompositor->m_pAqBackend->getImplementations() | std::views::reverse) { for (auto const& impl : g_pCompositor->m_pAqBackend->getImplementations() | std::views::reverse) {
auto type = impl->type(); auto type = impl->type();
if (type == Aquamarine::AQ_BACKEND_HEADLESS && (vars[2] == "headless" || vars[2] == "auto")) { if (type == Aquamarine::AQ_BACKEND_HEADLESS && (vars[2] == "headless" || vars[2] == "auto")) {
@@ -1464,7 +1512,7 @@ std::string dispatchPlugin(eHyprCtlOutputFormat format, std::string request) {
return "no plugins loaded"; return "no plugins loaded";
std::string list = ""; std::string list = "";
for (auto& p : PLUGINS) { for (auto const& p : PLUGINS) {
list += std::format("\nPlugin {} by {}:\n\tHandle: {:x}\n\tVersion: {}\n\tDescription: {}\n", p->name, p->author, (uintptr_t)p->m_pHandle, p->version, p->description); list += std::format("\nPlugin {} by {}:\n\tHandle: {:x}\n\tVersion: {}\n\tDescription: {}\n", p->name, p->author, (uintptr_t)p->m_pHandle, p->version, p->description);
} }
@@ -1561,6 +1609,21 @@ std::string getIsLocked(eHyprCtlOutputFormat format, std::string request) {
return lockedStr; return lockedStr;
} }
std::string getDescriptions(eHyprCtlOutputFormat format, std::string request) {
std::string json = "{";
const auto& DESCS = g_pConfigManager->getAllDescriptions();
for (const auto& d : DESCS) {
json += d.jsonify() + ",\n";
}
json.pop_back();
json.pop_back();
json += "}\n";
return json;
}
CHyprCtl::CHyprCtl() { CHyprCtl::CHyprCtl() {
registerCommand(SHyprCtlCommand{"workspaces", true, workspacesRequest}); registerCommand(SHyprCtlCommand{"workspaces", true, workspacesRequest});
registerCommand(SHyprCtlCommand{"workspacerules", true, workspaceRulesRequest}); registerCommand(SHyprCtlCommand{"workspacerules", true, workspaceRulesRequest});
@@ -1581,6 +1644,7 @@ CHyprCtl::CHyprCtl() {
registerCommand(SHyprCtlCommand{"layouts", true, layoutsRequest}); registerCommand(SHyprCtlCommand{"layouts", true, layoutsRequest});
registerCommand(SHyprCtlCommand{"configerrors", true, configErrorsRequest}); registerCommand(SHyprCtlCommand{"configerrors", true, configErrorsRequest});
registerCommand(SHyprCtlCommand{"locked", true, getIsLocked}); registerCommand(SHyprCtlCommand{"locked", true, getIsLocked});
registerCommand(SHyprCtlCommand{"descriptions", true, getDescriptions});
registerCommand(SHyprCtlCommand{"monitors", false, monitorsRequest}); registerCommand(SHyprCtlCommand{"monitors", false, monitorsRequest});
registerCommand(SHyprCtlCommand{"reload", false, reloadRequest}); registerCommand(SHyprCtlCommand{"reload", false, reloadRequest});
@@ -1657,7 +1721,7 @@ std::string CHyprCtl::getReply(std::string request) {
std::string result = ""; std::string result = "";
// parse exact cmds first, then non-exact. // parse exact cmds first, then non-exact.
for (auto& cmd : m_vCommands) { for (auto const& cmd : m_vCommands) {
if (!cmd->exact) if (!cmd->exact)
continue; continue;
@@ -1668,7 +1732,7 @@ std::string CHyprCtl::getReply(std::string request) {
} }
if (result.empty()) if (result.empty())
for (auto& cmd : m_vCommands) { for (auto const& cmd : m_vCommands) {
if (cmd->exact) if (cmd->exact)
continue; continue;
@@ -1699,7 +1763,7 @@ std::string CHyprCtl::getReply(std::string request) {
rd.blurFBDirty = true; rd.blurFBDirty = true;
} }
for (auto& m : g_pCompositor->m_vMonitors) { for (auto const& m : g_pCompositor->m_vMonitors) {
g_pHyprRenderer->damageMonitor(m.get()); g_pHyprRenderer->damageMonitor(m.get());
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
} }

View File

@@ -7,8 +7,8 @@ CHyprDebugOverlay::CHyprDebugOverlay() {
m_pTexture = makeShared<CTexture>(); m_pTexture = makeShared<CTexture>();
} }
void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float µs) { void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) {
m_dLastRenderTimes.push_back(µs / 1000.f); m_dLastRenderTimes.push_back(durationUs / 1000.f);
if (m_dLastRenderTimes.size() > (long unsigned int)pMonitor->refreshRate) if (m_dLastRenderTimes.size() > (long unsigned int)pMonitor->refreshRate)
m_dLastRenderTimes.pop_front(); m_dLastRenderTimes.pop_front();
@@ -17,8 +17,8 @@ void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float µs) {
m_pMonitor = pMonitor; m_pMonitor = pMonitor;
} }
void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float µs) { void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) {
m_dLastRenderTimesNoOverlay.push_back(µs / 1000.f); m_dLastRenderTimesNoOverlay.push_back(durationUs / 1000.f);
if (m_dLastRenderTimesNoOverlay.size() > (long unsigned int)pMonitor->refreshRate) if (m_dLastRenderTimesNoOverlay.size() > (long unsigned int)pMonitor->refreshRate)
m_dLastRenderTimesNoOverlay.pop_front(); m_dLastRenderTimesNoOverlay.pop_front();
@@ -57,7 +57,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
float avgFrametime = 0; float avgFrametime = 0;
float maxFrametime = 0; float maxFrametime = 0;
float minFrametime = 9999; float minFrametime = 9999;
for (auto& ft : m_dLastFrametimes) { for (auto const& ft : m_dLastFrametimes) {
if (ft > maxFrametime) if (ft > maxFrametime)
maxFrametime = ft; maxFrametime = ft;
if (ft < minFrametime) if (ft < minFrametime)
@@ -70,7 +70,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
float avgRenderTime = 0; float avgRenderTime = 0;
float maxRenderTime = 0; float maxRenderTime = 0;
float minRenderTime = 9999; float minRenderTime = 9999;
for (auto& rt : m_dLastRenderTimes) { for (auto const& rt : m_dLastRenderTimes) {
if (rt > maxRenderTime) if (rt > maxRenderTime)
maxRenderTime = rt; maxRenderTime = rt;
if (rt < minRenderTime) if (rt < minRenderTime)
@@ -83,7 +83,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
float avgRenderTimeNoOverlay = 0; float avgRenderTimeNoOverlay = 0;
float maxRenderTimeNoOverlay = 0; float maxRenderTimeNoOverlay = 0;
float minRenderTimeNoOverlay = 9999; float minRenderTimeNoOverlay = 9999;
for (auto& rt : m_dLastRenderTimesNoOverlay) { for (auto const& rt : m_dLastRenderTimesNoOverlay) {
if (rt > maxRenderTimeNoOverlay) if (rt > maxRenderTimeNoOverlay)
maxRenderTimeNoOverlay = rt; maxRenderTimeNoOverlay = rt;
if (rt < minRenderTimeNoOverlay) if (rt < minRenderTimeNoOverlay)
@@ -96,7 +96,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
float avgAnimMgrTick = 0; float avgAnimMgrTick = 0;
float maxAnimMgrTick = 0; float maxAnimMgrTick = 0;
float minAnimMgrTick = 9999; float minAnimMgrTick = 9999;
for (auto& at : m_dLastAnimationTicks) { for (auto const& at : m_dLastAnimationTicks) {
if (at > maxAnimMgrTick) if (at > maxAnimMgrTick)
maxAnimMgrTick = at; maxAnimMgrTick = at;
if (at < minAnimMgrTick) if (at < minAnimMgrTick)
@@ -188,12 +188,12 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
return posY - offset; return posY - offset;
} }
void CHyprDebugOverlay::renderData(CMonitor* pMonitor, float µs) { void CHyprDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) {
m_mMonitorOverlays[pMonitor].renderData(pMonitor, µs); m_mMonitorOverlays[pMonitor].renderData(pMonitor, durationUs);
} }
void CHyprDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float µs) { void CHyprDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) {
m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, µs); m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, durationUs);
} }
void CHyprDebugOverlay::frameData(CMonitor* pMonitor) { void CHyprDebugOverlay::frameData(CMonitor* pMonitor) {
@@ -217,7 +217,7 @@ void CHyprDebugOverlay::draw() {
// draw the things // draw the things
int offsetY = 0; int offsetY = 0;
for (auto& m : g_pCompositor->m_vMonitors) { for (auto const& m : g_pCompositor->m_vMonitors) {
offsetY += m_mMonitorOverlays[m.get()].draw(offsetY); offsetY += m_mMonitorOverlays[m.get()].draw(offsetY);
offsetY += 5; // for padding between mons offsetY += 5; // for padding between mons
} }

View File

@@ -13,8 +13,8 @@ class CHyprMonitorDebugOverlay {
public: public:
int draw(int offset); int draw(int offset);
void renderData(CMonitor* pMonitor, float µs); void renderData(CMonitor* pMonitor, float durationUs);
void renderDataNoOverlay(CMonitor* pMonitor, float µs); void renderDataNoOverlay(CMonitor* pMonitor, float durationUs);
void frameData(CMonitor* pMonitor); void frameData(CMonitor* pMonitor);
private: private:
@@ -33,8 +33,8 @@ class CHyprDebugOverlay {
public: public:
CHyprDebugOverlay(); CHyprDebugOverlay();
void draw(); void draw();
void renderData(CMonitor*, float µs); void renderData(CMonitor*, float durationUs);
void renderDataNoOverlay(CMonitor*, float µs); void renderDataNoOverlay(CMonitor*, float durationUs);
void frameData(CMonitor*); void frameData(CMonitor*);
private: private:

View File

@@ -44,7 +44,7 @@ void CHyprNotificationOverlay::addNotification(const std::string& text, const CC
PNOTIF->icon = icon; PNOTIF->icon = icon;
PNOTIF->fontSize = fontSize; PNOTIF->fontSize = fontSize;
for (auto& m : g_pCompositor->m_vMonitors) { for (auto const& m : g_pCompositor->m_vMonitors) {
g_pCompositor->scheduleFrameForMonitor(m.get()); g_pCompositor->scheduleFrameForMonitor(m.get());
} }
} }
@@ -87,7 +87,7 @@ CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
const auto iconBackendID = iconBackendFromLayout(layout); const auto iconBackendID = iconBackendFromLayout(layout);
const auto PBEZIER = g_pAnimationManager->getBezier("default"); const auto PBEZIER = g_pAnimationManager->getBezier("default");
for (auto& notif : m_dNotifications) { for (auto const& notif : m_dNotifications) {
const auto ICONPADFORNOTIF = notif->icon == ICON_NONE ? 0 : ICON_PAD; const auto ICONPADFORNOTIF = notif->icon == ICON_NONE ? 0 : ICON_PAD;
const auto FONTSIZE = std::clamp((int)(notif->fontSize * ((pMonitor->vecPixelSize.x * SCALE) / 1920.f)), 8, 40); const auto FONTSIZE = std::clamp((int)(notif->fontSize * ((pMonitor->vecPixelSize.x * SCALE) / 1920.f)), 8, 40);

View File

@@ -5,10 +5,13 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <fcntl.h>
void Debug::init(const std::string& IS) { void Debug::init(const std::string& IS) {
logFile = IS + (ISDEBUG ? "/hyprlandd.log" : "/hyprland.log"); logFile = IS + (ISDEBUG ? "/hyprlandd.log" : "/hyprland.log");
logOfs.open(logFile, std::ios::out | std::ios::app); logOfs.open(logFile, std::ios::out | std::ios::app);
auto handle = logOfs.native_handle();
fcntl(handle, F_SETFD, FD_CLOEXEC);
} }
void Debug::close() { void Debug::close() {

View File

@@ -55,8 +55,9 @@ namespace Debug {
// print date and time to the ofs // print date and time to the ofs
if (disableTime && !**disableTime) { if (disableTime && !**disableTime) {
#ifndef _LIBCPP_VERSION #ifndef _LIBCPP_VERSION
const auto zt = std::chrono::zoned_time{std::chrono::current_zone(), std::chrono::system_clock::now()}; static auto current_zone = std::chrono::current_zone();
const auto hms = std::chrono::hh_mm_ss{zt.get_local_time() - std::chrono::floor<std::chrono::days>(zt.get_local_time())}; const auto zt = std::chrono::zoned_time{current_zone, std::chrono::system_clock::now()};
const auto hms = std::chrono::hh_mm_ss{zt.get_local_time() - std::chrono::floor<std::chrono::days>(zt.get_local_time())};
#else #else
// TODO: current clang 17 does not support `zoned_time`, remove this once clang 19 is ready // TODO: current clang 17 does not support `zoned_time`, remove this once clang 19 is ready
const auto hms = std::chrono::hh_mm_ss{std::chrono::system_clock::now() - std::chrono::floor<std::chrono::days>(std::chrono::system_clock::now())}; const auto hms = std::chrono::hh_mm_ss{std::chrono::system_clock::now() - std::chrono::floor<std::chrono::days>(std::chrono::system_clock::now())};

View File

@@ -71,6 +71,12 @@ CLayerSurface::~CLayerSurface() {
surface->unassign(); surface->unassign();
g_pHyprRenderer->makeEGLCurrent(); g_pHyprRenderer->makeEGLCurrent();
std::erase_if(g_pHyprOpenGL->m_mLayerFramebuffers, [&](const auto& other) { return other.first.expired() || other.first.lock() == self.lock(); }); std::erase_if(g_pHyprOpenGL->m_mLayerFramebuffers, [&](const auto& other) { return other.first.expired() || other.first.lock() == self.lock(); });
for (auto const& mon : g_pCompositor->m_vRealMonitors) {
for (auto& lsl : mon->m_aLayerSurfaceLayers) {
std::erase_if(lsl, [this](auto& ls) { return ls.expired() || ls.get() == this; });
}
}
} }
void CLayerSurface::onDestroy() { void CLayerSurface::onDestroy() {
@@ -360,7 +366,7 @@ void CLayerSurface::applyRules() {
xray = -1; xray = -1;
animationStyle.reset(); animationStyle.reset();
for (auto& rule : g_pConfigManager->getMatchingRules(self.lock())) { for (auto const& rule : g_pConfigManager->getMatchingRules(self.lock())) {
if (rule.rule == "noanim") if (rule.rule == "noanim")
noAnimations = true; noAnimations = true;
else if (rule.rule == "blur") else if (rule.rule == "blur")
@@ -388,6 +394,11 @@ void CLayerSurface::applyRules() {
} else if (rule.rule.starts_with("animation")) { } else if (rule.rule.starts_with("animation")) {
CVarList vars{rule.rule, 2, 's'}; CVarList vars{rule.rule, 2, 's'};
animationStyle = vars[1]; animationStyle = vars[1];
} else if (rule.rule.starts_with("order")) {
CVarList vars{rule.rule, 2, 's'};
try {
order = std::stoi(vars[1]);
} catch (...) { Debug::log(ERR, "Invalid value passed to order"); }
} }
} }
} }

View File

@@ -42,7 +42,7 @@ class CLayerSurface {
bool mapped = false; bool mapped = false;
uint32_t layer = 0; uint32_t layer = 0;
int monitorID = -1; MONITORID monitorID = -1;
bool fadingOut = false; bool fadingOut = false;
bool readyToDelete = false; bool readyToDelete = false;
@@ -51,10 +51,11 @@ class CLayerSurface {
bool forceBlur = false; bool forceBlur = false;
bool forceBlurPopups = false; bool forceBlurPopups = false;
int xray = -1; int64_t xray = -1;
bool ignoreAlpha = false; bool ignoreAlpha = false;
float ignoreAlphaValue = 0.f; float ignoreAlphaValue = 0.f;
bool dimAround = false; bool dimAround = false;
int64_t order = 0;
std::optional<std::string> animationStyle; std::optional<std::string> animationStyle;

View File

@@ -202,6 +202,13 @@ void CPopup::reposition() {
m_pResource->applyPositioning(box, COORDS); m_pResource->applyPositioning(box, COORDS);
} }
SP<CWLSurface> CPopup::getT1Owner() {
if (m_pWindowOwner)
return m_pWindowOwner->m_pWLSurface;
else
return m_pLayerOwner->surface;
}
Vector2D CPopup::coordsRelativeToParent() { Vector2D CPopup::coordsRelativeToParent() {
Vector2D offset; Vector2D offset;
@@ -251,7 +258,7 @@ void CPopup::recheckTree() {
void CPopup::recheckChildrenRecursive() { void CPopup::recheckChildrenRecursive() {
auto cpy = m_vChildren; auto cpy = m_vChildren;
for (auto& c : cpy) { for (auto const& c : cpy) {
c->onCommit(true); c->onCommit(true);
c->recheckChildrenRecursive(); c->recheckChildrenRecursive();
} }
@@ -282,14 +289,14 @@ bool CPopup::visible() {
} }
void CPopup::bfHelper(std::vector<CPopup*> nodes, std::function<void(CPopup*, void*)> fn, void* data) { void CPopup::bfHelper(std::vector<CPopup*> nodes, std::function<void(CPopup*, void*)> fn, void* data) {
for (auto& n : nodes) { for (auto const& n : nodes) {
fn(n, data); fn(n, data);
} }
std::vector<CPopup*> nodes2; std::vector<CPopup*> nodes2;
for (auto& n : nodes) { for (auto const& n : nodes) {
for (auto& c : n->m_vChildren) { for (auto const& c : n->m_vChildren) {
nodes2.push_back(c.get()); nodes2.push_back(c.get());
} }
} }
@@ -308,7 +315,7 @@ CPopup* CPopup::at(const Vector2D& globalCoords, bool allowsInput) {
std::vector<CPopup*> popups; std::vector<CPopup*> popups;
breadthfirst([](CPopup* popup, void* data) { ((std::vector<CPopup*>*)data)->push_back(popup); }, &popups); breadthfirst([](CPopup* popup, void* data) { ((std::vector<CPopup*>*)data)->push_back(popup); }, &popups);
for (auto& p : popups | std::views::reverse) { for (auto const& p : popups | std::views::reverse) {
if (!p->m_pResource) if (!p->m_pResource)
continue; continue;

View File

@@ -18,21 +18,22 @@ class CPopup {
~CPopup(); ~CPopup();
Vector2D coordsRelativeToParent(); SP<CWLSurface> getT1Owner();
Vector2D coordsGlobal(); Vector2D coordsRelativeToParent();
Vector2D coordsGlobal();
Vector2D size(); Vector2D size();
void onNewPopup(SP<CXDGPopupResource> popup); void onNewPopup(SP<CXDGPopupResource> popup);
void onDestroy(); void onDestroy();
void onMap(); void onMap();
void onUnmap(); void onUnmap();
void onCommit(bool ignoreSiblings = false); void onCommit(bool ignoreSiblings = false);
void onReposition(); void onReposition();
void recheckTree(); void recheckTree();
bool visible(); bool visible();
// will also loop over this node // will also loop over this node
void breadthfirst(std::function<void(CPopup*, void*)> fn, void* data); void breadthfirst(std::function<void(CPopup*, void*)> fn, void* data);

View File

@@ -65,7 +65,7 @@ void CSubsurface::checkSiblingDamage() {
const double SCALE = m_pWindowParent.lock() && m_pWindowParent->m_bIsX11 ? 1.0 / m_pWindowParent->m_fX11SurfaceScaledBy : 1.0; const double SCALE = m_pWindowParent.lock() && m_pWindowParent->m_bIsX11 ? 1.0 / m_pWindowParent->m_fX11SurfaceScaledBy : 1.0;
for (auto& n : m_pParent->m_vChildren) { for (auto const& n : m_pParent->m_vChildren) {
if (n.get() == this) if (n.get() == this)
continue; continue;
@@ -75,7 +75,7 @@ void CSubsurface::checkSiblingDamage() {
} }
void CSubsurface::recheckDamageForSubsurfaces() { void CSubsurface::recheckDamageForSubsurfaces() {
for (auto& n : m_vChildren) { for (auto const& n : m_vChildren) {
const auto COORDS = n->coordsGlobal(); const auto COORDS = n->coordsGlobal();
g_pHyprRenderer->damageSurface(n->m_pWLSurface->resource(), COORDS.x, COORDS.y); g_pHyprRenderer->damageSurface(n->m_pWLSurface->resource(), COORDS.x, COORDS.y);
} }
@@ -183,7 +183,7 @@ Vector2D CSubsurface::coordsGlobal() {
} }
void CSubsurface::initExistingSubsurfaces(SP<CWLSurfaceResource> pSurface) { void CSubsurface::initExistingSubsurfaces(SP<CWLSurfaceResource> pSurface) {
for (auto& s : pSurface->subsurfaces) { for (auto const& s : pSurface->subsurfaces) {
if (!s || s->surface->hlSurface /* already assigned */) if (!s || s->surface->hlSurface /* already assigned */)
continue; continue;
onNewSubsurface(s.lock()); onNewSubsurface(s.lock());

View File

@@ -19,9 +19,8 @@ using namespace Hyprutils::String;
PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) { PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
PHLWINDOW pWindow = SP<CWindow>(new CWindow(surface)); PHLWINDOW pWindow = SP<CWindow>(new CWindow(surface));
pWindow->m_pSelf = pWindow; pWindow->m_pSelf = pWindow;
pWindow->m_bIsX11 = true; pWindow->m_bIsX11 = true;
pWindow->m_iX11Type = surface->overrideRedirect ? 2 : 1;
pWindow->m_vRealPosition.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_vRealPosition.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->m_vRealSize.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_vRealSize.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
@@ -31,6 +30,7 @@ PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
pWindow->m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW); pWindow->m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW);
pWindow->m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->m_fMovingToWorkspaceAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(pWindow)); pWindow->addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(pWindow));
pWindow->addWindowDeco(std::make_unique<CHyprBorderDecoration>(pWindow)); pWindow->addWindowDeco(std::make_unique<CHyprBorderDecoration>(pWindow));
@@ -52,6 +52,7 @@ PHLWINDOW CWindow::create(SP<CXDGSurfaceResource> resource) {
pWindow->m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW); pWindow->m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW);
pWindow->m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->m_fMovingToWorkspaceAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(pWindow)); pWindow->addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(pWindow));
pWindow->addWindowDeco(std::make_unique<CHyprBorderDecoration>(pWindow)); pWindow->addWindowDeco(std::make_unique<CHyprBorderDecoration>(pWindow));
@@ -252,7 +253,7 @@ void CWindow::updateWindowDecos() {
if (!m_bIsMapped || isHidden()) if (!m_bIsMapped || isHidden())
return; return;
for (auto& wd : m_vDecosToRemove) { for (auto const& wd : m_vDecosToRemove) {
for (auto it = m_dWindowDecorations.begin(); it != m_dWindowDecorations.end(); it++) { for (auto it = m_dWindowDecorations.begin(); it != m_dWindowDecorations.end(); it++) {
if (it->get() == wd) { if (it->get() == wd) {
g_pDecorationPositioner->uncacheDecoration(it->get()); g_pDecorationPositioner->uncacheDecoration(it->get());
@@ -270,11 +271,11 @@ void CWindow::updateWindowDecos() {
// make a copy because updateWindow can remove decos. // make a copy because updateWindow can remove decos.
std::vector<IHyprWindowDecoration*> decos; std::vector<IHyprWindowDecoration*> decos;
for (auto& wd : m_dWindowDecorations) { for (auto const& wd : m_dWindowDecorations) {
decos.push_back(wd.get()); decos.push_back(wd.get());
} }
for (auto& wd : decos) { for (auto const& wd : decos) {
if (std::find_if(m_dWindowDecorations.begin(), m_dWindowDecorations.end(), [wd](const auto& other) { return other.get() == wd; }) == m_dWindowDecorations.end()) if (std::find_if(m_dWindowDecorations.begin(), m_dWindowDecorations.end(), [wd](const auto& other) { return other.get() == wd; }) == m_dWindowDecorations.end())
continue; continue;
wd->updateWindow(m_pSelf.lock()); wd->updateWindow(m_pSelf.lock());
@@ -296,7 +297,7 @@ void CWindow::removeWindowDeco(IHyprWindowDecoration* deco) {
} }
void CWindow::uncacheWindowDecos() { void CWindow::uncacheWindowDecos() {
for (auto& wd : m_dWindowDecorations) { for (auto const& wd : m_dWindowDecorations) {
g_pDecorationPositioner->uncacheDecoration(wd.get()); g_pDecorationPositioner->uncacheDecoration(wd.get());
} }
} }
@@ -305,7 +306,7 @@ bool CWindow::checkInputOnDecos(const eInputType type, const Vector2D& mouseCoor
if (type != INPUT_TYPE_DRAG_END && hasPopupAt(mouseCoords)) if (type != INPUT_TYPE_DRAG_END && hasPopupAt(mouseCoords))
return false; return false;
for (auto& wd : m_dWindowDecorations) { for (auto const& wd : m_dWindowDecorations) {
if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT))
continue; continue;
@@ -337,7 +338,7 @@ pid_t CWindow::getPID() {
} }
IHyprWindowDecoration* CWindow::getDecorationByType(eDecorationType type) { IHyprWindowDecoration* CWindow::getDecorationByType(eDecorationType type) {
for (auto& wd : m_dWindowDecorations) { for (auto const& wd : m_dWindowDecorations) {
if (wd->getDecorationType() == type) if (wd->getDecorationType() == type)
return wd.get(); return wd.get();
} }
@@ -407,6 +408,11 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) {
const auto OLDWORKSPACE = m_pWorkspace; const auto OLDWORKSPACE = m_pWorkspace;
m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->m_iMonitorID : -1;
m_fMovingToWorkspaceAlpha.setValueAndWarp(1.F);
m_fMovingToWorkspaceAlpha = 0.F;
m_fMovingToWorkspaceAlpha.setCallbackOnEnd([this](void* thisptr) { m_iMonitorMovedFrom = -1; });
m_pWorkspace = pWorkspace; m_pWorkspace = pWorkspace;
setAnimationsToMove(); setAnimationsToMove();
@@ -454,7 +460,7 @@ PHLWINDOW CWindow::X11TransientFor() {
s = s->parent; s = s->parent;
} }
for (auto& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (w->m_pXWaylandSurface != s) if (w->m_pXWaylandSurface != s)
continue; continue;
return w; return w;
@@ -464,7 +470,7 @@ PHLWINDOW CWindow::X11TransientFor() {
} }
void CWindow::removeDecorationByType(eDecorationType type) { void CWindow::removeDecorationByType(eDecorationType type) {
for (auto& wd : m_dWindowDecorations) { for (auto const& wd : m_dWindowDecorations) {
if (wd->getDecorationType() == type) if (wd->getDecorationType() == type)
m_vDecosToRemove.push_back(wd.get()); m_vDecosToRemove.push_back(wd.get());
} }
@@ -502,6 +508,7 @@ void CWindow::onUnmap() {
m_fAlpha.setCallbackOnEnd(unregisterVar); m_fAlpha.setCallbackOnEnd(unregisterVar);
m_cRealShadowColor.setCallbackOnEnd(unregisterVar); m_cRealShadowColor.setCallbackOnEnd(unregisterVar);
m_fDimPercent.setCallbackOnEnd(unregisterVar); m_fDimPercent.setCallbackOnEnd(unregisterVar);
m_fMovingToWorkspaceAlpha.setCallbackOnEnd(unregisterVar);
m_vRealSize.setCallbackOnBegin(nullptr); m_vRealSize.setCallbackOnBegin(nullptr);
@@ -542,6 +549,7 @@ void CWindow::onMap() {
m_fAlpha.resetAllCallbacks(); m_fAlpha.resetAllCallbacks();
m_cRealShadowColor.resetAllCallbacks(); m_cRealShadowColor.resetAllCallbacks();
m_fDimPercent.resetAllCallbacks(); m_fDimPercent.resetAllCallbacks();
m_fMovingToWorkspaceAlpha.resetAllCallbacks();
m_vRealPosition.registerVar(); m_vRealPosition.registerVar();
m_vRealSize.registerVar(); m_vRealSize.registerVar();
@@ -551,6 +559,7 @@ void CWindow::onMap() {
m_fAlpha.registerVar(); m_fAlpha.registerVar();
m_cRealShadowColor.registerVar(); m_cRealShadowColor.registerVar();
m_fDimPercent.registerVar(); m_fDimPercent.registerVar();
m_fMovingToWorkspaceAlpha.registerVar();
m_fBorderAngleAnimationProgress.setCallbackOnEnd([&](void* ptr) { onBorderAngleAnimEnd(ptr); }, false); m_fBorderAngleAnimationProgress.setCallbackOnEnd([&](void* ptr) { onBorderAngleAnimEnd(ptr); }, false);
@@ -617,7 +626,7 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
int opacityIDX = 0; int opacityIDX = 0;
for (auto& r : vars) { for (auto const& r : vars) {
if (r == "opacity") if (r == "opacity")
continue; continue;
@@ -666,7 +675,7 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
return; return;
} }
for (auto& token : colorsAndAngles) { for (auto const& token : colorsAndAngles) {
// The first angle, or an explicit "0deg", splits the two gradients // The first angle, or an explicit "0deg", splits the two gradients
if (active && token.contains("deg")) { if (active && token.contains("deg")) {
activeBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0); activeBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
@@ -748,6 +757,9 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
if (m_sGroupData.pNextWindow.expired()) if (m_sGroupData.pNextWindow.expired())
setHidden(false); setHidden(false);
} catch (std::exception& e) { Debug::log(ERR, "minsize rule \"{}\" failed with: {}", r.szRule, e.what()); } } catch (std::exception& e) { Debug::log(ERR, "minsize rule \"{}\" failed with: {}", r.szRule, e.what()); }
} else if (r.szRule == "renderunfocused") {
m_sWindowData.renderUnfocused = CWindowOverridableVar(true, priority);
g_pHyprRenderer->addWindowToRenderUnfocused(m_pSelf.lock());
} }
} }
@@ -765,12 +777,14 @@ void CWindow::updateDynamicRules() {
m_sWindowData.activeBorderColor.unset(PRIORITY_WINDOW_RULE); m_sWindowData.activeBorderColor.unset(PRIORITY_WINDOW_RULE);
m_sWindowData.inactiveBorderColor.unset(PRIORITY_WINDOW_RULE); m_sWindowData.inactiveBorderColor.unset(PRIORITY_WINDOW_RULE);
m_sWindowData.renderUnfocused.unset(PRIORITY_WINDOW_RULE);
m_eIdleInhibitMode = IDLEINHIBIT_NONE; m_eIdleInhibitMode = IDLEINHIBIT_NONE;
m_tags.removeDynamicTags(); m_tags.removeDynamicTags();
m_vMatchedRules = g_pConfigManager->getMatchingRules(m_pSelf.lock()); m_vMatchedRules = g_pConfigManager->getMatchingRules(m_pSelf.lock());
for (auto& r : m_vMatchedRules) { for (auto const& r : m_vMatchedRules) {
applyDynamicRule(r); applyDynamicRule(r);
} }
@@ -881,7 +895,7 @@ void CWindow::destroyGroup() {
addresses += std::format("{:x},", (uintptr_t)curr.get()); addresses += std::format("{:x},", (uintptr_t)curr.get());
} while (curr.get() != this); } while (curr.get() != this);
for (auto& w : members) { for (auto const& w : members) {
if (w->m_sGroupData.head) if (w->m_sGroupData.head)
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(curr); g_pLayoutManager->getCurrentLayout()->onWindowRemoved(curr);
w->m_sGroupData.head = false; w->m_sGroupData.head = false;
@@ -889,7 +903,7 @@ void CWindow::destroyGroup() {
const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_bGroupsLocked; const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_bGroupsLocked;
g_pKeybindManager->m_bGroupsLocked = true; g_pKeybindManager->m_bGroupsLocked = true;
for (auto& w : members) { for (auto const& w : members) {
g_pLayoutManager->getCurrentLayout()->onWindowCreated(w); g_pLayoutManager->getCurrentLayout()->onWindowCreated(w);
w->updateWindowDecos(); w->updateWindowDecos();
} }
@@ -937,12 +951,16 @@ int CWindow::getGroupSize() {
} }
bool CWindow::canBeGroupedInto(PHLWINDOW pWindow) { bool CWindow::canBeGroupedInto(PHLWINDOW pWindow) {
static auto ALLOWGROUPMERGE = CConfigValue<Hyprlang::INT>("group:merge_groups_on_drag");
bool isGroup = m_sGroupData.pNextWindow;
bool disallowDragIntoGroup = g_pInputManager->m_bWasDraggingWindow && isGroup && !bool(*ALLOWGROUPMERGE);
return !g_pKeybindManager->m_bGroupsLocked // global group lock disengaged return !g_pKeybindManager->m_bGroupsLocked // global group lock disengaged
&& ((m_eGroupRules & GROUP_INVADE && m_bFirstMap) // window ignore local group locks, or && ((m_eGroupRules & GROUP_INVADE && m_bFirstMap) // window ignore local group locks, or
|| (!pWindow->getGroupHead()->m_sGroupData.locked // target unlocked || (!pWindow->getGroupHead()->m_sGroupData.locked // target unlocked
&& !(m_sGroupData.pNextWindow.lock() && getGroupHead()->m_sGroupData.locked))) // source unlocked or isn't group && !(m_sGroupData.pNextWindow.lock() && getGroupHead()->m_sGroupData.locked))) // source unlocked or isn't group
&& !m_sGroupData.deny // source is not denied entry && !m_sGroupData.deny // source is not denied entry
&& !(m_eGroupRules & GROUP_BARRED && m_bFirstMap); // group rule doesn't prevent adding window && !(m_eGroupRules & GROUP_BARRED && m_bFirstMap) // group rule doesn't prevent adding window
&& !disallowDragIntoGroup; // config allows groups to be merged
} }
PHLWINDOW CWindow::getGroupWindowByIndex(int index) { PHLWINDOW CWindow::getGroupWindowByIndex(int index) {
@@ -973,7 +991,7 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) {
const auto PCURRENT = getGroupCurrent(); const auto PCURRENT = getGroupCurrent();
const bool FULLSCREEN = PCURRENT->isFullscreen(); const bool FULLSCREEN = PCURRENT->isFullscreen();
const auto WORKSPACE = PCURRENT->m_pWorkspace; const auto WORKSPACE = PCURRENT->m_pWorkspace;
const auto MODE = PCURRENT->m_sFullscreenState.client; const auto MODE = PCURRENT->m_sFullscreenState.internal;
const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goal(); const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goal();
const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goal(); const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goal();
@@ -1243,7 +1261,7 @@ bool CWindow::isEffectiveInternalFSMode(const eFullscreenMode MODE) {
return (eFullscreenMode)std::bit_floor((uint8_t)m_sFullscreenState.internal) == MODE; return (eFullscreenMode)std::bit_floor((uint8_t)m_sFullscreenState.internal) == MODE;
} }
int CWindow::workspaceID() { WORKSPACEID CWindow::workspaceID() {
return m_pWorkspace ? m_pWorkspace->m_iID : m_iLastWorkspace; return m_pWorkspace ? m_pWorkspace->m_iID : m_iLastWorkspace;
} }
@@ -1282,7 +1300,7 @@ std::unordered_map<std::string, std::string> CWindow::getEnv() {
CVarList envs(std::string{buffer.data(), buffer.size() - 1}, 0, '\n', true); CVarList envs(std::string{buffer.data(), buffer.size() - 1}, 0, '\n', true);
for (auto& e : envs) { for (auto const& e : envs) {
if (!e.contains('=')) if (!e.contains('='))
continue; continue;
@@ -1307,6 +1325,11 @@ void CWindow::activate(bool force) {
if (!force && (!m_sWindowData.focusOnActivate.valueOr(*PFOCUSONACTIVATE) || (m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY) || (m_eSuppressedEvents & SUPPRESS_ACTIVATE))) if (!force && (!m_sWindowData.focusOnActivate.valueOr(*PFOCUSONACTIVATE) || (m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY) || (m_eSuppressedEvents & SUPPRESS_ACTIVATE)))
return; return;
if (!m_bIsMapped) {
Debug::log(LOG, "Ignoring CWindow::activate focus/warp, window is not mapped yet.");
return;
}
if (m_bIsFloating) if (m_bIsFloating)
g_pCompositor->changeWindowZOrder(m_pSelf.lock(), true); g_pCompositor->changeWindowZOrder(m_pSelf.lock(), true);
@@ -1511,7 +1534,7 @@ PHLWINDOW CWindow::getSwallower() {
if (!currentPid) if (!currentPid)
break; break;
for (auto& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped || w->isHidden()) if (!w->m_bIsMapped || w->isHidden())
continue; continue;
@@ -1536,7 +1559,7 @@ PHLWINDOW CWindow::getSwallower() {
return candidates.at(0); return candidates.at(0);
// walk up the focus history and find the last focused // walk up the focus history and find the last focused
for (auto& w : g_pCompositor->m_vWindowFocusHistory) { for (auto const& w : g_pCompositor->m_vWindowFocusHistory) {
if (!w) if (!w)
continue; continue;
@@ -1556,3 +1579,11 @@ void CWindow::unsetWindowData(eOverridePriority priority) {
element.second(m_pSelf.lock())->unset(priority); element.second(m_pSelf.lock())->unset(priority);
} }
} }
bool CWindow::isX11OverrideRedirect() {
return m_pXWaylandSurface && m_pXWaylandSurface->overrideRedirect;
}
bool CWindow::isModal() {
return (m_pXWaylandSurface && m_pXWaylandSurface->modal);
}

View File

@@ -174,6 +174,7 @@ struct SWindowData {
CWindowOverridableVar<bool> syncFullscreen = true; CWindowOverridableVar<bool> syncFullscreen = true;
CWindowOverridableVar<bool> tearing = false; CWindowOverridableVar<bool> tearing = false;
CWindowOverridableVar<bool> xray = false; CWindowOverridableVar<bool> xray = false;
CWindowOverridableVar<bool> renderUnfocused = false;
CWindowOverridableVar<int> rounding; CWindowOverridableVar<int> rounding;
CWindowOverridableVar<int> borderSize; CWindowOverridableVar<int> borderSize;
@@ -196,13 +197,14 @@ struct SWindowRule {
std::string szInitialTitle; std::string szInitialTitle;
std::string szInitialClass; std::string szInitialClass;
std::string szTag; std::string szTag;
int bX11 = -1; // -1 means "ANY" int bX11 = -1; // -1 means "ANY"
int bFloating = -1; int bFloating = -1;
int bFullscreen = -1; int bFullscreen = -1;
int bPinned = -1; int bPinned = -1;
int bFocus = -1; int bFocus = -1;
std::string szOnWorkspace = ""; // empty means any std::string szFullscreenState = ""; // empty means any
std::string szWorkspace = ""; // empty means any std::string szOnWorkspace = ""; // empty means any
std::string szWorkspace = ""; // empty means any
}; };
struct SInitialWorkspaceToken { struct SInitialWorkspaceToken {
@@ -270,7 +272,7 @@ class CWindow {
bool m_bDraggingTiled = false; // for dragging around tiled windows bool m_bDraggingTiled = false; // for dragging around tiled windows
bool m_bWasMaximized = false; bool m_bWasMaximized = false;
sFullscreenState m_sFullscreenState = {.internal = FSMODE_NONE, .client = FSMODE_NONE}; sFullscreenState m_sFullscreenState = {.internal = FSMODE_NONE, .client = FSMODE_NONE};
uint64_t m_iMonitorID = -1; MONITORID m_iMonitorID = -1;
std::string m_szTitle = ""; std::string m_szTitle = "";
std::string m_szClass = ""; std::string m_szClass = "";
std::string m_szInitialTitle = ""; std::string m_szInitialTitle = "";
@@ -287,8 +289,6 @@ class CWindow {
// XWayland stuff // XWayland stuff
bool m_bIsX11 = false; bool m_bIsX11 = false;
PHLWINDOWREF m_pX11Parent; PHLWINDOWREF m_pX11Parent;
uint64_t m_iX11Type = 0;
bool m_bIsModal = false;
bool m_bX11DoesntWantBorders = false; bool m_bX11DoesntWantBorders = false;
bool m_bX11ShouldntFocus = false; bool m_bX11ShouldntFocus = false;
float m_fX11SurfaceScaledBy = 1.f; float m_fX11SurfaceScaledBy = 1.f;
@@ -351,6 +351,10 @@ class CWindow {
// animated tint // animated tint
CAnimatedVariable<float> m_fDimPercent; CAnimatedVariable<float> m_fDimPercent;
// animate moving to an invisible workspace
int m_iMonitorMovedFrom = -1; // -1 means not moving
CAnimatedVariable<float> m_fMovingToWorkspaceAlpha;
// swallowing // swallowing
PHLWINDOWREF m_pSwallowed; PHLWINDOWREF m_pSwallowed;
@@ -358,8 +362,8 @@ class CWindow {
bool m_bStayFocused = false; bool m_bStayFocused = false;
// for toplevel monitor events // for toplevel monitor events
uint64_t m_iLastToplevelMonitorID = -1; MONITORID m_iLastToplevelMonitorID = -1;
uint64_t m_iLastSurfaceMonitorID = -1; MONITORID m_iLastSurfaceMonitorID = -1;
// for idle inhibiting windows // for idle inhibiting windows
eIdleInhibitMode m_eIdleInhibitMode = IDLEINHIBIT_NONE; eIdleInhibitMode m_eIdleInhibitMode = IDLEINHIBIT_NONE;
@@ -421,7 +425,7 @@ class CWindow {
bool canBeTorn(); bool canBeTorn();
void setSuspended(bool suspend); void setSuspended(bool suspend);
bool visibleOnMonitor(CMonitor* pMonitor); bool visibleOnMonitor(CMonitor* pMonitor);
int workspaceID(); WORKSPACEID workspaceID();
bool onSpecialWorkspace(); bool onSpecialWorkspace();
void activate(bool force = false); void activate(bool force = false);
int surfacesCount(); int surfacesCount();
@@ -463,6 +467,8 @@ class CWindow {
void warpCursor(); void warpCursor();
PHLWINDOW getSwallower(); PHLWINDOW getSwallower();
void unsetWindowData(eOverridePriority priority); void unsetWindowData(eOverridePriority priority);
bool isX11OverrideRedirect();
bool isModal();
// listeners // listeners
void onAck(uint32_t serial); void onAck(uint32_t serial);
@@ -490,9 +496,9 @@ class CWindow {
private: private:
// For hidden windows and stuff // For hidden windows and stuff
bool m_bHidden = false; bool m_bHidden = false;
bool m_bSuspended = false; bool m_bSuspended = false;
int m_iLastWorkspace = WORKSPACE_INVALID; WORKSPACEID m_iLastWorkspace = WORKSPACE_INVALID;
}; };
inline bool valid(PHLWINDOW w) { inline bool valid(PHLWINDOW w) {

View File

@@ -5,27 +5,28 @@
#include <hyprutils/string/String.hpp> #include <hyprutils/string/String.hpp>
using namespace Hyprutils::String; using namespace Hyprutils::String;
PHLWORKSPACE CWorkspace::create(int id, int monitorID, std::string name, bool special, bool isEmtpy) { PHLWORKSPACE CWorkspace::create(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmpty) {
PHLWORKSPACE workspace = makeShared<CWorkspace>(id, monitorID, name, special, isEmtpy); PHLWORKSPACE workspace = makeShared<CWorkspace>(id, monitorID, name, special, isEmpty);
workspace->init(workspace); workspace->init(workspace);
return workspace; return workspace;
} }
CWorkspace::CWorkspace(int id, int monitorID, std::string name, bool special, bool isEmtpy) { CWorkspace::CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bool special, bool isEmpty) {
m_iMonitorID = monitorID; m_iMonitorID = monitorID;
m_iID = id; m_iID = id;
m_szName = name; m_szName = name;
m_bIsSpecialWorkspace = special; m_bIsSpecialWorkspace = special;
m_bWasCreatedEmtpy = isEmtpy; m_bWasCreatedEmpty = isEmpty;
} }
void CWorkspace::init(PHLWORKSPACE self) { void CWorkspace::init(PHLWORKSPACE self) {
m_pSelf = self; m_pSelf = self;
m_vRenderOffset.create(m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), m_vRenderOffset.create(m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspaceIn") :
g_pConfigManager->getAnimationPropertyConfig("workspacesIn"),
self, AVARDAMAGE_ENTIRE); self, AVARDAMAGE_ENTIRE);
m_fAlpha.create(AVARTYPE_FLOAT, m_fAlpha.create(AVARTYPE_FLOAT,
m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), self, m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspaceIn") : g_pConfigManager->getAnimationPropertyConfig("workspacesIn"), self,
AVARDAMAGE_ENTIRE); AVARDAMAGE_ENTIRE);
m_fAlpha.setValueAndWarp(1.f); m_fAlpha.setValueAndWarp(1.f);
@@ -48,9 +49,9 @@ void CWorkspace::init(PHLWORKSPACE self) {
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(self); const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(self);
m_bPersistent = WORKSPACERULE.isPersistent; m_bPersistent = WORKSPACERULE.isPersistent;
if (self->m_bWasCreatedEmtpy) if (self->m_bWasCreatedEmpty)
if (auto cmd = WORKSPACERULE.onCreatedEmptyRunCmd) if (auto cmd = WORKSPACERULE.onCreatedEmptyRunCmd)
g_pKeybindManager->spawn(*cmd); g_pKeybindManager->spawnWithRules(*cmd, self);
g_pEventManager->postEvent({"createworkspace", m_szName}); g_pEventManager->postEvent({"createworkspace", m_szName});
g_pEventManager->postEvent({"createworkspacev2", std::format("{},{}", m_iID, m_szName)}); g_pEventManager->postEvent({"createworkspacev2", std::format("{},{}", m_iID, m_szName)});
@@ -81,12 +82,19 @@ CWorkspace::~CWorkspace() {
} }
void CWorkspace::startAnim(bool in, bool left, bool instant) { void CWorkspace::startAnim(bool in, bool left, bool instant) {
if (!instant) {
const std::string ANIMNAME = std::format("{}{}", m_bIsSpecialWorkspace ? "specialWorkspace" : "workspaces", in ? "In" : "Out");
m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME);
m_vRenderOffset.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME);
}
const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle; const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle;
static auto PWORKSPACEGAP = CConfigValue<Hyprlang::INT>("general:gaps_workspaces"); static auto PWORKSPACEGAP = CConfigValue<Hyprlang::INT>("general:gaps_workspaces");
// set floating windows offset callbacks // set floating windows offset callbacks
m_vRenderOffset.setUpdateCallback([&](void*) { m_vRenderOffset.setUpdateCallback([&](void*) {
for (auto& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (!validMapped(w) || w->workspaceID() != m_iID) if (!validMapped(w) || w->workspaceID() != m_iID)
continue; continue;
@@ -190,7 +198,7 @@ void CWorkspace::setActive(bool on) {
; // empty until https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/40 ; // empty until https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/40
} }
void CWorkspace::moveToMonitor(const int& id) { void CWorkspace::moveToMonitor(const MONITORID& id) {
; // empty until https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/40 ; // empty until https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/40
} }
@@ -275,7 +283,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
i = std::min(NEXTSPACE, std::string::npos - 1); i = std::min(NEXTSPACE, std::string::npos - 1);
if (cur == 'r') { if (cur == 'r') {
int from = 0, to = 0; WORKSPACEID from = 0, to = 0;
if (!prop.starts_with("r[") || !prop.ends_with("]")) { if (!prop.starts_with("r[") || !prop.ends_with("]")) {
Debug::log(LOG, "Invalid selector {}", selector); Debug::log(LOG, "Invalid selector {}", selector);
return false; return false;
@@ -365,7 +373,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
} }
if (cur == 'w') { if (cur == 'w') {
int from = 0, to = 0; WORKSPACEID from = 0, to = 0;
if (!prop.starts_with("w[") || !prop.ends_with("]")) { if (!prop.starts_with("w[") || !prop.ends_with("]")) {
Debug::log(LOG, "Invalid selector {}", selector); Debug::log(LOG, "Invalid selector {}", selector);
return false; return false;
@@ -378,7 +386,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
bool wantsCountVisible = false; bool wantsCountVisible = false;
int flagCount = 0; int flagCount = 0;
for (auto& flag : prop) { for (auto const& flag : prop) {
if (flag == 't' && wantsOnlyTiled == -1) { if (flag == 't' && wantsOnlyTiled == -1) {
wantsOnlyTiled = 1; wantsOnlyTiled = 1;
flagCount++; flagCount++;
@@ -446,7 +454,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
return false; return false;
} }
int count; WORKSPACEID count;
if (wantsCountGroup) if (wantsCountGroup)
count = g_pCompositor->getGroupsOnWorkspace(m_iID, wantsOnlyTiled == -1 ? std::nullopt : std::optional<bool>((bool)wantsOnlyTiled), count = g_pCompositor->getGroupsOnWorkspace(m_iID, wantsOnlyTiled == -1 ? std::nullopt : std::optional<bool>((bool)wantsOnlyTiled),
wantsCountVisible ? std::optional<bool>(wantsCountVisible) : std::nullopt); wantsCountVisible ? std::optional<bool>(wantsCountVisible) : std::nullopt);
@@ -506,7 +514,7 @@ bool CWorkspace::matchesStaticSelector(const std::string& selector_) {
void CWorkspace::markInert() { void CWorkspace::markInert() {
m_bInert = true; m_bInert = true;
m_iID = WORKSPACE_INVALID; m_iID = WORKSPACE_INVALID;
m_iMonitorID = -1; m_iMonitorID = MONITOR_INVALID;
m_bVisible = false; m_bVisible = false;
} }

View File

@@ -17,16 +17,16 @@ class CWindow;
class CWorkspace { class CWorkspace {
public: public:
static PHLWORKSPACE create(int id, int monitorID, std::string name, bool special = false, bool isEmtpy = true); static PHLWORKSPACE create(WORKSPACEID id, MONITORID monitorID, std::string name, bool special = false, bool isEmpty = true);
// use create() don't use this // use create() don't use this
CWorkspace(int id, int monitorID, std::string name, bool special = false, bool isEmpty = true); CWorkspace(WORKSPACEID id, MONITORID monitorID, std::string name, bool special = false, bool isEmpty = true);
~CWorkspace(); ~CWorkspace();
// Workspaces ID-based have IDs > 0 // Workspaces ID-based have IDs > 0
// and workspaces name-based have IDs starting with -1337 // and workspaces name-based have IDs starting with -1337
int m_iID = -1; WORKSPACEID m_iID = WORKSPACE_INVALID;
std::string m_szName = ""; std::string m_szName = "";
uint64_t m_iMonitorID = -1; MONITORID m_iMonitorID = MONITOR_INVALID;
// Previous workspace ID and name is stored during a workspace change, allowing travel // Previous workspace ID and name is stored during a workspace change, allowing travel
// to the previous workspace. // to the previous workspace.
SWorkspaceIDName m_sPrevWorkspace, m_sPrevWorkspacePerMonitor; SWorkspaceIDName m_sPrevWorkspace, m_sPrevWorkspacePerMonitor;
@@ -57,7 +57,7 @@ class CWorkspace {
// last monitor (used on reconnect) // last monitor (used on reconnect)
std::string m_szLastMonitor = ""; std::string m_szLastMonitor = "";
bool m_bWasCreatedEmtpy = true; bool m_bWasCreatedEmpty = true;
bool m_bPersistent = false; bool m_bPersistent = false;
@@ -67,7 +67,7 @@ class CWorkspace {
void startAnim(bool in, bool left, bool instant = false); void startAnim(bool in, bool left, bool instant = false);
void setActive(bool on); void setActive(bool on);
void moveToMonitor(const int&); void moveToMonitor(const MONITORID&);
PHLWINDOW getLastFocusedWindow(); PHLWINDOW getLastFocusedWindow();
void rememberPrevWorkspace(const PHLWORKSPACE& prevWorkspace); void rememberPrevWorkspace(const PHLWORKSPACE& prevWorkspace);

View File

@@ -119,7 +119,8 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) {
if (IDX != XKB_MOD_INVALID) if (IDX != XKB_MOD_INVALID)
modifiersState.locked |= (uint32_t)1 << IDX; modifiersState.locked |= (uint32_t)1 << IDX;
updateModifiers(modifiersState.depressed, modifiersState.latched, modifiersState.locked, modifiersState.group); // 0 to avoid mods getting stuck if depressed during reload
updateModifiers(0, 0, modifiersState.locked, modifiersState.group);
} }
for (size_t i = 0; i < LEDNAMES.size(); ++i) { for (size_t i = 0; i < LEDNAMES.size(); ++i) {

View File

@@ -27,7 +27,6 @@ namespace Events {
// Monitor part 2 the sequel // Monitor part 2 the sequel
DYNLISTENFUNC(monitorFrame); DYNLISTENFUNC(monitorFrame);
DYNLISTENFUNC(monitorDestroy);
DYNLISTENFUNC(monitorStateRequest); DYNLISTENFUNC(monitorStateRequest);
DYNLISTENFUNC(monitorDamage); DYNLISTENFUNC(monitorDamage);
DYNLISTENFUNC(monitorNeedsFrame); DYNLISTENFUNC(monitorNeedsFrame);

View File

@@ -85,31 +85,6 @@ void Events::listener_monitorFrame(void* owner, void* data) {
} }
} }
void Events::listener_monitorDestroy(void* owner, void* data) {
CMonitor* pMonitor = (CMonitor*)owner;
for (auto& m : g_pCompositor->m_vRealMonitors) {
if (m->output == pMonitor->output) {
pMonitor = m.get();
break;
}
}
if (!pMonitor)
return;
Debug::log(LOG, "Destroy called for monitor {}", pMonitor->output->name);
pMonitor->onDisconnect(true);
pMonitor->output = nullptr;
pMonitor->m_bRenderingInitPassed = false;
Debug::log(LOG, "Removing monitor {} from realMonitors", pMonitor->szName);
std::erase_if(g_pCompositor->m_vRealMonitors, [&](SP<CMonitor>& el) { return el.get() == pMonitor; });
}
void Events::listener_monitorNeedsFrame(void* owner, void* data) { void Events::listener_monitorNeedsFrame(void* owner, void* data) {
const auto PMONITOR = (CMonitor*)owner; const auto PMONITOR = (CMonitor*)owner;

View File

@@ -120,7 +120,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_bRequestsFloat = true; PWINDOW->m_bRequestsFloat = true;
} }
PWINDOW->m_bX11ShouldntFocus = PWINDOW->m_bX11ShouldntFocus || (PWINDOW->m_bIsX11 && PWINDOW->m_iX11Type == 2 && !PWINDOW->m_pXWaylandSurface->wantsFocus()); PWINDOW->m_bX11ShouldntFocus = PWINDOW->m_bX11ShouldntFocus || (PWINDOW->m_bIsX11 && PWINDOW->isX11OverrideRedirect() && !PWINDOW->m_pXWaylandSurface->wantsFocus());
if (PWORKSPACE->m_bDefaultFloating) if (PWORKSPACE->m_bDefaultFloating)
PWINDOW->m_bIsFloating = true; PWINDOW->m_bIsFloating = true;
@@ -139,7 +139,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (PWINDOW->m_bWantsInitialFullscreen || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->fullscreen)) if (PWINDOW->m_bWantsInitialFullscreen || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->fullscreen))
requestedClientFSMode = FSMODE_FULLSCREEN; requestedClientFSMode = FSMODE_FULLSCREEN;
for (auto& r : PWINDOW->m_vMatchedRules) { for (auto const& r : PWINDOW->m_vMatchedRules) {
if (r.szRule.starts_with("monitor")) { if (r.szRule.starts_with("monitor")) {
try { try {
const auto MONITORSTR = trim(r.szRule.substr(r.szRule.find(' '))); const auto MONITORSTR = trim(r.szRule.substr(r.szRule.find(' ')));
@@ -148,7 +148,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_iMonitorID = PMONITOR->ID; PWINDOW->m_iMonitorID = PMONITOR->ID;
} else { } else {
if (isNumber(MONITORSTR)) { if (isNumber(MONITORSTR)) {
const long int MONITOR = std::stoi(MONITORSTR); const MONITORID MONITOR = std::stoi(MONITORSTR);
if (!g_pCompositor->getMonitorFromID(MONITOR)) if (!g_pCompositor->getMonitorFromID(MONITOR))
PWINDOW->m_iMonitorID = 0; PWINDOW->m_iMonitorID = 0;
else else
@@ -326,7 +326,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_bCreatedOverFullscreen = true; PWINDOW->m_bCreatedOverFullscreen = true;
// size and move rules // size and move rules
for (auto& r : PWINDOW->m_vMatchedRules) { for (auto const& r : PWINDOW->m_vMatchedRules) {
if (r.szRule.starts_with("size")) { if (r.szRule.starts_with("size")) {
try { try {
const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1); const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1);
@@ -344,7 +344,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
Debug::log(LOG, "Rule size, applying to {}", PWINDOW); Debug::log(LOG, "Rule size, applying to {}", PWINDOW);
PWINDOW->m_vRealSize = Vector2D(SIZEX, SIZEY); PWINDOW->m_vRealSize = Vector2D(SIZEX, SIZEY);
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal();
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal());
PWINDOW->setHidden(false); PWINDOW->setHidden(false);
@@ -449,8 +450,36 @@ void Events::listener_mapWindow(void* owner, void* data) {
} else { } else {
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW); g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
// Set the pseudo size here too so that it doesnt end up being 0x0 bool setPseudo = false;
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal() - Vector2D(10, 10);
for (auto const& r : PWINDOW->m_vMatchedRules) {
if (r.szRule.starts_with("size")) {
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 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::stof(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::stof(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y);
Debug::log(LOG, "Rule size (tiled), applying to {}", PWINDOW);
setPseudo = true;
PWINDOW->m_vPseudoSize = Vector2D(SIZEX, SIZEY);
PWINDOW->setHidden(false);
} catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r.szRule, r.szValue); }
}
}
if (!setPseudo)
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal() - Vector2D(10, 10);
} }
const auto PFOCUSEDWINDOWPREV = g_pCompositor->m_pLastWindow.lock(); const auto PFOCUSEDWINDOWPREV = g_pCompositor->m_pLastWindow.lock();
@@ -477,7 +506,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
} }
if (!PWINDOW->m_sWindowData.noFocus.valueOrDefault() && !PWINDOW->m_bNoInitialFocus && if (!PWINDOW->m_sWindowData.noFocus.valueOrDefault() && !PWINDOW->m_bNoInitialFocus &&
(PWINDOW->m_iX11Type != 2 || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->wantsFocus())) && !workspaceSilent && (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW) && (!PWINDOW->isX11OverrideRedirect() || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->wantsFocus())) && !workspaceSilent && (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW) &&
!g_pInputManager->isConstrained()) { !g_pInputManager->isConstrained()) {
g_pCompositor->focusWindow(PWINDOW); g_pCompositor->focusWindow(PWINDOW);
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA); PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA);
@@ -577,7 +606,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
g_pCompositor->updateWorkspaceWindows(PWINDOW->workspaceID()); g_pCompositor->updateWorkspaceWindows(PWINDOW->workspaceID());
if (PMONITOR && PWINDOW->m_iX11Type == 2) if (PMONITOR && PWINDOW->isX11OverrideRedirect())
PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale; PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale;
} }
@@ -648,7 +677,12 @@ void Events::listener_unmapWindow(void* owner, void* data) {
// refocus on a new window if needed // refocus on a new window if needed
if (wasLastWindow) { if (wasLastWindow) {
const auto PWINDOWCANDIDATE = g_pLayoutManager->getCurrentLayout()->getNextWindowCandidate(PWINDOW); static auto FOCUSONCLOSE = CConfigValue<Hyprlang::INT>("input:focus_on_close");
PHLWINDOW PWINDOWCANDIDATE = nullptr;
if (*FOCUSONCLOSE)
PWINDOWCANDIDATE = (g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING));
else
PWINDOWCANDIDATE = g_pLayoutManager->getCurrentLayout()->getNextWindowCandidate(PWINDOW);
Debug::log(LOG, "On closed window, new focused candidate is {}", PWINDOWCANDIDATE); Debug::log(LOG, "On closed window, new focused candidate is {}", PWINDOWCANDIDATE);
@@ -811,7 +845,7 @@ void Events::listener_activateX11(void* owner, void* data) {
Debug::log(LOG, "X11 Activate request for window {}", PWINDOW); Debug::log(LOG, "X11 Activate request for window {}", PWINDOW);
if (PWINDOW->m_iX11Type == 2) { if (PWINDOW->isX11OverrideRedirect()) {
Debug::log(LOG, "Unmanaged X11 {} requests activate", PWINDOW); Debug::log(LOG, "Unmanaged X11 {} requests activate", PWINDOW);

View File

@@ -12,7 +12,7 @@ void CBezierCurve::setup(std::vector<Vector2D>* pVec) {
m_dPoints.emplace_back(Vector2D(0, 0)); m_dPoints.emplace_back(Vector2D(0, 0));
for (auto& p : *pVec) { for (auto const& p : *pVec) {
m_dPoints.push_back(p); m_dPoints.push_back(p);
} }

View File

@@ -21,6 +21,6 @@ CColor::CColor(uint64_t hex) {
this->a = ALPHA(hex); this->a = ALPHA(hex);
} }
uint32_t CColor::getAsHex() { uint32_t CColor::getAsHex() const {
return (uint32_t)(a * 255.f) * 0x1000000 + (uint32_t)(r * 255.f) * 0x10000 + (uint32_t)(g * 255.f) * 0x100 + (uint32_t)(b * 255.f) * 0x1; return (uint32_t)(a * 255.f) * 0x1000000 + (uint32_t)(r * 255.f) * 0x10000 + (uint32_t)(g * 255.f) * 0x100 + (uint32_t)(b * 255.f) * 0x1;
} }

View File

@@ -10,7 +10,7 @@ class CColor {
float r = 0, g = 0, b = 0, a = 1.f; float r = 0, g = 0, b = 0, a = 1.f;
uint32_t getAsHex(); uint32_t getAsHex() const;
CColor operator-(const CColor& c2) const { CColor operator-(const CColor& c2) const {
return CColor(r - c2.r, g - c2.g, b - c2.b, a - c2.a); return CColor(r - c2.r, g - c2.g, b - c2.b, a - c2.a);

View File

@@ -252,7 +252,7 @@ DRMFormat FormatUtils::shmToDRM(SHMFormat shm) {
} }
const SPixelFormat* FormatUtils::getPixelFormatFromDRM(DRMFormat drm) { const SPixelFormat* FormatUtils::getPixelFormatFromDRM(DRMFormat drm) {
for (auto& fmt : GLES3_FORMATS) { for (auto const& fmt : GLES3_FORMATS) {
if (fmt.drmFormat == drm) if (fmt.drmFormat == drm)
return &fmt; return &fmt;
} }
@@ -261,7 +261,7 @@ const SPixelFormat* FormatUtils::getPixelFormatFromDRM(DRMFormat drm) {
} }
const SPixelFormat* FormatUtils::getPixelFormatFromGL(uint32_t glFormat, uint32_t glType, bool alpha) { const SPixelFormat* FormatUtils::getPixelFormatFromGL(uint32_t glFormat, uint32_t glType, bool alpha) {
for (auto& fmt : GLES3_FORMATS) { for (auto const& fmt : GLES3_FORMATS) {
if (fmt.glFormat == (int)glFormat && fmt.glType == (int)glType && fmt.withAlpha == alpha) if (fmt.glFormat == (int)glFormat && fmt.glType == (int)glType && fmt.withAlpha == alpha)
return &fmt; return &fmt;
} }

View File

@@ -180,7 +180,7 @@ void handleNoop(struct wl_listener* listener, void* data) {
std::string escapeJSONStrings(const std::string& str) { std::string escapeJSONStrings(const std::string& str) {
std::ostringstream oss; std::ostringstream oss;
for (auto& c : str) { for (auto const& c : str) {
switch (c) { switch (c) {
case '"': oss << "\\\""; break; case '"': oss << "\\\""; break;
case '\\': oss << "\\\\"; break; case '\\': oss << "\\\\"; break;
@@ -249,17 +249,17 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
return {WORKSPACE_INVALID}; return {WORKSPACE_INVALID};
} }
std::set<int> invalidWSes; std::set<WORKSPACEID> invalidWSes;
if (same_mon) { if (same_mon) {
for (auto& rule : g_pConfigManager->getAllWorkspaceRules()) { for (auto const& rule : g_pConfigManager->getAllWorkspaceRules()) {
const auto PMONITOR = g_pCompositor->getMonitorFromName(rule.monitor); const auto PMONITOR = g_pCompositor->getMonitorFromName(rule.monitor);
if (PMONITOR && (PMONITOR->ID != g_pCompositor->m_pLastMonitor->ID)) if (PMONITOR && (PMONITOR->ID != g_pCompositor->m_pLastMonitor->ID))
invalidWSes.insert(rule.workspaceId); invalidWSes.insert(rule.workspaceId);
} }
} }
int id = next ? g_pCompositor->m_pLastMonitor->activeWorkspaceID() : 0; WORKSPACEID id = next ? g_pCompositor->m_pLastMonitor->activeWorkspaceID() : 0;
while (++id < INT_MAX) { while (++id < LONG_MAX) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id); const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id);
if (!invalidWSes.contains(id) && (!PWORKSPACE || g_pCompositor->getWindowsOnWorkspace(id) == 0)) { if (!invalidWSes.contains(id) && (!PWORKSPACE || g_pCompositor->getWindowsOnWorkspace(id) == 0)) {
result.id = id; result.id = id;
@@ -296,18 +296,18 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
result.id = (int)PLUSMINUSRESULT.value(); result.id = (int)PLUSMINUSRESULT.value();
int remains = (int)result.id; WORKSPACEID remains = result.id;
std::set<int> invalidWSes; std::set<WORKSPACEID> invalidWSes;
// Collect all the workspaces we can't jump to. // Collect all the workspaces we can't jump to.
for (auto& ws : g_pCompositor->m_vWorkspaces) { for (auto const& ws : g_pCompositor->m_vWorkspaces) {
if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID)) { if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID)) {
// Can't jump to this workspace // Can't jump to this workspace
invalidWSes.insert(ws->m_iID); invalidWSes.insert(ws->m_iID);
} }
} }
for (auto& rule : g_pConfigManager->getAllWorkspaceRules()) { for (auto const& rule : g_pConfigManager->getAllWorkspaceRules()) {
const auto PMONITOR = g_pCompositor->getMonitorFromName(rule.monitor); const auto PMONITOR = g_pCompositor->getMonitorFromName(rule.monitor);
if (!PMONITOR || PMONITOR->ID == g_pCompositor->m_pLastMonitor->ID) { if (!PMONITOR || PMONITOR->ID == g_pCompositor->m_pLastMonitor->ID) {
// Can't be invalid // Can't be invalid
@@ -318,8 +318,8 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
} }
// Prepare all named workspaces in case when we need them // Prepare all named workspaces in case when we need them
std::vector<int> namedWSes; std::vector<WORKSPACEID> namedWSes;
for (auto& ws : g_pCompositor->m_vWorkspaces) { for (auto const& ws : g_pCompositor->m_vWorkspaces) {
if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) || ws->m_iID >= 0) if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) || ws->m_iID >= 0)
continue; continue;
@@ -347,19 +347,19 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
} else { } else {
// Just take a blind guess at where we'll probably end up // Just take a blind guess at where we'll probably end up
int activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1; WORKSPACEID activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1;
int predictedWSID = activeWSID + remains; WORKSPACEID predictedWSID = activeWSID + remains;
int remainingWSes = 0; int remainingWSes = 0;
char walkDir = in[1]; char walkDir = in[1];
// sanitize. 0 means invalid oob in - // sanitize. 0 means invalid oob in -
predictedWSID = std::max(predictedWSID, 0); predictedWSID = std::max(predictedWSID, static_cast<int64_t>(0));
// Count how many invalidWSes are in between (how bad the prediction was) // Count how many invalidWSes are in between (how bad the prediction was)
int beginID = in[1] == '+' ? activeWSID + 1 : predictedWSID; WORKSPACEID beginID = in[1] == '+' ? activeWSID + 1 : predictedWSID;
int endID = in[1] == '+' ? predictedWSID : activeWSID; WORKSPACEID endID = in[1] == '+' ? predictedWSID : activeWSID;
auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >= auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >=
for (auto it = begin; *it <= endID && it != invalidWSes.end(); it++) { for (auto it = begin; it != invalidWSes.end() && *it <= endID; it++) {
remainingWSes++; remainingWSes++;
} }
@@ -367,7 +367,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
if (activeWSID < 0) { if (activeWSID < 0) {
// Behaviour similar to 'm' // Behaviour similar to 'm'
// Find current // Find current
int currentItem = -1; size_t currentItem = -1;
for (size_t i = 0; i < namedWSes.size(); i++) { for (size_t i = 0; i < namedWSes.size(); i++) {
if (namedWSes[i] == activeWSID) { if (namedWSes[i] == activeWSID) {
currentItem = i; currentItem = i;
@@ -376,15 +376,15 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
} }
currentItem += remains; currentItem += remains;
currentItem = std::max(currentItem, 0); currentItem = std::max(currentItem, static_cast<size_t>(0));
if (currentItem >= (int)namedWSes.size()) { if (currentItem >= namedWSes.size()) {
// At the seam between namedWSes and normal WSes. Behave like r+[diff] at imaginary ws 0 // At the seam between namedWSes and normal WSes. Behave like r+[diff] at imaginary ws 0
int diff = currentItem - (namedWSes.size() - 1); size_t diff = currentItem - (namedWSes.size() - 1);
predictedWSID = diff; predictedWSID = diff;
int beginID = 1; WORKSPACEID beginID = 1;
int endID = predictedWSID; WORKSPACEID endID = predictedWSID;
auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >= auto begin = invalidWSes.upper_bound(beginID - 1); // upper_bound is >, we want >=
for (auto it = begin; *it <= endID && it != invalidWSes.end(); it++) { for (auto it = begin; it != invalidWSes.end() && *it <= endID; it++) {
remainingWSes++; remainingWSes++;
} }
walkDir = '+'; walkDir = '+';
@@ -397,10 +397,10 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
// Go in the search direction for remainingWSes // Go in the search direction for remainingWSes
// The performance impact is directly proportional to the number of open and bound workspaces // The performance impact is directly proportional to the number of open and bound workspaces
int finalWSID = predictedWSID; WORKSPACEID finalWSID = predictedWSID;
if (walkDir == '-') { if (walkDir == '-') {
int beginID = finalWSID; WORKSPACEID beginID = finalWSID;
int curID = finalWSID; WORKSPACEID curID = finalWSID;
while (--curID > 0 && remainingWSes > 0) { while (--curID > 0 && remainingWSes > 0) {
if (!invalidWSes.contains(curID)) { if (!invalidWSes.contains(curID)) {
remainingWSes--; remainingWSes--;
@@ -411,9 +411,9 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
if (namedWSes.size()) { if (namedWSes.size()) {
// Go to the named workspaces // Go to the named workspaces
// Need remainingWSes more // Need remainingWSes more
int namedWSIdx = namedWSes.size() - remainingWSes; auto namedWSIdx = namedWSes.size() - remainingWSes;
// Sanitze // Sanitze
namedWSIdx = std::clamp(namedWSIdx, 0, (int)namedWSes.size() - 1); namedWSIdx = std::clamp(namedWSIdx, static_cast<size_t>(0), namedWSes.size() - static_cast<size_t>(1));
finalWSID = namedWSes[namedWSIdx]; finalWSID = namedWSes[namedWSIdx];
} else { } else {
// Couldn't find valid workspace in negative direction, search last first one back up positive direction // Couldn't find valid workspace in negative direction, search last first one back up positive direction
@@ -425,7 +425,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
} }
} }
if (walkDir == '+') { if (walkDir == '+') {
int curID = finalWSID; WORKSPACEID curID = finalWSID;
while (++curID < INT32_MAX && remainingWSes > 0) { while (++curID < INT32_MAX && remainingWSes > 0) {
if (!invalidWSes.contains(curID)) { if (!invalidWSes.contains(curID)) {
remainingWSes--; remainingWSes--;
@@ -460,10 +460,10 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
result.id = (int)PLUSMINUSRESULT.value(); result.id = (int)PLUSMINUSRESULT.value();
// result now has +/- what we should move on mon // result now has +/- what we should move on mon
int remains = (int)result.id; int remains = (int)result.id;
std::vector<int> validWSes; std::vector<WORKSPACEID> validWSes;
for (auto& ws : g_pCompositor->m_vWorkspaces) { for (auto const& ws : g_pCompositor->m_vWorkspaces) {
if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID && !onAllMonitors)) if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID && !onAllMonitors))
continue; continue;
@@ -472,7 +472,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
std::sort(validWSes.begin(), validWSes.end()); std::sort(validWSes.begin(), validWSes.end());
int currentItem = -1; ssize_t currentItem = -1;
if (absolute) { if (absolute) {
// 1-index // 1-index
@@ -481,7 +481,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
// clamp // clamp
if (currentItem < 0) { if (currentItem < 0) {
currentItem = 0; currentItem = 0;
} else if (currentItem >= (int)validWSes.size()) { } else if (currentItem >= (ssize_t)validWSes.size()) {
currentItem = validWSes.size() - 1; currentItem = validWSes.size() - 1;
} }
} else { } else {
@@ -489,8 +489,8 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
remains = remains < 0 ? -((-remains) % validWSes.size()) : remains % validWSes.size(); remains = remains < 0 ? -((-remains) % validWSes.size()) : remains % validWSes.size();
// get the current item // get the current item
int activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1; WORKSPACEID activeWSID = g_pCompositor->m_pLastMonitor->activeWorkspace ? g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID : 1;
for (size_t i = 0; i < validWSes.size(); i++) { for (ssize_t i = 0; i < (ssize_t)validWSes.size(); i++) {
if (validWSes[i] == activeWSID) { if (validWSes[i] == activeWSID) {
currentItem = i; currentItem = i;
break; break;
@@ -501,7 +501,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
currentItem += remains; currentItem += remains;
// sanitize // sanitize
if (currentItem >= (int)validWSes.size()) { if (currentItem >= (ssize_t)validWSes.size()) {
currentItem = currentItem % validWSes.size(); currentItem = currentItem % validWSes.size();
} else if (currentItem < 0) { } else if (currentItem < 0) {
currentItem = validWSes.size() + currentItem; currentItem = validWSes.size() + currentItem;
@@ -547,9 +547,9 @@ std::optional<std::string> cleanCmdForWorkspace(const std::string& inWorkspaceNa
const std::string workspaceRule = "workspace " + inWorkspaceName; const std::string workspaceRule = "workspace " + inWorkspaceName;
if (cmd[0] == '[') { if (cmd[0] == '[') {
const int closingBracketIdx = cmd.find_last_of(']'); const auto closingBracketIdx = cmd.find_last_of(']');
auto tmpRules = cmd.substr(1, closingBracketIdx - 1); auto tmpRules = cmd.substr(1, closingBracketIdx - 1);
cmd = cmd.substr(closingBracketIdx + 1); cmd = cmd.substr(closingBracketIdx + 1);
auto rulesList = CVarList(tmpRules, 0, ';'); auto rulesList = CVarList(tmpRules, 0, ';');
@@ -785,13 +785,13 @@ std::vector<SCallstackFrameInfo> getBacktrace() {
#ifdef HAS_EXECINFO #ifdef HAS_EXECINFO
void* bt[1024]; void* bt[1024];
size_t btSize; int btSize;
char** btSymbols; char** btSymbols;
btSize = backtrace(bt, 1024); btSize = backtrace(bt, 1024);
btSymbols = backtrace_symbols(bt, btSize); btSymbols = backtrace_symbols(bt, btSize);
for (size_t i = 0; i < btSize; ++i) { for (auto i = 0; i < btSize; ++i) {
callstack.emplace_back(SCallstackFrameInfo{bt[i], std::string{btSymbols[i]}}); callstack.emplace_back(SCallstackFrameInfo{bt[i], std::string{btSymbols[i]}});
} }
#else #else

View File

@@ -6,6 +6,8 @@
#include "math/Math.hpp" #include "math/Math.hpp"
#include <vector> #include <vector>
#include <format> #include <format>
#include "../SharedDefs.hpp"
#include "../macros.hpp"
struct SCallstackFrameInfo { struct SCallstackFrameInfo {
void* adr = nullptr; void* adr = nullptr;
@@ -13,7 +15,7 @@ struct SCallstackFrameInfo {
}; };
struct SWorkspaceIDName { struct SWorkspaceIDName {
int id = -1; WORKSPACEID id = WORKSPACE_INVALID;
std::string name; std::string name;
}; };

View File

@@ -2,7 +2,6 @@
#include "MiscFunctions.hpp" #include "MiscFunctions.hpp"
#include "math/Math.hpp" #include "math/Math.hpp"
#include "sync/SyncReleaser.hpp" #include "sync/SyncReleaser.hpp"
#include "ScopeGuard.hpp"
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include "../config/ConfigValue.hpp" #include "../config/ConfigValue.hpp"
#include "../protocols/GammaControl.hpp" #include "../protocols/GammaControl.hpp"
@@ -17,7 +16,9 @@
#include "sync/SyncTimeline.hpp" #include "sync/SyncTimeline.hpp"
#include <aquamarine/output/Output.hpp> #include <aquamarine/output/Output.hpp>
#include <hyprutils/string/String.hpp> #include <hyprutils/string/String.hpp>
#include <hyprutils/utils/ScopeGuard.hpp>
using namespace Hyprutils::String; using namespace Hyprutils::String;
using namespace Hyprutils::Utils;
int ratHandler(void* data) { int ratHandler(void* data) {
g_pHyprRenderer->renderMonitor((CMonitor*)data); g_pHyprRenderer->renderMonitor((CMonitor*)data);
@@ -25,7 +26,7 @@ int ratHandler(void* data) {
return 1; return 1;
} }
CMonitor::CMonitor() : state(this) { CMonitor::CMonitor(SP<Aquamarine::IOutput> output_) : state(this), output(output_) {
; ;
} }
@@ -40,14 +41,27 @@ void CMonitor::onConnect(bool noRule) {
outTimeline = CSyncTimeline::create(output->getBackend()->drmFD()); outTimeline = CSyncTimeline::create(output->getBackend()->drmFD());
} }
listeners.frame = output->events.frame.registerListener([this](std::any d) { Events::listener_monitorFrame(this, nullptr); }); listeners.frame = output->events.frame.registerListener([this](std::any d) { Events::listener_monitorFrame(this, nullptr); });
listeners.destroy = output->events.destroy.registerListener([this](std::any d) { Events::listener_monitorDestroy(this, nullptr); }); listeners.commit = output->events.commit.registerListener([this](std::any d) { Events::listener_monitorCommit(this, nullptr); });
listeners.commit = output->events.commit.registerListener([this](std::any d) { Events::listener_monitorCommit(this, nullptr); });
listeners.needsFrame = listeners.needsFrame =
output->events.needsFrame.registerListener([this](std::any d) { g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); }); output->events.needsFrame.registerListener([this](std::any d) { g_pCompositor->scheduleFrameForMonitor(this, Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); });
listeners.presented = output->events.present.registerListener([this](std::any d) { listeners.presented = output->events.present.registerListener([this](std::any d) {
auto E = std::any_cast<Aquamarine::IOutput::SPresentEvent>(d); auto E = std::any_cast<Aquamarine::IOutput::SPresentEvent>(d);
PROTO::presentation->onPresented(this, E.when, E.refresh, E.seq, E.flags); PROTO::presentation->onPresented(self.lock(), E.when, E.refresh, E.seq, E.flags);
});
listeners.destroy = output->events.destroy.registerListener([this](std::any d) {
Debug::log(LOG, "Destroy called for monitor {}", szName);
onDisconnect(true);
output = nullptr;
m_bRenderingInitPassed = false;
Debug::log(LOG, "Removing monitor {} from realMonitors", szName);
std::erase_if(g_pCompositor->m_vRealMonitors, [&](SP<CMonitor>& el) { return el.get() == this; });
}); });
listeners.state = output->events.state.registerListener([this](std::any d) { listeners.state = output->events.state.registerListener([this](std::any d) {
@@ -158,7 +172,7 @@ void CMonitor::onConnect(bool noRule) {
setupDefaultWS(monitorRule); setupDefaultWS(monitorRule);
for (auto& ws : g_pCompositor->m_vWorkspaces) { for (auto const& ws : g_pCompositor->m_vWorkspaces) {
if (!valid(ws)) if (!valid(ws))
continue; continue;
@@ -179,10 +193,6 @@ void CMonitor::onConnect(bool noRule) {
if (!activeMonitorRule.mirrorOf.empty()) if (!activeMonitorRule.mirrorOf.empty())
setMirror(activeMonitorRule.mirrorOf); setMirror(activeMonitorRule.mirrorOf);
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName});
g_pEventManager->postEvent(SHyprIPCEvent{"monitoraddedv2", std::format("{},{},{}", ID, szName, szShortDescription)});
EMIT_HOOK_EVENT("monitorAdded", this);
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
g_pCompositor->setActiveMonitor(this); g_pCompositor->setActiveMonitor(this);
@@ -194,7 +204,7 @@ void CMonitor::onConnect(bool noRule) {
// verify last mon valid // verify last mon valid
bool found = false; bool found = false;
for (auto& m : g_pCompositor->m_vMonitors) { for (auto const& m : g_pCompositor->m_vMonitors) {
if (m == g_pCompositor->m_pLastMonitor) { if (m == g_pCompositor->m_pLastMonitor) {
found = true; found = true;
break; break;
@@ -211,6 +221,10 @@ void CMonitor::onConnect(bool noRule) {
PROTO::gamma->applyGammaToState(this); PROTO::gamma->applyGammaToState(this);
events.connect.emit(); events.connect.emit();
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName});
g_pEventManager->postEvent(SHyprIPCEvent{"monitoraddedv2", std::format("{},{},{}", ID, szName, szShortDescription)});
EMIT_HOOK_EVENT("monitorAdded", this);
} }
void CMonitor::onDisconnect(bool destroy) { void CMonitor::onDisconnect(bool destroy) {
@@ -229,7 +243,7 @@ void CMonitor::onDisconnect(bool destroy) {
// Cleanup everything. Move windows back, snap cursor, shit. // Cleanup everything. Move windows back, snap cursor, shit.
CMonitor* BACKUPMON = nullptr; CMonitor* BACKUPMON = nullptr;
for (auto& m : g_pCompositor->m_vMonitors) { for (auto const& m : g_pCompositor->m_vMonitors) {
if (m.get() != this) { if (m.get() != this) {
BACKUPMON = m.get(); BACKUPMON = m.get();
break; break;
@@ -246,7 +260,7 @@ void CMonitor::onDisconnect(bool destroy) {
} }
if (!mirrors.empty()) { if (!mirrors.empty()) {
for (auto& m : mirrors) { for (auto const& m : mirrors) {
m->setMirror(""); m->setMirror("");
} }
@@ -259,7 +273,7 @@ void CMonitor::onDisconnect(bool destroy) {
listeners.commit.reset(); listeners.commit.reset();
for (size_t i = 0; i < 4; ++i) { for (size_t i = 0; i < 4; ++i) {
for (auto& ls : m_aLayerSurfaceLayers[i]) { for (auto const& ls : m_aLayerSurfaceLayers[i]) {
if (ls->layerSurface && !ls->fadingOut) if (ls->layerSurface && !ls->fadingOut)
ls->layerSurface->sendClosed(); ls->layerSurface->sendClosed();
} }
@@ -268,9 +282,6 @@ void CMonitor::onDisconnect(bool destroy) {
Debug::log(LOG, "Removed monitor {}!", szName); Debug::log(LOG, "Removed monitor {}!", szName);
g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName});
EMIT_HOOK_EVENT("monitorRemoved", this);
if (!BACKUPMON) { if (!BACKUPMON) {
Debug::log(WARN, "Unplugged last monitor, entering an unsafe state. Good luck my friend."); Debug::log(WARN, "Unplugged last monitor, entering an unsafe state. Good luck my friend.");
g_pCompositor->enterUnsafeState(); g_pCompositor->enterUnsafeState();
@@ -285,13 +296,13 @@ void CMonitor::onDisconnect(bool destroy) {
// move workspaces // move workspaces
std::deque<PHLWORKSPACE> wspToMove; std::deque<PHLWORKSPACE> wspToMove;
for (auto& w : g_pCompositor->m_vWorkspaces) { for (auto const& w : g_pCompositor->m_vWorkspaces) {
if (w->m_iMonitorID == ID || !g_pCompositor->getMonitorFromID(w->m_iMonitorID)) { if (w->m_iMonitorID == ID || !g_pCompositor->getMonitorFromID(w->m_iMonitorID)) {
wspToMove.push_back(w); wspToMove.push_back(w);
} }
} }
for (auto& w : wspToMove) { for (auto const& w : wspToMove) {
w->m_szLastMonitor = szName; w->m_szLastMonitor = szName;
g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON); g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON);
w->startAnim(true, true, true); w->startAnim(true, true, true);
@@ -319,7 +330,7 @@ void CMonitor::onDisconnect(bool destroy) {
int mostHz = 0; int mostHz = 0;
CMonitor* pMonitorMostHz = nullptr; CMonitor* pMonitorMostHz = nullptr;
for (auto& m : g_pCompositor->m_vMonitors) { for (auto const& m : g_pCompositor->m_vMonitors) {
if (m->refreshRate > mostHz && m.get() != this) { if (m->refreshRate > mostHz && m.get() != this) {
pMonitorMostHz = m.get(); pMonitorMostHz = m.get();
mostHz = m->refreshRate; mostHz = m->refreshRate;
@@ -329,6 +340,9 @@ void CMonitor::onDisconnect(bool destroy) {
g_pHyprRenderer->m_pMostHzMonitor = pMonitorMostHz; g_pHyprRenderer->m_pMostHzMonitor = pMonitorMostHz;
} }
std::erase_if(g_pCompositor->m_vMonitors, [&](SP<CMonitor>& el) { return el.get() == this; }); std::erase_if(g_pCompositor->m_vMonitors, [&](SP<CMonitor>& el) { return el.get() == this; });
g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", szName});
EMIT_HOOK_EVENT("monitorRemoved", this);
} }
void CMonitor::addDamage(const pixman_region32_t* rg) { void CMonitor::addDamage(const pixman_region32_t* rg) {
@@ -389,8 +403,8 @@ bool CMonitor::matchesStaticSelector(const std::string& selector) const {
} }
} }
int CMonitor::findAvailableDefaultWS() { WORKSPACEID CMonitor::findAvailableDefaultWS() {
for (size_t i = 1; i < INT32_MAX; ++i) { for (WORKSPACEID i = 1; i < LONG_MAX; ++i) {
if (g_pCompositor->getWorkspaceByID(i)) if (g_pCompositor->getWorkspaceByID(i))
continue; continue;
@@ -400,7 +414,7 @@ int CMonitor::findAvailableDefaultWS() {
return i; return i;
} }
return INT32_MAX; // shouldn't be reachable return LONG_MAX; // shouldn't be reachable
} }
void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) { void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) {
@@ -503,7 +517,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
g_pHyprRenderer->applyMonitorRule(this, (SMonitorRule*)&RULE, true); // will apply the offset and stuff g_pHyprRenderer->applyMonitorRule(this, (SMonitorRule*)&RULE, true); // will apply the offset and stuff
} else { } else {
CMonitor* BACKUPMON = nullptr; CMonitor* BACKUPMON = nullptr;
for (auto& m : g_pCompositor->m_vMonitors) { for (auto const& m : g_pCompositor->m_vMonitors) {
if (m.get() != this) { if (m.get() != this) {
BACKUPMON = m.get(); BACKUPMON = m.get();
break; break;
@@ -512,13 +526,13 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
// move all the WS // move all the WS
std::deque<PHLWORKSPACE> wspToMove; std::deque<PHLWORKSPACE> wspToMove;
for (auto& w : g_pCompositor->m_vWorkspaces) { for (auto const& w : g_pCompositor->m_vWorkspaces) {
if (w->m_iMonitorID == ID) { if (w->m_iMonitorID == ID) {
wspToMove.push_back(w); wspToMove.push_back(w);
} }
} }
for (auto& w : wspToMove) { for (auto const& w : wspToMove) {
g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON); g_pCompositor->moveWorkspaceToMonitor(w, BACKUPMON);
w->startAnim(true, true, true); w->startAnim(true, true, true);
} }
@@ -592,7 +606,7 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo
pWorkspace->startAnim(true, ANIMTOLEFT); pWorkspace->startAnim(true, ANIMTOLEFT);
// move pinned windows // move pinned windows
for (auto& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (w->m_pWorkspace == POLDWORKSPACE && w->m_bPinned) if (w->m_pWorkspace == POLDWORKSPACE && w->m_bPinned)
w->moveToWorkspace(pWorkspace); w->moveToWorkspace(pWorkspace);
} }
@@ -638,7 +652,7 @@ void CMonitor::changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal, bo
g_pCompositor->updateFullscreenFadeOnWorkspace(activeSpecialWorkspace); g_pCompositor->updateFullscreenFadeOnWorkspace(activeSpecialWorkspace);
} }
void CMonitor::changeWorkspace(const int& id, bool internal, bool noMouseMove, bool noFocus) { void CMonitor::changeWorkspace(const WORKSPACEID& id, bool internal, bool noMouseMove, bool noFocus) {
changeWorkspace(g_pCompositor->getWorkspaceByID(id), internal, noMouseMove, noFocus); changeWorkspace(g_pCompositor->getWorkspaceByID(id), internal, noMouseMove, noFocus);
} }
@@ -701,14 +715,14 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) {
if (animate) if (animate)
pWorkspace->startAnim(true, true); pWorkspace->startAnim(true, true);
for (auto& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (w->m_pWorkspace == pWorkspace) { if (w->m_pWorkspace == pWorkspace) {
w->m_iMonitorID = ID; w->m_iMonitorID = ID;
w->updateSurfaceScaleTransformDetails(); w->updateSurfaceScaleTransformDetails();
w->setAnimationsToMove(); w->setAnimationsToMove();
const auto MIDDLE = w->middle(); const auto MIDDLE = w->middle();
if (w->m_bIsFloating && !VECINRECT(MIDDLE, vecPosition.x, vecPosition.y, vecPosition.x + vecSize.x, vecPosition.y + vecSize.y) && w->m_iX11Type != 2) { if (w->m_bIsFloating && !VECINRECT(MIDDLE, vecPosition.x, vecPosition.y, vecPosition.x + vecSize.x, vecPosition.y + vecSize.y) && !w->isX11OverrideRedirect()) {
// if it's floating and the middle isnt on the current mon, move it to the center // if it's floating and the middle isnt on the current mon, move it to the center
const auto PMONFROMMIDDLE = g_pCompositor->getMonitorFromVector(MIDDLE); const auto PMONFROMMIDDLE = g_pCompositor->getMonitorFromVector(MIDDLE);
Vector2D pos = w->m_vRealPosition.goal(); Vector2D pos = w->m_vRealPosition.goal();
@@ -745,7 +759,7 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) {
g_pCompositor->updateSuspendedStates(); g_pCompositor->updateSuspendedStates();
} }
void CMonitor::setSpecialWorkspace(const int& id) { void CMonitor::setSpecialWorkspace(const WORKSPACEID& id) {
setSpecialWorkspace(g_pCompositor->getWorkspaceByID(id)); setSpecialWorkspace(g_pCompositor->getWorkspaceByID(id));
} }
@@ -766,11 +780,11 @@ void CMonitor::updateMatrix() {
} }
} }
int64_t CMonitor::activeWorkspaceID() { WORKSPACEID CMonitor::activeWorkspaceID() {
return activeWorkspace ? activeWorkspace->m_iID : 0; return activeWorkspace ? activeWorkspace->m_iID : 0;
} }
int64_t CMonitor::activeSpecialWorkspaceID() { WORKSPACEID CMonitor::activeSpecialWorkspaceID() {
return activeSpecialWorkspace ? activeSpecialWorkspace->m_iID : 0; return activeSpecialWorkspace ? activeSpecialWorkspace->m_iID : 0;
} }
@@ -819,6 +833,21 @@ bool CMonitor::attemptDirectScanout() {
// FIXME: make sure the buffer actually follows the available scanout dmabuf formats // FIXME: make sure the buffer actually follows the available scanout dmabuf formats
// and comes from the appropriate device. This may implode on multi-gpu!! // and comes from the appropriate device. This may implode on multi-gpu!!
const auto params = PSURFACE->current.buffer->buffer->dmabuf();
// scanout buffer isn't dmabuf, so no scanout
if (!params.success)
return false;
// entering into scanout, so save monitor format
if (lastScanout.expired())
prevDrmFormat = drmFormat;
if (drmFormat != params.format) {
output->state->setFormat(params.format);
drmFormat = params.format;
}
output->state->setBuffer(PSURFACE->current.buffer->buffer.lock()); output->state->setBuffer(PSURFACE->current.buffer->buffer.lock());
output->state->setPresentationMode(tearingState.activelyTearing ? Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_IMMEDIATE : output->state->setPresentationMode(tearingState.activelyTearing ? Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_IMMEDIATE :
Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC); Aquamarine::eOutputPresentationMode::AQ_OUTPUT_PRESENTATION_VSYNC);
@@ -848,7 +877,7 @@ bool CMonitor::attemptDirectScanout() {
timespec now; timespec now;
clock_gettime(CLOCK_MONOTONIC, &now); clock_gettime(CLOCK_MONOTONIC, &now);
PSURFACE->presentFeedback(&now, this); PSURFACE->presentFeedback(&now, self.lock());
output->state->addDamage(CBox{{}, vecPixelSize}); output->state->addDamage(CBox{{}, vecPixelSize});
output->state->resetExplicitFences(); output->state->resetExplicitFences();
@@ -902,17 +931,20 @@ CMonitorState::~CMonitorState() {
} }
void CMonitorState::ensureBufferPresent() { void CMonitorState::ensureBufferPresent() {
if (!m_pOwner->output->state->state().enabled) { const auto STATE = m_pOwner->output->state->state();
if (!STATE.enabled) {
Debug::log(TRACE, "CMonitorState::ensureBufferPresent: Ignoring, monitor is not enabled"); Debug::log(TRACE, "CMonitorState::ensureBufferPresent: Ignoring, monitor is not enabled");
return; return;
} }
if (m_pOwner->output->state->state().buffer) if (STATE.buffer) {
return; if (const auto params = STATE.buffer->dmabuf(); params.success && params.format == m_pOwner->drmFormat)
return;
}
// this is required for modesetting being possible and might be missing in case of first tests in the renderer // this is required for modesetting being possible and might be missing in case of first tests in the renderer
// where we test modes and buffers // where we test modes and buffers
Debug::log(LOG, "CMonitorState::ensureBufferPresent: no buffer, attaching one from the swapchain for modeset being possible"); Debug::log(LOG, "CMonitorState::ensureBufferPresent: no buffer or mismatched format, attaching one from the swapchain for modeset being possible");
m_pOwner->output->state->setBuffer(m_pOwner->output->swapchain->next(nullptr)); m_pOwner->output->state->setBuffer(m_pOwner->output->swapchain->next(nullptr));
m_pOwner->output->swapchain->rollback(); // restore the counter, don't advance the swapchain m_pOwner->output->swapchain->rollback(); // restore the counter, don't advance the swapchain
} }
@@ -946,7 +978,7 @@ bool CMonitorState::updateSwapchain() {
Debug::log(WARN, "updateSwapchain: No mode?"); Debug::log(WARN, "updateSwapchain: No mode?");
return true; return true;
} }
options.format = STATE.drmFormat; options.format = m_pOwner->drmFormat;
options.scanout = true; options.scanout = true;
options.length = 2; options.length = 2;
options.size = MODE->pixelSize; options.size = MODE->pixelSize;

View File

@@ -59,7 +59,7 @@ class CMonitorState {
class CMonitor { class CMonitor {
public: public:
CMonitor(); CMonitor(SP<Aquamarine::IOutput> output);
~CMonitor(); ~CMonitor();
Vector2D vecPosition = Vector2D(-1, -1); // means unset Vector2D vecPosition = Vector2D(-1, -1); // means unset
@@ -70,7 +70,7 @@ class CMonitor {
bool primary = false; bool primary = false;
uint64_t ID = -1; MONITORID ID = MONITOR_INVALID;
PHLWORKSPACE activeWorkspace = nullptr; PHLWORKSPACE activeWorkspace = nullptr;
PHLWORKSPACE activeSpecialWorkspace = nullptr; PHLWORKSPACE activeSpecialWorkspace = nullptr;
float setScale = 1; // scale set by cfg float setScale = 1; // scale set by cfg
@@ -100,6 +100,8 @@ class CMonitor {
std::optional<Vector2D> forceSize; std::optional<Vector2D> forceSize;
SP<Aquamarine::SOutputMode> currentMode; SP<Aquamarine::SOutputMode> currentMode;
SP<Aquamarine::CSwapchain> cursorSwapchain; SP<Aquamarine::CSwapchain> cursorSwapchain;
uint32_t drmFormat = DRM_FORMAT_INVALID;
uint32_t prevDrmFormat = DRM_FORMAT_INVALID;
bool dpmsStatus = true; 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 vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
@@ -155,31 +157,31 @@ class CMonitor {
std::array<std::vector<PHLLSREF>, 4> m_aLayerSurfaceLayers; std::array<std::vector<PHLLSREF>, 4> m_aLayerSurfaceLayers;
// methods // methods
void onConnect(bool noRule); void onConnect(bool noRule);
void onDisconnect(bool destroy = false); void onDisconnect(bool destroy = false);
void addDamage(const pixman_region32_t* rg); void addDamage(const pixman_region32_t* rg);
void addDamage(const CRegion* rg); void addDamage(const CRegion* rg);
void addDamage(const CBox* box); void addDamage(const CBox* box);
bool shouldSkipScheduleFrameOnMouseEvent(); bool shouldSkipScheduleFrameOnMouseEvent();
void setMirror(const std::string&); void setMirror(const std::string&);
bool isMirror(); bool isMirror();
bool matchesStaticSelector(const std::string& selector) const; bool matchesStaticSelector(const std::string& selector) const;
float getDefaultScale(); float getDefaultScale();
void changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false); void changeWorkspace(const PHLWORKSPACE& pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false);
void changeWorkspace(const int& id, bool internal = false, bool noMouseMove = false, bool noFocus = false); void changeWorkspace(const WORKSPACEID& id, bool internal = false, bool noMouseMove = false, bool noFocus = false);
void setSpecialWorkspace(const PHLWORKSPACE& pWorkspace); void setSpecialWorkspace(const PHLWORKSPACE& pWorkspace);
void setSpecialWorkspace(const int& id); void setSpecialWorkspace(const WORKSPACEID& id);
void moveTo(const Vector2D& pos); void moveTo(const Vector2D& pos);
Vector2D middle(); Vector2D middle();
void updateMatrix(); void updateMatrix();
int64_t activeWorkspaceID(); WORKSPACEID activeWorkspaceID();
int64_t activeSpecialWorkspaceID(); WORKSPACEID activeSpecialWorkspaceID();
CBox logicalBox(); CBox logicalBox();
void scheduleDone(); void scheduleDone();
bool attemptDirectScanout(); bool attemptDirectScanout();
bool m_bEnabled = false; bool m_bEnabled = false;
bool m_bRenderingInitPassed = false; bool m_bRenderingInitPassed = false;
// For the list lookup // For the list lookup
@@ -189,7 +191,7 @@ class CMonitor {
private: private:
void setupDefaultWS(const SMonitorRule&); void setupDefaultWS(const SMonitorRule&);
int findAvailableDefaultWS(); WORKSPACEID findAvailableDefaultWS();
wl_event_source* doneSource = nullptr; wl_event_source* doneSource = nullptr;

View File

@@ -1,10 +0,0 @@
#include "ScopeGuard.hpp"
CScopeGuard::CScopeGuard(const std::function<void()>& fn_) : fn(fn_) {
;
}
CScopeGuard::~CScopeGuard() {
if (fn)
fn();
}

View File

@@ -1,13 +0,0 @@
#pragma once
#include <functional>
// calls a function when it goes out of scope
class CScopeGuard {
public:
CScopeGuard(const std::function<void()>& fn_);
~CScopeGuard();
private:
std::function<void()> fn;
};

View File

@@ -8,6 +8,7 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
#include <string.h> #include <string.h>
#include <cstring>
namespace Systemd { namespace Systemd {
int SdBooted(void) { int SdBooted(void) {

View File

@@ -8,7 +8,7 @@ std::chrono::steady_clock::duration CTimer::getDuration() {
return std::chrono::steady_clock::now() - m_tpLastReset; return std::chrono::steady_clock::now() - m_tpLastReset;
} }
int CTimer::getMillis() { long CTimer::getMillis() {
return std::chrono::duration_cast<std::chrono::milliseconds>(getDuration()).count(); return std::chrono::duration_cast<std::chrono::milliseconds>(getDuration()).count();
} }

View File

@@ -6,7 +6,7 @@ class CTimer {
public: public:
void reset(); void reset();
float getSeconds(); float getSeconds();
int getMillis(); long getMillis();
const std::chrono::steady_clock::time_point& chrono() const; const std::chrono::steady_clock::time_point& chrono() const;
private: private:

View File

@@ -18,15 +18,14 @@ CWatchdog::CWatchdog() {
m_pWatchdog = std::make_unique<std::thread>([this] { m_pWatchdog = std::make_unique<std::thread>([this] {
static auto PTIMEOUT = CConfigValue<Hyprlang::INT>("debug:watchdog_timeout"); static auto PTIMEOUT = CConfigValue<Hyprlang::INT>("debug:watchdog_timeout");
while (1337) { m_bWatchdogInitialized = true;
std::unique_lock lk(m_mWatchdogMutex); while (!m_bExitThread) {
std::unique_lock<std::mutex> lk(m_mWatchdogMutex);
if (!m_bWillWatch) if (!m_bWillWatch)
m_cvWatchdogCondition.wait(lk, [this] { return m_bNotified; }); m_cvWatchdogCondition.wait(lk, [this] { return m_bNotified || m_bExitThread; });
else { else if (m_cvWatchdogCondition.wait_for(lk, std::chrono::milliseconds((int)(*PTIMEOUT * 1000.0)), [this] { return m_bNotified || m_bExitThread; }) == false)
if (m_cvWatchdogCondition.wait_for(lk, std::chrono::milliseconds((int)(*PTIMEOUT * 1000.0)), [this] { return m_bNotified; }) == false) pthread_kill(m_iMainThreadPID, SIGUSR1);
pthread_kill(m_iMainThreadPID, SIGUSR1);
}
if (m_bExitThread) if (m_bExitThread)
break; break;

View File

@@ -11,21 +11,23 @@ class CWatchdog {
CWatchdog(); CWatchdog();
~CWatchdog(); ~CWatchdog();
void startWatching(); void startWatching();
void endWatching(); void endWatching();
std::atomic<bool> m_bWatchdogInitialized{false};
private: private:
std::chrono::high_resolution_clock::time_point m_tTriggered; std::chrono::high_resolution_clock::time_point m_tTriggered;
pthread_t m_iMainThreadPID = 0; pthread_t m_iMainThreadPID = 0;
bool m_bWatching = false; std::atomic<bool> m_bWatching = false;
bool m_bWillWatch = false; std::atomic<bool> m_bWillWatch = false;
std::unique_ptr<std::thread> m_pWatchdog; std::unique_ptr<std::thread> m_pWatchdog;
std::mutex m_mWatchdogMutex; std::mutex m_mWatchdogMutex;
bool m_bNotified = false; std::atomic<bool> m_bNotified = false;
bool m_bExitThread = false; std::atomic<bool> m_bExitThread = false;
std::condition_variable m_cvWatchdogCondition; std::condition_variable m_cvWatchdogCondition;
}; };

View File

@@ -47,16 +47,16 @@ void SDwindleNodeData::getAllChildrenRecursive(std::deque<SDwindleNodeData*>* pD
} }
} }
int CHyprDwindleLayout::getNodesOnWorkspace(const int& id) { int CHyprDwindleLayout::getNodesOnWorkspace(const WORKSPACEID& id) {
int no = 0; int no = 0;
for (auto& n : m_lDwindleNodesData) { for (auto const& n : m_lDwindleNodesData) {
if (n.workspaceID == id && n.valid) if (n.workspaceID == id && n.valid)
++no; ++no;
} }
return no; return no;
} }
SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnWorkspace(const int& id) { SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnWorkspace(const WORKSPACEID& id) {
for (auto& n : m_lDwindleNodesData) { for (auto& n : m_lDwindleNodesData) {
if (n.workspaceID == id && validMapped(n.pWindow)) if (n.workspaceID == id && validMapped(n.pWindow))
return &n; return &n;
@@ -64,7 +64,7 @@ SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnWorkspace(const int& id) {
return nullptr; return nullptr;
} }
SDwindleNodeData* CHyprDwindleLayout::getClosestNodeOnWorkspace(const int& id, const Vector2D& point) { SDwindleNodeData* CHyprDwindleLayout::getClosestNodeOnWorkspace(const WORKSPACEID& id, const Vector2D& point) {
SDwindleNodeData* res = nullptr; SDwindleNodeData* res = nullptr;
double distClosest = -1; double distClosest = -1;
for (auto& n : m_lDwindleNodesData) { for (auto& n : m_lDwindleNodesData) {
@@ -88,7 +88,7 @@ SDwindleNodeData* CHyprDwindleLayout::getNodeFromWindow(PHLWINDOW pWindow) {
return nullptr; return nullptr;
} }
SDwindleNodeData* CHyprDwindleLayout::getMasterNodeOnWorkspace(const int& id) { SDwindleNodeData* CHyprDwindleLayout::getMasterNodeOnWorkspace(const WORKSPACEID& id) {
for (auto& n : m_lDwindleNodesData) { for (auto& n : m_lDwindleNodesData) {
if (!n.pParent && n.workspaceID == id) if (!n.pParent && n.workspaceID == id)
return &n; return &n;
@@ -104,7 +104,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
CMonitor* PMONITOR = nullptr; CMonitor* PMONITOR = nullptr;
if (g_pCompositor->isWorkspaceSpecial(pNode->workspaceID)) { if (g_pCompositor->isWorkspaceSpecial(pNode->workspaceID)) {
for (auto& m : g_pCompositor->m_vMonitors) { for (auto const& m : g_pCompositor->m_vMonitors) {
if (m->activeSpecialWorkspaceID() == pNode->workspaceID) { if (m->activeSpecialWorkspaceID() == pNode->workspaceID) {
PMONITOR = m.get(); PMONITOR = m.get();
break; break;
@@ -246,6 +246,8 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
} }
PWINDOW->updateWindowDecos();
} }
void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection direction) { void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection direction) {
@@ -535,7 +537,7 @@ void CHyprDwindleLayout::onWindowRemovedTiling(PHLWINDOW pWindow) {
m_lDwindleNodesData.remove(*PNODE); m_lDwindleNodesData.remove(*PNODE);
} }
void CHyprDwindleLayout::recalculateMonitor(const int& monid) { void CHyprDwindleLayout::recalculateMonitor(const MONITORID& monid) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid); const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
if (!PMONITOR || !PMONITOR->activeWorkspace) if (!PMONITOR || !PMONITOR->activeWorkspace)
@@ -872,7 +874,7 @@ void CHyprDwindleLayout::moveWindowTo(PHLWINDOW pWindow, const std::string& dir,
return; return;
const auto PNODE = getNodeFromWindow(pWindow); const auto PNODE = getNodeFromWindow(pWindow);
const int originalWorkspaceID = pWindow->workspaceID(); const auto originalWorkspaceID = pWindow->workspaceID();
const Vector2D originalPos = pWindow->middle(); const Vector2D originalPos = pWindow->middle();
if (!PNODE) if (!PNODE)
@@ -1073,7 +1075,7 @@ std::string CHyprDwindleLayout::getLayoutName() {
} }
void CHyprDwindleLayout::onEnable() { void CHyprDwindleLayout::onEnable() {
for (auto& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (w->m_bIsFloating || !w->m_bIsMapped || w->isHidden()) if (w->m_bIsFloating || !w->m_bIsMapped || w->isHidden())
continue; continue;

View File

@@ -24,7 +24,7 @@ struct SDwindleNodeData {
CBox box = {0}; CBox box = {0};
int workspaceID = -1; WORKSPACEID workspaceID = WORKSPACE_INVALID;
float splitRatio = 1.f; float splitRatio = 1.f;
@@ -48,7 +48,7 @@ class CHyprDwindleLayout : public IHyprLayout {
virtual void onWindowCreatedTiling(PHLWINDOW, eDirection direction = DIRECTION_DEFAULT); virtual void onWindowCreatedTiling(PHLWINDOW, eDirection direction = DIRECTION_DEFAULT);
virtual void onWindowRemovedTiling(PHLWINDOW); virtual void onWindowRemovedTiling(PHLWINDOW);
virtual bool isWindowTiled(PHLWINDOW); virtual bool isWindowTiled(PHLWINDOW);
virtual void recalculateMonitor(const int&); virtual void recalculateMonitor(const MONITORID&);
virtual void recalculateWindow(PHLWINDOW); virtual void recalculateWindow(PHLWINDOW);
virtual void onBeginDragWindow(); virtual void onBeginDragWindow();
virtual void resizeActiveWindow(const Vector2D&, eRectCorner corner = CORNER_NONE, PHLWINDOW pWindow = nullptr); virtual void resizeActiveWindow(const Vector2D&, eRectCorner corner = CORNER_NONE, PHLWINDOW pWindow = nullptr);
@@ -77,13 +77,13 @@ class CHyprDwindleLayout : public IHyprLayout {
std::optional<Vector2D> m_vOverrideFocalPoint; // for onWindowCreatedTiling. std::optional<Vector2D> m_vOverrideFocalPoint; // for onWindowCreatedTiling.
int getNodesOnWorkspace(const int&); int getNodesOnWorkspace(const WORKSPACEID&);
void applyNodeDataToWindow(SDwindleNodeData*, bool force = false); void applyNodeDataToWindow(SDwindleNodeData*, bool force = false);
void calculateWorkspace(const PHLWORKSPACE& pWorkspace); void calculateWorkspace(const PHLWORKSPACE& pWorkspace);
SDwindleNodeData* getNodeFromWindow(PHLWINDOW); SDwindleNodeData* getNodeFromWindow(PHLWINDOW);
SDwindleNodeData* getFirstNodeOnWorkspace(const int&); SDwindleNodeData* getFirstNodeOnWorkspace(const WORKSPACEID&);
SDwindleNodeData* getClosestNodeOnWorkspace(const int&, const Vector2D&); SDwindleNodeData* getClosestNodeOnWorkspace(const WORKSPACEID&, const Vector2D&);
SDwindleNodeData* getMasterNodeOnWorkspace(const int&); SDwindleNodeData* getMasterNodeOnWorkspace(const WORKSPACEID&);
void toggleSplit(PHLWINDOW); void toggleSplit(PHLWINDOW);
void swapSplit(PHLWINDOW); void swapSplit(PHLWINDOW);

View File

@@ -104,7 +104,7 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) {
pWindow->m_vRealSize = PWINDOWSURFACE->current.size; pWindow->m_vRealSize = PWINDOWSURFACE->current.size;
if ((desiredGeometry.width <= 1 || desiredGeometry.height <= 1) && pWindow->m_bIsX11 && 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->isX11OverrideRedirect()) { // XDG windows should be fine. TODO: check for weird atoms?
pWindow->setHidden(true); pWindow->setHidden(true);
return; return;
} }
@@ -113,7 +113,7 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) {
if (pWindow->m_vRealSize.goal().x <= 5 || pWindow->m_vRealSize.goal().y <= 5) if (pWindow->m_vRealSize.goal().x <= 5 || pWindow->m_vRealSize.goal().y <= 5)
pWindow->m_vRealSize = PMONITOR->vecSize / 2.f; pWindow->m_vRealSize = PMONITOR->vecSize / 2.f;
if (pWindow->m_bIsX11 && pWindow->m_iX11Type == 2) { if (pWindow->m_bIsX11 && pWindow->isX11OverrideRedirect()) {
if (pWindow->m_pXWaylandSurface->geometry.x != 0 && pWindow->m_pXWaylandSurface->geometry.y != 0) if (pWindow->m_pXWaylandSurface->geometry.x != 0 && pWindow->m_pXWaylandSurface->geometry.y != 0)
pWindow->m_vRealPosition = g_pXWaylandManager->xwaylandToWaylandCoords(pWindow->m_pXWaylandSurface->geometry.pos()); pWindow->m_vRealPosition = g_pXWaylandManager->xwaylandToWaylandCoords(pWindow->m_pXWaylandSurface->geometry.pos());
@@ -163,12 +163,12 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) {
if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11) if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11)
pWindow->m_vRealSize = pWindow->m_vRealSize.goal() / PMONITOR->scale; pWindow->m_vRealSize = pWindow->m_vRealSize.goal() / PMONITOR->scale;
if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->m_iX11Type == 2)) { if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->isX11OverrideRedirect())) {
pWindow->m_vRealPosition.warp(); pWindow->m_vRealPosition.warp();
pWindow->m_vRealSize.warp(); pWindow->m_vRealSize.warp();
} }
if (pWindow->m_iX11Type != 2) { if (!pWindow->isX11OverrideRedirect()) {
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal()); g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal());
g_pCompositor->changeWindowZOrder(pWindow, true); g_pCompositor->changeWindowZOrder(pWindow, true);
@@ -591,8 +591,8 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) {
if (pWindow->m_bIsFloating) { if (pWindow->m_bIsFloating) {
// find whether there is a floating window below this one // find whether there is a floating window below this one
for (auto& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_pWorkspace == pWindow->m_pWorkspace && !w->m_bX11ShouldntFocus && if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && !w->isX11OverrideRedirect() && w->m_pWorkspace == pWindow->m_pWorkspace && !w->m_bX11ShouldntFocus &&
!w->m_sWindowData.noFocus.valueOrDefault() && w != pWindow) { !w->m_sWindowData.noFocus.valueOrDefault() && w != pWindow) {
if (VECINRECT((pWindow->m_vSize / 2.f + pWindow->m_vPosition), w->m_vPosition.x, w->m_vPosition.y, w->m_vPosition.x + w->m_vSize.x, if (VECINRECT((pWindow->m_vSize / 2.f + pWindow->m_vPosition), w->m_vPosition.x, w->m_vPosition.y, w->m_vPosition.x + w->m_vSize.x,
w->m_vPosition.y + w->m_vSize.y)) { w->m_vPosition.y + w->m_vSize.y)) {
@@ -611,8 +611,8 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) {
return PWINDOWCANDIDATE; return PWINDOWCANDIDATE;
// if not, floating window // if not, floating window
for (auto& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_pWorkspace == pWindow->m_pWorkspace && !w->m_bX11ShouldntFocus && if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && !w->isX11OverrideRedirect() && w->m_pWorkspace == pWindow->m_pWorkspace && !w->m_bX11ShouldntFocus &&
!w->m_sWindowData.noFocus.valueOrDefault() && w != pWindow) !w->m_sWindowData.noFocus.valueOrDefault() && w != pWindow)
return w; return w;
} }
@@ -631,7 +631,7 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) {
pWindowCandidate = g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID()); pWindowCandidate = g_pCompositor->getFirstWindowOnWorkspace(pWindow->workspaceID());
if (!pWindowCandidate || pWindow == pWindowCandidate || !pWindowCandidate->m_bIsMapped || pWindowCandidate->isHidden() || pWindowCandidate->m_bX11ShouldntFocus || if (!pWindowCandidate || pWindow == pWindowCandidate || !pWindowCandidate->m_bIsMapped || pWindowCandidate->isHidden() || pWindowCandidate->m_bX11ShouldntFocus ||
pWindowCandidate->m_iX11Type == 2 || pWindowCandidate->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) pWindowCandidate->isX11OverrideRedirect() || pWindowCandidate->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID)
return nullptr; return nullptr;
return pWindowCandidate; return pWindowCandidate;
@@ -660,7 +660,7 @@ void IHyprLayout::requestFocusForWindow(PHLWINDOW pWindow) {
Vector2D IHyprLayout::predictSizeForNewWindowFloating(PHLWINDOW pWindow) { // get all rules, see if we have any size overrides. Vector2D IHyprLayout::predictSizeForNewWindowFloating(PHLWINDOW pWindow) { // get all rules, see if we have any size overrides.
Vector2D sizeOverride = {}; Vector2D sizeOverride = {};
if (g_pCompositor->m_pLastMonitor) { if (g_pCompositor->m_pLastMonitor) {
for (auto& r : g_pConfigManager->getMatchingRules(pWindow, true, true)) { for (auto const& r : g_pConfigManager->getMatchingRules(pWindow, true, true)) {
if (r.szRule.starts_with("size")) { if (r.szRule.starts_with("size")) {
try { try {
const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1); const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1);
@@ -691,7 +691,7 @@ Vector2D IHyprLayout::predictSizeForNewWindow(PHLWINDOW pWindow) {
bool shouldBeFloated = g_pXWaylandManager->shouldBeFloated(pWindow, true); bool shouldBeFloated = g_pXWaylandManager->shouldBeFloated(pWindow, true);
if (!shouldBeFloated) { if (!shouldBeFloated) {
for (auto& r : g_pConfigManager->getMatchingRules(pWindow, true, true)) { for (auto const& r : g_pConfigManager->getMatchingRules(pWindow, true, true)) {
if (r.szRule.starts_with("float")) { if (r.szRule.starts_with("float")) {
shouldBeFloated = true; shouldBeFloated = true;
break; break;

View File

@@ -63,7 +63,7 @@ class IHyprLayout {
Called when the monitor requires a layout recalculation Called when the monitor requires a layout recalculation
this usually means reserved area changes this usually means reserved area changes
*/ */
virtual void recalculateMonitor(const int&) = 0; virtual void recalculateMonitor(const MONITORID&) = 0;
/* /*
Called when the compositor requests a window Called when the compositor requests a window

View File

@@ -14,9 +14,9 @@ SMasterNodeData* CHyprMasterLayout::getNodeFromWindow(PHLWINDOW pWindow) {
return nullptr; return nullptr;
} }
int CHyprMasterLayout::getNodesOnWorkspace(const int& ws) { int CHyprMasterLayout::getNodesOnWorkspace(const WORKSPACEID& ws) {
int no = 0; int no = 0;
for (auto& n : m_lMasterNodesData) { for (auto const& n : m_lMasterNodesData) {
if (n.workspaceID == ws) if (n.workspaceID == ws)
no++; no++;
} }
@@ -24,9 +24,9 @@ int CHyprMasterLayout::getNodesOnWorkspace(const int& ws) {
return no; return no;
} }
int CHyprMasterLayout::getMastersOnWorkspace(const int& ws) { int CHyprMasterLayout::getMastersOnWorkspace(const WORKSPACEID& ws) {
int no = 0; int no = 0;
for (auto& n : m_lMasterNodesData) { for (auto const& n : m_lMasterNodesData) {
if (n.workspaceID == ws && n.isMaster) if (n.workspaceID == ws && n.isMaster)
no++; no++;
} }
@@ -34,7 +34,7 @@ int CHyprMasterLayout::getMastersOnWorkspace(const int& ws) {
return no; return no;
} }
SMasterWorkspaceData* CHyprMasterLayout::getMasterWorkspaceData(const int& ws) { SMasterWorkspaceData* CHyprMasterLayout::getMasterWorkspaceData(const WORKSPACEID& ws) {
for (auto& n : m_lMasterWorkspacesData) { for (auto& n : m_lMasterWorkspacesData) {
if (n.workspaceID == ws) if (n.workspaceID == ws)
return &n; return &n;
@@ -63,7 +63,7 @@ std::string CHyprMasterLayout::getLayoutName() {
return "Master"; return "Master";
} }
SMasterNodeData* CHyprMasterLayout::getMasterNodeOnWorkspace(const int& ws) { SMasterNodeData* CHyprMasterLayout::getMasterNodeOnWorkspace(const WORKSPACEID& ws) {
for (auto& n : m_lMasterNodesData) { for (auto& n : m_lMasterNodesData) {
if (n.isMaster && n.workspaceID == ws) if (n.isMaster && n.workspaceID == ws)
return &n; return &n;
@@ -172,7 +172,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire
} else if (WINDOWSONWORKSPACE == 2) { } else if (WINDOWSONWORKSPACE == 2) {
// when dropping as the second tiled window in the workspace, // when dropping as the second tiled window in the workspace,
// make it the master only if the cursor is on the master side of the screen // make it the master only if the cursor is on the master side of the screen
for (auto& nd : m_lMasterNodesData) { for (auto const& nd : m_lMasterNodesData) {
if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) { if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
switch (orientation) { switch (orientation) {
case ORIENTATION_LEFT: case ORIENTATION_LEFT:
@@ -304,7 +304,7 @@ void CHyprMasterLayout::onWindowRemovedTiling(PHLWINDOW pWindow) {
recalculateMonitor(pWindow->m_iMonitorID); recalculateMonitor(pWindow->m_iMonitorID);
} }
void CHyprMasterLayout::recalculateMonitor(const int& monid) { void CHyprMasterLayout::recalculateMonitor(const MONITORID& monid) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid); const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
if (!PMONITOR || !PMONITOR->activeWorkspace) if (!PMONITOR || !PMONITOR->activeWorkspace)
@@ -381,7 +381,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
if (*PSMARTRESIZING) { if (*PSMARTRESIZING) {
// check the total width and height so that later // check the total width and height so that later
// if larger/smaller than screen size them down/up // if larger/smaller than screen size them down/up
for (auto& nd : m_lMasterNodesData) { for (auto const& nd : m_lMasterNodesData) {
if (nd.workspaceID == pWorkspace->m_iID) { if (nd.workspaceID == pWorkspace->m_iID) {
if (nd.isMaster) if (nd.isMaster)
masterAccumulatedSize += totalSize / MASTERS * nd.percSize; masterAccumulatedSize += totalSize / MASTERS * nd.percSize;
@@ -552,7 +552,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
float slaveAccumulatedHeightL = 0; float slaveAccumulatedHeightL = 0;
float slaveAccumulatedHeightR = 0; float slaveAccumulatedHeightR = 0;
if (*PSMARTRESIZING) { if (*PSMARTRESIZING) {
for (auto& nd : m_lMasterNodesData) { for (auto const& nd : m_lMasterNodesData) {
if (nd.workspaceID != pWorkspace->m_iID || nd.isMaster) if (nd.workspaceID != pWorkspace->m_iID || nd.isMaster)
continue; continue;
@@ -619,7 +619,7 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
CMonitor* PMONITOR = nullptr; CMonitor* PMONITOR = nullptr;
if (g_pCompositor->isWorkspaceSpecial(pNode->workspaceID)) { if (g_pCompositor->isWorkspaceSpecial(pNode->workspaceID)) {
for (auto& m : g_pCompositor->m_vMonitors) { for (auto const& m : g_pCompositor->m_vMonitors) {
if (m->activeSpecialWorkspaceID() == pNode->workspaceID) { if (m->activeSpecialWorkspaceID() == pNode->workspaceID) {
PMONITOR = m.get(); PMONITOR = m.get();
break; break;
@@ -732,6 +732,8 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
} }
PWINDOW->updateWindowDecos();
} }
bool CHyprMasterLayout::isWindowTiled(PHLWINDOW pWindow) { bool CHyprMasterLayout::isWindowTiled(PHLWINDOW pWindow) {
@@ -1104,7 +1106,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
const auto NEWFOCUS = newFocusToChild ? NEWCHILD : NEWMASTER; const auto NEWFOCUS = newFocusToChild ? NEWCHILD : NEWMASTER;
switchToWindow(NEWFOCUS); switchToWindow(NEWFOCUS);
} else { } else {
for (auto& n : m_lMasterNodesData) { for (auto const& n : m_lMasterNodesData) {
if (n.workspaceID == PMASTER->workspaceID && !n.isMaster) { if (n.workspaceID == PMASTER->workspaceID && !n.isMaster) {
const auto NEWMASTER = n.pWindow.lock(); const auto NEWMASTER = n.pWindow.lock();
switchWindows(NEWMASTER, NEWCHILD); switchWindows(NEWMASTER, NEWCHILD);
@@ -1139,7 +1141,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
return 0; return 0;
} else { } else {
// if master is focused keep master focused (don't do anything) // if master is focused keep master focused (don't do anything)
for (auto& n : m_lMasterNodesData) { for (auto const& n : m_lMasterNodesData) {
if (n.workspaceID == PMASTER->workspaceID && !n.isMaster) { if (n.workspaceID == PMASTER->workspaceID && !n.isMaster) {
switchToWindow(n.pWindow.lock()); switchToWindow(n.pWindow.lock());
break; break;
@@ -1467,7 +1469,7 @@ Vector2D CHyprMasterLayout::predictSizeForNewWindowTiled() {
} }
void CHyprMasterLayout::onEnable() { void CHyprMasterLayout::onEnable() {
for (auto& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (w->m_bIsFloating || !w->m_bIsMapped || w->isHidden()) if (w->m_bIsFloating || !w->m_bIsMapped || w->isHidden())
continue; continue;

View File

@@ -30,7 +30,7 @@ struct SMasterNodeData {
float percSize = 1.f; // size multiplier for resizing children float percSize = 1.f; // size multiplier for resizing children
int workspaceID = -1; WORKSPACEID workspaceID = WORKSPACE_INVALID;
bool ignoreFullscreenChecks = false; bool ignoreFullscreenChecks = false;
@@ -41,7 +41,7 @@ struct SMasterNodeData {
}; };
struct SMasterWorkspaceData { struct SMasterWorkspaceData {
int workspaceID = -1; WORKSPACEID workspaceID = WORKSPACE_INVALID;
eOrientation orientation = ORIENTATION_LEFT; eOrientation orientation = ORIENTATION_LEFT;
// //
@@ -55,7 +55,7 @@ class CHyprMasterLayout : public IHyprLayout {
virtual void onWindowCreatedTiling(PHLWINDOW, eDirection direction = DIRECTION_DEFAULT); virtual void onWindowCreatedTiling(PHLWINDOW, eDirection direction = DIRECTION_DEFAULT);
virtual void onWindowRemovedTiling(PHLWINDOW); virtual void onWindowRemovedTiling(PHLWINDOW);
virtual bool isWindowTiled(PHLWINDOW); virtual bool isWindowTiled(PHLWINDOW);
virtual void recalculateMonitor(const int&); virtual void recalculateMonitor(const MONITORID&);
virtual void recalculateWindow(PHLWINDOW); virtual void recalculateWindow(PHLWINDOW);
virtual void resizeActiveWindow(const Vector2D&, eRectCorner corner = CORNER_NONE, PHLWINDOW pWindow = nullptr); virtual void resizeActiveWindow(const Vector2D&, eRectCorner corner = CORNER_NONE, PHLWINDOW pWindow = nullptr);
virtual void fullscreenRequestForWindow(PHLWINDOW pWindow, const eFullscreenMode CURRENT_EFFECTIVE_MODE, const eFullscreenMode EFFECTIVE_MODE); virtual void fullscreenRequestForWindow(PHLWINDOW pWindow, const eFullscreenMode CURRENT_EFFECTIVE_MODE, const eFullscreenMode EFFECTIVE_MODE);
@@ -81,14 +81,14 @@ class CHyprMasterLayout : public IHyprLayout {
void buildOrientationCycleVectorFromEOperation(std::vector<eOrientation>& cycle); void buildOrientationCycleVectorFromEOperation(std::vector<eOrientation>& cycle);
void runOrientationCycle(SLayoutMessageHeader& header, CVarList* vars, int next); void runOrientationCycle(SLayoutMessageHeader& header, CVarList* vars, int next);
eOrientation getDynamicOrientation(PHLWORKSPACE); eOrientation getDynamicOrientation(PHLWORKSPACE);
int getNodesOnWorkspace(const int&); int getNodesOnWorkspace(const WORKSPACEID&);
void applyNodeDataToWindow(SMasterNodeData*); void applyNodeDataToWindow(SMasterNodeData*);
SMasterNodeData* getNodeFromWindow(PHLWINDOW); SMasterNodeData* getNodeFromWindow(PHLWINDOW);
SMasterNodeData* getMasterNodeOnWorkspace(const int&); SMasterNodeData* getMasterNodeOnWorkspace(const WORKSPACEID&);
SMasterWorkspaceData* getMasterWorkspaceData(const int&); SMasterWorkspaceData* getMasterWorkspaceData(const WORKSPACEID&);
void calculateWorkspace(PHLWORKSPACE); void calculateWorkspace(PHLWORKSPACE);
PHLWINDOW getNextWindow(PHLWINDOW, bool); PHLWINDOW getNextWindow(PHLWINDOW, bool);
int getMastersOnWorkspace(const int&); int getMastersOnWorkspace(const WORKSPACEID&);
friend struct SMasterNodeData; friend struct SMasterNodeData;
friend struct SMasterWorkspaceData; friend struct SMasterWorkspaceData;

View File

@@ -27,6 +27,8 @@
#define WORKSPACE_INVALID -1L #define WORKSPACE_INVALID -1L
#define WORKSPACE_NOT_CHANGED -101 #define WORKSPACE_NOT_CHANGED -101
#define MONITOR_INVALID -1L
#define LISTENER(name) \ #define LISTENER(name) \
void listener_##name(wl_listener*, void*); \ void listener_##name(wl_listener*, void*); \
inline wl_listener listen_##name = {.notify = listener_##name} inline wl_listener listen_##name = {.notify = listener_##name}

View File

@@ -4,6 +4,9 @@
#include "config/ConfigManager.hpp" #include "config/ConfigManager.hpp"
#include "init/initHelpers.hpp" #include "init/initHelpers.hpp"
#include <hyprutils/string/String.hpp>
using namespace Hyprutils::String;
#include <fcntl.h> #include <fcntl.h>
#include <iostream> #include <iostream>
#include <iterator> #include <iterator>
@@ -20,6 +23,7 @@ void help() {
std::cout << " --socket NAME - Sets the Wayland socket name (for Wayland socket handover)\n"; std::cout << " --socket NAME - Sets the Wayland socket name (for Wayland socket handover)\n";
std::cout << " --wayland-fd FD - Sets the Wayland socket fd (for Wayland socket handover)\n"; std::cout << " --wayland-fd FD - Sets the Wayland socket fd (for Wayland socket handover)\n";
std::cout << " --i-am-really-stupid - Omits root user privileges check (why would you do that?)\n"; std::cout << " --i-am-really-stupid - Omits root user privileges check (why would you do that?)\n";
std::cout << " --version -v - Print this binary's version\n";
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {
@@ -36,7 +40,6 @@ int main(int argc, char** argv) {
setenv("XDG_BACKEND", "wayland", 1); setenv("XDG_BACKEND", "wayland", 1);
setenv("_JAVA_AWT_WM_NONREPARENTING", "1", 1); setenv("_JAVA_AWT_WM_NONREPARENTING", "1", 1);
setenv("MOZ_ENABLE_WAYLAND", "1", 1); setenv("MOZ_ENABLE_WAYLAND", "1", 1);
setenv("XDG_CURRENT_DESKTOP", "Hyprland", 1);
// parse some args // parse some args
std::string configPath; std::string configPath;
@@ -110,6 +113,25 @@ int main(int argc, char** argv) {
} else if (it->compare("-h") == 0 || it->compare("--help") == 0) { } else if (it->compare("-h") == 0 || it->compare("--help") == 0) {
help(); help();
return 0;
} else if (it->compare("-v") == 0 || it->compare("--version") == 0) {
auto commitMsg = trim(GIT_COMMIT_MESSAGE);
std::replace(commitMsg.begin(), commitMsg.end(), '#', ' ');
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg +
").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + ", commits: " + GIT_COMMITS + std::string{"\nbuilt against aquamarine "} + AQUAMARINE_VERSION + "\n" +
"\n\nflags: (if any)\n";
#ifdef LEGACY_RENDERER
result += "legacyrenderer\n";
#endif
#ifndef ISDEBUG
result += "debug\n";
#endif
#ifdef NO_XWAYLAND
result += "no xwayland\n";
#endif
std::cout << result;
return 0; return 0;
} else { } else {
std::cerr << "[ ERROR ] Unknown option '" << it->c_str() << "'!\n"; std::cerr << "[ ERROR ] Unknown option '" << it->c_str() << "'!\n";

View File

@@ -70,7 +70,7 @@ void CAnimationManager::tick() {
std::vector<CBaseAnimatedVariable*> animationEndedVars; std::vector<CBaseAnimatedVariable*> animationEndedVars;
for (auto& av : m_vActiveAnimatedVariables) { for (auto const& av : m_vActiveAnimatedVariables) {
if (av->m_eDamagePolicy == AVARDAMAGE_SHADOW && !*PSHADOWSENABLED) { if (av->m_eDamagePolicy == AVARDAMAGE_SHADOW && !*PSHADOWSENABLED) {
av->warp(false); av->warp(false);
@@ -113,7 +113,7 @@ void CAnimationManager::tick() {
g_pHyprRenderer->damageMonitor(PMONITOR); g_pHyprRenderer->damageMonitor(PMONITOR);
// TODO: just make this into a damn callback already vax... // TODO: just make this into a damn callback already vax...
for (auto& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped || w->isHidden() || w->m_pWorkspace != PWORKSPACE) if (!w->m_bIsMapped || w->isHidden() || w->m_pWorkspace != PWORKSPACE)
continue; continue;
@@ -131,7 +131,7 @@ void CAnimationManager::tick() {
} }
// damage any workspace window that is on any monitor // damage any workspace window that is on any monitor
for (auto& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (!validMapped(w) || w->m_pWorkspace != PWORKSPACE || w->m_bPinned) if (!validMapped(w) || w->m_pWorkspace != PWORKSPACE || w->m_bPinned)
continue; continue;
@@ -194,7 +194,7 @@ void CAnimationManager::tick() {
default: UNREACHABLE(); default: UNREACHABLE();
} }
// set size and pos if valid, but only if damage policy entire (dont if border for example) // set size and pos if valid, but only if damage policy entire (dont if border for example)
if (validMapped(PWINDOW) && av->m_eDamagePolicy == AVARDAMAGE_ENTIRE && PWINDOW->m_iX11Type != 2) if (validMapped(PWINDOW) && av->m_eDamagePolicy == AVARDAMAGE_ENTIRE && !PWINDOW->isX11OverrideRedirect())
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal()); g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal());
// check if we did not finish animating. If so, trigger onAnimationEnd. // check if we did not finish animating. If so, trigger onAnimationEnd.
@@ -214,7 +214,7 @@ void CAnimationManager::tick() {
PWINDOW->updateWindowDecos(); PWINDOW->updateWindowDecos();
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
} else if (PWORKSPACE) { } else if (PWORKSPACE) {
for (auto& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (!validMapped(w) || w->m_pWorkspace != PWORKSPACE) if (!validMapped(w) || w->m_pWorkspace != PWORKSPACE)
continue; continue;
@@ -263,7 +263,7 @@ void CAnimationManager::tick() {
} }
// do it here, because if this alters the animation vars deque we would be in trouble above. // do it here, because if this alters the animation vars deque we would be in trouble above.
for (auto& ave : animationEndedVars) { for (auto const& ave : animationEndedVars) {
ave->onAnimationEnd(); ave->onAnimationEnd();
} }
} }
@@ -293,7 +293,7 @@ bool CAnimationManager::deltazero(const CColor& a, const CColor& b) {
} }
bool CAnimationManager::bezierExists(const std::string& bezier) { bool CAnimationManager::bezierExists(const std::string& bezier) {
for (auto& [bc, bz] : m_mBezierCurves) { for (auto const& [bc, bz] : m_mBezierCurves) {
if (bc == bezier) if (bc == bezier)
return true; return true;
} }
@@ -471,7 +471,7 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config,
} }
return "unknown style"; return "unknown style";
} else if (config == "workspaces" || config == "specialWorkspace") { } else if (config.starts_with("workspaces") || config.starts_with("specialWorkspace")) {
if (style == "slide" || style == "slidevert" || style == "fade") if (style == "slide" || style == "slidevert" || style == "fade")
return ""; return "";
else if (style.starts_with("slidefade")) { else if (style.starts_with("slidefade")) {

View File

@@ -102,7 +102,7 @@ CCursorManager::CCursorManager() {
// since we fallback to xcursor always load it on startup. otherwise we end up with a empty theme if hyprcursor is enabled in the config // since we fallback to xcursor always load it on startup. otherwise we end up with a empty theme if hyprcursor is enabled in the config
// and then later is disabled. // and then later is disabled.
m_pXcursor->loadTheme(getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "default", m_iSize * std::ceil(m_fCursorScale)); m_pXcursor->loadTheme(getenv("XCURSOR_THEME") ? getenv("XCURSOR_THEME") : "default", m_iSize, m_fCursorScale);
m_pAnimationTimer = makeShared<CEventLoopTimer>(std::nullopt, cursorAnimTimer, this); m_pAnimationTimer = makeShared<CEventLoopTimer>(std::nullopt, cursorAnimTimer, this);
g_pEventLoopManager->addTimer(m_pAnimationTimer); g_pEventLoopManager->addTimer(m_pAnimationTimer);
@@ -163,7 +163,7 @@ void CCursorManager::setCursorFromName(const std::string& name) {
auto setXCursor = [this](auto const& name) { auto setXCursor = [this](auto const& name) {
float scale = std::ceil(m_fCursorScale); float scale = std::ceil(m_fCursorScale);
auto xcursor = m_pXcursor->getShape(name, m_iSize * scale); auto xcursor = m_pXcursor->getShape(name, m_iSize, m_fCursorScale);
auto& icon = xcursor->images.front(); auto& icon = xcursor->images.front();
auto buf = makeShared<CCursorBuffer>((uint8_t*)icon.pixels.data(), icon.size, icon.hotspot); auto buf = makeShared<CCursorBuffer>((uint8_t*)icon.pixels.data(), icon.size, icon.hotspot);
setCursorBuffer(buf, icon.hotspot / scale, scale); setCursorBuffer(buf, icon.hotspot / scale, scale);
@@ -193,7 +193,7 @@ void CCursorManager::setCursorFromName(const std::string& name) {
// fallback to a default if available // fallback to a default if available
constexpr const std::array<const char*, 3> fallbackShapes = {"default", "left_ptr", "left-ptr"}; constexpr const std::array<const char*, 3> fallbackShapes = {"default", "left_ptr", "left-ptr"};
for (auto& s : fallbackShapes) { for (auto const& s : fallbackShapes) {
m_sCurrentCursorShapeData = m_pHyprcursor->getShape(s, m_sCurrentStyleInfo); m_sCurrentCursorShapeData = m_pHyprcursor->getShape(s, m_sCurrentStyleInfo);
if (m_sCurrentCursorShapeData.images.size() > 0) if (m_sCurrentCursorShapeData.images.size() > 0)
@@ -277,7 +277,7 @@ void CCursorManager::setXWaylandCursor() {
g_pXWayland->setCursor(cairo_image_surface_get_data(CURSOR.surface), cairo_image_surface_get_stride(CURSOR.surface), {CURSOR.size, CURSOR.size}, g_pXWayland->setCursor(cairo_image_surface_get_data(CURSOR.surface), cairo_image_surface_get_stride(CURSOR.surface), {CURSOR.size, CURSOR.size},
{CURSOR.hotspotX, CURSOR.hotspotY}); {CURSOR.hotspotX, CURSOR.hotspotY});
else { else {
auto xcursor = m_pXcursor->getShape("left_ptr", m_iSize * std::ceil(m_fCursorScale)); auto xcursor = m_pXcursor->getShape("left_ptr", m_iSize, 1);
auto& icon = xcursor->images.front(); auto& icon = xcursor->images.front();
g_pXWayland->setCursor((uint8_t*)icon.pixels.data(), icon.size.x * 4, icon.size, icon.hotspot); g_pXWayland->setCursor((uint8_t*)icon.pixels.data(), icon.size.x * 4, icon.size, icon.hotspot);
@@ -288,7 +288,7 @@ void CCursorManager::updateTheme() {
static auto PUSEHYPRCURSOR = CConfigValue<Hyprlang::INT>("cursor:enable_hyprcursor"); static auto PUSEHYPRCURSOR = CConfigValue<Hyprlang::INT>("cursor:enable_hyprcursor");
float highestScale = 1.0; float highestScale = 1.0;
for (auto& m : g_pCompositor->m_vMonitors) { for (auto const& m : g_pCompositor->m_vMonitors) {
if (m->scale > highestScale) if (m->scale > highestScale)
highestScale = m->scale; highestScale = m->scale;
} }
@@ -307,7 +307,7 @@ void CCursorManager::updateTheme() {
setCursorFromName("left_ptr"); setCursorFromName("left_ptr");
for (auto& m : g_pCompositor->m_vMonitors) { for (auto const& m : g_pCompositor->m_vMonitors) {
m->forceFullFrames = 5; m->forceFullFrames = 5;
g_pCompositor->scheduleFrameForMonitor(m.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE); g_pCompositor->scheduleFrameForMonitor(m.get(), Aquamarine::IOutput::AQ_SCHEDULE_CURSOR_SHAPE);
} }
@@ -329,12 +329,16 @@ bool CCursorManager::changeTheme(const std::string& name, const int size) {
m_pHyprcursor = std::make_unique<Hyprcursor::CHyprcursorManager>(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), options); m_pHyprcursor = std::make_unique<Hyprcursor::CHyprcursorManager>(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), options);
if (!m_pHyprcursor->valid()) { if (!m_pHyprcursor->valid()) {
Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to XCursor.", m_szTheme); Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to XCursor.", m_szTheme);
m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize); m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize, m_fCursorScale);
} }
} else } else
m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize); m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize, m_fCursorScale);
updateTheme(); updateTheme();
return true; return true;
} }
void CCursorManager::syncGsettings() {
m_pXcursor->syncGsettings();
}

Some files were not shown because too many files have changed in this diff Show More