1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
|
# Pyr: plain outputs honor grid/zone_gap around the workarea like a physical zone (maximize, half/quarter slots, Move snap previews); stitched layouts unchanged; WAYFIRE_ABI unchanged
# Pyr: the Cube background choices list only what the 3d-windows Cube draws (Simple, Warp tunnel, Hyperspace, None); metadata only, WAYFIRE_ABI unchanged
# Pyr shell naming: session description only; compositor sources unchanged
# Hedron Sprint 3 follow-up: skip closing animation if snapshot allocation fails
# Hedron Sprint 3 (2026-10-28): optional shell seed, session logout, atomic config watches
# SrcUX Sprint 1 (panache work package, 2026-10-28): SrcUX keymap and plugin set in the shipped wayfire.ini (no code change; WAYFIRE_ABI unchanged), on top of the installed launch-origin-review r75
# SrcUX Sprint 2 (2026-10-28): Super+Ctrl+T theme chooser, Super+Ctrl+W live-sky cycle (wayfire-background-cycle), first-login welcome notification (wayfire-welcome); shipped wayfire.ini and two scripts only, WAYFIRE_ABI unchanged
# Copyright 2019-2026 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=8
inherit dot-a meson toolchain-funcs
DESCRIPTION="compiz like 3D wayland compositor"
HOMEPAGE="https://github.com/WayfireWM/wayfire"
if [[ ${PV} == 9999 ]]; then
inherit git-r3
EGIT_REPO_URI="https://github.com/WayfireWM/${PN}.git"
SLOT="0/0.12"
IUSE="vulkan"
# vulkan support is experimental and uses a bundled fork of wlroots
# keep it only in the live ebuild for now
RDEPEND="vulkan? ( media-libs/vulkan-loader )"
DEPEND="vulkan? ( dev-util/vulkan-headers )"
COMMON_DEPEND="
!vulkan? (
gui-libs/wlroots:0.20[drm(+),libinput(+),x11-backend,X?]
)
vulkan? (
dev-libs/libliftoff
media-libs/lcms:2
media-libs/libdisplay-info:=
media-libs/mesa
sys-auth/seatd:=
x11-libs/libdrm
x11-libs/xcb-util-errors
x11-libs/xcb-util-renderutil
x11-libs/xcb-util-wm
)
"
else
SRC_URI="https://github.com/WayfireWM/${PN}/releases/download/v${PV}/${P}.tar.xz"
KEYWORDS="~amd64 ~arm64 ~riscv"
SLOT="0/$(ver_cut 1-2)"
COMMON_DEPEND="gui-libs/wlroots:0.20[drm(+),libinput(+),x11-backend,X?]"
fi
LICENSE="MIT"
IUSE+=" X +dbus +gles3 nls openmp test"
RESTRICT="!test? ( test )"
# bundled wlroots has the following dependency string according to included headers.
# wlroots[drm,gles2-renderer,libinput,x11-backend?,X?]
# enable x11-backend with X and vice versa
COMMON_DEPEND+="
dev-cpp/nlohmann_json
dev-libs/glib:2
dev-libs/libevdev
dev-libs/libinput:=
dev-libs/wayland
dev-libs/yyjson:=
>=dev-libs/wayland-protocols-1.12
gui-libs/wf-config:${SLOT}
media-libs/glm
media-libs/libglvnd
media-libs/libjpeg-turbo:=
media-libs/libpng:=
virtual/libudev:=
x11-libs/cairo
x11-libs/libxkbcommon
x11-libs/pango
x11-libs/pixman
dbus? ( sys-apps/dbus )
X? ( x11-libs/libxcb:= )
"
RDEPEND+="
>=dev-lang/python-3.11
${COMMON_DEPEND}
x11-misc/xkeyboard-config
"
DEPEND+="
${COMMON_DEPEND}
test? ( dev-cpp/doctest )
"
BDEPEND="
dev-util/wayland-scanner
virtual/pkgconfig
openmp? (
|| (
sys-devel/gcc[openmp]
llvm-runtimes/clang-runtime[openmp]
)
)
nls? (
sys-devel/gettext
)
"
PATCHES=(
"${FILESDIR}"/${P}-transparent-cube.patch
"${FILESDIR}"/${P}-rotate-layer-shell.patch
"${FILESDIR}"/${P}-screensaver-layer.patch
"${FILESDIR}"/${P}-desktop-sampling.patch
"${FILESDIR}"/${P}-cube-damage-stacking.patch
"${FILESDIR}"/${P}-cube-panel-overlay.patch
"${FILESDIR}"/${P}-stitched-outputs.patch
"${FILESDIR}"/${P}-virtual-output-polish.patch
"${FILESDIR}"/${P}-wcm-displays.patch
"${FILESDIR}"/${P}-window-scope.patch
"${FILESDIR}"/${P}-float-on-top.patch
"${FILESDIR}"/${P}-physical-tiling.patch
"${FILESDIR}"/${P}-cube-key-repeat.patch
"${FILESDIR}"/${P}-cube-repeat-minimum-20.patch
"${FILESDIR}"/${P}-scope-toggle.patch
"${FILESDIR}"/${P}-dialog-family-stacking.patch
"${FILESDIR}"/${P}-physical-grid.patch
"${FILESDIR}"/${P}-grid-preview.patch
"${FILESDIR}"/${P}-grid-cycle.patch
"${FILESDIR}"/${P}-physical-output-focus.patch
"${FILESDIR}"/${P}-oswitch-local-symbols.patch
"${FILESDIR}"/${P}-oswitch-wrap.patch
"${FILESDIR}"/${P}-popup-physical-scope.patch
"${FILESDIR}"/${P}-move-snapping.patch
"${FILESDIR}"/${P}-move-held-redraw.patch
"${FILESDIR}"/${P}-workspace-backgrounds.patch
"${FILESDIR}"/${P}-show-desktop-workspace.patch
"${FILESDIR}"/${P}-vswitch-held-target.patch
"${FILESDIR}"/${P}-decoration-window-menu.patch
"${FILESDIR}"/${P}-layer-move-old-damage.patch
"${FILESDIR}"/${P}-workspace-grid-events.patch
"${FILESDIR}"/${P}-r35-fullscreen-subpasses.patch
"${FILESDIR}"/${P}-r36-cube-fixed-top.patch
"${FILESDIR}"/${P}-r37-cube-carried-visibility.patch
"${FILESDIR}"/${P}-r38-cube-workspace-lifecycle.patch
"${FILESDIR}"/${P}-r39-cube-workspace-rows.patch
"${FILESDIR}"/${P}-r40-cube-row-translation.patch
"${FILESDIR}"/${P}-r41-cube-complete-row-translation.patch
"${FILESDIR}"/${P}-r42-grid-monitor-window-move.patch
"${FILESDIR}"/${P}-r43-cube-mouse-overview.patch
"${FILESDIR}"/${P}-r44-cube-rigid-stack.patch
"${FILESDIR}"/${P}-r45-cube-stack-tilt.patch
"${FILESDIR}"/${P}-r46-cube-resting-faces.patch
"${FILESDIR}"/${P}-r47-cube-direct-drag.patch
"${FILESDIR}"/${P}-r48-cube-wheel-zoom.patch
"${FILESDIR}"/${P}-r49-cube-square-footprint.patch
"${FILESDIR}"/${P}-r50-cube-center-pivot.patch
"${FILESDIR}"/${P}-r51-cube-centered-entry.patch
"${FILESDIR}"/${P}-r53-cube-warp.patch
"${FILESDIR}"/${P}-r55-cube-backdrop-opacity.patch
"${FILESDIR}"/${P}-r56-cube-warp-rest.patch
"${FILESDIR}"/${P}-r57-cube-hyperspace.patch
"${FILESDIR}"/${P}-r58-cube-nebula.patch
"${FILESDIR}"/${P}-r59-ambient-background.patch
"${FILESDIR}"/${P}-r60-ambient-package-split.patch
"${FILESDIR}"/${P}-r65-output-transforms.patch
"${FILESDIR}"/${P}-drag-escape.patch
"${FILESDIR}"/${P}-r67-grid-gap.patch
"${FILESDIR}"/${P}-r68-ipc-control.patch
"${FILESDIR}"/${P}-ipc-backpressure.patch
"${FILESDIR}"/${P}-r71-switch-tile-exclusivity.patch
"${FILESDIR}"/${P}-r71-cube-teardown-backgrounds.patch
"${FILESDIR}"/${P}-r71-stitch-noop-reload.patch
"${FILESDIR}"/${P}-r72-review-followups.patch
"${FILESDIR}"/${P}-r73-stitch-persist.patch
"${FILESDIR}"/${P}-r74-review-lows.patch
"${FILESDIR}/wayfire-0.11.0-launch-origin-activation.patch"
"${FILESDIR}/wayfire-0.11.0-launch-origin-aliases.patch"
"${FILESDIR}/wayfire-0.11.0-launch-origin-plugin.patch"
"${FILESDIR}/wayfire-0.11.0-srcux-keymap.patch"
"${FILESDIR}/wayfire-0.11.0-sprint2-desktop.patch"
"${FILESDIR}/wayfire-0.11.0-hedron-session.patch"
"${FILESDIR}/wayfire-0.11.0-snapshot-allocation-failure.patch"
"${FILESDIR}/wayfire-0.11.0-qol-1.patch"
"${FILESDIR}/wayfire-0.11.0-cube-background-choices.patch"
"${FILESDIR}/wayfire-0.11.0-r83-unzoned-gap.patch"
)
# The local patches change the plugin ABI (scene layer indices, class layouts).
# Tie the subslot to WAYFIRE_API_ABI_VERSION so := consumers rebuild whenever a
# patch bumps it; src_prepare refuses to build if the two drift apart.
# wf-config above retains its upstream 0.11 subslot.
WAYFIRE_ABI="20260918"
SLOT="${SLOT}.abi${WAYFIRE_ABI}"
pkg_pretend() {
[[ ${MERGE_TYPE} != binary ]] && use openmp && tc-check-openmp
}
pkg_setup() {
[[ ${MERGE_TYPE} != binary ]] && use openmp && tc-check-openmp
}
src_prepare() {
default
local abi
abi=$(sed -n "s/^#define WAYFIRE_API_ABI_VERSION_MACRO \([0-9']*\)$/\1/p" \
src/api/wayfire/plugin.hpp) || die
abi=${abi//\'/}
if [[ ${abi} != "${WAYFIRE_ABI}" ]]; then
die "WAYFIRE_API_ABI_VERSION is '${abi}' but the subslot says '${WAYFIRE_ABI}'; update WAYFIRE_ABI"
fi
local dbusrunsession=$(usev dbus dbus-run-session)
sed -e "s:@EPREFIX@:${EPREFIX}:g" -e "s:@DBUS_RUN_SESSION@:${dbusrunsession}:" \
"${FILESDIR}"/wayfire-session-3 > "${T}"/wayfire-session || die
sed -e "s:@EPREFIX@:${EPREFIX}:" \
"${FILESDIR}"/wayfire-session-pyr.desktop > "${T}"/wayfire-session.desktop || die
}
src_configure() {
lto-guarantee-fat
local emesonargs=(
$(meson_feature test tests)
$(meson_feature X xwayland)
$(meson_use gles3 enable_gles32)
$(meson_feature nls build_locales)
$(meson_use openmp enable_openmp)
-Duse_system_wfconfig=enabled
)
if [[ ${PV} == 9999 ]]; then
emesonargs+=(
$(meson_feature !vulkan use_system_wlroots)
$(meson_use vulkan vulkan_effects)
)
else
emesonargs+=(
-Duse_system_wlroots=enabled
-Dvulkan_effects=false
)
fi
meson_src_configure
}
src_install() {
meson_src_install
dobin "${T}"/wayfire-session
insinto "/usr/share/wayland-sessions/"
insopts -m644
doins wayfire.desktop
doins "${T}"/wayfire-session.desktop
insinto "/usr/share/wayfire/"
doins wayfire.ini
# Started by the shipped wayfire.ini: Super+Ctrl+W and the first-login notification.
exeinto /usr/libexec/wayfire
newexe "${FILESDIR}"/wayfire-background-cycle wayfire-background-cycle-legacy
newexe "${FILESDIR}"/wayfire-welcome wayfire-welcome-legacy
newexe "${FILESDIR}"/wayfire-background-cycle-hedron wayfire-background-cycle
newexe "${FILESDIR}"/wayfire-welcome-hedron wayfire-welcome
insinto "/etc"
doins "${FILESDIR}"/wayfire.env
strip-lto-bytecode
}
|