Compare commits

...

937 Commits

Author SHA1 Message Date
Vaxry
e93fbd7c4f props: bump ver to 0.39.0 2024-04-14 19:48:28 +01:00
go0d1uck
83ab0f2d66 keybindmgr: fix workspace_back_and_forth (#5585) 2024-04-14 14:54:00 +01:00
MightyPlaza
0634aaeac6 renderer: remove border on fullscreen (#5577)
modified:   src/render/Renderer.cpp
2024-04-14 00:16:26 +01:00
André Silva
61fe47189b build: update asan patch (#5562) 2024-04-13 22:13:08 +01:00
Yaroslav
9e4b2efe7e cmake: Some small cmake cleanups (#5572)
* remove unnecessary include

* cmake: use pkg_get_variable

We can find wayland-scanner executable and wayland-protocols dir by
taking advantage of this function, so no need to use find_program or
manually call pkgconf executable.

* cmake: remove explicit rdynamic option

CMAKE_ENABLE_EXPORTS=ON already implies rdynamic so it's redundant to
set the latter explicitly.

Also, CMAKE_ENABLE_EXPORTS is superseded by
CMAKE_EXECUTABLE_ENABLE_EXPORTS in cmake 3.27.

* cmake: make xcb-errors dep optional

xcb-errors is being used in wlroots, where it's optional. So make it
optional in hyprland as well
2024-04-13 14:40:28 +01:00
thejch
d96501442f core: Fix double special workspace (#5574)
* fix double special name

* fix special on another monitor

* remove extra stuff
2024-04-13 14:39:20 +01:00
thejch
582d6233c8 workspace: fix workspace name selector returning true early (#5571) 2024-04-13 01:55:17 +01:00
thejch
34396f55a2 master: change the mfact dispatcher to use splitratio (#4766)
* master layout: change the mfact dispatcher to use splitratio

* add space for concat
2024-04-13 01:54:18 +01:00
Vaxry
0c513ba91b CI: fix packaging 2024-04-12 20:46:21 +01:00
Vaxry
dd6fdf49d9 window: always unref workspace on unmap
fixes #5563
2024-04-12 19:52:01 +01:00
Vaxry
ddcdb56f2c CI: fix arch 2024-04-12 19:50:36 +01:00
bvr-yr
32147f5e91 hyprpm: fix wlroots path (#5567) 2024-04-12 19:49:33 +01:00
Mihai Fufezan
d8d0d3b20b Nix & Meson: switch to wlroots-hyprland 2024-04-12 20:39:00 +03:00
Vaxry
382b6d3f6b makefile: move wlr headers dir 2024-04-12 18:07:04 +01:00
Vaxry
0a70ccd099 Makefile: remove refs to libwlroots 2024-04-12 17:58:18 +01:00
vaxerski
e1e11f5a87 [gha] Nix: update wlroots 2024-04-12 15:32:45 +00:00
Vaxry
45945a3e7d deps: move from wlroots to wlroots-hyprland 2024-04-12 16:31:50 +01:00
Vaxry
b1a9430289 inhibitor: always destroy on window unmap
ref #5555
2024-04-12 00:18:58 +01:00
Jan-Peter Dhallé
e0a7cf5c30 master: fix full height when all windows master (#5549) 2024-04-12 00:05:30 +01:00
Vaxry
185a3b4881 swipe: nuke numbered
fixes #5424

use_r instead
2024-04-11 12:46:19 +01:00
TheOnlyMrCat
47e5b41fea renderer: Add dimaround layer rule (#4643) 2024-04-11 12:41:18 +01:00
Vaxry
ac0f3411c1 macros: fix no pch warning 2024-04-11 02:13:05 +01:00
Vaxry
abc131ec7b configmgr: fix header priority 2024-04-11 02:12:29 +01:00
Ben Landon
558d1be7e3 hyprpm: Improve Hyprpm Update Performance (#5530)
* hyprpm: only clone the required history

* hyprpm: don't include tracy when building headers in release mode

* chore: remove old, commented-out code

See https://github.com/hyprwm/Hyprland/pull/4585#discussion_r1474780294

* chore: format code properly
2024-04-10 17:33:50 +01:00
SoSeDiK
0b2f7a1b2f cursor: Fallback to xcursor if failed to render hyprcursor (#5534) 2024-04-10 17:29:17 +01:00
Sungyoon Cho
c35fa9bacc workspace: update windows when selector match could change (#5533)
* workspace: update windows when group updates

* workspace: update windows when floating toggle

* workspace: update windows when stop dragging window by mouse
2024-04-10 17:26:11 +01:00
Vaxry
b573c20125 monitor: add workspace null check to visible flag
ref #5524
2024-04-10 17:21:45 +01:00
JManch
303b9956b2 hyprctl: print monitor disabled status (#5525) 2024-04-10 09:50:00 +01:00
SoSeDiK
1343aa865d config: Don't override fullscreen opacity if only two opacities are provided (#5512) 2024-04-09 16:22:44 +01:00
SoSeDiK
f2addfb404 props: Parse border color props as gradient (#5513) 2024-04-09 16:14:53 +01:00
Sungyoon Cho
fcac25bcc2 workspace: Add count group flag in windowCount workspace selector prop (#5499)
* Add groupCount workspace selector prop

* Intergrate groupCount with windowCount
2024-04-09 12:08:38 +01:00
ErrorNoInternet
f6786f04d2 hyprpm: install shell completions 2024-04-09 12:38:06 +03:00
ErrorNoInternet
c7b87e0aed hyprctl: fix fish completions 2024-04-09 12:38:06 +03:00
postsolar
d0d1ba5918 hyprctl: fix zsh completions
The file missed a line required by all ZSH completions in order to be automatically loaded
2024-04-09 07:08:54 +03:00
dranull
a06272ae55 input: Option for handling off-window axis events (#4177) 2024-04-08 23:35:21 +01:00
Mihai Fufezan
277f2bb76a Nix: add pkgconf 2024-04-08 20:54:06 +03:00
Vaxry
0457c2e348 pkg-config -> pkgconf for hyprpm and cmake 2024-04-08 20:54:06 +03:00
Tom Englund
125a8f7e07 workspace: fix crash on destruction of compositor (#5495)
when the compositor destructs because of exiting hyprland the
hookmanager and eventmanager is already destroyed, add an if check in
the destructor of workspace so it doesnt segfault on exit.
2024-04-08 18:28:11 +01:00
Vaxry
63e3668529 style: run clang-format 2024-04-08 15:33:02 +01:00
Tom Englund
db91d949f7 compositor: move wl_display_destroy_clients (#5498)
if enough clients are open when destructing the compositor destroying
clients will emit a wl_surface_unmap that a WLListener catches and doing
so it calls listener_unmapLayerSurface that tries to iterate over input
manager that is already destroyed, move the destruction of clients above
g_pInputManager.reset() and removeAllSignals() to ensure we dont
segfault at exit.
2024-04-08 15:32:31 +01:00
Vaxry
785d9d9521 config: verify string length in wrv2 before calling back
ref #5431
2024-04-08 15:27:13 +01:00
SoSeDiK
43b96f03b5 props: Allow setting per-window fullscreen opacity (#5470) 2024-04-07 23:19:02 +01:00
MightyPlaza
df1a3a978d input: don't remove pinned focus on workspace change (#5486)
modified:   src/helpers/Monitor.cpp
2024-04-07 23:13:56 +01:00
Vaxry
7d989f2cf0 damageSurface: don't correct smallVec twice 2024-04-07 22:25:34 +01:00
Vaxry
863c7b6072 eventloop: move timers to an event loop fd
fixes #5481
2024-04-07 21:55:29 +01:00
Mihai Fufezan
c0d283016b flake.lock: update
Contains hyprcursor 1.6
2024-04-07 22:52:10 +03:00
LOSEARDES77
20899d0df2 hyprpm: add shell completions (#5423)
* hyprpm: add completions

* hyprctl: correct spell mistakes

* Apply fixes

* makefile: correct shell completion paths

* makefile: remove complletions on uninstalling
2024-04-07 19:39:46 +03:00
Yaroslav Lelkin
b50182326c cmake: make sure that OpenGL::EGL is populated
bump cmake version cause 3.27 is the version where "... COMPONENTS
GLESx" option is introduced. See
https://cmake.org/cmake/help/latest/module/FindOpenGL.html
2024-04-07 19:08:25 +03:00
thejch
89f775aec2 master: fix crash (#5472) 2024-04-07 15:21:12 +01:00
Junxuan Liao
d657b59f70 IME: fix IME popup mouse inputs (again) (#5417)
`lastBoxLocal`'s size should be the actual popup's size instead of the cursor
rectangle's size. Also, the rectangle position is now relative to the popup.
(Actually fixes #5255 imho.)

One thing #3922 missed was handling focus held by buttons. Let's hope I get
it right this time.
2024-04-07 15:15:50 +01:00
Vaxry
f2a848cbcc core: Event loop rework (#5466)
* Event loop rework

* revert missed
2024-04-07 03:31:51 +01:00
thejch
9f1604e4b0 input: Dont set active monitor when simulating mouse movement (#5465)
* fix mouse simulation switching focusedmon

* fix some warnings with wrong enum
2024-04-07 01:07:21 +01:00
thejch
e80bccad51 master: fix workspace orientation not being restored after workspace rule no longer applies (#5463) 2024-04-06 23:49:38 +01:00
Vaxry
ff114cf6f9 input: fix focus on maximized bg surfaces 2024-04-06 18:59:23 +01:00
Vaxry
d846e82832 makefile: add patch option to make asan 2024-04-06 18:50:04 +01:00
Vaxry
fa79aacea3 constraint: fix possible uaf on double destruction
ref #5448
2024-04-06 18:43:17 +01:00
fred21O4
265c7924d8 flake.nix: add hyprcursor follows (#5435)
fixes a duplicate hyprlang instance sometimes being created due to hyprcursor not following hyprlands instance
2024-04-06 19:18:43 +03:00
Mihai Fufezan
3d64b0e9f0 flake.lock: update 2024-04-06 19:09:37 +03:00
Sungyoon Cho
04d067d78b IME: fix race condition on closing window (#5455) 2024-04-06 15:54:02 +01:00
staz
1596e2d1f7 workspacerules: add back on-created-empty functionality (#5452)
* workspacerules: add back on-created-empty functionality

* clang format

* workspacerules: spawn on-created-empty window while initializing CWorkspace

* clang format

* configManager: fix typo

---------

Co-authored-by: Your Name <you@example.com>
2024-04-06 15:53:32 +01:00
Vaxry
6cea710ac8 scripts: switch to branch --show-current for branch in generateVersion 2024-04-06 15:40:06 +01:00
Vaxry
f081a4300f input: fixup background layer checking on maximized 2024-04-06 15:18:58 +01:00
Vaxry
159444c45b compositor: fix ghost fadingOut windows remaining after cleanup 2024-04-06 14:59:30 +01:00
Vaxry
f8c22916ab compositor: remove windows from fadingOut properly 2024-04-06 14:51:35 +01:00
Vaxry
24734fbf1d subsurface: init existing subsurfaces on children creations
fixes #5333
2024-04-06 03:09:20 +01:00
Vaxry
dab149e4a6 core: fix compile without pch
fixes #5445
2024-04-05 21:23:28 +01:00
Vaxry
b5b1c0137d CColor: fix getAsHex 2024-04-05 21:23:06 +01:00
Vaxry
094bce8118 core: simplify sanityCheckWorkspaces 2024-04-05 19:43:51 +01:00
Vaxry
4909b0f350 monitor: unset visible flag from ws on disconnect
ref #5443
2024-04-05 19:25:40 +01:00
Vaxry
965a2e5b21 hooksystem: attempt allocating pages in linear order 2024-04-05 17:16:09 +01:00
Vaxry
f815a33f64 workspace: remove monitor and visible flags on inert 2024-04-05 16:57:49 +01:00
Vaxry
0051b078a1 monitor: check for invalid workspaces in onConnect
ref #5443
2024-04-05 16:57:49 +01:00
thejch
1e8f57c734 workspacerules: fix workspace rule loops (#5433) 2024-04-05 16:54:30 +01:00
Martin Sundhaug
942172d2dc hooksystem: Fix miscalculation in comment (#5442) 2024-04-05 12:56:53 +01:00
bvr-yr
baad44b4ca hyprpm: fix incorrect commits number parsing (#5437) 2024-04-05 04:40:44 +01:00
Vaxry
12d75c0c26 hyprpm: ignore version checks for shallow clones 2024-04-05 03:00:34 +01:00
Vaxry
1ae592fcd9 hyprpm: add support for minimum versions 2024-04-05 00:46:37 +01:00
Vaxry
51b3148f09 hyprpm: print more info on build failures 2024-04-05 00:23:05 +01:00
Vaxry
1454c6213e window: fix invalid last workspace id
ref #5432
2024-04-04 22:49:15 +01:00
Vaxry
ec2cc79c65 renderer: avoid double-rendering ls-es on fadingOut
fixes #5295
2024-04-04 22:43:57 +01:00
Vaxry
0569b9c300 hooksystem: manually map trampoline addresses
better patching of rip calls as we are close enough to just change them up
2024-04-04 18:50:37 +01:00
Vaxry
cba9c5ff95 core: fix visibility flags in moveWorkspaceToMonitor
fixes #5416
2024-04-04 18:30:50 +01:00
Sungyoon Cho
c4b660a339 IME: fix crash on restarting IME (#5428) 2024-04-04 17:34:04 +01:00
Vaxry
4f3e90ad2d popups: more safety in damage checking 2024-04-04 16:42:30 +01:00
end-4
9b8ef9206d layers: separate anim configs for open/close (#5421) 2024-04-04 16:41:09 +01:00
zakk4223
846162cce1 hyprpm: Use proper path to update repo when processing user provided revision (#5414) 2024-04-04 16:33:36 +01:00
Mihai Fufezan
81766647f2 hyprctl: fix grammar mistakes in completions 2024-04-04 10:49:25 +03:00
LOSEARDES77
1b43cd5231 hyprctl: Add shell completions (#5404) 2024-04-04 10:21:20 +03:00
Vaxry
b7d71bc0e1 keybinds: fix spammy warning 2024-04-04 01:16:47 +01:00
Vaxry
9cf563065a layouts: add missing include 2024-04-04 01:10:46 +01:00
Vaxry
36a8ae9bda input: allow focus to bottom layers on maximized in reserved 2024-04-03 21:57:19 +01:00
Micovec
949eb42613 hyprctl: improve help pages (#5385) 2024-04-03 23:41:10 +03:00
Vaxry
d605e47511 renderer: block screen shader on screencopy 2024-04-03 21:35:16 +01:00
Vaxry
10146f5ec5 core: fix some crash conditions around workspace ptrs in CWindow
ref #5402, supersedes #5409
2024-04-03 20:42:38 +01:00
Vaxry
d88d589880 swipe: add events 2024-04-03 19:20:47 +01:00
Vaxry
93915502d2 blur: block modif only on no new optimize 2024-04-03 17:08:11 +01:00
Vaxry
91061a2084 opengl: fix modif in blur 2024-04-03 15:08:29 +01:00
Vaxry
64964c4e3b renderer: render back layer for workspace-less passes 2024-04-03 14:28:15 +01:00
Vaxry
3981f85e94 opengl: log framebuffer errors 2024-04-03 14:24:15 +01:00
Vaxry
efdc1af044 renderer: some fixes for renderModif 2024-04-03 14:09:58 +01:00
Vaxry
347b839034 workspaces: add visible flag 2024-04-03 10:09:48 +01:00
thejch
fbdaf74a82 master: fix swapped workspaces (#5397) 2024-04-03 01:22:59 +01:00
thejch
3965faafac master: fix center resizing (#5394) 2024-04-03 01:22:27 +01:00
MightyPlaza
153c8f35ce workspace: fix special unnamed workspace rules (#5390)
modified:   src/desktop/Workspace.cpp
2024-04-02 22:58:45 +01:00
Vaxry
ef23ef60c5 Workspace/core: Refactor workspace storage (#5380)
* refactor workspaces to use ptrs

* clang-format
2024-04-02 20:32:39 +01:00
Vaxry
fc0a7af7ba IME: fix blurry ime on scaled
ref #5387
2024-04-02 16:10:55 +01:00
Vaxry
05eb2d4af2 master: guard window in moveWindowTo
fixes #5374
2024-04-02 12:46:15 +01:00
Sungyoon Cho
04a35891a1 IME: fix incorrect popup damage (#5383) 2024-04-02 12:22:41 +01:00
Vaxry
2e5b146e57 workspace: remove lastFocusedWindow on unmap 2024-04-02 12:10:03 +01:00
Vaxry
af3a61a4e4 core: assert attempted UAFs in windowExists
in prep of removing the thing altogether
2024-04-02 01:15:58 +01:00
Jan Beich
c377caee7a hyprerror: align 32-bit types after 4c796683c0 (#5375)
src/hyprerror/HyprError.cpp:64:33: error: no matching function for call to 'min'
    const auto   VISLINECOUNT = std::min(LINECOUNT, *LINELIMIT);
                                ^~~~~~~~
/usr/include/c++/v1/__algorithm/min.h:40:1: note: candidate template ignored: deduced conflicting types for parameter '_Tp' ('int' vs. 'long long')
min(const _Tp& __a, const _Tp& __b)
^
/usr/include/c++/v1/__algorithm/min.h:51:1: note: candidate template ignored: could not match 'initializer_list<_Tp>' against 'int'
min(initializer_list<_Tp> __t, _Compare __comp)
^
/usr/include/c++/v1/__algorithm/min.h:60:1: note: candidate function template not viable: requires single argument '__t', but 2 arguments were provided
min(initializer_list<_Tp> __t)
^
/usr/include/c++/v1/__algorithm/min.h:31:1: note: candidate function template not viable: requires 3 arguments, but 2 were provided
min(const _Tp& __a, const _Tp& __b, _Compare __comp)
^
2024-04-01 21:18:18 +01:00
Vaxry
3875679755 props: bump ver to 0.38.0 2024-04-01 19:30:37 +01:00
Sungyoon Cho
db1506130b IME: Fix ime popup coordinates and artifacts (#5373)
* ime: fix incorrect popup coordinate

* ime: fix popup artifacts
2024-04-01 16:37:59 +01:00
Vaxry
108163f1e5 animations: simplify window loop 2024-04-01 16:22:24 +01:00
thejch
7513c0cea5 renderer: Fix layer and window damage sometimes missing 1 frame (#5370)
* fix the layer and window damage missing 1 frame sometimes

* remove extra loop
2024-04-01 16:21:45 +01:00
thejch
800dbf71b0 renderer: Fix rendering when swiping workspaces (#5367)
* fix rendering on swiping

* add alpha check

* fix floating fs check
2024-04-01 16:16:18 +01:00
Vaxry
416b3d6167 socket2: sanitize data for newlines 2024-04-01 03:54:11 +01:00
thejch
ef7ac53e99 master: Make master workspace orientation rule dynamic (#5339)
* make master workspace orientation rule dynamic

* fix rebase

* fix special ws resizing

* style
2024-04-01 03:02:47 +01:00
thejch
9ae0c47a21 deco: fix groupbar offset (#5364) 2024-04-01 02:58:21 +01:00
Sungyoon Cho
ecc1f22e05 textinput: fix typo (#5365) 2024-04-01 00:41:00 +01:00
Micovec
8cb38d41d2 hyprctl: fix plugin list on no plugins (#5357) 2024-03-31 21:45:22 +01:00
Vaxry
9e8f051896 avar: minor fixes 2024-03-31 21:43:08 +01:00
Vaxry
64c8ba2fb1 avar: fix warp onEnd conditions
ref #5348
2024-03-31 21:34:11 +01:00
Vaxry
4156b55cf9 textinput: send deactivate on disable ti
ref #5288
2024-03-31 21:30:36 +01:00
thejch
e1e41e5448 reenderer: Add 1 border damage to fix number rounding issues (#5343)
* add 1 to border damage to avoid rounding issues

* add 1 to rounding too
2024-03-31 14:59:22 +01:00
thejch
16a9c16d9f renderer/animations: Fix various inaccurate damage tracking issues and offsets (#5297) 2024-03-31 02:14:26 +01:00
Zach DeCook
1cc9a44318 input: Fix incorrect keyboard focus taken when no window was present (#5337)
A non-keyboard layer never needs keyboard focus
2024-03-31 00:50:25 +00:00
thejch
5e8c25d498 core: match all workspace rules instead of the first one only (#5340) 2024-03-31 00:49:53 +00:00
Aqa-Ib
1aed45f61d core: Fix resizeparams (#5262)
* Revert a94b902

* Fix resizeparams using CVarList

* clang-format

* fix

* Use 's' as delimiter

* remove size checks

* fix tabs

* fix mixing tabs and spaces
2024-03-31 00:48:39 +00:00
Vaxry
77f26997fd IME: don't assert on lock mismatch, just fix it 2024-03-30 17:01:02 +00:00
thejch
906e498144 dispatchers: open special ws on active monitor instead of mouse monitor (#5330) 2024-03-30 16:58:18 +00:00
thejch
a17d7ba87b dispatchers: fix swap workspaces wrong positioning of floating windows (#5328) 2024-03-30 16:57:43 +00:00
Vaxry
6fb8f50205 hyprpm: avoid crashes on corrupted headers
ref #5329
2024-03-30 03:09:22 +00:00
Vaxry
54376d7b5f compositor: remove windows from fading out on destroy
ref #5321
2024-03-29 19:07:18 +00:00
Vaxry
3d1bf1405e keybinds: add binds:disable_keybind_grabbing
fixes #5273
2024-03-29 18:57:16 +00:00
Muhamed Hobi
53aa184d20 makefile: Remove old headers first (#5316)
Windows.cpp was moved and I found myself having both versions in my include. Clear out the headers before dumping new ones.
2024-03-29 14:07:33 +00:00
Vaxry
fcd9d77b64 layout: improve initial size prediction for floating 2024-03-29 00:43:50 +00:00
Vaxry
2930c5cb6f animvar: fixup update callbacks and cleanup 2024-03-29 00:23:23 +00:00
Mihai Fufezan
d8429eebc6 flake.lock: update
Fixes #5301
2024-03-28 18:44:00 +02:00
MightyPlaza
187caf4187 layers: don't change workspace on layer restore focus (#5308)
modified:   src/events/Layers.cpp
2024-03-28 14:15:34 +00:00
MightyPlaza
647d5a4ffc layers: fix bottom slide animation (#5307)
modified:   src/helpers/WLClasses.cpp
2024-03-28 14:14:27 +00:00
Vaxry
2571875453 format: fix format 2024-03-28 02:28:22 +00:00
MightyPlaza
c24034eb9d core: fix fullscreen + floating focus change (#5291)
modified:   src/Compositor.cpp
2024-03-28 02:08:21 +00:00
Vaxry
0869f65b0b input: add misc:hide_cursor_on_key_press
fixes #3045
2024-03-28 02:07:06 +00:00
Vaxry
132ab8d035 layers: add animation direction overrides
fixes #5285
2024-03-28 01:39:29 +00:00
vaxerski
93d0511471 layershell: update render pos and size in arrange
fixes #5258
2024-03-27 16:30:08 +00:00
Sungyoon Cho
ae52b7f468 textinput: fix ime when opening multiple windows (#5281) 2024-03-26 15:16:09 +00:00
Khalid
9b7ae25ae8 hyprctl: output json with --batch if requested (#5277) 2024-03-26 13:38:54 +00:00
vaxerski
1a0b8d1263 renderer: minor fixes to misaligned reported surface rendering
fixes #5257
2024-03-26 13:35:03 +00:00
Vaxry
a9d7526aae core: ensure m_pLastMonitor validity over unsafe state
ref #5241
2024-03-26 02:26:19 +00:00
thejch
414e37996d github: fix github issue template crash dir (#5269) 2024-03-26 02:21:31 +00:00
Vaxry
ae17e900e7 layer-shell: render popups above everything 2024-03-25 16:20:30 +00:00
Vaxry
ca17a89d86 renderer: allow blurring ls popups 2024-03-25 16:09:02 +00:00
thejch
356414639f core: fix missing workspace events during swapping (#5251) 2024-03-25 01:50:41 +00:00
dmayle
6b28bf563e keybinds: Fix exit trigger by moving it to monitor.frame (#5240) 2024-03-25 01:46:59 +00:00
thejch
8001b96bb5 renderer: dont render fullscreen special on wrong monitor (#5249) 2024-03-25 01:41:56 +00:00
Vaxry
89543e8e3c cursormgr: don't set x theme in changeTheme 2024-03-24 20:48:56 +00:00
Brett Alcox
03e99f93ae renderer: forward decl for b_pch=false (#5250) 2024-03-24 20:38:10 +00:00
Vaxry
294ff8609f cursormgr: log theme loading failures 2024-03-24 19:39:56 +00:00
Vaxry
1e82d5a04d ime: fix build without pch 2024-03-24 17:19:35 +00:00
Vaxry
5cc4bf699c IME: Refactor and fixup popups 2024-03-24 16:08:25 +00:00
Vaxry
acf15e5579 text-input: reset lock counter on surface destroy
fixes #5231
2024-03-24 15:00:00 +00:00
Vaxry
86dc46ffea animationmgr: use realpos and size for border damage
fixes #5239
2024-03-24 03:09:46 +00:00
Vaxry
09e1128da2 cursormgr: initialize size to 0
Because the ctor expects that. Ref #5237
2024-03-24 02:21:36 +00:00
Vaxry
432924b372 xwayland: assign wlr_surface on associate 2024-03-24 02:21:36 +00:00
thejch
c7fbea3368 animations: Fix animation issue in focusworkspaceoncurrentmonitor (#5202)
* dont render when workspace offset

* add guard

* can remove useless code now if workspace offset is not taken into account

* clang-format

* when special workspace is moved, set anim to move

* add offset back

* make it a configurable option because some folks apparently can't align their monitors correctly and may not want this feature😔

* remove config option
2024-03-23 22:14:50 +00:00
Vaxry
295128ab2a window: assign surface on create
ref #5076
2024-03-23 22:10:37 +00:00
Sungyoon Cho
2d5fda4810 input: fix crash with text-input-v1 (#5234) 2024-03-23 21:12:27 +00:00
Vaxry
0d91f82d83 config: be a bit louder in the disabled log warning 2024-03-23 21:11:00 +00:00
Khalid
059e85ae69 input: Add options to set tablet's active area (#5199)
* Add options to set tablet's active area

* Set tablet's active area in `setTabletConfigs`

* Fix formatting for new variables in ConfigManager

* Report tablet's physical size with hyprctl
2024-03-23 20:31:03 +00:00
fufexan
0dfdb6678f [gha] Nix: update inputs 2024-03-23 00:03:18 +00:00
Vaxry
9f2ed02f35 IME/TI: Fixes and refactoring
Fixes #5189
2024-03-22 23:08:52 +00:00
Vaxry
8c88689faf IME: guard unfocused TIs in leave 2024-03-22 18:58:28 +00:00
Vaxry
568b352b23 cmakelists: remove oopsie 2024-03-22 18:52:07 +00:00
Vaxry
d2b42e29c6 IME: fix crashes with destroyed text-inputs
ref #5189
2024-03-22 18:45:28 +00:00
Vaxry
461757e2fb scripts: fix asan patch 2024-03-22 18:45:28 +00:00
MightyPlaza
397e08c16a input: focus window on mouse down on groupbar (#5224)
modified:   src/render/decorations/CHyprGroupBarDecoration.cpp
2024-03-22 17:41:20 +00:00
Holger Schurig
c7c0e795d2 CGradientValueData: fix toString() method (#5220) 2024-03-22 17:34:51 +00:00
drendog
9bad62b85f layershell: release all mouse buttons before focus on new ls (#5219) 2024-03-22 01:28:50 +00:00
Philipp Schilk
a94b902bef windowrules: Fix resizeparams parsing. (#5206)
Parsing of resizeparams/relative vec2 did not correctly handle
multiple spaces between x and y arguments, causing the following
to fail to parse:

bind = $mainMod CTRL, h, resizeactive,  10       0

This is unexpected, because most other config values are whitespace
insensitive.
2024-03-21 15:18:24 +00:00
Andrey Donets
997ee82bdf hyprctl: add missing commands to usage (#5211) 2024-03-21 14:57:06 +00:00
Praneeth Jain
f1d06b773f hyprpm: add missing newline (#5207) 2024-03-21 14:50:19 +00:00
jill
ee00cb1dd8 opengl: report shader compilation errors from screen_shader (#5138)
* opengl: report shader compilation errors from screen_shader

* opengl: prefer .data()

* opengl: move shader error logging to logError

* opengl: quick glGetShaderiv -> glGetProgramiv fix

* opengl: typo fix

* opengl: format fixes

* opengl: minor compile fixes

* opengl: logError -> logShaderError
2024-03-21 14:46:23 +00:00
zakk4223
4c796683c0 config: Config error limit/hyprctl (#5165)
* Add error_limit to limit the number of config error messages shown in notification

* Add configerrors hyprctl command

* Formatting

* Formatting for not my code

* Use CVarList, add escapeJSONStrings

* Add indication there are more undisplayed errors

* Restore suppress_errors; move getErrors() to ConfigManager

* Formatting, wtf

* Format
2024-03-21 01:55:13 +00:00
Brett Alcox
214ec82ba7 build: fix builds without pch (#5198) 2024-03-21 01:54:10 +00:00
Horror Proton
bfc95e992d swipe: fix nullptr in onSwipeUpdate (#5191) 2024-03-20 18:13:31 +00:00
Nathan Hadley
d904f51716 README: Fix Preview B image (#5188) 2024-03-20 18:11:40 +00:00
Vaxry
361357095c workspace: fix selectors with special:
fixes #5187
2024-03-20 18:06:03 +00:00
Khalid
9ddf1b105e tablet: Add left_handed option for tablets (#5178)
* Add left_handed option for tablets

* Update left_handed tablet option's fallback string
2024-03-20 04:00:43 +00:00
thejch
95ac8a34b1 workspace: fix integer overflow in selector parser (#5177) 2024-03-20 02:33:39 +00:00
Vaxry
8593c45be3 refactor: move window.hpp to desktop/ 2024-03-20 01:44:51 +00:00
Vaxry
f6038837bc constraint: do not disable constraints in destroy
fixes #5170
2024-03-20 01:30:41 +00:00
Vaxry
07ab3b8cd6 hyprpm: log shell in build without fails 2024-03-19 22:12:55 +00:00
Vaxry
05cd6d3df1 config/workspace: added workspace selectors 2024-03-19 20:56:20 +00:00
Vaxry
c32b2331d1 constraint: set active flag before propagating props
fixes #5170
2024-03-19 18:55:17 +00:00
phonetic112
bcba3951f4 input: Only limit drag resizes (#5164)
* only limit drag resizes

* change to not equals

* remove extra parentheses
2024-03-19 16:03:31 +00:00
joshua
5c1097cbc1 IME: Improve handling of text-input and ime-relay (#5147)
* input: Handling multiple surfaces for the text-input-v1 protocol implementation and imporve InputMethodRelay logic

fixes #2708

* clang-format

* minor style nits

---------

Co-authored-by: Vaxry <vaxry@vaxry.net>
2024-03-19 15:54:33 +00:00
Epilepsy Gatherings
05c84304cc github: remove redundant instruction (#5163)
v0.34.0 is pretty old at this point.
2024-03-19 02:53:51 +00:00
Vaxry
7617c03dfd window: set config only when both props end anims 2024-03-19 02:53:13 +00:00
thejch
e6532ba024 animations: Fix incorrect animation when manually moving a window when its being created (#5141)
* fix incorrect rendering when manually moving a window when its being created

* add setAnimationsToMove
2024-03-19 02:52:52 +00:00
Vaxry
7a31c954e5 tablet: minor focus fixes
ref #3004
2024-03-19 02:45:11 +00:00
Vaxry
49f5fd59ad opengl: minor adjustment to getPreferredReadFormat
fixes #4791
2024-03-19 02:42:39 +00:00
Vaxry
7283dde878 screenShader: allow camel for screensize
ref #5059
2024-03-18 23:51:32 +00:00
Vaxry
4ffcdc41ff animations: fix layer slide with fade
fixes #5151
2024-03-18 18:29:57 +00:00
Vaxry
4b74123649 socket2: add pin event
fixes #4778
2024-03-18 18:11:20 +00:00
Vaxry
5eb33ff4d8 screenshader: add screen_size uniform
fixes #5059
2024-03-18 16:35:22 +00:00
Vaxry
7587cadd0a renderer: add support for gles3.2 screen shaders 2024-03-18 04:15:04 +00:00
Vaxry
c34ad12183 cursormgr: scale hotspot with buffer 2024-03-17 19:00:21 +00:00
Vaxry
30c5911718 renderer: minor fixups for misaligned surface rendering offsets
fixes #5136
2024-03-17 16:08:59 +00:00
Zach DeCook
3c21f5e07b swipe: Touchscreen workspace swipe (#4489)
* Workspace Swipe: Refactor update and end functions

* Touch: Implement workspace swipe better

ignoring additional fingers and new touches

allow gaps-right and gaps-left to be different
2024-03-17 15:43:59 +00:00
djvs
3ed3b34c4a keybinds: add Dispatchers for "force float" and "force tiling" (non-toggle) (#5137)
---------

Co-authored-by: djvs <djvs@users.noreply.github.com>
2024-03-17 15:41:43 +00:00
Vaxry
e68c07d809 renderer: don't render window on other mons during anim in
fixes #5139
2024-03-17 01:05:26 +00:00
thejch
0387528c56 master: fix moving fullscreen workspace and remove duplicate code (#5131) 2024-03-17 00:15:12 +00:00
Vaxry
0e87a08e15 renderer: disable surface adjustments for misaligned reported when manual resizing
ref #5135
2024-03-16 17:56:09 +00:00
Vaxry
3162739e1b renderer: don't translate surface box on interactive resizes with non-updated sizes
closes #5135
2024-03-16 17:12:29 +00:00
Omar
e566be7847 LICENSE: Update year (#5132)
Updating the license year from 2022-2023 to 2022-2024
2024-03-16 16:57:45 +00:00
Mihai Fufezan
bd332a79e7 Nix: match derivation to Nixpkgs 2024-03-16 18:12:42 +02:00
Vaxry
c5e28ebcfe props: bump ver 0.37.1 2024-03-16 14:51:49 +00:00
thejch
c942ce6dce renderer: add better multi monitor animations (#5126) 2024-03-16 14:49:34 +00:00
Vaxry
5e5d7e2abc renderer: fix non-reported sizes window box calculations
fixed #5129
2024-03-16 14:37:07 +00:00
Vaxry
19c90048d6 props: bump ver to 0.37.0 2024-03-15 23:58:39 +00:00
Vaxry
3f5f5f5491 splashes: add 2ya splash 2024-03-15 23:58:22 +00:00
Vaxry
2a2da6082e renderer: fix invalid access on non-assigned surfaces
fixes #5125
2024-03-15 21:29:20 +00:00
Vaxry
c4f52d1979 master: fix invalid config usage 2024-03-15 19:31:33 +00:00
Vaxry
38576d651a renderer: adjust surface dimensions for oversized not-yet ackd surface sizes
supersedes #5104
2024-03-15 19:23:51 +00:00
drendog
72d78eff95 sessionlock: refocus after destroy focused surface (#5117)
* fix: refocus after destroy focused surface

* refactor: minor refactor on refocus loop condition

* refactor: minor refactor on condition

* style: format code
2024-03-15 18:44:17 +00:00
Maximilian Seidler
a958884b52 lock: fix red screen issues with multiple monitors (#5100)
* lock: use uint64_t for iMonitorID

* lock: move activateLock to onNewSessionLock

* lock: add red screen fade

* lock: damage when fading the red screen and delay for screencopy

* lock: remove redundant scheduleFrameForMonitor
2024-03-15 16:17:13 +00:00
Vaxry
bb933dcf04 popup: avoid damage loops with commits
fixes #5118
2024-03-15 15:55:30 +00:00
thejch
bc15a8f600 renderer: Allow headless mode in hyprland (#4794)
* allow headless

* clang-format

* fix redundant logic lol
2024-03-15 14:28:14 +00:00
Mihai Fufezan
6c24cee88f flake.lock: update 2024-03-15 11:13:27 +02:00
Mihai Fufezan
d00c658405 Nix: add wrapping back
Ref: https://github.com/hyprwm/hyprland-plugins/issues/93
2024-03-15 10:11:56 +02:00
Vaxry
dc44bd7113 ci: remove codeql
bullshit, useless, and only fails for no reason
2024-03-15 03:32:24 +00:00
Vaxry
045c3fbd85 subsurface: fix visibility check
ref #5113
2024-03-14 20:42:33 +00:00
Vaxry
b7b13623ba subsurface/popup: expand on map/unmap to add buffering
ref #5113
2024-03-14 20:21:58 +00:00
Vaxry
164e92f8e3 internal: minor fixups for fading out xwayland windows
fixes #4935
2024-03-14 18:25:28 +00:00
Vaxry
3e67ee0f5f events: ignore setTitle when title didn't change 2024-03-13 15:38:24 +00:00
djvs
893c55217b input: only override dragging corner on floating (#5092)
Co-authored-by: djvs <djvs@users.noreply.github.com>
2024-03-13 03:38:32 +00:00
djvs
c58fcfbce2 input: add general:resize_corner for manual resizing (#5090)
* Resize corner config thing

* clang-format

---------

Co-authored-by: djvs <djvs@users.noreply.github.com>
2024-03-13 02:43:22 +00:00
thejch
7ea555da7f master: Fix master layout window focus and scroll (#5074)
* fix master switch window scrolling

* fix some more dispatchers and remove some duplicate code

* refactor and remove duplicate code

* fix focusmonitor: https://github.com/hyprwm/Hyprland/issues/5006#issuecomment-1986977255

* change check
2024-03-13 02:09:20 +00:00
Mihai Fufezan
6c53d4d82f Nix: remove hyprland-unwrapped leftover 2024-03-12 21:35:41 +02:00
Vaxry
5da9591775 config: more safety around monitor keyword
ref https://github.com/hyprwm/hyprland-wiki/issues/523
2024-03-12 15:37:46 +00:00
Ikko Eltociear Ashimine
f1ec0ba467 keybinds: Fix typo (#5081)
minor fix
2024-03-12 15:26:42 +00:00
Vaxry
a065b481f3 cursormgr: use XCURSOR_THEME for x themes 2024-03-11 20:33:26 +00:00
Lucas Reis
0fc9d45e4b core: Fix typo and check grandchild PID in spawn() (#5070) 2024-03-11 19:31:39 +00:00
Vaxry
66330281ff config: report errors from sourced files 2024-03-11 01:39:00 +00:00
Vaxry
220144276b layout: unfullscreen on toggle into tiled fullscreen
fixes a bug where the tiled window would be on top
2024-03-10 22:31:49 +00:00
Vaxry
0a1632a79f dwindle: preserve fs state on switchWindows
fixes #2842
2024-03-10 22:27:23 +00:00
NotAShelf
981296f101 flake: bump inputs (#5066) 2024-03-10 19:52:54 +00:00
Vaxry
0c28d4e334 window: prevent vector modification segfault while iterating
oops, updateWindow can modify the vec
2024-03-10 16:56:42 +00:00
Matt Wyatt
335506d555 constraints: only warp cursor on deactivate if constraint is locked. (#5056) 2024-03-09 23:19:48 +00:00
Vaxry
b0f98a3d3e compositor: reject focus to noFocus OR xwayland windows
fixes #4922
2024-03-09 22:39:23 +00:00
Vaxry
2ed032a7fd xwayland: fix no_xwayland compiles 2024-03-09 22:37:49 +00:00
Vaxry
739c5bc98c cursormgr: fix invalid access to hyprcursor in xwayland init
fixes #5048
2024-03-09 21:54:33 +00:00
Vaxry
26cd1bf949 input: fix minor default cursor reset conditions 2024-03-09 18:12:55 +00:00
Vaxry
18a35b1406 cursormgr: fix memory leak with cursor buffers 2024-03-09 18:04:33 +00:00
Vaxry
7e41e5146d cursormgr: add fallbacks for unknown cursors 2024-03-09 18:00:37 +00:00
Vaxry
c3882bb832 internal: Support libhyprcursor (#5009)
woo

---------

Co-authored-by: Mihai Fufezan <fufexan@protonmail.com>
2024-03-09 16:52:59 +00:00
Vaxry
e7a5db4852 xwayland: Set xwayland's name prop (#4924)
* set xwayland name

* [gha] Nix: update wlroots

* fix

---------

Co-authored-by: vaxerski <vaxerski@users.noreply.github.com>
2024-03-09 16:47:57 +00:00
Vaxry
a01949dd28 deco: fix warnings 2024-03-09 16:39:38 +00:00
vaxerski
fa886d8b11 [gha] Nix: update wlroots 2024-03-09 16:36:19 +00:00
Vaxry
3f58e77e75 deps: update wlroots 2024-03-09 16:35:35 +00:00
Vaxry
300d77edd9 keybinds: track submap at press for keypresses
fixes #5037
2024-03-09 16:08:07 +00:00
Vaxry
c9ea600baa layer-shell: allow for popup creation before map
ref https://github.com/jjsullivan5196/wvkbd/issues/65
2024-03-09 15:32:36 +00:00
Vaxry
3e930a568a format: fix format 2024-03-09 03:09:25 +00:00
Vaxry
024d4ddc74 input: scale local coords in constraints
fixes #5029
2024-03-08 22:51:28 +00:00
Vaxry
717d5b3cc2 hyprctl: hide unmapped windows without -a 2024-03-08 17:47:12 +00:00
Vaxry
0a4ade01d3 format: make ci happy 2024-03-08 17:40:28 +00:00
Aaron
5920c6a6b8 socket2: Add 5 IPC event with support for workspace ID (#5022)
- `moveworkspacev2`:    returns workspaceID,workspaceName,monitorName
- `movewindowv2`:       returns windowAddress,workspaceID,workspaceName
- `createWorkspacev2`:  returns workspaceID,workspaceName
- `destroyWorkspacev2`: returns workspaceID,workspaceName
- `workspacev2`:        returns workspaceID,workspaceName

- Include workspaceID as a parameter in CWorkspace constructor to support `createWorkspacev2`.

Resolves #4929
2024-03-08 17:39:53 +00:00
Vaxry
4c34e4aac2 windowrules: minor improvements to min/max size
fixes #5017
2024-03-08 17:10:38 +00:00
Fazzi
d1c80c31c8 README: change dwl link to new codeberg link (#5026) 2024-03-08 16:30:42 +00:00
Epilepsy Gatherings
1290507ac4 windowrules: check if floating when resizing from maxsize (#5019)
* check if floating

* use return
2024-03-08 14:54:45 +00:00
Epilepsy Gatherings
e52d3fa852 windowrules: Make min/maxsize rules dynamic (#4775)
* rebase

* simplify and remove prop

* Stuff

- add back win prop
- change minsize defaults
- change request formatting for setprop

* style fix

* remove empty line

* change defaults

* redo string to vec

* remove redundant parsing

* change to vec

* support commas

* remove static rules

* take out garbage

* format

* don't allow commas and resize on setprop

* use isNumber
2024-03-08 02:24:44 +00:00
ItsDrike
ceecdd0fd5 hyprctl: Fix incorrect invalid fontsize kwarg response (#5013) 2024-03-07 23:34:33 +00:00
thejch
6c4e2489a0 layout: Fix toggling fullscreen special workspace on different monitor (#5000)
* fix toggling fullscreen special ws on different monitor

* add for dwindle

* fix change regular workspace when special fullscreen
2024-03-07 13:27:58 +00:00
thejch
bf71026b8d master: change active monitor when moving windows around (#5001) 2024-03-07 13:23:22 +00:00
Mihai Fufezan
77161fdbef flake.lock: update 2024-03-07 11:03:43 +02:00
Mihai Fufezan
ce072638e9 Nix: use propagatedBuildInputs instead of wrapping
This way, users that want to wrap Hyprland themselves won't have the
issues of double-wrapping.
2024-03-07 11:02:18 +02:00
Vaxry
95769a3c54 compositor: update state after moving to workspace
fixes #4987
2024-03-06 21:33:55 +00:00
ItsDrike
067df84388 notify: Add custom fontsize support for notifications (#4981)
* Add custom fontsize support for notifications

* Remove debug stuff

* Use original default font size

* Handle fontsize as keyword arg

* Use CVarList::join instead of for loop

* Use size_t for msgidx
2024-03-06 21:20:26 +00:00
Vaxry
8e2a62e53b events: apply monitor state on sessionActive
ref #4839
2024-03-06 18:14:59 +00:00
Vaxry
669ea8a373 ci: pack hyprpm to the release tar 2024-03-06 15:26:58 +00:00
ItsDrike
082bf00254 hyprpm: Add support for specifying exact git revisions for plugin repo (#4983)
* hyprpm(feat): support specifying exact git revs

* Mention git rev argument in help

* Mention git rev arg is optional

* Wrap text
2024-03-06 12:01:04 +00:00
outfoxxed
d6f1b151b2 animations: fix m_Goal not being set after #4911 (#4992) 2024-03-06 10:14:13 +00:00
bvr-yr
fb87e332c5 input: fix window move stutter by introducing additional checks for low-hz monitors (#4553)
* resize-limiter: add additional check for low-hz monitors

* simplify checker

* add comment

* rename variable
2024-03-06 00:15:44 +00:00
Zach DeCook
b1e2ca04a0 CrashReporter: Fix compilation with musl libc (#4805)
It can be assumed this doesn't function correctly:
my 'configuration does not support execinfo.h', so I have no backtrace to test against
2024-03-05 22:51:34 +00:00
Vaxry
05dd204c5f window: ignore surface updates in unsafe / on invalid monitors 2024-03-05 20:46:08 +00:00
Vaxry
31e1287da2 subsurface: don't update transform on unmap
fixes #4969
2024-03-05 20:45:23 +00:00
Vaxry
a4c1f4a03d popup: send scale on map
fixes #4972
2024-03-05 20:42:29 +00:00
Grant Ammons
0ee69058c4 config: Add input:scroll_factor configuration (#4980)
* Allow for input:scroll_factor configuration

This PR will allow for a `scroll_factor` configuration within an `input`
block.  The purpose is to control the scroll factor of external mice.

Closes #2574.

* clang-format
2024-03-05 19:18:53 +00:00
Junxuan Liao
f8a081b56d layout: warp the cursor when focusing windows (#4982)
Similar to the `focuswindow` dispatcher, when focusing a window with
wlr-foreign-toplevel-management, the cursor should be warped. Otherwise, the
focus is lost immediately after the cursor moves.
2024-03-05 17:56:06 +00:00
Vaxry
bdfa8ab856 hyprctl: print format and modes
fixes #4971
2024-03-05 13:55:38 +00:00
Junxuan Liao
08152477dc monitor: remove commas from short description (#4970)
Since `hyprctl monitor` shows szShortDescription now, it needs to be sanitized.
(See #2457)

Also, monitor selectors are now compared against szShortDescription and
szDescription to avoid re-striping the string.
2024-03-05 13:41:51 +00:00
Vaxry
12985fa0d8 surface: fix damage tearing feedback
fixes #4935
2024-03-05 00:21:37 +00:00
thejch
9c48c322d4 keybinds: Allow fullscreen/maximize in special workspace (#4921)
* allow fullscreen/maximize in special workspace

* remove duplicate code

* hide top layer

* fix special fullscreen deco

* edit

* fix fade top layer when toggle special

* remove double render
2024-03-04 23:29:45 +00:00
Vaxry
7a76ab01d1 input: send motion to confined cursors 2024-03-04 23:07:16 +00:00
musjj
f3c92e75c8 CI/Nix: attempt to fix broken cache (#4963)
DeterminateSystems/nix-installer-action is causing hash inconsistency between CI & local build.
2024-03-04 20:33:42 +02:00
Tom Benham
07c7235b72 keybinds: Better handling of workspace_back_and_forth (#4952)
* Removed redundant boolean condition

* Better handling of workspace_back_and_forth when using focusworkspaceoncurrentmonitor dispatcher

* Fixed config acquisition

---------

Co-authored-by: Tom Benham <tom.benham@quadrille.fr>
2024-03-04 17:05:20 +00:00
Vaxry
12da0fc84f hyprctl: parse custom types in getoption 2024-03-04 10:36:38 +00:00
Isaiah Hamilton
9d89b7109d config: update per device input configs link (#4951) 2024-03-03 23:00:28 +00:00
Vaxry
063708df26 config: improve config value infrastructure 2024-03-03 18:41:38 +00:00
JManch
8ccbd272cc compositor: ignore grab extend behind special workspaces (#4944)
* compositor: ignore grab extend behind special workspaces

* ignore the window entirely
2024-03-03 17:04:39 +00:00
thejch
28272d2d74 master: Fix animate resize (#4942)
* fix master animate resize

* fix some other pointers
2024-03-03 17:03:23 +00:00
Vaxry
c701767038 xkb: handle invalid keymaps in updateXKBTranslationState
fixes #4941
2024-03-03 17:02:15 +00:00
Vaxry
cc94123fa7 renderer: minor fixes to transformations 2024-03-03 02:18:06 +00:00
Julien Roy
2a08f2ba84 opengl: fix compilation on legacy renderer (#4928) 2024-03-03 00:31:36 +00:00
Vaxry
689fced8b9 windowrules: fix center
fixes #4934
2024-03-03 00:22:40 +00:00
Epilepsy Gatherings
acf0b536a6 xwayland: disable initial focus for xwayland dialogs (#4936) 2024-03-03 00:18:53 +00:00
JManch
1762e9c6ec renderer: respect forceNoBlur when rendering small surface windows (#4932) 2024-03-03 00:17:40 +00:00
Tobias Zimmermann
964f1a438d keybinds: Add the 'catchall' keyword that matches all keys (#4930)
* Add the 'catchall' keyword that matches all keys

This keyword can be used to define arbitrary keybinds. The only special
behavior that it exhibits is that it matches every key, including
modifier keys. Any flags still apply normally.

This commit also fixes an issue that keys bound via the code:KEYCODE
format were not unbound correctly.

* Disallow catchall keybinds outside of submaps

A catchall keybind outside a submap would prevent essentially all key
events from going through to applications and would be difficult to
remove again.
2024-03-03 00:17:02 +00:00
JManch
508262b7db events: update render data after workspace window rule (#4931) 2024-03-02 22:15:07 +00:00
Vaxry
d72ea5f2a7 input: Rewritten pointer constraints (#4889)
* rewritten constraints

* send pointer enter on activate if not pointer focus

* minor cleanup

* simulate movement on commit

* don't ignore oneshot prop

* various fixes

* dont send motion on confined

* update pos hint on region change
2024-03-02 21:04:55 +00:00
Vaxry
328ab43165 hyprpm: don't copy .so if file doesn't exist
ref #4926
2024-03-02 19:06:09 +00:00
Vaxry
d2289d8327 xdg: minor improvements to initial size reporting
fixes #4918
2024-03-02 18:53:17 +00:00
ItsDrike
be89d6faa9 notifs: Implement notification dimissing (#4790) 2024-03-02 18:12:31 +00:00
Vaxry
8811f4b69a drag: check min size for reisze drags
fixes #4920
2024-03-02 15:25:32 +00:00
Vaxry
52db216608 events: don't switch to active workspace on workspace rule 2024-03-02 15:20:40 +00:00
ves
1e311c947e Nix: add missing dependencies for make asan (#4919) 2024-03-02 17:02:33 +02:00
Vaxry
7ce781e87c keybinds: better follow xkb translation state
fixes #4908
2024-03-02 01:46:55 +00:00
GartoxFR
b2c3440477 animations: Refactor AnimatedVariable (#4911)
* animation: Refactor AnimatedVariable

This commit decomposes the AnimatedVariable class into a base class
with the common attribute to all variable types and a templated derived
type containing strongly typed info on the type being animated.

Access to the typed version is perfomed using the visitor pattern. A
utility is provided to build a visitor on the fly using lambdas.

Adding a new type to be animated should just be a matter of adding the
typed in the list defined by the ANIMABLE_TYPES macro

The size of the commit is justified by the API change in the
AnimatedVariable class. No more vec(), fl() or col() method but a unified
value() method.

* animation: Remove visitor pattern

* animation: Fix coding style

* animation: Fix coding style
2024-03-02 00:35:17 +00:00
Vaxry
f115ba94d2 xwayland: set scaledBy for unmanaged windows in map 2024-03-01 23:04:34 +00:00
Brett Alcox
6e3a494d1d core: add additional headers for Popup.cpp and InputMethodRelay.hpp (#4909) 2024-03-01 20:07:36 +00:00
Vaxry
555afea73c makefile: add config to make asan 2024-03-01 14:16:56 +00:00
Vaxry
4937352761 makefile: add asan 2024-03-01 14:14:28 +00:00
Vaxry
f590505daf popup: minor fixes to xdg geometries
fixes #4900
2024-02-29 21:51:50 +00:00
Vaxry
f801d15947 configmgr: fix compile on 32-bit archs
fixes #4895
2024-02-29 21:33:39 +00:00
Vaxry
e63b4b18aa renderer: force a few render frames on init anim end
fixes #4875
2024-02-29 19:04:40 +00:00
Vaxry
1698d336f2 core: fix crashes on access of deleted wlr_ surface
ref fixes #4893
2024-02-29 17:23:44 +00:00
Vaxry
fbba8757cb window: remove unused list 2024-02-29 16:16:03 +00:00
Vaxry
6916d0a6a3 surface: unify owners 2024-02-29 15:07:14 +00:00
Anton Samokhvalov
bcec082a1c build: fix libc++/clang build (#4886) 2024-02-29 15:01:56 +00:00
Vaxry
2e111c8cf9 xdg: rewrite entire popup implementation 2024-02-29 14:26:02 +00:00
Vaxry
b39dcfa497 refactor: move a few things to desktop/ 2024-02-29 13:03:38 +00:00
Vaxry
4bff762d97 xwaylandmgr: don't read xwayland surface from unmapped xwayland 2024-02-29 01:21:23 +00:00
Vaxry
b1c0f1cc01 subsurface: Rewrite the subsurface tree (#4877) 2024-02-29 00:03:28 +00:00
Vaxry
1e7eb3a5a5 xdg: check for floating conditions before sending tiled size hint
ref #4871
2024-02-28 23:14:50 +00:00
Vaxry
097f561e41 surfacetree: Revert "subsurfaceTree: assign surfaces to a CWLSurface"
This reverts commit 51b1b17fcb.

Crash issues, fixes #4874
2024-02-28 19:42:04 +00:00
Vaxry
a31433c215 renderer: damage whole ring on failed commit
fixes #4770
2024-02-28 18:00:02 +00:00
Vaxry
51b1b17fcb subsurfaceTree: assign surfaces to a CWLSurface
fixes #4872
2024-02-28 17:53:17 +00:00
Vaxry
29cdd7de1f layers: minor fixes for new animations 2024-02-28 15:59:45 +00:00
Vaxry
4bc669f933 layers: add fully featured animations
Adds configs and layerrules to handle them

alas fixes #981

I have cooked
2024-02-28 15:00:40 +00:00
vaxerski
f4f3aa2e50 layout: add size prediction for initial xdg commits
fixes #4022
2024-02-28 11:45:43 +00:00
JManch
c198d744b7 keybinds: unconstrain mouse on focusmonitor and cyclenext (#4863) 2024-02-28 00:52:45 +00:00
Vaxry
1c460e98f8 props: bump ver to 0.36.0 2024-02-28 00:32:40 +00:00
Tobias Zimmermann
489ac40abd config: Add option to resolve keybinds by sym instead of code (#4851)
This commit adds the new configuration option 'resolve_binds_by_sym'
which can be set globally or per-device. It is off by default, which
preserves the current behavior.

This setting only affects the behavior of keybinds that are defined via
key symbols, not those defined via keycode. Binds defined by symbols
currently activate if the keycode pressed would generate the specified
symbol on the first layout specified in the input section.
If enabled, keys pressed on the relevant device will instead match
keybinds by the symbols they produce with their current layout.

Closes #1881.
2024-02-27 23:21:22 +00:00
Vaxry
e3373669e5 wayland: implement keyboard_shortcuts_inhibit_v1
fixes #4568
2024-02-27 23:15:24 +00:00
Vaxry
f26d7aa58d config: add defaultName for workspace rules
alas, fixes #665
2024-02-27 22:44:42 +00:00
Vaxry
e2c286548d avar: return curve value of 1 when not animated
fixes #4862
2024-02-27 22:34:07 +00:00
Philip Damianik
60f81b8a23 input: Map touch devices and tablets bound to an output (#3544)
* Map bound touch devices and tablets to an output

* Add "[[Auto]]" default option for auto detecting outputs for touch inputs

* Bind new monitors to configured touch and tablet devices

* Use Monitor::matchesStaticSelector in CConfigManager::getMonitorRuleFor

* Use Monitor::matchesStaticSelector in CCompositor::getMonitorFromString
2024-02-27 22:11:59 +00:00
vaxerski
98034fea3c screencopy: send full frame damage
fixes #4855
2024-02-27 14:51:27 +00:00
Vaxry
21f7f32dc9 screencopy: avoid dangling client ptrs on client destroy 2024-02-27 12:23:59 +00:00
Vaxry
ffd7217243 IME: don't set modifiers on grab destroy 2024-02-27 12:23:45 +00:00
Vaxry
bc3f5b94eb core: nullcheck for old monitor in moveWorkspaceToMonitor
fixes #4495
2024-02-26 21:12:12 +00:00
Vaxry
f7a3453487 socket2: move to the wayland event loop 2024-02-26 17:20:51 +00:00
Bernd Müller
1742605eb8 keybinds: fix movewindoworgroup onto empy workspace on next monitor (#4486)
* fix: movewindoworgroup when no window or group is in desired direction, e.g. move window onto empty workspace on next monitor

* fix: movewindoworgroup when no window or group is in desired direction, e.g. move window onto empty workspace on next monitor

* reset flake.nix

* add: changes mentioned in review of #4486
2024-02-26 14:05:24 +00:00
github-usr-name
81fe2ae7f1 surface: ensure global pointers valid before using in destructor (#4844)
This fixes an observed SigSegV resulting from the cursor surface using
`g_pInputManager` when invoked from the `CInputManager` destructor

Co-authored-by: github-user-name <spam-here@github.com>
2024-02-26 09:52:12 +00:00
Vaxry
dfcfb92ec6 renderer: take into account fading out windows in solitary recheck 2024-02-26 00:19:16 +00:00
Vaxry
9815402074 keybinds: focus floating on top of fs 2024-02-26 00:15:59 +00:00
shezdy
a14f6b570f keybinds: fix focuswindow for fullscreen (#4840)
* focuswindow fix

* fix format

---------

Co-authored-by: ddmetz <77217897+ddmetz@users.noreply.github.com>
2024-02-26 00:05:20 +00:00
fufexan
7f35bff720 [gha] Nix: update inputs 2024-02-26 00:03:49 +00:00
Tom Benham
54a8329936 layout: Fixed ghost window when opened while fullscreen on a different workspace (#4822)
* Fixed ghost window when opened while fullscreen on a different workspace

* Format

---------

Co-authored-by: Tom Benham <tom.benham@quadrille.fr>
2024-02-25 14:09:41 +00:00
github-usr-name
f9cfec8abb compositor: allow source monitor to be provided to getMonitorInDirection (#4837)
Co-authored-by: github-user-name <spam-here@github.com>
2024-02-25 14:03:00 +00:00
Sergei Trofimovich
f534ac3fc4 hyprctl: add missing newline in error case of missing HYPRLAND_INSTANCE_SIGNATURE (#4832)
Before the change running a `hyprctl` in incomplete `Hyprland`
environment merged error message and prompt for me as:

    $ hyprctl activewindow
    HYPRLAND_INSTANCE_SIGNATURE not set! (is hyprland running?)$

(note trailing `$` prompt).

After the change the newline is present as expected:

    $ hyprctl activewindow
    HYPRLAND_INSTANCE_SIGNATURE not set! (is hyprland running?)
    $
2024-02-24 23:35:36 +00:00
Vaxry
9103af317e hyprctl: ignore non-lock files for instances 2024-02-24 23:35:18 +00:00
Vaxry
5824b0f305 hyprctl: fix showing invalid instances 2024-02-24 17:36:43 +00:00
JManch
e9528fc214 config: fix layout invalidation for keyword commands (#4826) 2024-02-24 14:06:28 +00:00
Vaxry
6f83856025 hyprctl: add -r argument 2024-02-24 14:02:03 +00:00
thejch
d92da7959a core: Fix SEGV/ABRT core dump when exiting (#4823)
* reset input manager first

* move reset
2024-02-24 02:50:54 +00:00
Mihai Fufezan
f27054c13e flake.nix: override inputs for xdph and hyprlang 2024-02-24 00:48:11 +02:00
Vaxry
bdbd8d965d hyprctl: jsonify new gaps
fixes #4820
2024-02-23 21:25:04 +00:00
Vaxry
bfb1e876a8 config: add opengl:force_introspection
fixes #4819
2024-02-23 21:21:24 +00:00
Vaxry
ca59bd5739 opengl: check bottom/bg layers for required introspection
ref #4818
2024-02-23 21:09:47 +00:00
thejch
f389f77015 core: Try to fix the exit hang (#4811)
* add signal removal

* use a flag instead

* remove signals in cleanup
2024-02-23 16:48:27 +00:00
Vaxry
8c3613632a renderer: nuke lastFrameDamage and rework finalDamage
this fucking SUCKED
2024-02-23 01:02:32 +00:00
Vaxry
c1ef361e02 renderer: fix logs 2024-02-23 00:02:48 +00:00
Vaxry
35e80a64a6 renderer: add more logging for fails in beginRender 2024-02-22 23:50:56 +00:00
Vaxry
e83bf4f7b7 core: add env to disable crash reporter 2024-02-22 23:10:59 +00:00
Vaxry
c353b7c4f7 renderer: minor fixes for introspection detection 2024-02-22 23:01:22 +00:00
Vaxry
d9757b61bf xdg: manually schedule initial configures
chasing wlroots

fixes #4801
2024-02-22 17:33:23 +00:00
vaxerski
28410922da [gha] Nix: update wlroots 2024-02-22 16:23:35 +00:00
Vaxry
cfc652e17d deps: downgrade wlroots due to xwayland segfaults 2024-02-22 16:22:51 +00:00
vaxerski
dbccbabac5 [gha] Nix: update wlroots 2024-02-22 15:56:22 +00:00
Vaxry
9a6956fe67 deps: update wlroots 2024-02-22 15:55:33 +00:00
Vaxry
af0c8e299b input: fix vectorToWindowUnified with floating over fs
fixes #4800
2024-02-22 15:42:17 +00:00
Vaxry
7fbe016c15 animationmgr: expand layer box for damage 2024-02-22 15:34:18 +00:00
Vaxry
0ebee80bca config: adjust default splash col 2024-02-22 15:28:58 +00:00
Vaxry
c4283abb9f compositor: check for pworkspace validity in setActiveMonitor 2024-02-22 15:12:51 +00:00
Vaxry
94aeb06d6b toplevelexport: set last damage for dmabuf copy 2024-02-22 03:10:01 +00:00
Vaxry
ea3fd13e24 shadow: fix missed invalid use of cfg val ptr
fixes #4785
2024-02-21 19:26:21 +00:00
Hiram Muñoz
dad8ffd576 renderer: Update splash text properties to be configurable (#4707)
* Update splash text properties to be configurable

The splash text's font and color properties have been updated to be configurable. This change includes adding new configuration values for the splash screen color and font. The rendering of the splash screen is also adjusted to use these new config values, allowing for easy customization of the splash text appearance.

* Updated to use Hyprlang config manager
2024-02-21 18:31:29 +00:00
q234rty
fc5ca391ad core: Fix building plugins (#4783) 2024-02-21 16:57:44 +00:00
André Silva
e5eb1bdf01 renderer: ignore set cursor surface if cursor should be hidden (#4780) 2024-02-21 13:48:48 +00:00
Dashie
ddf022d61c feat: Add css style gaps (#4723) 2024-02-21 11:07:39 +00:00
Vaxry
13d9854897 xdgpopup: fix UAF because of an invalid listener connection
destroy should be connected to popup::destroy, not popup::surface::destroy...

ref #4751
2024-02-20 18:14:36 +00:00
vaxerski
cd73dda16e sessionLock: send preferred fractional scale 2024-02-20 16:13:01 +00:00
vaxerski
02c9a2d769 screencopy: damage entire screen on a no-damage request 2024-02-20 15:22:54 +00:00
vaxerski
7ea37c9dc9 surface: fix damage calcs with a viewport src 2024-02-20 15:21:30 +00:00
Vaxry
86be75dd97 events: bring back accidentally nuked preConfigReload 2024-02-20 03:24:15 +00:00
thejch
030ed27cc8 crashreporter: Use ~/.cache as cache dir (#4719)
* use ~/.cache for crash reports

* minor word edit

* clang-format

* minor typo
2024-02-20 00:55:04 +00:00
Vaxry
e793f10b8b screencopy: fix invalid damage being used for final copy in dma 2024-02-19 20:05:51 +00:00
Vaxry
d62e7a5125 renderer: fixup damage_ring rotation 2024-02-19 19:11:05 +00:00
Vaxry
fe9c8d8745 format: fix formatting 2024-02-19 17:20:39 +00:00
vaxerski
df82625206 hyprctl: reload everything on dynamic source keywords 2024-02-19 12:45:05 +00:00
vaxerski
1763566308 surface: minor fixes for last logicalDamage calc fix 2024-02-19 11:34:55 +00:00
vaxerski
e4790e3f8e surface: fix invalid damage tracking in damageSurface
ref #4744
2024-02-19 11:24:54 +00:00
rszyma
69a4f08dbe keybinds: fix keys without keysyms triggering random binds (#4739) 2024-02-19 00:02:03 +00:00
Vaxry
c6b1d82c70 hyprctl: more safety around stoull 2024-02-18 23:31:43 +00:00
Vaxry
301b48b740 renderer: fix invalid damage accumulation with invalid buffer_age
fixes #4670
2024-02-18 16:04:08 +00:00
Vaxry
fae47ef462 config: fix errors in default config 2024-02-18 15:34:43 +00:00
Vaxry
5fc0b772c7 config: update default config for hyprlang migration 2024-02-18 15:02:34 +00:00
Vaxry
13f6f0b923 Migrate the config to hyprlang (#4656)
* Migrate to hyprlang

* pop up errors

* fix swapped args

* Meson & Nix: build with hyprlang

* CI: add hyprlang to setup action

* add infra for plugin stuff

* fix hyprctl getoption

* fix hyprctl getoption with json

* format

* fix post parse logic

* fix autogen config

* oops missed exec-once

* fmt

* fix ws rules

* require 0.3.0 for hyprlang

* nix: flaek

* minor type fixes

* fix cfg usages in swipe

* use cvarlist for ws rules

* fix throw in addPluginConfigVar

* Nix: update hyprlang

* minor fixes

* fix disableLogs

* mention hyprlang docs

* bump hyprlang dep in cmake

* Meson: bump min hyprlang version

Nix: update hyprlang

* minor fix

* Nix: update meson patch

---------

Co-authored-by: Mihai Fufezan <fufexan@protonmail.com>
2024-02-18 15:00:34 +00:00
Alessio Molinari
7e8bcd675d monitors: fix outputmgr nullptr crash (#4738) 2024-02-18 02:24:01 +00:00
Vaxry
683a4b07c5 rules: ignore static tile/float rules in dynamic gets
fixes #4736
2024-02-18 00:13:43 +00:00
Federico Maria Morrone
5261a8df81 keybinds: Add an option to pass a window argument to moveoutofgroup (#4724)
* keybinds: allow passing window to moveoutofgroup

* keybinds: cleaner handling of certain args
2024-02-17 22:44:22 +00:00
epicgamer256705
289d952a6e dispatchers: add Fullscreen without sending fullscreen to application (#4720)
* Add extra option to fullscreen

* Remove useless branch

fixes #1817

---------

Co-authored-by: matteo bob <matteo4375@gmail.com>
2024-02-17 16:21:06 +00:00
Vaxry
294e51a857 input: refocus on completed drags 2024-02-17 16:02:17 +00:00
Vaxry
cdcc5aba06 xwayland: ignore OR activate requests if surface doesn't want focus 2024-02-17 02:47:07 +00:00
Abílio Costa
e3e7e1fdda monitor: don't damage twice (#4727)
When scaled, the ring is already fully damaged, no need to add the region
damage.

Also moved a variable that was being declared way to far for where it is
actually used.

Co-authored-by: Abilio Costa <abilio.costa@criticaltechworks.com>
2024-02-17 02:09:12 +00:00
Vaxry
fbf5ba87ce shaders: use highp for fragments 2024-02-15 17:32:34 +00:00
Jacob Birkett
a8dae8f5e1 socket2: monitoraddedv2 IPC event for monitor description and id (#4646)
* add monitor szShortDescription without DRM node name

* change hyprctl to use szShortDescription

* add monitoraddedv2 event

* add monitor ID as first param of monitoraddedv2
2024-02-15 14:22:20 +00:00
Vaxry
a42b984f51 screencopy: fix ~dtor being in monitorRenderResources map 2024-02-15 02:01:40 +00:00
Vaxry
e5ac970d6e input: fix follow_focus 2024-02-15 01:51:01 +00:00
Vaxry
770956b092 input: don't schedule frame on cursor move on hw cursors
spams unnecessary frames. Maybe we should ignore empty damage frame requests too?

ref #3747 #3490
2024-02-15 01:26:48 +00:00
Vaxry
3cca36e773 input: avoid rampant refocuses on popups 2024-02-15 01:24:40 +00:00
Vaxry
ef490965a2 screencopy: attempt binding framebuffer before gathering format 2024-02-15 00:59:06 +00:00
Vaxry
b7ab15dc80 input: log cursor image requests 2024-02-15 00:59:04 +00:00
Vaxry
9c3f3b0018 renderer: don't calculate mirror damage without mirrors present 2024-02-14 22:33:50 +00:00
Vaxry
8d68d6bfa5 windowrules: nuke no*request 2024-02-14 22:27:53 +00:00
Vaxry
60834a4687 config: remove usages of nomaximizerequest from default cfg 2024-02-14 22:26:45 +00:00
Vaxry
7f52db806c windowrules: add suppressevent
deprecates nofullscreenrequest nomaximizerequest
2024-02-14 22:19:49 +00:00
Vaxry
305b1419c8 renderer: accept custom state requests for fake outputs 2024-02-14 22:05:41 +00:00
Niklas Haas
d5950f7719 dwindle: add swapsplit dispatcher (#4702)
This is distinct from `swapwindow` in that it allows swapping the entire
tree node with its neighbour.

Fixes: https://github.com/hyprwm/Hyprland/issues/4701
2024-02-14 17:58:28 +00:00
vaxerski
0608791480 dwindle: round wbox before setting 2024-02-14 11:44:47 +00:00
vaxerski
2a002f31e4 renderer: don't set solitary on present notifications
fixes #4647
2024-02-14 11:09:18 +00:00
Epilepsy Gatherings
2a3429d4cf internal: add forcenofocus prop (#4672)
* add forcenofocus

* change nofocus to overridable var
2024-02-13 18:07:19 +00:00
Vaxry
95abf1220f keybinds: fix swapactiveworkspaces not moving focus
fixes #4626
2024-02-13 17:53:50 +00:00
Vaxry
b500e5699b renderer: update cursor also when hostpot only changes
fixes #4691
2024-02-13 17:39:51 +00:00
Filipe Paniguel
61378380ee config: fix tiny typo in defaultConfig.hpp (#4693) 2024-02-13 17:30:17 +00:00
Vaxry
890307532c input: avoid reassigns of unchanged surfaces in processMouseRequest 2024-02-12 20:02:00 +00:00
GrizzlT
f33d73b9cf nix: overlay polish for prev parameter (#4558) 2024-02-12 19:11:08 +02:00
ComycSans
927da86e3e hyprctl: fix dispatchBatch() treating empty curitem as last request (#4681) 2024-02-12 15:16:00 +00:00
Alessio Molinari
cca3c64301 hyprctl: remove hardcoded hyprctl commands. (#4671)
* fix: remove hardcoded hyprctl commands.

This allows plugin to properly register hyprctl commands.

* fix: restore commands with min args
2024-02-12 10:34:21 +00:00
fufexan
6e5c78bf63 [gha] Nix: update inputs 2024-02-12 00:03:37 +00:00
Vaxry
e4bb5fa4af input: focus monitor on mouse down
fixes #4649
2024-02-10 17:39:53 +00:00
Vaxry
cb258c82f4 assets: update tetrahedra by honkadaloonga 2024-02-10 17:23:27 +00:00
Vaxry
658f718fa3 input: partially revert #4514
issues with refocus in #4649
2024-02-10 17:05:38 +00:00
Sefa Eyeoglu
334a0f03ee keybinds: Fix focus not moving along when moving workspace (#4660)
---------

Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
2024-02-09 23:47:00 +00:00
Ben Landon
289d4241be groupbar: scale groupbar text according to monitor scale (#4640) 2024-02-08 22:29:10 +00:00
Vaxry
a6ccd36147 screencopy: move monitor verif check to the proper place
oops
2024-02-07 23:47:14 +00:00
thejch
3d9ca6381d crashreporter: fix logging of function data (#4632) 2024-02-07 09:50:23 +00:00
Vaxry
f085ed4454 screencopy/toplevelexport: sanitize pointers in ::copyFrame
oopsie~~ >///<
2024-02-07 00:18:47 +00:00
Vaxry
ded174d6e5 misc: remove unused var 2024-02-05 23:39:19 +00:00
Vaxry
181f651de2 vector: avoid min0 clamps without a max being invalid 2024-02-05 22:37:34 +00:00
Epilepsy Gatherings
8a6e428d32 keybinds: focusWorkspaceOnCurrentMonitor: use focused monitor instead (#4625) 2024-02-05 22:36:22 +00:00
Vaxry
1fd82e37a7 xwaylandmgr: proper clamping for setWindowSize
closes #4622 fixes #4621
2024-02-05 20:56:20 +00:00
Vaxry
f9202f791e xwaylandmgr: clamp size in setWindowSize
fixes #4586
2024-02-05 14:08:08 +00:00
Vaxry
84ab8d11e8 props: bump ver to 0.35.0 2024-02-05 01:59:02 +00:00
Vaxry
60bda7ee3d pluginapi: allow registering hyprctl commands
closes #4616
2024-02-05 01:57:29 +00:00
Vaxry
939696f97e hyprctl: move to a class and unify commands 2024-02-05 01:56:49 +00:00
MightyPlaza
cbadf3e3f3 input: focus window on mouse down on decoration (#4514)
Also unifies vectorToWindow funcs
2024-02-04 15:40:20 +00:00
JManch
1ed4f1cb25 screenshader: rename output uniform to wl_output (#4606)
* screenshader: rename output uniform to monitor

* rename to wl_output
2024-02-04 02:30:00 +00:00
Vaxry
5d4ff60f53 hyprpm: fix invalid pkg-config path env in build
ref #4573
2024-02-03 18:32:59 +00:00
Vaxry
504ebe1b37 box: add missing include 2024-02-03 01:31:52 +00:00
Vaxry
cf1886ca44 renderer: avoid unnecessary gpu resource deletions
fixes #4594
2024-02-02 15:36:13 +00:00
Vaxry
341e04a36c dwindle: avoid sending negative sizes to wlr
fixes #4591
2024-02-02 15:04:04 +00:00
Vaxry
d7514412d8 renderer: reset fb pointers after render pass
fixes #4590
2024-02-02 14:56:04 +00:00
Vaxry
7447be8220 hyprpm: fix crash on add plugin
ref #4563
2024-02-02 01:51:14 +00:00
Vaxry
4644de2269 keybinds: fix ignoremods with release 2024-02-02 01:09:57 +00:00
Vaxry
3656045ad8 hyprpm: install headers locally (#4585)
* hyprpm: install headers locally

* oopsie
2024-02-01 19:38:43 +00:00
Abílio Costa
15316aaa31 subsurfaceTree: Fix nullptr crash when disconnecting a monitor (#4577)
I was able to reproduce this frequently by having a kitty terminal on an
monitor running the following command and then unplugging that monitor:

`while true; do echo "" && sleep 0.02; done`
2024-02-01 03:09:31 +00:00
Vaxry
cfd68af5b6 tearing-control: handle unmapped surfaces for hints
fixes #4570
2024-02-01 00:55:29 +00:00
Roger Roger
4f804d5f96 Makefile: remove hyprland symlink on uninstall 2024-01-31 19:34:16 +02:00
Mihai Fufezan
e6f7724ab0 subprojects: remove wlroots.wrap 2024-01-31 14:04:30 +02:00
Mihai Fufezan
e65f52bf2d Makefile: pass PREFIX to CMake 2024-01-30 22:22:06 +02:00
Vaxry
c51b3fb06f events: ignore sending mouse enter to focused if a constraint is active
fixes #4186
2024-01-30 16:24:41 +00:00
Vaxry
3ff59e7e1d hyprpm: update global state on plugin recompile not header update
ref #4547
2024-01-29 23:37:05 +00:00
Mihai Fufezan
3d0d3b6343 Meson: fix wallpaper installation 2024-01-30 01:28:07 +02:00
Vaxry
2e3f0d5991 renderer: Add new background infrastructure
Adds new backgrounds from the winners of the contest
Rewrites how it works
Allows high color precision PNGs (RGB32F precisely)
Fixes a small bug in renderTextureInternalWithDamage
Nukes misc:force_hypr_chan
2024-01-29 23:11:00 +00:00
Vaxry
91e8c42843 hyprpm: don't update headers if they are up-to-date, only recompile
will not update headers if plugins are compiled for different ones, and instead only compile.

ref #4284
2024-01-29 10:30:31 +00:00
Vaxry
4b4bd90b14 renderer: fixup misaligned fsv1 surfaces with uv
fixes #4548
2024-01-28 23:42:49 +00:00
GrizzlT
7009dc9184 nix: fix overlay composition 2024-01-29 00:27:51 +02:00
Vaxry
b7840c6461 xwayland: remove delta from pos sets in configureX11
ref #4536
2024-01-28 20:13:44 +00:00
Vaxry
5a90911b70 hyprpm: verify headersHashCompiled as well in headersValid()
ref #4547
2024-01-28 20:01:46 +00:00
Epilepsy Gatherings
0e5f14d8d2 xwayland: remove reportedsize set in unmanagedSetGeometry (#4539) 2024-01-28 19:22:02 +00:00
Vaxry
df990c80e2 hyprpm: log verbose return of cmake and meson in update 2024-01-28 03:00:05 +00:00
Vaxry
352574d862 hyprpm: add --force for update
closes #4547
2024-01-28 02:04:35 +00:00
Vaxry
bfcc2adbda monitor: wrap usage of wlr_output_state
for better control and convenience in usage.

fixes #4546
2024-01-28 01:57:13 +00:00
Vaxry
9002657bcc monitor: don't call output_state_finish on buffer-less state clears
ref #4546
2024-01-28 00:41:54 +00:00
Vaxry
3e93fdf779 opengl: use texBox for rendering background texture
fixes #4543
2024-01-28 00:32:54 +00:00
Vaxry
bc7e488a4c monitor: clear output state after usage
fixes massive lag
2024-01-27 19:11:14 +00:00
Mihai Fufezan
8b1069b330 flake.lock: update 2024-01-27 17:31:39 +02:00
vaxerski
61fd75b55e [gha] Nix: update wlroots 2024-01-27 13:59:16 +00:00
Vaxry
7b3d039388 deps: update wlroots
drops requirement for WLR_DRM_NO_ATOMIC provided kernel >= 6.8
2024-01-27 13:58:28 +00:00
rszyma
12d79d6342 dwindle: fix windows being created at incorrect position when cursor is over reserved area (#4520)
* fix: smart_split not working correctly when creating a window with cursor over reserved area

* use getClosestNodeOnWorkspace instead of getFirstNodeOnWorkspace when hovering over reserved area

* optimize `getClosestNodeOnWorkspace`

* remove unused methods
2024-01-26 22:30:36 +00:00
bvr-yr
08e3519747 layout: save float props before setting fs state (#4537)
fixes #4388
2024-01-26 17:24:00 +00:00
Epilepsy Gatherings
5cd7e4587e compositor: don't close special on focus on pinned (#4533) 2024-01-26 12:24:52 +00:00
Vaxry
72987dee88 opengl: rassert false on lost context
we do not have infra to deal with this. It will cause hyprland to freeze rendering, we might as well die.
2024-01-26 02:26:10 +00:00
Vaxry
754eaf5b8b pluginapi: fix hooks with negative rip offsets
fixes #4484
2024-01-24 13:53:18 +00:00
Zach DeCook
df17991b1c input: Allow disabling touchscreen input (#4517)
* enable/disable touch device

* ConfigManager: update documentation of 'enabled'
2024-01-24 00:15:01 +00:00
Vaxry
791e1b96b3 internal: minor header cleanup 2024-01-23 01:32:34 +00:00
vaxerski
02b4a9bded compositor: clarify common errors at launch 2024-01-22 09:46:47 +01:00
Sean McGovern
4d403dac32 build: protocols: require wayland-protocols >= 1.32
The cursor-shape-v1 protocol was not available until this release.
2024-01-20 22:33:12 +02:00
vaxerski
f40e382fc6 crashreporter: skip first possibly cut off line in log tail 2024-01-20 09:16:27 +01:00
vaxerski
b86ed02d8a keybinds: avoid duplicated held keys, only use last, remove all
ref #4471
2024-01-19 19:09:32 +01:00
vaxerski
17339e0ae9 input: track exclusive LSes
ref #4465
2024-01-19 16:45:34 +01:00
vaxerski
5eeec8860e core: improve cleanup logic 2024-01-19 16:20:30 +01:00
Epilepsy Gatherings
9f20a15955 input: remove animate checks on resize limiter (#4480) 2024-01-19 15:45:51 +01:00
vaxerski
c4365f20ed damage: use buffer_damage instead of effective_damage 2024-01-17 16:01:20 +01:00
vaxerski
307dd8f511 input: partially revert #4401
ref #4465
2024-01-17 14:43:38 +01:00
Huy Nguyen
8342bac697 Nix: disable fortify for devshell (#4463)
This disables '_FORTIFY_SOURCE' Werrors trying to compile wlroots.
Long standing issue in https://github.com/NixOS/nixpkgs/issues/60919
afaik.

After this change you should be able to:
```
nix develop
mmeson setup build -Dbuildtype=debug
ninja -C build
```
2024-01-17 14:27:35 +02:00
virchau13
3c964a9fdc keybinds: Add dispatcher for xmonad/qtile-style workspace switching (#4439)
* feat: implement xmonad/qtile-style workspace switching

Implements the focusWorkspaceOnCurrentMonitor dispatcher and function,
which implements XMonad/Qtile-style workspace switching.

When called, focusWorkspaceOnCurrentMonitor will:
1. Send the requested workspace to the current monitor,
2. If the workspace was previously active on a different monitor,
   replace it with the workspace that was previously active on the
   current monitor,
3. Focus the workspace on the current monitor.

* fix: address PR comments
2024-01-15 16:30:46 +01:00
MightyPlaza
f14c5ea5c5 groupbar: separate gradients from title (#4444)
* separate gradients from title logic
modified:   src/config/ConfigManager.cpp
modified:   src/render/decorations/CHyprGroupBarDecoration.cpp

* fix disabled extents
modified:   src/render/decorations/CHyprGroupBarDecoration.cpp

* fix disabled height
modified:   src/render/decorations/CHyprGroupBarDecoration.cpp
2024-01-15 16:17:42 +01:00
fufexan
dcd7a92b01 [gha] Nix: update inputs 2024-01-15 00:03:29 +00:00
Isaac Myhal
b6516bad02 config: Add border gradients to windowrulev2 (#4335)
* Add border gradients to windowrulev2

* windowrule border gradient: Use CVarList to parse

* windowrule border gradient: No {} around short ifs
2024-01-14 18:27:32 +01:00
dranull
13d9a637d6 hyprctl: screen_shader config fixes (#4102)
* Allow "/" in values of requests

* Don't tick on empty value
2024-01-14 18:12:52 +01:00
1over137
4cee94b91c fractional: Set preferred scale on monitor config reload (#4406) 2024-01-14 14:56:35 +01:00
Zach DeCook
c4da4b026d layershell: Fix greedy mouse grab from keyboard_interactive layer (#4401)
* Layer: Don't allow a keyboard-layer to steal focus from other layers

* Input: Don't change keyboard focus on click if focus is locked
2024-01-12 15:43:16 +01:00
scorpion-26
babb9c07b0 swipe: Prevent hiding current workspace when swiping (#4417)
When workspace_swipe_use_r is enabled, swiping from WS 1 to a non-empty WS 2 would
hide WS 1 (Similar effect to issue #4076). This is caused by a faulty
check which doesn't consider, that workspaceIDLeft could be the current
workspace.
This bug is only a problem for r, because m wraps around on WS 1 m-1, whereas r stays on WS 1.
2024-01-11 19:22:40 +01:00
vaxerski
6b92144f15 surface: avoid spam of window surfaces with scale and transform events
fixes #4408
2024-01-11 14:07:28 +01:00
Clyybber
8d31c84483 layout: Round window pos and size on togglefloating (#4407)
Also restore the behaviour introduced in bc4a51dbbb
2024-01-10 18:08:58 +01:00
vaxerski
d484506600 keybinds: fix tracking of sent key states 2024-01-10 18:06:38 +01:00
vaxerski
b240704bee renderer: allow rendering multiple fullscreen windows in third fs pass
something might be fading out, sliding out, etc. We handle it before, why not use it?

fixes #4076
2024-01-09 20:42:07 +01:00
vaxerski
71166ef40b subsurfaceTree: update surface tree protocol feedback on map 2024-01-09 18:14:08 +01:00
vaxerski
252aaaecfa input: add special_fallthrough
fixes #4323
2024-01-09 13:17:55 +01:00
vaxerski
f92a86af53 renderer: ignore box offsets for fullscreen windows 2024-01-08 19:58:15 +01:00
MightyPlaza
2ba2c8aeee groupbar: improve gradient handling (#4390)
modified:   src/render/decorations/CHyprGroupBarDecoration.cpp
2024-01-08 19:38:22 +01:00
Piroro-hs
955009655d cmake: Propagate NO_XWAYLAND to wlroots building setup (#4385) 2024-01-08 19:24:52 +01:00
vaxerski
d7d333d162 opengl: apply box rot to projections 2024-01-07 18:51:08 +01:00
vaxerski
f5b2fd2bc3 opengl: add renderdata.forceIntrospection 2024-01-07 18:37:02 +01:00
vaxerski
44ee9915e3 renderer: overhaul renderModifData 2024-01-07 18:35:44 +01:00
vaxerski
9f2bde925b hyprpm: handle failed compilations gracefully 2024-01-07 18:15:51 +01:00
vaxerski
7904188de9 input: allow focusSurface when locked if surfase is sessionLock 2024-01-07 14:04:32 +01:00
Epilepsy Gatherings
666ee61c13 input: leave special on focus (#4358) 2024-01-07 12:06:33 +01:00
Jan Beich
7e033e48ac make: unbreak with non-GNU ln(1) after 78f9ba9fdd
ln -s -r -f /usr/local/bin/Hyprland /usr/local/bin/hyprland
ln: illegal option -- r
usage: ln [-s [-F] | -L | -P] [-f | -i] [-hnv] source_file [target_file]
       ln [-s [-F] | -L | -P] [-f | -i] [-hnv] source_file ... target_dir
       link source_file target_file
*** Error code 1
2024-01-05 19:22:43 +02:00
Naksu
d8dbdc4a01 main: Fix typo in std::cerr (#4359) 2024-01-05 12:45:49 +01:00
vaxerski
d3acf8da3b CI: don't close stale issues 2024-01-05 12:40:18 +01:00
Mihai Fufezan
aeeeace102 flake.lock: update 2024-01-04 22:52:03 +02:00
thejch
880996b053 master: Add more null checks for rollnext (#4343)
* add more null check for rollnext

* remove pwindow check
2024-01-04 16:17:17 +01:00
rszyma
4d6d662c67 Makefile: force ln command to overwrite symlink (#4347)
When running `make install` twice ln shows an error:
```
ln -s -r /usr/local/bin/Hyprland /usr/local/bin/hyprland
ln: failed to create symbolic link '/usr/local/bin/hyprland': File exists
```
2024-01-04 10:20:17 +01:00
vaxerski
1512b81126 master: guard PNODE in roll*
fixes #4331
2024-01-02 22:18:38 +01:00
flicko
4f26c4e1eb config: variables update their value when set again (#4263)
* variables update their value when set again

* only sort if new variable is found

* clang-format
2024-01-02 16:38:30 +01:00
dranull
3c33d4b9dd keybinds: Refocus only if the silently moved window had the focus (#4328) 2024-01-02 14:50:30 +01:00
vaxerski
bd3ea8dcb5 examples: remove example plugin
closes #4329
2024-01-02 14:25:18 +01:00
vaxerski
813af393f1 layout: update rules before applying fullscreen nodes in layouts 2024-01-02 14:21:36 +01:00
dranull
583b05a8c6 groupbar: Drag single window instead of destroying group (#4327) 2024-01-02 13:37:03 +01:00
Zach DeCook
1607e96704 HookSystem: rename PAGESIZE_VAR from PAGESIZE to avoid conflict (#4321) 2024-01-01 23:05:26 +01:00
q234rty
1a4f23eb2f renderer: Only force nearest neighbor when the sizes are off by one or two (#4325)
Fixes rendering issues in arch's extra/telegram-desktop
2024-01-01 20:20:27 +01:00
bvr-yr
42ab06e7c8 meson: fix wlroots patch (#4324) 2024-01-01 19:58:01 +01:00
vaxerski
46753b1f22 CI: limit stalebot ops per run 2024-01-01 18:37:49 +01:00
Vaxry
d4e68ab602 CI: allow manual stale execution 2024-01-01 18:34:15 +01:00
rszyma
37b76cd1ca keybinds: fix keys getting stuck + minor refactor & optimizations to keybind handling (#4304) 2024-01-01 18:29:51 +01:00
vaxerski
0be36cd02d cmakelists: fix wlroots patch sed 2024-01-01 18:29:10 +01:00
Vaxry
4e0e8d933e CI: add stalebot 2024-01-01 18:26:48 +01:00
vaxerski
c7ba460687 wlroots: update version patches 2024-01-01 18:19:22 +01:00
vaxerski
3a189c265d issue templates: make versions spoiler'd 2024-01-01 18:05:49 +01:00
vaxerski
069880e374 hyprctl: add systeminfo 2024-01-01 17:53:03 +01:00
vaxerski
fa5e812304 [gha] Nix: update wlroots 2024-01-01 15:48:37 +00:00
vaxerski
33444e1e5e deps: update wlroots 2024-01-01 16:47:54 +01:00
vaxerski
03ebbe18ed props: bump ver to 0.34.0 2024-01-01 13:03:15 +01:00
dranull
7c1ac58a4b input: Ignore some input events when focus is on a layer surface (#4306)
* No motion events with focus on LS on workspace change

* Don't check scroll events on decorations with focus on LS
2024-01-01 13:02:16 +01:00
vaxerski
46997a7643 renderer: fix auto scale detection with fractional
ref #4225
2023-12-31 13:54:24 +01:00
vaxerski
b5b025a1ed renderer: use nearest_neighbor for misaligned fractional-scale surfaces
ref #4225
2023-12-31 13:11:26 +01:00
MightyPlaza
94d6b2d2c1 deco: fix missing border on togglefloating (#4305)
modified:   src/managers/KeybindManager.cpp
2023-12-30 16:59:01 +01:00
zakk4223
33fe3a2e7f hyprpm: Make sure we're in git repo before getting new hash (#4303) 2023-12-30 15:19:53 +01:00
MightyPlaza
2ad2e1d5f5 groupbar: add enabling groupbar and setting priority (#4299) 2023-12-30 15:18:53 +01:00
dranull
5f8e4068e5 groupbar: Middle click on groupbar to close tab (#4297)
* Prevent window swapping when the head is removed

* Bring floating windows to top when selected

* Allow clicks on gropubar in fullscreen 1

* Close window on groupbar with middle click
2023-12-30 00:38:12 +01:00
vaxerski
78f9ba9fdd makefile: add symbolic link for lowercase binary name
ref #4272
2023-12-29 10:37:58 +01:00
vaxerski
9242b03317 internal: minor include fixes and missed format 2023-12-29 10:27:09 +01:00
vaxerski
f9c13b614c xdg-shell: fix sending of suspended state
fixes #4287
2023-12-29 00:26:23 +01:00
vaxerski
ddf8e01c1e config: don't emit reloaded event before eventManager is created 2023-12-29 00:17:58 +01:00
vaxerski
f771c10d1a renderer: ignore windowRequestedCursorHide
ref #4197, thanks @dtop129

co-authored-by: dtop129
2023-12-29 00:04:01 +01:00
dranull
8321d6be46 internal: Unify input handling on decorations (#4280)
* Unify input handling on decorations

* Make input methods private

* Optional data
2023-12-28 23:54:41 +01:00
Mihai Fufezan
cedf5f1fca CI/Nix: fix build 2023-12-29 00:07:23 +02:00
vaxerski
9fba887cc9 socket2: emit configreloaded event
fixes #4285
2023-12-28 22:34:12 +01:00
vaxerski
4f3ee4c645 renderer: add decoration:blur:popups_ignorealpha
fixes #4282
2023-12-28 22:29:04 +01:00
MightyPlaza
5f65946c84 hyprctl: add decorations (#4275)
* add hyprctl decorations

modified:   hyprctl/main.cpp
modified:   src/debug/HyprCtl.cpp
modified:   src/render/decorations/CHyprBorderDecoration.cpp
modified:   src/render/decorations/CHyprBorderDecoration.hpp
modified:   src/render/decorations/CHyprDropShadowDecoration.cpp
modified:   src/render/decorations/CHyprDropShadowDecoration.hpp
modified:   src/render/decorations/CHyprGroupBarDecoration.cpp
modified:   src/render/decorations/CHyprGroupBarDecoration.hpp
modified:   src/render/decorations/IHyprWindowDecoration.cpp
modified:   src/render/decorations/IHyprWindowDecoration.hpp

* fixes
modified:   hyprctl/main.cpp
modified:   src/render/decorations/IHyprWindowDecoration.cpp
2023-12-28 16:38:16 +01:00
vaxerski
6a93cee74e pluginapi: manually detect endbr64 opcodes in function hooks
ref #4277
2023-12-28 13:36:09 +01:00
vaxerski
07132741bc renderer: use 120 as the denominator in scale checks 2023-12-27 23:47:01 +01:00
Mihai Fufezan
e5eb11ad04 Nix: wrap with gcc
This ensures the function hook can assemble.
2023-12-27 20:27:55 +02:00
vaxerski
e75dafd8b2 pluginapi: better wording for plugin function hook errors 2023-12-27 19:27:15 +01:00
vaxerski
b7e8110a30 pluginapi: log assembler return 2023-12-27 19:23:06 +01:00
vaxerski
2702814a3f opengl: add toggleable nvidia_anti_flicker
ref #4252
2023-12-27 19:17:07 +01:00
André Silva
f86cdcf8d5 nix: fix wlroots build 2023-12-27 14:29:15 +02:00
André Silva
85d375e8ab flake.lock: update nixpkgs 2023-12-27 14:29:15 +02:00
MightyPlaza
6cd82d948f input: don't steal mouseDown from LS (#4260)
modified:   src/managers/input/InputManager.cpp
2023-12-27 11:44:13 +01:00
MightyPlaza
1ecd173c7a groupbar: remove extra border size from groupbars (#4262)
modified:   src/render/decorations/CHyprGroupBarDecoration.cpp
2023-12-27 11:43:55 +01:00
Vaxry
7474c81958 pluginapi: Trampoline hooks %rip patching improvements (#4256)
---------

Co-authored-by: Jan Beich <jbeich@FreeBSD.org>
2023-12-27 11:43:04 +01:00
Tuur Vanhoutte
191fa587f4 windowrules: add initialTitle and initialClass (#4259) 2023-12-26 23:47:46 +01:00
vaxerski
9fb50252d3 special: move floating windows along with the workspace 2023-12-26 19:44:38 +01:00
André Silva
bfb4d66c81 compositor: spawn environment setup with keybind manager (#3722) 2023-12-26 18:16:59 +01:00
dranull
34b0ce66b3 dwindle: Use window->middle() when cursor is on reserved area (#4253) 2023-12-26 17:24:31 +01:00
André Silva
2c2ff4b61b hyprctl: check only ISDEBUG in version (#3702) 2023-12-26 14:14:12 +01:00
Mihai Fufezan
4f99e805b9 flake.lock: update 2023-12-25 19:27:25 +02:00
vaxerski
e2d04ae503 renderer: add option to blur popups
closes #2134
2023-12-25 18:07:07 +01:00
MightyPlaza
b25b06430b groupbar: add egl context to refreshGroupBarGradients() (#4238)
* add egl context to refreshGroupBarGradients()

modified:   src/render/decorations/CHyprGroupBarDecoration.cpp

* don't unsetEGL
modified:   src/render/decorations/CHyprGroupBarDecoration.cpp
2023-12-24 19:29:04 +01:00
vaxerski
5aab4a96e3 dispatchers: add tiled/floating to cyclenext 2023-12-24 15:08:48 +01:00
vaxerski
ff75f991a5 compositor: don't block focus if there is no keyboard 2023-12-24 13:20:31 +01:00
vaxerski
f013acc6ee renderer: add occlusion for special workspaces 2023-12-23 22:41:42 +01:00
vaxerski
d5811283d2 xdgshell: bump to 6, send suspended states 2023-12-23 22:30:56 +01:00
dranull
5c7e23f86b shadow: Avoid rounded shadows when rounding is 0 (#4230) 2023-12-23 20:40:07 +01:00
vaxerski
b9c1414f25 border: fix missed translate by offset 2023-12-23 16:11:26 +01:00
vaxerski
cc0516a9ae windowrules: minor fixes to onworkspace
fixes #4227
2023-12-23 15:49:42 +01:00
vaxerski
6c8e0f9863 config: add debug:disable_scale_checks
ref #4225
2023-12-23 00:21:02 +01:00
vaxerski
6b6f3396cf renderer: deny invalid scales and suggest a replacement
ref #4225 #3511
2023-12-23 00:09:55 +01:00
vaxerski
79ef29d6e0 renderer: apply scale to wlr after checks
ref #4225
2023-12-22 23:00:36 +01:00
vaxerski
c416880cf9 shadow: correctly scale boxes 2023-12-22 19:54:31 +01:00
vaxerski
37d2840246 renderer: reject non-clean scales, find nearest clean 2023-12-22 19:54:31 +01:00
thejch
7cec618fe4 master: add dispatchers rollnext and rollprev (#4209) 2023-12-22 12:37:38 +01:00
vaxerski
bd952dcef2 systemd: add HYPRLAND_NO_SD_NOTIFY
fixes #4217
2023-12-21 22:27:12 +01:00
vaxerski
bc51a91043 crashreporter: don't explicitly set 777 on crash report directory
fixes #4218
2023-12-21 22:18:07 +01:00
vaxerski
698f3b6576 hyprpm: trim paths in PATH
fixes #4210
2023-12-21 22:01:55 +01:00
Ahmed Yasser
79f3888b4b signal: fix invalid pointer access (#4207) 2023-12-20 23:54:52 +01:00
vaxerski
4eb42fab7b windowrules: add onworkspace
cool
2023-12-20 23:52:18 +01:00
vaxerski
48ecb13b14 renderer: improve cursor hiding infra
ref #4197
2023-12-20 21:40:44 +01:00
vaxerski
a197fe3c11 renderer: don't set surfaces on cursor timeout 2023-12-20 17:59:11 +01:00
Junxuan Liao
53c78ab906 idle: notify idle on tablet inputs (#4201)
Fixes #4028.
2023-12-20 17:53:54 +01:00
vaxerski
b4f4bd38e8 configmanager: set a limit to config variable substitutions
fixes #4198
2023-12-20 13:07:12 +01:00
vaxerski
d1b8a63a8e input: allow setting cursor even if it's hidden
ref #4197
2023-12-20 13:00:35 +01:00
Husam Harazi
3771c49a94 filesystem: Set the sticky bit on /tmp/hypr (#4199)
To prevent unprivileged users from deleting other users' files.
2023-12-20 11:56:15 +00:00
vaxerski
d9b74ff96b renderer: staticize local functions 2023-12-19 11:55:56 +00:00
Vaxry
ef445093f9 internal: convert uname fields to strings before logging
fixes #4188, thanks @jbeich
2023-12-18 23:33:10 +00:00
Vaxry
11fd37418c renderer: fix null cursor surface sets being ignored
oopsie from #4184
2023-12-18 22:06:50 +00:00
dusanx
0c74df4f9e renderer: cursor hiding logic improvements (#4184)
Co-authored-by: Dusan Popovic <dpx@binaryapparatus.com>
2023-12-18 16:06:06 +00:00
Vaxry
460a326c90 Revert "xdgshell: set predicted tiled windows to monitor res size pre-map"
This reverts commit 763d5fa05f.

Some issues and fixes #4185
2023-12-18 14:45:20 +00:00
Vaxry
403fd7d9f6 xwayland: move commit handler connect to associate
fixes #4179
2023-12-18 00:15:30 +00:00
Vaxry
763d5fa05f xdgshell: set predicted tiled windows to monitor res size pre-map
Should improve #4022 although not exactly fix. Fixing would require more witchcraft
2023-12-17 20:09:34 +00:00
Vaxry
9fd928e114 internal: nuke CWindow::m_bMappedX11
it's useless. m_bIsMapped is the same.
2023-12-17 20:00:18 +00:00
Vaxry
bf7374011b xwaylandmgr: allow resizes without a monitor 2023-12-17 19:58:11 +00:00
Vaxry
8c9f38e405 events: improve wl_surface::commit event tracking 2023-12-17 19:58:01 +00:00
Vaxry
c0d9dcc586 xwayland: set reported and pending size/pos on geometry sets 2023-12-17 14:53:59 +00:00
MightyPlaza
2a777cb71b hyprctl: add commit date to "hyprctl version" (#4171)
* add commit date to "hyprctl version"
modified:   scripts/generateVersion.sh
modified:   src/debug/HyprCtl.cpp
modified:   src/version.h.in

* Nix: add date to hyprctl

---------

Co-authored-by: Mihai Fufezan <fufexan@protonmail.com>
2023-12-17 14:29:58 +00:00
dranull
9ca0c7d814 input: Activate resize_on_border only when key is pressed (#4170) 2023-12-16 20:47:58 +00:00
Vaxry
b1b8d732e6 toplevelexport: fix missed pmonitor set for opengl
ref #4165
2023-12-15 21:20:13 +00:00
Vaxry
4e5d9b90c0 toplevelexport: fix missing GL_READ_FRAMEBUFFER set in shm copy
ref #4165
2023-12-15 21:04:34 +00:00
Vaxry
e1ed8e11ca internal: import qt env to dbus 2023-12-15 20:59:13 +00:00
Vaxry
79d8d14fe0 config: add qt env to default config 2023-12-15 18:27:04 +00:00
Vaxry
395ab3ba37 xdg: use better min/max size checks for floating resizes 2023-12-15 15:38:20 +00:00
dranull
36fa33f7ca input: Prevent crash with invalid keyboard layout (#4157) 2023-12-15 00:39:03 +00:00
Mihai Fufezan
f7cde9c92c Nix: remove duplicate options from modules (#4012) 2023-12-14 20:02:20 +02:00
Vaxry
01e5c59d75 Revert "xwayland: push invisible windows outside layout"
This reverts commit accb3d8d0b.

Bad idea
2023-12-13 17:25:19 +00:00
Junxuan Liao
b2e5a80e2f hyprpm: Link against tomlplusplus when using cmake (#4145)
This reduces the compilation time and is consistent with the meson version.
2023-12-13 14:15:03 +00:00
Mihai Fufezan
55cb565e6d Nix: expose legacyRenderer package 2023-12-13 13:31:36 +02:00
Vaxry
4190b96718 hyprpm: add duplicate header error and log more verbose in install fails 2023-12-13 02:33:07 +00:00
Mihai Fufezan
d9bc210285 Nix: remove libdrm override
Nixpkgs update has the new version.
2023-12-12 23:34:22 +02:00
dranull
4de986072c layout: Focus a floating window after closing the last tiled (#4137) 2023-12-12 16:44:31 +00:00
dranull
934112af5b config: Use canonical instead of read_symlink (#4136) 2023-12-12 16:43:38 +00:00
Vaxry
ba2af6f86d focus: prefer sendMotionEventsToFocused for ensuring cursor image 2023-12-12 14:58:43 +00:00
Vaxry
1950c3fc9c input: unset resize cursor on empty focus
fixes #4133
2023-12-12 14:55:48 +00:00
Vaxry
8f38487884 xwayland: don't change workspace on configure for invisible windows
fixes #3578
2023-12-12 01:15:17 +00:00
Vaxry
accb3d8d0b xwayland: push invisible windows outside layout
fixes some xwl focus issues with special especially.
2023-12-12 01:14:36 +00:00
Vaxry
ea7569d7e0 config: improve layoutopt handling for workspacerules 2023-12-11 22:58:51 +00:00
François Conzelmann
e53134ca90 internal: fix interactions with fakefullscreen (#4113)
- In a maximized window, unstuck fakefullscreen from on state
- In a fakefullscreen window, going in and out of fullscreen state
  keep the fakefullscreen state rendered
2023-12-11 16:51:10 +00:00
Vaxry
8191e635a3 deco-positioner: include sticky in sent geometry 2023-12-11 16:46:20 +00:00
Vaxry
0fdf909b19 renderer: don't render decorations on renderdata.decorate false
fixes #4117
2023-12-11 16:32:11 +00:00
Jan Beich
50648e6bae hyprpm: cast std::clamp args to be of the same type (#4116)
hyprpm/src/progress/CProgressBar.cpp:50:27: error: no matching function for call to 'clamp'
    const auto BARWIDTH = std::clamp(w.ws_col - m_szCurrentMessage.length() - 2, 0UL, 50UL);
                          ^~~~~~~~~~
/usr/include/c++/v1/__algorithm/clamp.h:38:1: note: candidate template ignored: deduced conflicting types for parameter '_Tp' ('size_type' (aka 'unsigned int') vs. 'unsigned long')
clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi)
^
/usr/include/c++/v1/__algorithm/clamp.h:27:1: note: candidate function template not viable: requires 4 arguments, but 3 were provided
clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi, _Compare __comp)
^
2023-12-11 16:29:04 +00:00
nmzik
53ce7992be renderer: double lookup fix, input: double conversion fix (#4124) 2023-12-11 16:28:22 +00:00
Vaxry
167f2ed3b2 border: fix failed assert on small windows
fixes #4115
2023-12-10 19:32:03 +00:00
Vaxry
d02ba422da hyprpm: guard empty command
fixes #4114
2023-12-10 19:30:26 +00:00
François Conzelmann
359baa0214 ci: use composite action to minimize code duplication (#4112) 2023-12-10 19:26:25 +00:00
nmzik
efdf07e295 renderer: Allocate background texture only if required (#4111) 2023-12-10 16:53:08 +00:00
Mihai Fufezan
0c10b8ab2d input: Add scroll_points option for device (#4101) 2023-12-10 16:30:08 +00:00
Vaxry
9f5b9053c6 internal: Remake borders as window decorations (#4104) 2023-12-10 16:28:12 +00:00
Vaxry
b3dc58e104 hyprpm: clone plugins recursively 2023-12-10 16:18:30 +00:00
Vaxry
af6aae4e12 renderer: don't use clipBox for pinned window occlusion during animations
ref #4094
2023-12-09 18:41:32 +00:00
Vaxry
0ebbf371ff renderer: improve fullscreen workspace client rendering
fixes #4076
2023-12-09 18:38:32 +00:00
dranull
89d8f665b5 config: Avoid regenerating config if --config is used (#4103) 2023-12-09 18:27:30 +00:00
Vaxry
9132660768 functionHooks: fix incorrect protlen calcs 2023-12-09 16:16:46 +00:00
Vaxry
dd0714c22a input: add relative_input for tablets
closes #2639
2023-12-09 04:07:28 +00:00
Vaxry
11d1c50420 windowrules: add focus param 2023-12-08 16:02:16 +00:00
Vaxry
288f1863f0 hyprctl: allow instances without HIS 2023-12-08 15:40:01 +00:00
thejch
6fb1b89b98 makefile: add rm hyprpm for uninstall (#4086) 2023-12-07 22:36:18 +00:00
dranull
004bf94a23 keybinds: Keep focus on special when switching workspaces (#4084) 2023-12-07 22:12:08 +00:00
Vaxry
aa020a2a1a toplevel-export: commence render pass before reading
fixes #4070
2023-12-07 17:58:13 +00:00
Vaxry
d9175a0181 hyprpm: fix with system headers
fixes #4082
2023-12-07 17:22:02 +00:00
Vaxry
a794eecd6a README: add note about hyprpm + clang-format 2023-12-07 10:46:12 +00:00
Vaxry
d360550546 hyprpm: Add hyprpm, a Hyprland Plugin Manager (#4072) 2023-12-07 10:41:09 +00:00
ddmetz
62a8d0be5c keybinds: check for null last monitor in changeworkspace (#4077) 2023-12-07 00:09:25 +00:00
François Conzelmann
4a42344e97 style/ci: apply clang-format and verify it in ci (#4039)
* style: apply clang-format

* ci: add new clang-format job to CI
2023-12-06 22:54:56 +00:00
Vaxry
5489f9f07a renderer: use xray for background blur on small() surfaces
ref #4050
2023-12-06 20:17:40 +00:00
Vaxry
d74607e414 props: bump ver to 0.33.1 2023-12-06 16:47:26 +00:00
Vaxry
c4bd91ec8a makefile: only require version.h before installheaders 2023-12-06 15:31:23 +00:00
Vaxry
03c6f4506a internal: various improvements to avoid crashes on exit 2023-12-06 14:46:29 +00:00
swwind
13b4c6de86 input: don't send mouse events on touch (#4071) 2023-12-06 14:30:40 +00:00
Tungsten842
8bd86cf37e hyprctl: order commands alphabetically (#4061) 2023-12-05 23:39:57 +00:00
dranull
cfd94c5b30 input: Stop propagating axis events after valid binds (#4059) 2023-12-05 21:16:26 +00:00
Vaxry
ab66fa430e screencopy: fix glReadPixels offset
fixes #4042
2023-12-05 20:04:53 +00:00
Vaxry
37d7a8c64d framebuffer: ignore addStencil on legacyRenderer
ref #4044
2023-12-05 15:41:17 +00:00
Vaxry
da863459c4 screencopy: fix legacyrenderer builds
fixes #4044
2023-12-05 14:59:12 +00:00
Vaxry
83248b6936 toplevelexport: fix getPreferredReadFormat param in captureToplevel
fixes #4043
2023-12-05 14:43:54 +00:00
Vaxry
3bb9c7c5cf props: bump ver to 0.33.0 2023-12-05 00:52:16 +00:00
Vaxry
2d04cb1cc6 input: make fallback layout us 2023-12-05 00:48:39 +00:00
Vaxry
c6804ccaab opengl: fixup blur dirty repaint conditions with solitary
fixes #4025
2023-12-05 00:43:09 +00:00
Glizda
aa46aaed04 config: Add variables to default config (#4032)
* update default config

* Fix inconsistency in variable naming

* continuation of last commit

* edited example/hyprland.conf for parity

* fix  issue

* deleted unwanted newline
2023-12-04 18:47:58 +00:00
Vaxry
68783d904d screencopy: use buffer format for glReadPixels
fixes #4029
2023-12-04 03:52:54 +00:00
Vaxry
5d100bdcbb opengl: clear layer fade fbs in ~dtor 2023-12-04 02:08:34 +00:00
Vaxry
45d3fbb8d8 opengl: free window framebuffers in ~dtor
ref #4036
2023-12-04 01:44:16 +00:00
dranull
9a9528d093 config: Minor --config improvements, fixes (#4034)
* Follow symlink, only file, absolute path for -c

* Create config file only for default paths

* Skip non-file source= glob results

* Check for absolute path on XDG_CONFIG_HOME

As per spec, all non-absolute paths should be ignored.
https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
2023-12-04 01:35:24 +00:00
Vaxry
e496b0f250 screencopy: fix detecting gl shm formats
ref #4029
2023-12-03 22:04:07 +00:00
Vaxry
dc2082b00a screencopy: fix transformed on shm 2023-12-03 19:06:51 +00:00
dranull
59cb0e20de input: Handle fullscreen windows in vectorToWindowIdeal (#4021) 2023-12-03 12:53:12 +00:00
Vaxry
80b9b21f9f opengl: fix nvidia read formats
fixes #4023
2023-12-02 14:51:45 +00:00
thejch
758cf90ea1 workspacerules: Add workspace rule for master layout orientation (#3964)
* add workspace rule for master layout orientation

* change rule format

* edit rule name

* use map for layoutopts

* use std::any instead of string
2023-12-02 14:42:49 +00:00
Vaxry
6e8b9ef7d8 opengl: fix swapped rgb drm formats 2023-12-01 17:23:50 +00:00
Vaxry
9c09f2a847 screencopy: fix shm exports with 10-bit
fixes #4019
2023-12-01 17:20:56 +00:00
Wren Baxter
8440a30231 input: fix overzealous mouse capture on resize_on_border (#4010)
fixes #2456
2023-12-01 01:12:08 +00:00
Vaxry
ab40f240c3 screencopy: use drmFormat instead of wlr funcs
ref #4014
2023-12-01 00:23:48 +00:00
vaxerski
b394c1695c [gha] Nix: update wlroots 2023-11-30 18:53:34 +00:00
Vaxry
0a4c4da5f0 deps: update wlroots 2023-11-30 18:52:49 +00:00
Vaxry
b2f3623131 events: add keyPress and mouseAxis
fixes #4011 fixes #4008
2023-11-30 18:45:12 +00:00
François Conzelmann
5513eed64d managers: fix debug log using printf format (#4007)
Some debug messages where using printf format style to print variable
content instead of std::format format.
2023-11-30 15:20:08 +00:00
André Silva
29970228c5 nix: override libdrm to use newer version (#4003) 2023-11-30 11:40:14 +00:00
vaxerski
12ec549a18 screencopy: fix shm sharing if introspection required 2023-11-30 11:07:17 +00:00
Vaxry
9f2027be4b opengl: don't make a mirror buffer on fakeFrame 2023-11-30 10:15:02 +00:00
Vaxry
b9937484f4 screencopy: fix broken shm copying
fixes #4001
2023-11-30 10:14:35 +00:00
Vaxry
776f944619 opengl: fix missed makeEGLCurrent
fixes #3998
2023-11-30 02:19:27 +00:00
François Conzelmann
1fc1e4e9cb monitor: remove comma from monitor description (#3996)
this allows for monitor specific rules to work on monitor with comma on
their description

fixes #2457
2023-11-30 01:48:10 +00:00
vaxerski
e1258707ad [gha] Nix: update wlroots 2023-11-30 01:19:51 +00:00
Vaxry
d2c3b23ace deps: update wlroots 2023-11-30 01:18:55 +00:00
Vaxry
b80c72c7dd groupbar: fix crash in renderGradientTo
fixes #3985
2023-11-29 13:36:37 +00:00
Vaxry
3caaa483d4 configmgr: fix parsing of touchdevice groups
fixes #3992
2023-11-29 03:39:45 +00:00
Vaxry
e2f18f8c7f groupbar: more safety around gradient textures 2023-11-28 19:03:02 +00:00
Vaxry
99ca26d4eb hooksystem: fix missed log include 2023-11-26 18:33:53 +00:00
Vaxry
e416ab740d config: log info about logs before loading vars 2023-11-26 18:02:33 +00:00
MightyPlaza
7a0a5666d5 groupbar: allow reload and fix locked groupbar gradient (#3546)
modified:   src/config/ConfigManager.cpp
modified:   src/render/decorations/CHyprGroupBarDecoration.cpp
modified:   src/render/decorations/CHyprGroupBarDecoration.hpp
2023-11-26 17:59:49 +00:00
Vaxry
1778fb77e2 functionhooks: throw an exception on unsupported %rip usage
ref #2479, now will actually tell you what's wrong instead of crashing
2023-11-26 17:53:51 +00:00
Vaxry
adeb20ea11 opengl: tiled special require introspection 2023-11-26 16:42:04 +00:00
Vaxry
68e57b7ee3 renderer: proper full occlusion checks for back layer 2023-11-26 15:24:24 +00:00
Vaxry
408d96668d renderer: use occlusion checks for buffer clear 2023-11-26 15:06:42 +00:00
Vaxry
75e5799310 layer-shell: simulate mouse movement on unmap 2023-11-26 14:54:34 +00:00
Vaxry
9e2b939024 surface: avoid infinite pointer image resets
fixes #3729, should also #3968
2023-11-26 14:53:22 +00:00
Vaxry
cd96ceecc5 build: remove nv patches (#3957) 2023-11-26 02:58:57 +00:00
Vaxry
ad3f688648 opengl: check for introspection on special_blur 2023-11-25 19:44:34 +00:00
vaxerski
98c7ba4782 [gha] Nix: update wlroots 2023-11-25 19:25:44 +00:00
Vaxry
a5f64b48ca deps: downgrade wlroots to fix crashes 2023-11-25 19:24:59 +00:00
Vaxry
b281d8647a screencopy: use new isNvidia() for format 2023-11-25 17:56:38 +00:00
Vaxry
15b282ee0c opengl: fix window introspection check 2023-11-25 17:46:50 +00:00
Vaxry
6f733292bf renderer: nvidia checks and use glFinish on nvidia
fixes #3952 #3946
2023-11-25 17:45:08 +00:00
Vaxry
3fe6162af1 opengl: fix xray modes in introspection checks for ls
fixes #3953
2023-11-25 14:52:52 +00:00
Jibin George
2ce4b94a22 input: Fix custom acceleration profile config (#3948) 2023-11-25 14:39:21 +00:00
coldified
de95e956a0 meson: Update wlroots-meson-build.patch (#3950) 2023-11-25 14:32:01 +00:00
Junxuan Liao
929c44e361 input: pass mouse input to IME popups (#3922) 2023-11-25 14:27:57 +00:00
Vaxry
512a59731b config: default special_scale_factor to 1 2023-11-25 01:45:04 +00:00
Vaxry
a6eba91935 opengl: require introspection on mirroring
fixes #3939
2023-11-25 00:48:02 +00:00
Xavier
745b998587 renderer: Adding an option to disable first launch animation (#3933) 2023-11-24 21:45:59 +00:00
Vaxry
1a2a2da6aa renderer: fixup cursor scaling
fixes #3935
2023-11-24 21:30:28 +00:00
Vaxry
822775aa8c renderer: Fixup double rendering cases with special (#3928)
* fixup

* better fullscreen
2023-11-24 21:18:50 +00:00
Vaxry
d79cf0afe2 renderer: fix software cursors on nvidia
fixes #3926
2023-11-24 13:47:36 +00:00
Vaxry
334d0ae31b monitor: fix transform matrix calculations for transformed
fixes #3929
2023-11-24 13:45:10 +00:00
Vaxry
be3d635265 makefile: update wlroots sover 2023-11-24 13:08:58 +00:00
André Silva
f9ba5a0551 flake.lock: update nixpkgs and xdph 2023-11-24 15:06:35 +02:00
thejch
258c83f3bb exec: remove redundant environment variables from spawn (#3923) 2023-11-24 12:42:20 +00:00
vaxerski
aedcade68d opengl: better checking for required introspection
performance woo
2023-11-24 12:37:10 +00:00
vaxerski
802ab58f8a renderer: fix inverseOpaque calcs in renderWithBlur 2023-11-24 12:32:35 +00:00
Vaxry
af5d06593f cmakelists: fix old wlroots sover 2023-11-24 10:59:02 +00:00
Vaxry
2ebfd0c745 renderer: Move to a full Hyprland GL rendering pipeline (#3920)
Also updates wlroots
2023-11-24 10:54:21 +00:00
vaxerski
e40e486f61 renderer: better checks for special rendering in renderWorkspaceWindows
ref #3916 #3888
2023-11-23 11:31:52 +00:00
Vaxry
e55c5a916a renderer: make sure lastWindow has correct ws in renderWorkspaceWindows
fixes #3916 fixes #3888
2023-11-22 23:43:46 +00:00
Vaxry
45ebe0df8f config: fix red warn in default config
fixes #3917
2023-11-22 23:38:14 +00:00
Vaxry
812a3f6d78 renderer: fix double render of tiled on workspace switch
fixes #3889
2023-11-22 20:05:50 +00:00
Vaxry
44accacff9 config: add nomaximizerequest all to default cfg 2023-11-22 19:50:37 +00:00
Ngô Huy
d417370bb7 makefile: Add CXXFLAGS to hyprlctl's Makefile (#3913) 2023-11-22 11:02:36 +00:00
zakk4223
4729265284 hyprctl: Add 'layouts' command (#3895)
* Add hyprctl 'layouts' command

formatting

* Add getAllLayoutNames(), move m_vLayouts back to private

Formatting

* clang-format
2023-11-21 18:43:38 +00:00
thejch
572fd554b8 renderer: Fix floating clipbox (#3907)
* fix floating decoration clipbox scale

* use vecTransformedSize

* use workspace offset
2023-11-21 00:34:34 +00:00
thejch
7d1c8d827a shadow: add workspace offset to floating window shadow (#3906) 2023-11-20 22:34:28 +00:00
thejch
6d26199e1c renderer: fix floating window rendering when scale > 1 (#3901) 2023-11-20 12:13:09 +00:00
end-4
646f4bc638 general: add workspace gaps (#3877)
* anims: workspace gap

* anims: ws gaps: on swipe end

* anims: ws gaps: add missing parentheses

* format

* refractor

* Update Swipe.cpp

* format

* fix swipe to right

* ws gaps: move animations:workspace_gap to general:gaps_workspace

* ws gaps: general:gaps_workspace -> general:gaps_workspaces
2023-11-19 12:33:26 +00:00
MightyPlaza
7e0c90b92c groupbar: fix text pos with verical offset (#3893)
modified:   src/render/decorations/CHyprGroupBarDecoration.cpp
2023-11-19 12:29:26 +00:00
MightyPlaza
add23a9ba2 group: fix dragging into floating groups (#3719)
* allow dragging into floating groups

modified:   src/Compositor.cpp
modified:   src/Compositor.hpp
modified:   src/layout/IHyprLayout.cpp
modified:   src/render/decorations/CHyprGroupBarDecoration.cpp

* floating-only
modified:   src/layout/IHyprLayout.cpp
2023-11-19 12:29:01 +00:00
Dickby
3d89654254 vector: New operator overloads and small fix in Vector2D. (#3891) 2023-11-18 21:37:16 +00:00
Dickby
6ad5f26cfe layout: Don't update pseudoSize after window moved by mouse. (#3873) 2023-11-18 19:59:12 +00:00
Vaxry
89f6457a99 renderer: avoid rendering floating windows twice with special
fixes #3887
2023-11-18 19:53:45 +00:00
Vaxry
8b57a1973e internal: Allow floating windows on special (#3872)
* allow floating on special

* fix mistake

* fix clipbox
2023-11-18 17:00:24 +00:00
Vaxry
483302a2cd env: add HYPRLAND_NO_RT 2023-11-17 23:29:30 +00:00
Vaxry
a903dba858 cmake: include tracy cpp if set 2023-11-17 23:26:54 +00:00
Vaxry
395985f815 pluginmgr: fix double use of dlerror() 2023-11-17 22:24:52 +00:00
Vaxry
51282f964f plugins: make logging on error more verbose
ref #3874
2023-11-17 22:22:31 +00:00
TheAngusMcFire
db8f13291a hyprctl: add monitors all to report all connected monitors (#3730)
---------

Co-authored-by: Christian Rieger <christian.rieger@student.tugraz.at>
2023-11-17 16:01:21 +00:00
André Silva
30ad71ff36 nix: add libGL to build inputs 2023-11-17 17:36:18 +02:00
Vaxry
84bc0a73f6 compositor: drop unused vectorToWindow func 2023-11-17 15:30:04 +00:00
Dickby
1d9bfa60a1 opengl: Don't use wrong shader just because it's GLES (#3867) 2023-11-16 21:03:17 +00:00
Vaxry
a34e192433 renderer: clip floating boxes on slide anim
fixes #3514
2023-11-16 20:20:41 +00:00
Vaxry
4868d4dfd3 shadow: avoid fatal mutation of the windowBox for calcs
fixes #3865
2023-11-16 17:31:52 +00:00
vaxerski
859841f4d1 renderer: don't make snapshots of invisible windows on close 2023-11-16 12:24:07 +00:00
vaxerski
28ef18a921 shadow: avoid using glClear and don't draw behind window if ignore_window
fixes #3860
2023-11-16 11:42:53 +00:00
Dickby
91d6be1f09 groupbar: Fix position of groupbar titles on monitor scales != 1.0 (#3856) 2023-11-15 20:32:44 +00:00
thejch
9e3dccca76 keybinds: Close special workspace after moving windows out of it (#3649)
* use old monitor

* use pMonitor for for special workspace
2023-11-15 12:32:02 +00:00
Vaxry
81598b3dbd README: update showcase 2023-11-14 20:08:00 +00:00
Vaxry
e195e51c1b logging: move to an internal rolling log buffer
disables logging to the logfile by default
2023-11-14 20:06:04 +00:00
Vaxry
e8469f8b1b renderer: drop unnecessary spammy logs 2023-11-14 19:51:47 +00:00
Vaxry
49597688e9 windowrules: make idleinhibit dynamic 2023-11-14 15:46:57 +00:00
Vaxry
5edb4e4a30 decorations: recalc layout and positioner on add/remove 2023-11-13 16:42:58 +00:00
Ching Pei Yang
4d6fa6ed0c pluginapi: add touch event hooks (#3836) 2023-11-13 16:32:12 +00:00
Vaxry
016a7a9c9b hyprctl: use a rolling buffer for reading requests
fixes #3846
2023-11-13 16:30:37 +00:00
Vaxry
2e26542e3b renderer: use viewporter corrected size for uv calcs 2023-11-12 23:57:53 +00:00
Vaxry
68935ba9dc renderer: separate oversize uv calcs in dimensions 2023-11-12 23:27:52 +00:00
Vaxry
ba5bc5871f subsurfaces: damage window on subsurface size change 2023-11-12 23:06:31 +00:00
Vaxry
824ccd957b renderer: pass proper arg to main param of uv calcs
was fucking up some non-fitting subsurfaces
2023-11-12 22:59:19 +00:00
Vaxry
45e86d4fdf groupbar: translate box by workspace offset 2023-11-12 22:40:21 +00:00
Vaxry
0ba2e68704 deco-positioner: don't remove hidden windows' data 2023-11-12 17:02:42 +00:00
Dickby
e974d1fe98 shaders: Some more changes in rgb2hsl. (#3834) 2023-11-12 16:20:23 +00:00
Vaxry
47d46aa56c inputmgr: clean lists in ~dtor
ref #3558
2023-11-12 14:03:46 +00:00
Vaxry
65efde32c9 internal: make getPlusMinusKeywordResult return optional 2023-11-12 13:40:02 +00:00
Vaxry
69e314207d internal: replace INT_MAX with WORKSPACE_INVALID 2023-11-12 13:34:54 +00:00
Alessio Molinari
1bfd4a2bff output-layout: fix wlroots display handling (#3718) 2023-11-12 13:14:05 +00:00
Vaxry
91cbe93cf8 decoration: add NON_SOLID flag for shadow
fixes #3841
2023-11-12 13:01:23 +00:00
Vaxry
9afdd61ade props: bump ver to 0.32.3 2023-11-11 18:14:46 +00:00
Vaxry
f39a6ca17c decoration-positioner: improve stability 2023-11-11 18:07:56 +00:00
Vaxry
eab2799842 props: bump ver to 0.32.2 2023-11-11 17:24:04 +00:00
Dickby
6eb2abcb20 shaders: Small optimization in rgb2hsl. (#3831) 2023-11-11 17:20:18 +00:00
Vaxry
ae46fbafe5 xdg: set state maximized for all tiled windows
forces them to not draw stupid decorations of their own. Wlroots stopped doing it for us. Fixes #3830
2023-11-11 17:13:20 +00:00
Vaxry
52cf122a0a shadow: move workspace offset calcs to draw
fixes #3829
2023-11-11 16:15:23 +00:00
Dickby
844da8db56 shaders: Avoid calculating unused values in hsl2rgb. (#3827) 2023-11-11 15:43:31 +00:00
Vaxry
db82fc5b09 animationmgr: push shadow avs to ended on disabled 2023-11-11 15:23:33 +00:00
Vaxry
8180ca65a5 props: bump ver to 0.32.1 2023-11-11 15:20:21 +00:00
Vaxry
bea828ea45 decoration-positioner: improve extent handling 2023-11-11 15:18:17 +00:00
vaxerski
c5d1faf72d [gha] Nix: update wlroots 2023-11-11 14:53:18 +00:00
Vaxry
cc04b52ce1 deco-positioner: recalc after uncache 2023-11-11 14:52:27 +00:00
Vaxry
9b5e2e71e0 deps: update wlroots 2023-11-11 14:47:25 +00:00
Vaxry
9be6fbf5ea decorations: Decoration Positioner (#3800) 2023-11-11 14:37:17 +00:00
Dickby
7345b1a1ea shaders: Use clamp in doubleCircleSigmoid. (#3824) 2023-11-11 13:15:37 +00:00
Vaxry
e44d6de555 shadow: alpha treatment improvements 2023-11-11 00:52:40 +00:00
Vaxry
427153e86a xwayland: add half of delta to configure request sizes 2023-11-10 23:49:35 +00:00
Greatly Pleased
1e6e9b66a5 hyprctl: Fix build warnings (#3821) 2023-11-10 21:45:20 +00:00
Vaxry
92cb44ddb2 input: don't schedule repaint on cursor move if hardware cursors are in use 2023-11-10 18:49:15 +00:00
Vaxry
b8a615ffb8 xdg-shell: improve ack-configure handling
fixes #3807
2023-11-10 00:13:22 +00:00
Vaxry
8dd02eb5f3 xdg-shell: update reported size on ack_configure 2023-11-09 22:43:52 +00:00
Vaxry
14195835ef opengl: switch to black-and-white for alpha mattes
also fixes shadows on 10b
2023-11-09 22:11:54 +00:00
Vaxry
11432f69b9 opengl: remove unused alpha matte from shadow 2023-11-09 22:11:54 +00:00
Tobias Pisani
da6fa9cbd2 hyprctl: return group list in correct order (#3683) 2023-11-09 16:05:05 +00:00
Vaxry
c619e6976f screencopy: round boxes
fixes #3795
2023-11-08 12:43:07 +00:00
Vaxry
751d2851cc props: bump ver to 0.32.0 2023-11-07 21:06:38 +00:00
Vaxry
a0fcda301d layout: round box in mouseMove
fixes #3792
2023-11-07 20:47:09 +00:00
Vaxry
47654a84c2 main: set isShuttingDown after display dispatch reaches the end
relates to #3558
2023-11-07 14:53:56 +00:00
Visual-Dawg
29e0a7112e renderer: added new customization options to the blur shaders (#3650)
Adds to `decoration:blur:` `vibrancy` and `vibrancy_darkness`
2023-11-06 18:49:03 +00:00
Vaxry
a1b7a5a53d layout: fix various rounding errors
maybe finally will end #3761
2023-11-06 17:00:37 +00:00
Vaxry
ecf98069f6 layout: round window boxes after special scale factor
fixes #3761 again
2023-11-05 19:57:23 +00:00
David Leal
0476e1b498 groups: add option to configure font name (#3751) 2023-11-05 19:25:50 +00:00
Brett Alcox
a122271f09 includes: fix box headers (#3771) 2023-11-05 17:32:27 +00:00
Vaxry
600a128f83 compositor: allow windowfromregex tiled param 2023-11-05 16:22:43 +00:00
Vaxry
55825c301e compositor: allow windowfromregex floating param
fixes #3766
2023-11-05 16:21:47 +00:00
Vaxry
d8b7ded18c compositor: find windows in direction on floating 2023-11-05 16:18:41 +00:00
Vaxry
c4e1a9b13b box: use std::round instead of std::floor in ::round()
fixes #3761, possibly also #3511
2023-11-05 14:47:24 +00:00
Vaxry
9404972732 events: set reported size on floating map
fixes #3767
2023-11-05 14:12:55 +00:00
Vaxry
3b786419d8 subprojects: update tracy 2023-11-05 00:32:22 +00:00
Vaxry
92e535025e region: include box in the header 2023-11-04 23:12:08 +00:00
Vaxry
d3e5796ee1 layout: fix missed setWindowSize in no_gaps_when_only node apply
fixes #3758
2023-11-04 23:00:20 +00:00
Vaxry
56dec1c6a2 renderer: properly set currentFB on snapshot renders 2023-11-04 22:25:09 +00:00
Vaxry
931927de29 dwindle: move to CBox for expressing nodes 2023-11-04 21:45:34 +00:00
Vaxry
74cf2281dd binds: add movefocus_cycles_fullscreen
fixes #3738
2023-11-04 21:03:08 +00:00
Vaxry
2b07d54bc7 shadow: fix missed fullBox.scale 2023-11-04 20:11:22 +00:00
Vaxry
66a3719b86 renderer: allow transform enabling from outside opengl 2023-11-04 19:35:49 +00:00
Vaxry
64a084477e shadows: fix on transformed 2023-11-04 19:32:50 +00:00
Vaxry
7a09d24065 shadow: fix ignore_window false 2023-11-04 17:45:31 +00:00
Vaxry
a3e20d2d5f wlsurface: fix small detection 2023-11-04 17:39:56 +00:00
Vaxry
32b3d2b456 includes: include vector2d for sharedDefs 2023-11-04 17:27:21 +00:00
Vaxry
447c173cad includes: include sharedDefs in includes.hpp 2023-11-04 17:04:10 +00:00
Vaxry
55b4f84fea Internal: Hyprland box implementation (#3755)
* box impl

* remove unused operators

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

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

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

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

* chore: Remove unused include

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

modified:   src/render/decorations/CHyprGroupBarDecoration.cpp

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

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

* Formated using clang-format.

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

* compare workspace IDs instead

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

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

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

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

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

1
.clang-format-ignore Normal file
View File

@@ -0,0 +1 @@
subprojects/**/*

View File

@@ -9,12 +9,23 @@ body:
---
- type: input
- type: textarea
id: ver
attributes:
label: Hyprland Version
description: "Paste here the output of `hyprctl version`."
placeholder: Hyprland, built from branch main at commit...
description: "Paste the output of `hyprctl systeminfo` here."
value: "<details>
<summary>System/Version info</summary>
```sh
<Paste the output of the command here>
```
</details>"
validations:
required: true
@@ -52,5 +63,5 @@ body:
description: |
Anything that can help. Please always ATTACH and not paste them.
Logs can be found in /tmp/hypr
Crash reports are stored in ~/.hyprland or $XDG_CACHE_HOME/hyprland
Crash reports are stored in ~/.cache/hyprland or $XDG_CACHE_HOME/hyprland

90
.github/actions/setup_base/action.yml vendored Normal file
View File

@@ -0,0 +1,90 @@
name: "Setup base"
inputs:
INSTALL_XORG_PKGS:
description: 'Install xorg dependencies'
required: false
default: false
runs:
using: "composite"
steps:
- name: Get required pacman pkgs
shell: bash
run: |
sed -i -e "1i [extra-testing]\nInclude = /etc/pacman.d/mirrorlist" "/etc/pacman.conf"
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
pacman --noconfirm --noprogressbar -Syyu
pacman --noconfirm --noprogressbar -Sy \
base-devel \
cairo \
clang \
cmake \
git \
glm \
glslang \
go \
hyprlang \
jq \
libc++ \
libdisplay-info \
libdrm \
libepoxy \
libfontenc \
libglvnd \
libinput \
libliftoff \
libxcvt \
libxfont2 \
libxkbcommon \
libxkbfile \
lld \
meson \
ninja \
pango \
pixman \
pkgconf \
scdoc \
seatd \
systemd \
tomlplusplus \
wayland \
wayland-protocols \
xcb-util-errors \
xcb-util-renderutil \
xcb-util-wm \
xcb-util \
xcb-util-image \
libzip \
librsvg
- name: Get hyprcursor-git
shell: bash
run: |
git clone https://github.com/hyprwm/hyprcursor --recursive
cd hyprcursor
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -S . -B ./build
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
cmake --install build
- name: Get Xorg pacman pkgs
shell: bash
if: inputs.INSTALL_XORG_PKGS == 'true'
run: |
pacman --noconfirm --noprogressbar -Sy \
xorg-fonts-encodings \
xorg-server-common \
xorg-setxkbmap \
xorg-xkbcomp \
xorg-xwayland
- name: Checkout Hyprland
uses: actions/checkout@v4
with:
submodules: recursive
# Fix an issue with actions/checkout where the checkout repo is not mark as safe
- name: Mark directory as safe for git
shell: bash
run: |
git config --global --add safe.directory /__w/Hyprland/Hyprland

View File

@@ -8,29 +8,20 @@ jobs:
container:
image: archlinux
steps:
- name: Get required pacman pkgs
run: |
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
pacman --noconfirm --noprogressbar -Syyu
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd python libliftoff
- name: Set up user
run: |
useradd -m githubuser
echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
- name: Install libdisplay-info from the AUR
run: |
su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar"
- name: Fix permissions for git
run: |
git config --global --add safe.directory /__w/Hyprland/Hyprland
- name: Checkout Hyprland
uses: actions/checkout@v3
- name: Checkout repository actions
uses: actions/checkout@v4
with:
submodules: recursive
sparse-checkout: .github/actions
- name: Setup base
uses: ./.github/actions/setup_base
with:
INSTALL_XORG_PKGS: true
- name: Build Hyprland
run: |
git submodule sync --recursive && git submodule update --init --force --recursive
make all
- name: Compress and package artifacts
run: |
mkdir x86_64-pc-linux-gnu
@@ -40,11 +31,12 @@ jobs:
cp ./LICENSE hyprland/
cp build/Hyprland hyprland/
cp build/hyprctl/hyprctl hyprland/
cp subprojects/wlroots/build/libwlroots.so.12032 hyprland/
cp build/hyprpm/hyprpm hyprland/
cp build/Hyprland hyprland/
cp -r example/ hyprland/
cp -r assets/ hyprland/
tar -cvf Hyprland.tar.xz hyprland
- name: Release
uses: actions/upload-artifact@v3
with:
@@ -57,28 +49,19 @@ jobs:
container:
image: archlinux
steps:
- name: Download dependencies
run: |
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
pacman --noconfirm --noprogressbar -Syyu
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd cmake jq python libliftoff
- name: Set up user
run: |
useradd -m githubuser
echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
- name: Install libdisplay-info from the AUR
run: |
su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar"
- name: Checkout Hyprland
uses: actions/checkout@v3
- name: Checkout repository actions
uses: actions/checkout@v4
with:
submodules: true
sparse-checkout: .github/actions
- name: Setup base
uses: ./.github/actions/setup_base
- name: Configure
run: |
meson obj-x86_64-pc-linux-gnu \
-Ddefault_library=static
run: meson setup build -Ddefault_library=static
- name: Compile
run: ninja -C obj-x86_64-pc-linux-gnu
run: ninja -C build
noxwayland:
name: "Build Hyprland in pure Wayland (Arch)"
@@ -86,23 +69,36 @@ jobs:
container:
image: archlinux
steps:
- name: Download dependencies
run: |
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
pacman --noconfirm --noprogressbar -Syyu
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd libliftoff
- name: Set up user
run: |
useradd -m githubuser
echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
- name: Install libdisplay-info from the AUR
run: |
su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar"
- name: Checkout Hyprland
uses: actions/checkout@v3
- name: Checkout repository actions
uses: actions/checkout@v4
with:
submodules: true
sparse-checkout: .github/actions
- name: Setup base
uses: ./.github/actions/setup_base
- name: Configure
run: mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DNO_XWAYLAND:STRING=true -H./ -B./build -G Ninja
- name: Compile
run: make release
clang-format:
name: "Code Style (Arch)"
runs-on: ubuntu-latest
container:
image: archlinux
steps:
- name: Checkout repository actions
uses: actions/checkout@v4
with:
sparse-checkout: .github/actions
- name: Setup base
uses: ./.github/actions/setup_base
- name: Configure
run: meson setup build -Ddefault_library=static
- name: clang-format check
run: ninja -C build clang-format-check

View File

@@ -10,7 +10,6 @@ jobs:
matrix:
package:
- hyprland
- hyprland-nvidia
- xdg-desktop-portal-hyprland
runs-on: ubuntu-latest
@@ -20,11 +19,11 @@ jobs:
with:
ref: ${{ github.ref }}
- uses: DeterminateSystems/nix-installer-action@main
- uses: cachix/install-nix-action@v25
- uses: DeterminateSystems/magic-nix-cache-action@main
- uses: cachix/cachix-action@v12
with:
name: hyprland
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- run: nix build -L ${{ matrix.command }}
- run: nix build .#${{ matrix.package }} -L

View File

@@ -24,53 +24,3 @@ jobs:
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: ${{github.workspace}}/flawfinder_results.sarif
codeql:
name: CodeQL
runs-on: ubuntu-latest
container:
image: archlinux
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
- name: Init Hyprland build
run: |
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
pacman --noconfirm --noprogressbar -Syyu
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd python libliftoff
useradd -m githubuser
echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers
su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar"
git config --global --add safe.directory /__w/Hyprland/Hyprland
- name: Checkout Hyprland
uses: actions/checkout@v3
with:
submodules: recursive
- name: Build Hyprland
run: |
git submodule sync --recursive && git submodule update --init --force --recursive
make all
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"

28
.github/workflows/stale.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time.
#
# You can adjust the behavior by modifying this file.
# For more information, see:
# https://github.com/actions/stale
name: Mark stale issues and pull requests
on:
schedule:
- cron: '7 */4 * * *'
workflow_dispatch:
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v5
with:
repo-token: ${{ secrets.STALEBOT_PAT }}
stale-issue-label: 'stale'
stale-pr-label: 'stale'
operations-per-run: 40
days-before-close: -1

2
.gitignore vendored
View File

@@ -31,3 +31,5 @@ gmon.out
PKGBUILD
src/version.h
.direnv

6
.gitmodules vendored
View File

@@ -1,6 +1,3 @@
[submodule "wlroots"]
path = subprojects/wlroots
url = https://gitlab.freedesktop.org/wlroots/wlroots.git
[submodule "subprojects/hyprland-protocols"]
path = subprojects/hyprland-protocols
url = https://github.com/hyprwm/hyprland-protocols
@@ -10,3 +7,6 @@
[submodule "subprojects/tracy"]
path = subprojects/tracy
url = https://github.com/wolfpld/tracy
[submodule "subprojects/wlroots-hyprland"]
path = subprojects/wlroots-hyprland
url = https://github.com/hyprwm/wlroots-hyprland

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.19)
cmake_minimum_required(VERSION 3.27)
include(CheckIncludeFile)
# Get version
@@ -33,27 +33,43 @@ add_subdirectory("subprojects/udis86")
message(STATUS "Setting up wlroots")
include(ExternalProject)
string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER)
if(CMAKE_BUILD_TYPE)
string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER)
if(BUILDTYPE_LOWER STREQUAL "release")
# Pass.
elseif(BUILDTYPE_LOWER STREQUAL "debug")
# Pass.
elseif(BUILDTYPE_LOWER STREQUAL "relwithdebinfo")
set(BUILDTYPE_LOWER "debugoptimized")
elseif(BUILDTYPE_LOWER STREQUAL "minsizerel")
set(BUILDTYPE_LOWER "minsize")
elseif(BUILDTYPE_LOWER STREQUAL "none")
set(BUILDTYPE_LOWER "plain")
else()
set(BUILDTYPE_LOWER "release")
endif()
else()
set(BUILDTYPE_LOWER "release")
endif()
ExternalProject_Add(
wlroots
PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots
SOURCE_DIR ${CMAKE_SOURCE_DIR}/subprojects/wlroots
PATCH_COMMAND sed -E -i -e "s/(soversion = 12)([^032]|$$)/soversion = 12032/g" meson.build
CONFIGURE_COMMAND meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $<IF:$<BOOL:${WITH_ASAN}>,-Db_sanitize=address,-Db_sanitize=none> && meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $<IF:$<BOOL:${WITH_ASAN}>,-Db_sanitize=address,-Db_sanitize=none> --reconfigure
wlroots-hyprland
PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland
SOURCE_DIR ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland
CONFIGURE_COMMAND meson setup --reconfigure build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dxwayland=$<IF:$<BOOL:${NO_XWAYLAND}>,disabled,enabled> -Dexamples=false -Drenderers=gles2 -Dbackends=drm,libinput $<IF:$<BOOL:${WITH_ASAN}>,-Db_sanitize=address,-Db_sanitize=none>
BUILD_COMMAND ninja -C build
BUILD_ALWAYS true
BUILD_IN_SOURCE true
BUILD_BYPRODUCTS ${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.12032
INSTALL_COMMAND echo "wlroots: install not needed"
BUILD_BYPRODUCTS ${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland/build/libwlroots.a
INSTALL_COMMAND echo "wlroots-hyprland: install not needed"
)
find_program(WaylandScanner NAMES wayland-scanner)
find_package(PkgConfig REQUIRED)
pkg_get_variable(WaylandScanner wayland-scanner wayland_scanner)
message(STATUS "Found WaylandScanner at ${WaylandScanner}")
execute_process(
COMMAND pkg-config --variable=pkgdatadir wayland-protocols
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE WAYLAND_PROTOCOLS_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}")
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
@@ -67,28 +83,45 @@ endif()
include_directories(
.
"src/"
"subprojects/wlroots/include/"
"subprojects/wlroots/build/include/"
"subprojects/wlroots-hyprland/include/"
"subprojects/wlroots-hyprland/build/include/"
"subprojects/udis86/"
"protocols/")
set(CMAKE_CXX_STANDARD 23)
add_compile_definitions(WLR_USE_UNSTABLE)
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing -Wno-pointer-arith)
add_link_options(-rdynamic)
set(CMAKE_ENABLE_EXPORTS TRUE)
set(CMAKE_EXECUTABLE_ENABLE_EXPORTS TRUE)
message(STATUS "Checking deps...")
find_package(Threads REQUIRED)
find_package(PkgConfig REQUIRED)
find_package(OpenGL REQUIRED)
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo libdrm xkbcommon libinput pango pangocairo pixman-1) # we do not check for wlroots, as we provide it ourselves
if(LEGACY_RENDERER)
set(GLES_VERSION "GLES2")
else()
set(GLES_VERSION "GLES3")
endif()
find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
pkg_check_modules(deps REQUIRED IMPORTED_TARGET
xkbcommon
wayland-server wayland-client wayland-cursor wayland-protocols
cairo pango pangocairo pixman-1
libdrm libinput hwdata libseat libdisplay-info libliftoff libudev gbm
hyprlang>=0.3.2 hyprcursor
)
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
add_executable(Hyprland ${SRCFILES})
add_dependencies(Hyprland wlroots)
set(TRACY_CPP_FILES "")
if(USE_TRACY)
set(TRACY_CPP_FILES "subprojects/tracy/public/TracyClient.cpp")
message(STATUS "Tracy enabled, TRACY_CPP_FILES: " ${TRACY_CPP_FILES})
endif()
add_executable(Hyprland ${SRCFILES} ${TRACY_CPP_FILES})
add_dependencies(Hyprland wlroots-hyprland)
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "Setting debug flags")
@@ -97,7 +130,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "Enabling ASan")
target_link_libraries(Hyprland asan)
add_compile_options(-fsanitize=address)
target_compile_options(Hyprland PUBLIC -fsanitize=address)
endif()
if(USE_TRACY)
@@ -141,8 +174,12 @@ if(NO_XWAYLAND)
add_compile_definitions(NO_XWAYLAND)
else()
message(STATUS "XWAYLAND Enabled (NO_XWAYLAND not defined) checking deps...")
pkg_check_modules(xcbdep REQUIRED IMPORTED_TARGET xcb)
target_link_libraries(Hyprland PkgConfig::xcbdep)
pkg_check_modules(xdeps REQUIRED IMPORTED_TARGET xcb xwayland xcb-util xcb-render xcb-image xcb-xfixes xcb-icccm xcb-composite xcb-res xcb-ewmh)
pkg_check_modules(xcb_errors IMPORTED_TARGET xcb-errors)
target_link_libraries(Hyprland PkgConfig::xdeps)
if(xcb_errors_FOUND)
target_link_libraries(Hyprland PkgConfig::xcb_errors)
endif()
endif()
if(NO_SYSTEMD)
@@ -164,14 +201,6 @@ else()
endif()
endif()
target_compile_definitions(Hyprland
PRIVATE
"GIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\""
"GIT_BRANCH=\"${GIT_BRANCH}\""
"GIT_COMMIT_MESSAGE=\"${GIT_COMMIT_MESSAGE}\""
"GIT_DIRTY=\"${GIT_DIRTY}\""
"GIT_TAG=\"${GIT_TAG}\"")
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
@@ -205,7 +234,7 @@ function(protocol protoPath protoName external)
endfunction()
target_link_libraries(Hyprland
${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.12032 # wlroots is provided by us
${CMAKE_SOURCE_DIR}/subprojects/wlroots-hyprland/build/libwlroots.a
OpenGL::EGL
OpenGL::GL
Threads::Threads
@@ -229,5 +258,6 @@ protocol("staging/tearing-control/tearing-control-v1.xml" "tearing-control-v1" f
protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v1" false)
protocol("staging/cursor-shape/cursor-shape-v1.xml" "cursor-shape-v1" false)
# hyprctl
# tools
add_subdirectory(hyprctl)
add_subdirectory(hyprpm)

View File

@@ -1,6 +1,6 @@
BSD 3-Clause License
Copyright (c) 2022-2023, vaxerski
Copyright (c) 2022-2024, vaxerski
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -1,29 +1,29 @@
PREFIX = /usr/local
legacyrenderer:
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -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 ./build -G Ninja
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
chmod -R 777 ./build
legacyrendererdebug:
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -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 -G Ninja
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
chmod -R 777 ./build
release:
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
chmod -R 777 ./build
debug:
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -S . -B ./build -G Ninja
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja
cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
chmod -R 777 ./build
clear:
rm -rf build
rm -f ./protocols/*-protocol.h ./protocols/*-protocol.c
rm -rf ./subprojects/wlroots/build
rm -rf ./subprojects/wlroots-hyprland/build
all:
@if [[ "$EUID" = 0 ]]; then echo -en "Avoid running $(MAKE) all as sudo.\n"; fi
@@ -36,48 +36,65 @@ install:
mkdir -p ${PREFIX}/share/wayland-sessions
mkdir -p ${PREFIX}/bin
mkdir -p ${PREFIX}/share/hyprland
mkdir -p ${PREFIX}/share/bash-completion/completions
mkdir -p ${PREFIX}/share/fish/vendor_completions.d
mkdir -p ${PREFIX}/share/zsh/site-functions
cp -f ./build/Hyprland ${PREFIX}/bin
cp -f ./build/hyprctl/hyprctl ${PREFIX}/bin
cp -f ./build/hyprpm/hyprpm ${PREFIX}/bin
cp -f ./hyprctl/hyprctl.bash ${PREFIX}/share/bash-completion/completions/hyprctl
cp -f ./hyprctl/hyprctl.fish ${PREFIX}/share/fish/vendor_completions.d/hyprctl.fish
cp -f ./hyprctl/hyprctl.zsh ${PREFIX}/share/zsh/site-functions/_hyprctl
cp -f ./hyprpm/hyprpm.bash ${PREFIX}/share/bash-completion/completions/hyprpm
cp -f ./hyprpm/hyprpm.fish ${PREFIX}/share/fish/vendor_completions.d/hyprpm.fish
cp -f ./hyprpm/hyprpm.zsh ${PREFIX}/share/zsh/site-functions/_hyprpm
chmod 755 ${PREFIX}/bin/Hyprland
chmod 755 ${PREFIX}/bin/hyprctl
chmod 755 ${PREFIX}/bin/hyprpm
cd ${PREFIX}/bin && ln -sf Hyprland hyprland
if [ ! -f ${PREFIX}/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions; fi
mkdir -p ${PREFIX}/share/hyprland
cp ./assets/wall_* ${PREFIX}/share/hyprland
cp ./assets/wall* ${PREFIX}/share/hyprland
mkdir -p ${PREFIX}/share/xdg-desktop-portal
cp ./assets/hyprland-portals.conf ${PREFIX}/share/xdg-desktop-portal
mkdir -p ${PREFIX}/share/man/man1
install -m644 ./docs/*.1 ${PREFIX}/share/man/man1
mkdir -p ${PREFIX}/lib/
cp ./subprojects/wlroots/build/libwlroots.so.12032 ${PREFIX}/lib/
$(MAKE) installheaders
uninstall:
rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop
rm -f ${PREFIX}/bin/Hyprland
rm -f ${PREFIX}/bin/hyprland
rm -f ${PREFIX}/bin/hyprctl
rm -f ${PREFIX}/lib/libwlroots.so.12032
rm -f ${PREFIX}/bin/hyprpm
rm -rf ${PREFIX}/share/hyprland
rm -f ${PREFIX}/share/man/man1/Hyprland.1
rm -f ${PREFIX}/share/man/man1/hyprctl.1
rm -f ${PREFIX}/share/bash-completion/completions/hyprctl
rm -f ${PREFIX}/share/fish/vendor_completions.d/hyprctl.fish
rm -f ${PREFIX}/share/zsh/site-functions/_hyprctl
rm -f ${PREFIX}/share/bash-completion/completions/hyprpm
rm -f ${PREFIX}/share/fish/vendor_completions.d/hyprpm.fish
rm -f ${PREFIX}/share/zsh/site-functions/_hyprpm
pluginenv:
@echo -en "$(MAKE) pluginenv has been deprecated.\nPlease run $(MAKE) all && sudo $(MAKE) installheaders\n"
@exit 1
installheaders:
@if [ ! -f ./build/Hyprland ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi
@if [ ! -f ./src/version.h ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi
rm -fr ${PREFIX}/include/hyprland
mkdir -p ${PREFIX}/include/hyprland
mkdir -p ${PREFIX}/include/hyprland/protocols
mkdir -p ${PREFIX}/include/hyprland/wlroots
mkdir -p ${PREFIX}/include/hyprland/wlroots-hyprland
mkdir -p ${PREFIX}/share/pkgconfig
find src -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland
cd subprojects/wlroots/include && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlroots && cd ../../..
cd subprojects/wlroots/build/include && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlroots && cd ../../../..
cd subprojects/wlroots-hyprland/include && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlroots-hyprland && cd ../../..
cd subprojects/wlroots-hyprland/build/include && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlroots-hyprland && cd ../../../..
cp ./protocols/*-protocol.h ${PREFIX}/include/hyprland/protocols
cp ./build/hyprland.pc ${PREFIX}/share/pkgconfig
if [ -d /usr/share/pkgconfig ]; then cp ./build/hyprland.pc /usr/share/pkgconfig 2>/dev/null || true; fi
@@ -101,3 +118,28 @@ man:
--variable=section:1 \
--from rst \
--to man > ./docs/hyprctl.1
asan:
@echo -en "!!WARNING!!\nOnly run this in the TTY.\n"
@pidof Hyprland > /dev/null && echo -ne "Refusing to run with Hyprland running.\n" || echo ""
@pidof Hyprland > /dev/null && exit 1 || echo ""
rm -rf ./wayland
git reset --hard
@echo -en "If you want to apply a patch, input its path (leave empty for none):\n"
@read patchvar
@if [-n "$patchvar"]; then patch -p1 < $patchvar || echo ""; else echo "No patch specified"; fi
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 ..
cp ./wayland/build/src/libwayland-server.a .
@echo "Wayland done"
patch -p1 < ./scripts/hyprlandStaticAsan.diff
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DWITH_ASAN:STRING=True -DUSE_TRACY:STRING=False -DUSE_TRACY_GPU:STRING=False -S . -B ./build -G Ninja
cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
@echo "Hyprland done"
ASAN_OPTIONS="detect_odr_violation=0,log_path=asan.log" HYPRLAND_NO_CRASHREPORTER=1 ./build/Hyprland -c ~/.config/hypr/hyprland.conf

View File

@@ -41,6 +41,7 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more...
- Much more QoL stuff than other wlr-based compositors
- Custom bezier curves for the best animations
- Powerful plugin support
- Built-in plugin manager
- Tearing support for better gaming performance
- Easily expandable and readable codebase
- Fast and active development
@@ -123,13 +124,13 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more...
[Wayfire]: https://github.com/WayfireWM/wayfire
[TinyWl]: https://gitlab.freedesktop.org/wlroots/wlroots/-/blob/master/tinywl/tinywl.c
[Sway]: https://github.com/swaywm/sway
[DWL]: https://github.com/djpohly/dwl
[DWL]: https://codeberg.org/dwl/dwl
<!----------------------------------{ Images }--------------------------------->
[Stars Preview]: https://starchart.cc/vaxerski/Hyprland.svg
[Preview A]: https://cdn.discordapp.com/attachments/1091569872535814185/1107675866101723277/screenshot-summer.png
[Preview B]: https://i.ibb.co/SX7GbYR/winter-rice.png
[Preview A]: https://i.ibb.co/C1yTb0r/falf.png
[Preview B]: https://linfindel.github.io/cdn/hyprland-preview-b.png
[Preview C]: https://i.ibb.co/B3GJg28/20221126-20h53m26s-grim.png

View File

@@ -1,9 +1,7 @@
wallpaper_types = ['', 'anime_', 'anime2_']
wallpapers = ['0', '1', '2']
foreach type : wallpaper_types
foreach size : [2, 4, 8]
install_data(f'wall_@type@@size@K.png', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
endforeach
foreach type : wallpapers
install_data(f'wall@type@.png', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
endforeach
install_data('hyprland-portals.conf', install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'), install_tag: 'runtime')

BIN
assets/wall0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 MiB

BIN
assets/wall1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 MiB

BIN
assets/wall2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 511 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 502 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

View File

@@ -47,7 +47,7 @@ basically, directories in /tmp/hypr are your sessions.
## Obtaining the Hyprland Crash Report (v0.22.0beta and up)
If you have `$XDG_CACHE_HOME` set, the crash report directory is `$XDG_CACHE_HOME/hyprland`. If not, it's `~/.hyprland`
If you have `$XDG_CACHE_HOME` set, the crash report directory is `$XDG_CACHE_HOME/hyprland`. If not, it's `$HOME/.cache/hyprland`.
Go to the crash report directory and you should find a file named `hyprlandCrashReport[XXXX].txt` where `[XXXX]` is the PID of the process that crashed.

View File

@@ -1,8 +0,0 @@
# compile with HYPRLAND_HEADERS=<path_to_hl> make all
# make sure that the path above is to the root hl repo directory, NOT src/
# and that you have ran `make protocols` in the hl dir.
all:
$(CXX) -shared -fPIC --no-gnu-unique main.cpp customLayout.cpp customDecoration.cpp -o examplePlugin.so -g `pkg-config --cflags pixman-1 libdrm hyprland` -std=c++2b
clean:
rm ./examplePlugin.so

View File

@@ -1,74 +0,0 @@
#include "customDecoration.hpp"
#include <hyprland/src/Window.hpp>
#include <hyprland/src/Compositor.hpp>
#include "globals.hpp"
CCustomDecoration::CCustomDecoration(CWindow* pWindow) {
m_pWindow = pWindow;
m_vLastWindowPos = pWindow->m_vRealPosition.vec();
m_vLastWindowSize = pWindow->m_vRealSize.vec();
}
CCustomDecoration::~CCustomDecoration() {
damageEntire();
}
SWindowDecorationExtents CCustomDecoration::getWindowDecorationExtents() {
return m_seExtents;
}
void CCustomDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& offset) {
if (!g_pCompositor->windowValidMapped(m_pWindow))
return;
if (!m_pWindow->m_sSpecialRenderData.decorate)
return;
static auto* const PCOLOR = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:example:border_color")->intValue;
static auto* const PROUNDING = &HyprlandAPI::getConfigValue(PHANDLE, "decoration:rounding")->intValue;
static auto* const PBORDERSIZE = &HyprlandAPI::getConfigValue(PHANDLE, "general:border_size")->intValue;
const auto ROUNDING = !m_pWindow->m_sSpecialRenderData.rounding ?
0 :
(m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? *PROUNDING : m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying());
// draw the border
wlr_box fullBox = {(int)(m_vLastWindowPos.x - *PBORDERSIZE), (int)(m_vLastWindowPos.y - *PBORDERSIZE), (int)(m_vLastWindowSize.x + 2.0 * *PBORDERSIZE),
(int)(m_vLastWindowSize.y + 2.0 * *PBORDERSIZE)};
fullBox.x -= pMonitor->vecPosition.x;
fullBox.y -= pMonitor->vecPosition.y;
m_seExtents = {{m_vLastWindowPos.x - fullBox.x - pMonitor->vecPosition.x + 2, m_vLastWindowPos.y - fullBox.y - pMonitor->vecPosition.y + 2},
{fullBox.x + fullBox.width + pMonitor->vecPosition.x - m_vLastWindowPos.x - m_vLastWindowSize.x + 2,
fullBox.y + fullBox.height + pMonitor->vecPosition.y - m_vLastWindowPos.y - m_vLastWindowSize.y + 2}};
fullBox.x += offset.x;
fullBox.y += offset.y;
if (fullBox.width < 1 || fullBox.height < 1)
return; // don't draw invisible shadows
g_pHyprOpenGL->scissor((wlr_box*)nullptr);
scaleBox(&fullBox, pMonitor->scale);
g_pHyprOpenGL->renderBorder(&fullBox, CColor(*PCOLOR), *PROUNDING * pMonitor->scale + *PBORDERSIZE * 2, a);
}
eDecorationType CCustomDecoration::getDecorationType() {
return DECORATION_CUSTOM;
}
void CCustomDecoration::updateWindow(CWindow* pWindow) {
m_vLastWindowPos = pWindow->m_vRealPosition.vec();
m_vLastWindowSize = pWindow->m_vRealSize.vec();
damageEntire();
}
void CCustomDecoration::damageEntire() {
wlr_box dm = {(int)(m_vLastWindowPos.x - m_seExtents.topLeft.x), (int)(m_vLastWindowPos.y - m_seExtents.topLeft.y),
(int)(m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x), (int)m_seExtents.topLeft.y};
g_pHyprRenderer->damageBox(&dm);
}

View File

@@ -1,29 +0,0 @@
#pragma once
#define WLR_USE_UNSTABLE
#include <hyprland/src/render/decorations/IHyprWindowDecoration.hpp>
class CCustomDecoration : public IHyprWindowDecoration {
public:
CCustomDecoration(CWindow*);
virtual ~CCustomDecoration();
virtual SWindowDecorationExtents getWindowDecorationExtents();
virtual void draw(CMonitor*, float a, const Vector2D& offset);
virtual eDecorationType getDecorationType();
virtual void updateWindow(CWindow*);
virtual void damageEntire();
private:
SWindowDecorationExtents m_seExtents;
CWindow* m_pWindow = nullptr;
Vector2D m_vLastWindowPos;
Vector2D m_vLastWindowSize;
};

View File

@@ -1,80 +0,0 @@
#include "customLayout.hpp"
#include <hyprland/src/Compositor.hpp>
#include "globals.hpp"
void CHyprCustomLayout::onWindowCreatedTiling(CWindow* pWindow) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
const auto SIZE = PMONITOR->vecSize;
// these are used for focus and move calculations, and are *required* to touch for moving focus to work properly.
pWindow->m_vPosition = Vector2D{(SIZE.x / 2.0) * (m_vWindowData.size() % 2), (SIZE.y / 2.0) * (int)(m_vWindowData.size() > 1)};
pWindow->m_vSize = SIZE / 2.0;
// this is the actual pos and size of the window (where it's rendered)
pWindow->m_vRealPosition = pWindow->m_vPosition + Vector2D{10, 10};
pWindow->m_vRealSize = pWindow->m_vSize - Vector2D{20, 20};
const auto PDATA = &m_vWindowData.emplace_back();
PDATA->pWindow = pWindow;
}
void CHyprCustomLayout::onWindowRemovedTiling(CWindow* pWindow) {
std::erase_if(m_vWindowData, [&](const auto& other) { return other.pWindow == pWindow; });
}
bool CHyprCustomLayout::isWindowTiled(CWindow* pWindow) {
return std::find_if(m_vWindowData.begin(), m_vWindowData.end(), [&](const auto& other) { return other.pWindow == pWindow; }) != m_vWindowData.end();
}
void CHyprCustomLayout::recalculateMonitor(const int& eIdleInhibitMode) {
; // empty
}
void CHyprCustomLayout::recalculateWindow(CWindow* pWindow) {
; // empty
}
void CHyprCustomLayout::resizeActiveWindow(const Vector2D& delta, CWindow* pWindow) {
; // empty
}
void CHyprCustomLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode mode, bool on) {
; // empty
}
std::any CHyprCustomLayout::layoutMessage(SLayoutMessageHeader header, std::string content) {
return "";
}
SWindowRenderLayoutHints CHyprCustomLayout::requestRenderHints(CWindow* pWindow) {
return {};
}
void CHyprCustomLayout::switchWindows(CWindow* pWindowA, CWindow* pWindowB) {
; // empty
}
void CHyprCustomLayout::alterSplitRatio(CWindow* pWindow, float delta, bool exact) {
; // empty
}
std::string CHyprCustomLayout::getLayoutName() {
return "custom";
}
void CHyprCustomLayout::replaceWindowDataWith(CWindow* from, CWindow* to) {
; // empty
}
void CHyprCustomLayout::onEnable() {
for (auto& w : g_pCompositor->m_vWindows) {
if (w->isHidden() || !w->m_bIsMapped || w->m_bFadingOut || w->m_bIsFloating)
continue;
onWindowCreatedTiling(w.get());
}
}
void CHyprCustomLayout::onDisable() {
m_vWindowData.clear();
}

View File

@@ -1,32 +0,0 @@
#pragma once
#define WLR_USE_UNSTABLE
#include <hyprland/src/layout/IHyprLayout.hpp>
struct SWindowData {
CWindow* pWindow = nullptr;
};
class CHyprCustomLayout : public IHyprLayout {
public:
virtual void onWindowCreatedTiling(CWindow*);
virtual void onWindowRemovedTiling(CWindow*);
virtual bool isWindowTiled(CWindow*);
virtual void recalculateMonitor(const int&);
virtual void recalculateWindow(CWindow*);
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
virtual void switchWindows(CWindow*, CWindow*);
virtual void alterSplitRatio(CWindow*, float, bool);
virtual std::string getLayoutName();
virtual void replaceWindowDataWith(CWindow* from, CWindow* to);
virtual void onEnable();
virtual void onDisable();
private:
std::vector<SWindowData> m_vWindowData;
};

View File

@@ -1,5 +0,0 @@
#pragma once
#include <hyprland/src/plugins/PluginAPI.hpp>
inline HANDLE PHANDLE = nullptr;

View File

@@ -1,99 +0,0 @@
#define WLR_USE_UNSTABLE
#include "globals.hpp"
#include <hyprland/src/Window.hpp>
#include <hyprland/src/Compositor.hpp>
#include "customLayout.hpp"
#include "customDecoration.hpp"
#include <unistd.h>
#include <thread>
// Methods
inline std::unique_ptr<CHyprCustomLayout> g_pCustomLayout;
inline CFunctionHook* g_pFocusHook = nullptr;
inline CFunctionHook* g_pMotionHook = nullptr;
inline CFunctionHook* g_pMouseDownHook = nullptr;
typedef void (*origFocusWindow)(void*, CWindow*, wlr_surface*);
typedef void (*origMotion)(wlr_seat*, uint32_t, double, double);
typedef void (*origMouseDownNormal)(void*, wlr_pointer_button_event*);
// Do NOT change this function.
APICALL EXPORT std::string PLUGIN_API_VERSION() {
return HYPRLAND_API_VERSION;
}
static void onActiveWindowChange(void* self, std::any data) {
try {
auto* const PWINDOW = std::any_cast<CWindow*>(data);
HyprlandAPI::addNotification(PHANDLE, "[ExamplePlugin] Active window: " + (PWINDOW ? PWINDOW->m_szTitle : "None"), CColor{0.f, 0.5f, 1.f, 1.f}, 5000);
} catch (std::bad_any_cast& e) { HyprlandAPI::addNotification(PHANDLE, "[ExamplePlugin] Active window: None", CColor{0.f, 0.5f, 1.f, 1.f}, 5000); }
}
static void onNewWindow(void* self, std::any data) {
auto* const PWINDOW = std::any_cast<CWindow*>(data);
HyprlandAPI::addWindowDecoration(PHANDLE, PWINDOW, new CCustomDecoration(PWINDOW));
}
void hkFocusWindow(void* thisptr, CWindow* pWindow, wlr_surface* pSurface) {
// HyprlandAPI::addNotification(PHANDLE, getFormat("FocusWindow with %lx %lx", pWindow, pSurface), CColor{0.f, 1.f, 1.f, 1.f}, 5000);
(*(origFocusWindow)g_pFocusHook->m_pOriginal)(thisptr, pWindow, pSurface);
}
void hkNotifyMotion(wlr_seat* wlr_seat, uint32_t time_msec, double sx, double sy) {
// HyprlandAPI::addNotification(PHANDLE, getFormat("NotifyMotion with %lf %lf", sx, sy), CColor{0.f, 1.f, 1.f, 1.f}, 5000);
(*(origMotion)g_pMotionHook->m_pOriginal)(wlr_seat, time_msec, sx, sy);
}
void hkProcessMouseDownNormal(void* thisptr, wlr_pointer_button_event* e) {
// HyprlandAPI::addNotification(PHANDLE, "Mouse down normal!", CColor{0.8f, 0.2f, 0.5f, 1.0f}, 5000);
(*(origMouseDownNormal)g_pMouseDownHook->m_pOriginal)(thisptr, e);
}
APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
PHANDLE = handle;
HyprlandAPI::addNotification(PHANDLE, "Hello World from an example plugin!", CColor{0.f, 1.f, 1.f, 1.f}, 5000);
HyprlandAPI::registerCallbackDynamic(PHANDLE, "activeWindow", [&](void* self, std::any data) { onActiveWindowChange(self, data); });
HyprlandAPI::registerCallbackDynamic(PHANDLE, "openWindow", [&](void* self, std::any data) { onNewWindow(self, data); });
g_pCustomLayout = std::make_unique<CHyprCustomLayout>();
HyprlandAPI::addLayout(PHANDLE, "custom", g_pCustomLayout.get());
HyprlandAPI::addConfigValue(PHANDLE, "plugin:example:border_color", SConfigValue{.intValue = configStringToInt("rgb(44ee44)")});
HyprlandAPI::addDispatcher(PHANDLE, "example", [](std::string arg) { HyprlandAPI::addNotification(PHANDLE, "Arg passed: " + arg, CColor{0.5f, 0.5f, 0.7f, 1.0f}, 5000); });
// Hook a public member
g_pFocusHook = HyprlandAPI::createFunctionHook(PHANDLE, (void*)&CCompositor::focusWindow, (void*)&hkFocusWindow);
// Hook a public non-member
g_pMotionHook = HyprlandAPI::createFunctionHook(PHANDLE, (void*)&wlr_seat_pointer_notify_motion, (void*)&hkNotifyMotion);
// Hook a private member
static const auto METHODS = HyprlandAPI::findFunctionsByName(PHANDLE, "processMouseDownNormal");
g_pMouseDownHook = HyprlandAPI::createFunctionHook(PHANDLE, METHODS[0].address, (void*)&hkProcessMouseDownNormal);
static auto* const PBORDERCOLOR = HyprlandAPI::getConfigValue(PHANDLE, "plugin:example:border_color");
// fancy notifications
HyprlandAPI::addNotificationV2(
PHANDLE,
{{"text", "Example hint, color " + std::to_string(PBORDERCOLOR->intValue)}, {"time", (uint64_t)10000}, {"color", CColor{PBORDERCOLOR->intValue}}, {"icon", ICON_HINT}});
// Enable our hooks
g_pFocusHook->hook();
g_pMotionHook->hook();
g_pMouseDownHook->hook();
HyprlandAPI::reloadConfig();
return {"ExamplePlugin", "An example plugin", "Vaxry", "1.0"};
}
APICALL EXPORT void PLUGIN_EXIT() {
HyprlandAPI::invokeHyprctlCommand("seterror", "disable");
}

View File

@@ -19,8 +19,14 @@ monitor=,preferred,auto,auto
# Source a file (multi-file configs)
# source = ~/.config/hypr/myColors.conf
# Set programs that you use
$terminal = kitty
$fileManager = dolphin
$menu = wofi --show drun
# Some default env vars.
env = XCURSOR_SIZE,24
env = QT_QPA_PLATFORMTHEME,qt5ct # change to qt6ct if you have that
# For all categories, see https://wiki.hyprland.org/Configuring/Variables/
input {
@@ -63,6 +69,8 @@ decoration {
enabled = true
size = 3
passes = 1
vibrancy = 0.1696
}
drop_shadow = true
@@ -104,12 +112,13 @@ gestures {
misc {
# See https://wiki.hyprland.org/Configuring/Variables/ for more
force_default_wallpaper = -1 # Set to 0 to disable the anime mascot wallpapers
force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers
}
# Example per-device config
# See https://wiki.hyprland.org/Configuring/Keywords/#per-device-input-configs for more
device:epic-mouse-v1 {
device {
name = epic-mouse-v1
sensitivity = -0.5
}
@@ -118,18 +127,19 @@ device:epic-mouse-v1 {
# Example windowrule v2
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
$mainMod = SUPER
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
bind = $mainMod, Q, exec, kitty
bind = $mainMod, Q, exec, $terminal
bind = $mainMod, C, killactive,
bind = $mainMod, M, exit,
bind = $mainMod, E, exec, dolphin
bind = $mainMod, E, exec, $fileManager
bind = $mainMod, V, togglefloating,
bind = $mainMod, R, exec, wofi --show drun
bind = $mainMod, R, exec, $menu
bind = $mainMod, P, pseudo, # dwindle
bind = $mainMod, J, togglesplit, # dwindle
@@ -163,6 +173,10 @@ bind = $mainMod SHIFT, 8, movetoworkspace, 8
bind = $mainMod SHIFT, 9, movetoworkspace, 9
bind = $mainMod SHIFT, 0, movetoworkspace, 10
# Example special workspace (scratchpad)
bind = $mainMod, S, togglespecialworkspace, magic
bind = $mainMod SHIFT, S, movetoworkspace, special:magic
# Scroll through existing workspaces with mainMod + scroll
bind = $mainMod, mouse_down, workspace, e+1
bind = $mainMod, mouse_up, workspace, e-1

88
flake.lock generated
View File

@@ -1,5 +1,31 @@
{
"nodes": {
"hyprcursor": {
"inputs": {
"hyprlang": [
"hyprlang"
],
"nixpkgs": [
"nixpkgs"
],
"systems": [
"systems"
]
},
"locked": {
"lastModified": 1712434681,
"narHash": "sha256-qwmR2p1oc48Bj7gUDvb1oGL19Rjs2PmEmk4ChV01A5o=",
"owner": "hyprwm",
"repo": "hyprcursor",
"rev": "818d8c4b69e0997483d60b75f701fe14b561a7a3",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "hyprcursor",
"type": "github"
}
},
"hyprland-protocols": {
"inputs": {
"nixpkgs": [
@@ -23,13 +49,36 @@
"type": "github"
}
},
"hyprlang": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"systems": [
"systems"
]
},
"locked": {
"lastModified": 1711671891,
"narHash": "sha256-C/Wwsy/RLxHP1axFFl+AnwJRWfd8gxDKKoa8nt8Qk3c=",
"owner": "hyprwm",
"repo": "hyprlang",
"rev": "c1402612146ba06606ebf64963a02bc1efe11e74",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "hyprlang",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1694767346,
"narHash": "sha256-5uH27SiVFUwsTsqC5rs3kS7pBoNhtoy9QfTP9BmknGk=",
"lastModified": 1712439257,
"narHash": "sha256-aSpiNepFOMk9932HOax0XwNxbA38GOUVOiXfUVPOrck=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ace5093e36ab1e95cb9463863491bee90d5a4183",
"rev": "ff0dbd94265ac470dda06a657d5fe49de93b4599",
"type": "github"
},
"original": {
@@ -41,7 +90,9 @@
},
"root": {
"inputs": {
"hyprcursor": "hyprcursor",
"hyprland-protocols": "hyprland-protocols",
"hyprlang": "hyprlang",
"nixpkgs": "nixpkgs",
"systems": "systems",
"wlroots": "wlroots",
@@ -66,20 +117,18 @@
"wlroots": {
"flake": false,
"locked": {
"host": "gitlab.freedesktop.org",
"lastModified": 1696410538,
"narHash": "sha256-ecDhdYLXWHsxMv+EWG36mCNDvzRbu9qfjH7dLxL7aGM=",
"owner": "wlroots",
"repo": "wlroots",
"rev": "3406c1b17a4a7e6d4e2a7d9c1176affa72bce1bc",
"type": "gitlab"
"lastModified": 1712935342,
"narHash": "sha256-zzIbTFNFd/as42jyGx23fil2uBDYYv+8GA5JmRq5y9c=",
"owner": "hyprwm",
"repo": "wlroots-hyprland",
"rev": "62eeffbe233d199f520a5755c344e85f8eab7940",
"type": "github"
},
"original": {
"host": "gitlab.freedesktop.org",
"owner": "wlroots",
"repo": "wlroots",
"rev": "3406c1b17a4a7e6d4e2a7d9c1176affa72bce1bc",
"type": "gitlab"
"owner": "hyprwm",
"repo": "wlroots-hyprland",
"rev": "62eeffbe233d199f520a5755c344e85f8eab7940",
"type": "github"
}
},
"xdph": {
@@ -87,6 +136,9 @@
"hyprland-protocols": [
"hyprland-protocols"
],
"hyprlang": [
"hyprlang"
],
"nixpkgs": [
"nixpkgs"
],
@@ -95,11 +147,11 @@
]
},
"locked": {
"lastModified": 1694628480,
"narHash": "sha256-Qg9hstRw0pvjGu5hStkr2UX1D73RYcQ9Ns/KnZMIm9w=",
"lastModified": 1709299639,
"narHash": "sha256-jYqJM5khksLIbqSxCLUUcqEgI+O2LdlSlcMEBs39CAU=",
"owner": "hyprwm",
"repo": "xdg-desktop-portal-hyprland",
"rev": "8f45a6435069b9e24ebd3160eda736d7a391cbf2",
"rev": "2d2fb547178ec025da643db57d40a971507b82fe",
"type": "github"
},
"original": {

View File

@@ -8,25 +8,38 @@
systems.url = "github:nix-systems/default-linux";
wlroots = {
type = "gitlab";
host = "gitlab.freedesktop.org";
owner = "wlroots";
repo = "wlroots";
rev = "3406c1b17a4a7e6d4e2a7d9c1176affa72bce1bc";
type = "github";
owner = "hyprwm";
repo = "wlroots-hyprland";
rev = "62eeffbe233d199f520a5755c344e85f8eab7940";
flake = false;
};
hyprcursor = {
url = "github:hyprwm/hyprcursor";
inputs.nixpkgs.follows = "nixpkgs";
inputs.systems.follows = "systems";
inputs.hyprlang.follows = "hyprlang";
};
hyprland-protocols = {
url = "github:hyprwm/hyprland-protocols";
inputs.nixpkgs.follows = "nixpkgs";
inputs.systems.follows = "systems";
};
hyprlang = {
url = "github:hyprwm/hyprlang";
inputs.nixpkgs.follows = "nixpkgs";
inputs.systems.follows = "systems";
};
xdph = {
url = "github:hyprwm/xdg-desktop-portal-hyprland";
inputs.nixpkgs.follows = "nixpkgs";
inputs.systems.follows = "systems";
inputs.hyprland-protocols.follows = "hyprland-protocols";
inputs.hyprlang.follows = "hyprlang";
};
};
@@ -62,13 +75,16 @@
inherit
(pkgsFor.${system})
# hyprland-packages
hyprland
hyprland-unwrapped
hyprland-debug
hyprland-nvidia
hyprland-legacy-renderer
hyprland-unwrapped
# hyprland-extras
xdg-desktop-portal-hyprland
# dependencies
hyprland-protocols
wlroots-hyprland
udis86
@@ -76,17 +92,19 @@
});
devShells = eachSystem (system: {
default = pkgsFor.${system}.mkShell.override {
stdenv = pkgsFor.${system}.gcc13Stdenv;
} {
name = "hyprland-shell";
nativeBuildInputs = with pkgsFor.${system}; [cmake python3];
buildInputs = [self.packages.${system}.wlroots-hyprland];
inputsFrom = [
self.packages.${system}.wlroots-hyprland
self.packages.${system}.hyprland
];
};
default =
pkgsFor.${system}.mkShell.override {
stdenv = pkgsFor.${system}.gcc13Stdenv;
} {
name = "hyprland-shell";
nativeBuildInputs = with pkgsFor.${system}; [cmake python3 expat libxml2];
buildInputs = [self.packages.${system}.wlroots-hyprland];
hardeningDisable = ["fortify"];
inputsFrom = [
self.packages.${system}.wlroots-hyprland
self.packages.${system}.hyprland
];
};
});
formatter = eachSystem (system: nixpkgs.legacyPackages.${system}.alejandra);

View File

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

158
hyprctl/Strings.hpp Normal file
View File

@@ -0,0 +1,158 @@
#pragma once
const std::string_view USAGE = R"#(usage: hyprctl [flags] <command> [args...|--help]
commands:
activewindow Gets the active window name and its properties
activeworkspace Gets the active workspace and its properties
animations Gets the current config'd info about animations
and beziers
binds Lists all registered binds
clients Lists all windows with their properties
configerrors Lists all current config parsing errors
cursorpos Gets the current cursor position in global layout
coordinates
decorations <window_regex> Lists all decorations and their info
devices Lists all connected keyboards and mice
dismissnotify [amount] Dismisses all or up to AMOUNT notifications
dispatch <dispatcher> [args] Issue a dispatch to call a keybind
dispatcher with arguments
getoption <option> Gets the config option status (values)
globalshortcuts Lists all global shortcuts
hyprpaper ... Issue a hyprpaper request
instances Lists all running instances of Hyprland with
their info
keyword <name> <value> Issue a keyword to call a config keyword
dynamically
kill Issue a kill to get into a kill mode, where you can
kill an app by clicking on it. You can exit it
with ESCAPE
layers Lists all the surface layers
layouts Lists all layouts available (including plugin'd ones)
monitors Lists active outputs with their properties,
'monitors all' lists active and inactive outputs
notify ... Sends a notification using the built-in Hyprland
notification system
output ... Allows you to add and remove fake outputs to your
preferred backend
plugin ... Issue a plugin request
reload [config-only] Issue a reload to force reload the config. Pass
'config-only' to disable monitor reload
rollinglog Prints tail of the log
setcursor <theme> <size> Sets the cursor theme and reloads the cursor
manager
seterror <color> <message...> Sets the hyprctl error string. Color has
the same format as in colors in config. Will reset
when Hyprland's config is reloaded
setprop ... Sets a window property
splash Get the current splash
switchxkblayout ... Sets the xkb layout index for a keyboard
systeminfo Get system info
version Prints the hyprland version, meaning flags, commit
and branch of build.
workspacerules Lists all workspace rules
workspaces Lists all workspaces with their properties
flags:
-j Output in JSON
-r Refresh state after issuing command (e.g. for
updating variables)
--batch Execute a batch of commands, separated by ';'
--instance (-i) use a specific instance. Can be either signature or
index in hyprctl instances (0, 1, etc)
--help:
Can be used to print command's arguments that did not fit into this page
(three dots))#";
const std::string_view HYPRPAPER_HELP = R"#(usage: hyprctl [flags] hyprpaper <request>
requests:
listactive Lists all active images
listloaded Lists all loaded images
preload <path> Preloads image
unload <path> Unloads image. Pass 'all' as path to unload all images
wallpaper Issue a wallpaper to call a config wallpaper dynamically
flags:
See 'hyprctl --help')#";
const std::string_view NOTIFY_HELP = R"#(usage: hyprctl [flags] notify <icon> <time_ms> <color> <message...>
icon:
Integer of value:
0 Warning
1 Info
2 Hint
3 Error
4 Confused
5 Ok
6 or -1 No icon
time_ms:
Time to display notification in milliseconds
color:
Notification color. Format is the same as for colors in hyprland.conf. Use
0 for default color for icon
message:
Notification message
flags:
See 'hyprctl --help')#";
const std::string_view OUTPUT_HELP = R"#(usage: hyprctl [flags] output <create <backend> | remove <name>>
create <backend>:
Creates new virtual output. Possible values for backend: wayland, x11,
headless or auto.
remove <name>:
Removes virtual output. Pass the output's name, as found in
'hyprctl monitors'
flags:
See 'hyprctl --help')#";
const std::string_view PLUGIN_HELP = R"#(usage: hyprctl [flags] plugin <request>
requests:
load <path> Loads a plugin. Path must be absolute
unload <path> Unloads a plugin. Path must be absolute
list Lists all loaded plugins
flags:
See 'hyprctl --help')#";
const std::string_view SETPROP_HELP = R"#(usage: hyprctl [flags] setprop <regex> <property> <value> [lock]
regex:
Regular expression by which a window will be searched
property:
See https://wiki.hyprland.org/Configuring/Using-hyprctl/#setprop for list
of properties
value:
Property value
lock:
Optional argument. If lock is not added, will be unlocked. Locking means a
dynamic windowrule cannot override this setting.
flags:
See 'hyprctl --help')#";
const std::string_view SWITCHXKBLAYOUT_HELP = R"#(usage: [flags] switchxkblayout <device> <cmd>
device:
You can find the device using 'hyprctl devices' command
cmd:
'next' for next, 'prev' for previous, or ID for a specific one. IDs are
assigned based on their order in config file (keyboard_layout),
starting from 0
flags:
See 'hyprctl --help')#";

127
hyprctl/hyprctl.bash Normal file
View File

@@ -0,0 +1,127 @@
_hyprctl_cmd_2 () {
hyprctl monitors | grep Monitor | awk '{ print $2 }'
}
_hyprctl_cmd_1 () {
hyprpm list | grep "Plugin" | awk '{print $4}'
}
_hyprctl_cmd_0 () {
hyprctl clients | grep class | awk '{print $2}'
}
_hyprctl_cmd_3 () {
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
}
_hyprctl () {
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
return 1
fi
local 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" "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" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow")
declare -A literal_transitions
literal_transitions[0]="([103]=1 [74]=2 [33]=3 [1]=2 [2]=2 [77]=2 [105]=4 [36]=2 [108]=5 [40]=2 [45]=2 [112]=2 [84]=6 [113]=8 [51]=2 [53]=2 [88]=9 [117]=2 [119]=2 [121]=2 [15]=2 [58]=10 [59]=2 [17]=11 [122]=12 [19]=2 [124]=2 [126]=2 [25]=13 [67]=2 [96]=5 [97]=2 [27]=2 [28]=14 [100]=2 [102]=5)"
literal_transitions[3]="([72]=18 [13]=2 [32]=18 [54]=18 [55]=18 [89]=18 [104]=2 [120]=2 [76]=1 [16]=2 [123]=18 [3]=1 [5]=2 [63]=18 [127]=2 [129]=18 [80]=18 [130]=18 [83]=18 [31]=18 [48]=2 [12]=2 [85]=18 [10]=18 [86]=18 [137]=18)"
literal_transitions[7]="([103]=1 [74]=2 [33]=3 [1]=2 [2]=2 [77]=2 [105]=4 [36]=2 [40]=2 [45]=2 [112]=2 [84]=6 [113]=8 [51]=2 [53]=2 [88]=9 [117]=2 [119]=2 [121]=2 [15]=2 [58]=10 [59]=2 [17]=11 [122]=12 [19]=2 [124]=2 [126]=2 [25]=13 [67]=2 [97]=2 [27]=2 [28]=14 [100]=2)"
literal_transitions[8]="([128]=2 [131]=2 [0]=2 [73]=2 [35]=2 [106]=2 [37]=2 [107]=2 [4]=2 [78]=2 [39]=2 [79]=2 [110]=2 [6]=2 [41]=2 [42]=2 [81]=2 [82]=2 [46]=2 [47]=2 [9]=2 [109]=2 [50]=2 [52]=2 [11]=2 [115]=2 [87]=2 [49]=2 [56]=2 [90]=2 [57]=2 [91]=2 [92]=2 [60]=2 [61]=2 [125]=2 [93]=2 [62]=2 [20]=2 [95]=2 [22]=2 [23]=2 [64]=2 [65]=2 [24]=2 [132]=2 [26]=2 [68]=2 [98]=2 [69]=2 [29]=2 [136]=2 [70]=2 [99]=2)"
literal_transitions[9]="([114]=15 [111]=16)"
literal_transitions[11]="([101]=2)"
literal_transitions[13]="([21]=1 [116]=1 [30]=1 [135]=1 [118]=1 [43]=1 [71]=1)"
literal_transitions[14]="([38]=2)"
literal_transitions[15]="([8]=2 [66]=2 [14]=2 [133]=2)"
literal_transitions[17]="([75]=19)"
literal_transitions[18]="([18]=2 [7]=2)"
literal_transitions[19]="([34]=5 [44]=5)"
literal_transitions[20]="([134]=2 [94]=2)"
declare -A match_anything_transitions
match_anything_transitions=([1]=2 [0]=7 [6]=2 [20]=2 [10]=2 [2]=17 [7]=7 [12]=2 [14]=17 [16]=2 [4]=20 [11]=17)
declare -A subword_transitions
local state=0
local word_index=1
while [[ $word_index -lt $cword ]]; do
local word=${words[$word_index]}
if [[ -v "literal_transitions[$state]" ]]; then
declare -A state_transitions
eval "state_transitions=${literal_transitions[$state]}"
local word_matched=0
for literal_id in $(seq 0 $((${#literals[@]} - 1))); do
if [[ ${literals[$literal_id]} = "$word" ]]; then
if [[ -v "state_transitions[$literal_id]" ]]; then
state=${state_transitions[$literal_id]}
word_index=$((word_index + 1))
word_matched=1
break
fi
fi
done
if [[ $word_matched -ne 0 ]]; then
continue
fi
fi
if [[ -v "match_anything_transitions[$state]" ]]; then
state=${match_anything_transitions[$state]}
word_index=$((word_index + 1))
continue
fi
return 1
done
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
local state_transitions_initializer=${literal_transitions[$state]}
declare -A state_transitions
eval "state_transitions=$state_transitions_initializer"
for literal_id in "${!state_transitions[@]}"; do
local literal="${literals[$literal_id]}"
if [[ $literal = "${prefix}"* ]]; then
local completion=${literal#"$superfluous_prefix"}
COMPREPLY+=("$completion ")
fi
done
fi
declare -A commands
commands=([16]=2 [4]=3 [12]=1 [10]=0)
if [[ -v "commands[$state]" ]]; then
local command_id=${commands[$state]}
local completions=()
mapfile -t completions < <(_hyprctl_cmd_${command_id} "$prefix" | cut -f1)
for item in "${completions[@]}"; do
if [[ $item = "${prefix}"* ]]; then
COMPREPLY+=("$item")
fi
done
fi
return 0
}
complete -o nospace -F _hyprctl hyprctl

216
hyprctl/hyprctl.fish Normal file
View File

@@ -0,0 +1,216 @@
function _hyprctl_3
set 1 $argv[1]
hyprctl monitors | grep Monitor | awk '{ print $2 }'
end
function _hyprctl_2
set 1 $argv[1]
hyprpm list | grep "Plugin" | awk '{print $4}'
end
function _hyprctl_1
set 1 $argv[1]
hyprctl clients | grep class | awk '{print $2}'
end
function _hyprctl_4
set 1 $argv[1]
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
end
function _hyprctl
set COMP_LINE (commandline --cut-at-cursor)
set COMP_WORDS
echo $COMP_LINE | read --tokenize --array COMP_WORDS
if string match --quiet --regex '.*\s$' $COMP_LINE
set COMP_CWORD (math (count $COMP_WORDS) + 1)
else
set COMP_CWORD (count $COMP_WORDS)
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" "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" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow"
set --local descriptions
set descriptions[1] "Focus the next window on a workspace"
set descriptions[3] "Get the current cursor pos in global layout coordinates"
set descriptions[5] "Rename a workspace"
set descriptions[7] "Focus the first window matching"
set descriptions[10] "Swap the focused window with the next window"
set descriptions[12] "Move the active window"
set descriptions[16] "List the layers"
set descriptions[18] "List active outputs with their properties"
set descriptions[20] "Get into a kill mode, where you can kill an app by clicking on it"
set descriptions[21] "Set the current window's floating state to false"
set descriptions[22] "ERROR"
set descriptions[23] "Focus a monitor"
set descriptions[24] "Swap the active window with another window"
set descriptions[25] "Move the active window out of a group"
set descriptions[26] "Send a notification using the built-in Hyprland notification system"
set descriptions[27] "Move the cursor to a specified position"
set descriptions[28] "Set the cursor theme and reloads the cursor manager"
set descriptions[29] "Set the hyprctl error string"
set descriptions[30] "Move the active workspace to a monitor"
set descriptions[31] "CONFUSED"
set descriptions[34] "Set a property of a window"
set descriptions[35] "Specify the Hyprland instance"
set descriptions[36] "Toggle the current window's floating state"
set descriptions[37] "Get the list of defined workspace rules"
set descriptions[38] "Move the focused window to a workspace"
set descriptions[40] "Temporarily enable or disable binds:ignore_group_lock"
set descriptions[41] "List all workspaces with their properties"
set descriptions[42] "Swap the active window with the next or previous in a group"
set descriptions[43] "Close a specified window"
set descriptions[44] "WARNING"
set descriptions[45] "Specify the Hyprland instance"
set descriptions[46] "List all registered binds"
set descriptions[47] "Move the active window in a direction or to a monitor"
set descriptions[48] "Change the split ratio"
set descriptions[50] "Prohibit the active window from becoming or being inserted into group"
set descriptions[51] "Change the workspace"
set descriptions[52] "List all current config parsing errors"
set descriptions[53] "Toggle the current active window into a group"
set descriptions[54] "Get the config option status (values)"
set descriptions[57] "Close the active window"
set descriptions[58] "Pass the key to a specified window"
set descriptions[59] "List all decorations and their info"
set descriptions[60] "List all connected keyboards and mice"
set descriptions[61] "Switch focus from current to previously focused window"
set descriptions[62] "Change the current mapping group"
set descriptions[63] "Execute a Global Shortcut using the GlobalShortcuts portal"
set descriptions[65] "Force the renderer to reload all resources and outputs"
set descriptions[66] "Move a selected window"
set descriptions[68] "Print the Hyprland version: flags, commit and branch of build"
set descriptions[69] "Set all monitors' DPMS status"
set descriptions[70] "Resize the active window"
set descriptions[71] "Move the active window into a group"
set descriptions[72] "OK"
set descriptions[74] "Set the current window's floating state to true"
set descriptions[75] "Print tail of the log"
set descriptions[78] "List all layouts available (including plugin ones)"
set descriptions[79] "Move a workspace to a monitor"
set descriptions[80] "Execute a shell command"
set descriptions[82] "Modify the window stack order of the active or specified window"
set descriptions[83] "Toggle the focused window's internal fullscreen state"
set descriptions[85] "Issue a keyword to call a config keyword dynamically"
set descriptions[88] "Pin a window"
set descriptions[89] "Allows adding/removing fake outputs to a specific backend"
set descriptions[91] "Toggle a special workspace on/off"
set descriptions[92] "Toggle the focused window's fullscreen state"
set descriptions[93] "Toggle the current window to always be opaque"
set descriptions[94] "Focus the requested workspace"
set descriptions[96] "Switch to the next window in a group"
set descriptions[97] "Output in JSON format"
set descriptions[98] "List all running Hyprland instances and their info"
set descriptions[99] "Execute a raw shell command"
set descriptions[100] "Exit the compositor with no questions asked"
set descriptions[101] "List all windows with their properties"
set descriptions[103] "Execute a batch of commands separated by ;"
set descriptions[104] "Dismiss all or up to amount of notifications"
set descriptions[106] "Set the xkb layout index for a keyboard"
set descriptions[107] "Move window doesnt switch to the workspace"
set descriptions[108] "Behave as moveintogroup"
set descriptions[109] "Refresh state after issuing the command"
set descriptions[110] "Move the focus in a direction"
set descriptions[111] "Focus the urgent window or the last window"
set descriptions[113] "Get the active workspace name and its properties"
set descriptions[114] "Issue a dispatch to call a keybind dispatcher with an arg"
set descriptions[116] "Center the active window"
set descriptions[117] "HINT"
set descriptions[118] "Interact with hyprpaper if present"
set descriptions[119] "No Icon"
set descriptions[120] "Force reload the config"
set descriptions[122] "Print system info"
set descriptions[123] "Interact with a plugin"
set descriptions[125] "Get the active window name and its properties"
set descriptions[126] "Swap the active workspaces between two monitors"
set descriptions[127] "Print the current random splash"
set descriptions[129] "Lock the focused group"
set descriptions[132] "Lock the groups"
set descriptions[133] "Move the cursor to the corner of the active window"
set descriptions[136] "INFO"
set descriptions[137] "Resize a selected window"
set --local literal_transitions
set literal_transitions[1] "set inputs 104 75 34 2 3 78 106 37 109 41 46 113 85 114 52 54 89 118 120 122 16 59 60 18 123 20 125 127 26 68 97 98 28 29 101 103; set tos 2 3 4 3 3 3 5 3 6 3 3 3 7 9 3 3 10 3 3 3 3 11 3 12 13 3 3 3 14 3 6 3 3 15 3 6"
set literal_transitions[4] "set inputs 73 14 33 55 56 90 105 121 77 17 124 4 6 64 128 130 81 131 84 32 49 13 86 11 87 138; set tos 19 3 19 19 19 19 3 3 2 3 19 2 3 19 3 19 19 19 19 19 3 3 19 19 19 19"
set literal_transitions[8] "set inputs 104 75 34 2 3 78 106 37 41 46 113 85 114 52 54 89 118 120 122 16 59 60 18 123 20 125 127 26 68 98 28 29 101; set tos 2 3 4 3 3 3 5 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[9] "set inputs 129 132 1 74 36 107 38 108 5 79 40 80 111 7 42 43 82 83 47 48 10 110 51 53 12 116 88 50 57 91 58 92 93 61 62 126 94 63 21 96 23 24 65 66 25 133 27 69 99 70 30 137 71 100; 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"
set literal_transitions[10] "set inputs 115 112; set tos 16 17"
set literal_transitions[12] "set inputs 102; set tos 3"
set literal_transitions[14] "set inputs 22 117 31 136 119 44 72; set tos 2 2 2 2 2 2 2"
set literal_transitions[15] "set inputs 39; set tos 3"
set literal_transitions[16] "set inputs 9 67 15 134; set tos 3 3 3 3"
set literal_transitions[18] "set inputs 76; set tos 20"
set literal_transitions[19] "set inputs 19 8; set tos 3 3"
set literal_transitions[20] "set inputs 35 45; set tos 6 6"
set literal_transitions[21] "set inputs 135 95; set tos 3 3"
set --local match_anything_transitions_from 2 1 7 21 11 3 8 13 15 17 5 12
set --local match_anything_transitions_to 3 8 3 3 3 18 8 3 18 3 21 18
set --local state 1
set --local word_index 2
while test $word_index -lt $COMP_CWORD
set --local -- word $COMP_WORDS[$word_index]
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
set --local --erase inputs
set --local --erase tos
eval $literal_transitions[$state]
if contains -- $word $literals
set --local literal_matched 0
for literal_id in (seq 1 (count $literals))
if test $literals[$literal_id] = $word
set --local index (contains --index -- $literal_id $inputs)
set state $tos[$index]
set word_index (math $word_index + 1)
set literal_matched 1
break
end
end
if test $literal_matched -ne 0
continue
end
end
end
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 state $match_anything_transitions_to[$index]
set word_index (math $word_index + 1)
continue
end
return 1
end
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
set --local --erase inputs
set --local --erase tos
eval $literal_transitions[$state]
for literal_id in $inputs
if test -n $descriptions[$literal_id]
printf '%s\t%s\n' $literals[$literal_id] $descriptions[$literal_id]
else
printf '%s\n' $literals[$literal_id]
end
end
end
set command_states 17 5 13 11
set command_ids 3 4 2 1
if contains $state $command_states
set --local index (contains --index $state $command_states)
set --local function_id $command_ids[$index]
set --local function_name _hyprctl_$function_id
set --local --erase inputs
set --local --erase tos
$function_name "$COMP_WORDS[$COMP_CWORD]"
end
return 0
end
complete --command hyprctl --no-files --arguments "(_hyprctl)"

148
hyprctl/hyprctl.usage Normal file
View File

@@ -0,0 +1,148 @@
# This is a file feeded to complgen to generate bash/fish/zsh completions
# 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"
hyprctl [<OPTIONS>]... <ARGUMENTS>
<OPTIONS> ::= (-i | --instance) "Specify the Hyprland instance"
| (-j) "Output in JSON format"
| (-r) "Refresh state after issuing the command"
| (--batch) "Execute a batch of commands separated by ;"
;
<WINDOWS> ::= {{{ hyprctl clients | grep class | awk '{print $2}' }}};
<AVAILABLE_PLUGINS> ::= {{{ hyprpm list | grep "Plugin" | awk '{print $4}' }}};
<MONITORS> ::= {{{ hyprctl monitors | grep Monitor | awk '{ print $2 }' }}};
<KEYBOARDS> ::= {{{ hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}' }}};
<NOTIFICATION_TYPES> ::= (0) "WARNING"
| (1) "INFO"
| (2) "HINT"
| (3) "ERROR"
| (4) "CONFUSED"
| (5) "OK"
| (-1) "No Icon"
;
<PROPS> ::= (animationstyle)
| (rounding <NUM>)
| (bordersize <NUM>)
| (forcenoblur (0 | 1))
| (forceopaque (0 | 1))
| (forceopaqueoverriden (0 | 1))
| (forceallowsinput (0 | 1))
| (forcenoanims (0 | 1))
| (forcenoborder (0 | 1))
| (forcenodim (0 | 1))
| (forcenoshadow (0 | 1))
| (nofocus (0 | 1))
| (windowdancecompat (0 | 1))
| (nomaxsize (0 | 1))
| (minsize)
| (maxsize)
| (dimaround (0 | 1))
| (keepaspectratio (0 | 1))
| (alphaoverride (0 | 1))
| (alpha)
| (alphainactiveoverride (0 | 1))
| (alphainactive)
| (alphafullscreenoverride (0 | 1))
| (alphafullscreen)
| (activebordercolor)
| (inactivebordercolor)
;
<ARGUMENTS> ::= (activewindow) "Get the active window name and its properties"
| (activeworkspace) "Get the active workspace name and its properties"
| (binds) "List all registered binds"
| (clients) "List all windows with their properties"
| (configerrors) "List all current config parsing errors"
| (cursorpos) "Get the current cursor pos in global layout coordinates"
| (decorations <WINDOWS>) "List all decorations and their info"
| (devices) "List all connected keyboards and mice"
| (dismissnotify <NUM>) "Dismiss all or up to amount of notifications"
| (dispatch <DISPATCHERS>) "Issue a dispatch to call a keybind dispatcher with an arg"
| (getoption) "Get the config option status (values)"
| (globalshortcuts) ""
| (hyprpaper) "Interact with hyprpaper if present"
| (instances) "List all running Hyprland instances and their info"
| (keyword <KEYWORDS>) "Issue a keyword to call a config keyword dynamically"
| (kill) "Get into a kill mode, where you can kill an app by clicking on it"
| (layers) "List the layers"
| (layouts) "List all layouts available (including plugin ones)"
| (monitors [all]) "List active outputs with their properties"
| (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"
| (plugin <AVAILABLE_PLUGINS>) "Interact with a plugin"
| (reload) "Force reload the config"
| (rollinglog) "Print tail of the log"
| (setcursor) "Set the cursor theme and reloads the cursor manager"
| (seterror [disable]) "Set the hyprctl error string"
| (setprop <PROPS>) "Set a property of a window"
| (splash) "Print the current random splash"
| (switchxkblayout <KEYBOARDS> (next | prev | <NUM>)) "Set the xkb layout index for a keyboard"
| (systeminfo) "Print system info"
| (version) "Print the Hyprland version: flags, commit and branch of build"
| (workspacerules) "Get the list of defined workspace rules"
| (workspaces) "List all workspaces with their properties"
;
<DISPATCHERS> ::= (exec) "Execute a shell command"
| (execr) "Execute a raw shell command"
| (pass) "Pass the key to a specified window"
| (killactive) "Close the active window"
| (closewindow) "Close a specified window"
| (workspace) "Change the workspace"
| (movetoworkspace) "Move the focused window to a workspace"
| (movetoworkspacesilent) "Move window doesnt switch to the workspace"
| (togglefloating) "Toggle the current window's floating state"
| (setfloating) "Set the current window's floating state to true"
| (settiled) "Set the current window's floating state to false"
| (fullscreen) "Toggle the focused window's fullscreen state"
| (fakefullscreen) "Toggle the focused window's internal fullscreen state"
| (dpms) "Set all monitors' DPMS status"
| (pin) "Pin a window"
| (movefocus) "Move the focus in a direction"
| (movewindow) "Move the active window in a direction or to a monitor"
| (swapwindow) "Swap the active window with another window"
| (centerwindow) "Center the active window"
| (resizeactive) "Resize the active window"
| (moveactive) "Move the active window"
| (resizewindowpixel) "Resize a selected window"
| (movewindowpixel) "Move a selected window"
| (cyclenext) "Focus the next window on a workspace"
| (swapnext) "Swap the focused window with the next window"
| (focuswindow) "Focus the first window matching"
| (focusmonitor) "Focus a monitor"
| (splitratio) "Change the split ratio"
| (toggleopaque) "Toggle the current window to always be opaque"
| (movecursortocorner) "Move the cursor to the corner of the active window"
| (movecursor) "Move the cursor to a specified position"
| (renameworkspace) "Rename a workspace"
| (exit) "Exit the compositor with no questions asked"
| (forcerendererreload) "Force the renderer to reload all resources and outputs"
| (movecurrentworkspacetomonitor) "Move the active workspace to a monitor"
| (focusworkspaceoncurrentmonitor) "Focus the requested workspace"
| (moveworkspacetomonitor) "Move a workspace to a monitor"
| (swapactiveworkspaces) "Swap the active workspaces between two monitors"
| (alterzorder) "Modify the window stack order of the active or specified window"
| (togglespecialworkspace) "Toggle a special workspace on/off"
| (focusurgentorlast) "Focus the urgent window or the last window"
| (togglegroup) "Toggle the current active window into a group"
| (changegroupactive) "Switch to the next window in a group"
| (focuscurrentorlast) "Switch focus from current to previously focused window"
| (lockgroups) "Lock the groups"
| (lockactivegroup) "Lock the focused group"
| (moveintogroup) "Move the active window into a group"
| (moveoutofgroup) "Move the active window out of a group"
| (movewindoworgroup) "Behave as moveintogroup"
| (movegroupwindow) "Swap the active window with the next or previous in a group"
| (denywindowfromgroup) "Prohibit the active window from becoming or being inserted into group"
| (setignoregrouplock) "Temporarily enable or disable binds:ignore_group_lock"
| (global) "Execute a Global Shortcut using the GlobalShortcuts portal"
| (submap) "Change the current mapping group"
;

251
hyprctl/hyprctl.zsh Normal file
View File

@@ -0,0 +1,251 @@
#compdef hyprctl
_hyprctl_cmd_2 () {
hyprctl monitors | grep Monitor | awk '{ print $2 }'
}
_hyprctl_cmd_1 () {
hyprpm list | grep "Plugin" | awk '{print $4}'
}
_hyprctl_cmd_0 () {
hyprctl clients | grep class | awk '{print $2}'
}
_hyprctl_cmd_3 () {
hyprctl devices | sed -n '/Keyboard at/{n; s/^\s\+//; p}'
}
_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" "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" "pin" "output" "forcenoblur" "togglespecialworkspace" "fullscreen" "toggleopaque" "focusworkspaceoncurrentmonitor" "next" "changegroupactive" "-j" "instances" "execr" "exit" "clients" "all" "--batch" "dismissnotify" "inactivebordercolor" "switchxkblayout" "movetoworkspacesilent" "movewindoworgroup" "-r" "movefocus" "focusurgentorlast" "remove" "activeworkspace" "dispatch" "create" "centerwindow" "2" "hyprpaper" "-1" "reload" "alphainactive" "systeminfo" "plugin" "dimaround" "activewindow" "swapactiveworkspaces" "splash" "maxsize" "lockactivegroup" "windowdancecompat" "forceopaqueoverriden" "lockgroups" "movecursortocorner" "x11" "prev" "1" "resizewindowpixel" "forcenoshadow")
local -A descriptions
descriptions[1]="Focus the next window on a workspace"
descriptions[3]="Get the current cursor pos in global layout coordinates"
descriptions[5]="Rename a workspace"
descriptions[7]="Focus the first window matching"
descriptions[10]="Swap the focused window with the next window"
descriptions[12]="Move the active window"
descriptions[16]="List the layers"
descriptions[18]="List active outputs with their properties"
descriptions[20]="Get into a kill mode, where you can kill an app by clicking on it"
descriptions[21]="Set the current window's floating state to false"
descriptions[22]="ERROR"
descriptions[23]="Focus a monitor"
descriptions[24]="Swap the active window with another window"
descriptions[25]="Move the active window out of a group"
descriptions[26]="Send a notification using the built-in Hyprland notification system"
descriptions[27]="Move the cursor to a specified position"
descriptions[28]="Set the cursor theme and reloads the cursor manager"
descriptions[29]="Set the hyprctl error string"
descriptions[30]="Move the active workspace to a monitor"
descriptions[31]="CONFUSED"
descriptions[34]="Set a property of a window"
descriptions[35]="Specify the Hyprland instance"
descriptions[36]="Toggle the current window's floating state"
descriptions[37]="Get the list of defined workspace rules"
descriptions[38]="Move the focused window to a workspace"
descriptions[40]="Temporarily enable or disable binds:ignore_group_lock"
descriptions[41]="List all workspaces with their properties"
descriptions[42]="Swap the active window with the next or previous in a group"
descriptions[43]="Close a specified window"
descriptions[44]="WARNING"
descriptions[45]="Specify the Hyprland instance"
descriptions[46]="List all registered binds"
descriptions[47]="Move the active window in a direction or to a monitor"
descriptions[48]="Change the split ratio"
descriptions[50]="Prohibit the active window from becoming or being inserted into group"
descriptions[51]="Change the workspace"
descriptions[52]="List all current config parsing errors"
descriptions[53]="Toggle the current active window into a group"
descriptions[54]="Get the config option status (values)"
descriptions[57]="Close the active window"
descriptions[58]="Pass the key to a specified window"
descriptions[59]="List all decorations and their info"
descriptions[60]="List all connected keyboards and mice"
descriptions[61]="Switch focus from current to previously focused window"
descriptions[62]="Change the current mapping group"
descriptions[63]="Execute a Global Shortcut using the GlobalShortcuts portal"
descriptions[65]="Force the renderer to reload all resources and outputs"
descriptions[66]="Move a selected window"
descriptions[68]="Print the Hyprland version: flags, commit and branch of build"
descriptions[69]="Set all monitors' DPMS status"
descriptions[70]="Resize the active window"
descriptions[71]="Move the active window into a group"
descriptions[72]="OK"
descriptions[74]="Set the current window's floating state to true"
descriptions[75]="Print tail of the log"
descriptions[78]="List all layouts available (including plugin ones)"
descriptions[79]="Move a workspace to a monitor"
descriptions[80]="Execute a shell command"
descriptions[82]="Modify the window stack order of the active or specified window"
descriptions[83]="Toggle the focused window's internal fullscreen state"
descriptions[85]="Issue a keyword to call a config keyword dynamically"
descriptions[88]="Pin a window"
descriptions[89]="Allows adding/removing fake outputs to a specific backend"
descriptions[91]="Toggle a special workspace on/off"
descriptions[92]="Toggle the focused window's fullscreen state"
descriptions[93]="Toggle the current window to always be opaque"
descriptions[94]="Focus the requested workspace"
descriptions[96]="Switch to the next window in a group"
descriptions[97]="Output in JSON format"
descriptions[98]="List all running Hyprland instances and their info"
descriptions[99]="Execute a raw shell command"
descriptions[100]="Exit the compositor with no questions asked"
descriptions[101]="List all windows with their properties"
descriptions[103]="Execute a batch of commands separated by ;"
descriptions[104]="Dismiss all or up to amount of notifications"
descriptions[106]="Set the xkb layout index for a keyboard"
descriptions[107]="Move window doesnt switch to the workspace"
descriptions[108]="Behave as moveintogroup"
descriptions[109]="Refresh state after issuing the command"
descriptions[110]="Move the focus in a direction"
descriptions[111]="Focus the urgent window or the last window"
descriptions[113]="Get the active workspace name and its properties"
descriptions[114]="Issue a dispatch to call a keybind dispatcher with an arg"
descriptions[116]="Center the active window"
descriptions[117]="HINT"
descriptions[118]="Interact with hyprpaper if present"
descriptions[119]="No Icon"
descriptions[120]="Force reload the config"
descriptions[122]="Print system info"
descriptions[123]="Interact with a plugin"
descriptions[125]="Get the active window name and its properties"
descriptions[126]="Swap the active workspaces between two monitors"
descriptions[127]="Print the current random splash"
descriptions[129]="Lock the focused group"
descriptions[132]="Lock the groups"
descriptions[133]="Move the cursor to the corner of the active window"
descriptions[136]="INFO"
descriptions[137]="Resize a selected window"
local -A literal_transitions
literal_transitions[1]="([104]=2 [75]=3 [34]=4 [2]=3 [3]=3 [78]=3 [106]=5 [37]=3 [109]=6 [41]=3 [46]=3 [113]=3 [85]=7 [114]=9 [52]=3 [54]=3 [89]=10 [118]=3 [120]=3 [122]=3 [16]=3 [59]=11 [60]=3 [18]=12 [123]=13 [20]=3 [125]=3 [127]=3 [26]=14 [68]=3 [97]=6 [98]=3 [28]=3 [29]=15 [101]=3 [103]=6)"
literal_transitions[4]="([73]=19 [14]=3 [33]=19 [55]=19 [56]=19 [90]=19 [105]=3 [121]=3 [77]=2 [17]=3 [124]=19 [4]=2 [6]=3 [64]=19 [128]=3 [130]=19 [81]=19 [131]=19 [84]=19 [32]=19 [49]=3 [13]=3 [86]=19 [11]=19 [87]=19 [138]=19)"
literal_transitions[8]="([104]=2 [75]=3 [34]=4 [2]=3 [3]=3 [78]=3 [106]=5 [37]=3 [41]=3 [46]=3 [113]=3 [85]=7 [114]=9 [52]=3 [54]=3 [89]=10 [118]=3 [120]=3 [122]=3 [16]=3 [59]=11 [60]=3 [18]=12 [123]=13 [20]=3 [125]=3 [127]=3 [26]=14 [68]=3 [98]=3 [28]=3 [29]=15 [101]=3)"
literal_transitions[9]="([129]=3 [132]=3 [1]=3 [74]=3 [36]=3 [107]=3 [38]=3 [108]=3 [5]=3 [79]=3 [40]=3 [80]=3 [111]=3 [7]=3 [42]=3 [43]=3 [82]=3 [83]=3 [47]=3 [48]=3 [10]=3 [110]=3 [51]=3 [53]=3 [12]=3 [116]=3 [88]=3 [50]=3 [57]=3 [91]=3 [58]=3 [92]=3 [93]=3 [61]=3 [62]=3 [126]=3 [94]=3 [63]=3 [21]=3 [96]=3 [23]=3 [24]=3 [65]=3 [66]=3 [25]=3 [133]=3 [27]=3 [69]=3 [99]=3 [70]=3 [30]=3 [137]=3 [71]=3 [100]=3)"
literal_transitions[10]="([115]=16 [112]=17)"
literal_transitions[12]="([102]=3)"
literal_transitions[14]="([22]=2 [117]=2 [31]=2 [136]=2 [119]=2 [44]=2 [72]=2)"
literal_transitions[15]="([39]=3)"
literal_transitions[16]="([9]=3 [67]=3 [15]=3 [134]=3)"
literal_transitions[18]="([76]=20)"
literal_transitions[19]="([19]=3 [8]=3)"
literal_transitions[20]="([35]=6 [45]=6)"
literal_transitions[21]="([135]=3 [95]=3)"
local -A match_anything_transitions
match_anything_transitions=([2]=3 [1]=8 [7]=3 [21]=3 [11]=3 [3]=18 [8]=8 [13]=3 [15]=18 [17]=3 [5]=21 [12]=18)
declare -A subword_transitions
local state=1
local word_index=2
while [[ $word_index -lt $CURRENT ]]; do
if [[ -v "literal_transitions[$state]" ]]; then
local -A state_transitions
eval "state_transitions=${literal_transitions[$state]}"
local word=${words[$word_index]}
local word_matched=0
for ((literal_id = 1; literal_id <= $#literals; literal_id++)); do
if [[ ${literals[$literal_id]} = "$word" ]]; then
if [[ -v "state_transitions[$literal_id]" ]]; then
state=${state_transitions[$literal_id]}
word_index=$((word_index + 1))
word_matched=1
break
fi
fi
done
if [[ $word_matched -ne 0 ]]; then
continue
fi
fi
if [[ -v "match_anything_transitions[$state]" ]]; then
state=${match_anything_transitions[$state]}
word_index=$((word_index + 1))
continue
fi
return 1
done
completions_no_description_trailing_space=()
completions_no_description_no_trailing_space=()
completions_trailing_space=()
suffixes_trailing_space=()
descriptions_trailing_space=()
completions_no_trailing_space=()
suffixes_no_trailing_space=()
descriptions_no_trailing_space=()
if [[ -v "literal_transitions[$state]" ]]; then
local -A state_transitions
eval "state_transitions=${literal_transitions[$state]}"
for literal_id in ${(k)state_transitions}; do
if [[ -v "descriptions[$literal_id]" ]]; then
completions_trailing_space+=("${literals[$literal_id]}")
suffixes_trailing_space+=("${literals[$literal_id]}")
descriptions_trailing_space+=("${descriptions[$literal_id]}")
else
completions_no_description_trailing_space+=("${literals[$literal_id]}")
fi
done
fi
local -A commands=([17]=2 [5]=3 [13]=1 [11]=0)
if [[ -v "commands[$state]" ]]; then
local command_id=${commands[$state]}
local output=$(_hyprctl_cmd_${command_id} "${words[$CURRENT]}")
local -a command_completions=("${(@f)output}")
for line in ${command_completions[@]}; do
local parts=(${(@s: :)line})
if [[ -v "parts[2]" ]]; then
completions_trailing_space+=("${parts[1]}")
suffixes_trailing_space+=("${parts[1]}")
descriptions_trailing_space+=("${parts[2]}")
else
completions_no_description_trailing_space+=("${parts[1]}")
fi
done
fi
local maxlen=0
for suffix in ${suffixes_trailing_space[@]}; do
if [[ ${#suffix} -gt $maxlen ]]; then
maxlen=${#suffix}
fi
done
for suffix in ${suffixes_no_trailing_space[@]}; do
if [[ ${#suffix} -gt $maxlen ]]; then
maxlen=${#suffix}
fi
done
for ((i = 1; i <= $#suffixes_trailing_space; i++)); do
if [[ -z ${descriptions_trailing_space[$i]} ]]; then
descriptions_trailing_space[$i]="${(r($maxlen)( ))${suffixes_trailing_space[$i]}}"
else
descriptions_trailing_space[$i]="${(r($maxlen)( ))${suffixes_trailing_space[$i]}} -- ${descriptions_trailing_space[$i]}"
fi
done
for ((i = 1; i <= $#suffixes_no_trailing_space; i++)); do
if [[ -z ${descriptions_no_trailing_space[$i]} ]]; then
descriptions_no_trailing_space[$i]="${(r($maxlen)( ))${suffixes_no_trailing_space[$i]}}"
else
descriptions_no_trailing_space[$i]="${(r($maxlen)( ))${suffixes_no_trailing_space[$i]}} -- ${descriptions_no_trailing_space[$i]}"
fi
done
compadd -Q -a completions_no_description_trailing_space
compadd -Q -S ' ' -a completions_no_description_no_trailing_space
compadd -l -Q -a -d descriptions_trailing_space completions_trailing_space
compadd -l -Q -S '' -a -d descriptions_no_trailing_space completions_no_trailing_space
return 0
}
compdef _hyprctl hyprctl

View File

@@ -22,41 +22,9 @@
#include <deque>
#include <filesystem>
#include <stdarg.h>
#include <regex>
const std::string USAGE = R"#(usage: hyprctl [(opt)flags] [command] [(opt)args]
commands:
monitors
workspaces
activeworkspace
clients
activewindow
layers
devices
binds
dispatch
keyword
version
kill
splash
hyprpaper
reload
setcursor
getoption
cursorpos
switchxkblayout
seterror
setprop
plugin
notify
globalshortcuts
instances
flags:
-j -> output in JSON
--batch -> execute a batch of commands, separated by ';'
--instance (-i) -> use a specific instance. Can be either signature or index in hyprctl instances (0, 1, etc)
)#";
#include "Strings.hpp"
#define PAD
@@ -74,7 +42,7 @@ std::vector<SInstanceData> instances() {
std::vector<SInstanceData> result;
for (const auto& el : std::filesystem::directory_iterator("/tmp/hypr")) {
if (el.is_directory())
if (el.is_directory() || !el.path().string().ends_with(".lock"))
continue;
// read lock
@@ -82,7 +50,9 @@ std::vector<SInstanceData> instances() {
data->id = el.path().string();
data->id = data->id.substr(data->id.find_last_of('/') + 1, data->id.find(".lock") - data->id.find_last_of('/') - 1);
data->time = std::stoull(data->id.substr(data->id.find_first_of('_') + 1));
try {
data->time = std::stoull(data->id.substr(data->id.find_first_of('_') + 1));
} catch (std::exception& e) { continue; }
// read file
std::ifstream ifs(el.path().string());
@@ -90,7 +60,9 @@ std::vector<SInstanceData> instances() {
int i = 0;
for (std::string line; std::getline(ifs, line); ++i) {
if (i == 0) {
data->pid = std::stoull(line);
try {
data->pid = std::stoull(line);
} catch (std::exception& e) { continue; }
} else if (i == 1) {
data->wlSocket = line;
} else
@@ -221,9 +193,14 @@ void requestHyprpaper(std::string arg) {
std::cout << std::string(buffer);
}
void batchRequest(std::string arg) {
std::string rq = "[[BATCH]]" + arg.substr(arg.find_first_of(" ") + 1);
void batchRequest(std::string arg, bool json) {
std::string commands = arg.substr(arg.find_first_of(" ") + 1);
if (json) {
commands = "j/" + std::regex_replace(commands, std::regex(";\\s*"), ";j/");
}
std::string rq = "[[BATCH]]" + commands;
request(rq);
}
@@ -273,11 +250,10 @@ bool isNumber(const std::string& str, bool allowfloat) {
}
int main(int argc, char** argv) {
int bflag = 0, sflag = 0, index, c;
bool parseArgs = true;
if (argc < 2) {
printf("%s\n", USAGE.c_str());
std::cout << USAGE << std::endl;
return 1;
}
@@ -287,7 +263,7 @@ int main(int argc, char** argv) {
bool json = false;
std::string overrideInstance = "";
for (auto i = 0; i < ARGS.size(); ++i) {
for (std::size_t i = 0; i < ARGS.size(); ++i) {
if (ARGS[i] == "--") {
// Stop parsing arguments after --
parseArgs = false;
@@ -298,19 +274,43 @@ int main(int argc, char** argv) {
if (ARGS[i] == "-j" && !fullArgs.contains("j")) {
fullArgs += "j";
json = true;
} else if (ARGS[i] == "-r" && !fullArgs.contains("r")) {
fullArgs += "r";
} else if (ARGS[i] == "-a" && !fullArgs.contains("a")) {
fullArgs += "a";
} else if (ARGS[i] == "--batch") {
fullRequest = "--batch ";
} else if (ARGS[i] == "--instance" || ARGS[i] == "-i") {
++i;
if (i >= ARGS.size()) {
printf("%s\n", USAGE.c_str());
std::cout << USAGE << std::endl;
return 1;
}
overrideInstance = ARGS[i];
} else if (ARGS[i] == "--help") {
const std::string& cmd = ARGS[0];
if (cmd == "hyprpaper") {
std::cout << HYPRPAPER_HELP << std::endl;
} else if (cmd == "notify") {
std::cout << NOTIFY_HELP << std::endl;
} else if (cmd == "output") {
std::cout << OUTPUT_HELP << std::endl;
} else if (cmd == "plugin") {
std::cout << PLUGIN_HELP << std::endl;
} else if (cmd == "setprop") {
std::cout << SETPROP_HELP << std::endl;
} else if (cmd == "switchxkblayout") {
std::cout << SWITCHXKBLAYOUT_HELP << std::endl;
} else {
std::cout << USAGE << std::endl;
}
return 1;
} else {
printf("%s\n", USAGE.c_str());
std::cout << USAGE << std::endl;
return 1;
}
@@ -321,7 +321,7 @@ int main(int argc, char** argv) {
}
if (fullRequest.empty()) {
printf("%s\n", USAGE.c_str());
std::cout << USAGE << std::endl;
return 1;
}
@@ -329,6 +329,12 @@ int main(int argc, char** argv) {
fullRequest = fullArgs + "/" + fullRequest;
// instances is HIS-independent
if (fullRequest.contains("/instances")) {
instancesRequest(json);
return 0;
}
if (overrideInstance.contains("_"))
instanceSignature = overrideInstance;
else if (!overrideInstance.empty()) {
@@ -341,7 +347,7 @@ int main(int argc, char** argv) {
const auto INSTANCES = instances();
if (INSTANCENO < 0 || INSTANCENO >= INSTANCES.size()) {
if (INSTANCENO < 0 || static_cast<std::size_t>(INSTANCENO) >= INSTANCES.size()) {
std::cout << "no such instance\n";
return 1;
}
@@ -351,7 +357,7 @@ int main(int argc, char** argv) {
const auto ISIG = getenv("HYPRLAND_INSTANCE_SIGNATURE");
if (!ISIG) {
std::cout << "HYPRLAND_INSTANCE_SIGNATURE not set! (is hyprland running?)";
std::cout << "HYPRLAND_INSTANCE_SIGNATURE not set! (is hyprland running?)\n";
return 1;
}
@@ -361,41 +367,9 @@ int main(int argc, char** argv) {
int exitStatus = 0;
if (fullRequest.contains("/--batch"))
batchRequest(fullRequest);
else if (fullRequest.contains("/monitors"))
request(fullRequest);
else if (fullRequest.contains("/clients"))
request(fullRequest);
else if (fullRequest.contains("/workspaces"))
request(fullRequest);
else if (fullRequest.contains("/activeworkspace"))
request(fullRequest);
else if (fullRequest.contains("/activewindow"))
request(fullRequest);
else if (fullRequest.contains("/layers"))
request(fullRequest);
else if (fullRequest.contains("/version"))
request(fullRequest);
else if (fullRequest.contains("/kill"))
request(fullRequest);
else if (fullRequest.contains("/splash"))
request(fullRequest);
else if (fullRequest.contains("/devices"))
request(fullRequest);
else if (fullRequest.contains("/reload"))
request(fullRequest);
else if (fullRequest.contains("/getoption"))
request(fullRequest);
else if (fullRequest.contains("/binds"))
request(fullRequest);
else if (fullRequest.contains("/cursorpos"))
request(fullRequest);
else if (fullRequest.contains("/animations"))
request(fullRequest);
else if (fullRequest.contains("/globalshortcuts"))
request(fullRequest);
else if (fullRequest.contains("/instances"))
instancesRequest(json);
batchRequest(fullRequest, json);
else if (fullRequest.contains("/hyprpaper"))
requestHyprpaper(fullRequest);
else if (fullRequest.contains("/switchxkblayout"))
request(fullRequest, 2);
else if (fullRequest.contains("/seterror"))
@@ -404,6 +378,8 @@ int main(int argc, char** argv) {
request(fullRequest, 3);
else if (fullRequest.contains("/plugin"))
request(fullRequest, 1);
else if (fullRequest.contains("/dismissnotify"))
request(fullRequest, 0);
else if (fullRequest.contains("/notify"))
request(fullRequest, 2);
else if (fullRequest.contains("/output"))
@@ -414,15 +390,14 @@ int main(int argc, char** argv) {
request(fullRequest, 1);
else if (fullRequest.contains("/keyword"))
request(fullRequest, 2);
else if (fullRequest.contains("/hyprpaper"))
requestHyprpaper(fullRequest);
else if (fullRequest.contains("/decorations"))
request(fullRequest, 1);
else if (fullRequest.contains("/--help"))
printf("%s", USAGE.c_str());
std::cout << USAGE << std::endl;
else {
printf("%s\n", USAGE.c_str());
return 1;
request(fullRequest);
}
printf("\n");
std::cout << std::endl;
return exitStatus;
}

View File

@@ -1,3 +1,7 @@
executable('hyprctl', 'main.cpp',
install: true
)
install_data('hyprctl.bash', install_dir: join_paths(get_option('datadir'), 'bash-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

@@ -5,4 +5,4 @@ Name: Hyprland
URL: https://github.com/hyprwm/Hyprland
Description: Hyprland header files
Version: @HYPRLAND_VERSION@
Cflags: -I"${includedir}/hyprland/protocols" -I"${includedir}/hyprland/wlroots" -I"${includedir}"
Cflags: -I"${includedir}/hyprland/protocols" -I"${includedir}/hyprland/wlroots-hyprland" -I"${includedir}"

16
hyprpm/CMakeLists.txt Normal file
View File

@@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.19)
project(
hyprpm
DESCRIPTION "A Hyprland Plugin Manager"
)
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
set(CMAKE_CXX_STANDARD 23)
pkg_check_modules(tomlplusplus REQUIRED IMPORTED_TARGET tomlplusplus)
add_executable(hyprpm ${SRCFILES})
target_link_libraries(hyprpm PUBLIC PkgConfig::tomlplusplus)

106
hyprpm/hyprpm.bash Normal file
View File

@@ -0,0 +1,106 @@
_hyprpm_cmd_0 () {
hyprpm list | grep Plugin | awk '{print $4}'
}
_hyprpm () {
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
return 1
fi
local 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 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[1]="([10]=2 [11]=3 [3]=3 [2]=2 [14]=2 [5]=2 [6]=2)"
literal_transitions[4]="([1]=5)"
literal_transitions[5]="([0]=6 [12]=6)"
declare -A match_anything_transitions
match_anything_transitions=([3]=2 [2]=4 [0]=1 [1]=1)
declare -A subword_transitions
local state=0
local word_index=1
while [[ $word_index -lt $cword ]]; do
local word=${words[$word_index]}
if [[ -v "literal_transitions[$state]" ]]; then
declare -A state_transitions
eval "state_transitions=${literal_transitions[$state]}"
local word_matched=0
for literal_id in $(seq 0 $((${#literals[@]} - 1))); do
if [[ ${literals[$literal_id]} = "$word" ]]; then
if [[ -v "state_transitions[$literal_id]" ]]; then
state=${state_transitions[$literal_id]}
word_index=$((word_index + 1))
word_matched=1
break
fi
fi
done
if [[ $word_matched -ne 0 ]]; then
continue
fi
fi
if [[ -v "match_anything_transitions[$state]" ]]; then
state=${match_anything_transitions[$state]}
word_index=$((word_index + 1))
continue
fi
return 1
done
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
local state_transitions_initializer=${literal_transitions[$state]}
declare -A state_transitions
eval "state_transitions=$state_transitions_initializer"
for literal_id in "${!state_transitions[@]}"; do
local literal="${literals[$literal_id]}"
if [[ $literal = "${prefix}"* ]]; then
local completion=${literal#"$superfluous_prefix"}
COMPREPLY+=("$completion ")
fi
done
fi
declare -A commands
commands=([3]=0)
if [[ -v "commands[$state]" ]]; then
local command_id=${commands[$state]}
local completions=()
mapfile -t completions < <(_hyprpm_cmd_${command_id} "$prefix" | cut -f1)
for item in "${completions[@]}"; do
if [[ $item = "${prefix}"* ]]; then
COMPREPLY+=("$item")
fi
done
fi
return 0
}
complete -o nospace -F _hyprpm hyprpm

109
hyprpm/hyprpm.fish Normal file
View File

@@ -0,0 +1,109 @@
function _hyprpm_1
set 1 $argv[1]
hyprpm list | grep Plugin | awk '{print $4}'
end
function _hyprpm
set COMP_LINE (commandline --cut-at-cursor)
set COMP_WORDS
echo $COMP_LINE | read --tokenize --array COMP_WORDS
if string match --quiet --regex '.*\s$' $COMP_LINE
set COMP_CWORD (math (count $COMP_WORDS) + 1)
else
set COMP_CWORD (count $COMP_WORDS)
end
set --local literals "-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f"
set --local descriptions
set descriptions[1] "Send a hyprland notification for important events (e.g. load fail)"
set descriptions[3] "List all installed plugins"
set descriptions[4] "Unload a plugin"
set descriptions[5] "Show help menu"
set descriptions[6] "Check and update all plugins if needed"
set descriptions[7] "Install a new plugin repository from git"
set descriptions[8] "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[11] "Remove a plugin repository"
set descriptions[12] "Load a plugin"
set descriptions[13] "Send a hyprland notification for important events (e.g. load fail)"
set descriptions[14] "Show help menu"
set descriptions[15] "Reload all plugins"
set descriptions[16] "Force an operation ignoring checks (e.g. update -f)"
set --local 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[2] "set inputs 11 12 4 3 15 6 7; set tos 3 4 4 3 3 3 3"
set literal_transitions[5] "set inputs 2; set tos 6"
set literal_transitions[6] "set inputs 1 13; set tos 7 7"
set --local match_anything_transitions_from 4 3 1 2
set --local match_anything_transitions_to 3 5 2 2
set --local state 1
set --local word_index 2
while test $word_index -lt $COMP_CWORD
set --local -- word $COMP_WORDS[$word_index]
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
set --local --erase inputs
set --local --erase tos
eval $literal_transitions[$state]
if contains -- $word $literals
set --local literal_matched 0
for literal_id in (seq 1 (count $literals))
if test $literals[$literal_id] = $word
set --local index (contains --index -- $literal_id $inputs)
set state $tos[$index]
set word_index (math $word_index + 1)
set literal_matched 1
break
end
end
if test $literal_matched -ne 0
continue
end
end
end
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 state $match_anything_transitions_to[$index]
set word_index (math $word_index + 1)
continue
end
return 1
end
if set --query literal_transitions[$state] && test -n $literal_transitions[$state]
set --local --erase inputs
set --local --erase tos
eval $literal_transitions[$state]
for literal_id in $inputs
if test -n $descriptions[$literal_id]
printf '%s\t%s\n' $literals[$literal_id] $descriptions[$literal_id]
else
printf '%s\n' $literals[$literal_id]
end
end
end
set command_states 4
set command_ids 1
if contains $state $command_states
set --local index (contains --index $state $command_states)
set --local function_id $command_ids[$index]
set --local function_name _hyprpm_$function_id
set --local --erase inputs
set --local --erase tos
$function_name "$COMP_WORDS[$COMP_CWORD]"
end
return 0
end
complete --command hyprpm --no-files --arguments "(_hyprpm)"

19
hyprpm/hyprpm.usage Normal file
View File

@@ -0,0 +1,19 @@
hyprpm [<FLAGS>]... <ARGUMENT>
<FLAGS> ::= (--notify | -n) "Send a hyprland notification for important events (e.g. load fail)"
| (--help | -h) "Show help menu"
| (--verbose | -v) "Enable too much loggin"
| (--force | -f) "Force an operation ignoring checks (e.g. update -f)"
;
<ARGUMENT> ::= (add) "Install a new plugin repository from git"
| (remove) "Remove a plugin repository"
| (update) "Check and update all plugins if needed"
| (list) "List all installed plugins"
| (enable <PLUGINS>) "Load a plugin"
| (disable <PLUGINS>) "Unload a plugin"
| (reload) "Reload all plugins"
;
<PLUGINS> ::= {{{ hyprpm list | grep Plugin | awk '{print $4}' }}};

151
hyprpm/hyprpm.zsh Normal file
View File

@@ -0,0 +1,151 @@
#compdef hyprpm
_hyprpm_cmd_0 () {
hyprpm list | grep Plugin | awk '{print $4}'
}
_hyprpm () {
local -a literals=("-n" "::=" "list" "disable" "--help" "update" "add" "--verbose" "-v" "--force" "remove" "enable" "--notify" "-h" "reload" "-f")
local -A descriptions
descriptions[1]="Send a hyprland notification for important events (e.g. load fail)"
descriptions[3]="List all installed plugins"
descriptions[4]="Unload a plugin"
descriptions[5]="Show help menu"
descriptions[6]="Check and update all plugins if needed"
descriptions[7]="Install a new plugin repository from git"
descriptions[8]="Enable too much loggin"
descriptions[9]="Enable too much loggin"
descriptions[10]="Force an operation ignoring checks (e.g. update -f)"
descriptions[11]="Remove a plugin repository"
descriptions[12]="Load a plugin"
descriptions[13]="Send a hyprland notification for important events (e.g. load fail)"
descriptions[14]="Show help menu"
descriptions[15]="Reload all plugins"
descriptions[16]="Force an operation ignoring checks (e.g. update -f)"
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[2]="([11]=3 [12]=4 [4]=4 [3]=3 [15]=3 [6]=3 [7]=3)"
literal_transitions[5]="([2]=6)"
literal_transitions[6]="([1]=7 [13]=7)"
local -A match_anything_transitions
match_anything_transitions=([4]=3 [3]=5 [1]=2 [2]=2)
declare -A subword_transitions
local state=1
local word_index=2
while [[ $word_index -lt $CURRENT ]]; do
if [[ -v "literal_transitions[$state]" ]]; then
local -A state_transitions
eval "state_transitions=${literal_transitions[$state]}"
local word=${words[$word_index]}
local word_matched=0
for ((literal_id = 1; literal_id <= $#literals; literal_id++)); do
if [[ ${literals[$literal_id]} = "$word" ]]; then
if [[ -v "state_transitions[$literal_id]" ]]; then
state=${state_transitions[$literal_id]}
word_index=$((word_index + 1))
word_matched=1
break
fi
fi
done
if [[ $word_matched -ne 0 ]]; then
continue
fi
fi
if [[ -v "match_anything_transitions[$state]" ]]; then
state=${match_anything_transitions[$state]}
word_index=$((word_index + 1))
continue
fi
return 1
done
completions_no_description_trailing_space=()
completions_no_description_no_trailing_space=()
completions_trailing_space=()
suffixes_trailing_space=()
descriptions_trailing_space=()
completions_no_trailing_space=()
suffixes_no_trailing_space=()
descriptions_no_trailing_space=()
if [[ -v "literal_transitions[$state]" ]]; then
local -A state_transitions
eval "state_transitions=${literal_transitions[$state]}"
for literal_id in ${(k)state_transitions}; do
if [[ -v "descriptions[$literal_id]" ]]; then
completions_trailing_space+=("${literals[$literal_id]}")
suffixes_trailing_space+=("${literals[$literal_id]}")
descriptions_trailing_space+=("${descriptions[$literal_id]}")
else
completions_no_description_trailing_space+=("${literals[$literal_id]}")
fi
done
fi
local -A commands=([4]=0)
if [[ -v "commands[$state]" ]]; then
local command_id=${commands[$state]}
local output=$(_hyprpm_cmd_${command_id} "${words[$CURRENT]}")
local -a command_completions=("${(@f)output}")
for line in ${command_completions[@]}; do
local parts=(${(@s: :)line})
if [[ -v "parts[2]" ]]; then
completions_trailing_space+=("${parts[1]}")
suffixes_trailing_space+=("${parts[1]}")
descriptions_trailing_space+=("${parts[2]}")
else
completions_no_description_trailing_space+=("${parts[1]}")
fi
done
fi
local maxlen=0
for suffix in ${suffixes_trailing_space[@]}; do
if [[ ${#suffix} -gt $maxlen ]]; then
maxlen=${#suffix}
fi
done
for suffix in ${suffixes_no_trailing_space[@]}; do
if [[ ${#suffix} -gt $maxlen ]]; then
maxlen=${#suffix}
fi
done
for ((i = 1; i <= $#suffixes_trailing_space; i++)); do
if [[ -z ${descriptions_trailing_space[$i]} ]]; then
descriptions_trailing_space[$i]="${(r($maxlen)( ))${suffixes_trailing_space[$i]}}"
else
descriptions_trailing_space[$i]="${(r($maxlen)( ))${suffixes_trailing_space[$i]}} -- ${descriptions_trailing_space[$i]}"
fi
done
for ((i = 1; i <= $#suffixes_no_trailing_space; i++)); do
if [[ -z ${descriptions_no_trailing_space[$i]} ]]; then
descriptions_no_trailing_space[$i]="${(r($maxlen)( ))${suffixes_no_trailing_space[$i]}}"
else
descriptions_no_trailing_space[$i]="${(r($maxlen)( ))${suffixes_no_trailing_space[$i]}} -- ${descriptions_no_trailing_space[$i]}"
fi
done
compadd -Q -a completions_no_description_trailing_space
compadd -Q -S ' ' -a completions_no_description_no_trailing_space
compadd -l -Q -a -d descriptions_trailing_space completions_trailing_space
compadd -l -Q -S '' -a -d descriptions_no_trailing_space completions_no_trailing_space
return 0
}
if [[ $ZSH_EVAL_CONTEXT =~ :file$ ]]; then
compdef _hyprpm hyprpm
else
_hyprpm
fi

View File

@@ -0,0 +1,245 @@
#include "DataState.hpp"
#include <toml++/toml.hpp>
#include <iostream>
#include <filesystem>
#include <fstream>
#include "PluginManager.hpp"
std::string DataState::getDataStatePath() {
const auto HOME = getenv("HOME");
if (!HOME) {
std::cerr << "DataState: no $HOME\n";
throw std::runtime_error("no $HOME");
return "";
}
const auto XDG_DATA_HOME = getenv("XDG_DATA_HOME");
if (XDG_DATA_HOME)
return std::string{XDG_DATA_HOME} + "/hyprpm";
return std::string{HOME} + "/.local/share/hyprpm";
}
std::string DataState::getHeadersPath() {
return getDataStatePath() + "/headersRoot";
}
void DataState::ensureStateStoreExists() {
const auto PATH = getDataStatePath();
if (!std::filesystem::exists(PATH))
std::filesystem::create_directories(PATH);
if (!std::filesystem::exists(getHeadersPath()))
std::filesystem::create_directories(getHeadersPath());
}
void DataState::addNewPluginRepo(const SPluginRepository& repo) {
ensureStateStoreExists();
const auto PATH = getDataStatePath() + "/" + repo.name;
std::filesystem::create_directories(PATH);
// clang-format off
auto DATA = toml::table{
{"repository", toml::table{
{"name", repo.name},
{"hash", repo.hash},
{"url", repo.url},
{"rev", repo.rev}
}}
};
for (auto& p : repo.plugins) {
// copy .so to the good place
if (std::filesystem::exists(p.filename))
std::filesystem::copy_file(p.filename, PATH + "/" + p.name + ".so");
DATA.emplace(p.name, toml::table{
{"filename", p.name + ".so"},
{"enabled", p.enabled},
{"failed", p.failed}
});
}
// clang-format on
std::ofstream ofs(PATH + "/state.toml", std::ios::trunc);
ofs << DATA;
ofs.close();
}
bool DataState::pluginRepoExists(const std::string& urlOrName) {
ensureStateStoreExists();
const auto PATH = getDataStatePath();
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
if (!entry.is_directory() || entry.path().stem() == "headersRoot")
continue;
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
continue;
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
const auto NAME = STATE["repository"]["name"].value_or("");
const auto URL = STATE["repository"]["url"].value_or("");
if (URL == urlOrName || NAME == urlOrName)
return true;
}
return false;
}
void DataState::removePluginRepo(const std::string& urlOrName) {
ensureStateStoreExists();
const auto PATH = getDataStatePath();
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
if (!entry.is_directory() || entry.path().stem() == "headersRoot")
continue;
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
continue;
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
const auto NAME = STATE["repository"]["name"].value_or("");
const auto URL = STATE["repository"]["url"].value_or("");
if (URL == urlOrName || NAME == urlOrName) {
// unload the plugins!!
for (const auto& file : std::filesystem::directory_iterator(entry.path())) {
if (!file.path().string().ends_with(".so"))
continue;
g_pPluginManager->loadUnloadPlugin(std::filesystem::absolute(file.path()), false);
}
std::filesystem::remove_all(entry.path());
return;
}
}
}
void DataState::updateGlobalState(const SGlobalState& state) {
ensureStateStoreExists();
const auto PATH = getDataStatePath();
std::filesystem::create_directories(PATH);
// clang-format off
auto DATA = toml::table{
{"state", toml::table{
{"hash", state.headersHashCompiled},
{"dont_warn_install", state.dontWarnInstall}
}}
};
// clang-format on
std::ofstream ofs(PATH + "/state.toml", std::ios::trunc);
ofs << DATA;
ofs.close();
}
SGlobalState DataState::getGlobalState() {
ensureStateStoreExists();
const auto PATH = getDataStatePath();
if (!std::filesystem::exists(PATH + "/state.toml"))
return SGlobalState{};
auto DATA = toml::parse_file(PATH + "/state.toml");
SGlobalState state;
state.headersHashCompiled = DATA["state"]["hash"].value_or("");
state.dontWarnInstall = DATA["state"]["dont_warn_install"].value_or(false);
return state;
}
std::vector<SPluginRepository> DataState::getAllRepositories() {
ensureStateStoreExists();
const auto PATH = getDataStatePath();
std::vector<SPluginRepository> repos;
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
if (!entry.is_directory() || entry.path().stem() == "headersRoot")
continue;
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
continue;
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
const auto NAME = STATE["repository"]["name"].value_or("");
const auto URL = STATE["repository"]["url"].value_or("");
const auto REV = STATE["repository"]["rev"].value_or("");
const auto HASH = STATE["repository"]["hash"].value_or("");
SPluginRepository repo;
repo.hash = HASH;
repo.name = NAME;
repo.url = URL;
repo.rev = REV;
for (const auto& [key, val] : STATE) {
if (key == "repository")
continue;
const auto ENABLED = STATE[key]["enabled"].value_or(false);
const auto FAILED = STATE[key]["failed"].value_or(false);
const auto FILENAME = STATE[key]["filename"].value_or("");
repo.plugins.push_back(SPlugin{std::string{key.str()}, FILENAME, ENABLED, FAILED});
}
repos.push_back(repo);
}
return repos;
}
bool DataState::setPluginEnabled(const std::string& name, bool enabled) {
ensureStateStoreExists();
const auto PATH = getDataStatePath();
for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
if (!entry.is_directory() || entry.path().stem() == "headersRoot")
continue;
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
continue;
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
for (const auto& [key, val] : STATE) {
if (key == "repository")
continue;
if (key.str() != name)
continue;
const auto FAILED = STATE[key]["failed"].value_or(false);
if (FAILED)
return false;
(*STATE[key].as_table()).insert_or_assign("enabled", enabled);
std::ofstream state(entry.path().string() + "/state.toml", std::ios::trunc);
state << STATE;
state.close();
return true;
}
}
return false;
}

View File

@@ -0,0 +1,22 @@
#pragma once
#include <string>
#include <vector>
#include "Plugin.hpp"
struct SGlobalState {
std::string headersHashCompiled = "";
bool dontWarnInstall = false;
};
namespace DataState {
std::string getDataStatePath();
std::string getHeadersPath();
void ensureStateStoreExists();
void addNewPluginRepo(const SPluginRepository& repo);
void removePluginRepo(const std::string& urlOrName);
bool pluginRepoExists(const std::string& urlOrName);
void updateGlobalState(const SGlobalState& state);
SGlobalState getGlobalState();
bool setPluginEnabled(const std::string& name, bool enabled);
std::vector<SPluginRepository> getAllRepositories();
};

View File

@@ -0,0 +1,105 @@
#include "Manifest.hpp"
#include <toml++/toml.hpp>
#include <iostream>
CManifest::CManifest(const eManifestType type, const std::string& path) {
auto manifest = toml::parse_file(path);
if (type == MANIFEST_HYPRLOAD) {
for (auto& [key, val] : manifest) {
if (key.str().ends_with(".build"))
continue;
CManifest::SManifestPlugin plugin;
plugin.name = key;
m_vPlugins.push_back(plugin);
}
for (auto& plugin : m_vPlugins) {
plugin.description = manifest[plugin.name]["description"].value_or("?");
plugin.version = manifest[plugin.name]["version"].value_or("?");
plugin.output = manifest[plugin.name]["build"]["output"].value_or("?");
auto authors = manifest[plugin.name]["authors"].as_array();
if (authors) {
for (auto&& a : *authors) {
plugin.authors.push_back(a.as_string()->value_or("?"));
}
} else {
auto author = manifest[plugin.name]["author"].value_or("");
if (!std::string{author}.empty())
plugin.authors.push_back(author);
}
auto buildSteps = manifest[plugin.name]["build"]["steps"].as_array();
if (buildSteps) {
for (auto&& s : *buildSteps) {
plugin.buildSteps.push_back(s.as_string()->value_or("?"));
}
}
if (plugin.output.empty() || plugin.buildSteps.empty()) {
m_bGood = false;
return;
}
}
} else if (type == MANIFEST_HYPRPM) {
m_sRepository.name = manifest["repository"]["name"].value_or("");
auto authors = manifest["repository"]["authors"].as_array();
if (authors) {
for (auto&& a : *authors) {
m_sRepository.authors.push_back(a.as_string()->value_or("?"));
}
} else {
auto author = manifest["repository"]["author"].value_or("");
if (!std::string{author}.empty())
m_sRepository.authors.push_back(author);
}
auto pins = manifest["repository"]["commit_pins"].as_array();
if (pins) {
for (auto&& pin : *pins) {
auto pinArr = pin.as_array();
if (pinArr && pinArr->get(1))
m_sRepository.commitPins.push_back(std::make_pair<>(pinArr->get(0)->as_string()->get(), pinArr->get(1)->as_string()->get()));
}
}
for (auto& [key, val] : manifest) {
if (key.str() == "repository")
continue;
CManifest::SManifestPlugin plugin;
plugin.name = key;
m_vPlugins.push_back(plugin);
}
for (auto& plugin : m_vPlugins) {
plugin.description = manifest[plugin.name]["description"].value_or("?");
plugin.output = manifest[plugin.name]["output"].value_or("?");
plugin.since = manifest[plugin.name]["since_hyprland"].value_or(0);
auto authors = manifest[plugin.name]["authors"].as_array();
if (authors) {
for (auto&& a : *authors) {
plugin.authors.push_back(a.as_string()->value_or("?"));
}
} else {
auto author = manifest[plugin.name]["author"].value_or("");
if (!std::string{author}.empty())
plugin.authors.push_back(author);
}
auto buildSteps = manifest[plugin.name]["build"].as_array();
if (buildSteps) {
for (auto&& s : *buildSteps) {
plugin.buildSteps.push_back(s.as_string()->value_or("?"));
}
}
if (plugin.output.empty() || plugin.buildSteps.empty()) {
m_bGood = false;
return;
}
}
} else {
// ???
m_bGood = false;
}
}

View File

@@ -0,0 +1,34 @@
#pragma once
#include <string>
#include <vector>
enum eManifestType {
MANIFEST_HYPRLOAD,
MANIFEST_HYPRPM
};
class CManifest {
public:
CManifest(const eManifestType type, const std::string& path);
struct SManifestPlugin {
std::string name;
std::string description;
std::string version;
std::vector<std::string> authors;
std::vector<std::string> buildSteps;
std::string output;
int since = 0;
bool failed = false;
};
struct {
std::string name;
std::vector<std::string> authors;
std::vector<std::pair<std::string, std::string>> commitPins;
} m_sRepository;
std::vector<SManifestPlugin> m_vPlugins;
bool m_bGood = true;
};

View File

@@ -0,0 +1,19 @@
#pragma once
#include <string>
#include <vector>
struct SPlugin {
std::string name;
std::string filename;
bool enabled = false;
bool failed = false;
};
struct SPluginRepository {
std::string url;
std::string rev;
std::string name;
std::vector<SPlugin> plugins;
std::string hash;
};

View File

@@ -0,0 +1,819 @@
#include "PluginManager.hpp"
#include "../helpers/Colors.hpp"
#include "../progress/CProgressBar.hpp"
#include "Manifest.hpp"
#include "DataState.hpp"
#include <iostream>
#include <array>
#include <filesystem>
#include <thread>
#include <fstream>
#include <algorithm>
#include <format>
#include <toml++/toml.hpp>
static std::string removeBeginEndSpacesTabs(std::string str) {
if (str.empty())
return str;
int countBefore = 0;
while (str[countBefore] == ' ' || str[countBefore] == '\t') {
countBefore++;
}
int countAfter = 0;
while ((int)str.length() - countAfter - 1 >= 0 && (str[str.length() - countAfter - 1] == ' ' || str[str.length() - 1 - countAfter] == '\t')) {
countAfter++;
}
str = str.substr(countBefore, str.length() - countBefore - countAfter);
return str;
}
static std::string execAndGet(std::string cmd) {
cmd += " 2>&1";
std::array<char, 128> buffer;
std::string result;
const std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
if (!pipe)
return "";
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
result += buffer.data();
}
return result;
}
SHyprlandVersion CPluginManager::getHyprlandVersion() {
static SHyprlandVersion ver;
static bool once = false;
if (once)
return ver;
once = true;
const auto HLVERCALL = execAndGet("hyprctl version");
if (m_bVerbose)
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "version returned: " << HLVERCALL << "\n";
if (!HLVERCALL.contains("Tag:")) {
std::cerr << "\n" << Colors::RED << "" << Colors::RESET << " You don't seem to be running Hyprland.";
return SHyprlandVersion{};
}
std::string hlcommit = HLVERCALL.substr(HLVERCALL.find("at commit") + 10);
hlcommit = hlcommit.substr(0, hlcommit.find_first_of(' '));
std::string hlbranch = HLVERCALL.substr(HLVERCALL.find("from branch") + 12);
hlbranch = hlbranch.substr(0, hlbranch.find(" at commit "));
std::string hldate = HLVERCALL.substr(HLVERCALL.find("Date: ") + 6);
hldate = hldate.substr(0, hldate.find("\n"));
std::string hlcommits;
if (HLVERCALL.contains("commits:")) {
hlcommits = HLVERCALL.substr(HLVERCALL.find("commits:") + 9);
hlcommits = hlcommits.substr(0, hlcommits.find(" "));
}
int commits = 0;
try {
commits = std::stoi(hlcommits);
} catch (...) { ; }
if (m_bVerbose)
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "parsed commit " << hlcommit << " at branch " << hlbranch << " on " << hldate << ", commits " << commits << "\n";
ver = SHyprlandVersion{hlbranch, hlcommit, hldate, commits};
return ver;
}
bool CPluginManager::addNewPluginRepo(const std::string& url, const std::string& rev) {
const auto HLVER = getHyprlandVersion();
if (DataState::pluginRepoExists(url)) {
std::cerr << "\n" << Colors::RED << "" << Colors::RESET << " Could not clone the plugin repository. Repository already installed.\n";
return false;
}
auto GLOBALSTATE = DataState::getGlobalState();
if (!GLOBALSTATE.dontWarnInstall) {
std::cout << Colors::YELLOW << "!" << Colors::RED << " Disclaimer:\n " << Colors::RESET
<< "plugins, especially not official, have no guarantee of stability, availablity or security.\n Run them at your own risk.\n "
<< "This message will not appear again.\n";
GLOBALSTATE.dontWarnInstall = true;
DataState::updateGlobalState(GLOBALSTATE);
}
std::cout << Colors::GREEN << "" << Colors::RESET << Colors::RED << " adding a new plugin repository " << Colors::RESET << "from " << url << "\n " << Colors::RED
<< "MAKE SURE" << Colors::RESET << " that you trust the authors. " << Colors::RED << "DO NOT" << Colors::RESET
<< " install random plugins without verifying the code and author.\n "
<< "Are you sure? [Y/n] ";
std::fflush(stdout);
std::string input;
std::getline(std::cin, input);
if (input.size() > 0 && input[0] != 'Y' && input[0] != 'y') {
std::cout << "Aborting.\n";
return false;
}
CProgressBar progress;
progress.m_iMaxSteps = 5;
progress.m_iSteps = 0;
progress.m_szCurrentMessage = "Cloning the plugin repository";
progress.print();
if (!std::filesystem::exists("/tmp/hyprpm")) {
std::filesystem::create_directory("/tmp/hyprpm");
std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace);
}
if (std::filesystem::exists("/tmp/hyprpm/new")) {
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " old plugin repo build files found in temp directory, removing.");
std::filesystem::remove_all("/tmp/hyprpm/new");
}
progress.printMessageAbove(std::string{Colors::RESET} + " → Cloning " + url);
std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + url + " new");
if (!std::filesystem::exists("/tmp/hyprpm/new")) {
std::cerr << "\n" << Colors::RED << "" << Colors::RESET << " Could not clone the plugin repository. shell returned:\n" << ret << "\n";
return false;
}
if (!rev.empty()) {
std::string ret = execAndGet("git -C /tmp/hyprpm/new reset --hard --recurse-submodules " + rev);
if (ret.compare(0, 6, "fatal:") == 0) {
std::cerr << "\n" << Colors::RED << "" << Colors::RESET << " Could not check out revision " << rev << ". shell returned:\n" << ret << "\n";
return false;
}
}
progress.m_iSteps = 1;
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " cloned");
progress.m_szCurrentMessage = "Reading the manifest";
progress.print();
std::unique_ptr<CManifest> pManifest;
if (std::filesystem::exists("/tmp/hyprpm/new/hyprpm.toml")) {
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " found hyprpm manifest");
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRPM, "/tmp/hyprpm/new/hyprpm.toml");
} else if (std::filesystem::exists("/tmp/hyprpm/new/hyprload.toml")) {
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " found hyprload manifest");
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRLOAD, "/tmp/hyprpm/new/hyprload.toml");
}
if (!pManifest) {
std::cerr << "\n" << Colors::RED << "" << Colors::RESET << " The provided plugin repository does not have a valid manifest\n";
return false;
}
if (!pManifest->m_bGood) {
std::cerr << "\n" << Colors::RED << "" << Colors::RESET << " The provided plugin repository has a corrupted manifest\n";
return false;
}
progress.m_iSteps = 2;
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) {
std::string message = std::string{Colors::RESET} + "" + pl.name + " by ";
for (auto& a : pl.authors) {
message += a + ", ";
}
if (pl.authors.size() > 0) {
message.pop_back();
message.pop_back();
}
message += " version " + pl.version;
progress.printMessageAbove(message);
}
if (!pManifest->m_sRepository.commitPins.empty()) {
// check commit pins
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) {
if (hl != HLVER.hash)
continue;
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " commit pin " + plugin + " matched hl, resetting");
execAndGet("cd /tmp/hyprpm/new/ && git reset --hard --recurse-submodules " + plugin);
}
}
progress.m_szCurrentMessage = "Verifying headers";
progress.print();
const auto HEADERSSTATUS = headersValid();
if (HEADERSSTATUS != HEADERS_OK) {
std::cerr << "\n" << headerError(HEADERSSTATUS);
return false;
}
progress.m_iSteps = 3;
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " Hyprland headers OK");
progress.m_szCurrentMessage = "Building plugin(s)";
progress.print();
for (auto& p : pManifest->m_vPlugins) {
std::string out;
if (p.since > HLVER.commits && HLVER.commits >= 1 /* for --depth 1 clones, we can't check this. */) {
progress.printMessageAbove(std::string{Colors::RED} + "" + Colors::RESET + " Not building " + p.name + ": your Hyprland version is too old.\n");
p.failed = true;
continue;
}
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
for (auto& bs : p.buildSteps) {
std::string cmd = std::format("cd /tmp/hyprpm/new && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", DataState::getHeadersPath(), bs);
out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n";
}
if (m_bVerbose)
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n";
if (!std::filesystem::exists("/tmp/hyprpm/new/" + p.output)) {
progress.printMessageAbove(std::string{Colors::RED} + "" + Colors::RESET + " Plugin " + p.name + " failed to build.\n" +
" This likely means that the plugin is either outdated, not yet available for your version, or broken.\n If you are on -git, update "
"first.\n Try re-running with -v to see "
"more verbose output.\n");
p.failed = true;
continue;
}
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " built " + p.name + " into " + p.output);
}
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " all plugins built");
progress.m_iSteps = 4;
progress.m_szCurrentMessage = "Installing repository";
progress.print();
// add repo toml to DataState
SPluginRepository repo;
std::string repohash = execAndGet("cd /tmp/hyprpm/new/ && git rev-parse HEAD");
if (repohash.length() > 0)
repohash.pop_back();
repo.name = pManifest->m_sRepository.name.empty() ? url.substr(url.find_last_of('/') + 1) : pManifest->m_sRepository.name;
repo.url = url;
repo.rev = rev;
repo.hash = repohash;
for (auto& p : pManifest->m_vPlugins) {
repo.plugins.push_back(SPlugin{p.name, "/tmp/hyprpm/new/" + p.output, false, p.failed});
}
DataState::addNewPluginRepo(repo);
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " installed repository");
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " you can now enable the plugin(s) with hyprpm enable");
progress.m_iSteps = 5;
progress.m_szCurrentMessage = "Done!";
progress.print();
std::cout << "\n";
// remove build files
std::filesystem::remove_all("/tmp/hyprpm/new");
return true;
}
bool CPluginManager::removePluginRepo(const std::string& urlOrName) {
if (!DataState::pluginRepoExists(urlOrName)) {
std::cerr << "\n" << Colors::RED << "" << Colors::RESET << " Could not remove the repository. Repository is not installed.\n";
return false;
}
std::cout << Colors::YELLOW << "!" << Colors::RESET << Colors::RED << " removing a plugin repository: " << Colors::RESET << urlOrName << "\n "
<< "Are you sure? [Y/n] ";
std::fflush(stdout);
std::string input;
std::getline(std::cin, input);
if (input.size() > 0 && input[0] != 'Y' && input[0] != 'y') {
std::cout << "Aborting.\n";
return false;
}
DataState::removePluginRepo(urlOrName);
return true;
}
eHeadersErrors CPluginManager::headersValid() {
const auto HLVER = getHyprlandVersion();
if (!std::filesystem::exists(DataState::getHeadersPath() + "/share/pkgconfig/hyprland.pc"))
return HEADERS_MISSING;
// find headers commit
std::string cmd = std::format("PKG_CONFIG_PATH=\"{}/share/pkgconfig\" pkgconf --cflags --keep-system-cflags hyprland", DataState::getHeadersPath());
auto headers = execAndGet(cmd.c_str());
if (!headers.contains("-I/"))
return HEADERS_MISSING;
headers.pop_back(); // pop newline
std::string verHeader = "";
while (!headers.empty()) {
const auto PATH = headers.substr(0, headers.find(" -I/", 3));
if (headers.find(" -I/", 3) != std::string::npos)
headers = headers.substr(headers.find("-I/", 3));
else
headers = "";
if (PATH.ends_with("protocols") || PATH.ends_with("wlroots-hyprland"))
continue;
verHeader = removeBeginEndSpacesTabs(PATH.substr(2)) + "/hyprland/src/version.h";
break;
}
if (verHeader.empty())
return HEADERS_CORRUPTED;
// read header
std::ifstream ifs(verHeader);
if (!ifs.good())
return HEADERS_CORRUPTED;
std::string verHeaderContent((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
ifs.close();
const auto HASHPOS = verHeaderContent.find("#define GIT_COMMIT_HASH");
if (HASHPOS == std::string::npos || HASHPOS + 23 >= verHeaderContent.length())
return HEADERS_CORRUPTED;
std::string hash = verHeaderContent.substr(HASHPOS + 23);
hash = hash.substr(0, hash.find_first_of('\n'));
hash = hash.substr(hash.find_first_of('"') + 1);
hash = hash.substr(0, hash.find_first_of('"'));
if (hash != HLVER.hash)
return HEADERS_MISMATCHED;
return HEADERS_OK;
}
bool CPluginManager::updateHeaders(bool force) {
DataState::ensureStateStoreExists();
const auto HLVER = getHyprlandVersion();
if (!std::filesystem::exists("/tmp/hyprpm")) {
std::filesystem::create_directory("/tmp/hyprpm");
std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace);
}
if (!force && headersValid() == HEADERS_OK) {
std::cout << "\n" << std::string{Colors::GREEN} + "" + Colors::RESET + " Headers up to date.\n";
return true;
}
CProgressBar progress;
progress.m_iMaxSteps = 5;
progress.m_iSteps = 0;
progress.m_szCurrentMessage = "Cloning the hyprland repository";
progress.print();
if (std::filesystem::exists("/tmp/hyprpm/hyprland")) {
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " old hyprland source files found in temp directory, removing.");
std::filesystem::remove_all("/tmp/hyprpm/hyprland");
}
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " Cloning https://github.com/hyprwm/hyprland, this might take a moment.");
std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland --shallow-since='" + HLVER.date + "'");
if (!std::filesystem::exists("/tmp/hyprpm/hyprland")) {
std::cerr << "\n" << Colors::RED << "" << Colors::RESET << " Could not clone the hyprland repository. shell returned:\n" << ret << "\n";
return false;
}
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " cloned");
progress.m_iSteps = 2;
progress.m_szCurrentMessage = "Checking out sources";
progress.print();
ret = execAndGet("cd /tmp/hyprpm/hyprland && git checkout " + HLVER.branch +
" 2>&1 && git rm subprojects/tracy && git submodule update --init 2>&1 && git reset --hard --recurse-submodules " + HLVER.hash);
if (m_bVerbose)
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned: " + ret);
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " checked out to running ver");
progress.m_iSteps = 3;
progress.m_szCurrentMessage = "Building Hyprland";
progress.print();
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " configuring Hyprland");
if (m_bVerbose)
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "setting PREFIX for cmake to " + DataState::getHeadersPath());
ret = execAndGet(
std::format("cd /tmp/hyprpm/hyprland && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=\"{}\" -S . -B ./build -G Ninja",
DataState::getHeadersPath()));
if (m_bVerbose)
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "cmake returned: " + ret);
// le hack. Wlroots has to generate its build/include
ret = execAndGet("cd /tmp/hyprpm/hyprland/subprojects/wlroots-hyprland && meson setup -Drenderers=gles2 -Dexamples=false build");
if (m_bVerbose)
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "meson returned: " + ret);
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " configured Hyprland");
progress.m_iSteps = 4;
progress.m_szCurrentMessage = "Installing sources";
progress.print();
std::string cmd = std::format("sed -i -e \"s#PREFIX = /usr/local#PREFIX = {}#\" /tmp/hyprpm/hyprland/Makefile && cd /tmp/hyprpm/hyprland && make installheaders",
DataState::getHeadersPath());
if (m_bVerbose)
progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "installation will run: " + cmd);
ret = execAndGet(cmd);
if (m_bVerbose)
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "installer returned: " << ret << "\n";
// remove build files
std::filesystem::remove_all("/tmp/hyprpm/hyprland");
auto HEADERSVALID = headersValid();
if (HEADERSVALID == HEADERS_OK) {
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " installed headers");
progress.m_iSteps = 5;
progress.m_szCurrentMessage = "Done!";
progress.print();
std::cout << "\n";
} else {
progress.printMessageAbove(std::string{Colors::RED} + "" + Colors::RESET + " failed to install headers with error code " + std::to_string((int)HEADERSVALID));
progress.m_iSteps = 5;
progress.m_szCurrentMessage = "Failed";
progress.print();
std::cout << "\n";
std::cerr << "\n" << headerError(HEADERSVALID);
return false;
}
return true;
}
bool CPluginManager::updatePlugins(bool forceUpdateAll) {
if (headersValid() != HEADERS_OK) {
std::cout << "\n" << std::string{Colors::RED} + "" + Colors::RESET + " headers are not up-to-date, please run hyprpm update.\n";
return false;
}
const auto REPOS = DataState::getAllRepositories();
if (REPOS.size() < 1) {
std::cout << "\n" << std::string{Colors::RED} + "" + Colors::RESET + " No repos to update.\n";
return true;
}
const auto HLVER = getHyprlandVersion();
CProgressBar progress;
progress.m_iMaxSteps = REPOS.size() * 2 + 2;
progress.m_iSteps = 0;
progress.m_szCurrentMessage = "Updating repositories";
progress.print();
for (auto& repo : REPOS) {
bool update = forceUpdateAll;
progress.m_iSteps++;
progress.m_szCurrentMessage = "Updating " + repo.name;
progress.print();
progress.printMessageAbove(std::string{Colors::RESET} + " → checking for updates for " + repo.name);
if (std::filesystem::exists("/tmp/hyprpm/update")) {
progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " old update build files found in temp directory, removing.");
std::filesystem::remove_all("/tmp/hyprpm/update");
}
progress.printMessageAbove(std::string{Colors::RESET} + " → Cloning " + repo.url);
std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + repo.url + " update");
if (!std::filesystem::exists("/tmp/hyprpm/update")) {
std::cout << "\n" << std::string{Colors::RED} + "" + Colors::RESET + " could not clone repo: shell returned:\n" + ret;
return false;
}
if (!repo.rev.empty()) {
progress.printMessageAbove(std::string{Colors::RESET} + " → Plugin has revision set, resetting: " + repo.rev);
std::string ret = execAndGet("git -C /tmp/hyprpm/update reset --hard --recurse-submodules " + repo.rev);
if (ret.compare(0, 6, "fatal:") == 0) {
std::cout << "\n" << std::string{Colors::RED} + "" + Colors::RESET + " could not check out revision " + repo.rev + ": shell returned:\n" + ret;
return false;
}
}
if (!update) {
// check if git has updates
std::string hash = execAndGet("cd /tmp/hyprpm/update && git rev-parse HEAD");
if (!hash.empty())
hash.pop_back();
update = update || hash != repo.hash;
}
if (!update) {
std::filesystem::remove_all("/tmp/hyprpm/update");
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " repository " + repo.name + " is up-to-date.");
progress.m_iSteps++;
progress.print();
continue;
}
// we need to update
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " repository " + repo.name + " has updates.");
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + repo.name);
progress.m_iSteps++;
progress.print();
std::unique_ptr<CManifest> pManifest;
if (std::filesystem::exists("/tmp/hyprpm/update/hyprpm.toml")) {
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " found hyprpm manifest");
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRPM, "/tmp/hyprpm/update/hyprpm.toml");
} else if (std::filesystem::exists("/tmp/hyprpm/update/hyprload.toml")) {
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " found hyprload manifest");
pManifest = std::make_unique<CManifest>(MANIFEST_HYPRLOAD, "/tmp/hyprpm/update/hyprload.toml");
}
if (!pManifest) {
std::cerr << "\n" << Colors::RED << "" << Colors::RESET << " The provided plugin repository does not have a valid manifest\n";
continue;
}
if (!pManifest->m_bGood) {
std::cerr << "\n" << Colors::RED << "" << Colors::RESET << " The provided plugin repository has a corrupted manifest\n";
continue;
}
if (repo.rev.empty() && !pManifest->m_sRepository.commitPins.empty()) {
// check commit pins unless a revision is specified
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) {
if (hl != HLVER.hash)
continue;
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " commit pin " + plugin + " matched hl, resetting");
execAndGet("cd /tmp/hyprpm/update/ && git reset --hard --recurse-submodules " + plugin);
}
}
for (auto& p : pManifest->m_vPlugins) {
std::string out;
if (p.since > HLVER.commits && HLVER.commits >= 1 /* for --depth 1 clones, we can't check this. */) {
progress.printMessageAbove(std::string{Colors::RED} + "" + Colors::RESET + " Not building " + p.name + ": your Hyprland version is too old.\n");
p.failed = true;
continue;
}
progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name);
for (auto& bs : p.buildSteps) {
std::string cmd = std::format("cd /tmp/hyprpm/update && PKG_CONFIG_PATH=\"{}/share/pkgconfig\" {}", DataState::getHeadersPath(), bs);
out += " -> " + cmd + "\n" + execAndGet(cmd) + "\n";
}
if (m_bVerbose)
std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n";
if (!std::filesystem::exists("/tmp/hyprpm/update/" + p.output)) {
std::cerr << "\n"
<< Colors::RED << "" << Colors::RESET << " Plugin " << p.name << " failed to build.\n"
<< " This likely means that the plugin is either outdated, not yet available for your version, or broken.\n If you are on -git, update first.\n Try "
"re-running with -v to see more verbose "
"output.\n";
p.failed = true;
continue;
}
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " built " + p.name + " into " + p.output);
}
// add repo toml to DataState
SPluginRepository newrepo = repo;
newrepo.plugins.clear();
execAndGet(
"cd /tmp/hyprpm/update/ && git pull --recurse-submodules && git reset --hard --recurse-submodules"); // repo hash in the state.toml has to match head and not any pin
std::string repohash = execAndGet("cd /tmp/hyprpm/update && git rev-parse HEAD");
if (repohash.length() > 0)
repohash.pop_back();
newrepo.hash = repohash;
for (auto& p : pManifest->m_vPlugins) {
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, "/tmp/hyprpm/update/" + p.output, OLDPLUGINIT != repo.plugins.end() ? OLDPLUGINIT->enabled : false});
}
DataState::removePluginRepo(newrepo.name);
DataState::addNewPluginRepo(newrepo);
std::filesystem::remove_all("/tmp/hyprpm/update");
progress.printMessageAbove(std::string{Colors::GREEN} + "" + Colors::RESET + " updated " + repo.name);
}
progress.m_iSteps++;
progress.m_szCurrentMessage = "Updating global state...";
progress.print();
auto GLOBALSTATE = DataState::getGlobalState();
GLOBALSTATE.headersHashCompiled = HLVER.hash;
DataState::updateGlobalState(GLOBALSTATE);
progress.m_iSteps++;
progress.m_szCurrentMessage = "Done!";
progress.print();
std::cout << "\n";
return true;
}
bool CPluginManager::enablePlugin(const std::string& name) {
bool ret = DataState::setPluginEnabled(name, true);
if (ret)
std::cout << Colors::GREEN << "" << Colors::RESET << " Enabled " << name << "\n";
return ret;
}
bool CPluginManager::disablePlugin(const std::string& name) {
bool ret = DataState::setPluginEnabled(name, false);
if (ret)
std::cout << Colors::GREEN << "" << Colors::RESET << " Disabled " << name << "\n";
return ret;
}
ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
if (headersValid() != HEADERS_OK) {
std::cerr << "\n" << std::string{Colors::RED} + "" + Colors::RESET + " headers are not up-to-date, please run hyprpm update.\n";
return LOADSTATE_HEADERS_OUTDATED;
}
const auto HOME = getenv("HOME");
const auto HIS = getenv("HYPRLAND_INSTANCE_SIGNATURE");
if (!HOME || !HIS) {
std::cerr << "PluginManager: no $HOME or HIS\n";
return LOADSTATE_FAIL;
}
const auto HYPRPMPATH = DataState::getDataStatePath() + "/";
auto pluginLines = execAndGet("hyprctl plugins list | grep Plugin");
std::vector<std::string> loadedPlugins;
std::cout << Colors::GREEN << "" << Colors::RESET << " Ensuring plugin load state\n";
// iterate line by line
while (!pluginLines.empty()) {
auto plLine = pluginLines.substr(0, pluginLines.find("\n"));
if (pluginLines.find("\n") != std::string::npos)
pluginLines = pluginLines.substr(pluginLines.find("\n") + 1);
else
pluginLines = "";
if (plLine.back() != ':')
continue;
plLine = plLine.substr(7);
plLine = plLine.substr(0, plLine.find(" by "));
loadedPlugins.push_back(plLine);
}
// get state
const auto REPOS = DataState::getAllRepositories();
auto enabled = [REPOS](const std::string& plugin) -> bool {
for (auto& r : REPOS) {
for (auto& p : r.plugins) {
if (p.name == plugin && p.enabled)
return true;
}
}
return false;
};
auto repoForName = [REPOS](const std::string& name) -> std::string {
for (auto& r : REPOS) {
for (auto& p : r.plugins) {
if (p.name == name)
return r.name;
}
}
return "";
};
// unload disabled plugins
for (auto& p : loadedPlugins) {
if (!enabled(p)) {
// unload
loadUnloadPlugin(HYPRPMPATH + repoForName(p) + "/" + p + ".so", false);
std::cout << Colors::GREEN << "" << Colors::RESET << " Unloaded " << p << "\n";
}
}
// load enabled plugins
for (auto& r : REPOS) {
for (auto& p : r.plugins) {
if (!p.enabled)
continue;
if (std::find_if(loadedPlugins.begin(), loadedPlugins.end(), [&](const auto& other) { return other == p.name; }) != loadedPlugins.end())
continue;
loadUnloadPlugin(HYPRPMPATH + repoForName(p.name) + "/" + p.filename, true);
std::cout << Colors::GREEN << "" << Colors::RESET << " Loaded " << p.name << "\n";
}
}
std::cout << Colors::GREEN << "" << Colors::RESET << " Plugin load state ensured\n";
return LOADSTATE_OK;
}
bool CPluginManager::loadUnloadPlugin(const std::string& path, bool load) {
if (load)
execAndGet("hyprctl plugin load " + path);
else
execAndGet("hyprctl plugin unload " + path);
return true;
}
void CPluginManager::listAllPlugins() {
const auto REPOS = DataState::getAllRepositories();
for (auto& r : REPOS) {
std::cout << std::string{Colors::RESET} + " → Repository " + r.name + ":\n";
for (auto& p : r.plugins) {
std::cout << std::string{Colors::RESET} + " │ Plugin " + p.name;
if (!p.failed)
std::cout << "\n └─ enabled: " << (p.enabled ? Colors::GREEN : Colors::RED) << (p.enabled ? "true" : "false") << Colors::RESET << "\n";
else
std::cout << "\n └─ enabled: " << Colors::RED << "Plugin failed to build" << Colors::RESET << "\n";
}
}
}
void CPluginManager::notify(const eNotifyIcons icon, uint32_t color, int durationMs, const std::string& message) {
execAndGet("hyprctl notify " + std::to_string((int)icon) + " " + std::to_string(durationMs) + " " + std::to_string(color) + " " + message);
}
std::string CPluginManager::headerError(const eHeadersErrors err) {
switch (err) {
case HEADERS_CORRUPTED: return std::string{Colors::RED} + "" + Colors::RESET + " Headers corrupted. Please run hyprpm update to fix those.\n";
case HEADERS_MISMATCHED: return std::string{Colors::RED} + "" + Colors::RESET + " Headers version mismatch. Please run hyprpm update to fix those.\n";
case HEADERS_NOT_HYPRLAND: return std::string{Colors::RED} + "" + Colors::RESET + " It doesn't seem you are running on hyprland.\n";
case HEADERS_MISSING: return std::string{Colors::RED} + "" + Colors::RESET + " Headers missing. Please run hyprpm update to fix those.\n";
case HEADERS_DUPLICATED: {
return std::string{Colors::RED} + "" + Colors::RESET + " Headers duplicated!!! This is a very bad sign.\n" +
" This could be due to e.g. installing hyprland manually while a system package of hyprland is also installed.\n" +
" If the above doesn't apply, check your /usr/include and /usr/local/include directories\n and remove all the hyprland headers.\n";
}
default: break;
}
return std::string{Colors::RED} + "" + Colors::RESET + " Unknown header error. Please run hyprpm update to fix those.\n";
}

View File

@@ -0,0 +1,65 @@
#pragma once
#include <memory>
#include <string>
enum eHeadersErrors {
HEADERS_OK = 0,
HEADERS_NOT_HYPRLAND,
HEADERS_MISSING,
HEADERS_CORRUPTED,
HEADERS_MISMATCHED,
HEADERS_DUPLICATED
};
enum eNotifyIcons {
ICON_WARNING = 0,
ICON_INFO,
ICON_HINT,
ICON_ERROR,
ICON_CONFUSED,
ICON_OK,
ICON_NONE
};
enum ePluginLoadStateReturn {
LOADSTATE_OK = 0,
LOADSTATE_FAIL,
LOADSTATE_PARTIAL_FAIL,
LOADSTATE_HEADERS_OUTDATED
};
struct SHyprlandVersion {
std::string branch;
std::string hash;
std::string date;
int commits = 0;
};
class CPluginManager {
public:
bool addNewPluginRepo(const std::string& url, const std::string& rev);
bool removePluginRepo(const std::string& urlOrName);
eHeadersErrors headersValid();
bool updateHeaders(bool force = false);
bool updatePlugins(bool forceUpdateAll);
void listAllPlugins();
bool enablePlugin(const std::string& name);
bool disablePlugin(const std::string& name);
ePluginLoadStateReturn ensurePluginsLoadState();
bool loadUnloadPlugin(const std::string& path, bool load);
SHyprlandVersion getHyprlandVersion();
void notify(const eNotifyIcons icon, uint32_t color, int durationMs, const std::string& message);
bool m_bVerbose = false;
private:
std::string headerError(const eHeadersErrors err);
};
inline std::unique_ptr<CPluginManager> g_pPluginManager;

View File

@@ -0,0 +1,11 @@
#pragma once
namespace Colors {
constexpr const char* RED = "\x1b[31m";
constexpr const char* GREEN = "\x1b[32m";
constexpr const char* YELLOW = "\x1b[33m";
constexpr const char* BLUE = "\x1b[34m";
constexpr const char* MAGENTA = "\x1b[35m";
constexpr const char* CYAN = "\x1b[36m";
constexpr const char* RESET = "\x1b[0m";
};

164
hyprpm/src/main.cpp Normal file
View File

@@ -0,0 +1,164 @@
#include "progress/CProgressBar.hpp"
#include "helpers/Colors.hpp"
#include "core/PluginManager.hpp"
#include "core/DataState.hpp"
#include <iostream>
#include <vector>
#include <string>
#include <chrono>
#include <thread>
const std::string HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager
add [url] [git rev] Install a new plugin repository from git. Git revision
is optional, when set, commit locks are ignored.
remove [url/name] Remove an installed plugin repository
enable [name] Enable a plugin
disable [name] Disable a plugin
update Check and update all plugins if needed
reload Reload hyprpm state. Ensure all enabled plugins are loaded.
list List all installed plugins
Flags:
--notify | -n Send a hyprland notification for important events (e.g. load fail)
--help | -h Show this menu
--verbose | -v Enable too much logging
--force | -f Force an operation ignoring checks (e.g. update -f)
)#";
int main(int argc, char** argv, char** envp) {
std::vector<std::string> ARGS{argc};
for (int i = 0; i < argc; ++i) {
ARGS[i] = std::string{argv[i]};
}
if (ARGS.size() < 2) {
std::cout << HELP;
return 1;
}
std::vector<std::string> command;
bool notify = false, verbose = false, force = false;
for (int i = 1; i < argc; ++i) {
if (ARGS[i].starts_with("-")) {
if (ARGS[i] == "--help" || ARGS[i] == "-h") {
std::cout << HELP;
return 0;
} else if (ARGS[i] == "--notify" || ARGS[i] == "-n") {
notify = true;
} else if (ARGS[i] == "--verbose" || ARGS[i] == "-v") {
verbose = true;
} else if (ARGS[i] == "--force" || ARGS[i] == "-f") {
force = true;
std::cout << Colors::RED << "!" << Colors::RESET << " Using --force, I hope you know what you are doing.\n";
} else {
std::cerr << "Unrecognized option " << ARGS[i] << "\n";
return 1;
}
} else {
command.push_back(ARGS[i]);
}
}
if (command.empty()) {
std::cout << HELP;
return 0;
}
g_pPluginManager = std::make_unique<CPluginManager>();
g_pPluginManager->m_bVerbose = verbose;
if (command[0] == "add") {
if (command.size() < 2) {
std::cerr << Colors::RED << "" << Colors::RESET << " Not enough args for add.\n";
return 1;
}
std::string rev = "";
if (command.size() >= 3) {
rev = command[2];
}
return g_pPluginManager->addNewPluginRepo(command[1], rev) ? 0 : 1;
} else if (command[0] == "remove") {
if (ARGS.size() < 2) {
std::cerr << Colors::RED << "" << Colors::RESET << " Not enough args for remove.\n";
return 1;
}
return g_pPluginManager->removePluginRepo(command[1]) ? 0 : 1;
} else if (command[0] == "update") {
bool headersValid = g_pPluginManager->headersValid() == HEADERS_OK;
bool headers = g_pPluginManager->updateHeaders(force);
if (headers) {
const auto HLVER = g_pPluginManager->getHyprlandVersion();
auto GLOBALSTATE = DataState::getGlobalState();
const auto COMPILEDOUTDATED = HLVER.hash != GLOBALSTATE.headersHashCompiled;
bool ret1 = g_pPluginManager->updatePlugins(!headersValid || force || COMPILEDOUTDATED);
if (!ret1)
return 1;
auto ret2 = g_pPluginManager->ensurePluginsLoadState();
if (ret2 != LOADSTATE_OK)
return 1;
} else if (notify)
g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Couldn't update headers");
} else if (command[0] == "enable") {
if (ARGS.size() < 2) {
std::cerr << Colors::RED << "" << Colors::RESET << " Not enough args for enable.\n";
return 1;
}
if (!g_pPluginManager->enablePlugin(command[1])) {
std::cerr << Colors::RED << "" << Colors::RESET << " Couldn't enable plugin (missing?)\n";
return 1;
}
auto ret = g_pPluginManager->ensurePluginsLoadState();
if (ret != LOADSTATE_OK)
return 1;
} else if (command[0] == "disable") {
if (command.size() < 2) {
std::cerr << Colors::RED << "" << Colors::RESET << " Not enough args for disable.\n";
return 1;
}
if (!g_pPluginManager->disablePlugin(command[1])) {
std::cerr << Colors::RED << "" << Colors::RESET << " Couldn't disable plugin (missing?)\n";
return 1;
}
auto ret = g_pPluginManager->ensurePluginsLoadState();
if (ret != LOADSTATE_OK)
return 1;
} else if (command[0] == "reload") {
auto ret = g_pPluginManager->ensurePluginsLoadState();
if (ret != LOADSTATE_OK && notify) {
switch (ret) {
case LOADSTATE_FAIL:
case LOADSTATE_PARTIAL_FAIL: g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Failed to load plugins"); break;
case LOADSTATE_HEADERS_OUTDATED:
g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Failed to load plugins: Outdated headers. Please run hyprpm update manually.");
break;
default: break;
}
} else if (notify) {
g_pPluginManager->notify(ICON_OK, 0, 4000, "[hyprpm] Loaded plugins");
}
} else if (command[0] == "list") {
g_pPluginManager->listAllPlugins();
} else {
std::cout << HELP;
return 1;
}
return 0;
}

14
hyprpm/src/meson.build Normal file
View File

@@ -0,0 +1,14 @@
globber = run_command('sh', '-c', 'find . -name "*.cpp" | sort', check: true)
src = globber.stdout().strip().split('\n')
executable('hyprpm', src,
dependencies: [
dependency('threads'),
dependency('tomlplusplus')
],
install : true
)
install_data('../hyprpm.bash', install_dir: join_paths(get_option('datadir'), 'bash-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

@@ -0,0 +1,80 @@
#include "CProgressBar.hpp"
#include <iostream>
#include <algorithm>
#include <cmath>
#include <format>
#include <sys/ioctl.h>
#include <stdio.h>
#include <unistd.h>
#include "../helpers/Colors.hpp"
void CProgressBar::printMessageAbove(const std::string& msg) {
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
std::string spaces;
for (size_t i = 0; i < w.ws_col; ++i) {
spaces += ' ';
}
std::cout << "\r" << spaces << "\r" << msg << "\n";
print();
}
void CProgressBar::print() {
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
if (m_bFirstPrint)
std::cout << "\n";
m_bFirstPrint = false;
std::string spaces;
for (size_t i = 0; i < w.ws_col; ++i) {
spaces += ' ';
}
std::cout << "\r" << spaces << "\r";
std::string message = "";
float percentDone = 0;
if (m_fPercentage >= 0)
percentDone = m_fPercentage;
else
percentDone = (float)m_iSteps / (float)m_iMaxSteps;
const auto BARWIDTH = std::clamp(w.ws_col - static_cast<unsigned long>(m_szCurrentMessage.length()) - 2, 0UL, 50UL);
// draw bar
message += std::string{" "} + Colors::GREEN;
size_t i = 0;
for (; i < std::floor(percentDone * BARWIDTH); ++i) {
message += "";
}
if (i < BARWIDTH) {
i++;
message += std::string{""} + Colors::RESET;
for (; i < BARWIDTH; ++i) {
message += "";
}
} else
message += Colors::RESET;
// draw progress
if (m_fPercentage >= 0)
message += " " + std::format("{}%", static_cast<int>(percentDone * 100.0)) + " ";
else
message += " " + std::format("{} / {}", m_iSteps, m_iMaxSteps) + " ";
// draw message
std::cout << message + " " + m_szCurrentMessage;
std::fflush(stdout);
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include <string>
class CProgressBar {
public:
void print();
void printMessageAbove(const std::string& msg);
std::string m_szCurrentMessage = "";
size_t m_iSteps = 0;
size_t m_iMaxSteps = 0;
float m_fPercentage = -1; // if != -1, use percentage
private:
bool m_bFirstPrint = true;
};

View File

@@ -33,7 +33,7 @@ if cpp_compiler.check_header('execinfo.h')
add_project_arguments('-DHAS_EXECINFO', language: 'cpp')
endif
wlroots = subproject('wlroots', default_options: ['examples=false', 'renderers=gles2'])
wlroots = subproject('wlroots-hyprland', default_options: ['examples=false', 'renderers=gles2'])
have_xwlr = wlroots.get_variable('features').get('xwayland')
xcb_dep = dependency('xcb', required: get_option('xwayland'))
@@ -69,17 +69,18 @@ if get_option('buildtype') == 'debug'
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
endif
version_h = run_command('sh', '-c', 'scripts/generateVersion.sh')
globber = run_command('find', 'src', '-name', '*.h*', check: true)
headers = globber.stdout().strip().split('\n')
foreach file : headers
install_headers(file, subdir: 'hyprland', preserve_path: true)
endforeach
version_h = run_command('sh', '-c', 'scripts/generateVersion.sh')
subdir('protocols')
subdir('src')
subdir('hyprctl')
subdir('hyprpm/src')
subdir('assets')
subdir('example')
subdir('docs')

View File

@@ -2,15 +2,20 @@
lib,
stdenv,
pkg-config,
pkgconf,
makeWrapper,
meson,
ninja,
binutils,
cairo,
git,
hyprcursor,
hyprland-protocols,
hyprlang,
jq,
libGL,
libdrm,
libexecinfo,
libinput,
libxcb,
libxkbcommon,
@@ -18,29 +23,34 @@
pango,
pciutils,
systemd,
tomlplusplus,
udis86,
wayland,
wayland-protocols,
wayland-scanner,
wlroots,
wlroots-hyprland,
xcbutilwm,
xwayland,
debug ? false,
enableNvidiaPatches ? false,
enableXWayland ? true,
legacyRenderer ? false,
withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemd,
wrapRuntimeDeps ? true,
version ? "git",
commit,
date,
# deprecated flags
enableNvidiaPatches ? false,
nvidiaPatches ? false,
hidpiXWayland ? false,
}:
assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been renamed `enableNvidiaPatches`";
assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland";
assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed.";
assert lib.assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed.";
assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland"; let
wlr = wlroots-hyprland.override {inherit enableXWayland;};
in
stdenv.mkDerivation {
pname = "hyprland${lib.optionalString enableNvidiaPatches "-nvidia"}${lib.optionalString debug "-debug"}";
pname = "hyprland${lib.optionalString debug "-debug"}";
inherit version;
src = lib.cleanSourceWith {
@@ -51,52 +61,6 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
src = lib.cleanSource ../.;
};
nativeBuildInputs = [
jq
meson
ninja
pkg-config
makeWrapper
wayland-scanner
];
outputs = [
"out"
"man"
"dev"
];
buildInputs =
[
git
cairo
hyprland-protocols
libdrm
libinput
libxkbcommon
mesa
pango
udis86
wayland
wayland-protocols
pciutils
(wlroots.override {inherit enableNvidiaPatches;})
]
++ lib.optionals enableXWayland [libxcb xcbutilwm xwayland]
++ lib.optionals withSystemd [systemd];
mesonBuildType =
if debug
then "debug"
else "release";
mesonFlags = builtins.concatLists [
["-Dauto_features=disabled"]
(lib.optional enableXWayland "-Dxwayland=enabled")
(lib.optional legacyRenderer "-Dlegacy_renderer=enabled")
(lib.optional withSystemd "-Dsystemd=enabled")
];
patches = [
# make meson use the provided wlroots instead of the git submodule
./patches/meson-build.patch
@@ -112,6 +76,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
--replace "@HASH@" '${commit}' \
--replace "@BRANCH@" "" \
--replace "@MESSAGE@" "" \
--replace "@DATE@" "${date}" \
--replace "@TAG@" "" \
--replace "@DIRTY@" '${
if commit == ""
@@ -120,21 +85,80 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
}'
'';
nativeBuildInputs = [
jq
makeWrapper
meson
ninja
pkg-config
wayland-scanner
];
outputs = [
"out"
"man"
"dev"
];
buildInputs =
wlr.buildInputs
++ [
cairo
git
hyprcursor.dev
hyprland-protocols
hyprlang
libdrm
libGL
libinput
libxkbcommon
mesa
pango
pciutils
tomlplusplus
udis86
wayland
wayland-protocols
wlr
]
++ lib.optionals stdenv.hostPlatform.isMusl [libexecinfo]
++ lib.optionals enableXWayland [libxcb xcbutilwm xwayland]
++ lib.optionals withSystemd [systemd];
mesonBuildType =
if debug
then "debug"
else "release";
mesonAutoFeatures = "disabled";
mesonFlags = [
(lib.mesonEnable "xwayland" enableXWayland)
(lib.mesonEnable "legacy_renderer" legacyRenderer)
(lib.mesonEnable "systemd" withSystemd)
];
postInstall = ''
ln -s ${wlroots}/include/wlr $dev/include/hyprland/wlroots
ln -s ${wlr}/include/wlr $dev/include/hyprland/wlroots
${lib.optionalString wrapRuntimeDeps ''
wrapProgram $out/bin/Hyprland \
--suffix PATH : ${lib.makeBinPath [binutils pciutils]}
--suffix PATH : ${lib.makeBinPath [
stdenv.cc
binutils
pciutils
pkgconf
]}
''}
'';
passthru.providedSessions = ["hyprland"];
meta = with lib; {
homepage = "https://github.com/vaxerski/Hyprland";
homepage = "https://github.com/hyprwm/Hyprland";
description = "A dynamic tiling Wayland compositor that doesn't sacrifice on its looks";
license = licenses.bsd3;
platforms = platforms.linux;
platforms = wlr.meta.platforms;
mainProgram = "Hyprland";
};
}

View File

@@ -4,174 +4,11 @@ self: {
pkgs,
...
}: let
cfg = config.wayland.windowManager.hyprland;
defaultHyprlandPackage = self.packages.${pkgs.stdenv.hostPlatform.system}.default.override {
enableXWayland = cfg.xwayland.enable;
inherit (cfg) enableNvidiaPatches;
};
inherit (pkgs.stdenv.hostPlatform) system;
package = self.packages.${system}.default;
in {
disabledModules = ["services/window-managers/hyprland.nix"];
meta.maintainers = [lib.maintainers.fufexan];
options.wayland.windowManager.hyprland = {
enable =
lib.mkEnableOption null
// {
description = lib.mdDoc ''
Whether to enable Hyprland, the dynamic tiling Wayland compositor
that doesn't sacrifice on its looks.
You can manually launch Hyprland by executing {command}`Hyprland` on
a TTY.
See <https://wiki.hyprland.org> for more information.
'';
};
package = lib.mkOption {
type = with lib.types; nullOr package;
default = defaultHyprlandPackage;
defaultText = lib.literalExpression ''
hyprland.packages.''${pkgs.stdenv.hostPlatform.system}.default.override {
enableXWayland = config.wayland.windowManager.hyprland.xwayland.enable;
inherit (config.wayland.windowManager.hyprland) enableNvidiaPatches;
}
'';
description = lib.mdDoc ''
Hyprland package to use. Will override the 'xwayland' and
'enableNvidiaPatches' options.
Defaults to the one provided by the flake. Set it to
{package}`pkgs.hyprland` to use the one provided by nixpkgs or
if you have an overlay.
Set to null to not add any Hyprland package to your path. This should
be done if you want to use the NixOS module to install Hyprland.
'';
};
plugins = lib.mkOption {
type = with lib.types; listOf (either package path);
default = [];
description = lib.mdDoc ''
List of Hyprland plugins to use. Can either be packages or
absolute plugin paths.
'';
};
systemdIntegration = lib.mkOption {
type = lib.types.bool;
default = pkgs.stdenv.isLinux;
description = lib.mdDoc ''
Whether to enable {file}`hyprland-session.target` on
Hyprland startup. This links to {file}`graphical-session.target`.
Some important environment variables will be imported to systemd
and dbus user environment before reaching the target, including
- {env}`DISPLAY`
- {env}`HYPRLAND_INSTANCE_SIGNATURE`
- {env}`WAYLAND_DISPLAY`
- {env}`XDG_CURRENT_DESKTOP`
'';
};
disableAutoreload =
lib.mkEnableOption null
// {
description = lib.mdDoc ''
Whether to disable automatically reloading Hyprland's configuration when
rebuilding the Home Manager profile.
'';
};
xwayland.enable = lib.mkEnableOption (lib.mdDoc "XWayland") // {default = true;};
enableNvidiaPatches = lib.mkEnableOption (lib.mdDoc "patching wlroots for better Nvidia support.");
extraConfig = lib.mkOption {
type = lib.types.nullOr lib.types.lines;
default = "";
description = lib.mdDoc ''
Extra configuration lines to add to {file}`~/.config/hypr/hyprland.conf`.
'';
};
recommendedEnvironment =
lib.mkEnableOption null
// {
description = lib.mdDoc ''
Whether to set the recommended environment variables.
'';
};
config = {
wayland.windowManager.hyprland.package = lib.mkDefault package;
};
config = lib.mkIf cfg.enable {
warnings =
if (cfg.systemdIntegration || cfg.plugins != []) && cfg.extraConfig == null
then [
''
You have enabled hyprland.systemdIntegration or listed plugins in hyprland.plugins.
Your Hyprland config will be linked by home manager.
Set hyprland.extraConfig or unset hyprland.systemdIntegration and hyprland.plugins to remove this warning.
''
]
else [];
home.packages =
lib.optional (cfg.package != null) cfg.package
++ lib.optional cfg.xwayland.enable pkgs.xwayland;
home.sessionVariables =
lib.mkIf cfg.recommendedEnvironment {NIXOS_OZONE_WL = "1";};
xdg.configFile."hypr/hyprland.conf" = lib.mkIf (cfg.systemdIntegration || cfg.extraConfig != null || cfg.plugins != []) {
text =
(lib.optionalString cfg.systemdIntegration ''
exec-once=${pkgs.dbus}/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP && systemctl --user start hyprland-session.target
'')
+ lib.concatStrings (builtins.map (entry: let
plugin =
if lib.types.package.check entry
then "${entry}/lib/lib${entry.pname}.so"
else entry;
in "plugin = ${plugin}\n")
cfg.plugins)
+ (
if cfg.extraConfig != null
then cfg.extraConfig
else ""
);
onChange = let
hyprlandPackage =
if cfg.package == null
then defaultHyprlandPackage
else cfg.package;
in
lib.mkIf (!cfg.disableAutoreload) ''
( # execute in subshell so that `shopt` won't affect other scripts
shopt -s nullglob # so that nothing is done if /tmp/hypr/ does not exist or is empty
for instance in /tmp/hypr/*; do
HYPRLAND_INSTANCE_SIGNATURE=''${instance##*/} ${hyprlandPackage}/bin/hyprctl reload config-only \
|| true # ignore dead instance(s)
done
)
'';
};
systemd.user.targets.hyprland-session = lib.mkIf cfg.systemdIntegration {
Unit = {
Description = "Hyprland compositor session";
Documentation = ["man:systemd.special(7)"];
BindsTo = ["graphical-session.target"];
Wants = ["graphical-session-pre.target"];
After = ["graphical-session-pre.target"];
};
};
};
imports = [
(lib.mkRemovedOptionModule ["wayland" "windowManager" "hyprland" "xwayland" "hidpi"]
"Support for this option has been removed. Refer to https://wiki.hyprland.org/Configuring/XWayland for more info")
];
}

View File

@@ -2,98 +2,20 @@ inputs: {
config,
lib,
pkgs,
options,
...
}:
with lib; let
cfg = config.programs.hyprland;
}: let
inherit (pkgs.stdenv.hostPlatform) system;
cfg = config.programs.hyprland;
finalPortalPackage = cfg.portalPackage.override {
package = inputs.self.packages.${system}.hyprland;
portalPackage = inputs.self.packages.${system}.xdg-desktop-portal-hyprland.override {
hyprland = cfg.finalPackage;
};
in {
# disables Nixpkgs Hyprland module to avoid conflicts
disabledModules = ["programs/hyprland.nix"];
options.programs.hyprland = {
enable =
mkEnableOption null
// {
description = mdDoc ''
Hyprland, the dynamic tiling Wayland compositor that doesn't sacrifice on its looks.
You can manually launch Hyprland by executing {command}`Hyprland` on a TTY.
A configuration file will be generated in {file}`~/.config/hypr/hyprland.conf`.
See <https://wiki.hyprland.org> for more information.
'';
};
package = mkPackageOptionMD inputs.self.packages.${system} "hyprland" { };
finalPackage = mkOption {
type = types.package;
readOnly = true;
default = cfg.package.override {
enableXWayland = cfg.xwayland.enable;
enableNvidiaPatches = cfg.enableNvidiaPatches;
};
defaultText =
literalExpression
"`programs.hyprland.package` with applied configuration";
description = mdDoc ''
The Hyprland package after applying configuration.
'';
};
portalPackage = mkPackageOptionMD inputs.xdph.packages.${system} "xdg-desktop-portal-hyprland" {};
xwayland.enable = mkEnableOption (mdDoc "support for XWayland") // {default = true;};
enableNvidiaPatches =
mkEnableOption null
// {
description = mdDoc "Whether to apply patches to wlroots for better Nvidia support.";
};
};
config = mkIf cfg.enable {
environment.systemPackages = [cfg.finalPackage];
# NixOS changed the name of this attribute between NixOS 23.05 and
# 23.11
fonts = if builtins.hasAttr "enableDefaultPackages" options.fonts
then {enableDefaultPackages = mkDefault true;}
else {enableDefaultFonts = mkDefault true;};
hardware.opengl.enable = mkDefault true;
programs = {
dconf.enable = mkDefault true;
xwayland.enable = mkDefault cfg.xwayland.enable;
};
security.polkit.enable = true;
services.xserver.displayManager.sessionPackages = [cfg.finalPackage];
xdg.portal = {
enable = mkDefault true;
extraPortals = [finalPortalPackage];
config = {
programs.hyprland = {
package = lib.mkDefault package;
portalPackage = lib.mkDefault portalPackage;
};
};
imports = with lib; [
(
mkRemovedOptionModule
["programs" "hyprland" "xwayland" "hidpi"]
"XWayland patches are deprecated. Refer to https://wiki.hyprland.org/Configuring/XWayland"
)
(
mkRenamedOptionModule
["programs" "hyprland" "nvidiaPatches"]
["programs" "hyprland" "enableNvidiaPatches"]
)
];
}

View File

@@ -10,35 +10,43 @@
(builtins.substring 4 2 longDate)
(builtins.substring 6 2 longDate)
]);
mkJoinedOverlays = overlays: final: prev:
lib.foldl' (attrs: overlay: attrs // (overlay final prev)) {} overlays;
in {
# Contains what a user is most likely to care about:
# Hyprland itself, XDPH and the Share Picker.
default = mkJoinedOverlays (with self.overlays; [
default = lib.composeManyExtensions (with self.overlays; [
hyprland-packages
hyprland-extras
]);
# Packages for variations of Hyprland, dependencies included.
hyprland-packages = mkJoinedOverlays [
hyprland-packages = lib.composeManyExtensions [
# Dependencies
inputs.hyprcursor.overlays.default
inputs.hyprland-protocols.overlays.default
inputs.hyprlang.overlays.default
self.overlays.wlroots-hyprland
self.overlays.udis86
# Hyprland packages themselves
(final: prev: {
(final: prev: let
date = mkDate (self.lastModifiedDate or "19700101");
in {
hyprland = final.callPackage ./default.nix {
stdenv = final.gcc13Stdenv;
version = "${props.version}+date=${mkDate (self.lastModifiedDate or "19700101")}_${self.shortRev or "dirty"}";
wlroots = final.wlroots-hyprland;
version = "${props.version}+date=${date}_${self.shortRev or "dirty"}";
commit = self.rev or "";
inherit (final) udis86 hyprland-protocols;
udis86 = final.udis86-hyprland; # explicit override until decided on breaking change of the name
inherit (final) wlroots-hyprland; # explicit override until decided on breaking change of the name
inherit date;
};
hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;};
hyprland-debug = final.hyprland.override {debug = true;};
hyprland-nvidia = final.hyprland.override {enableNvidiaPatches = true;};
hyprland-legacy-renderer = final.hyprland.override {legacyRenderer = true;};
hyprland-nvidia =
builtins.trace ''
hyprland-nvidia was removed. Please use the hyprland package.
Nvidia patches are no longer needed.
''
final.hyprland;
hyprland-hidpi =
builtins.trace ''
hyprland-hidpi was removed. Please use the hyprland package.
@@ -50,12 +58,12 @@ in {
# Packages for extra software recommended for usage with Hyprland,
# including forked or patched packages for compatibility.
hyprland-extras = mkJoinedOverlays [
hyprland-extras = lib.composeManyExtensions [
inputs.xdph.overlays.xdg-desktop-portal-hyprland
];
udis86 = final: prev: {
udis86 = final.callPackage ./udis86.nix {};
udis86-hyprland = final.callPackage ./udis86.nix {};
};
# Patched version of wlroots for Hyprland.
@@ -65,30 +73,6 @@ in {
wlroots-hyprland = final.callPackage ./wlroots.nix {
version = "${mkDate (inputs.wlroots.lastModifiedDate or "19700101")}_${inputs.wlroots.shortRev or "dirty"}";
src = inputs.wlroots;
libdisplay-info = prev.libdisplay-info.overrideAttrs (old: {
version = "0.1.1+date=2023-03-02";
src = final.fetchFromGitLab {
domain = "gitlab.freedesktop.org";
owner = "emersion";
repo = old.pname;
rev = "147d6611a64a6ab04611b923e30efacaca6fc678";
sha256 = "sha256-/q79o13Zvu7x02SBGu0W5yQznQ+p7ltZ9L6cMW5t/o4=";
};
});
libliftoff = prev.libliftoff.overrideAttrs (old: {
version = "0.5.0-dev";
src = final.fetchFromGitLab {
domain = "gitlab.freedesktop.org";
owner = "emersion";
repo = old.pname;
rev = "d98ae243280074b0ba44bff92215ae8d785658c0";
sha256 = "sha256-DjwlS8rXE7srs7A8+tHqXyUsFGtucYSeq6X0T/pVOc8=";
};
NIX_CFLAGS_COMPILE = toString ["-Wno-error=sign-conversion"];
});
};
};
}

View File

@@ -1,12 +1,12 @@
diff --git a/meson.build b/meson.build
index 726933bc..28b4d9ac 100644
index 1d2c7f9f..c5ef4e67 100644
--- a/meson.build
+++ b/meson.build
@@ -29,20 +29,7 @@ add_project_arguments(
],
language: 'cpp')
@@ -33,20 +33,7 @@ if cpp_compiler.check_header('execinfo.h')
add_project_arguments('-DHAS_EXECINFO', language: 'cpp')
endif
-wlroots = subproject('wlroots', default_options: ['examples=false', 'renderers=gles2'])
-wlroots = subproject('wlroots-hyprland', default_options: ['examples=false', 'renderers=gles2'])
-have_xwlr = wlroots.get_variable('features').get('xwayland')
-xcb_dep = dependency('xcb', required: get_option('xwayland'))
-
@@ -24,27 +24,29 @@ index 726933bc..28b4d9ac 100644
add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
endif
@@ -71,8 +58,6 @@ foreach file : headers
install_headers(file, subdir: 'hyprland', preserve_path: true)
endforeach
@@ -69,8 +56,6 @@ if get_option('buildtype') == 'debug'
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
endif
-version_h = run_command('sh', '-c', 'scripts/generateVersion.sh')
-
subdir('protocols')
subdir('src')
subdir('hyprctl')
globber = run_command('find', 'src', '-name', '*.h*', check: true)
headers = globber.stdout().strip().split('\n')
foreach file : headers
diff --git a/src/meson.build b/src/meson.build
index 2065c6f5..55530605 100644
index 45701f5f..3505cefe 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -9,16 +9,16 @@ executable('Hyprland', src,
@@ -9,7 +9,7 @@ executable('Hyprland', src,
server_protos,
dependency('wayland-server'),
dependency('wayland-client'),
- wlroots.get_variable('wlroots'),
+ dependency('wlroots'),
dependency('cairo'),
dependency('libdrm'),
dependency('hyprcursor'),
dependency('hyprlang', version: '>= 0.3.2'),
@@ -16,12 +16,12 @@ executable('Hyprland', src,
dependency('egl'),
dependency('xkbcommon'),
dependency('libinput'),

View File

@@ -1,41 +0,0 @@
diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c
index 9fe934f7..9662d4ee 100644
--- a/render/gles2/renderer.c
+++ b/render/gles2/renderer.c
@@ -176,7 +176,7 @@ static bool gles2_bind_buffer(struct wlr_renderer *wlr_renderer,
assert(wlr_egl_is_current(renderer->egl));
push_gles2_debug(renderer);
- glFlush();
+ glFinish();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
pop_gles2_debug(renderer);
diff --git a/types/output/render.c b/types/output/render.c
index 2e38919a..97f78608 100644
--- a/types/output/render.c
+++ b/types/output/render.c
@@ -240,22 +240,7 @@ bool output_pick_format(struct wlr_output *output,
}
uint32_t wlr_output_preferred_read_format(struct wlr_output *output) {
- struct wlr_renderer *renderer = output->renderer;
- assert(renderer != NULL);
-
- if (!renderer->impl->preferred_read_format || !renderer->impl->read_pixels) {
- return DRM_FORMAT_INVALID;
- }
-
- if (!wlr_output_attach_render(output, NULL)) {
- return false;
- }
-
- uint32_t fmt = renderer->impl->preferred_read_format(renderer);
-
- output_clear_back_buffer(output);
-
- return fmt;
+ return DRM_FORMAT_XRGB8888;
}
struct wlr_render_pass *wlr_output_begin_render_pass(struct wlr_output *output,

View File

@@ -8,7 +8,7 @@ CRT_REV=$(rg rev flake.nix | awk '{ print substr($3, 2, 40) }')
if [ "$SUB_REV" != "$CRT_REV" ]; then
echo "Updating wlroots..."
# update wlroots to submodule revision
sed -Ei "s/\w{40}/$SUB_REV/g" flake.nix subprojects/wlroots.wrap
sed -Ei "s/\w{40}/$SUB_REV/g" flake.nix
nix flake lock
echo "wlroots: $CRT_REV -> $SUB_REV"

View File

@@ -1,28 +1,13 @@
{
lib,
version,
src,
wlroots,
hwdata,
libdisplay-info,
libliftoff,
enableXWayland ? true,
enableNvidiaPatches ? false,
}:
wlroots.overrideAttrs (old: {
inherit version src enableXWayland;
pname = "${old.pname}-hyprland${lib.optionalString enableNvidiaPatches "-nvidia"}";
pname = "${old.pname}-hyprland";
patches =
(old.patches or [])
++ (lib.optionals enableNvidiaPatches [
./patches/wlroots-nvidia.patch
]);
buildInputs = old.buildInputs ++ [hwdata libliftoff libdisplay-info];
NIX_CFLAGS_COMPILE = toString [
"-Wno-error=maybe-uninitialized"
];
patches = [ ]; # don't inherit old.patches
})

View File

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

View File

@@ -1,5 +1,5 @@
wayland_protos = dependency('wayland-protocols',
version: '>=1.25',
version: '>=1.32',
fallback: 'wayland-protocols',
default_options: ['tests=false'],
)

View File

@@ -2,13 +2,17 @@
cp -fr ./src/version.h.in ./src/version.h
HASH=$(git rev-parse HEAD)
BRANCH=$(git rev-parse --abbrev-ref HEAD)
BRANCH=$(git branch --show-current)
MESSAGE=$(git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1 | sed -e 's/#//g' -e 's/\"//g')
DATE=$(git show ${GIT_COMMIT_HASH} --no-patch --format=%cd --date=local)
DIRTY=$(git diff-index --quiet HEAD -- || echo dirty)
TAG=$(git describe --tags)
COMMITS=$(git rev-list --count HEAD)
sed -i -e "s#@HASH@#${HASH}#" ./src/version.h
sed -i -e "s#@BRANCH@#${BRANCH}#" ./src/version.h
sed -i -e "s#@MESSAGE@#${MESSAGE}#" ./src/version.h
sed -i -e "s#@DATE@#${DATE}#" ./src/version.h
sed -i -e "s#@DIRTY@#${DIRTY}#" ./src/version.h
sed -i -e "s#@TAG@#${TAG}#" ./src/version.h
sed -i -e "s#@COMMITS@#${COMMITS}#" ./src/version.h

View File

@@ -0,0 +1,20 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1190876d..0e7573f9 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -110,6 +110,7 @@ pkg_check_modules(deps REQUIRED IMPORTED_TARGET
cairo pango pangocairo pixman-1
libdrm libinput hwdata libseat libdisplay-info libliftoff libudev gbm
hyprlang>=0.3.2 hyprcursor
+ libffi
)
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
@@ -130,6 +131,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "Enabling ASan")
target_link_libraries(Hyprland asan)
+ target_link_libraries(Hyprland ${CMAKE_SOURCE_DIR}/libwayland-server.a)
target_compile_options(Hyprland PUBLIC -fsanitize=address)
endif()

View File

@@ -0,0 +1,23 @@
diff --git a/src/meson.build b/src/meson.build
index 5d04334..6645eec 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -170,7 +170,7 @@ if get_option('libraries')
error('We probably need to bump the SONAME of libwayland-server and -client')
endif
- wayland_server = library(
+ wayland_server = static_library(
'wayland-server',
sources: [
wayland_server_protocol_core_h,
@@ -180,9 +180,6 @@ if get_option('libraries')
'wayland-shm.c',
'event-loop.c'
],
- # To avoid an unnecessary SONAME bump, wayland 1.x.y produces
- # libwayland-server.so.0.x.y.
- version: '.'.join(['0', wayland_version[1], wayland_version[2]]),
dependencies: [
epoll_dep,
ffi_dep,

File diff suppressed because it is too large Load Diff

View File

@@ -21,16 +21,15 @@
#include "debug/HyprDebugOverlay.hpp"
#include "debug/HyprNotificationOverlay.hpp"
#include "helpers/Monitor.hpp"
#include "helpers/Workspace.hpp"
#include "Window.hpp"
#include "desktop/Workspace.hpp"
#include "desktop/Window.hpp"
#include "render/Renderer.hpp"
#include "render/OpenGL.hpp"
#include "hyprerror/HyprError.hpp"
#include "plugins/PluginSystem.hpp"
#include "helpers/Watchdog.hpp"
enum eManagersInitStage
{
enum eManagersInitStage {
STAGE_PRIORITY = 0,
STAGE_LATE
};
@@ -54,16 +53,13 @@ class CCompositor {
wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr;
wlr_xdg_activation_v1* m_sWLRXDGActivation;
wlr_output_layout* m_sWLROutputLayout;
wlr_idle* m_sWLRIdle;
wlr_idle_notifier_v1* m_sWLRIdleNotifier;
wlr_layer_shell_v1* m_sWLRLayerShell;
wlr_xdg_shell* m_sWLRXDGShell;
wlr_cursor* m_sWLRCursor;
wlr_xcursor_manager* m_sWLRXCursorMgr;
wlr_virtual_keyboard_manager_v1* m_sWLRVKeyboardMgr;
wlr_output_manager_v1* m_sWLROutputMgr;
wlr_presentation* m_sWLRPresentation;
wlr_input_inhibit_manager* m_sWLRInhibitMgr;
wlr_keyboard_shortcuts_inhibit_manager_v1* m_sWLRKbShInhibitMgr;
wlr_egl* m_sWLREGL;
int m_iDRMFD;
@@ -96,9 +92,7 @@ class CCompositor {
std::vector<std::shared_ptr<CMonitor>> m_vMonitors;
std::vector<std::shared_ptr<CMonitor>> m_vRealMonitors; // for all monitors, even those turned off
std::vector<std::unique_ptr<CWindow>> m_vWindows;
std::vector<std::unique_ptr<SXDGPopup>> m_vXDGPopups;
std::vector<std::unique_ptr<CWorkspace>> m_vWorkspaces;
std::vector<std::unique_ptr<SSubsurface>> m_vSubsurfaces;
std::vector<PHLWORKSPACE> m_vWorkspaces;
std::vector<CWindow*> m_vWindowsFadingOut;
std::vector<SLayerSurface*> m_vSurfacesFadingOut;
@@ -122,7 +116,9 @@ class CCompositor {
bool m_bSessionActive = true;
bool m_bDPMSStateON = true;
bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
wlr_output* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state
bool m_bNextIsUnsafe = false; // because wlroots
CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state
bool m_bExitTriggered = false; // For exit dispatcher
bool m_bIsShuttingDown = false;
// ------------------------------------------------- //
@@ -137,26 +133,26 @@ class CCompositor {
void focusSurface(wlr_surface*, CWindow* pWindowOwner = nullptr);
bool windowExists(CWindow*);
bool windowValidMapped(CWindow*);
CWindow* vectorToWindow(const Vector2D&);
CWindow* vectorToWindowIdeal(const Vector2D&); // used only for finding a window to focus on, basically a "findFocusableWindow"
CWindow* vectorToWindowTiled(const Vector2D&);
bool monitorExists(CMonitor*);
CWindow* vectorToWindowUnified(const Vector2D&, uint8_t properties, CWindow* pIgnoreWindow = nullptr);
wlr_surface* vectorToLayerSurface(const Vector2D&, std::vector<std::unique_ptr<SLayerSurface>>*, Vector2D*, SLayerSurface**);
wlr_surface* vectorToLayerPopupSurface(const Vector2D&, CMonitor* monitor, Vector2D*, SLayerSurface**);
wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl);
Vector2D vectorToSurfaceLocal(const Vector2D&, CWindow*, wlr_surface*);
CWindow* windowFromCursor();
CWindow* windowFloatingFromCursor();
CMonitor* getMonitorFromOutput(wlr_output*);
CWindow* getWindowForPopup(wlr_xdg_popup*);
CMonitor* getRealMonitorFromOutput(wlr_output*);
CWindow* getWindowFromSurface(wlr_surface*);
CWindow* getWindowFromHandle(uint32_t);
CWindow* getWindowFromZWLRHandle(wl_resource*);
bool isWorkspaceVisible(const int&);
CWorkspace* getWorkspaceByID(const int&);
CWorkspace* getWorkspaceByName(const std::string&);
CWorkspace* getWorkspaceByString(const std::string&);
bool isWorkspaceVisible(PHLWORKSPACE);
PHLWORKSPACE getWorkspaceByID(const int&);
PHLWORKSPACE getWorkspaceByName(const std::string&);
PHLWORKSPACE getWorkspaceByString(const std::string&);
void sanityCheckWorkspaces();
void updateWorkspaceWindowDecos(const int&);
int getWindowsOnWorkspace(const int&);
void updateWorkspaceSpecialRenderData(const int&);
int getWindowsOnWorkspace(const int& id, std::optional<bool> onlyTiled = {});
int getGroupsOnWorkspace(const int& id, std::optional<bool> onlyTiled = {});
CWindow* getUrgentWindow();
bool hasUrgentWindowOnWorkspace(const int&);
CWindow* getFirstWindowOnWorkspace(const int&);
@@ -167,21 +163,23 @@ class CCompositor {
void changeWindowZOrder(CWindow*, bool);
void cleanupFadingOut(const int& monid);
CWindow* getWindowInDirection(CWindow*, char);
CWindow* getNextWindowOnWorkspace(CWindow*, bool focusableOnly = false);
CWindow* getPrevWindowOnWorkspace(CWindow*, bool focusableOnly = false);
CWindow* getNextWindowOnWorkspace(CWindow*, bool focusableOnly = false, std::optional<bool> floating = {});
CWindow* getPrevWindowOnWorkspace(CWindow*, bool focusableOnly = false, std::optional<bool> floating = {});
int getNextAvailableNamedWorkspace();
bool isPointOnAnyMonitor(const Vector2D&);
CWindow* getConstraintWindow(SMouse*);
bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr);
CMonitor* getMonitorInDirection(const char&);
CMonitor* getMonitorInDirection(CMonitor*, const char&);
void updateAllWindowsAnimatedDecorationValues();
void updateWorkspaceWindows(const int64_t& id);
void updateWindowAnimatedDecorationValues(CWindow*);
int getNextAvailableMonitorID(std::string const& name);
void moveWorkspaceToMonitor(CWorkspace*, CMonitor*);
void moveWorkspaceToMonitor(PHLWORKSPACE, CMonitor*, bool noWarpCursor = false);
void swapActiveWorkspaces(CMonitor*, CMonitor*);
CMonitor* getMonitorFromString(const std::string&);
bool workspaceIDOutOfBounds(const int64_t&);
void setWindowFullscreen(CWindow*, bool, eFullscreenMode);
void updateFullscreenFadeOnWorkspace(CWorkspace*);
void setWindowFullscreen(CWindow*, bool, eFullscreenMode mode = FULLSCREEN_INVALID);
void updateFullscreenFadeOnWorkspace(PHLWORKSPACE);
CWindow* getX11Parent(CWindow*);
void scheduleFrameForMonitor(CMonitor*);
void addToFadingOutSafe(SLayerSurface*);
@@ -193,27 +191,31 @@ class CCompositor {
void closeWindow(CWindow*);
Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&);
void forceReportSizesToWindowsOnWorkspace(const int&);
bool cursorOnReservedArea();
CWorkspace* createNewWorkspace(const int&, const int&, const std::string& name = ""); // will be deleted next frame if left empty and unfocused!
PHLWORKSPACE createNewWorkspace(const int&, const int&, const std::string& name = ""); // will be deleted next frame if left empty and unfocused!
void renameWorkspace(const int&, const std::string& name = "");
void setActiveMonitor(CMonitor*);
bool isWorkspaceSpecial(const int&);
int getNewSpecialID();
void performUserChecks();
void moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorkspace);
void moveWindowToWorkspaceSafe(CWindow* pWindow, PHLWORKSPACE pWorkspace);
CWindow* getForceFocus();
void notifyIdleActivity();
void setIdleActivityInhibit(bool inhibit);
void arrangeMonitors();
void enterUnsafeState();
void leaveUnsafeState();
void setPreferredScaleForSurface(wlr_surface* pSurface, double scale);
void setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform);
void updateSuspendedStates();
std::string explicitConfigPath;
private:
void initAllSignals();
void removeAllSignals();
void setRandomSplash();
void initManagers(eManagersInitStage stage);
void prepareFallbackOutput();
uint64_t m_iHyprlandPID = 0;
};
@@ -233,4 +235,7 @@ inline std::map<std::string, xcb_atom_t> HYPRATOMS = {HYPRATOM("_NET_WM_WINDOW_T
HYPRATOM("_NET_WM_WINDOW_TYPE_POPUP_MENU"),
HYPRATOM("_NET_WM_WINDOW_TYPE_TOOLTIP"),
HYPRATOM("_NET_WM_WINDOW_TYPE_NOTIFICATION"),
HYPRATOM("_KDE_NET_WM_WINDOW_TYPE_OVERRIDE")};
HYPRATOM("_KDE_NET_WM_WINDOW_TYPE_OVERRIDE"),
HYPRATOM("_NET_SUPPORTING_WM_CHECK"),
HYPRATOM("_NET_WM_NAME"),
HYPRATOM("UTF8_STRING")};

View File

@@ -1,7 +1,9 @@
#pragma once
enum eIcons
{
#include "helpers/Vector2D.hpp"
#include <functional>
enum eIcons {
ICON_WARNING = 0,
ICON_INFO,
ICON_HINT,
@@ -11,8 +13,7 @@ enum eIcons
ICON_NONE
};
enum eRenderStage
{
enum eRenderStage {
RENDER_PRE = 0, /* Before binding the gl context */
RENDER_BEGIN, /* Just when the rendering begins, nothing has been rendered yet. Damage, current render data in opengl valid. */
RENDER_PRE_WINDOWS, /* Pre windows, post bottom and overlay layers */
@@ -23,3 +24,51 @@ enum eRenderStage
RENDER_PRE_WINDOW, /* Before rendering a window (any pass) Note some windows (e.g. tiled) may have 2 passes (main & popup) */
RENDER_POST_WINDOW, /* After rendering a window (any pass) */
};
enum eInputType {
INPUT_TYPE_AXIS = 0,
INPUT_TYPE_BUTTON,
INPUT_TYPE_DRAG_START,
INPUT_TYPE_DRAG_END,
INPUT_TYPE_MOTION
};
struct SCallbackInfo {
bool cancelled = false; /* on cancellable events, will cancel the event. */
};
struct SWindowDecorationExtents {
Vector2D topLeft;
Vector2D bottomRight;
//
SWindowDecorationExtents operator*(const double& scale) const {
return SWindowDecorationExtents{topLeft * scale, bottomRight * scale};
}
SWindowDecorationExtents round() {
return {topLeft.round(), bottomRight.round()};
}
bool operator==(const SWindowDecorationExtents& other) const {
return topLeft == other.topLeft && bottomRight == other.bottomRight;
}
void addExtents(const SWindowDecorationExtents& other) {
topLeft = topLeft.getComponentMax(other.topLeft);
bottomRight = bottomRight.getComponentMax(other.bottomRight);
}
};
enum eHyprCtlOutputFormat {
FORMAT_NORMAL = 0,
FORMAT_JSON
};
struct SHyprCtlCommand {
std::string name = "";
bool exact = true;
std::function<std::string(eHyprCtlOutputFormat, std::string)> fn;
};
typedef std::function<void(void*, SCallbackInfo&, std::any)> HOOK_CALLBACK_FN;

View File

@@ -1,10 +1,12 @@
#pragma once
#include "../defines.hpp"
#include "../helpers/VarList.hpp"
#include <vector>
enum eConfigValueDataTypes {
CVD_TYPE_INVALID = -1,
CVD_TYPE_GRADIENT = 0
CVD_TYPE_INVALID = -1,
CVD_TYPE_GRADIENT = 0,
CVD_TYPE_CSS_VALUE = 1
};
class ICustomConfigValueData {
@@ -12,10 +14,13 @@ class ICustomConfigValueData {
virtual ~ICustomConfigValueData() = 0;
virtual eConfigValueDataTypes getDataType() = 0;
virtual std::string toString() = 0;
};
class CGradientValueData : public ICustomConfigValueData {
public:
CGradientValueData(){};
CGradientValueData(CColor col) {
m_vColors.push_back(col);
};
@@ -48,4 +53,70 @@ class CGradientValueData : public ICustomConfigValueData {
return true;
}
virtual std::string toString() {
std::string result;
for (auto& c : m_vColors) {
result += std::format("{:x} ", c.getAsHex());
}
result += std::format("{}deg", (int)(m_fAngle * 180.0 / M_PI));
return result;
}
};
class CCssGapData : public ICustomConfigValueData {
public:
CCssGapData() : top(0), right(0), bottom(0), left(0){};
CCssGapData(int64_t global) : top(global), right(global), bottom(global), left(global){};
CCssGapData(int64_t vertical, int64_t horizontal) : top(vertical), right(horizontal), bottom(vertical), left(horizontal){};
CCssGapData(int64_t top, int64_t horizontal, int64_t bottom) : top(top), right(horizontal), bottom(bottom), left(horizontal){};
CCssGapData(int64_t top, int64_t right, int64_t bottom, int64_t left) : top(top), right(right), bottom(bottom), left(left){};
/* Css like directions */
int64_t top;
int64_t right;
int64_t bottom;
int64_t left;
void parseGapData(CVarList varlist) {
switch (varlist.size()) {
case 1: {
*this = CCssGapData(std::stoi(varlist[0]));
break;
}
case 2: {
*this = CCssGapData(std::stoi(varlist[0]), std::stoi(varlist[1]));
break;
}
case 3: {
*this = CCssGapData(std::stoi(varlist[0]), std::stoi(varlist[1]), std::stoi(varlist[2]));
break;
}
case 4: {
*this = CCssGapData(std::stoi(varlist[0]), std::stoi(varlist[1]), std::stoi(varlist[2]), std::stoi(varlist[3]));
break;
}
default: {
Debug::log(WARN, "Too many arguments provided for gaps.");
*this = CCssGapData(std::stoi(varlist[0]), std::stoi(varlist[1]), std::stoi(varlist[2]), std::stoi(varlist[3]));
break;
}
}
}
void reset(int64_t global) {
top = global;
right = global;
bottom = global;
left = global;
}
virtual eConfigValueDataTypes getDataType() {
return CVD_TYPE_CSS_VALUE;
}
virtual std::string toString() {
return std::format("{} {} {} {}", top, right, bottom, left);
}
};

File diff suppressed because it is too large Load Diff

View File

@@ -11,44 +11,42 @@
#include <algorithm>
#include <regex>
#include <optional>
#include <functional>
#include <xf86drmMode.h>
#include "../Window.hpp"
#include "../helpers/WLClasses.hpp"
#include "../helpers/Monitor.hpp"
#include "../helpers/VarList.hpp"
#include "../desktop/Window.hpp"
#include "defaultConfig.hpp"
#include "ConfigDataValues.hpp"
#include <hyprlang.hpp>
#define INITANIMCFG(name) animationConfig[name] = {}
#define CREATEANIMCFG(name, parent) animationConfig[name] = {false, "", "", 0.f, -1, &animationConfig["global"], &animationConfig[parent]}
#define HANDLE void*
struct SConfigValue {
int64_t intValue = -INT64_MAX;
float floatValue = -__FLT_MAX__;
std::string strValue = "";
Vector2D vecValue = Vector2D(-__FLT_MAX__, -__FLT_MAX__);
std::shared_ptr<ICustomConfigValueData> data;
bool set = false; // used for device configs
};
class CWindow;
struct SWorkspaceRule {
std::string monitor = "";
std::string workspaceString = "";
std::string workspaceName = "";
int workspaceId = -1;
bool isDefault = false;
bool isPersistent = false;
std::optional<int64_t> gapsIn;
std::optional<int64_t> gapsOut;
std::optional<int64_t> borderSize;
std::optional<int> border;
std::optional<int> rounding;
std::optional<int> decorate;
std::optional<int> shadow;
std::string monitor = "";
std::string workspaceString = "";
std::string workspaceName = "";
int workspaceId = -1;
bool isDefault = false;
bool isPersistent = false;
std::optional<CCssGapData> gapsIn;
std::optional<CCssGapData> gapsOut;
std::optional<int64_t> borderSize;
std::optional<int> border;
std::optional<int> rounding;
std::optional<int> decorate;
std::optional<int> shadow;
std::optional<std::string> onCreatedEmptyRunCmd;
std::optional<std::string> defaultName;
std::map<std::string, std::string> layoutopts;
};
struct SMonitorAdditionalReservedArea {
@@ -70,6 +68,17 @@ struct SAnimationPropertyConfig {
SAnimationPropertyConfig* pParentAnimation = nullptr;
};
struct SPluginKeyword {
HANDLE handle = 0;
std::string name = "";
Hyprlang::PCONFIGHANDLERFUNC fn = nullptr;
};
struct SPluginVariable {
HANDLE handle = 0;
std::string name = "";
};
struct SExecRequestedRule {
std::string szRule = "";
uint64_t iPid = 0;
@@ -82,44 +91,38 @@ class CConfigManager {
void tick();
void init();
int getInt(const std::string&);
float getFloat(const std::string&);
Vector2D getVec(const std::string&);
std::string getString(const std::string&);
void setFloat(const std::string&, float);
void setInt(const std::string&, int);
void setVec(const std::string&, Vector2D);
void setString(const std::string&, const std::string&);
int getDeviceInt(const std::string&, const std::string&, const std::string& fallback = "");
float getDeviceFloat(const std::string&, const std::string&, const std::string& fallback = "");
Vector2D getDeviceVec(const std::string&, const std::string&, const std::string& fallback = "");
std::string getDeviceString(const std::string&, const std::string&, const std::string& fallback = "");
bool deviceConfigExists(const std::string&);
Hyprlang::CConfigValue* getConfigValueSafeDevice(const std::string& dev, const std::string& val, const std::string& fallback);
bool shouldBlurLS(const std::string&);
SConfigValue* getConfigValuePtr(const std::string&);
SConfigValue* getConfigValuePtrSafe(const std::string&);
void* const* getConfigValuePtr(const std::string&);
Hyprlang::CConfigValue* getHyprlangConfigValuePtr(const std::string& name, const std::string& specialCat = "");
void onPluginLoadUnload(const std::string& name, bool load);
static std::string getConfigDir();
static std::string getMainConfigPath();
SMonitorRule getMonitorRuleFor(const std::string&, const std::string& displayName = "");
SWorkspaceRule getWorkspaceRuleFor(CWorkspace*);
SMonitorRule getMonitorRuleFor(const CMonitor&);
SWorkspaceRule getWorkspaceRuleFor(PHLWORKSPACE workspace);
std::string getDefaultWorkspaceFor(const std::string&);
CMonitor* getBoundMonitorForWS(const std::string&);
std::string getBoundMonitorStringForWS(const std::string&);
const std::deque<SWorkspaceRule>& getAllWorkspaceRules();
std::vector<SWindowRule> getMatchingRules(CWindow*);
std::vector<SWindowRule> getMatchingRules(CWindow*, bool dynamic = true, bool shadowExec = false);
std::vector<SLayerRule> getMatchingRules(SLayerSurface*);
std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas;
std::unordered_map<std::string, SAnimationPropertyConfig> getAnimationConfig();
void addPluginConfigVar(HANDLE handle, const std::string& name, const SConfigValue& value);
void removePluginConfig(HANDLE handle);
void addPluginConfigVar(HANDLE handle, const std::string& name, const Hyprlang::CConfigValue& value);
void addPluginKeyword(HANDLE handle, const std::string& name, Hyprlang::PCONFIGHANDLERFUNC fun, Hyprlang::SHandlerOptions opts = {});
void removePluginConfig(HANDLE handle);
// no-op when done.
void dispatchExecOnce();
@@ -131,7 +134,7 @@ class CConfigManager {
void ensureMonitorStatus();
void ensureVRR(CMonitor* pMonitor = nullptr);
std::string parseKeyword(const std::string&, const std::string&, bool dynamic = false);
std::string parseKeyword(const std::string&, const std::string&);
void addParseError(const std::string&);
@@ -140,77 +143,68 @@ class CConfigManager {
void addExecRule(const SExecRequestedRule&);
void handlePluginLoads();
std::string getErrors();
std::string configCurrentPath;
// keywords
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> handleMonitor(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> handleWindowRule(const std::string&, const std::string&);
std::optional<std::string> handleLayerRule(const std::string&, const std::string&);
std::optional<std::string> handleWindowRuleV2(const std::string&, const std::string&);
std::optional<std::string> handleWorkspaceRules(const std::string&, const std::string&);
std::optional<std::string> handleBezier(const std::string&, const std::string&);
std::optional<std::string> handleAnimation(const std::string&, const std::string&);
std::optional<std::string> handleSource(const std::string&, const std::string&);
std::optional<std::string> handleSubmap(const std::string&, const std::string&);
std::optional<std::string> handleBlurLS(const std::string&, const std::string&);
std::optional<std::string> handleBindWS(const std::string&, const std::string&);
std::optional<std::string> handleEnv(const std::string&, const std::string&);
std::optional<std::string> handlePlugin(const std::string&, const std::string&);
std::string configCurrentPath;
private:
std::deque<std::string> configPaths; // stores all the config paths
std::unordered_map<std::string, time_t> configModifyTimes; // stores modify times
std::vector<std::pair<std::string, std::string>> configDynamicVars; // stores dynamic vars declared by the user
std::unordered_map<std::string, SConfigValue> configValues;
std::unordered_map<std::string, std::unordered_map<std::string, SConfigValue>> deviceConfigs; // stores device configs
std::unique_ptr<Hyprlang::CConfig> m_pConfig;
std::unordered_map<std::string, SAnimationPropertyConfig> animationConfig; // stores all the animations with their set values
std::deque<std::string> configPaths; // stores all the config paths
std::unordered_map<std::string, time_t> configModifyTimes; // stores modify times
std::string currentCategory = ""; // For storing the category of the current item
std::unordered_map<std::string, SAnimationPropertyConfig> animationConfig; // stores all the animations with their set values
std::string parseError = ""; // For storing a parse error to display later
std::string m_szCurrentSubmap = ""; // For storing the current keybind submap
std::string m_szCurrentSubmap = ""; // For storing the current keybind submap
std::vector<SExecRequestedRule> execRequestedRules; // rules requested with exec, e.g. [workspace 2] kitty
std::vector<SExecRequestedRule> execRequestedRules; // rules requested with exec, e.g. [workspace 2] kitty
std::vector<std::string> m_vDeclaredPlugins;
std::vector<SPluginKeyword> pluginKeywords;
std::vector<SPluginVariable> pluginVariables;
std::vector<std::string> m_vDeclaredPlugins;
std::unordered_map<HANDLE, std::unique_ptr<std::unordered_map<std::string, SConfigValue>>> pluginConfigs; // stores plugin configs
bool isFirstLaunch = true; // For exec-once
bool isFirstLaunch = true; // For exec-once
std::deque<SMonitorRule> m_dMonitorRules;
std::deque<SWorkspaceRule> m_dWorkspaceRules;
std::deque<SWindowRule> m_dWindowRules;
std::deque<SLayerRule> m_dLayerRules;
std::deque<std::string> m_dBlurLSNamespaces;
std::deque<SMonitorRule> m_dMonitorRules;
std::deque<SWorkspaceRule> m_dWorkspaceRules;
std::deque<SWindowRule> m_dWindowRules;
std::deque<SLayerRule> m_dLayerRules;
std::deque<std::string> m_dBlurLSNamespaces;
bool firstExecDispatched = false;
bool m_bManualCrashInitiated = false;
std::deque<std::string> firstExecRequests;
bool firstExecDispatched = false;
bool m_bManualCrashInitiated = false;
std::deque<std::string> firstExecRequests;
std::vector<std::pair<std::string, std::string>> environmentVariables;
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 = "";
// internal methods
void setDefaultVars();
void setDefaultAnimationVars();
void setDeviceDefaultVars(const std::string&);
void populateEnvironment();
void setAnimForChildren(SAnimationPropertyConfig* const);
void updateBlurredLS(const std::string&, const bool);
void applyUserDefinedVars(std::string&, const size_t);
void loadConfigLoadVars();
SConfigValue getConfigValueSafe(const std::string&);
SConfigValue getConfigValueSafeDevice(const std::string&, const std::string&, const std::string& fallback = "");
void parseLine(std::string&);
void configSetValueSafe(const std::string&, const std::string&);
void handleDeviceConfig(const std::string&, const std::string&);
void handleRawExec(const std::string&, const std::string&);
void handleMonitor(const std::string&, const std::string&);
void handleBind(const std::string&, const std::string&);
void handleUnbind(const std::string&, const std::string&);
void handleWindowRule(const std::string&, const std::string&);
void handleLayerRule(const std::string&, const std::string&);
void handleWindowRuleV2(const std::string&, const std::string&);
void handleWorkspaceRules(const std::string&, const std::string&);
void handleBezier(const std::string&, const std::string&);
void handleAnimation(const std::string&, const std::string&);
void handleSource(const std::string&, const std::string&);
void handleSubmap(const std::string&, const std::string&);
void handleBlurLS(const std::string&, const std::string&);
void handleBindWS(const std::string&, const std::string&);
void handleEnv(const std::string&, const std::string&);
void handlePlugin(const std::string&, const std::string&);
void setAnimForChildren(SAnimationPropertyConfig* const);
void updateBlurredLS(const std::string&, const bool);
void setDefaultAnimationVars();
std::optional<std::string> resetHLConfig();
std::optional<std::string> verifyConfigExists();
void postConfigReload(const Hyprlang::CParseResult& result);
void reload();
};
inline std::unique_ptr<CConfigManager> g_pConfigManager;

View File

@@ -0,0 +1,73 @@
#pragma once
#include <string>
#include <typeindex>
#include <hyprlang.hpp>
#include "../debug/Log.hpp"
#include "../macros.hpp"
#include "ConfigManager.hpp"
template <typename T>
class CConfigValue {
public:
CConfigValue(const std::string& val) {
const auto PVHYPRLANG = g_pConfigManager->getHyprlangConfigValuePtr(val.c_str());
p_ = PVHYPRLANG->getDataStaticPtr();
#ifdef HYPRLAND_DEBUG
// verify type
const auto ANY = PVHYPRLANG->getValue();
const auto TYPE = std::type_index(ANY.type());
// exceptions
const bool STRINGEX = (typeid(T) == typeid(std::string) && TYPE == typeid(Hyprlang::STRING));
const bool CUSTOMEX = (typeid(T) == typeid(Hyprlang::CUSTOMTYPE) && (TYPE == typeid(Hyprlang::CUSTOMTYPE*) || TYPE == typeid(void*) /* dunno why it does this? */));
RASSERT(typeid(T) == TYPE || STRINGEX || CUSTOMEX, "Mismatched type in CConfigValue<T>, got {} but has {}", typeid(T).name(), TYPE.name());
#endif
}
T* ptr() const {
return *(T* const*)p_;
}
T operator*() const {
return *ptr();
}
private:
void* const* p_ = nullptr;
};
template <>
inline std::string* CConfigValue<std::string>::ptr() const {
RASSERT(false, "Impossible to implement ptr() of CConfigValue<std::string>");
return nullptr;
}
template <>
inline std::string CConfigValue<std::string>::operator*() const {
return std::string{*(Hyprlang::STRING*)p_};
}
template <>
inline Hyprlang::STRING* CConfigValue<Hyprlang::STRING>::ptr() const {
return (Hyprlang::STRING*)p_;
}
template <>
inline Hyprlang::STRING CConfigValue<Hyprlang::STRING>::operator*() const {
return *(Hyprlang::STRING*)p_;
}
template <>
inline Hyprlang::CUSTOMTYPE* CConfigValue<Hyprlang::CUSTOMTYPE>::ptr() const {
return *(Hyprlang::CUSTOMTYPE* const*)p_;
}
template <>
inline Hyprlang::CUSTOMTYPE CConfigValue<Hyprlang::CUSTOMTYPE>::operator*() const {
RASSERT(false, "Impossible to implement operator* of CConfigValue<Hyprlang::CUSTOMTYPE>, use ptr()");
return *ptr();
}

View File

@@ -3,11 +3,11 @@
#include <string>
inline const std::string AUTOCONFIG = R"#(
########################################################################################
AUTOGENERATED HYPR CONFIG.
PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hypr.conf AND EDIT IT,
OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
########################################################################################
# #######################################################################################
# AUTOGENERATED HYPR CONFIG.
# PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hypr.conf AND EDIT IT,
# OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
# #######################################################################################
#
# Please note not all available settings / options are set here.
@@ -28,8 +28,14 @@ monitor=,preferred,auto,auto
# Source a file (multi-file configs)
# source = ~/.config/hypr/myColors.conf
# Set programs that you use
$terminal = kitty
$fileManager = dolphin
$menu = wofi --show drun
# Some default env vars.
env = XCURSOR_SIZE,24
env = QT_QPA_PLATFORMTHEME,qt5ct # change to qt6ct if you have that
# For all categories, see https://wiki.hyprland.org/Configuring/Variables/
input {
@@ -45,7 +51,7 @@ input {
natural_scroll = no
}
sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
sensitivity = 0 # -1.0 to 1.0, 0 means no modification.
}
general {
@@ -113,12 +119,13 @@ gestures {
misc {
# See https://wiki.hyprland.org/Configuring/Variables/ for more
force_default_wallpaper = -1 # Set to 0 to disable the anime mascot wallpapers
force_default_wallpaper = -1 # Set to 0 or 1 to disable the anime mascot wallpapers
}
# Example per-device config
# See https://wiki.hyprland.org/Configuring/Keywords/#executing for more
device:epic-mouse-v1 {
# See https://wiki.hyprland.org/Configuring/Keywords/#per-device-input-configs for more
device {
name = epic-mouse-v1
sensitivity = -0.5
}
@@ -127,18 +134,19 @@ device:epic-mouse-v1 {
# Example windowrule v2
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
$mainMod = SUPER
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
bind = $mainMod, Q, exec, kitty
bind = $mainMod, Q, exec, $terminal
bind = $mainMod, C, killactive,
bind = $mainMod, M, exit,
bind = $mainMod, E, exec, dolphin
bind = $mainMod, E, exec, $fileManager
bind = $mainMod, V, togglefloating,
bind = $mainMod, R, exec, wofi --show drun
bind = $mainMod, R, exec, $menu
bind = $mainMod, P, pseudo, # dwindle
bind = $mainMod, J, togglesplit, # dwindle
@@ -172,6 +180,10 @@ bind = $mainMod SHIFT, 8, movetoworkspace, 8
bind = $mainMod SHIFT, 9, movetoworkspace, 9
bind = $mainMod SHIFT, 0, movetoworkspace, 10
# Example special workspace (scratchpad)
bind = $mainMod, S, togglespecialworkspace, magic
bind = $mainMod SHIFT, S, movetoworkspace, special:magic
# Scroll through existing workspaces with mainMod + scroll
bind = $mainMod, mouse_down, workspace, e+1
bind = $mainMod, mouse_up, workspace, e-1

View File

@@ -3,6 +3,7 @@
#include <sys/utsname.h>
#include <fstream>
#include <signal.h>
#include <link.h>
#include "../plugins/PluginSystem.hpp"
@@ -13,19 +14,19 @@
std::string getRandomMessage() {
const std::vector<std::string> MESSAGES = {"Sorry, didn't mean to...",
"This was an accident, I swear!",
"Calm down, it was a misinput! MISINPUT!",
"Oops",
"Vaxry is going to be upset.",
"Who tried dividing by zero?!",
"Maybe you should try dusting your PC in the meantime?",
"I tried so hard, and got so far...",
"I don't feel so good...",
"*thud*",
"Well this is awkward.",
"\"stable\"",
"I hope you didn't have any unsaved progress.",
"All these computers..."};
"This was an accident, I swear!",
"Calm down, it was a misinput! MISINPUT!",
"Oops",
"Vaxry is going to be upset.",
"Who tried dividing by zero?!",
"Maybe you should try dusting your PC in the meantime?",
"I tried so hard, and got so far...",
"I don't feel so good...",
"*thud*",
"Well this is awkward.",
"\"stable\"",
"I hope you didn't have any unsaved progress.",
"All these computers..."};
std::random_device dev;
std::mt19937 engine(dev());
@@ -63,8 +64,8 @@ void CrashReporter::createAndSaveCrash(int sig) {
struct utsname unameInfo;
uname(&unameInfo);
finalCrashReport +=
std::format("\tSystem name: {}\n\tNode name: {}\n\tRelease: {}\n\tVersion: {}\n\n", unameInfo.sysname, unameInfo.nodename, unameInfo.release, unameInfo.version);
finalCrashReport += std::format("\tSystem name: {}\n\tNode name: {}\n\tRelease: {}\n\tVersion: {}\n\n", std::string{unameInfo.sysname}, std::string{unameInfo.nodename},
std::string{unameInfo.release}, std::string{unameInfo.version});
#if defined(__DragonFly__) || defined(__FreeBSD__)
const std::string GPUINFO = execAndGet("pciconf -lv | fgrep -A4 vga");
@@ -105,21 +106,43 @@ void CrashReporter::createAndSaveCrash(int sig) {
const auto FPATH = std::filesystem::canonical("/proc/self/exe");
#endif
std::string addrs = "";
for (size_t i = 0; i < CALLSTACK.size(); ++i) {
finalCrashReport += std::format("\t#{} | {}\n", i, CALLSTACK[i].desc);
#ifdef __clang__
const auto CMD = std::format("llvm-addr2line -e {} -f 0x{:x}", FPATH.c_str(), (uint64_t)CALLSTACK[i].adr);
#ifdef __GLIBC__
// convert in memory address to VMA address
Dl_info info;
struct link_map* linkMap;
dladdr1((void*)CALLSTACK[i].adr, &info, (void**)&linkMap, RTLD_DL_LINKMAP);
size_t vmaAddr = (size_t)CALLSTACK[i].adr - linkMap->l_addr;
#else
const auto CMD = std::format("addr2line -e {} -f 0x{:x}", FPATH.c_str(), (uint64_t)CALLSTACK[i].adr);
// musl doesn't define dladdr1
size_t vmaAddr = (size_t)CALLSTACK[i].adr;
#endif
const auto ADDR2LINE = replaceInString(execAndGet(CMD.c_str()), "\n", "\n\t\t");
finalCrashReport += "\t\t" + ADDR2LINE.substr(0, ADDR2LINE.length() - 2);
addrs += std::format("0x{:x} ", vmaAddr);
}
#ifdef __clang__
const auto CMD = std::format("llvm-addr2line -e {} -Cf {}", FPATH.c_str(), addrs);
#else
const auto CMD = std::format("addr2line -e {} -Cf {}", FPATH.c_str(), addrs);
#endif
const auto ADDR2LINE = execAndGet(CMD.c_str());
std::stringstream ssin(ADDR2LINE);
for (size_t i = 0; i < CALLSTACK.size(); ++i) {
finalCrashReport += std::format("\t#{} | {}", i, CALLSTACK[i].desc);
std::string functionInfo;
std::string fileLineInfo;
std::getline(ssin, functionInfo);
std::getline(ssin, fileLineInfo);
finalCrashReport += std::format("\n\t\t{}\n\t\t{}\n", functionInfo, fileLineInfo);
}
finalCrashReport += "\n\nLog tail:\n";
finalCrashReport += execAndGet(("cat \"" + Debug::logFile + "\" | tail -n 50").c_str());
finalCrashReport += Debug::rollingLog.substr(Debug::rollingLog.find("\n") + 1);
const auto HOME = getenv("HOME");
const auto CACHE_HOME = getenv("XDG_CACHE_HOME");
@@ -128,25 +151,18 @@ void CrashReporter::createAndSaveCrash(int sig) {
return;
std::ofstream ofs;
std::string path;
if (!CACHE_HOME || std::string(CACHE_HOME).empty()) {
if (!std::filesystem::exists(std::string(HOME) + "/.hyprland")) {
std::filesystem::create_directory(std::string(HOME) + "/.hyprland");
std::filesystem::permissions(std::string(HOME) + "/.hyprland", std::filesystem::perms::all, std::filesystem::perm_options::replace);
}
std::string reportDir;
path = std::string(HOME) + "/.hyprland/hyprlandCrashReport" + std::to_string(PID) + ".txt";
ofs.open(path, std::ios::trunc);
if (!CACHE_HOME || std::string(CACHE_HOME).empty())
reportDir = std::string(HOME) + "/.cache/hyprland";
else
reportDir = std::string(CACHE_HOME) + "/hyprland";
} else {
if (!std::filesystem::exists(std::string(CACHE_HOME) + "/hyprland")) {
std::filesystem::create_directory(std::string(CACHE_HOME) + "/hyprland");
std::filesystem::permissions(std::string(CACHE_HOME) + "/hyprland", std::filesystem::perms::all, std::filesystem::perm_options::replace);
}
if (!std::filesystem::exists(reportDir))
std::filesystem::create_directory(reportDir);
const auto path = reportDir + "/hyprlandCrashReport" + std::to_string(PID) + ".txt";
path = std::string(CACHE_HOME) + "/hyprland/hyprlandCrashReport" + std::to_string(PID) + ".txt";
ofs.open(path, std::ios::trunc);
}
ofs.open(path, std::ios::trunc);
ofs << finalCrashReport;

File diff suppressed because it is too large Load Diff

View File

@@ -3,24 +3,27 @@
#include "../Compositor.hpp"
#include <fstream>
#include "../helpers/MiscFunctions.hpp"
#include <functional>
namespace HyprCtl {
void startHyprCtlSocket();
std::string makeDynamicCall(const std::string& input);
class CHyprCtl {
public:
CHyprCtl();
// very simple thread-safe request method
inline bool requestMade = false;
inline bool requestReady = false;
inline std::string request = "";
std::string makeDynamicCall(const std::string& input);
std::shared_ptr<SHyprCtlCommand> registerCommand(SHyprCtlCommand cmd);
void unregisterCommand(const std::shared_ptr<SHyprCtlCommand>& cmd);
std::string getReply(std::string);
inline std::ifstream requestStream;
int m_iSocketFD = -1;
inline wl_event_source* hyprCtlTickSource = nullptr;
struct {
bool all = false;
} m_sCurrentRequestParams;
inline int iSocketFD = -1;
private:
void startHyprCtlSocket();
enum eHyprCtlOutputFormat {
FORMAT_NORMAL = 0,
FORMAT_JSON
};
std::vector<std::shared_ptr<SHyprCtlCommand>> m_vCommands;
};
inline std::unique_ptr<CHyprCtl> g_pHyprCtl;

View File

@@ -233,6 +233,6 @@ void CHyprDebugOverlay::draw() {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
wlr_box pMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
CBox pMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
}

View File

@@ -24,7 +24,7 @@ class CHyprMonitorDebugOverlay {
std::deque<float> m_dLastAnimationTicks;
std::chrono::high_resolution_clock::time_point m_tpLastFrame;
CMonitor* m_pMonitor = nullptr;
wlr_box m_wbLastDrawnBox;
CBox m_wbLastDrawnBox;
friend class CHyprRenderer;
};

View File

@@ -3,7 +3,7 @@
#include <pango/pangocairo.h>
CHyprNotificationOverlay::CHyprNotificationOverlay() {
g_pHookSystem->hookDynamic("focusedMon", [&](void* self, std::any param) {
g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) {
if (m_dNotifications.size() == 0)
return;
@@ -36,21 +36,34 @@ CHyprNotificationOverlay::CHyprNotificationOverlay() {
m_szIconFontName = fonts.substr(COLON + 2, LASTCHAR - (COLON + 2));
}
void CHyprNotificationOverlay::addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon) {
void CHyprNotificationOverlay::addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon, const float fontSize) {
const auto PNOTIF = m_dNotifications.emplace_back(std::make_unique<SNotification>()).get();
PNOTIF->text = text;
PNOTIF->color = color == CColor(0) ? ICONS_COLORS[icon] : color;
PNOTIF->started.reset();
PNOTIF->timeMs = timeMs;
PNOTIF->icon = icon;
PNOTIF->timeMs = timeMs;
PNOTIF->icon = icon;
PNOTIF->fontSize = fontSize;
for (auto& m : g_pCompositor->m_vMonitors) {
g_pCompositor->scheduleFrameForMonitor(m.get());
}
}
wlr_box CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
void CHyprNotificationOverlay::dismissNotifications(const int amount) {
if (amount == -1)
m_dNotifications.clear();
else {
const int AMT = std::min(amount, static_cast<int>(m_dNotifications.size()));
for (int i = 0; i < AMT; ++i) {
m_dNotifications.pop_front();
}
}
}
CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
static constexpr auto ANIM_DURATION_MS = 600.0;
static constexpr auto ANIM_LAG_MS = 100.0;
static constexpr auto NOTIF_LEFTBAR_SIZE = 5.0;
@@ -61,28 +74,25 @@ wlr_box CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
float offsetY = 10;
float maxWidth = 0;
const auto SCALE = pMonitor->scale;
const auto FONTSIZE = std::clamp((int)(13.f * ((pMonitor->vecPixelSize.x * SCALE) / 1920.f)), 8, 40);
const auto SCALE = pMonitor->scale;
const auto MONSIZE = pMonitor->vecPixelSize;
cairo_text_extents_t cairoExtents;
int iconW = 0, iconH = 0;
PangoLayout* pangoLayout;
PangoFontDescription* pangoFD;
pangoLayout = pango_cairo_create_layout(m_pCairo);
pangoFD = pango_font_description_from_string(("Sans " + std::to_string(FONTSIZE * ICON_SCALE)).c_str());
pango_layout_set_font_description(pangoLayout, pangoFD);
cairo_select_font_face(m_pCairo, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(m_pCairo, FONTSIZE);
const auto PBEZIER = g_pAnimationManager->getBezier("default");
for (auto& 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);
PangoLayout* pangoLayout = pango_cairo_create_layout(m_pCairo);
PangoFontDescription* pangoFD = pango_font_description_from_string(("Sans " + std::to_string(FONTSIZE * ICON_SCALE)).c_str());
pango_layout_set_font_description(pangoLayout, pangoFD);
cairo_set_font_size(m_pCairo, FONTSIZE);
// first rect (bg, col)
const float FIRSTRECTANIMP =
@@ -162,15 +172,15 @@ wlr_box CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
if (maxWidth < NOTIFSIZE.x)
maxWidth = NOTIFSIZE.x;
}
pango_font_description_free(pangoFD);
g_object_unref(pangoLayout);
pango_font_description_free(pangoFD);
g_object_unref(pangoLayout);
}
// cleanup notifs
std::erase_if(m_dNotifications, [](const auto& notif) { return notif->started.getMillis() > notif->timeMs; });
return wlr_box{(int)(pMonitor->vecPosition.x + pMonitor->vecSize.x - maxWidth - 20), (int)pMonitor->vecPosition.y, (int)maxWidth + 20, (int)offsetY + 10};
return CBox{(int)(pMonitor->vecPosition.x + pMonitor->vecSize.x - maxWidth - 20), (int)pMonitor->vecPosition.y, (int)maxWidth + 20, (int)offsetY + 10};
}
void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
@@ -201,7 +211,7 @@ void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
cairo_surface_flush(m_pCairoSurface);
wlr_box damage = drawNotifications(pMonitor);
CBox damage = drawNotifications(pMonitor);
g_pHyprRenderer->damageBox(&damage);
g_pHyprRenderer->damageBox(&m_bLastDamage);
@@ -224,6 +234,10 @@ void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
wlr_box pMonBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
CBox pMonBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
}
bool CHyprNotificationOverlay::hasAny() {
return !m_dNotifications.empty();
}

View File

@@ -10,16 +10,15 @@
#include <cairo/cairo.h>
enum eIconBackend
{
enum eIconBackend {
ICONS_BACKEND_NONE = 0,
ICONS_BACKEND_NF,
ICONS_BACKEND_FA
};
static const std::array<std::array<std::string, ICON_NONE + 1>, 3 /* backends */> ICONS_ARRAY = {
std::array<std::string, ICON_NONE + 1>{"[!]", "[i]", "[Hint]", "[Err]", "[?]", "[ok]", ""}, std::array<std::string, ICON_NONE + 1>{"", "", "", "", "", "󰸞", ""},
std::array<std::string, ICON_NONE + 1>{"", "", "", "", "", ""}};
std::array<std::string, ICON_NONE + 1>{"[!]", "[i]", "[Hint]", "[Err]", "[?]", "[ok]", ""},
std::array<std::string, ICON_NONE + 1>{"", "", "", "", "", "󰸞", ""}, std::array<std::string, ICON_NONE + 1>{"", "", "", "", "", ""}};
static const std::array<CColor, ICON_NONE + 1> ICONS_COLORS = {CColor{255.0 / 255.0, 204 / 255.0, 102 / 255.0, 1.0},
CColor{128 / 255.0, 255 / 255.0, 255 / 255.0, 1.0},
CColor{179 / 255.0, 255 / 255.0, 204 / 255.0, 1.0},
@@ -32,8 +31,9 @@ struct SNotification {
std::string text = "";
CColor color;
CTimer started;
float timeMs = 0;
eIcons icon = ICON_NONE;
float timeMs = 0;
eIcons icon = ICON_NONE;
float fontSize = 13.f;
};
class CHyprNotificationOverlay {
@@ -41,11 +41,13 @@ class CHyprNotificationOverlay {
CHyprNotificationOverlay();
void draw(CMonitor* pMonitor);
void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE);
void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE, const float fontSize = 13.f);
void dismissNotifications(const int amount);
bool hasAny();
private:
wlr_box drawNotifications(CMonitor* pMonitor);
wlr_box m_bLastDamage;
CBox drawNotifications(CMonitor* pMonitor);
CBox m_bLastDamage;
std::deque<std::unique_ptr<SNotification>> m_dNotifications;

View File

@@ -10,25 +10,24 @@ void Debug::init(const std::string& IS) {
}
void Debug::wlrLog(wlr_log_importance level, const char* fmt, va_list args) {
if (disableLogs && *disableLogs)
return;
if (level > wlr_log_get_verbosity())
return;
char* outputStr = nullptr;
std::ofstream ofs;
ofs.open(logFile, std::ios::out | std::ios::app);
char* outputStr = nullptr;
vasprintf(&outputStr, fmt, args);
std::string output = std::string(outputStr);
free(outputStr);
ofs << "[wlr] " << output << "\n";
rollingLog += output + "\n";
ofs.close();
if (!disableLogs || !**disableLogs) {
std::ofstream ofs;
ofs.open(logFile, std::ios::out | std::ios::app);
ofs << "[wlr] " << output << "\n";
ofs.close();
}
if (!disableStdout)
std::cout << output << "\n";

View File

@@ -1,13 +1,14 @@
#pragma once
#include <string>
#include <wlr/util/log.h>
#include <format>
#include <iostream>
#include <fstream>
#include <chrono>
#include "../includes.hpp"
#include "../helpers/MiscFunctions.hpp"
#define LOGMESSAGESIZE 1024
#define LOGMESSAGESIZE 1024
#define ROLLING_LOG_SIZE 4096
enum LogLevel {
NONE = -1,
@@ -20,19 +21,22 @@ enum LogLevel {
};
namespace Debug {
inline std::string logFile;
inline int64_t* disableLogs = nullptr;
inline int64_t* disableTime = nullptr;
inline bool disableStdout = false;
inline bool trace = false;
inline std::string logFile;
inline int64_t* const* disableLogs = nullptr;
inline int64_t* const* disableTime = nullptr;
inline bool disableStdout = false;
inline bool trace = false;
inline bool shuttingDown = false;
void init(const std::string& IS);
inline std::string rollingLog = ""; // rolling log contains the ROLLING_LOG_SIZE tail of the log
void init(const std::string& IS);
template <typename... Args>
void log(LogLevel level, std::format_string<Args...> fmt, Args&&... args) {
if (disableLogs && *disableLogs)
if (level == TRACE && !trace)
return;
if (level == TRACE && !trace)
if (shuttingDown)
return;
std::string logMsg = "";
@@ -47,12 +51,8 @@ namespace Debug {
default: break;
}
// log to a file
std::ofstream ofs;
ofs.open(logFile, std::ios::out | std::ios::app);
// print date and time to the ofs
if (disableTime && !*disableTime) {
if (disableTime && !**disableTime) {
#ifndef _LIBCPP_VERSION
logMsg += std::format("[{:%T}] ", std::chrono::hh_mm_ss{std::chrono::system_clock::now() - std::chrono::floor<std::chrono::days>(std::chrono::system_clock::now())});
#else
@@ -69,9 +69,18 @@ namespace Debug {
// 3. this is actually what std::format in stdlib does
logMsg += std::vformat(fmt.get(), std::make_format_args(args...));
ofs << logMsg << "\n";
rollingLog += logMsg + "\n";
if (rollingLog.size() > ROLLING_LOG_SIZE)
rollingLog = rollingLog.substr(rollingLog.size() - ROLLING_LOG_SIZE);
ofs.close();
if (!disableLogs || !**disableLogs) {
// log to a file
std::ofstream ofs;
ofs.open(logFile, std::ios::out | std::ios::app);
ofs << logMsg << "\n";
ofs.close();
}
// log it to the stdout too.
if (!disableStdout)

View File

@@ -13,15 +13,6 @@ inline PFNGLGETQUERYOBJECTUI64VEXTPROC glGetQueryObjectui64v;
#include "../../subprojects/tracy/public/tracy/TracyOpenGL.hpp"
inline void loadGLProc(void* pProc, const char* name) {
void* proc = (void*)eglGetProcAddress(name);
if (proc == NULL) {
Debug::log(CRIT, "[Tracy GPU Profiling] eglGetProcAddress({}) failed", name);
abort();
}
*(void**)pProc = proc;
}
#define TRACY_GPU_CONTEXT TracyGpuContext
#define TRACY_GPU_ZONE(e) TracyGpuZone(e)
#define TRACY_GPU_COLLECT TracyGpuCollect

131
src/desktop/Constraint.cpp Normal file
View File

@@ -0,0 +1,131 @@
#include "Constraint.hpp"
#include "WLSurface.hpp"
#include "../Compositor.hpp"
CConstraint::CConstraint(wlr_pointer_constraint_v1* constraint, CWLSurface* owner) : m_pOwner(owner), m_pConstraint(constraint) {
RASSERT(!constraint->data, "CConstraint: attempted to duplicate ownership");
constraint->data = this;
initSignals();
m_vCursorPosOnActivate = g_pInputManager->getMouseCoordsInternal();
g_pInputManager->m_vConstraints.push_back(this);
if (g_pCompositor->m_pLastFocus == m_pOwner->wlr())
activate();
}
CConstraint::~CConstraint() {
std::erase(g_pInputManager->m_vConstraints, this);
}
static void onConstraintDestroy(void* owner, void* data) {
const auto CONSTRAINT = (CConstraint*)owner;
CONSTRAINT->onDestroy();
}
static void onConstraintSetRegion(void* owner, void* data) {
const auto CONSTRAINT = (CConstraint*)owner;
CONSTRAINT->onSetRegion();
}
void CConstraint::initSignals() {
hyprListener_setConstraintRegion.initCallback(&m_pConstraint->events.set_region, ::onConstraintSetRegion, this, "CConstraint");
hyprListener_destroyConstraint.initCallback(&m_pConstraint->events.destroy, ::onConstraintDestroy, this, "CConstraint");
}
void CConstraint::onDestroy() {
hyprListener_setConstraintRegion.removeCallback();
hyprListener_destroyConstraint.removeCallback();
if (active() && isLocked())
g_pCompositor->warpCursorTo(logicPositionHint(), true);
// this is us
m_pOwner->m_pConstraint.reset();
}
void CConstraint::onSetRegion() {
if (!m_bActive)
return;
m_rRegion.set(&m_pConstraint->region);
m_vPositionHint = m_rRegion.closestPoint(m_vPositionHint);
g_pInputManager->simulateMouseMovement(); // to warp the cursor if anything's amiss
}
void CConstraint::onCommit() {
if (!m_bActive)
return;
const auto COMMITTED = m_pConstraint->current.committed;
if (COMMITTED & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) {
m_bHintSet = true;
m_vPositionHint = {m_pConstraint->current.cursor_hint.x, m_pConstraint->current.cursor_hint.y};
g_pInputManager->simulateMouseMovement();
}
if (COMMITTED & WLR_POINTER_CONSTRAINT_V1_STATE_REGION)
onSetRegion();
}
CRegion CConstraint::logicConstraintRegion() {
CRegion rg = m_rRegion;
const auto SURFBOX = m_pOwner->getSurfaceBoxGlobal();
const auto CONSTRAINTPOS = SURFBOX.has_value() ? SURFBOX->pos() : Vector2D{};
rg.translate(CONSTRAINTPOS);
return rg;
}
CWLSurface* CConstraint::owner() {
return m_pOwner;
}
bool CConstraint::isLocked() {
return m_pConstraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED;
}
Vector2D CConstraint::logicPositionHint() {
const auto SURFBOX = m_pOwner->getSurfaceBoxGlobal();
const auto CONSTRAINTPOS = SURFBOX.has_value() ? SURFBOX->pos() : Vector2D{};
return m_bHintSet ? CONSTRAINTPOS + m_vPositionHint : m_vCursorPosOnActivate;
}
void CConstraint::deactivate() {
if (!m_bActive)
return;
m_bActive = false;
if (isLocked())
g_pCompositor->warpCursorTo(logicPositionHint(), true);
if (m_pConstraint->lifetime == ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT)
m_bDead = true;
wlr_pointer_constraint_v1_send_deactivated(m_pConstraint);
}
void CConstraint::activate() {
if (m_bActive || m_bDead)
return;
m_bActive = true;
// TODO: hack, probably not a super duper great idea
if (g_pCompositor->m_sSeat.seat->pointer_state.focused_surface != m_pOwner->wlr()) {
const auto SURFBOX = m_pOwner->getSurfaceBoxGlobal();
const auto LOCAL = SURFBOX.has_value() ? logicPositionHint() - SURFBOX->pos() : Vector2D{};
wlr_seat_pointer_enter(g_pCompositor->m_sSeat.seat, m_pOwner->wlr(), LOCAL.x, LOCAL.y);
}
g_pCompositor->warpCursorTo(logicPositionHint(), true);
wlr_pointer_constraint_v1_send_activated(m_pConstraint);
}
bool CConstraint::active() {
return m_bActive;
}

View File

@@ -0,0 +1,44 @@
#pragma once
#include "../includes.hpp"
#include "../helpers/Region.hpp"
#include "../helpers/WLListener.hpp"
class CWLSurface;
class CConstraint {
public:
CConstraint(wlr_pointer_constraint_v1* constraint, CWLSurface* owner);
~CConstraint();
void onCommit();
void onDestroy();
void onSetRegion();
CRegion logicConstraintRegion();
bool isLocked();
Vector2D logicPositionHint();
void deactivate();
void activate();
bool active();
CWLSurface* owner();
private:
bool m_bActive = false;
CWLSurface* m_pOwner = nullptr;
wlr_pointer_constraint_v1* m_pConstraint;
CRegion m_rRegion;
bool m_bHintSet = false;
Vector2D m_vPositionHint = {-1, -1};
Vector2D m_vCursorPosOnActivate = {-1, -1};
// for oneshot constraints that have been activated once
bool m_bDead = false;
DYNLISTENER(destroyConstraint);
DYNLISTENER(setConstraintRegion);
void initSignals();
};

View File

@@ -0,0 +1,6 @@
#pragma once
#include <memory>
class CWorkspace;
typedef std::shared_ptr<CWorkspace> PHLWORKSPACE;

269
src/desktop/Popup.cpp Normal file
View File

@@ -0,0 +1,269 @@
#include "Popup.hpp"
#include "../config/ConfigValue.hpp"
#include "../Compositor.hpp"
CPopup::CPopup(CWindow* pOwner) : m_pWindowOwner(pOwner) {
initAllSignals();
}
CPopup::CPopup(SLayerSurface* pOwner) : m_pLayerOwner(pOwner) {
initAllSignals();
}
CPopup::CPopup(wlr_xdg_popup* popup, CPopup* pOwner) : m_pParent(pOwner), m_pWLR(popup) {
m_pWLR->base->data = this;
m_sWLSurface.assign(popup->base->surface, this);
m_pLayerOwner = pOwner->m_pLayerOwner;
m_pWindowOwner = pOwner->m_pWindowOwner;
m_vLastSize = {m_pWLR->current.geometry.width, m_pWLR->current.geometry.height};
unconstrain();
initAllSignals();
}
CPopup::~CPopup() {
m_sWLSurface.unassign();
if (m_pWLR)
m_pWLR->base->data = nullptr;
hyprListener_commitPopup.removeCallback();
hyprListener_repositionPopup.removeCallback();
hyprListener_mapPopup.removeCallback();
hyprListener_unmapPopup.removeCallback();
hyprListener_newPopup.removeCallback();
hyprListener_destroyPopup.removeCallback();
}
static void onNewPopup(void* owner, void* data) {
const auto POPUP = (CPopup*)owner;
POPUP->onNewPopup((wlr_xdg_popup*)data);
}
static void onMapPopup(void* owner, void* data) {
const auto POPUP = (CPopup*)owner;
POPUP->onMap();
}
static void onDestroyPopup(void* owner, void* data) {
const auto POPUP = (CPopup*)owner;
POPUP->onDestroy();
}
static void onUnmapPopup(void* owner, void* data) {
const auto POPUP = (CPopup*)owner;
POPUP->onUnmap();
}
static void onCommitPopup(void* owner, void* data) {
const auto POPUP = (CPopup*)owner;
POPUP->onCommit();
}
static void onRepositionPopup(void* owner, void* data) {
const auto POPUP = (CPopup*)owner;
POPUP->onReposition();
}
void CPopup::initAllSignals() {
if (!m_pWLR) {
if (m_pWindowOwner)
hyprListener_newPopup.initCallback(&m_pWindowOwner->m_uSurface.xdg->events.new_popup, ::onNewPopup, this, "CPopup Head");
else if (m_pLayerOwner)
hyprListener_newPopup.initCallback(&m_pLayerOwner->layerSurface->events.new_popup, ::onNewPopup, this, "CPopup Head");
else
ASSERT(false);
return;
}
hyprListener_repositionPopup.initCallback(&m_pWLR->events.reposition, ::onRepositionPopup, this, "CPopup");
hyprListener_destroyPopup.initCallback(&m_pWLR->events.destroy, ::onDestroyPopup, this, "CPopup");
hyprListener_mapPopup.initCallback(&m_sWLSurface.wlr()->events.map, ::onMapPopup, this, "CPopup");
hyprListener_unmapPopup.initCallback(&m_sWLSurface.wlr()->events.unmap, ::onUnmapPopup, this, "CPopup");
hyprListener_commitPopup.initCallback(&m_sWLSurface.wlr()->events.commit, ::onCommitPopup, this, "CPopup");
hyprListener_newPopup.initCallback(&m_pWLR->base->events.new_popup, ::onNewPopup, this, "CPopup");
}
void CPopup::onNewPopup(wlr_xdg_popup* popup) {
const auto POPUP = m_vChildren.emplace_back(std::make_unique<CPopup>(popup, this)).get();
Debug::log(LOG, "New popup at wlr {:x} and hl {:x}", (uintptr_t)popup, (uintptr_t)POPUP);
}
void CPopup::onDestroy() {
m_bInert = true;
if (!m_pParent)
return; // head node
std::erase_if(m_pParent->m_vChildren, [this](const auto& other) { return other.get() == this; });
}
void CPopup::onMap() {
m_vLastSize = {m_pWLR->base->current.geometry.width, m_pWLR->base->current.geometry.height};
const auto COORDS = coordsGlobal();
CBox box;
wlr_surface_get_extends(m_sWLSurface.wlr(), box.pWlr());
box.applyFromWlr().translate(COORDS).expand(4);
g_pHyprRenderer->damageBox(&box);
m_vLastPos = coordsRelativeToParent();
g_pInputManager->simulateMouseMovement();
m_pSubsurfaceHead = std::make_unique<CSubsurface>(this);
unconstrain();
sendScale();
if (m_pLayerOwner && m_pLayerOwner->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP)
g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner->layer));
}
void CPopup::onUnmap() {
m_vLastSize = {m_pWLR->base->current.geometry.width, m_pWLR->base->current.geometry.height};
const auto COORDS = coordsGlobal();
CBox box;
wlr_surface_get_extends(m_sWLSurface.wlr(), box.pWlr());
box.applyFromWlr().translate(COORDS).expand(4);
g_pHyprRenderer->damageBox(&box);
m_pSubsurfaceHead.reset();
g_pInputManager->simulateMouseMovement();
if (m_pLayerOwner && m_pLayerOwner->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP)
g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner->layer));
}
void CPopup::onCommit(bool ignoreSiblings) {
if (m_pWLR->base->initial_commit) {
wlr_xdg_surface_schedule_configure(m_pWLR->base);
return;
}
if (m_pWindowOwner && (!m_pWindowOwner->m_bIsMapped || !m_pWindowOwner->m_pWorkspace->m_bVisible)) {
m_vLastSize = {m_pWLR->base->current.geometry.width, m_pWLR->base->current.geometry.height};
static auto PLOGDAMAGE = CConfigValue<Hyprlang::INT>("debug:log_damage");
if (*PLOGDAMAGE)
Debug::log(LOG, "Refusing to commit damage from a subsurface of {} because it's invisible.", m_pWindowOwner);
return;
}
if (!m_pWLR->base->surface->mapped)
return;
const auto COORDS = coordsGlobal();
const auto COORDSLOCAL = coordsRelativeToParent();
if (m_vLastSize != Vector2D{m_pWLR->base->current.geometry.width, m_pWLR->base->current.geometry.height} || m_bRequestedReposition || m_vLastPos != COORDSLOCAL) {
CBox box = {localToGlobal(m_vLastPos), m_vLastSize};
g_pHyprRenderer->damageBox(&box);
m_vLastSize = {m_pWLR->base->current.geometry.width, m_pWLR->base->current.geometry.height};
box = {COORDS, m_vLastSize};
g_pHyprRenderer->damageBox(&box);
m_vLastPos = COORDSLOCAL;
}
if (!ignoreSiblings && m_pSubsurfaceHead)
m_pSubsurfaceHead->recheckDamageForSubsurfaces();
g_pHyprRenderer->damageSurface(m_sWLSurface.wlr(), COORDS.x, COORDS.y);
m_bRequestedReposition = false;
if (m_pLayerOwner && m_pLayerOwner->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP)
g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner->layer));
}
void CPopup::onReposition() {
Debug::log(LOG, "Popup {:x} requests reposition", (uintptr_t)this);
m_bRequestedReposition = true;
m_vLastPos = coordsRelativeToParent();
unconstrain();
}
void CPopup::unconstrain() {
const auto COORDS = t1ParentCoords();
const auto PMONITOR = g_pCompositor->getMonitorFromVector(COORDS);
if (!PMONITOR)
return;
CBox box = {PMONITOR->vecPosition.x - COORDS.x, PMONITOR->vecPosition.y - COORDS.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
wlr_xdg_popup_unconstrain_from_box(m_pWLR, box.pWlr());
}
Vector2D CPopup::coordsRelativeToParent() {
Vector2D offset;
CPopup* current = this;
offset -= {m_pWLR->base->current.geometry.x, m_pWLR->base->current.geometry.y};
while (current->m_pParent) {
offset += {current->m_sWLSurface.wlr()->current.dx, current->m_sWLSurface.wlr()->current.dy};
offset += {current->m_pWLR->current.geometry.x, current->m_pWLR->current.geometry.y};
current = current->m_pParent;
}
return offset;
}
Vector2D CPopup::coordsGlobal() {
return localToGlobal(coordsRelativeToParent());
}
Vector2D CPopup::localToGlobal(const Vector2D& rel) {
return t1ParentCoords() + rel;
}
Vector2D CPopup::t1ParentCoords() {
if (m_pWindowOwner)
return m_pWindowOwner->m_vRealPosition.value();
if (m_pLayerOwner)
return m_pLayerOwner->realPosition.value();
ASSERT(false);
return {};
}
void CPopup::recheckTree() {
CPopup* curr = this;
while (curr->m_pParent) {
curr = curr->m_pParent;
}
curr->recheckChildrenRecursive();
}
void CPopup::recheckChildrenRecursive() {
for (auto& c : m_vChildren) {
c->onCommit(true);
c->recheckChildrenRecursive();
}
}
Vector2D CPopup::size() {
return m_vLastSize;
}
void CPopup::sendScale() {
if (m_pWindowOwner)
g_pCompositor->setPreferredScaleForSurface(m_sWLSurface.wlr(), m_pWindowOwner->m_pWLSurface.m_fLastScale);
else if (m_pLayerOwner)
g_pCompositor->setPreferredScaleForSurface(m_sWLSurface.wlr(), m_pLayerOwner->surface.m_fLastScale);
else
UNREACHABLE();
}

72
src/desktop/Popup.hpp Normal file
View File

@@ -0,0 +1,72 @@
#pragma once
#include <vector>
#include <memory>
#include "Subsurface.hpp"
struct SLayerSurface;
class CPopup {
public:
// dummy head nodes
CPopup(CWindow* pOwner);
CPopup(SLayerSurface* pOwner);
// real nodes
CPopup(wlr_xdg_popup* popup, CPopup* pOwner);
~CPopup();
Vector2D coordsRelativeToParent();
Vector2D coordsGlobal();
Vector2D size();
void onNewPopup(wlr_xdg_popup* popup);
void onDestroy();
void onMap();
void onUnmap();
void onCommit(bool ignoreSiblings = false);
void onReposition();
void recheckTree();
CWLSurface m_sWLSurface;
private:
// T1 owners, each popup has to have one of these
CWindow* m_pWindowOwner = nullptr;
SLayerSurface* m_pLayerOwner = nullptr;
// T2 owners
CPopup* m_pParent = nullptr;
wlr_xdg_popup* m_pWLR = nullptr;
Vector2D m_vLastSize = {};
Vector2D m_vLastPos = {};
bool m_bRequestedReposition = false;
bool m_bInert = false;
//
std::vector<std::unique_ptr<CPopup>> m_vChildren;
std::unique_ptr<CSubsurface> m_pSubsurfaceHead;
// signals
DYNLISTENER(newPopup);
DYNLISTENER(destroyPopup);
DYNLISTENER(mapPopup);
DYNLISTENER(unmapPopup);
DYNLISTENER(commitPopup);
DYNLISTENER(repositionPopup);
void initAllSignals();
void unconstrain();
void recheckChildrenRecursive();
void sendScale();
Vector2D localToGlobal(const Vector2D& rel);
Vector2D t1ParentCoords();
};

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