mirror of
https://github.com/swaywm/sway.git
synced 2025-10-29 05:40:18 -04:00
Compare commits
242 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
055be4ec35 | ||
|
|
b7eb6177e1 | ||
|
|
90d3270970 | ||
|
|
ecfea6b8ae | ||
|
|
b4a9a1716f | ||
|
|
d9e615c507 | ||
|
|
bc96d0acdf | ||
|
|
a7d9535eb3 | ||
|
|
7c1e192ea3 | ||
|
|
50a8750e01 | ||
|
|
a41b25020d | ||
|
|
35b69158d7 | ||
|
|
862e9b8c20 | ||
|
|
68ac52ffc2 | ||
|
|
e6fc3ffa3f | ||
|
|
70c51c44f6 | ||
|
|
ca45c22376 | ||
|
|
c5456be750 | ||
|
|
aaab7f961e | ||
|
|
73c244fb48 | ||
|
|
b3dcde8d69 | ||
|
|
0770a8d643 | ||
|
|
340505bb6f | ||
|
|
f50e307227 | ||
|
|
87fbcf0574 | ||
|
|
357d341f8f | ||
|
|
14fbe9242f | ||
|
|
e50b16a699 | ||
|
|
cb33701f5e | ||
|
|
08142c3f3a | ||
|
|
3826535ab0 | ||
|
|
f57c82a6f7 | ||
|
|
8d7c756276 | ||
|
|
94c819cc1f | ||
|
|
6fed1f9d89 | ||
|
|
bac8c0f4d0 | ||
|
|
c7d7d56f61 | ||
|
|
a1ac2a2e93 | ||
|
|
56f2db062d | ||
|
|
0cd45d4ad2 | ||
|
|
3d6b9a2848 | ||
|
|
e28e6484e8 | ||
|
|
4f59eeef05 | ||
|
|
c2f08075ec | ||
|
|
170c9c9525 | ||
|
|
eb8acfd7b1 | ||
|
|
25ea1a0af2 | ||
|
|
4b15b3427f | ||
|
|
17f7c1b782 | ||
|
|
6c27c2cdf2 | ||
|
|
1ab573bf54 | ||
|
|
0a740a24d9 | ||
|
|
3d401d9390 | ||
|
|
6816b51c86 | ||
|
|
9fb9e9f7d5 | ||
|
|
7e7994dbb2 | ||
|
|
63689bfb83 | ||
|
|
45267bb576 | ||
|
|
534491d3aa | ||
|
|
005924f260 | ||
|
|
88c7b4a7eb | ||
|
|
1b47277962 | ||
|
|
5cfcd1c7c2 | ||
|
|
8fecf3aa8c | ||
|
|
fb6d61b58f | ||
|
|
810142dcc4 | ||
|
|
a4072486de | ||
|
|
652019d6da | ||
|
|
3fbff5b4bb | ||
|
|
8d3a52aa30 | ||
|
|
6021f4d83f | ||
|
|
4ab411cab0 | ||
|
|
f9945d81fb | ||
|
|
8ac1f72c9e | ||
|
|
6cac61b6b9 | ||
|
|
6894b498a8 | ||
|
|
5b8874e3f4 | ||
|
|
38a42f97d4 | ||
|
|
0e19d85d37 | ||
|
|
86ff19fade | ||
|
|
1d4632f97f | ||
|
|
0153bc92ab | ||
|
|
d3e1c13e1f | ||
|
|
8a8c78deac | ||
|
|
7733bf9963 | ||
|
|
3f0b3f8f9b | ||
|
|
4943534929 | ||
|
|
240a69ad63 | ||
|
|
ab2e1f5817 | ||
|
|
53126cdceb | ||
|
|
92c82e6952 | ||
|
|
e51ecf71aa | ||
|
|
0a9b0b83eb | ||
|
|
583862e6d1 | ||
|
|
cc482228a4 | ||
|
|
541183b322 | ||
|
|
5e6a6ea340 | ||
|
|
8f089f0229 | ||
|
|
cb246cb9c2 | ||
|
|
a25645a5a6 | ||
|
|
ab455bbada | ||
|
|
c2d6aff64c | ||
|
|
4b185a0fe0 | ||
|
|
d148560f50 | ||
|
|
30434b2beb | ||
|
|
3a49409dae | ||
|
|
2f5b3c0999 | ||
|
|
61cc08cf3c | ||
|
|
8238e5242b | ||
|
|
5d7b9a8320 | ||
|
|
9dcccf784b | ||
|
|
048e304b8a | ||
|
|
e3d9cc2aa5 | ||
|
|
962e1e70a6 | ||
|
|
8a60f30423 | ||
|
|
7fab75a7a6 | ||
|
|
0da0d37f3d | ||
|
|
38005bd854 | ||
|
|
10e50e6bf9 | ||
|
|
c1031d8465 | ||
|
|
4852087e61 | ||
|
|
851b8c6fb6 | ||
|
|
d093c2e358 | ||
|
|
3ff60987f3 | ||
|
|
8acb0482da | ||
|
|
30c858423d | ||
|
|
0b08dce08c | ||
|
|
f177d05441 | ||
|
|
3ab1f0ca3d | ||
|
|
60f06fc4f1 | ||
|
|
cff16d32f9 | ||
|
|
e3f0ba4cd9 | ||
|
|
3629a832e5 | ||
|
|
a6c0441ee0 | ||
|
|
c7c0a5a1b3 | ||
|
|
a1838c5522 | ||
|
|
0c60d1581f | ||
|
|
c55dff95bc | ||
|
|
801bc76ce3 | ||
|
|
f293418d9d | ||
|
|
4eb86fce07 | ||
|
|
1d783794b5 | ||
|
|
4faf0f9098 | ||
|
|
bbadf9b8b1 | ||
|
|
e2409aa496 | ||
|
|
5312376077 | ||
|
|
fec3da7d58 | ||
|
|
a2c73c9b8b | ||
|
|
6111297d91 | ||
|
|
96db66abf0 | ||
|
|
fdc4318ac6 | ||
|
|
463c4c9369 | ||
|
|
f23d100747 | ||
|
|
03483ff370 | ||
|
|
62fd8c4d01 | ||
|
|
78fa4e9856 | ||
|
|
4cfcb3643b | ||
|
|
d417a8fcd0 | ||
|
|
f38719f575 | ||
|
|
1e53007bc3 | ||
|
|
e7c972b04a | ||
|
|
839434abc0 | ||
|
|
015e357fce | ||
|
|
a63027245a | ||
|
|
17ecb9eb1d | ||
|
|
af0d4a048a | ||
|
|
7e0c0dda42 | ||
|
|
7d93652105 | ||
|
|
35d8adefc4 | ||
|
|
8363699f14 | ||
|
|
ce6b2db0f2 | ||
|
|
db76fefd0c | ||
|
|
dd063a0ef7 | ||
|
|
17e2e52c6d | ||
|
|
7f1cd0b73b | ||
|
|
f855b0898b | ||
|
|
c90cb37b2a | ||
|
|
9a9be01ad4 | ||
|
|
a2757e5f16 | ||
|
|
a0b3606f17 | ||
|
|
00e9a94152 | ||
|
|
63345977e2 | ||
|
|
cdff4f7c74 | ||
|
|
b73f54a966 | ||
|
|
b6da218974 | ||
|
|
861dde100a | ||
|
|
e9dd218231 | ||
|
|
74e507962e | ||
|
|
023f6b0a50 | ||
|
|
1537c9dae5 | ||
|
|
48069097ea | ||
|
|
266cd4515a | ||
|
|
e940acd374 | ||
|
|
9765c29be1 | ||
|
|
034d02f8a5 | ||
|
|
785a459a55 | ||
|
|
f957c7e658 | ||
|
|
d7a76d381b | ||
|
|
29b3f00e6f | ||
|
|
0496477f92 | ||
|
|
a0c0349934 | ||
|
|
fb5eadc363 | ||
|
|
c5ba7f23a5 | ||
|
|
f4a6b0395f | ||
|
|
14bff7b451 | ||
|
|
4f9ce4675c | ||
|
|
fc6b8d6af2 | ||
|
|
4fe054c6db | ||
|
|
cfb292cca7 | ||
|
|
af28ac04a4 | ||
|
|
6045ad9a02 | ||
|
|
b83e5aaa54 | ||
|
|
be840f730e | ||
|
|
980a4e0211 | ||
|
|
f2b2a81149 | ||
|
|
77b9ddabe2 | ||
|
|
f00f964abf | ||
|
|
7288f77bbe | ||
|
|
f9c0f043e5 | ||
|
|
ae7c1b139a | ||
|
|
c30c451907 | ||
|
|
c3279944fb | ||
|
|
5a3621460f | ||
|
|
6576b99c24 | ||
|
|
b44015578a | ||
|
|
9ba1beee58 | ||
|
|
f344e9d5a5 | ||
|
|
951a22c244 | ||
|
|
32e5e5232d | ||
|
|
3e956b9229 | ||
|
|
05e895c463 | ||
|
|
9a1c411abd | ||
|
|
b881c2e84c | ||
|
|
6e4ccb99c3 | ||
|
|
9bb45a4037 | ||
|
|
7e74a49142 | ||
|
|
4d4c88f0a7 | ||
|
|
3f327b3db0 | ||
|
|
a3a9ec1211 | ||
|
|
50073dc579 | ||
|
|
fc2796aee8 | ||
|
|
274a5fcb73 |
138 changed files with 2835 additions and 1620 deletions
|
|
@ -29,12 +29,12 @@ sources:
|
|||
tasks:
|
||||
- wlroots: |
|
||||
cd wlroots
|
||||
meson --prefix=/usr build -Dexamples=false
|
||||
meson setup --prefix=/usr build -Dexamples=false
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
- setup: |
|
||||
cd sway
|
||||
meson build --fatal-meson-warnings -Dauto_features=enabled -Dtray=disabled
|
||||
meson setup build --fatal-meson-warnings -Dauto_features=enabled -Dtray=disabled
|
||||
- build: |
|
||||
cd sway
|
||||
ninja -C build
|
||||
|
|
@ -52,5 +52,5 @@ tasks:
|
|||
mkdir subprojects
|
||||
ln -s ../../wlroots subprojects/wlroots
|
||||
rm -rf build
|
||||
meson build --fatal-meson-warnings --default-library=static --force-fallback-for=wlroots
|
||||
meson setup build --fatal-meson-warnings --default-library=static --force-fallback-for=wlroots
|
||||
ninja -C build
|
||||
|
|
|
|||
|
|
@ -26,12 +26,12 @@ sources:
|
|||
tasks:
|
||||
- wlroots: |
|
||||
cd wlroots
|
||||
meson --prefix=/usr build -Dexamples=false
|
||||
meson setup --prefix=/usr build -Dexamples=false
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
- setup: |
|
||||
cd sway
|
||||
meson build --fatal-meson-warnings -Dauto_features=enabled -Dsd-bus-provider=libsystemd
|
||||
meson setup build --fatal-meson-warnings -Dauto_features=enabled -Dsd-bus-provider=libsystemd
|
||||
- build: |
|
||||
cd sway
|
||||
ninja -C build
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ packages:
|
|||
- x11/libX11
|
||||
- x11/pixman
|
||||
- x11/xcb-util-wm
|
||||
- x11-servers/xwayland-devel
|
||||
- x11-servers/xwayland
|
||||
- misc/hwdata
|
||||
sources:
|
||||
- https://github.com/swaywm/sway
|
||||
|
|
@ -39,7 +39,7 @@ tasks:
|
|||
cd subprojects
|
||||
ln -s ../../wlroots wlroots
|
||||
cd ..
|
||||
meson build --fatal-meson-warnings -Dtray=enabled -Dsd-bus-provider=basu
|
||||
meson setup build --fatal-meson-warnings -Dtray=enabled -Dsd-bus-provider=basu
|
||||
- build: |
|
||||
cd sway
|
||||
ninja -C build
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ _\* Compile-time dep_
|
|||
|
||||
نفذ هذه الأوامر:
|
||||
|
||||
meson build/
|
||||
meson setup build/
|
||||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
|
|
|
|||
66
README.az.md
Normal file
66
README.az.md
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# sway
|
||||
|
||||
sway [i3]-ə uyğun [Wayland] kompozitorudur. [Tez-tez verilən sualları] oxuyun.
|
||||
[IRC kanalına] qoşulun ("irc.libera.chat"-da #sway).
|
||||
|
||||
## Buraxılış İmzaları
|
||||
|
||||
Buraxılışlar [E88F5E48] ilə imzalanıb və [GitHub-da][GitHub releases] dərc edilib.
|
||||
|
||||
## Quraşdırma
|
||||
|
||||
### Paketlərdən
|
||||
|
||||
Sway bir çox distributivdə mövcuddur. Öz distributiviniz üçün
|
||||
"sway" paketini quraşdırmağa çalışın.
|
||||
|
||||
### Mənbə kodundan kompilyasiya
|
||||
|
||||
Test və ya inkişaf üçün sway və wlroots-un HEAD-ini qurmaq istəyirsinizsə,
|
||||
[bu viki səhifəsini][Development setup] nəzərdən keçirin.
|
||||
|
||||
Asılılıqları quraşdırın:
|
||||
|
||||
* meson \*
|
||||
* [wlroots]
|
||||
* wayland
|
||||
* wayland-protocols \*
|
||||
* pcre2
|
||||
* json-c
|
||||
* pango
|
||||
* cairo
|
||||
* gdk-pixbuf2 (ixtiyari: sistem trayı üçün əlavə şəkil formatları)
|
||||
* [swaybg] (ixtiyari: divar kağızı)
|
||||
* [scdoc] (ixtiyari: man səhifələri) \*
|
||||
* git (ixtiyari: versiya məlumatı) \*
|
||||
|
||||
_\* Kompilyasiya asılılıqları_
|
||||
|
||||
Bu əmrləri icra edin:
|
||||
|
||||
meson setup build/
|
||||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
## Konfiqurasiya
|
||||
|
||||
Əgər artıq i3-dən istifadə edirsinizsə, i3 konfiqurasiyanızı `~/.config/sway/config`
|
||||
ünvanına köçürün və o, dərhal işləyəcək. Əks halda, nümunə konfiqurasiya faylını
|
||||
`~/.config/sway/config` ünvanına köçürün. O, adətən `/etc/sway/config` ünvanında yerləşir.
|
||||
Konfiqurasiya haqqında məlumat üçün `man 5 sway` əmrini icra edin.
|
||||
|
||||
## İşə Salma
|
||||
|
||||
TTY-dan `sway`-ı işə salın. Bəzi ekran menecerləri işləyə bilər, lakin sway tərəfindən
|
||||
dəstəklənmir (gdm-in kifayət qədər yaxşı işlədiyi məlumdur).
|
||||
|
||||
[i3]: https://i3wm.org/
|
||||
[Wayland]: http://wayland.freedesktop.org/
|
||||
[Tez-tez verilən sualları]: https://github.com/swaywm/sway/wiki
|
||||
[IRC kanalına]: https://web.libera.chat/gamja/?channels=#sway
|
||||
[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48
|
||||
[GitHub releases]: https://github.com/swaywm/sway/releases
|
||||
[Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup
|
||||
[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots
|
||||
[swaybg]: https://github.com/swaywm/swaybg/
|
||||
[scdoc]: https://git.sr.ht/~sircmpwn/scdoc
|
||||
37
README.cs.md
37
README.cs.md
|
|
@ -1,25 +1,24 @@
|
|||
# sway
|
||||
|
||||
[English][en] - **[Česky][cs]** - [Deutsch][de] - [Dansk][dk] - [Español][es] - [Français][fr] - [Svenska][sv] - [Ελληνικά][gr] - [हिन्दी][hi] - [Magyar][hu] - [فارسی][ir] - [Italiano][it] - [日本語][ja] - [한국어][ko] - [Nederlands][nl] - [Polski][pl] - [Português][pt] - [Română][ro] - [Русский][ru] - [Türkçe][tr] - [Українська][uk] - [中文-简体][zh-CN] - [中文-繁體][zh-TW]
|
||||
|
||||
sway je s [i3] kompatibilní [Wayland] kompozitor. Přečtěte si [FAQ]. Připojte se na
|
||||
[IRC kanál][IRC channel] \(#sway na irc.libera.chat).
|
||||
sway je [waylandový][Wayland] kompozitor kompatibilní s [i3]. Přečtěte si
|
||||
[FAQ (anglicky)][FAQ]. Připojte se na [IRC kanál (anglicky)][IRC channel]
|
||||
\(#sway na irc.libera.chat).
|
||||
|
||||
## Podpisy vydání
|
||||
|
||||
Vydání jsou podepsána [E88F5E48] a publikována [na GitHubu][GitHub releases].
|
||||
Vydané verze jsou podepsány klíčem [E88F5E48] a publikovány
|
||||
[na GitHubu][GitHub releases].
|
||||
|
||||
## Instalace
|
||||
|
||||
### Z balíčků
|
||||
### Z balíků
|
||||
|
||||
Sway je dostupný ve spoustě distribucí. Zkuste nainstalovat balíček "sway" ve vaší
|
||||
distribuci.
|
||||
Sway je dostupný v mnoha distribucích. Zkuste v té vaší nainstalovat balík "sway".
|
||||
|
||||
### Kompilace ze zdrojových kódů
|
||||
|
||||
Podívejte se na [tuto stránku wiki][Development setup], pokud chcete sestavit HEAD
|
||||
sway a wlroots pro testování nebo vývoj.
|
||||
Pokud chcete sestavit HEAD repozitáře sway a wlroots pro testování nebo vývoj,
|
||||
použijte návod na [této stránce na wiki (anglicky)][Development setup].
|
||||
|
||||
Nainstalujte závislosti:
|
||||
|
||||
|
|
@ -31,15 +30,16 @@ Nainstalujte závislosti:
|
|||
* json-c
|
||||
* pango
|
||||
* cairo
|
||||
* gdk-pixbuf2 (volitelné: oznamovací oblast)
|
||||
* [scdoc] (volitelné: manuálové stránky) \*
|
||||
* gdk-pixbuf2 (volitelné: dodatečné formáty ikon pro oznamovací oblast)
|
||||
* [swaybg] (volitelné: tapeta plochy)
|
||||
* [scdoc] (volitelné: man stránky) \*
|
||||
* git (volitelné: informace o verzi) \*
|
||||
|
||||
_\* Závislost pouze pro sestavení_
|
||||
_\* Závislost pouze pro kompilaci_
|
||||
|
||||
Spusťte tyto příkazy:
|
||||
|
||||
meson build/
|
||||
meson setup build/
|
||||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
|
|
@ -52,16 +52,16 @@ Pro více informací o konfiguraci spusťte `man 5 sway`.
|
|||
|
||||
## Spuštění
|
||||
|
||||
Spusťte `sway` z TTY. Některé správce zobrazení mohou fungovat, ale nejsou
|
||||
podporovány sway (je známo, že gdm funguje docela dobře).
|
||||
Spusťte `sway` z TTY nebo ze správce displeje.
|
||||
|
||||
[en]: https://github.com/swaywm/sway#readme
|
||||
[ar]: README.ar.md
|
||||
[cs]: README.cs.md
|
||||
[de]: README.de.md
|
||||
[dk]: README.dk.md
|
||||
[es]: README.es.md
|
||||
[fr]: README.fr.md
|
||||
[sv]: README.sv.md
|
||||
[ge]: README.ge.md
|
||||
[gr]: README.gr.md
|
||||
[hi]: README.hi.md
|
||||
[hu]: README.hu.md
|
||||
|
|
@ -70,10 +70,12 @@ podporovány sway (je známo, že gdm funguje docela dobře).
|
|||
[ja]: README.ja.md
|
||||
[ko]: README.ko.md
|
||||
[nl]: README.nl.md
|
||||
[no]: README.no.md
|
||||
[pl]: README.pl.md
|
||||
[pt]: README.pt.md
|
||||
[ro]: README.ro.md
|
||||
[ru]: README.ru.md
|
||||
[sv]: README.sv.md
|
||||
[tr]: README.tr.md
|
||||
[uk]: README.uk.md
|
||||
[zh-CN]: README.zh-CN.md
|
||||
|
|
@ -86,4 +88,5 @@ podporovány sway (je známo, že gdm funguje docela dobře).
|
|||
[GitHub releases]: https://github.com/swaywm/sway/releases
|
||||
[Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup
|
||||
[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots
|
||||
[swaybg]: https://github.com/swaywm/swaybg/
|
||||
[scdoc]: https://git.sr.ht/~sircmpwn/scdoc
|
||||
|
|
|
|||
35
README.de.md
35
README.de.md
|
|
@ -1,21 +1,21 @@
|
|||
# Sway
|
||||
Sway ist ein [i3](https://i3wm.org/)-kompatibler [Wayland](http://wayland.freedesktop.org/)-Compositor. Lies die [FAQ](https://github.com/swaywm/sway/wiki). Tritt dem [IRC Channel](https://web.libera.chat/gamja/?channels=#sway) bei (#sway on irc.libera.chat; Englisch).
|
||||
Sway ist ein [i3]-kompatibler [Wayland]-Compositor. Lies die [FAQ]. Tritt dem [IRC Channel] bei (#sway on irc.libera.chat; Englisch).
|
||||
|
||||
## Signaturen
|
||||
Jedes Release wird mit dem PGP-Schlüssel [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) signiert und [auf GitHub](https://github.com/swaywm/sway/releases) veröffentlicht.
|
||||
Jeder Release wird mit dem PGP-Schlüssel [E88F5E48] signiert und [auf GitHub][GitHub releases] veröffentlicht.
|
||||
|
||||
## Installation
|
||||
|
||||
### Über die Paketverwaltung
|
||||
|
||||
Sway kann in vielen Distributionen direkt durch die Paketverwaltung installiert werden. Versuche einfach das Packet "sway" zu installieren.
|
||||
Sway kann in vielen Distributionen direkt durch die Paketverwaltung installiert werden. Versuche einfach das Paket "sway" zu installieren.
|
||||
|
||||
### Quellcode selbst kompilieren
|
||||
|
||||
sway benötigt die folgenden Pakete:
|
||||
|
||||
* meson \*
|
||||
* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots)
|
||||
* [wlroots]
|
||||
* wayland
|
||||
* wayland-protocols\*
|
||||
* pcre2
|
||||
|
|
@ -23,21 +23,34 @@ sway benötigt die folgenden Pakete:
|
|||
* pango
|
||||
* cairo
|
||||
* gdk-pixbuf2 (Optional, wird für das Benachrichtigungsfeld (System Tray) benötigt)
|
||||
* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (Optional, wird für die Dokumentation (Man Pages) benötigt)\*
|
||||
* [swaybg] (Optional, wird für das Setzen von Desktophintergrundbildern benötigt)
|
||||
* [scdoc] (Optional, wird für die Dokumentation (Man Pages) benötigt)\*
|
||||
* git (Optional: Versionsinfo)\*
|
||||
|
||||
_\*Werden nur während des Kompilierens benötigt_
|
||||
_\*Werden nur für das Kompilieren benötigt_
|
||||
|
||||
Führe die folgenden Befehle aus:
|
||||
|
||||
meson build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
meson setup build/
|
||||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
Schaue in das [Wiki][Development setup] (Englisch) für Informationen, falls du zum Testen oder Entwickeln den neuesten Stand (HEAD) von sway und wlroots kompilieren willst.
|
||||
|
||||
## Konfiguration
|
||||
|
||||
Falls du von i3 migrierst, kannst du deine Konfigurationsdatei nach `~/.config/sway/config` kopieren und die Einstellungen sollten ohne Weiteres funktionieren. Ansonsten kannst du die Beispielkonfiguration, die normalerweise in `/etc/sway/config` liegt, nach `~/.config/sway/config` kopieren. Die Dokumentation zur Konfigurationsdatei findest du in `man 5 sway`.
|
||||
|
||||
## Sway starten
|
||||
Sway kann einfach mit dem Befehl `sway` vom TTY gestartet werden.
|
||||
Display-Manager werden nicht offiziell unterstützt. Es gibt aber durchaus einige, die mit Sway funktionieren (z.B. gdm).
|
||||
Sway kann einfach mit dem Befehl `sway` vom TTY oder mithilfe eines Displaymanagers gestartet werden.
|
||||
|
||||
[i3]: https://i3wm.org/
|
||||
[Wayland]: http://wayland.freedesktop.org/
|
||||
[FAQ]: https://github.com/swaywm/sway/wiki
|
||||
[IRC channel]: https://web.libera.chat/gamja/?channels=#sway
|
||||
[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48
|
||||
[GitHub releases]: https://github.com/swaywm/sway/releases
|
||||
[Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup
|
||||
[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots
|
||||
[swaybg]: https://github.com/swaywm/swaybg
|
||||
[scdoc]: https://git.sr.ht/~sircmpwn/scdoc
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ _\*Kompileringsafhængighed_
|
|||
|
||||
Kør følgende kommandoer:
|
||||
|
||||
meson build
|
||||
meson setup build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
|
|
@ -54,8 +54,7 @@ Hvis du allerede bruger i3 kan du bare kopiere din i3 konfiguration til
|
|||
|
||||
## Eksekvering
|
||||
|
||||
Kør `sway` fra en TTY. Nogle display managers kan fungere, men Sway yder ikke
|
||||
support til dem (gdm er kendt for at fungere temmelig godt).
|
||||
Kør `sway` fra en TTY eller fra en display manager.
|
||||
|
||||
[i3]: https://i3wm.org/
|
||||
[Wayland]: http://wayland.freedesktop.org/
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ _\*Compile-time dep_
|
|||
|
||||
Desde su consola, ejecute las órdenes:
|
||||
|
||||
meson build
|
||||
meson setup build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ _\* Requis uniquement pour la compilation_
|
|||
|
||||
Exécutez ces commandes :
|
||||
|
||||
meson build
|
||||
meson setup build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
|
|
@ -61,9 +61,7 @@ documentation pour la configuration de sway.
|
|||
|
||||
## Exécution
|
||||
|
||||
Exécutez `sway` à partir d'un TTY. Certains gestionnaires d'affichage peuvent
|
||||
fonctionner, mais ne sont pas supportés par Sway (gdm est réputé pour assez
|
||||
bien fonctionner).
|
||||
Exécutez `sway` à partir d'un TTY ou d'un gestionnaires d'affichage.
|
||||
|
||||
[Wayland]: http://wayland.freedesktop.org/
|
||||
[i3]: https://i3wm.org/
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ _\* Compile-time dep_
|
|||
|
||||
გაუშვით ეს ბრძანებები:
|
||||
|
||||
meson build/
|
||||
meson setup build/
|
||||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ _\*Compile-time dep_
|
|||
|
||||
Τρέξτε αυτά τα commands:
|
||||
|
||||
meson build/
|
||||
meson setup build/
|
||||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ _\* Compilation के समय आवश्यक_
|
|||
|
||||
ये commands चलाएं:
|
||||
|
||||
meson build/
|
||||
meson setup build/
|
||||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
|
|
|
|||
12
README.hu.md
12
README.hu.md
|
|
@ -1,10 +1,10 @@
|
|||
# sway
|
||||
|
||||
A Sway egy [i3]-kompatibilis [Wayland] kompozitor. Olvasd el a [Gyarkan Ismételt Kérdéseket][FAQ]. Csatlakozz az [IRC csatornához][IRC channel] \(`#sway` az `irc.libera.chat`-en).
|
||||
A Sway egy [i3]-kompatibilis [Wayland]-kompozitor. Olvasd el a [Gyarkan Ismételt Kérdéseket][FAQ]. Csatlakozz az [IRC-csatornához][IRC channel] \(`#sway` az `irc.libera.chat`-en).
|
||||
|
||||
## Csomagaláírások
|
||||
|
||||
A kiadott csomagok az [E88F5E48] kulccsal vannak aláírva és [GitHub-on][GitHub releases] publikálva.
|
||||
A kiadott csomagok az [E88F5E48] kulccsal vannak aláírva, és [GitHubon][GitHub releases] publikálva.
|
||||
|
||||
## Telepítés
|
||||
|
||||
|
|
@ -13,7 +13,7 @@ A kiadott csomagok az [E88F5E48] kulccsal vannak aláírva és [GitHub-on][GitHu
|
|||
A Sway sok disztribúció csomagkezelőjéből elérhető, próbáld meg a "sway"
|
||||
csomagot telepíteni az általad használt eszközzel.
|
||||
|
||||
Ha szeretnél csomagot készíteni a saját disztribúciódhoz, ugorj be az IRC
|
||||
Ha szeretnél csomagot készíteni a saját disztribúciódhoz, ugorj be az IRC-
|
||||
csatornára, vagy küldj levelet a sir@cmpwn.com címre tanácsokért.
|
||||
|
||||
### Fordítás forráskódból
|
||||
|
|
@ -40,13 +40,13 @@ _\*Fordításidejű függőség_
|
|||
|
||||
Futtasd ezeket a parancsokat:
|
||||
|
||||
meson build
|
||||
meson setup build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
## Konfiguráció
|
||||
|
||||
Ha előzőleg i3-mat használtál, akkor átmásolhatod az i3 beállításaidat a
|
||||
Ha előzőleg i3-at használtál, akkor átmásolhatod az i3-beállításaidat a
|
||||
`~/.config/sway/config` file-ba és ugyanúgy működni fognak. Egyéb esetben másold
|
||||
le kiindulási alapnak a mintát, ami általában az `etc/sway/config` elérési
|
||||
útvonalon található.
|
||||
|
|
@ -55,7 +55,7 @@ kapcsolatban.
|
|||
|
||||
## Futtatás
|
||||
|
||||
Futtasd a `sway` parancsot egy TTY felületről. Néhány bejelentkezéskezelő
|
||||
Futtasd a `sway` parancsot egy TTY-felületről. Néhány bejelentkezéskezelő
|
||||
(display manager) működhet, de alapvetően nem támogatottak a sway által. (A
|
||||
gdm-ről ismeretes, hogy egész jól működik.)
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ _\*نیازمندیهای زمان کامپایل برنامه_
|
|||
|
||||
این فرمانها را اجرا کنید:
|
||||
|
||||
meson build
|
||||
meson setup build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# sway
|
||||
|
||||
sway è un compositore di [Wayland] compatibile con [i3]. Leggi le [FAQ].
|
||||
Unisciti al [canale di IRC] \(#sway su irc.libera.chat).
|
||||
Unisciti al [canale IRC] \(#sway su irc.libera.chat).
|
||||
|
||||
## Firma delle versioni
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ _\* Dipendenza necessaria per la compilazione_
|
|||
|
||||
Esegui questi comandi:
|
||||
|
||||
meson build/
|
||||
meson setup build/
|
||||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
|
|
@ -52,13 +52,12 @@ configurazione.
|
|||
|
||||
## Esecuzione
|
||||
|
||||
Lancia `sway` da un TTY. Alcuni gestori d'accesso potrebbero funzionare ma non
|
||||
sono supportati da sway (gdm funziona abbastanza bene).
|
||||
Lancia `sway` da un TTY o da un display manager.
|
||||
|
||||
[i3]: https://i3wm.org/
|
||||
[Wayland]: http://wayland.freedesktop.org/
|
||||
[FAQ]: https://github.com/swaywm/sway/wiki
|
||||
[canale di IRC]: https://web.libera.chat/gamja/?channels=#sway
|
||||
[canale IRC]: https://web.libera.chat/gamja/?channels=#sway
|
||||
[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48
|
||||
[GitHub releases]: https://github.com/swaywm/sway/releases
|
||||
[Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ _\*コンパイル時の依存_
|
|||
|
||||
次のコマンドを実行してください:
|
||||
|
||||
meson build
|
||||
meson setup build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
|
|
@ -52,5 +52,4 @@ _\*コンパイル時の依存_
|
|||
|
||||
## 実行
|
||||
|
||||
`sway`をTTYから実行してください。いくつかのディスプレイマネージャは動くかもしれませんが、Swayからサポートされていません(gdmは非常に良く動作することが知られています)。
|
||||
|
||||
`sway`をTTYまたはディスプレイマネージャから実行してください。
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ _\*컴파일 떄 필요_
|
|||
|
||||
다음 명령을 실행하세요:
|
||||
|
||||
meson build
|
||||
meson setup build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
|
|
@ -52,4 +52,4 @@ i3를 이미 사용 중이라면, i3 config을 `~/.config/sway/config`로 복사
|
|||
|
||||
## 실행
|
||||
|
||||
TTY에서 `sway`를 실행하세요. 일부 display manager는 작동하지만, sway로 부터 지원되지 않습니다(gdm은 상당히 잘 작동한다고 알려져 있습니다).
|
||||
TTY나 display manager에서 `sway`를 실행하세요.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# sway
|
||||
|
||||
**[English][en]** - [عربي][ar] - [Česky][cs] - [Deutsch][de] - [Dansk][dk] - [Español][es] - [Français][fr] - [ქართული][ge] - [Ελληνικά][gr] - [हिन्दी][hi] - [Magyar][hu] - [فارسی][ir] - [Italiano][it] - [日本語][ja] - [한국어][ko] - [Nederlands][nl] - [Norsk][no] - [Polski][pl] - [Português][pt] - [Română][ro] - [Русский][ru] - [Svenska][sv] - [Türkçe][tr] - [Українська][uk] - [中文-简体][zh-CN] - [中文-繁體][zh-TW]
|
||||
**[English][en]** - [عربي][ar] - [Azərbaycanca][az] - [Česky][cs] - [Deutsch][de] - [Dansk][dk] - [Español][es] - [Français][fr] - [ქართული][ge] - [Ελληνικά][gr] - [हिन्दी][hi] - [Magyar][hu] - [فارسی][ir] - [Italiano][it] - [日本語][ja] - [한국어][ko] - [Nederlands][nl] - [Norsk][no] - [Polski][pl] - [Português][pt] - [Română][ro] - [Русский][ru] - [Српски][sr] - [Svenska][sv] - [Türkçe][tr] - [Українська][uk] - [中文-简体][zh-CN] - [中文-繁體][zh-TW]
|
||||
|
||||
sway is an [i3]-compatible [Wayland] compositor. Read the [FAQ]. Join the
|
||||
[IRC channel] \(#sway on irc.libera.chat).
|
||||
|
|
@ -40,7 +40,7 @@ _\* Compile-time dep_
|
|||
|
||||
Run these commands:
|
||||
|
||||
meson build/
|
||||
meson setup build/
|
||||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
|
|
@ -53,11 +53,11 @@ Run `man 5 sway` for information on the configuration.
|
|||
|
||||
## Running
|
||||
|
||||
Run `sway` from a TTY. Some display managers may work but are not supported by
|
||||
sway (gdm is known to work fairly well).
|
||||
Run `sway` from a TTY or from a display manager.
|
||||
|
||||
[en]: https://github.com/swaywm/sway#readme
|
||||
[ar]: README.ar.md
|
||||
[az]: README.az.md
|
||||
[cs]: README.cs.md
|
||||
[de]: README.de.md
|
||||
[dk]: README.dk.md
|
||||
|
|
@ -77,6 +77,7 @@ sway (gdm is known to work fairly well).
|
|||
[pt]: README.pt.md
|
||||
[ro]: README.ro.md
|
||||
[ru]: README.ru.md
|
||||
[sr]: README.sr.md
|
||||
[sv]: README.sv.md
|
||||
[tr]: README.tr.md
|
||||
[uk]: README.uk.md
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ _\* Compileerafhankelijkheden_
|
|||
|
||||
Voer deze opdrachten uit:
|
||||
|
||||
meson build
|
||||
meson setup build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
|
|
|
|||
45
README.no.md
45
README.no.md
|
|
@ -1,29 +1,25 @@
|
|||
# Sway
|
||||
|
||||
Sway er en [i3]-kompatibel [Wayland] compositor. Les [Ofte stilte spørsmål].
|
||||
Delta på [IRC kanalen][IRC kanal] \(#sway på irc.libera.chat).
|
||||
Sway er en [i3]-kompatibel [Wayland]-compositor. Les [Ofte stilte spørsmål].
|
||||
Delta på [IRC-kanalen][IRC-kanal] \(#sway på irc.libera.chat).
|
||||
|
||||
## Utgivelses Signaturer
|
||||
## Signaturer
|
||||
|
||||
Utgivelser er signert med [E88F5E48] og publisert [på GitHub][GitHub
|
||||
releases].
|
||||
Utgivelser er signert med [E88F5E48] og publisert [på GitHub][GitHub releases].
|
||||
|
||||
## Installasjon
|
||||
|
||||
### Fra systempakker
|
||||
|
||||
Sway er tilgjengelig i mange distribusjoner. Prøv å installere "sway" pakken
|
||||
Sway er tilgjengelig i mange distribusjoner. Prøv å installere pakken "sway"
|
||||
fra din distro sine repoer.
|
||||
|
||||
Er du interessert i å pakke Sway for din distribusjon kan du ta turen innom
|
||||
IRC-kanalen eller send en e-post til sir@cmpwn.com for råd.
|
||||
|
||||
### Kompilering fra kildekode
|
||||
|
||||
Se [denne wiki-siden][Oppsetting for utvikling] hvis du vil bygge fra HEAD grenen av sway og
|
||||
wlroots for testing eller utvikling.
|
||||
Se [denne wiki-siden][Oppsetting for utvikling] hvis du vil bygge fra HEAD-grenen av
|
||||
sway og wlroots for testing eller utvikling.
|
||||
|
||||
Installasjonsavhengigheter:
|
||||
Installer avhengigheter:
|
||||
|
||||
* meson \*
|
||||
* [wlroots]
|
||||
|
|
@ -33,36 +29,37 @@ Installasjonsavhengigheter:
|
|||
* json-c
|
||||
* pango
|
||||
* cairo
|
||||
* gdk-pixbuf2 (valgfritt: system tray)
|
||||
* gdk-pixbuf2 (valgfritt: støtte for ekstra bildeformater i system tray)
|
||||
* [swaybg] (valgfritt: bakgrunnsbilde)
|
||||
* [scdoc] (valgfritt: man pages) \*
|
||||
* git \*
|
||||
* git (valgfritt: versjonsinformasjon) \*
|
||||
|
||||
_\* Kompileringsavhengigheter_
|
||||
|
||||
Kjør følgende kommandoer:
|
||||
|
||||
meson build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
meson setup build/
|
||||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
## Konfigurasjon
|
||||
|
||||
Hvis du allerede bruker i3 kan du bare kopiere din i3 konfigurasjon til
|
||||
Hvis du allerede bruker i3 kan du bare kopiere din i3-konfigurasjon til
|
||||
`~/.config/sway/config`. Ellers skal du kopiere eksempelkonfigurasjonsfilen til
|
||||
`~/.config/sway/config`. Eksempel filen er normalt plasert i `/etc/sway/config`. Kjør
|
||||
`man 5 sway` for å få oplysninger om konfigurasjonen.
|
||||
`~/.config/sway/config`. Eksempelfilen er normalt plasert i `/etc/sway/config`.
|
||||
Kjør `man 5 sway` for å få opplysninger om konfigurasjonen.
|
||||
|
||||
## Utførelse
|
||||
## Kjøring
|
||||
|
||||
Kjør `sway` fra en TTY. Noen display managers kan fungere, men Sway har ikke
|
||||
støtte for dem (gdm er kjent for å fungere ganske bra).
|
||||
Kjør `sway` fra en TTY eller fra en display manager.
|
||||
|
||||
[i3]: https://i3wm.org/
|
||||
[Wayland]: http://wayland.freedesktop.org/
|
||||
[Ofte stilte spørsmål]: https://github.com/swaywm/sway/wiki
|
||||
[IRC kanal]: https://web.libera.chat/gamja/?channels=#sway
|
||||
[IRC-kanal]: https://web.libera.chat/gamja/?channels=#sway
|
||||
[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48
|
||||
[GitHub releases]: https://github.com/swaywm/sway/releases
|
||||
[Oppsetting for utvikling]: https://github.com/swaywm/sway/wiki/Development-Setup
|
||||
[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots
|
||||
[swaybg]: https://github.com/swaywm/swaybg/
|
||||
[scdoc]: https://git.sr.ht/~sircmpwn/scdoc
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ _\*zależności kompilacji_
|
|||
|
||||
Wykonaj następujące polecenia:
|
||||
|
||||
meson build
|
||||
meson setup build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
|
|
@ -53,5 +53,4 @@ Wykonaj polecenie `man 5 sway` aby uzyskać informacje dotyczące konfiguracji.
|
|||
|
||||
## Uruchamianie
|
||||
|
||||
Wykonaj polecenie `sway` z poziomu TTY. Niektóre menedżery wyświetlania mogą umożliwiać rozruch z ich
|
||||
poziomu, ale nie jest to wspierane przez sway (w gdm podobno działa to całkiem nieźle).
|
||||
Wykonaj polecenie `sway` z poziomu TTY lub menedżera wyświetlania.
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ _\*Dependência de tempo de compilação_
|
|||
|
||||
Execute esses comandos:
|
||||
|
||||
meson build
|
||||
meson setup build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ Dependențe pentru instalare:
|
|||
Rulați aceste comenzi:
|
||||
|
||||
```
|
||||
meson build
|
||||
meson setup build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
```
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ _\*Зависимости для сборки_
|
|||
|
||||
Выполните эти команды:
|
||||
|
||||
meson build
|
||||
meson setup build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
|
|
@ -54,8 +54,7 @@ _\*Зависимости для сборки_
|
|||
|
||||
## Запуск
|
||||
|
||||
Выполните команду `sway` прямо из TTY. Некоторые дисплейные менеджеры могут работать, но они не поддерживаются со стороны
|
||||
sway (gdm работает довольно неплохо).
|
||||
Выполните команду `sway` прямо из TTY или дисплейного менеджера.
|
||||
|
||||
[i3]: https://i3wm.org/
|
||||
[Wayland]: http://wayland.freedesktop.org/
|
||||
|
|
|
|||
65
README.sr.md
Normal file
65
README.sr.md
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
# sway
|
||||
|
||||
sway је [i3]-компатибилан [Wayland] композитор. Прочитајте [FAQ]. Придружите се
|
||||
[IRC каналу] \(#sway на irc.libera.chat).
|
||||
|
||||
## Потписи Издања
|
||||
|
||||
Издања су потписана са [E88F5E48] и објављена [на GitHub-у][GitHub releases].
|
||||
|
||||
## Инсталација
|
||||
|
||||
### Из пакета
|
||||
|
||||
Sway је доступан у многим дистрибуцијама. Покушајте да инсталирате "sway" пакет за
|
||||
вашу.
|
||||
|
||||
### Компајлирање из Извора
|
||||
|
||||
Погледајте [ову вики страницу][Development setup], ако желите да компајлирате HEAD верзију
|
||||
sway-а и wlroots-а за тестирање или развој.
|
||||
|
||||
Инсталирајте зависности:
|
||||
|
||||
* meson \*
|
||||
* [wlroots]
|
||||
* wayland
|
||||
* wayland-protocols \*
|
||||
* pcre2
|
||||
* json-c
|
||||
* pango
|
||||
* cairo
|
||||
* gdk-pixbuf2 (опционо: додатни формати слика за системску траку)
|
||||
* [swaybg] (опционо: позадина)
|
||||
* [scdoc] (опционо: man странице) \*
|
||||
* git (опционо: информације о верзији) \*
|
||||
|
||||
_\* Потребно само за компајлирање_
|
||||
|
||||
Покрените следеће команде:
|
||||
|
||||
meson setup build/
|
||||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
## Конфигурација
|
||||
|
||||
Ако већ користите i3, копирајте вашу i3 конфигурацију у `~/.config/sway/config` и
|
||||
радиће одмах. У супротном, копирајте пример конфигурационе датотеке у
|
||||
`~/.config/sway/config`. Обично се налази у `/etc/sway/config`.
|
||||
Покрените `man 5 sway` за информације о конфигурацији.
|
||||
|
||||
## Покретање
|
||||
|
||||
Покрените `sway` из TTY-a или из менаџера приказа.
|
||||
|
||||
[i3]: https://i3wm.org/
|
||||
[Wayland]: http://wayland.freedesktop.org/
|
||||
[FAQ]: https://github.com/swaywm/sway/wiki
|
||||
[IRC каналу]: https://web.libera.chat/gamja/?channels=#sway
|
||||
[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48
|
||||
[GitHub releases]: https://github.com/swaywm/sway/releases
|
||||
[Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup
|
||||
[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots
|
||||
[swaybg]: https://github.com/swaywm/swaybg/
|
||||
[scdoc]: https://git.sr.ht/~sircmpwn/scdoc
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
# sway
|
||||
|
||||
[English][en] - [Deutsch][de] - [Dansk][dk] - [Español][es] - [Français][fr] - **[Svenska][sv]** - [Ελληνικά][gr] - [Magyar][hu] - [فارسی][ir] - [Italiano][it] - [日本語][ja] - [한국어][ko] - [Nederlands][nl] - [Polski][pl] - [Português][pt] - [Română][ro] - [Русский][ru] - [Türkçe][tr] - [Українська][uk] - [中文-简体][zh-CN] - [中文-繁體][zh-TW]
|
||||
|
||||
sway är en [i3]-kompatibel [Wayland] compositor. Läs våran [FAQ]-sida. Gå med i vår
|
||||
[IRC-kanal] \(#sway på irc.libera.chat).
|
||||
|
||||
|
|
@ -37,7 +35,7 @@ _\* Krav för kompilering_
|
|||
|
||||
Kör dessa kommandon:
|
||||
|
||||
meson build/
|
||||
meson setup build/
|
||||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ _\*Derleme-anı bağımlılıkları_
|
|||
|
||||
Şu komutları çalıştırın:
|
||||
|
||||
meson build
|
||||
meson setup build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ _\*Лише для компіляції_
|
|||
|
||||
Виконайте ці команди:
|
||||
|
||||
meson build
|
||||
meson setup build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ _\*编译时依赖_
|
|||
|
||||
运行如下命令:
|
||||
|
||||
meson build/
|
||||
meson setup build/
|
||||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ _\*編譯時相依_
|
|||
|
||||
執行這些指令:
|
||||
|
||||
meson build
|
||||
meson setup build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
|
|
|
|||
|
|
@ -360,3 +360,7 @@ char *format_str(const char *fmt, ...) {
|
|||
va_end(args);
|
||||
return str;
|
||||
}
|
||||
|
||||
bool has_prefix(const char *str, const char *prefix) {
|
||||
return strncmp(str, prefix, strlen(prefix)) == 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,3 +141,9 @@ bool sway_set_cloexec(int fd, bool cloexec) {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t get_current_time_in_msec(void) {
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
return now.tv_sec * 1000 + now.tv_nsec / 1000000;
|
||||
}
|
||||
|
|
|
|||
34
config.in
34
config.in
|
|
@ -16,9 +16,7 @@ set $right l
|
|||
# Your preferred terminal emulator
|
||||
set $term foot
|
||||
# Your preferred application launcher
|
||||
# Note: pass the final command to swaymsg so that the resulting window can be opened
|
||||
# on the original workspace that the command was run on.
|
||||
set $menu dmenu_path | wmenu | xargs swaymsg exec --
|
||||
set $menu wmenu-run
|
||||
|
||||
### Output configuration
|
||||
#
|
||||
|
|
@ -48,14 +46,18 @@ output * bg @datadir@/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png fill
|
|||
#
|
||||
# Example configuration:
|
||||
#
|
||||
# input "2:14:SynPS/2_Synaptics_TouchPad" {
|
||||
# input type:touchpad {
|
||||
# dwt enabled
|
||||
# tap enabled
|
||||
# natural_scroll enabled
|
||||
# middle_emulation enabled
|
||||
# }
|
||||
#
|
||||
# You can get the names of your inputs by running: swaymsg -t get_inputs
|
||||
# input type:keyboard {
|
||||
# xkb_layout "eu"
|
||||
# }
|
||||
#
|
||||
# You can also configure each device individually.
|
||||
# Read `man 5 sway-input` for more information about this section.
|
||||
|
||||
### Key bindings
|
||||
|
|
@ -195,6 +197,28 @@ mode "resize" {
|
|||
bindsym Escape mode "default"
|
||||
}
|
||||
bindsym $mod+r mode "resize"
|
||||
#
|
||||
# Utilities:
|
||||
#
|
||||
# Special keys to adjust volume via PulseAudio
|
||||
bindsym --locked XF86AudioMute exec pactl set-sink-mute \@DEFAULT_SINK@ toggle
|
||||
bindsym --locked XF86AudioLowerVolume exec pactl set-sink-volume \@DEFAULT_SINK@ -5%
|
||||
bindsym --locked XF86AudioRaiseVolume exec pactl set-sink-volume \@DEFAULT_SINK@ +5%
|
||||
bindsym --locked XF86AudioMicMute exec pactl set-source-mute \@DEFAULT_SOURCE@ toggle
|
||||
|
||||
# Special keys to control media via playerctl
|
||||
bindsym --locked XF86AudioPlay exec playerctl play-pause
|
||||
bindsym --locked XF86AudioPause exec playerctl play-pause
|
||||
bindsym --locked XF86AudioPrev exec playerctl previous
|
||||
bindsym --locked XF86AudioNext exec playerctl next
|
||||
bindsym --locked XF86AudioStop exec playerctl stop
|
||||
|
||||
# Special keys to adjust brightness via brightnessctl
|
||||
bindsym --locked XF86MonBrightnessDown exec brightnessctl set 5%-
|
||||
bindsym --locked XF86MonBrightnessUp exec brightnessctl set 5%+
|
||||
|
||||
# Special key to take a screenshot with grim
|
||||
bindsym Print exec grim
|
||||
|
||||
#
|
||||
# Status Bar:
|
||||
|
|
|
|||
|
|
@ -40,4 +40,6 @@ bool expand_path(char **path);
|
|||
char *vformat_str(const char *fmt, va_list args) _SWAY_ATTRIB_PRINTF(1, 0);
|
||||
char *format_str(const char *fmt, ...) _SWAY_ATTRIB_PRINTF(1, 2);
|
||||
|
||||
bool has_prefix(const char *str, const char *prefix);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ struct sway_container *container_find_resize_parent(struct sway_container *con,
|
|||
sway_cmd cmd_exec_validate;
|
||||
sway_cmd cmd_exec_process;
|
||||
|
||||
sway_cmd cmd_allow_tearing;
|
||||
sway_cmd cmd_assign;
|
||||
sway_cmd cmd_bar;
|
||||
sway_cmd cmd_bindcode;
|
||||
|
|
@ -283,11 +284,13 @@ sway_cmd input_cmd_xkb_switch_layout;
|
|||
sway_cmd input_cmd_xkb_variant;
|
||||
|
||||
sway_cmd output_cmd_adaptive_sync;
|
||||
sway_cmd output_cmd_allow_tearing;
|
||||
sway_cmd output_cmd_background;
|
||||
sway_cmd output_cmd_color_profile;
|
||||
sway_cmd output_cmd_disable;
|
||||
sway_cmd output_cmd_dpms;
|
||||
sway_cmd output_cmd_enable;
|
||||
sway_cmd output_cmd_hdr;
|
||||
sway_cmd output_cmd_max_render_time;
|
||||
sway_cmd output_cmd_mode;
|
||||
sway_cmd output_cmd_modeline;
|
||||
|
|
|
|||
|
|
@ -261,7 +261,8 @@ enum scale_filter_mode {
|
|||
};
|
||||
|
||||
enum render_bit_depth {
|
||||
RENDER_BIT_DEPTH_DEFAULT, // the default is currently 8
|
||||
RENDER_BIT_DEPTH_DEFAULT, // the default is currently 8 for SDR, 10 for HDR
|
||||
RENDER_BIT_DEPTH_6,
|
||||
RENDER_BIT_DEPTH_8,
|
||||
RENDER_BIT_DEPTH_10,
|
||||
};
|
||||
|
|
@ -289,20 +290,14 @@ struct output_config {
|
|||
enum render_bit_depth render_bit_depth;
|
||||
bool set_color_transform;
|
||||
struct wlr_color_transform *color_transform;
|
||||
int allow_tearing;
|
||||
int hdr;
|
||||
|
||||
char *background;
|
||||
char *background_option;
|
||||
char *background_fallback;
|
||||
};
|
||||
|
||||
/**
|
||||
* An output config pre-matched to an output
|
||||
*/
|
||||
struct matched_output_config {
|
||||
struct sway_output *output;
|
||||
struct output_config *config;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stores size of gaps for each side
|
||||
*/
|
||||
|
|
@ -692,13 +687,10 @@ const char *sway_output_scale_filter_to_string(enum scale_filter_mode scale_filt
|
|||
|
||||
struct output_config *new_output_config(const char *name);
|
||||
|
||||
bool apply_output_configs(struct matched_output_config *configs,
|
||||
size_t configs_len, bool test_only, bool degrade_to_off);
|
||||
bool apply_output_configs(struct output_config **ocs, size_t ocs_len,
|
||||
bool test_only, bool degrade_to_off);
|
||||
|
||||
void apply_all_output_configs(void);
|
||||
|
||||
void sort_output_configs_by_priority(struct matched_output_config *configs,
|
||||
size_t configs_len);
|
||||
void apply_stored_output_configs(void);
|
||||
|
||||
/**
|
||||
* store_output_config stores a new output config. An output may be matched by
|
||||
|
|
@ -713,6 +705,10 @@ struct output_config *find_output_config(struct sway_output *output);
|
|||
|
||||
void free_output_config(struct output_config *oc);
|
||||
|
||||
void request_modeset(void);
|
||||
void force_modeset(void);
|
||||
bool modeset_is_pending(void);
|
||||
|
||||
bool spawn_swaybg(void);
|
||||
|
||||
int workspace_output_cmp_workspace(const void *a, const void *b);
|
||||
|
|
|
|||
|
|
@ -53,6 +53,10 @@ struct criteria {
|
|||
char urgent; // 'l' for latest or 'o' for oldest
|
||||
struct pattern *workspace;
|
||||
pid_t pid;
|
||||
struct pattern *sandbox_engine;
|
||||
struct pattern *sandbox_app_id;
|
||||
struct pattern *sandbox_instance_id;
|
||||
struct pattern *tag;
|
||||
};
|
||||
|
||||
bool criteria_is_empty(struct criteria *criteria);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ enum sway_idle_inhibit_mode {
|
|||
struct sway_idle_inhibit_manager_v1 {
|
||||
struct wlr_idle_inhibit_manager_v1 *wlr_manager;
|
||||
struct wl_listener new_idle_inhibitor_v1;
|
||||
struct wl_listener manager_destroy;
|
||||
struct wl_list inhibitors;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ struct sway_input_manager {
|
|||
|
||||
struct sway_input_manager *input_manager_create(struct sway_server *server);
|
||||
|
||||
void input_manager_finish(struct sway_input_manager *input);
|
||||
|
||||
bool input_manager_has_focus(struct sway_node *node);
|
||||
|
||||
void input_manager_set_focus(struct sway_node *node);
|
||||
|
|
|
|||
|
|
@ -25,8 +25,10 @@ struct sway_input_method_relay {
|
|||
struct wlr_input_method_v2 *input_method; // doesn't have to be present
|
||||
|
||||
struct wl_listener text_input_new;
|
||||
struct wl_listener text_input_manager_destroy;
|
||||
|
||||
struct wl_listener input_method_new;
|
||||
struct wl_listener input_method_manager_destroy;
|
||||
struct wl_listener input_method_commit;
|
||||
struct wl_listener input_method_new_popup_surface;
|
||||
struct wl_listener input_method_grab_keyboard;
|
||||
|
|
|
|||
|
|
@ -9,11 +9,14 @@ struct sway_input_popup {
|
|||
struct wlr_scene_tree *scene_tree;
|
||||
struct sway_popup_desc desc;
|
||||
struct wlr_input_popup_surface_v2 *popup_surface;
|
||||
struct wlr_output *fixed_output;
|
||||
|
||||
struct wl_list link;
|
||||
|
||||
struct wl_listener popup_destroy;
|
||||
struct wl_listener popup_surface_commit;
|
||||
struct wl_listener popup_surface_map;
|
||||
struct wl_listener popup_surface_unmap;
|
||||
|
||||
struct wl_listener focused_surface_unmap;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ struct sway_layer_surface {
|
|||
struct wl_listener map;
|
||||
struct wl_listener unmap;
|
||||
struct wl_listener surface_commit;
|
||||
struct wl_listener output_destroy;
|
||||
struct wl_listener node_destroy;
|
||||
struct wl_listener new_popup;
|
||||
|
||||
|
|
@ -19,6 +18,8 @@ struct sway_layer_surface {
|
|||
struct sway_popup_desc desc;
|
||||
|
||||
struct sway_output *output;
|
||||
struct wl_list link; // sway_output.layer_surfaces
|
||||
|
||||
struct wlr_scene_layer_surface_v1 *scene;
|
||||
struct wlr_scene_tree *tree;
|
||||
struct wlr_layer_surface_v1 *layer_surface;
|
||||
|
|
@ -41,4 +42,6 @@ struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface(
|
|||
|
||||
void arrange_layers(struct sway_output *output);
|
||||
|
||||
void destroy_layers(struct sway_output *output);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
6
include/sway/lock.h
Normal file
6
include/sway/lock.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef _SWAY_LOCK_H
|
||||
#define _SWAY_LOCK_H
|
||||
|
||||
void arrange_locks(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -52,27 +52,25 @@ struct sway_output {
|
|||
|
||||
bool enabled;
|
||||
list_t *workspaces;
|
||||
struct wl_list layer_surfaces; // sway_layer_surface.link
|
||||
|
||||
struct sway_output_state current;
|
||||
|
||||
struct wl_listener layout_destroy;
|
||||
struct wl_listener destroy;
|
||||
struct wl_listener commit;
|
||||
struct wl_listener present;
|
||||
struct wl_listener frame;
|
||||
struct wl_listener request_state;
|
||||
|
||||
struct {
|
||||
struct wl_signal disable;
|
||||
} events;
|
||||
|
||||
struct wlr_color_transform *color_transform;
|
||||
|
||||
struct timespec last_presentation;
|
||||
uint32_t refresh_nsec;
|
||||
int max_render_time; // In milliseconds
|
||||
struct wl_event_source *repaint_timer;
|
||||
bool gamma_lut_changed;
|
||||
|
||||
bool allow_tearing;
|
||||
bool hdr;
|
||||
};
|
||||
|
||||
struct sway_output_non_desktop {
|
||||
|
|
@ -92,6 +90,9 @@ struct sway_output *output_from_wlr_output(struct wlr_output *output);
|
|||
struct sway_output *output_get_in_direction(struct sway_output *reference,
|
||||
enum wlr_direction direction);
|
||||
|
||||
void output_configure_scene(struct sway_output *output,
|
||||
struct wlr_scene_node *node, float opacity);
|
||||
|
||||
void output_add_workspace(struct sway_output *output,
|
||||
struct sway_workspace *workspace);
|
||||
|
||||
|
|
@ -130,15 +131,13 @@ struct sway_container *output_find_container(struct sway_output *output,
|
|||
|
||||
void output_get_box(struct sway_output *output, struct wlr_box *box);
|
||||
|
||||
bool output_supports_hdr(struct wlr_output *output, const char **unsupported_reason_ptr);
|
||||
|
||||
enum sway_container_layout output_get_default_layout(
|
||||
struct sway_output *output);
|
||||
|
||||
enum wlr_direction opposite_direction(enum wlr_direction d);
|
||||
|
||||
void handle_output_layout_change(struct wl_listener *listener, void *data);
|
||||
|
||||
void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data);
|
||||
|
||||
void handle_output_manager_apply(struct wl_listener *listener, void *data);
|
||||
|
||||
void handle_output_manager_test(struct wl_listener *listener, void *data);
|
||||
|
|
@ -148,4 +147,6 @@ void handle_output_power_manager_set_mode(struct wl_listener *listener,
|
|||
|
||||
struct sway_output_non_desktop *output_non_desktop_create(struct wlr_output *wlr_output);
|
||||
|
||||
void update_output_manager_config(struct sway_server *server);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ struct sway_session_lock {
|
|||
struct sway_server {
|
||||
struct wl_display *wl_display;
|
||||
struct wl_event_loop *wl_event_loop;
|
||||
const char *socket;
|
||||
char *socket;
|
||||
|
||||
struct wlr_backend *backend;
|
||||
struct wlr_session *session;
|
||||
|
|
@ -45,8 +45,8 @@ struct sway_server {
|
|||
struct sway_input_manager *input;
|
||||
|
||||
struct wl_listener new_output;
|
||||
struct wl_listener output_layout_change;
|
||||
struct wl_listener renderer_lost;
|
||||
struct wl_event_source *recreating_renderer;
|
||||
|
||||
struct wlr_idle_notifier_v1 *idle_notifier_v1;
|
||||
struct sway_idle_inhibit_manager_v1 idle_inhibit_manager_v1;
|
||||
|
|
@ -105,17 +105,28 @@ struct sway_server {
|
|||
struct wlr_ext_foreign_toplevel_list_v1 *foreign_toplevel_list;
|
||||
struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager;
|
||||
struct wlr_content_type_manager_v1 *content_type_manager_v1;
|
||||
struct wlr_data_control_manager_v1 *data_control_manager_v1;
|
||||
struct wlr_data_control_manager_v1 *wlr_data_control_manager_v1;
|
||||
struct wlr_ext_data_control_manager_v1 *ext_data_control_manager_v1;
|
||||
struct wlr_screencopy_manager_v1 *screencopy_manager_v1;
|
||||
struct wlr_ext_image_copy_capture_manager_v1 *ext_image_copy_capture_manager_v1;
|
||||
struct wlr_export_dmabuf_manager_v1 *export_dmabuf_manager_v1;
|
||||
struct wlr_security_context_manager_v1 *security_context_manager_v1;
|
||||
|
||||
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1 *ext_foreign_toplevel_image_capture_source_manager_v1;
|
||||
struct wl_listener new_foreign_toplevel_capture_request;
|
||||
|
||||
struct wlr_xdg_activation_v1 *xdg_activation_v1;
|
||||
struct wl_listener xdg_activation_v1_request_activate;
|
||||
struct wl_listener xdg_activation_v1_new_token;
|
||||
|
||||
struct wl_listener xdg_toplevel_tag_manager_v1_set_tag;
|
||||
|
||||
struct wl_listener request_set_cursor_shape;
|
||||
|
||||
struct wlr_tearing_control_manager_v1 *tearing_control_v1;
|
||||
struct wl_listener tearing_control_new_object;
|
||||
struct wl_list tearing_controllers; // sway_tearing_controller::link
|
||||
|
||||
struct wl_list pending_launcher_ctxs; // launcher_ctx::link
|
||||
|
||||
// The timeout for transactions, after which a transaction is applied
|
||||
|
|
@ -145,20 +156,19 @@ struct sway_debug {
|
|||
bool noatomic; // Ignore atomic layout updates
|
||||
bool txn_timings; // Log verbose messages about transactions
|
||||
bool txn_wait; // Always wait for the timeout before applying
|
||||
bool legacy_wl_drm; // Enable the legacy wl_drm interface
|
||||
};
|
||||
|
||||
extern struct sway_debug debug;
|
||||
|
||||
extern bool allow_unsupported_gpu;
|
||||
|
||||
void sway_terminate(int exit_code);
|
||||
|
||||
bool server_init(struct sway_server *server);
|
||||
void server_fini(struct sway_server *server);
|
||||
bool server_start(struct sway_server *server);
|
||||
void server_run(struct sway_server *server);
|
||||
|
||||
void restore_nofile_limit(void);
|
||||
|
||||
void handle_new_output(struct wl_listener *listener, void *data);
|
||||
|
||||
void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data);
|
||||
|
|
@ -182,4 +192,6 @@ void xdg_activation_v1_handle_new_token(struct wl_listener *listener,
|
|||
|
||||
void set_rr_scheduling(void);
|
||||
|
||||
void handle_new_tearing_hint(struct wl_listener *listener, void *data);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ struct sway_container {
|
|||
|
||||
struct wl_listener output_enter;
|
||||
struct wl_listener output_leave;
|
||||
struct wl_listener output_handler_destroy;
|
||||
|
||||
struct sway_container_state current;
|
||||
struct sway_container_state pending;
|
||||
|
|
@ -103,6 +104,8 @@ struct sway_container {
|
|||
char *formatted_title; // The title displayed in the title bar
|
||||
int title_width;
|
||||
|
||||
char *title_format;
|
||||
|
||||
enum sway_container_layout prev_split_layout;
|
||||
|
||||
// Whether stickiness has been enabled on this container. Use
|
||||
|
|
@ -183,6 +186,8 @@ void container_update_title_bar(struct sway_container *container);
|
|||
|
||||
void container_update_marks(struct sway_container *container);
|
||||
|
||||
size_t parse_title_format(struct sway_container *container, char *buffer);
|
||||
|
||||
size_t container_build_representation(enum sway_container_layout layout,
|
||||
list_t *children, char *buffer);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,6 @@ struct sway_root {
|
|||
struct sway_node node;
|
||||
struct wlr_output_layout *output_layout;
|
||||
|
||||
struct wl_listener output_layout_change;
|
||||
|
||||
// scene node layout:
|
||||
// - root
|
||||
// - staging
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <wlr/config.h>
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/types/wlr_scene.h>
|
||||
#include <wlr/types/wlr_tearing_control_v1.h>
|
||||
#include "sway/config.h"
|
||||
#if WLR_HAS_XWAYLAND
|
||||
#include <wlr/xwayland.h>
|
||||
|
|
@ -24,6 +25,7 @@ enum sway_view_type {
|
|||
enum sway_view_prop {
|
||||
VIEW_PROP_TITLE,
|
||||
VIEW_PROP_APP_ID,
|
||||
VIEW_PROP_TAG,
|
||||
VIEW_PROP_CLASS,
|
||||
VIEW_PROP_INSTANCE,
|
||||
VIEW_PROP_WINDOW_TYPE,
|
||||
|
|
@ -34,6 +36,12 @@ enum sway_view_prop {
|
|||
#endif
|
||||
};
|
||||
|
||||
enum sway_view_tearing_mode {
|
||||
TEARING_OVERRIDE_FALSE,
|
||||
TEARING_OVERRIDE_TRUE,
|
||||
TEARING_WINDOW_HINT,
|
||||
};
|
||||
|
||||
struct sway_view_impl {
|
||||
void (*get_constraints)(struct sway_view *view, double *min_width,
|
||||
double *max_width, double *min_height, double *max_height);
|
||||
|
|
@ -62,6 +70,9 @@ struct sway_view {
|
|||
struct wlr_scene_tree *content_tree;
|
||||
struct wlr_scene_tree *saved_surface_tree;
|
||||
|
||||
struct wlr_scene *image_capture_scene;
|
||||
struct wlr_ext_image_capture_source_v1 *image_capture_source;
|
||||
|
||||
struct sway_container *container; // NULL if unmapped and transactions finished
|
||||
struct wlr_surface *surface; // NULL for unmapped views
|
||||
struct sway_xdg_decoration *xdg_decoration;
|
||||
|
|
@ -73,8 +84,6 @@ struct sway_view {
|
|||
// Used when changing a view from tiled to floating.
|
||||
int natural_width, natural_height;
|
||||
|
||||
char *title_format;
|
||||
|
||||
bool using_csd;
|
||||
|
||||
struct timespec urgent;
|
||||
|
|
@ -111,11 +120,17 @@ struct sway_view {
|
|||
int max_render_time; // In milliseconds
|
||||
|
||||
enum seat_config_shortcuts_inhibit shortcuts_inhibit;
|
||||
|
||||
enum sway_view_tearing_mode tearing_mode;
|
||||
enum wp_tearing_control_v1_presentation_hint tearing_hint;
|
||||
};
|
||||
|
||||
struct sway_xdg_shell_view {
|
||||
struct sway_view view;
|
||||
|
||||
struct wlr_scene_tree *image_capture_tree;
|
||||
char *tag;
|
||||
|
||||
struct wl_listener commit;
|
||||
struct wl_listener request_move;
|
||||
struct wl_listener request_resize;
|
||||
|
|
@ -134,6 +149,8 @@ struct sway_xwayland_view {
|
|||
|
||||
struct wlr_scene_tree *surface_tree;
|
||||
|
||||
struct wlr_scene_surface *image_capture_scene_surface;
|
||||
|
||||
struct wl_listener commit;
|
||||
struct wl_listener request_move;
|
||||
struct wl_listener request_resize;
|
||||
|
|
@ -184,10 +201,12 @@ struct sway_popup_desc {
|
|||
|
||||
struct sway_xdg_popup {
|
||||
struct sway_view *view;
|
||||
struct wlr_xdg_popup *wlr_xdg_popup;
|
||||
|
||||
struct wlr_scene_tree *scene_tree;
|
||||
struct wlr_scene_tree *xdg_surface_tree;
|
||||
struct wlr_xdg_popup *wlr_xdg_popup;
|
||||
|
||||
struct wlr_scene_tree *image_capture_tree;
|
||||
|
||||
struct sway_popup_desc desc;
|
||||
|
||||
|
|
@ -213,6 +232,14 @@ const char *view_get_window_role(struct sway_view *view);
|
|||
|
||||
uint32_t view_get_window_type(struct sway_view *view);
|
||||
|
||||
const char *view_get_sandbox_engine(struct sway_view *view);
|
||||
|
||||
const char *view_get_sandbox_app_id(struct sway_view *view);
|
||||
|
||||
const char *view_get_sandbox_instance_id(struct sway_view *view);
|
||||
|
||||
const char *view_get_tag(struct sway_view *view);
|
||||
|
||||
const char *view_get_shell(struct sway_view *view);
|
||||
|
||||
void view_get_constraints(struct sway_view *view, double *min_width,
|
||||
|
|
@ -335,4 +362,8 @@ void view_assign_ctx(struct sway_view *view, struct launcher_ctx *ctx);
|
|||
|
||||
void view_send_frame_done(struct sway_view *view);
|
||||
|
||||
bool view_can_tear(struct sway_view *view);
|
||||
|
||||
void xdg_toplevel_tag_manager_v1_handle_set_tag(struct wl_listener *listener, void *data);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ void workspace_output_add_priority(struct sway_workspace *workspace,
|
|||
struct sway_output *output);
|
||||
|
||||
struct sway_output *workspace_output_get_highest_available(
|
||||
struct sway_workspace *ws, struct sway_output *exclude);
|
||||
struct sway_workspace *ws);
|
||||
|
||||
void workspace_detect_urgent(struct sway_workspace *workspace);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,11 @@ struct box_colors {
|
|||
uint32_t text;
|
||||
};
|
||||
|
||||
struct box_size {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
};
|
||||
|
||||
struct config_output {
|
||||
struct wl_list link; // swaybar_config::outputs
|
||||
char *name;
|
||||
|
|
|
|||
|
|
@ -61,4 +61,6 @@ const char *sway_wl_output_subpixel_to_string(enum wl_output_subpixel subpixel);
|
|||
|
||||
bool sway_set_cloexec(int fd, bool cloexec);
|
||||
|
||||
uint32_t get_current_time_in_msec(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
50
meson.build
50
meson.build
|
|
@ -1,13 +1,14 @@
|
|||
project(
|
||||
'sway',
|
||||
'c',
|
||||
version: '1.10-dev',
|
||||
version: '1.12-dev',
|
||||
license: 'MIT',
|
||||
meson_version: '>=0.60.0',
|
||||
meson_version: '>=1.3',
|
||||
default_options: [
|
||||
'c_std=c11',
|
||||
'warning_level=2',
|
||||
'werror=true',
|
||||
'wrap_mode=nodownload',
|
||||
],
|
||||
)
|
||||
|
||||
|
|
@ -38,14 +39,14 @@ if is_freebsd
|
|||
endif
|
||||
|
||||
# Execute the wlroots subproject, if any
|
||||
wlroots_version = ['>=0.18.0', '<0.19.0']
|
||||
wlroots_version = ['>=0.20.0', '<0.21.0']
|
||||
subproject(
|
||||
'wlroots',
|
||||
default_options: ['examples=false'],
|
||||
required: false,
|
||||
version: wlroots_version,
|
||||
)
|
||||
wlroots = dependency('wlroots-0.18', version: wlroots_version, fallback: 'wlroots')
|
||||
wlroots = dependency('wlroots-0.20', version: wlroots_version, fallback: 'wlroots')
|
||||
wlroots_features = {
|
||||
'xwayland': false,
|
||||
'libinput_backend': false,
|
||||
|
|
@ -64,7 +65,7 @@ pcre2 = dependency('libpcre2-8')
|
|||
wayland_server = dependency('wayland-server', version: '>=1.21.0')
|
||||
wayland_client = dependency('wayland-client')
|
||||
wayland_cursor = dependency('wayland-cursor')
|
||||
wayland_protos = dependency('wayland-protocols', version: '>=1.24', default_options: ['tests=false'])
|
||||
wayland_protos = dependency('wayland-protocols', version: '>=1.41', default_options: ['tests=false'])
|
||||
xkbcommon = dependency('xkbcommon', version: '>=1.5.0')
|
||||
cairo = dependency('cairo')
|
||||
pango = dependency('pango')
|
||||
|
|
@ -79,7 +80,7 @@ libudev = wlroots_features['libinput_backend'] ? dependency('libudev') : null_de
|
|||
math = cc.find_library('m')
|
||||
rt = cc.find_library('rt')
|
||||
xcb_icccm = wlroots_features['xwayland'] ? dependency('xcb-icccm') : null_dep
|
||||
threads = dependency('threads') # for pthread_setschedparam
|
||||
threads = dependency('threads') # for pthread_setschedparam and pthread_atfork
|
||||
|
||||
if get_option('sd-bus-provider') == 'auto'
|
||||
if not get_option('tray').disabled()
|
||||
|
|
@ -109,11 +110,9 @@ conf_data.set10('HAVE_LIBSYSTEMD', sdbus.found() and sdbus.name() == 'libsystemd
|
|||
conf_data.set10('HAVE_LIBELOGIND', sdbus.found() and sdbus.name() == 'libelogind')
|
||||
conf_data.set10('HAVE_BASU', sdbus.found() and sdbus.name() == 'basu')
|
||||
conf_data.set10('HAVE_TRAY', have_tray)
|
||||
conf_data.set10('HAVE_LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM', cc.has_header_symbol(
|
||||
'libinput.h',
|
||||
'LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM',
|
||||
dependencies: libinput,
|
||||
))
|
||||
foreach sym : ['LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM', 'LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY']
|
||||
conf_data.set10('HAVE_' + sym, cc.has_header_symbol('libinput.h', sym, dependencies: libinput))
|
||||
endforeach
|
||||
|
||||
scdoc = dependency('scdoc', version: '>=1.9.2', native: true, required: get_option('man-pages'))
|
||||
if scdoc.found()
|
||||
|
|
@ -160,8 +159,8 @@ add_project_arguments('-DSYSCONFDIR="/@0@"'.format(join_paths(prefix, sysconfdir
|
|||
version = '"@0@"'.format(meson.project_version())
|
||||
git = find_program('git', native: true, required: false)
|
||||
if git.found()
|
||||
git_commit = run_command([git, 'rev-parse', '--short', 'HEAD'], check: false)
|
||||
git_branch = run_command([git, 'rev-parse', '--abbrev-ref', 'HEAD'], check: false)
|
||||
git_commit = run_command([git, '--git-dir=.git', 'rev-parse', '--short', 'HEAD'], check: false)
|
||||
git_branch = run_command([git, '--git-dir=.git', 'rev-parse', '--abbrev-ref', 'HEAD'], check: false)
|
||||
if git_commit.returncode() == 0 and git_branch.returncode() == 0
|
||||
version = '"@0@-@1@ (" __DATE__ ", branch \'@2@\')"'.format(
|
||||
meson.project_version(),
|
||||
|
|
@ -172,31 +171,10 @@ if git.found()
|
|||
endif
|
||||
add_project_arguments('-DSWAY_VERSION=@0@'.format(version), language: 'c')
|
||||
|
||||
# Compute the relative path used by compiler invocations.
|
||||
source_root = meson.current_source_dir().split('/')
|
||||
build_root = meson.global_build_root().split('/')
|
||||
relative_dir_parts = []
|
||||
i = 0
|
||||
in_prefix = true
|
||||
foreach p : build_root
|
||||
if i >= source_root.length() or not in_prefix or p != source_root[i]
|
||||
in_prefix = false
|
||||
relative_dir_parts += '..'
|
||||
endif
|
||||
i += 1
|
||||
endforeach
|
||||
i = 0
|
||||
in_prefix = true
|
||||
foreach p : source_root
|
||||
if i >= build_root.length() or not in_prefix or build_root[i] != p
|
||||
in_prefix = false
|
||||
relative_dir_parts += p
|
||||
endif
|
||||
i += 1
|
||||
endforeach
|
||||
relative_dir = join_paths(relative_dir_parts) + '/'
|
||||
fs = import('fs')
|
||||
|
||||
# Strip relative path prefixes from the code if possible, otherwise hide them.
|
||||
relative_dir = fs.relative_to(meson.current_source_dir(), meson.global_build_root()) + '/'
|
||||
if cc.has_argument('-fmacro-prefix-map=/prefix/to/hide=')
|
||||
add_project_arguments(
|
||||
'-fmacro-prefix-map=@0@='.format(relative_dir),
|
||||
|
|
|
|||
|
|
@ -9,11 +9,8 @@ wayland_scanner = find_program(
|
|||
protocols = [
|
||||
wl_protocol_dir / 'stable/tablet/tablet-v2.xml',
|
||||
wl_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
|
||||
wl_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
|
||||
wl_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml',
|
||||
wl_protocol_dir / 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml',
|
||||
wl_protocol_dir / 'staging/content-type/content-type-v1.xml',
|
||||
wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
|
||||
wl_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
|
||||
'wlr-layer-shell-unstable-v1.xml',
|
||||
'idle.xml',
|
||||
'wlr-output-power-management-unstable-v1.xml',
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/sh -eu
|
||||
|
||||
prev=$(git describe --tags --abbrev=0)
|
||||
next=$(meson rewrite kwargs info project / 2>&1 >/dev/null | jq -r '.kwargs["project#/"].version')
|
||||
next=$(meson rewrite kwargs info project / | jq -r '.kwargs["project#/"].version')
|
||||
|
||||
case "$next" in
|
||||
*-dev)
|
||||
|
|
@ -28,4 +28,5 @@ archive=$prefix.tar.gz
|
|||
git archive --prefix="$prefix/" -o "$archive" "$next"
|
||||
gpg --output "$archive".sig --detach-sig "$archive"
|
||||
|
||||
git push --follow-tags
|
||||
gh release create "sway $next" -t "$next" -n "" -d "$archive" "$archive.sig"
|
||||
|
|
|
|||
|
|
@ -3,3 +3,4 @@ Name=Sway
|
|||
Comment=An i3-compatible Wayland compositor
|
||||
Exec=sway
|
||||
Type=Application
|
||||
DesktopNames=sway;wlroots
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ static const struct cmd_handler config_handlers[] = {
|
|||
|
||||
/* Runtime-only commands. Keep alphabetized */
|
||||
static const struct cmd_handler command_handlers[] = {
|
||||
{ "allow_tearing", cmd_allow_tearing },
|
||||
{ "border", cmd_border },
|
||||
{ "create_output", cmd_create_output },
|
||||
{ "exit", cmd_exit },
|
||||
|
|
|
|||
24
sway/commands/allow_tearing.c
Normal file
24
sway/commands/allow_tearing.c
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#include <sway/commands.h>
|
||||
#include "sway/config.h"
|
||||
#include "sway/tree/view.h"
|
||||
#include "util.h"
|
||||
|
||||
struct cmd_results *cmd_allow_tearing(int argc, char **argv) {
|
||||
struct cmd_results *error = NULL;
|
||||
if ((error = checkarg(argc, "allow_tearing", EXPECTED_AT_LEAST, 1))) {
|
||||
return error;
|
||||
}
|
||||
|
||||
struct sway_container *container = config->handler_context.container;
|
||||
if (!container || !container->view) {
|
||||
return cmd_results_new(CMD_INVALID, "Tearing can only be allowed on views");
|
||||
}
|
||||
|
||||
bool wants_tearing = parse_boolean(argv[0], true);
|
||||
|
||||
struct sway_view *view = container->view;
|
||||
view->tearing_mode = wants_tearing ? TEARING_OVERRIDE_TRUE :
|
||||
TEARING_OVERRIDE_FALSE;
|
||||
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@ struct cmd_results *cmd_assign(int argc, char **argv) {
|
|||
|
||||
--argc; ++argv;
|
||||
|
||||
if (strncmp(*argv, "→", strlen("→")) == 0) {
|
||||
if (has_prefix(*argv, "→")) {
|
||||
if (argc < 2) {
|
||||
free(criteria);
|
||||
return cmd_results_new(CMD_INVALID, "Missing workspace");
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ struct cmd_results *bar_cmd_font(int argc, char **argv) {
|
|||
char *font = join_args(argv, argc);
|
||||
free(config->current_bar->font);
|
||||
|
||||
if (strncmp(font, "pango:", 6) == 0) {
|
||||
if (has_prefix(font, "pango:")) {
|
||||
if (config->current_bar->pango_markup == PANGO_MARKUP_DEFAULT) {
|
||||
config->current_bar->pango_markup = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -367,8 +367,7 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
|
|||
}
|
||||
} else if (strcmp("--exclude-titlebar", argv[0]) == 0) {
|
||||
exclude_titlebar = true;
|
||||
} else if (strncmp("--input-device=", argv[0],
|
||||
strlen("--input-device=")) == 0) {
|
||||
} else if (has_prefix(argv[0], "--input-device=")) {
|
||||
free(binding->input);
|
||||
binding->input = strdup(argv[0] + strlen("--input-device="));
|
||||
strip_quotes(binding->input);
|
||||
|
|
@ -399,7 +398,7 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
|
|||
list_t *split = split_string(argv[0], "+");
|
||||
for (int i = 0; i < split->length; ++i) {
|
||||
// Check for group
|
||||
if (strncmp(split->items[i], "Group", strlen("Group")) == 0) {
|
||||
if (has_prefix(split->items[i], "Group")) {
|
||||
if (binding->group != XKB_LAYOUT_INVALID) {
|
||||
free_sway_binding(binding);
|
||||
list_free_items_and_destroy(split);
|
||||
|
|
|
|||
|
|
@ -25,16 +25,6 @@ struct cmd_results *cmd_exec_validate(int argc, char **argv) {
|
|||
return error;
|
||||
}
|
||||
|
||||
static void export_xdga_token(struct launcher_ctx *ctx) {
|
||||
const char *token = launcher_ctx_get_token_name(ctx);
|
||||
setenv("XDG_ACTIVATION_TOKEN", token, 1);
|
||||
}
|
||||
|
||||
static void export_startup_id(struct launcher_ctx *ctx) {
|
||||
const char *token = launcher_ctx_get_token_name(ctx);
|
||||
setenv("DESKTOP_STARTUP_ID", token, 1);
|
||||
}
|
||||
|
||||
struct cmd_results *cmd_exec_process(int argc, char **argv) {
|
||||
struct cmd_results *error = NULL;
|
||||
char *cmd = NULL;
|
||||
|
|
@ -56,67 +46,37 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) {
|
|||
|
||||
sway_log(SWAY_DEBUG, "Executing %s", cmd);
|
||||
|
||||
int fd[2];
|
||||
if (pipe(fd) != 0) {
|
||||
sway_log(SWAY_ERROR, "Unable to create pipe for fork");
|
||||
struct launcher_ctx *ctx = launcher_ctx_create_internal();
|
||||
|
||||
// Fork process
|
||||
pid_t child = fork();
|
||||
if (child == 0) {
|
||||
setsid();
|
||||
|
||||
if (ctx) {
|
||||
const char *token = launcher_ctx_get_token_name(ctx);
|
||||
setenv("XDG_ACTIVATION_TOKEN", token, 1);
|
||||
if (!no_startup_id) {
|
||||
setenv("DESKTOP_STARTUP_ID", token, 1);
|
||||
}
|
||||
}
|
||||
|
||||
pid_t pid, child;
|
||||
struct launcher_ctx *ctx = launcher_ctx_create_internal();
|
||||
// Fork process
|
||||
if ((pid = fork()) == 0) {
|
||||
// Fork child process again
|
||||
restore_nofile_limit();
|
||||
setsid();
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
sigprocmask(SIG_SETMASK, &set, NULL);
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
close(fd[0]);
|
||||
if ((child = fork()) == 0) {
|
||||
close(fd[1]);
|
||||
if (ctx) {
|
||||
export_xdga_token(ctx);
|
||||
}
|
||||
if (ctx && !no_startup_id) {
|
||||
export_startup_id(ctx);
|
||||
}
|
||||
execlp("sh", "sh", "-c", cmd, (void*)NULL);
|
||||
sway_log_errno(SWAY_ERROR, "execlp failed");
|
||||
_exit(1);
|
||||
}
|
||||
ssize_t s = 0;
|
||||
while ((size_t)s < sizeof(pid_t)) {
|
||||
s += write(fd[1], ((uint8_t *)&child) + s, sizeof(pid_t) - s);
|
||||
}
|
||||
close(fd[1]);
|
||||
sway_log_errno(SWAY_ERROR, "execve failed");
|
||||
_exit(0); // Close child process
|
||||
} else if (pid < 0) {
|
||||
} else if (child < 0) {
|
||||
launcher_ctx_destroy(ctx);
|
||||
free(cmd);
|
||||
close(fd[0]);
|
||||
close(fd[1]);
|
||||
return cmd_results_new(CMD_FAILURE, "fork() failed");
|
||||
}
|
||||
free(cmd);
|
||||
close(fd[1]); // close write
|
||||
ssize_t s = 0;
|
||||
while ((size_t)s < sizeof(pid_t)) {
|
||||
s += read(fd[0], ((uint8_t *)&child) + s, sizeof(pid_t) - s);
|
||||
}
|
||||
close(fd[0]);
|
||||
// cleanup child process
|
||||
waitpid(pid, NULL, 0);
|
||||
if (child > 0) {
|
||||
|
||||
sway_log(SWAY_DEBUG, "Child process created with pid %d", child);
|
||||
if (ctx != NULL) {
|
||||
sway_log(SWAY_DEBUG, "Recording workspace for process %d", child);
|
||||
ctx->pid = child;
|
||||
}
|
||||
} else {
|
||||
launcher_ctx_destroy(ctx);
|
||||
return cmd_results_new(CMD_FAILURE, "Second fork() failed");
|
||||
}
|
||||
|
||||
free(cmd);
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
#include <stddef.h>
|
||||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
|
||||
void sway_terminate(int exit_code);
|
||||
#include "sway/server.h"
|
||||
|
||||
struct cmd_results *cmd_exit(int argc, char **argv) {
|
||||
struct cmd_results *error = NULL;
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ struct cmd_results *cmd_font(int argc, char **argv) {
|
|||
char *font = join_args(argv, argc);
|
||||
free(config->font);
|
||||
|
||||
if (strncmp(font, "pango:", 6) == 0) {
|
||||
if (has_prefix(font, "pango:")) {
|
||||
config->pango_markup = true;
|
||||
config->font = strdup(font + 6);
|
||||
config->font = strdup(font + strlen("pango:"));
|
||||
free(font);
|
||||
} else {
|
||||
config->pango_markup = false;
|
||||
|
|
|
|||
|
|
@ -215,15 +215,13 @@ struct cmd_results *cmd_gaps(int argc, char **argv) {
|
|||
return error;
|
||||
}
|
||||
|
||||
bool config_loading = !config->active || config->reloading;
|
||||
|
||||
if (argc == 2) {
|
||||
return gaps_set_defaults(argc, argv);
|
||||
}
|
||||
if (argc == 4 && !config_loading) {
|
||||
if (argc == 4 && !config->reading) {
|
||||
return gaps_set_runtime(argc, argv);
|
||||
}
|
||||
if (config_loading) {
|
||||
if (config->reading) {
|
||||
return cmd_results_new(CMD_INVALID, "Expected %s", expected_defaults);
|
||||
}
|
||||
return cmd_results_new(CMD_INVALID, "Expected %s or %s",
|
||||
|
|
|
|||
|
|
@ -121,8 +121,7 @@ static struct cmd_results *cmd_bind_or_unbind_gesture(int argc, char **argv, boo
|
|||
binding->flags |= BINDING_EXACT;
|
||||
} else if (strcmp("--no-warn", argv[0]) == 0) {
|
||||
warn = false;
|
||||
} else if (strncmp("--input-device=", argv[0],
|
||||
strlen("--input-device=")) == 0) {
|
||||
} else if (has_prefix(argv[0], "--input-device=")) {
|
||||
free(binding->input);
|
||||
binding->input = strdup(argv[0] + strlen("--input-device="));
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@
|
|||
|
||||
struct cmd_results *cmd_include(int argc, char **argv) {
|
||||
struct cmd_results *error = NULL;
|
||||
if ((error = checkarg(argc, "include", EXPECTED_EQUAL_TO, 1))) {
|
||||
if ((error = checkarg(argc, "include", EXPECTED_AT_LEAST, 1))) {
|
||||
return error;
|
||||
}
|
||||
|
||||
char *files = join_args(argv, argc);
|
||||
// We don't care if the included config(s) fails to load.
|
||||
load_include_configs(argv[0], config, &config->swaynag_config_errors);
|
||||
load_include_configs(files, config, &config->swaynag_config_errors);
|
||||
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ struct cmd_results *cmd_input(int argc, char **argv) {
|
|||
return res;
|
||||
}
|
||||
|
||||
if (!config->reloading) {
|
||||
if (!config->reading) {
|
||||
input_manager_apply_input_config(ic);
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@ struct cmd_results *input_cmd_drag_lock(int argc, char **argv) {
|
|||
return cmd_results_new(CMD_FAILURE, "No input device defined.");
|
||||
}
|
||||
|
||||
#if HAVE_LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY
|
||||
if (strcmp(argv[0], "enabled_sticky") == 0) {
|
||||
ic->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY;
|
||||
} else
|
||||
#endif
|
||||
if (parse_boolean(argv[0], true)) {
|
||||
ic->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ static void toggle_select_send_events_for_device(struct input_config *ic,
|
|||
static void toggle_send_events(int argc, char **argv) {
|
||||
struct input_config *ic = config->handler_context.input_config;
|
||||
bool wildcard = strcmp(ic->identifier, "*") == 0;
|
||||
const char *type = strncmp(ic->identifier, "type:", strlen("type:")) == 0
|
||||
const char *type = has_prefix(ic->identifier, "type:")
|
||||
? ic->identifier + strlen("type:") : NULL;
|
||||
struct sway_input_device *device = NULL;
|
||||
wl_list_for_each(device, &server.input->devices, link) {
|
||||
|
|
@ -146,8 +146,7 @@ struct cmd_results *input_cmd_events(int argc, char **argv) {
|
|||
|
||||
toggle_send_events(argc - 1, argv + 1);
|
||||
|
||||
if (strcmp(ic->identifier, "*") == 0 ||
|
||||
strncmp(ic->identifier, "type:", strlen("type:")) == 0) {
|
||||
if (strcmp(ic->identifier, "*") == 0 || has_prefix(ic->identifier, "type:")) {
|
||||
// Update the device input configs and then reset the type/wildcard
|
||||
// config send events mode so that is does not override the device
|
||||
// ones. The device ones will be applied when attempting to apply
|
||||
|
|
|
|||
|
|
@ -95,10 +95,18 @@ struct cmd_results *input_cmd_xkb_switch_layout(int argc, char **argv) {
|
|||
continue;
|
||||
}
|
||||
|
||||
struct wlr_keyboard *keyboard =
|
||||
wlr_keyboard_from_input_device(dev->wlr_device);
|
||||
if (keyboard->keymap == NULL && dev->is_virtual) {
|
||||
// The `sway_keyboard_set_layout` function is by default skipped
|
||||
// when configuring virtual keyboards.
|
||||
continue;
|
||||
}
|
||||
|
||||
struct xkb_switch_layout_action *action =
|
||||
&actions[actions_len++];
|
||||
action->keyboard = keyboard;
|
||||
|
||||
action->keyboard = wlr_keyboard_from_input_device(dev->wlr_device);
|
||||
if (relative) {
|
||||
action->layout = get_layout_relative(action->keyboard, relative);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -134,6 +134,19 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
|
|||
// Operate on parent container, like i3.
|
||||
if (container) {
|
||||
container = container->pending.parent;
|
||||
// If parent has only a singe child operate on its parent and
|
||||
// flatten once, like i3
|
||||
if (container && container->pending.children->length == 1) {
|
||||
// Also check grandparent to avoid restricting layouts
|
||||
struct sway_container *parent = container->pending.parent;
|
||||
if (parent && parent->pending.children->length == 1) {
|
||||
struct sway_container *child = container->pending.children->items[0];
|
||||
struct sway_container *parent = container->pending.parent;
|
||||
container_replace(container, child);
|
||||
container_begin_destroy(container);
|
||||
container = parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We could be working with a container OR a workspace. These are different
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ struct cmd_results *cmd_mark(int argc, char **argv) {
|
|||
}
|
||||
|
||||
bool add = false, toggle = false;
|
||||
while (argc > 0 && strncmp(*argv, "--", 2) == 0) {
|
||||
while (argc > 0 && has_prefix(*argv, "--")) {
|
||||
if (strcmp(*argv, "--add") == 0) {
|
||||
add = true;
|
||||
} else if (strcmp(*argv, "--replace") == 0) {
|
||||
|
|
|
|||
|
|
@ -222,6 +222,7 @@ static void container_move_to_workspace(struct sway_container *container,
|
|||
container_detach(container);
|
||||
if (workspace_is_empty(workspace) && container->pending.children) {
|
||||
workspace_unwrap_children(workspace, container);
|
||||
container_reap_empty(container);
|
||||
} else {
|
||||
container->pending.width = container->pending.height = 0;
|
||||
container->width_fraction = container->height_fraction = 0;
|
||||
|
|
@ -240,7 +241,6 @@ static void container_move_to_workspace(struct sway_container *container,
|
|||
static void container_move_to_container(struct sway_container *container,
|
||||
struct sway_container *destination) {
|
||||
if (container == destination
|
||||
|| container_has_ancestor(container, destination)
|
||||
|| container_has_ancestor(destination, container)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -510,6 +510,7 @@ static struct cmd_results *cmd_move_container(bool no_auto_back_and_forth,
|
|||
}
|
||||
}
|
||||
ws = workspace_create(NULL, ws_name);
|
||||
arrange_workspace(ws);
|
||||
}
|
||||
free(ws_name);
|
||||
struct sway_container *dst = seat_get_focus_inactive_tiling(seat, ws);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include "sway/commands.h"
|
||||
#include "sway/tree/view.h"
|
||||
#include "sway/tree/container.h"
|
||||
#include "sway/output.h"
|
||||
#include "log.h"
|
||||
|
||||
struct cmd_results *cmd_opacity(int argc, char **argv) {
|
||||
|
|
@ -37,6 +38,7 @@ struct cmd_results *cmd_opacity(int argc, char **argv) {
|
|||
}
|
||||
|
||||
con->alpha = val;
|
||||
output_configure_scene(NULL, &con->scene_tree->node, 1);
|
||||
container_update(con);
|
||||
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
|
|
|
|||
|
|
@ -8,12 +8,14 @@
|
|||
// must be in order for the bsearch
|
||||
static const struct cmd_handler output_handlers[] = {
|
||||
{ "adaptive_sync", output_cmd_adaptive_sync },
|
||||
{ "allow_tearing", output_cmd_allow_tearing },
|
||||
{ "background", output_cmd_background },
|
||||
{ "bg", output_cmd_background },
|
||||
{ "color_profile", output_cmd_color_profile },
|
||||
{ "disable", output_cmd_disable },
|
||||
{ "dpms", output_cmd_dpms },
|
||||
{ "enable", output_cmd_enable },
|
||||
{ "hdr", output_cmd_hdr },
|
||||
{ "max_render_time", output_cmd_max_render_time },
|
||||
{ "mode", output_cmd_mode },
|
||||
{ "modeline", output_cmd_modeline },
|
||||
|
|
@ -106,18 +108,17 @@ struct cmd_results *cmd_output(int argc, char **argv) {
|
|||
|
||||
store_output_config(output);
|
||||
|
||||
// If reloading, the output configs will be applied after reading the
|
||||
// entire config and before the deferred commands so that an auto generated
|
||||
// workspace name is not given to re-enabled outputs.
|
||||
if (!config->reloading && !config->validating) {
|
||||
apply_all_output_configs();
|
||||
if (background) {
|
||||
if (!spawn_swaybg()) {
|
||||
if (config->reading) {
|
||||
// When reading the config file, we wait till the end to do a single
|
||||
// modeset and swaybg spawn.
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
}
|
||||
request_modeset();
|
||||
|
||||
if (background && !spawn_swaybg()) {
|
||||
return cmd_results_new(CMD_FAILURE,
|
||||
"Failed to apply background configuration");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#include <strings.h>
|
||||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
#include "sway/output.h"
|
||||
#include "util.h"
|
||||
|
||||
struct cmd_results *output_cmd_adaptive_sync(int argc, char **argv) {
|
||||
|
|
@ -10,12 +12,26 @@ struct cmd_results *output_cmd_adaptive_sync(int argc, char **argv) {
|
|||
return cmd_results_new(CMD_INVALID, "Missing adaptive_sync argument");
|
||||
}
|
||||
|
||||
if (parse_boolean(argv[0], true)) {
|
||||
config->handler_context.output_config->adaptive_sync = 1;
|
||||
} else {
|
||||
config->handler_context.output_config->adaptive_sync = 0;
|
||||
bool current_value = true;
|
||||
if (strcasecmp(argv[0], "toggle") == 0) {
|
||||
const char *oc_name = config->handler_context.output_config->name;
|
||||
if (strcmp(oc_name, "*") == 0) {
|
||||
return cmd_results_new(CMD_INVALID,
|
||||
"Cannot apply toggle to all outputs");
|
||||
}
|
||||
|
||||
struct sway_output *sway_output = all_output_by_name_or_id(oc_name);
|
||||
if (!sway_output || !sway_output->wlr_output) {
|
||||
return cmd_results_new(CMD_FAILURE,
|
||||
"Cannot apply toggle to unknown output %s", oc_name);
|
||||
}
|
||||
|
||||
current_value =
|
||||
sway_output->wlr_output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED;
|
||||
}
|
||||
|
||||
config->handler_context.output_config->adaptive_sync = parse_boolean(argv[0], current_value);
|
||||
|
||||
config->handler_context.leftovers.argc = argc - 1;
|
||||
config->handler_context.leftovers.argv = argv + 1;
|
||||
return NULL;
|
||||
|
|
|
|||
23
sway/commands/output/allow_tearing.c
Normal file
23
sway/commands/output/allow_tearing.c
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
#include "util.h"
|
||||
|
||||
struct cmd_results *output_cmd_allow_tearing(int argc, char **argv) {
|
||||
if (!config->handler_context.output_config) {
|
||||
return cmd_results_new(CMD_FAILURE, "Missing output config");
|
||||
}
|
||||
if (argc == 0) {
|
||||
return cmd_results_new(CMD_INVALID, "Missing allow_tearing argument");
|
||||
}
|
||||
|
||||
if (parse_boolean(argv[0],
|
||||
(config->handler_context.output_config->allow_tearing == 1))) {
|
||||
config->handler_context.output_config->allow_tearing = 1;
|
||||
} else {
|
||||
config->handler_context.output_config->allow_tearing = 0;
|
||||
}
|
||||
|
||||
config->handler_context.leftovers.argc = argc - 1;
|
||||
config->handler_context.leftovers.argv = argv + 1;
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -3,10 +3,8 @@
|
|||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
#include "sway/swaynag.h"
|
||||
#include "log.h"
|
||||
#include "stringop.h"
|
||||
|
||||
|
|
@ -42,14 +40,14 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
|
|||
}
|
||||
|
||||
struct output_config *output = config->handler_context.output_config;
|
||||
|
||||
char *src = NULL;
|
||||
if (strcasecmp(argv[1], "solid_color") == 0) {
|
||||
if (!validate_color(argv[0])) {
|
||||
return cmd_results_new(CMD_INVALID,
|
||||
"Colors should be of the form #RRGGBB");
|
||||
}
|
||||
output->background = strdup(argv[0]);
|
||||
output->background_option = strdup("solid_color");
|
||||
if (!(output->background = strdup(argv[0]))) goto cleanup;
|
||||
if (!(output->background_option = strdup("solid_color"))) goto cleanup;
|
||||
output->background_fallback = NULL;
|
||||
argc -= 2; argv += 2;
|
||||
} else {
|
||||
|
|
@ -77,37 +75,25 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
|
|||
return cmd_results_new(CMD_INVALID, "Missing background file");
|
||||
}
|
||||
|
||||
char *src = join_args(argv, j);
|
||||
if (!(src = join_args(argv, j))) goto cleanup;
|
||||
if (!expand_path(&src)) {
|
||||
struct cmd_results *cmd_res = cmd_results_new(CMD_INVALID,
|
||||
"Invalid syntax (%s)", src);
|
||||
free(src);
|
||||
return cmd_res;
|
||||
}
|
||||
if (!src) {
|
||||
sway_log(SWAY_ERROR, "Failed to allocate expanded path");
|
||||
return cmd_results_new(CMD_FAILURE, "Unable to allocate resource");
|
||||
}
|
||||
|
||||
if (config->reading && *src != '/') {
|
||||
// src file is inside configuration dir
|
||||
|
||||
char *conf = strdup(config->current_config_path);
|
||||
if (!conf) {
|
||||
sway_log(SWAY_ERROR, "Failed to duplicate string");
|
||||
free(src);
|
||||
return cmd_results_new(CMD_FAILURE,
|
||||
"Unable to allocate resources");
|
||||
}
|
||||
if (!conf) goto cleanup;
|
||||
|
||||
char *conf_path = dirname(conf);
|
||||
char *real_src = malloc(strlen(conf_path) + strlen(src) + 2);
|
||||
if (!real_src) {
|
||||
free(src);
|
||||
free(conf);
|
||||
sway_log(SWAY_ERROR, "Unable to allocate memory");
|
||||
return cmd_results_new(CMD_FAILURE,
|
||||
"Unable to allocate resources");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
snprintf(real_src, strlen(conf_path) + strlen(src) + 2, "%s/%s", conf_path, src);
|
||||
|
|
@ -117,40 +103,48 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
|
|||
}
|
||||
|
||||
bool can_access = access(src, F_OK) != -1;
|
||||
argc -= j + 1; argv += j + 1;
|
||||
free(output->background_option);
|
||||
free(output->background_fallback);
|
||||
free(output->background);
|
||||
output->background = output->background_option = output->background_fallback = NULL;
|
||||
char *fallback = NULL;
|
||||
|
||||
if (argc && *argv[0] == '#') {
|
||||
if (validate_color(argv[0])) {
|
||||
if (!(fallback = strdup(argv[0]))) goto cleanup;
|
||||
output->background_fallback = fallback;
|
||||
} else {
|
||||
sway_log(SWAY_ERROR, "fallback '%s' should be of the form #RRGGBB", argv[0]);
|
||||
config_add_swaynag_warning("fallback '%s' should be of the form #RRGGBB\n", argv[0]);
|
||||
}
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
if (!can_access) {
|
||||
sway_log_errno(SWAY_ERROR, "Unable to access background file '%s'",
|
||||
src);
|
||||
config_add_swaynag_warning("Unable to access background file '%s'",
|
||||
src);
|
||||
struct cmd_results *result = cmd_results_new(CMD_FAILURE,
|
||||
"unable to access background file '%s'", src);
|
||||
if (!fallback) {
|
||||
sway_log(SWAY_ERROR, "Unable to access background file '%s' "
|
||||
"and no valid fallback provided", src);
|
||||
struct cmd_results *res = cmd_results_new(CMD_FAILURE, "Unable to access "
|
||||
"background file '%s' and no valid fallback provided", src);
|
||||
free(src);
|
||||
return result;
|
||||
return res;
|
||||
}
|
||||
sway_log(SWAY_DEBUG, "Cannot access file '%s', using fallback '%s'", src, fallback);
|
||||
output->background = fallback;
|
||||
if (!(output->background_option = strdup("solid_color"))) goto cleanup;
|
||||
output->background_fallback = NULL;
|
||||
} else {
|
||||
output->background = src;
|
||||
output->background_option = strdup(mode);
|
||||
}
|
||||
argc -= j + 1; argv += j + 1;
|
||||
|
||||
output->background_fallback = NULL;
|
||||
if (argc && *argv[0] == '#') {
|
||||
if (!validate_color(argv[0])) {
|
||||
return cmd_results_new(CMD_INVALID,
|
||||
"fallback color should be of the form #RRGGBB");
|
||||
}
|
||||
|
||||
output->background_fallback = strdup(argv[0]);
|
||||
argc--; argv++;
|
||||
|
||||
if (!can_access) {
|
||||
output->background = output->background_fallback;
|
||||
output->background_option = strdup("solid_color");
|
||||
output->background_fallback = NULL;
|
||||
if (!(output->background_option = strdup(mode))) goto cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config->handler_context.leftovers.argc = argc;
|
||||
config->handler_context.leftovers.argv = argv;
|
||||
return NULL;
|
||||
|
||||
cleanup:
|
||||
free(src);
|
||||
sway_log(SWAY_ERROR, "Failed to allocate resources");
|
||||
return cmd_results_new(CMD_FAILURE, "Unable to allocate resources");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <wlr/render/color.h>
|
||||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
#include "stringop.h"
|
||||
|
||||
static bool read_file_into_buf(const char *path, void **buf, size_t *size) {
|
||||
/* Why not use fopen/fread directly? glibc will succesfully open directories,
|
||||
|
|
@ -70,12 +71,23 @@ struct cmd_results *output_cmd_color_profile(int argc, char **argv) {
|
|||
return cmd_results_new(CMD_INVALID,
|
||||
"Invalid color profile specification: icc type requires a file");
|
||||
}
|
||||
|
||||
char *icc_path = strdup(argv[1]);
|
||||
if (!expand_path(&icc_path)) {
|
||||
struct cmd_results *cmd_res = cmd_results_new(CMD_INVALID,
|
||||
"Invalid color profile specification: invalid file path");
|
||||
free(icc_path);
|
||||
return cmd_res;
|
||||
}
|
||||
|
||||
void *data = NULL;
|
||||
size_t size = 0;
|
||||
if (!read_file_into_buf(argv[1], &data, &size)) {
|
||||
if (!read_file_into_buf(icc_path, &data, &size)) {
|
||||
free(icc_path);
|
||||
return cmd_results_new(CMD_FAILURE,
|
||||
"Failed to load color profile: could not read ICC file");
|
||||
}
|
||||
free(icc_path);
|
||||
|
||||
struct wlr_color_transform *tmp =
|
||||
wlr_color_transform_init_linear_to_icc(data, size);
|
||||
|
|
|
|||
37
sway/commands/output/hdr.c
Normal file
37
sway/commands/output/hdr.c
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#include <strings.h>
|
||||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
#include "sway/output.h"
|
||||
#include "util.h"
|
||||
|
||||
struct cmd_results *output_cmd_hdr(int argc, char **argv) {
|
||||
if (!config->handler_context.output_config) {
|
||||
return cmd_results_new(CMD_FAILURE, "Missing output config");
|
||||
}
|
||||
if (argc == 0) {
|
||||
return cmd_results_new(CMD_INVALID, "Missing hdr argument");
|
||||
}
|
||||
|
||||
bool current = false;
|
||||
if (strcasecmp(argv[0], "toggle") == 0) {
|
||||
const char *oc_name = config->handler_context.output_config->name;
|
||||
if (strcmp(oc_name, "*") == 0) {
|
||||
return cmd_results_new(CMD_INVALID,
|
||||
"Cannot apply toggle to all outputs");
|
||||
}
|
||||
|
||||
struct sway_output *output = all_output_by_name_or_id(oc_name);
|
||||
if (!output) {
|
||||
return cmd_results_new(CMD_FAILURE,
|
||||
"Cannot apply toggle to unknown output %s", oc_name);
|
||||
}
|
||||
|
||||
current = output->hdr;
|
||||
}
|
||||
|
||||
config->handler_context.output_config->hdr = parse_boolean(argv[0], current);
|
||||
|
||||
config->handler_context.leftovers.argc = argc - 1;
|
||||
config->handler_context.leftovers.argv = argv + 1;
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -11,7 +11,10 @@ struct cmd_results *output_cmd_render_bit_depth(int argc, char **argv) {
|
|||
return cmd_results_new(CMD_INVALID, "Missing bit depth argument.");
|
||||
}
|
||||
|
||||
if (strcmp(*argv, "8") == 0) {
|
||||
if (strcmp(*argv, "6") == 0) {
|
||||
config->handler_context.output_config->render_bit_depth =
|
||||
RENDER_BIT_DEPTH_6;
|
||||
} else if (strcmp(*argv, "8") == 0) {
|
||||
config->handler_context.output_config->render_bit_depth =
|
||||
RENDER_BIT_DEPTH_8;
|
||||
} else if (strcmp(*argv, "10") == 0) {
|
||||
|
|
@ -19,7 +22,7 @@ struct cmd_results *output_cmd_render_bit_depth(int argc, char **argv) {
|
|||
RENDER_BIT_DEPTH_10;
|
||||
} else {
|
||||
return cmd_results_new(CMD_INVALID,
|
||||
"Invalid bit depth. Must be a value in (8|10).");
|
||||
"Invalid bit depth. Must be a value in (6|8|10).");
|
||||
}
|
||||
|
||||
config->handler_context.leftovers.argc = argc - 1;
|
||||
|
|
|
|||
|
|
@ -80,61 +80,46 @@ void container_resize_tiled(struct sway_container *con,
|
|||
}
|
||||
|
||||
// For HORIZONTAL or VERTICAL, we are growing in two directions so select
|
||||
// both adjacent siblings. For RIGHT or DOWN, just select the next sibling.
|
||||
// For LEFT or UP, convert it to a RIGHT or DOWN resize and reassign con to
|
||||
// the previous sibling.
|
||||
struct sway_container *prev = NULL;
|
||||
struct sway_container *next = NULL;
|
||||
// all adjacent siblings. For RIGHT or DOWN or LEFT or UP select just the
|
||||
// previous or next sibling.
|
||||
list_t *resize = create_list();
|
||||
list_t *siblings = container_get_siblings(con);
|
||||
int index = container_sibling_index(con);
|
||||
|
||||
if (axis == AXIS_HORIZONTAL || axis == AXIS_VERTICAL) {
|
||||
if (index == 0) {
|
||||
next = siblings->items[1];
|
||||
} else if (index == siblings->length - 1) {
|
||||
// Convert edge to top/left
|
||||
next = con;
|
||||
con = siblings->items[index - 1];
|
||||
amount = -amount;
|
||||
} else {
|
||||
prev = siblings->items[index - 1];
|
||||
next = siblings->items[index + 1];
|
||||
}
|
||||
list_cat(resize, siblings);
|
||||
} else if (axis == WLR_EDGE_TOP || axis == WLR_EDGE_LEFT) {
|
||||
if (!sway_assert(index > 0, "Didn't expect first child")) {
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
next = con;
|
||||
con = siblings->items[index - 1];
|
||||
amount = -amount;
|
||||
list_add(resize, siblings->items[index - 1]);
|
||||
list_add(resize, con);
|
||||
} else {
|
||||
if (!sway_assert(index < siblings->length - 1,
|
||||
"Didn't expect last child")) {
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
next = siblings->items[index + 1];
|
||||
list_add(resize, con);
|
||||
list_add(resize, siblings->items[index + 1]);
|
||||
}
|
||||
|
||||
// Apply new dimensions
|
||||
int sibling_amount = prev ? ceil((double)amount / 2.0) : amount;
|
||||
int sibling_amount = ceil((double)amount / (double)(resize->length - 1));
|
||||
|
||||
if (is_horizontal(axis)) {
|
||||
if (con->pending.width + amount < MIN_SANE_W) {
|
||||
return;
|
||||
for (int i = 0; i < resize->length; i++) {
|
||||
struct sway_container *sibling = resize->items[i];
|
||||
double change = sibling == con ? amount : -sibling_amount;
|
||||
if (sibling->pending.width + change < MIN_SANE_W) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (next->pending.width - sibling_amount < MIN_SANE_W) {
|
||||
return;
|
||||
}
|
||||
if (prev && prev->pending.width - sibling_amount < MIN_SANE_W) {
|
||||
return;
|
||||
}
|
||||
if (con->child_total_width <= 0) {
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// We're going to resize so snap all the width fractions to full pixels
|
||||
// to avoid rounding issues
|
||||
list_t *siblings = container_get_siblings(con);
|
||||
for (int i = 0; i < siblings->length; ++i) {
|
||||
struct sway_container *con = siblings->items[i];
|
||||
con->width_fraction = con->pending.width / con->child_total_width;
|
||||
|
|
@ -142,30 +127,27 @@ void container_resize_tiled(struct sway_container *con,
|
|||
|
||||
double amount_fraction = (double)amount / con->child_total_width;
|
||||
double sibling_amount_fraction =
|
||||
prev ? amount_fraction / 2.0 : amount_fraction;
|
||||
amount_fraction / (double)(resize->length - 1);
|
||||
|
||||
con->width_fraction += amount_fraction;
|
||||
next->width_fraction -= sibling_amount_fraction;
|
||||
if (prev) {
|
||||
prev->width_fraction -= sibling_amount_fraction;
|
||||
for (int i = 0; i < resize->length; i++) {
|
||||
struct sway_container *sibling = resize->items[i];
|
||||
sibling->width_fraction +=
|
||||
sibling == con ? amount_fraction : -sibling_amount_fraction;
|
||||
}
|
||||
} else {
|
||||
if (con->pending.height + amount < MIN_SANE_H) {
|
||||
return;
|
||||
for (int i = 0; i < resize->length; i++) {
|
||||
struct sway_container *sibling = resize->items[i];
|
||||
double change = sibling == con ? amount : -sibling_amount;
|
||||
if (sibling->pending.height + change < MIN_SANE_H) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (next->pending.height - sibling_amount < MIN_SANE_H) {
|
||||
return;
|
||||
}
|
||||
if (prev && prev->pending.height - sibling_amount < MIN_SANE_H) {
|
||||
return;
|
||||
}
|
||||
if (con->child_total_height <= 0) {
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// We're going to resize so snap all the height fractions to full pixels
|
||||
// to avoid rounding issues
|
||||
list_t *siblings = container_get_siblings(con);
|
||||
for (int i = 0; i < siblings->length; ++i) {
|
||||
struct sway_container *con = siblings->items[i];
|
||||
con->height_fraction = con->pending.height / con->child_total_height;
|
||||
|
|
@ -173,12 +155,12 @@ void container_resize_tiled(struct sway_container *con,
|
|||
|
||||
double amount_fraction = (double)amount / con->child_total_height;
|
||||
double sibling_amount_fraction =
|
||||
prev ? amount_fraction / 2.0 : amount_fraction;
|
||||
amount_fraction / (double)(resize->length - 1);
|
||||
|
||||
con->height_fraction += amount_fraction;
|
||||
next->height_fraction -= sibling_amount_fraction;
|
||||
if (prev) {
|
||||
prev->height_fraction -= sibling_amount_fraction;
|
||||
for (int i = 0; i < resize->length; i++) {
|
||||
struct sway_container *sibling = resize->items[i];
|
||||
sibling->height_fraction +=
|
||||
sibling == con ? amount_fraction : -sibling_amount_fraction;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -187,6 +169,9 @@ void container_resize_tiled(struct sway_container *con,
|
|||
} else {
|
||||
arrange_workspace(con->pending.workspace);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
list_free(resize);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -457,7 +442,7 @@ static struct cmd_results *cmd_resize_set(int argc, char **argv) {
|
|||
if (argc > num_consumed_args) {
|
||||
return cmd_results_new(CMD_INVALID, "%s", usage);
|
||||
}
|
||||
if (width.unit == MOVEMENT_UNIT_INVALID) {
|
||||
if (height.unit == MOVEMENT_UNIT_INVALID) {
|
||||
return cmd_results_new(CMD_INVALID, "%s", usage);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,10 +118,10 @@ struct cmd_results *cmd_scratchpad(int argc, char **argv) {
|
|||
|
||||
// If using criteria, this command is executed for every container which
|
||||
// matches the criteria. If this container isn't in the scratchpad,
|
||||
// we'll just silently return a success. The same is true if the
|
||||
// we'll return an error. The same is true if the
|
||||
// overridden node is not a container.
|
||||
if (!con || !con->scratchpad) {
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
return cmd_results_new(CMD_INVALID, "Container is not in scratchpad.");
|
||||
}
|
||||
scratchpad_toggle_container(con);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <string.h>
|
||||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
|
|
@ -11,16 +12,19 @@ struct cmd_results *cmd_title_format(int argc, char **argv) {
|
|||
return error;
|
||||
}
|
||||
struct sway_container *container = config->handler_context.container;
|
||||
if (!container || !container->view) {
|
||||
if (!container) {
|
||||
return cmd_results_new(CMD_INVALID,
|
||||
"Only views can have a title_format");
|
||||
"Only valid containers can have a title_format");
|
||||
}
|
||||
struct sway_view *view = container->view;
|
||||
char *format = join_args(argv, argc);
|
||||
if (view->title_format) {
|
||||
free(view->title_format);
|
||||
if (container->title_format) {
|
||||
free(container->title_format);
|
||||
}
|
||||
container->title_format = format;
|
||||
if (container->view) {
|
||||
view_update_title(container->view, true);
|
||||
} else {
|
||||
container_update_representation(container);
|
||||
}
|
||||
view->title_format = format;
|
||||
view_update_title(view, true);
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -516,7 +516,7 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
|
|||
// Only really necessary if not explicitly `font` is set in the config.
|
||||
config_update_font_height();
|
||||
|
||||
if (is_active && !validating) {
|
||||
if (!validating) {
|
||||
input_manager_verify_fallback_seat();
|
||||
|
||||
for (int i = 0; i < config->input_configs->length; i++) {
|
||||
|
|
@ -533,14 +533,16 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
|
|||
}
|
||||
sway_switch_retrigger_bindings_for_all();
|
||||
|
||||
apply_all_output_configs();
|
||||
spawn_swaybg();
|
||||
|
||||
config->reloading = false;
|
||||
if (is_active) {
|
||||
request_modeset();
|
||||
if (config->swaynag_config_errors.client != NULL) {
|
||||
swaynag_show(&config->swaynag_config_errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (old_config) {
|
||||
destroy_removed_seats(old_config, config);
|
||||
|
|
@ -550,28 +552,12 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
|
|||
return success;
|
||||
}
|
||||
|
||||
static bool load_include_config(const char *path, const char *parent_dir,
|
||||
struct sway_config *config, struct swaynag_instance *swaynag) {
|
||||
static bool load_include_config(const char *path, struct sway_config *config,
|
||||
struct swaynag_instance *swaynag) {
|
||||
// save parent config
|
||||
const char *parent_config = config->current_config_path;
|
||||
|
||||
char *full_path;
|
||||
int len = strlen(path);
|
||||
if (len >= 1 && path[0] != '/') {
|
||||
len = len + strlen(parent_dir) + 2;
|
||||
full_path = malloc(len * sizeof(char));
|
||||
if (!full_path) {
|
||||
sway_log(SWAY_ERROR,
|
||||
"Unable to allocate full path to included config");
|
||||
return false;
|
||||
}
|
||||
snprintf(full_path, len, "%s/%s", parent_dir, path);
|
||||
} else {
|
||||
full_path = strdup(path);
|
||||
}
|
||||
|
||||
char *real_path = realpath(full_path, NULL);
|
||||
free(full_path);
|
||||
char *real_path = realpath(path, NULL);
|
||||
|
||||
if (real_path == NULL) {
|
||||
sway_log(SWAY_DEBUG, "%s not found.", path);
|
||||
|
|
@ -623,7 +609,7 @@ void load_include_configs(const char *path, struct sway_config *config,
|
|||
char **w = p.we_wordv;
|
||||
size_t i;
|
||||
for (i = 0; i < p.we_wordc; ++i) {
|
||||
load_include_config(w[i], parent_dir, config, swaynag);
|
||||
load_include_config(w[i], config, swaynag);
|
||||
}
|
||||
wordfree(&p);
|
||||
}
|
||||
|
|
@ -923,8 +909,8 @@ char *do_var_replacement(char *str) {
|
|||
// Find matching variable
|
||||
for (i = 0; i < config->symbols->length; ++i) {
|
||||
struct sway_variable *var = config->symbols->items[i];
|
||||
if (has_prefix(find, var->name)) {
|
||||
int vnlen = strlen(var->name);
|
||||
if (strncmp(find, var->name, vnlen) == 0) {
|
||||
int vvlen = strlen(var->value);
|
||||
char *newstr = malloc(strlen(str) - vnlen + vvlen + 1);
|
||||
if (!newstr) {
|
||||
|
|
|
|||
|
|
@ -212,19 +212,6 @@ static void invoke_swaybar(struct bar_config *bar) {
|
|||
if (pid < 0) {
|
||||
sway_log(SWAY_ERROR, "Failed to create fork for swaybar");
|
||||
return;
|
||||
} else if (pid == 0) {
|
||||
// Remove the SIGUSR1 handler that wlroots adds for xwayland
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
sigprocmask(SIG_SETMASK, &set, NULL);
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
|
||||
restore_nofile_limit();
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||
_exit(EXIT_FAILURE);
|
||||
} else if (pid == 0) {
|
||||
if (!sway_set_cloexec(sockets[1], false)) {
|
||||
_exit(EXIT_FAILURE);
|
||||
|
|
@ -242,19 +229,12 @@ static void invoke_swaybar(struct bar_config *bar) {
|
|||
execvp(cmd[0], cmd);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (close(sockets[1]) != 0) {
|
||||
sway_log_errno(SWAY_ERROR, "close failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (waitpid(pid, NULL, 0) < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "waitpid failed");
|
||||
return;
|
||||
}
|
||||
|
||||
sway_log(SWAY_DEBUG, "Spawned swaybar %s", bar->id);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -300,7 +300,7 @@ struct input_config *store_input_config(struct input_config *ic,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool type = strncmp(ic->identifier, "type:", strlen("type:")) == 0;
|
||||
bool type = has_prefix(ic->identifier, "type:");
|
||||
if (type && error && !validate_type_on_existing(ic, error)) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,14 +6,20 @@
|
|||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <wlr/config.h>
|
||||
#include <wlr/render/allocator.h>
|
||||
#include <wlr/types/wlr_cursor.h>
|
||||
#include <wlr/types/wlr_output_layout.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
#include <wlr/types/wlr_output_swapchain_manager.h>
|
||||
#include <xf86drm.h>
|
||||
#include "sway/config.h"
|
||||
#include "sway/desktop/transaction.h"
|
||||
#include "sway/input/cursor.h"
|
||||
#include "sway/layers.h"
|
||||
#include "sway/lock.h"
|
||||
#include "sway/output.h"
|
||||
#include "sway/server.h"
|
||||
#include "sway/tree/arrange.h"
|
||||
#include "sway/tree/root.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
|
|
@ -22,13 +28,6 @@
|
|||
#include <wlr/backend/drm.h>
|
||||
#endif
|
||||
|
||||
int output_name_cmp(const void *item, const void *data) {
|
||||
const struct output_config *output = item;
|
||||
const char *name = data;
|
||||
|
||||
return strcmp(output->name, name);
|
||||
}
|
||||
|
||||
void output_get_identifier(char *identifier, size_t len,
|
||||
struct sway_output *output) {
|
||||
struct wlr_output *wlr_output = output->wlr_output;
|
||||
|
|
@ -68,7 +67,7 @@ struct output_config *new_output_config(const char *name) {
|
|||
oc->refresh_rate = -1;
|
||||
oc->custom_mode = -1;
|
||||
oc->drm_mode.type = -1;
|
||||
oc->x = oc->y = -1;
|
||||
oc->x = oc->y = INT_MAX;
|
||||
oc->scale = -1;
|
||||
oc->scale_filter = SCALE_FILTER_DEFAULT;
|
||||
oc->transform = -1;
|
||||
|
|
@ -79,6 +78,8 @@ struct output_config *new_output_config(const char *name) {
|
|||
oc->set_color_transform = false;
|
||||
oc->color_transform = NULL;
|
||||
oc->power = -1;
|
||||
oc->allow_tearing = -1;
|
||||
oc->hdr = -1;
|
||||
return oc;
|
||||
}
|
||||
|
||||
|
|
@ -93,11 +94,11 @@ static void supersede_output_config(struct output_config *dst, struct output_con
|
|||
if (src->height != -1) {
|
||||
dst->height = -1;
|
||||
}
|
||||
if (src->x != -1) {
|
||||
dst->x = -1;
|
||||
if (src->x != INT_MAX) {
|
||||
dst->x = INT_MAX;
|
||||
}
|
||||
if (src->y != -1) {
|
||||
dst->y = -1;
|
||||
if (src->y != INT_MAX) {
|
||||
dst->y = INT_MAX;
|
||||
}
|
||||
if (src->scale != -1) {
|
||||
dst->scale = -1;
|
||||
|
|
@ -129,6 +130,13 @@ static void supersede_output_config(struct output_config *dst, struct output_con
|
|||
if (src->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) {
|
||||
dst->render_bit_depth = RENDER_BIT_DEPTH_DEFAULT;
|
||||
}
|
||||
if (src->set_color_transform) {
|
||||
if (dst->color_transform) {
|
||||
wlr_color_transform_unref(dst->color_transform);
|
||||
dst->color_transform = NULL;
|
||||
}
|
||||
dst->set_color_transform = false;
|
||||
}
|
||||
if (src->background) {
|
||||
free(dst->background);
|
||||
dst->background = NULL;
|
||||
|
|
@ -144,6 +152,12 @@ static void supersede_output_config(struct output_config *dst, struct output_con
|
|||
if (src->power != -1) {
|
||||
dst->power = -1;
|
||||
}
|
||||
if (src->allow_tearing != -1) {
|
||||
dst->allow_tearing = -1;
|
||||
}
|
||||
if (src->hdr != -1) {
|
||||
dst->hdr = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// merge_output_config sets all fields in dst that were set in src
|
||||
|
|
@ -157,10 +171,10 @@ static void merge_output_config(struct output_config *dst, struct output_config
|
|||
if (src->height != -1) {
|
||||
dst->height = src->height;
|
||||
}
|
||||
if (src->x != -1) {
|
||||
if (src->x != INT_MAX) {
|
||||
dst->x = src->x;
|
||||
}
|
||||
if (src->y != -1) {
|
||||
if (src->y != INT_MAX) {
|
||||
dst->y = src->y;
|
||||
}
|
||||
if (src->scale != -1) {
|
||||
|
|
@ -216,6 +230,12 @@ static void merge_output_config(struct output_config *dst, struct output_config
|
|||
if (src->power != -1) {
|
||||
dst->power = src->power;
|
||||
}
|
||||
if (src->allow_tearing != -1) {
|
||||
dst->allow_tearing = src->allow_tearing;
|
||||
}
|
||||
if (src->hdr != -1) {
|
||||
dst->hdr = src->hdr;
|
||||
}
|
||||
}
|
||||
|
||||
void store_output_config(struct output_config *oc) {
|
||||
|
|
@ -258,11 +278,11 @@ void store_output_config(struct output_config *oc) {
|
|||
|
||||
sway_log(SWAY_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz "
|
||||
"position %d,%d scale %f subpixel %s transform %d) (bg %s %s) (power %d) "
|
||||
"(max render time: %d)",
|
||||
"(max render time: %d) (allow tearing: %d) (hdr: %d)",
|
||||
oc->name, oc->enabled, oc->width, oc->height, oc->refresh_rate,
|
||||
oc->x, oc->y, oc->scale, sway_wl_output_subpixel_to_string(oc->subpixel),
|
||||
oc->transform, oc->background, oc->background_option, oc->power,
|
||||
oc->max_render_time);
|
||||
oc->max_render_time, oc->allow_tearing, oc->hdr);
|
||||
|
||||
// If the configuration was not merged into an existing configuration, add
|
||||
// it to the list. Otherwise we're done with it and can free it.
|
||||
|
|
@ -283,7 +303,6 @@ static void set_mode(struct wlr_output *output, struct wlr_output_state *pending
|
|||
mhz = mhz <= 0 ? INT_MAX : mhz;
|
||||
|
||||
if (wl_list_empty(&output->modes) || custom) {
|
||||
sway_log(SWAY_DEBUG, "Assigning custom mode to %s", output->name);
|
||||
wlr_output_state_set_custom_mode(pending, width, height,
|
||||
refresh_rate > 0 ? mhz : 0);
|
||||
return;
|
||||
|
|
@ -303,10 +322,7 @@ static void set_mode(struct wlr_output *output, struct wlr_output_state *pending
|
|||
}
|
||||
}
|
||||
}
|
||||
if (best) {
|
||||
sway_log(SWAY_INFO, "Assigning configured mode (%dx%d@%.3fHz) to %s",
|
||||
best->width, best->height, best->refresh / 1000.f, output->name);
|
||||
} else {
|
||||
if (!best) {
|
||||
best = wlr_output_preferred_mode(output);
|
||||
sway_log(SWAY_INFO, "Configured mode (%dx%d@%.3fHz) not available, "
|
||||
"applying preferred mode (%dx%d@%.3fHz)",
|
||||
|
|
@ -323,7 +339,6 @@ static void set_modeline(struct wlr_output *output,
|
|||
sway_log(SWAY_ERROR, "Modeline can only be set to DRM output");
|
||||
return;
|
||||
}
|
||||
sway_log(SWAY_DEBUG, "Assigning custom modeline to %s", output->name);
|
||||
struct wlr_output_mode *mode = wlr_drm_connector_add_mode(output, drm_mode);
|
||||
if (mode) {
|
||||
wlr_output_state_set_mode(pending, mode);
|
||||
|
|
@ -333,6 +348,45 @@ static void set_modeline(struct wlr_output *output,
|
|||
#endif
|
||||
}
|
||||
|
||||
bool output_supports_hdr(struct wlr_output *output, const char **unsupported_reason_ptr) {
|
||||
const char *unsupported_reason = NULL;
|
||||
if (!(output->supported_primaries & WLR_COLOR_NAMED_PRIMARIES_BT2020)) {
|
||||
unsupported_reason = "BT2020 primaries not supported by output";
|
||||
} else if (!(output->supported_transfer_functions & WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ)) {
|
||||
unsupported_reason = "PQ transfer function not supported by output";
|
||||
} else if (!server.renderer->features.output_color_transform) {
|
||||
unsupported_reason = "renderer doesn't support output color transforms";
|
||||
}
|
||||
if (unsupported_reason_ptr != NULL) {
|
||||
*unsupported_reason_ptr = unsupported_reason;
|
||||
}
|
||||
return unsupported_reason == NULL;
|
||||
}
|
||||
|
||||
static void set_hdr(struct wlr_output *output, struct wlr_output_state *pending, bool enabled) {
|
||||
const char *unsupported_reason = NULL;
|
||||
if (enabled && !output_supports_hdr(output, &unsupported_reason)) {
|
||||
sway_log(SWAY_ERROR, "Cannot enable HDR on output %s: %s",
|
||||
output->name, unsupported_reason);
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
if (!enabled) {
|
||||
if (output->supported_primaries != 0 || output->supported_transfer_functions != 0) {
|
||||
sway_log(SWAY_DEBUG, "Disabling HDR on output %s", output->name);
|
||||
wlr_output_state_set_image_description(pending, NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
sway_log(SWAY_DEBUG, "Enabling HDR on output %s", output->name);
|
||||
const struct wlr_output_image_description image_desc = {
|
||||
.primaries = WLR_COLOR_NAMED_PRIMARIES_BT2020,
|
||||
.transfer_function = WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ,
|
||||
};
|
||||
wlr_output_state_set_image_description(pending, &image_desc);
|
||||
}
|
||||
|
||||
/* Some manufacturers hardcode the aspect-ratio of the output in the physical
|
||||
* size field. */
|
||||
static bool phys_size_is_aspect_ratio(struct wlr_output *output) {
|
||||
|
|
@ -389,7 +443,6 @@ static int compute_default_scale(struct wlr_output *output,
|
|||
|
||||
double dpi_x = (double) width / (output->phys_width / MM_PER_INCH);
|
||||
double dpi_y = (double) height / (output->phys_height / MM_PER_INCH);
|
||||
sway_log(SWAY_DEBUG, "Output DPI: %fx%f", dpi_x, dpi_y);
|
||||
if (dpi_x <= HIDPI_DPI_LIMIT || dpi_y <= HIDPI_DPI_LIMIT) {
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -397,9 +450,25 @@ static int compute_default_scale(struct wlr_output *output,
|
|||
return 2;
|
||||
}
|
||||
|
||||
static bool render_format_is_10bit(uint32_t render_format) {
|
||||
return render_format == DRM_FORMAT_XRGB2101010 ||
|
||||
render_format == DRM_FORMAT_XBGR2101010;
|
||||
static enum render_bit_depth bit_depth_from_format(uint32_t render_format) {
|
||||
if (render_format == DRM_FORMAT_XRGB2101010 || render_format == DRM_FORMAT_XBGR2101010) {
|
||||
return RENDER_BIT_DEPTH_10;
|
||||
} else if (render_format == DRM_FORMAT_XRGB8888 || render_format == DRM_FORMAT_ARGB8888) {
|
||||
return RENDER_BIT_DEPTH_8;
|
||||
} else if (render_format == DRM_FORMAT_RGB565) {
|
||||
return RENDER_BIT_DEPTH_6;
|
||||
}
|
||||
return RENDER_BIT_DEPTH_DEFAULT;
|
||||
}
|
||||
|
||||
static enum render_bit_depth get_config_render_bit_depth(const struct output_config *oc) {
|
||||
if (oc && oc->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) {
|
||||
return oc->render_bit_depth;
|
||||
}
|
||||
if (oc && oc->hdr == 1) {
|
||||
return RENDER_BIT_DEPTH_10;
|
||||
}
|
||||
return RENDER_BIT_DEPTH_8;
|
||||
}
|
||||
|
||||
static bool render_format_is_bgr(uint32_t fmt) {
|
||||
|
|
@ -419,94 +488,82 @@ static void queue_output_config(struct output_config *oc,
|
|||
struct wlr_output *wlr_output = output->wlr_output;
|
||||
|
||||
if (output_config_is_disabling(oc)) {
|
||||
sway_log(SWAY_DEBUG, "Turning off output %s", wlr_output->name);
|
||||
wlr_output_state_set_enabled(pending, false);
|
||||
return;
|
||||
}
|
||||
|
||||
sway_log(SWAY_DEBUG, "Turning on output %s", wlr_output->name);
|
||||
wlr_output_state_set_enabled(pending, true);
|
||||
|
||||
if (oc && oc->drm_mode.type != 0 && oc->drm_mode.type != (uint32_t) -1) {
|
||||
sway_log(SWAY_DEBUG, "Set %s modeline",
|
||||
wlr_output->name);
|
||||
set_modeline(wlr_output, pending, &oc->drm_mode);
|
||||
} else if (oc && oc->width > 0 && oc->height > 0) {
|
||||
sway_log(SWAY_DEBUG, "Set %s mode to %dx%d (%f Hz)",
|
||||
wlr_output->name, oc->width, oc->height, oc->refresh_rate);
|
||||
set_mode(wlr_output, pending, oc->width, oc->height,
|
||||
oc->refresh_rate, oc->custom_mode == 1);
|
||||
} else if (!wl_list_empty(&wlr_output->modes)) {
|
||||
sway_log(SWAY_DEBUG, "Set preferred mode");
|
||||
struct wlr_output_mode *preferred_mode =
|
||||
wlr_output_preferred_mode(wlr_output);
|
||||
wlr_output_state_set_mode(pending, preferred_mode);
|
||||
}
|
||||
|
||||
if (oc && (oc->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN || config->reloading)) {
|
||||
sway_log(SWAY_DEBUG, "Set %s subpixel to %s", oc->name,
|
||||
sway_wl_output_subpixel_to_string(oc->subpixel));
|
||||
if (oc && oc->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN) {
|
||||
wlr_output_state_set_subpixel(pending, oc->subpixel);
|
||||
} else {
|
||||
wlr_output_state_set_subpixel(pending, output->detected_subpixel);
|
||||
}
|
||||
|
||||
enum wl_output_transform tr = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
if (oc && oc->transform >= 0) {
|
||||
tr = oc->transform;
|
||||
wlr_output_state_set_transform(pending, oc->transform);
|
||||
#if WLR_HAS_DRM_BACKEND
|
||||
} else if (wlr_output_is_drm(wlr_output)) {
|
||||
tr = wlr_drm_connector_get_panel_orientation(wlr_output);
|
||||
sway_log(SWAY_DEBUG, "Auto-detected output transform: %d", tr);
|
||||
wlr_output_state_set_transform(pending,
|
||||
wlr_drm_connector_get_panel_orientation(wlr_output));
|
||||
#endif
|
||||
}
|
||||
if (wlr_output->transform != tr) {
|
||||
sway_log(SWAY_DEBUG, "Set %s transform to %d", wlr_output->name, tr);
|
||||
wlr_output_state_set_transform(pending, tr);
|
||||
} else {
|
||||
wlr_output_state_set_transform(pending, WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
}
|
||||
|
||||
// Apply the scale last before the commit, because the scale auto-detection
|
||||
// reads the pending output size
|
||||
float scale;
|
||||
// Apply the scale after sorting out the mode, because the scale
|
||||
// auto-detection reads the pending output size
|
||||
if (oc && oc->scale > 0) {
|
||||
scale = oc->scale;
|
||||
|
||||
// The factional-scale-v1 protocol uses increments of 120ths to send
|
||||
// the scale factor to the client. Adjust the scale so that we use the
|
||||
// same value as the clients'.
|
||||
float adjusted_scale = round(scale * 120) / 120;
|
||||
if (scale != adjusted_scale) {
|
||||
sway_log(SWAY_INFO, "Adjusting output scale from %f to %f",
|
||||
scale, adjusted_scale);
|
||||
scale = adjusted_scale;
|
||||
}
|
||||
wlr_output_state_set_scale(pending, round(oc->scale * 120) / 120);
|
||||
} else {
|
||||
scale = compute_default_scale(wlr_output, pending);
|
||||
sway_log(SWAY_DEBUG, "Auto-detected output scale: %f", scale);
|
||||
}
|
||||
if (scale != wlr_output->scale) {
|
||||
sway_log(SWAY_DEBUG, "Set %s scale to %f", wlr_output->name, scale);
|
||||
wlr_output_state_set_scale(pending, scale);
|
||||
wlr_output_state_set_scale(pending,
|
||||
compute_default_scale(wlr_output, pending));
|
||||
}
|
||||
|
||||
if (wlr_output->adaptive_sync_supported) {
|
||||
if (oc && oc->adaptive_sync != -1) {
|
||||
sway_log(SWAY_DEBUG, "Set %s adaptive sync to %d", wlr_output->name,
|
||||
oc->adaptive_sync);
|
||||
wlr_output_state_set_adaptive_sync_enabled(pending, oc->adaptive_sync == 1);
|
||||
} else {
|
||||
wlr_output_state_set_adaptive_sync_enabled(pending, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (oc && oc->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) {
|
||||
if (oc->render_bit_depth == RENDER_BIT_DEPTH_10 &&
|
||||
render_format_is_10bit(output->wlr_output->render_format)) {
|
||||
enum render_bit_depth render_bit_depth = get_config_render_bit_depth(oc);
|
||||
if (render_bit_depth == RENDER_BIT_DEPTH_10 &&
|
||||
bit_depth_from_format(output->wlr_output->render_format) == render_bit_depth) {
|
||||
// 10-bit was set successfully before, try to save some tests by reusing the format
|
||||
wlr_output_state_set_render_format(pending, output->wlr_output->render_format);
|
||||
} else if (oc->render_bit_depth == RENDER_BIT_DEPTH_10) {
|
||||
} else if (render_bit_depth == RENDER_BIT_DEPTH_10) {
|
||||
wlr_output_state_set_render_format(pending, DRM_FORMAT_XRGB2101010);
|
||||
} else if (render_bit_depth == RENDER_BIT_DEPTH_6) {
|
||||
wlr_output_state_set_render_format(pending, DRM_FORMAT_RGB565);
|
||||
} else {
|
||||
wlr_output_state_set_render_format(pending, DRM_FORMAT_XRGB8888);
|
||||
}
|
||||
|
||||
bool hdr = oc && oc->hdr == 1;
|
||||
if (hdr && oc->color_transform != NULL) {
|
||||
sway_log(SWAY_ERROR, "Cannot HDR on output %s: output has an ICC profile set", wlr_output->name);
|
||||
hdr = false;
|
||||
}
|
||||
set_hdr(wlr_output, pending, hdr);
|
||||
}
|
||||
|
||||
static bool finalize_output_config(struct output_config *oc, struct sway_output *output) {
|
||||
static bool finalize_output_config(struct output_config *oc, struct sway_output *output,
|
||||
const struct wlr_output_state *applied) {
|
||||
if (output == root->fallback_output) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -521,9 +578,9 @@ static bool finalize_output_config(struct output_config *oc, struct sway_output
|
|||
return true;
|
||||
}
|
||||
|
||||
if (oc) {
|
||||
enum scale_filter_mode scale_filter_old = output->scale_filter;
|
||||
switch (oc->scale_filter) {
|
||||
enum scale_filter_mode scale_filter_new = oc ? oc->scale_filter : SCALE_FILTER_DEFAULT;
|
||||
switch (scale_filter_new) {
|
||||
case SCALE_FILTER_DEFAULT:
|
||||
case SCALE_FILTER_SMART:
|
||||
output->scale_filter = ceilf(wlr_output->scale) == wlr_output->scale ?
|
||||
|
|
@ -531,7 +588,7 @@ static bool finalize_output_config(struct output_config *oc, struct sway_output
|
|||
break;
|
||||
case SCALE_FILTER_LINEAR:
|
||||
case SCALE_FILTER_NEAREST:
|
||||
output->scale_filter = oc->scale_filter;
|
||||
output->scale_filter = scale_filter_new;
|
||||
break;
|
||||
}
|
||||
if (scale_filter_old != output->scale_filter) {
|
||||
|
|
@ -539,109 +596,86 @@ static bool finalize_output_config(struct output_config *oc, struct sway_output
|
|||
sway_output_scale_filter_to_string(output->scale_filter));
|
||||
wlr_damage_ring_add_whole(&output->scene_output->damage_ring);
|
||||
}
|
||||
}
|
||||
|
||||
// Find position for it
|
||||
if (oc && (oc->x != -1 || oc->y != -1)) {
|
||||
if (oc && oc->x != INT_MAX && oc->y != INT_MAX) {
|
||||
sway_log(SWAY_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y);
|
||||
wlr_output_layout_add(root->output_layout, wlr_output, oc->x, oc->y);
|
||||
} else {
|
||||
wlr_output_layout_add_auto(root->output_layout, wlr_output);
|
||||
}
|
||||
|
||||
// Update output->{lx, ly, width, height}
|
||||
struct wlr_box output_box;
|
||||
wlr_output_layout_get_box(root->output_layout, wlr_output, &output_box);
|
||||
output->lx = output_box.x;
|
||||
output->ly = output_box.y;
|
||||
output->width = output_box.width;
|
||||
output->height = output_box.height;
|
||||
|
||||
if (!output->enabled) {
|
||||
output_enable(output);
|
||||
}
|
||||
|
||||
if (oc && oc->max_render_time >= 0) {
|
||||
sway_log(SWAY_DEBUG, "Set %s max render time to %d",
|
||||
oc->name, oc->max_render_time);
|
||||
output->max_render_time = oc->max_render_time;
|
||||
}
|
||||
|
||||
if (oc && oc->set_color_transform) {
|
||||
if (oc->color_transform) {
|
||||
wlr_color_transform_ref(oc->color_transform);
|
||||
}
|
||||
wlr_color_transform_unref(output->color_transform);
|
||||
output->color_transform = oc->color_transform;
|
||||
} else {
|
||||
wlr_color_transform_unref(output->color_transform);
|
||||
output->color_transform = NULL;
|
||||
}
|
||||
|
||||
output->max_render_time = oc && oc->max_render_time > 0 ? oc->max_render_time : 0;
|
||||
output->allow_tearing = oc && oc->allow_tearing > 0;
|
||||
output->hdr = applied->image_description != NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void default_output_config(struct output_config *oc,
|
||||
struct wlr_output *wlr_output) {
|
||||
oc->enabled = 1;
|
||||
oc->power = 1;
|
||||
struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output);
|
||||
if (mode != NULL) {
|
||||
oc->width = mode->width;
|
||||
oc->height = mode->height;
|
||||
oc->refresh_rate = mode->refresh / 1000.f;
|
||||
}
|
||||
oc->x = oc->y = -1;
|
||||
oc->scale = 0; // auto
|
||||
oc->scale_filter = SCALE_FILTER_DEFAULT;
|
||||
struct sway_output *output = wlr_output->data;
|
||||
oc->subpixel = output->detected_subpixel;
|
||||
oc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
oc->max_render_time = 0;
|
||||
static void output_update_position(struct sway_output *output) {
|
||||
struct wlr_box output_box;
|
||||
wlr_output_layout_get_box(root->output_layout, output->wlr_output, &output_box);
|
||||
output->lx = output_box.x;
|
||||
output->ly = output_box.y;
|
||||
output->width = output_box.width;
|
||||
output->height = output_box.height;
|
||||
}
|
||||
|
||||
// find_output_config returns a merged output_config containing all stored
|
||||
// configuration that applies to the specified output.
|
||||
struct output_config *find_output_config(struct sway_output *sway_output) {
|
||||
// find_output_config_from_list returns a merged output_config containing all
|
||||
// stored configuration that applies to the specified output.
|
||||
static struct output_config *find_output_config_from_list(
|
||||
struct output_config **configs, size_t configs_len,
|
||||
struct sway_output *sway_output) {
|
||||
const char *name = sway_output->wlr_output->name;
|
||||
struct output_config *oc = NULL;
|
||||
|
||||
struct output_config *result = new_output_config(name);
|
||||
if (config->reloading) {
|
||||
default_output_config(result, sway_output->wlr_output);
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char id[128];
|
||||
output_get_identifier(id, sizeof(id), sway_output);
|
||||
|
||||
int i;
|
||||
bool match = false;
|
||||
if ((i = list_seq_find(config->output_configs, output_name_cmp, "*")) >= 0) {
|
||||
match = true;
|
||||
oc = config->output_configs->items[i];
|
||||
// We take a new config and merge on top, in order, the wildcard config,
|
||||
// output config by name, and output config by identifier to form the final
|
||||
// config. If there are multiple matches, they are merged in order.
|
||||
struct output_config *oc = NULL;
|
||||
const char *names[] = {"*", name, id, NULL};
|
||||
for (const char **name = &names[0]; *name; name++) {
|
||||
for (size_t idx = 0; idx < configs_len; idx++) {
|
||||
oc = configs[idx];
|
||||
if (strcmp(oc->name, *name) == 0) {
|
||||
merge_output_config(result, oc);
|
||||
}
|
||||
if ((i = list_seq_find(config->output_configs, output_name_cmp, name)) >= 0) {
|
||||
match = true;
|
||||
oc = config->output_configs->items[i];
|
||||
merge_output_config(result, oc);
|
||||
}
|
||||
if ((i = list_seq_find(config->output_configs, output_name_cmp, id)) >= 0) {
|
||||
match = true;
|
||||
oc = config->output_configs->items[i];
|
||||
merge_output_config(result, oc);
|
||||
}
|
||||
|
||||
if (!match && !config->reloading) {
|
||||
// No name, identifier, or wildcard config. Since we are not
|
||||
// reloading with defaults, the output config will be empty, so
|
||||
// just return NULL
|
||||
free_output_config(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool config_has_auto_mode(struct output_config *oc) {
|
||||
struct output_config *find_output_config(struct sway_output *sway_output) {
|
||||
return find_output_config_from_list(
|
||||
(struct output_config **)config->output_configs->items,
|
||||
config->output_configs->length, sway_output);
|
||||
}
|
||||
|
||||
static bool config_has_manual_mode(struct output_config *oc) {
|
||||
if (!oc) {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
if (oc->drm_mode.type != 0 && oc->drm_mode.type != (uint32_t)-1) {
|
||||
return true;
|
||||
|
|
@ -651,6 +685,14 @@ static bool config_has_auto_mode(struct output_config *oc) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* An output config pre-matched to an output
|
||||
*/
|
||||
struct matched_output_config {
|
||||
struct sway_output *output;
|
||||
struct output_config *config;
|
||||
};
|
||||
|
||||
struct search_context {
|
||||
struct wlr_output_swapchain_manager *swapchain_mgr;
|
||||
struct wlr_backend_output_state *states;
|
||||
|
|
@ -665,7 +707,9 @@ static void dump_output_state(struct wlr_output *wlr_output, struct wlr_output_s
|
|||
sway_log(SWAY_DEBUG, " enabled: %s", state->enabled ? "yes" : "no");
|
||||
}
|
||||
if (state->committed & WLR_OUTPUT_STATE_RENDER_FORMAT) {
|
||||
sway_log(SWAY_DEBUG, " render_format: %d", state->render_format);
|
||||
char *format_name = drmGetFormatName(state->render_format);
|
||||
sway_log(SWAY_DEBUG, " render_format: %s", format_name);
|
||||
free(format_name);
|
||||
}
|
||||
if (state->committed & WLR_OUTPUT_STATE_MODE) {
|
||||
if (state->mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM) {
|
||||
|
|
@ -681,6 +725,13 @@ static void dump_output_state(struct wlr_output *wlr_output, struct wlr_output_s
|
|||
sway_log(SWAY_DEBUG, " adaptive_sync: %s",
|
||||
state->adaptive_sync_enabled ? "enabled": "disabled");
|
||||
}
|
||||
if (state->committed & WLR_OUTPUT_STATE_SCALE) {
|
||||
sway_log(SWAY_DEBUG, " scale: %f", state->scale);
|
||||
}
|
||||
if (state->committed & WLR_OUTPUT_STATE_SUBPIXEL) {
|
||||
sway_log(SWAY_DEBUG, " subpixel: %s",
|
||||
sway_wl_output_subpixel_to_string(state->subpixel));
|
||||
}
|
||||
}
|
||||
|
||||
static bool search_valid_config(struct search_context *ctx, size_t output_idx);
|
||||
|
|
@ -742,7 +793,8 @@ static bool search_mode(struct search_context *ctx, size_t output_idx) {
|
|||
struct wlr_output_state *state = &backend_state->base;
|
||||
struct wlr_output *wlr_output = backend_state->output;
|
||||
|
||||
if (!config_has_auto_mode(cfg->config)) {
|
||||
// We only search for mode if one is not explicitly specified in the config
|
||||
if (config_has_manual_mode(cfg->config)) {
|
||||
return search_adaptive_sync(ctx, output_idx);
|
||||
}
|
||||
|
||||
|
|
@ -783,6 +835,8 @@ static bool search_render_format(struct search_context *ctx, size_t output_idx)
|
|||
DRM_FORMAT_XRGB2101010,
|
||||
DRM_FORMAT_XBGR2101010,
|
||||
DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_ARGB8888,
|
||||
DRM_FORMAT_RGB565,
|
||||
DRM_FORMAT_INVALID,
|
||||
};
|
||||
if (render_format_is_bgr(wlr_output->render_format)) {
|
||||
|
|
@ -792,13 +846,15 @@ static bool search_render_format(struct search_context *ctx, size_t output_idx)
|
|||
}
|
||||
|
||||
const struct wlr_drm_format_set *primary_formats =
|
||||
wlr_output_get_primary_formats(wlr_output, WLR_BUFFER_CAP_DMABUF);
|
||||
bool need_10bit = cfg->config && cfg->config->render_bit_depth == RENDER_BIT_DEPTH_10;
|
||||
wlr_output_get_primary_formats(wlr_output, server.allocator->buffer_caps);
|
||||
enum render_bit_depth needed_bits = get_config_render_bit_depth(cfg->config);
|
||||
for (size_t idx = 0; fmts[idx] != DRM_FORMAT_INVALID; idx++) {
|
||||
if (!need_10bit && render_format_is_10bit(fmts[idx])) {
|
||||
enum render_bit_depth format_bits = bit_depth_from_format(fmts[idx]);
|
||||
if (needed_bits < format_bits) {
|
||||
continue;
|
||||
}
|
||||
if (!wlr_drm_format_set_get(primary_formats, fmts[idx])) {
|
||||
// If primary_formats is NULL, all formats are supported
|
||||
if (primary_formats && !wlr_drm_format_set_get(primary_formats, fmts[idx])) {
|
||||
// This is not a supported format for this output
|
||||
continue;
|
||||
}
|
||||
|
|
@ -868,12 +924,12 @@ static int compare_matched_output_config_priority(const void *a, const void *b)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void sort_output_configs_by_priority(struct matched_output_config *configs,
|
||||
size_t configs_len) {
|
||||
static void sort_output_configs_by_priority(
|
||||
struct matched_output_config *configs, size_t configs_len) {
|
||||
qsort(configs, configs_len, sizeof(*configs), compare_matched_output_config_priority);
|
||||
}
|
||||
|
||||
bool apply_output_configs(struct matched_output_config *configs,
|
||||
static bool apply_resolved_output_configs(struct matched_output_config *configs,
|
||||
size_t configs_len, bool test_only, bool degrade_to_off) {
|
||||
struct wlr_backend_output_state *states = calloc(configs_len, sizeof(*states));
|
||||
if (!states) {
|
||||
|
|
@ -888,9 +944,8 @@ bool apply_output_configs(struct matched_output_config *configs,
|
|||
backend_state->output = cfg->output->wlr_output;
|
||||
wlr_output_state_init(&backend_state->base);
|
||||
|
||||
sway_log(SWAY_DEBUG, "Preparing config for %s",
|
||||
cfg->output->wlr_output->name);
|
||||
queue_output_config(cfg->config, cfg->output, &backend_state->base);
|
||||
dump_output_state(cfg->output->wlr_output, &backend_state->base);
|
||||
}
|
||||
|
||||
struct wlr_output_swapchain_manager swapchain_mgr;
|
||||
|
|
@ -947,11 +1002,25 @@ bool apply_output_configs(struct matched_output_config *configs,
|
|||
|
||||
for (size_t idx = 0; idx < configs_len; idx++) {
|
||||
struct matched_output_config *cfg = &configs[idx];
|
||||
struct wlr_backend_output_state *backend_state = &states[idx];
|
||||
sway_log(SWAY_DEBUG, "Finalizing config for %s",
|
||||
cfg->output->wlr_output->name);
|
||||
finalize_output_config(cfg->config, cfg->output);
|
||||
finalize_output_config(cfg->config, cfg->output, &backend_state->base);
|
||||
}
|
||||
|
||||
// Output layout being applied in finalize_output_config can shift outputs
|
||||
// around, so we do a second pass to update positions and arrange.
|
||||
for (size_t idx = 0; idx < configs_len; idx++) {
|
||||
struct matched_output_config *cfg = &configs[idx];
|
||||
output_update_position(cfg->output);
|
||||
arrange_layers(cfg->output);
|
||||
}
|
||||
|
||||
arrange_root();
|
||||
arrange_locks();
|
||||
update_output_manager_config(&server);
|
||||
transaction_commit_dirty();
|
||||
|
||||
out:
|
||||
wlr_output_swapchain_manager_finish(&swapchain_mgr);
|
||||
for (size_t idx = 0; idx < configs_len; idx++) {
|
||||
|
|
@ -976,11 +1045,12 @@ out:
|
|||
return ok;
|
||||
}
|
||||
|
||||
void apply_all_output_configs(void) {
|
||||
bool apply_output_configs(struct output_config **ocs, size_t ocs_len,
|
||||
bool test_only, bool degrade_to_off) {
|
||||
size_t configs_len = wl_list_length(&root->all_outputs);
|
||||
struct matched_output_config *configs = calloc(configs_len, sizeof(*configs));
|
||||
if (!configs) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
int config_idx = 0;
|
||||
|
|
@ -993,16 +1063,22 @@ void apply_all_output_configs(void) {
|
|||
|
||||
struct matched_output_config *config = &configs[config_idx++];
|
||||
config->output = sway_output;
|
||||
config->config = find_output_config(sway_output);
|
||||
config->config = find_output_config_from_list(ocs, ocs_len, sway_output);
|
||||
}
|
||||
|
||||
sort_output_configs_by_priority(configs, configs_len);
|
||||
apply_output_configs(configs, configs_len, false, true);
|
||||
bool ok = apply_resolved_output_configs(configs, configs_len, test_only, degrade_to_off);
|
||||
for (size_t idx = 0; idx < configs_len; idx++) {
|
||||
struct matched_output_config *cfg = &configs[idx];
|
||||
free_output_config(cfg->config);
|
||||
}
|
||||
free(configs);
|
||||
return ok;
|
||||
}
|
||||
|
||||
void apply_stored_output_configs(void) {
|
||||
apply_output_configs((struct output_config **)config->output_configs->items,
|
||||
config->output_configs->length, false, true);
|
||||
}
|
||||
|
||||
void free_output_config(struct output_config *oc) {
|
||||
|
|
@ -1012,6 +1088,7 @@ void free_output_config(struct output_config *oc) {
|
|||
free(oc->name);
|
||||
free(oc->background);
|
||||
free(oc->background_option);
|
||||
free(oc->background_fallback);
|
||||
wlr_color_transform_unref(oc->color_transform);
|
||||
free(oc);
|
||||
}
|
||||
|
|
@ -1052,13 +1129,6 @@ static bool _spawn_swaybg(char **command) {
|
|||
if (pid < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||
return false;
|
||||
} else if (pid == 0) {
|
||||
restore_nofile_limit();
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||
_exit(EXIT_FAILURE);
|
||||
} else if (pid == 0) {
|
||||
if (!sway_set_cloexec(sockets[1], false)) {
|
||||
_exit(EXIT_FAILURE);
|
||||
|
|
@ -1075,20 +1145,12 @@ static bool _spawn_swaybg(char **command) {
|
|||
command[0]);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (close(sockets[1]) != 0) {
|
||||
sway_log_errno(SWAY_ERROR, "close failed");
|
||||
return false;
|
||||
}
|
||||
int fork_status = 0;
|
||||
if (waitpid(pid, &fork_status, 0) < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "waitpid failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return WIFEXITED(fork_status) && WEXITSTATUS(fork_status) == EXIT_SUCCESS;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spawn_swaybg(void) {
|
||||
|
|
|
|||
117
sway/criteria.c
117
sway/criteria.c
|
|
@ -34,7 +34,11 @@ bool criteria_is_empty(struct criteria *criteria) {
|
|||
&& !criteria->tiling
|
||||
&& !criteria->urgent
|
||||
&& !criteria->workspace
|
||||
&& !criteria->pid;
|
||||
&& !criteria->pid
|
||||
&& !criteria->sandbox_engine
|
||||
&& !criteria->sandbox_app_id
|
||||
&& !criteria->sandbox_instance_id
|
||||
&& !criteria->tag;
|
||||
}
|
||||
|
||||
// The error pointer is used for parsing functions, and saves having to pass it
|
||||
|
|
@ -98,6 +102,10 @@ void criteria_destroy(struct criteria *criteria) {
|
|||
#endif
|
||||
pattern_destroy(criteria->con_mark);
|
||||
pattern_destroy(criteria->workspace);
|
||||
pattern_destroy(criteria->sandbox_engine);
|
||||
pattern_destroy(criteria->sandbox_app_id);
|
||||
pattern_destroy(criteria->sandbox_instance_id);
|
||||
pattern_destroy(criteria->tag);
|
||||
free(criteria->target);
|
||||
free(criteria->cmdlist);
|
||||
free(criteria->raw);
|
||||
|
|
@ -248,6 +256,86 @@ static bool criteria_matches_view(struct criteria *criteria,
|
|||
}
|
||||
}
|
||||
|
||||
if (criteria->sandbox_engine) {
|
||||
const char *sandbox_engine = view_get_sandbox_engine(view);
|
||||
if (!sandbox_engine) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (criteria->sandbox_engine->match_type) {
|
||||
case PATTERN_FOCUSED:
|
||||
if (focused && lenient_strcmp(sandbox_engine, view_get_sandbox_engine(focused))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case PATTERN_PCRE2:
|
||||
if (regex_cmp(sandbox_engine, criteria->sandbox_engine->regex) < 0) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (criteria->sandbox_app_id) {
|
||||
const char *sandbox_app_id = view_get_sandbox_app_id(view);
|
||||
if (!sandbox_app_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (criteria->sandbox_app_id->match_type) {
|
||||
case PATTERN_FOCUSED:
|
||||
if (focused && lenient_strcmp(sandbox_app_id, view_get_sandbox_app_id(focused))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case PATTERN_PCRE2:
|
||||
if (regex_cmp(sandbox_app_id, criteria->sandbox_app_id->regex) < 0) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (criteria->sandbox_instance_id) {
|
||||
const char *sandbox_instance_id = view_get_sandbox_instance_id(view);
|
||||
if (!sandbox_instance_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (criteria->sandbox_instance_id->match_type) {
|
||||
case PATTERN_FOCUSED:
|
||||
if (focused && lenient_strcmp(sandbox_instance_id, view_get_sandbox_instance_id(focused))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case PATTERN_PCRE2:
|
||||
if (regex_cmp(sandbox_instance_id, criteria->sandbox_instance_id->regex) < 0) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (criteria->tag) {
|
||||
const char *tag = view_get_tag(view);
|
||||
if (!tag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (criteria->tag->match_type) {
|
||||
case PATTERN_FOCUSED:
|
||||
if (focused && lenient_strcmp(tag, view_get_tag(focused))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case PATTERN_PCRE2:
|
||||
if (regex_cmp(tag, criteria->tag->regex) < 0) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!criteria_matches_container(criteria, view->container)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -475,6 +563,10 @@ enum criteria_token {
|
|||
T_URGENT,
|
||||
T_WORKSPACE,
|
||||
T_PID,
|
||||
T_SANDBOX_ENGINE,
|
||||
T_SANDBOX_APP_ID,
|
||||
T_SANDBOX_INSTANCE_ID,
|
||||
T_TAG,
|
||||
|
||||
T_INVALID,
|
||||
};
|
||||
|
|
@ -514,6 +606,14 @@ static enum criteria_token token_from_name(char *name) {
|
|||
return T_FLOATING;
|
||||
} else if (strcmp(name, "pid") == 0) {
|
||||
return T_PID;
|
||||
} else if (strcmp(name, "sandbox_engine") == 0) {
|
||||
return T_SANDBOX_ENGINE;
|
||||
} else if (strcmp(name, "sandbox_app_id") == 0) {
|
||||
return T_SANDBOX_APP_ID;
|
||||
} else if (strcmp(name, "sandbox_instance_id") == 0) {
|
||||
return T_SANDBOX_INSTANCE_ID;
|
||||
} else if (strcmp(name, "tag") == 0) {
|
||||
return T_TAG;
|
||||
}
|
||||
return T_INVALID;
|
||||
}
|
||||
|
|
@ -555,8 +655,7 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) {
|
|||
if (strcmp(value, "__focused__") == 0) {
|
||||
struct sway_seat *seat = input_manager_current_seat();
|
||||
struct sway_container *focus = seat_get_focused_container(seat);
|
||||
struct sway_view *view = focus ? focus->view : NULL;
|
||||
criteria->con_id = view ? view->container->node.id : 0;
|
||||
criteria->con_id = focus ? focus->node.id : 0;
|
||||
} else {
|
||||
criteria->con_id = strtoul(value, &endptr, 10);
|
||||
if (*endptr != 0) {
|
||||
|
|
@ -617,6 +716,18 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) {
|
|||
error = strdup("The value for 'pid' should be numeric");
|
||||
}
|
||||
break;
|
||||
case T_SANDBOX_ENGINE:
|
||||
pattern_create(&criteria->sandbox_engine, value);
|
||||
break;
|
||||
case T_SANDBOX_APP_ID:
|
||||
pattern_create(&criteria->sandbox_app_id, value);
|
||||
break;
|
||||
case T_SANDBOX_INSTANCE_ID:
|
||||
pattern_create(&criteria->sandbox_instance_id, value);
|
||||
break;
|
||||
case T_TAG:
|
||||
pattern_create(&criteria->tag, value);
|
||||
break;
|
||||
case T_INVALID:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <wlr/types/wlr_idle_notify_v1.h>
|
||||
#include <wlr/types/wlr_session_lock_v1.h>
|
||||
#include "log.h"
|
||||
#include "sway/desktop/idle_inhibit_v1.h"
|
||||
#include "sway/input/seat.h"
|
||||
|
|
@ -44,6 +45,14 @@ void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) {
|
|||
sway_idle_inhibit_v1_check_active();
|
||||
}
|
||||
|
||||
void handle_manager_destroy(struct wl_listener *listener, void *data) {
|
||||
struct sway_idle_inhibit_manager_v1 *manager =
|
||||
wl_container_of(listener, manager, manager_destroy);
|
||||
|
||||
wl_list_remove(&manager->manager_destroy.link);
|
||||
wl_list_remove(&manager->new_idle_inhibitor_v1.link);
|
||||
}
|
||||
|
||||
void sway_idle_inhibit_v1_user_inhibitor_register(struct sway_view *view,
|
||||
enum sway_idle_inhibit_mode mode) {
|
||||
struct sway_idle_inhibit_manager_v1 *manager = &server.idle_inhibit_manager_v1;
|
||||
|
|
@ -103,11 +112,34 @@ void sway_idle_inhibit_v1_user_inhibitor_destroy(
|
|||
}
|
||||
|
||||
bool sway_idle_inhibit_v1_is_active(struct sway_idle_inhibitor_v1 *inhibitor) {
|
||||
if (server.session_lock.lock) {
|
||||
// A session lock is active. In this case, only application inhibitors
|
||||
// on the session lock surface can have any effect.
|
||||
if (inhibitor->mode != INHIBIT_IDLE_APPLICATION) {
|
||||
return false;
|
||||
}
|
||||
struct wlr_surface *wlr_surface = inhibitor->wlr_inhibitor->surface;
|
||||
if (!wlr_session_lock_surface_v1_try_from_wlr_surface(wlr_surface)) {
|
||||
return false;
|
||||
}
|
||||
return wlr_surface->mapped;
|
||||
}
|
||||
|
||||
switch (inhibitor->mode) {
|
||||
case INHIBIT_IDLE_APPLICATION:;
|
||||
// If there is no view associated with the inhibitor, assume visible
|
||||
struct sway_view *view = view_from_wlr_surface(inhibitor->wlr_inhibitor->surface);
|
||||
return !view || !view->container || view_is_visible(view);
|
||||
struct wlr_surface *wlr_surface = inhibitor->wlr_inhibitor->surface;
|
||||
struct wlr_layer_surface_v1 *layer_surface =
|
||||
wlr_layer_surface_v1_try_from_wlr_surface(wlr_surface);
|
||||
if (layer_surface) {
|
||||
// Layer surfaces can be occluded but are always on screen after
|
||||
// they have been mapped.
|
||||
return layer_surface->output && layer_surface->output->enabled &&
|
||||
wlr_surface->mapped;
|
||||
}
|
||||
|
||||
// If there is no view associated with the inhibitor, assume invisible
|
||||
struct sway_view *view = view_from_wlr_surface(wlr_surface);
|
||||
return view && view->container && view_is_visible(view);
|
||||
case INHIBIT_IDLE_FOCUS:;
|
||||
struct sway_seat *seat = NULL;
|
||||
wl_list_for_each(seat, &server.input->seats, link) {
|
||||
|
|
@ -153,6 +185,9 @@ bool sway_idle_inhibit_manager_v1_init(void) {
|
|||
wl_signal_add(&manager->wlr_manager->events.new_inhibitor,
|
||||
&manager->new_idle_inhibitor_v1);
|
||||
manager->new_idle_inhibitor_v1.notify = handle_idle_inhibitor_v1;
|
||||
wl_signal_add(&manager->wlr_manager->events.destroy,
|
||||
&manager->manager_destroy);
|
||||
manager->manager_destroy.notify = handle_manager_destroy;
|
||||
wl_list_init(&manager->inhibitors);
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface(
|
|||
}
|
||||
|
||||
static void arrange_surface(struct sway_output *output, const struct wlr_box *full_area,
|
||||
struct wlr_box *usable_area, struct wlr_scene_tree *tree) {
|
||||
struct wlr_box *usable_area, struct wlr_scene_tree *tree, bool exclusive) {
|
||||
struct wlr_scene_node *node;
|
||||
wl_list_for_each(node, &tree->children, link) {
|
||||
struct sway_layer_surface *surface = scene_descriptor_try_get(node,
|
||||
|
|
@ -68,6 +68,10 @@ static void arrange_surface(struct sway_output *output, const struct wlr_box *fu
|
|||
continue;
|
||||
}
|
||||
|
||||
if ((surface->scene->layer_surface->current.exclusive_zone > 0) != exclusive) {
|
||||
continue;
|
||||
}
|
||||
|
||||
wlr_scene_layer_surface_v1_configure(surface->scene, full_area, usable_area);
|
||||
}
|
||||
}
|
||||
|
|
@ -78,10 +82,15 @@ void arrange_layers(struct sway_output *output) {
|
|||
&usable_area.width, &usable_area.height);
|
||||
const struct wlr_box full_area = usable_area;
|
||||
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_background);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_top);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay, true);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_top, true);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom, true);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_background, true);
|
||||
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay, false);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_top, false);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom, false);
|
||||
arrange_surface(output, &full_area, &usable_area, output->layers.shell_background, false);
|
||||
|
||||
if (!wlr_box_equal(&usable_area, &output->usable_area)) {
|
||||
sway_log(SWAY_DEBUG, "Usable area changed, rearranging output");
|
||||
|
|
@ -90,6 +99,43 @@ void arrange_layers(struct sway_output *output) {
|
|||
} else {
|
||||
arrange_popups(root->layers.popup);
|
||||
}
|
||||
|
||||
// Find topmost keyboard interactive layer, if such a layer exists
|
||||
struct wlr_scene_tree *layers_above_shell[] = {
|
||||
output->layers.shell_overlay,
|
||||
output->layers.shell_top,
|
||||
};
|
||||
size_t nlayers = sizeof(layers_above_shell) / sizeof(layers_above_shell[0]);
|
||||
struct wlr_scene_node *node;
|
||||
struct sway_layer_surface *topmost = NULL;
|
||||
for (size_t i = 0; i < nlayers; ++i) {
|
||||
wl_list_for_each_reverse(node,
|
||||
&layers_above_shell[i]->children, link) {
|
||||
struct sway_layer_surface *surface = scene_descriptor_try_get(node,
|
||||
SWAY_SCENE_DESC_LAYER_SHELL);
|
||||
if (surface && surface->layer_surface->current.keyboard_interactive
|
||||
== ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE &&
|
||||
surface->layer_surface->surface->mapped) {
|
||||
topmost = surface;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (topmost != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct sway_seat *seat;
|
||||
wl_list_for_each(seat, &server.input->seats, link) {
|
||||
seat->has_exclusive_layer = false;
|
||||
if (topmost != NULL) {
|
||||
seat_set_focus_layer(seat, topmost->layer_surface);
|
||||
} else if (seat->focused_layer &&
|
||||
seat->focused_layer->current.keyboard_interactive
|
||||
!= ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) {
|
||||
seat_set_focus_layer(seat, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct wlr_scene_tree *sway_layer_get_scene(struct sway_output *output,
|
||||
|
|
@ -170,14 +216,6 @@ static struct sway_layer_surface *find_mapped_layer_by_client(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void handle_output_destroy(struct wl_listener *listener, void *data) {
|
||||
struct sway_layer_surface *layer =
|
||||
wl_container_of(listener, layer, output_destroy);
|
||||
|
||||
layer->output = NULL;
|
||||
wlr_scene_node_destroy(&layer->scene->tree->node);
|
||||
}
|
||||
|
||||
static void handle_node_destroy(struct wl_listener *listener, void *data) {
|
||||
struct sway_layer_surface *layer =
|
||||
wl_container_of(listener, layer, node_destroy);
|
||||
|
|
@ -210,10 +248,11 @@ static void handle_node_destroy(struct wl_listener *listener, void *data) {
|
|||
wl_list_remove(&layer->unmap.link);
|
||||
wl_list_remove(&layer->surface_commit.link);
|
||||
wl_list_remove(&layer->node_destroy.link);
|
||||
wl_list_remove(&layer->output_destroy.link);
|
||||
wl_list_remove(&layer->new_popup.link);
|
||||
|
||||
layer->layer_surface->data = NULL;
|
||||
|
||||
wl_list_remove(&layer->link);
|
||||
free(layer);
|
||||
}
|
||||
|
||||
|
|
@ -222,12 +261,8 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
|
|||
wl_container_of(listener, surface, surface_commit);
|
||||
|
||||
struct wlr_layer_surface_v1 *layer_surface = surface->layer_surface;
|
||||
if (!layer_surface->initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t committed = layer_surface->current.committed;
|
||||
if (committed & WLR_LAYER_SURFACE_V1_STATE_LAYER) {
|
||||
if (layer_surface->initialized && committed & WLR_LAYER_SURFACE_V1_STATE_LAYER) {
|
||||
enum zwlr_layer_shell_v1_layer layer_type = layer_surface->current.layer;
|
||||
struct wlr_scene_tree *output_layer = sway_layer_get_scene(
|
||||
surface->output, layer_type);
|
||||
|
|
@ -432,6 +467,7 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
|
||||
surface->output = output;
|
||||
wl_list_insert(&output->layer_surfaces, &surface->link);
|
||||
|
||||
// now that the surface's output is known, we can advertise its scale
|
||||
wlr_fractional_scale_v1_notify_scale(surface->layer_surface->surface,
|
||||
|
|
@ -449,9 +485,14 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
|
|||
surface->new_popup.notify = handle_new_popup;
|
||||
wl_signal_add(&layer_surface->events.new_popup, &surface->new_popup);
|
||||
|
||||
surface->output_destroy.notify = handle_output_destroy;
|
||||
wl_signal_add(&output->events.disable, &surface->output_destroy);
|
||||
|
||||
surface->node_destroy.notify = handle_node_destroy;
|
||||
wl_signal_add(&scene_surface->tree->node.events.destroy, &surface->node_destroy);
|
||||
}
|
||||
|
||||
void destroy_layers(struct sway_output *output) {
|
||||
struct sway_layer_surface *layer, *layer_tmp;
|
||||
wl_list_for_each_safe(layer, layer_tmp, &output->layer_surfaces, link) {
|
||||
layer->output = NULL;
|
||||
wlr_layer_surface_v1_destroy(layer->layer_surface);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
#include <wlr/render/swapchain.h>
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
#include <wlr/types/wlr_buffer.h>
|
||||
#include <wlr/types/wlr_alpha_modifier_v1.h>
|
||||
#include <wlr/types/wlr_gamma_control_v1.h>
|
||||
#include <wlr/types/wlr_matrix.h>
|
||||
#include <wlr/types/wlr_output_layout.h>
|
||||
#include <wlr/types/wlr_output_management_v1.h>
|
||||
#include <wlr/types/wlr_output_power_management_v1.h>
|
||||
|
|
@ -97,11 +97,11 @@ struct buffer_timer {
|
|||
};
|
||||
|
||||
static int handle_buffer_timer(void *data) {
|
||||
struct wlr_scene_buffer *buffer = data;
|
||||
struct wlr_scene_surface *scene_surface = data;
|
||||
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
wlr_scene_buffer_send_frame_done(buffer, &now);
|
||||
wlr_scene_surface_send_frame_done(scene_surface, &now);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +114,9 @@ static void handle_buffer_timer_destroy(struct wl_listener *listener,
|
|||
free(timer);
|
||||
}
|
||||
|
||||
static struct buffer_timer *buffer_timer_get_or_create(struct wlr_scene_buffer *buffer) {
|
||||
static struct buffer_timer *buffer_timer_get_or_create(struct wlr_scene_surface *scene_surface) {
|
||||
struct wlr_scene_buffer *buffer = scene_surface->buffer;
|
||||
|
||||
struct buffer_timer *timer =
|
||||
scene_descriptor_try_get(&buffer->node, SWAY_SCENE_DESC_BUFFER_TIMER);
|
||||
if (timer) {
|
||||
|
|
@ -127,7 +129,7 @@ static struct buffer_timer *buffer_timer_get_or_create(struct wlr_scene_buffer *
|
|||
}
|
||||
|
||||
timer->frame_done_timer = wl_event_loop_add_timer(server.wl_event_loop,
|
||||
handle_buffer_timer, buffer);
|
||||
handle_buffer_timer, scene_surface);
|
||||
if (!timer->frame_done_timer) {
|
||||
free(timer);
|
||||
return NULL;
|
||||
|
|
@ -151,6 +153,11 @@ static void send_frame_done_iterator(struct wlr_scene_buffer *buffer,
|
|||
return;
|
||||
}
|
||||
|
||||
struct wlr_scene_surface *scene_surface = wlr_scene_surface_try_from_buffer(buffer);
|
||||
if (scene_surface == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_scene_node *current = &buffer->node;
|
||||
while (true) {
|
||||
struct sway_view *view = scene_descriptor_try_get(current,
|
||||
|
|
@ -173,13 +180,13 @@ static void send_frame_done_iterator(struct wlr_scene_buffer *buffer,
|
|||
struct buffer_timer *timer = NULL;
|
||||
|
||||
if (output->max_render_time != 0 && view_max_render_time != 0 && delay > 0) {
|
||||
timer = buffer_timer_get_or_create(buffer);
|
||||
timer = buffer_timer_get_or_create(scene_surface);
|
||||
}
|
||||
|
||||
if (timer) {
|
||||
wl_event_source_timer_update(timer->frame_done_timer, delay);
|
||||
} else {
|
||||
wlr_scene_buffer_send_frame_done(buffer, &data->when);
|
||||
wlr_scene_surface_send_frame_done(scene_surface, &data->when);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -187,8 +194,8 @@ static enum wlr_scale_filter_mode get_scale_filter(struct sway_output *output,
|
|||
struct wlr_scene_buffer *buffer) {
|
||||
// if we are scaling down, we should always choose linear
|
||||
if (buffer->dst_width > 0 && buffer->dst_height > 0 && (
|
||||
buffer->dst_width < buffer->buffer_width ||
|
||||
buffer->dst_height < buffer->buffer_height)) {
|
||||
buffer->dst_width < buffer->WLR_PRIVATE.buffer_width ||
|
||||
buffer->dst_height < buffer->WLR_PRIVATE.buffer_height)) {
|
||||
return WLR_SCALE_FILTER_BILINEAR;
|
||||
}
|
||||
|
||||
|
|
@ -202,7 +209,7 @@ static enum wlr_scale_filter_mode get_scale_filter(struct sway_output *output,
|
|||
}
|
||||
}
|
||||
|
||||
static void output_configure_scene(struct sway_output *output,
|
||||
void output_configure_scene(struct sway_output *output,
|
||||
struct wlr_scene_node *node, float opacity) {
|
||||
if (!node->enabled) {
|
||||
return;
|
||||
|
|
@ -216,11 +223,22 @@ static void output_configure_scene(struct sway_output *output,
|
|||
|
||||
if (node->type == WLR_SCENE_NODE_BUFFER) {
|
||||
struct wlr_scene_buffer *buffer = wlr_scene_buffer_from_node(node);
|
||||
struct wlr_scene_surface *surface = wlr_scene_surface_try_from_buffer(buffer);
|
||||
|
||||
if (surface) {
|
||||
const struct wlr_alpha_modifier_surface_v1_state *alpha_modifier_state =
|
||||
wlr_alpha_modifier_v1_get_surface_state(surface->surface);
|
||||
if (alpha_modifier_state != NULL) {
|
||||
opacity *= (float)alpha_modifier_state->multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
// hack: don't call the scene setter because that will damage all outputs
|
||||
// We don't want to damage outputs that aren't our current output that
|
||||
// we're configuring
|
||||
if (output) {
|
||||
buffer->filter_mode = get_scale_filter(output, buffer);
|
||||
}
|
||||
|
||||
wlr_scene_buffer_set_opacity(buffer, opacity);
|
||||
} else if (node->type == WLR_SCENE_NODE_TREE) {
|
||||
|
|
@ -232,40 +250,56 @@ static void output_configure_scene(struct sway_output *output,
|
|||
}
|
||||
}
|
||||
|
||||
static bool output_can_tear(struct sway_output *output) {
|
||||
struct sway_workspace *workspace = output->current.active_workspace;
|
||||
if (!workspace) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct sway_container *fullscreen_con = root->fullscreen_global;
|
||||
if (!fullscreen_con) {
|
||||
fullscreen_con = workspace->current.fullscreen;
|
||||
}
|
||||
if (fullscreen_con && fullscreen_con->view) {
|
||||
return (output->allow_tearing && view_can_tear(fullscreen_con->view));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int output_repaint_timer_handler(void *data) {
|
||||
struct sway_output *output = data;
|
||||
|
||||
if (!output->enabled) {
|
||||
output->wlr_output->frame_pending = false;
|
||||
if (!output->wlr_output->enabled) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
output->wlr_output->frame_pending = false;
|
||||
|
||||
output_configure_scene(output, &root->root_scene->tree.node, 1.0f);
|
||||
|
||||
struct wlr_scene_output_state_options opts = {
|
||||
.color_transform = output->color_transform,
|
||||
};
|
||||
|
||||
struct wlr_output_state pending;
|
||||
wlr_output_state_init(&pending);
|
||||
if (!wlr_scene_output_build_state(output->scene_output, &pending, &opts)) {
|
||||
struct wlr_scene_output *scene_output = output->scene_output;
|
||||
if (!wlr_scene_output_needs_frame(scene_output)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (output->gamma_lut_changed) {
|
||||
output->gamma_lut_changed = false;
|
||||
struct wlr_gamma_control_v1 *gamma_control =
|
||||
wlr_gamma_control_manager_v1_get_control(
|
||||
server.gamma_control_manager_v1, output->wlr_output);
|
||||
if (!wlr_gamma_control_v1_apply(gamma_control, &pending)) {
|
||||
struct wlr_output_state pending;
|
||||
wlr_output_state_init(&pending);
|
||||
if (!wlr_scene_output_build_state(output->scene_output, &pending, &opts)) {
|
||||
wlr_output_state_finish(&pending);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (output_can_tear(output)) {
|
||||
pending.tearing_page_flip = true;
|
||||
|
||||
if (!wlr_output_test_state(output->wlr_output, &pending)) {
|
||||
wlr_gamma_control_v1_send_failed_and_destroy(gamma_control);
|
||||
wlr_output_state_set_gamma_lut(&pending, 0, NULL, NULL, NULL);
|
||||
sway_log(SWAY_DEBUG, "Output test failed on '%s', retrying without tearing page-flip",
|
||||
output->wlr_output->name);
|
||||
pending.tearing_page_flip = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -340,7 +374,7 @@ static void handle_frame(struct wl_listener *listener, void *user_data) {
|
|||
wlr_scene_output_for_each_buffer(output->scene_output, send_frame_done_iterator, &data);
|
||||
}
|
||||
|
||||
static void update_output_manager_config(struct sway_server *server) {
|
||||
void update_output_manager_config(struct sway_server *server) {
|
||||
struct wlr_output_configuration_v1 *config =
|
||||
wlr_output_configuration_v1_create();
|
||||
|
||||
|
|
@ -370,45 +404,56 @@ static int timer_modeset_handle(void *data) {
|
|||
wl_event_source_remove(server->delayed_modeset);
|
||||
server->delayed_modeset = NULL;
|
||||
|
||||
apply_all_output_configs();
|
||||
transaction_commit_dirty();
|
||||
update_output_manager_config(server);
|
||||
|
||||
apply_stored_output_configs();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void request_modeset(struct sway_server *server) {
|
||||
if (server->delayed_modeset == NULL) {
|
||||
server->delayed_modeset = wl_event_loop_add_timer(server->wl_event_loop,
|
||||
timer_modeset_handle, server);
|
||||
wl_event_source_timer_update(server->delayed_modeset, 10);
|
||||
void request_modeset(void) {
|
||||
if (server.delayed_modeset == NULL) {
|
||||
server.delayed_modeset = wl_event_loop_add_timer(server.wl_event_loop,
|
||||
timer_modeset_handle, &server);
|
||||
wl_event_source_timer_update(server.delayed_modeset, 10);
|
||||
}
|
||||
}
|
||||
|
||||
bool modeset_is_pending(void) {
|
||||
return server.delayed_modeset != NULL;
|
||||
}
|
||||
|
||||
void force_modeset(void) {
|
||||
if (server.delayed_modeset != NULL) {
|
||||
wl_event_source_remove(server.delayed_modeset);
|
||||
server.delayed_modeset = NULL;
|
||||
}
|
||||
apply_stored_output_configs();
|
||||
}
|
||||
|
||||
static void begin_destroy(struct sway_output *output) {
|
||||
struct sway_server *server = output->server;
|
||||
|
||||
if (output->enabled) {
|
||||
output_disable(output);
|
||||
}
|
||||
|
||||
output_begin_destroy(output);
|
||||
|
||||
wl_list_remove(&output->link);
|
||||
|
||||
wl_list_remove(&output->layout_destroy.link);
|
||||
wl_list_remove(&output->destroy.link);
|
||||
wl_list_remove(&output->commit.link);
|
||||
wl_list_remove(&output->present.link);
|
||||
wl_list_remove(&output->frame.link);
|
||||
wl_list_remove(&output->request_state.link);
|
||||
|
||||
// Remove the scene_output first to ensure that the scene does not emit
|
||||
// events for this output.
|
||||
wlr_scene_output_destroy(output->scene_output);
|
||||
output->scene_output = NULL;
|
||||
|
||||
if (output->enabled) {
|
||||
output_disable(output);
|
||||
}
|
||||
output_begin_destroy(output);
|
||||
wl_list_remove(&output->link);
|
||||
|
||||
output->wlr_output->data = NULL;
|
||||
output->wlr_output = NULL;
|
||||
|
||||
request_modeset(server);
|
||||
wl_event_source_remove(output->repaint_timer);
|
||||
output->repaint_timer = NULL;
|
||||
|
||||
request_modeset();
|
||||
}
|
||||
|
||||
static void handle_destroy(struct wl_listener *listener, void *data) {
|
||||
|
|
@ -421,31 +466,6 @@ static void handle_layout_destroy(struct wl_listener *listener, void *data) {
|
|||
begin_destroy(output);
|
||||
}
|
||||
|
||||
static void handle_commit(struct wl_listener *listener, void *data) {
|
||||
struct sway_output *output = wl_container_of(listener, output, commit);
|
||||
struct wlr_output_event_commit *event = data;
|
||||
|
||||
if (!output->enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->state->committed & (
|
||||
WLR_OUTPUT_STATE_MODE |
|
||||
WLR_OUTPUT_STATE_TRANSFORM |
|
||||
WLR_OUTPUT_STATE_SCALE)) {
|
||||
arrange_layers(output);
|
||||
arrange_output(output);
|
||||
transaction_commit_dirty();
|
||||
|
||||
update_output_manager_config(output->server);
|
||||
}
|
||||
|
||||
// Next time the output is enabled, try to re-apply the gamma LUT
|
||||
if ((event->state->committed & WLR_OUTPUT_STATE_ENABLED) && !output->wlr_output->enabled) {
|
||||
output->gamma_lut_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_present(struct wl_listener *listener, void *data) {
|
||||
struct sway_output *output = wl_container_of(listener, output, present);
|
||||
struct wlr_output_event_present *output_event = data;
|
||||
|
|
@ -454,7 +474,7 @@ static void handle_present(struct wl_listener *listener, void *data) {
|
|||
return;
|
||||
}
|
||||
|
||||
output->last_presentation = *output_event->when;
|
||||
output->last_presentation = output_event->when;
|
||||
output->refresh_nsec = output_event->refresh;
|
||||
}
|
||||
|
||||
|
|
@ -462,7 +482,44 @@ static void handle_request_state(struct wl_listener *listener, void *data) {
|
|||
struct sway_output *output =
|
||||
wl_container_of(listener, output, request_state);
|
||||
const struct wlr_output_event_request_state *event = data;
|
||||
wlr_output_commit_state(output->wlr_output, event->state);
|
||||
const struct wlr_output_state *state = event->state;
|
||||
|
||||
// Store the requested changes so that the active configuration is
|
||||
// consistent with the current state, and to avoid duplicate logic to apply
|
||||
// the changes.
|
||||
struct output_config *oc = new_output_config(output->wlr_output->name);
|
||||
if (!oc) {
|
||||
sway_log(SWAY_ERROR, "Allocation failed");
|
||||
return;
|
||||
}
|
||||
|
||||
int committed = state->committed;
|
||||
if (committed & WLR_OUTPUT_STATE_MODE) {
|
||||
if (state->mode != NULL) {
|
||||
oc->width = state->mode->width;
|
||||
oc->height = state->mode->height;
|
||||
oc->refresh_rate = state->mode->refresh / 1000.f;
|
||||
} else {
|
||||
oc->width = state->custom_mode.width;
|
||||
oc->height = state->custom_mode.height;
|
||||
oc->refresh_rate = state->custom_mode.refresh / 1000.f;
|
||||
}
|
||||
committed &= ~WLR_OUTPUT_STATE_MODE;
|
||||
}
|
||||
if (committed & WLR_OUTPUT_STATE_SCALE) {
|
||||
oc->scale = state->scale;
|
||||
committed &= ~WLR_OUTPUT_STATE_SCALE;
|
||||
}
|
||||
if (committed & WLR_OUTPUT_STATE_TRANSFORM) {
|
||||
oc->transform = state->transform;
|
||||
committed &= ~WLR_OUTPUT_STATE_TRANSFORM;
|
||||
}
|
||||
|
||||
// We do not expect or support any other changes here
|
||||
assert(committed == 0);
|
||||
store_output_config(oc);
|
||||
|
||||
force_modeset();
|
||||
}
|
||||
|
||||
static unsigned int last_headless_num = 0;
|
||||
|
|
@ -526,8 +583,6 @@ void handle_new_output(struct wl_listener *listener, void *data) {
|
|||
output->layout_destroy.notify = handle_layout_destroy;
|
||||
wl_signal_add(&wlr_output->events.destroy, &output->destroy);
|
||||
output->destroy.notify = handle_destroy;
|
||||
wl_signal_add(&wlr_output->events.commit, &output->commit);
|
||||
output->commit.notify = handle_commit;
|
||||
wl_signal_add(&wlr_output->events.present, &output->present);
|
||||
output->present.notify = handle_present;
|
||||
wl_signal_add(&wlr_output->events.frame, &output->frame);
|
||||
|
|
@ -542,35 +597,16 @@ void handle_new_output(struct wl_listener *listener, void *data) {
|
|||
sway_session_lock_add_output(server->session_lock.lock, output);
|
||||
}
|
||||
|
||||
request_modeset(server);
|
||||
}
|
||||
|
||||
void handle_output_layout_change(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct sway_server *server =
|
||||
wl_container_of(listener, server, output_layout_change);
|
||||
update_output_manager_config(server);
|
||||
}
|
||||
|
||||
void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data) {
|
||||
struct sway_server *server =
|
||||
wl_container_of(listener, server, gamma_control_set_gamma);
|
||||
const struct wlr_gamma_control_manager_v1_set_gamma_event *event = data;
|
||||
|
||||
struct sway_output *output = event->output->data;
|
||||
|
||||
if(!output) {
|
||||
return;
|
||||
}
|
||||
|
||||
output->gamma_lut_changed = true;
|
||||
wlr_output_schedule_frame(output->wlr_output);
|
||||
request_modeset();
|
||||
}
|
||||
|
||||
static struct output_config *output_config_for_config_head(
|
||||
struct wlr_output_configuration_head_v1 *config_head,
|
||||
struct sway_output *output) {
|
||||
struct output_config *oc = new_output_config(output->wlr_output->name);
|
||||
struct wlr_output_configuration_head_v1 *config_head) {
|
||||
struct output_config *oc = new_output_config(config_head->state.output->name);
|
||||
if (!oc) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
oc->enabled = config_head->state.enabled;
|
||||
if (!oc->enabled) {
|
||||
return oc;
|
||||
|
|
@ -596,71 +632,59 @@ static struct output_config *output_config_for_config_head(
|
|||
}
|
||||
|
||||
static void output_manager_apply(struct sway_server *server,
|
||||
struct wlr_output_configuration_v1 *config, bool test_only) {
|
||||
size_t configs_len = wl_list_length(&root->all_outputs);
|
||||
struct matched_output_config *configs = calloc(configs_len, sizeof(*configs));
|
||||
struct wlr_output_configuration_v1 *cfg, bool test_only) {
|
||||
bool ok = false;
|
||||
size_t configs_len = config->output_configs->length + wl_list_length(&cfg->heads);
|
||||
struct output_config **configs = calloc(configs_len, sizeof(*configs));
|
||||
if (!configs) {
|
||||
return;
|
||||
sway_log(SWAY_ERROR, "Allocation failed");
|
||||
goto error;
|
||||
}
|
||||
size_t start_new_configs = config->output_configs->length;
|
||||
for (size_t idx = 0; idx < start_new_configs; idx++) {
|
||||
configs[idx] = config->output_configs->items[idx];
|
||||
}
|
||||
|
||||
int config_idx = 0;
|
||||
struct sway_output *sway_output;
|
||||
wl_list_for_each(sway_output, &root->all_outputs, link) {
|
||||
if (sway_output == root->fallback_output) {
|
||||
configs_len--;
|
||||
continue;
|
||||
}
|
||||
|
||||
struct matched_output_config *cfg = &configs[config_idx++];
|
||||
cfg->output = sway_output;
|
||||
|
||||
size_t config_idx = start_new_configs;
|
||||
struct wlr_output_configuration_head_v1 *config_head;
|
||||
wl_list_for_each(config_head, &config->heads, link) {
|
||||
if (config_head->state.output == sway_output->wlr_output) {
|
||||
cfg->config = output_config_for_config_head(config_head, sway_output);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!cfg->config) {
|
||||
cfg->config = find_output_config(sway_output);
|
||||
wl_list_for_each(config_head, &cfg->heads, link) {
|
||||
// Generate the configuration and store it as a temporary
|
||||
// config. We keep a record of it so we can remove it later.
|
||||
struct output_config *oc = output_config_for_config_head(config_head);
|
||||
if (!oc) {
|
||||
sway_log(SWAY_ERROR, "Allocation failed");
|
||||
goto error_config;
|
||||
}
|
||||
configs[config_idx++] = oc;
|
||||
}
|
||||
|
||||
sort_output_configs_by_priority(configs, configs_len);
|
||||
bool ok = apply_output_configs(configs, configs_len, test_only, false);
|
||||
for (size_t idx = 0; idx < configs_len; idx++) {
|
||||
struct matched_output_config *cfg = &configs[idx];
|
||||
// Try to commit without degrade to off enabled. Note that this will fail
|
||||
// if any output configured for enablement fails to be enabled, even if it
|
||||
// was not part of the config heads we were asked to configure.
|
||||
ok = apply_output_configs(configs, configs_len, test_only, false);
|
||||
|
||||
// Only store new configs for successful non-test commits. Old configs,
|
||||
// test-only and failed commits just get freed.
|
||||
bool store_config = false;
|
||||
error_config:
|
||||
for (size_t idx = start_new_configs; idx < configs_len; idx++) {
|
||||
struct output_config *cfg = configs[idx];
|
||||
if (!test_only && ok) {
|
||||
struct wlr_output_configuration_head_v1 *config_head;
|
||||
wl_list_for_each(config_head, &config->heads, link) {
|
||||
if (config_head->state.output == cfg->output->wlr_output) {
|
||||
store_config = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (store_config) {
|
||||
store_output_config(cfg->config);
|
||||
store_output_config(cfg);
|
||||
} else {
|
||||
free_output_config(cfg->config);
|
||||
free_output_config(cfg);
|
||||
}
|
||||
}
|
||||
free(configs);
|
||||
|
||||
error:
|
||||
if (ok) {
|
||||
wlr_output_configuration_v1_send_succeeded(config);
|
||||
wlr_output_configuration_v1_send_succeeded(cfg);
|
||||
if (server->delayed_modeset != NULL) {
|
||||
wl_event_source_remove(server->delayed_modeset);
|
||||
server->delayed_modeset = NULL;
|
||||
}
|
||||
} else {
|
||||
wlr_output_configuration_v1_send_failed(config);
|
||||
}
|
||||
wlr_output_configuration_v1_destroy(config);
|
||||
|
||||
if (!test_only) {
|
||||
update_output_manager_config(server);
|
||||
wlr_output_configuration_v1_send_failed(cfg);
|
||||
}
|
||||
wlr_output_configuration_v1_destroy(cfg);
|
||||
}
|
||||
|
||||
void handle_output_manager_apply(struct wl_listener *listener, void *data) {
|
||||
|
|
@ -685,6 +709,11 @@ void handle_output_power_manager_set_mode(struct wl_listener *listener,
|
|||
struct sway_output *output = event->output->data;
|
||||
|
||||
struct output_config *oc = new_output_config(output->wlr_output->name);
|
||||
if (!oc) {
|
||||
sway_log(SWAY_ERROR, "Allocation failed");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event->mode) {
|
||||
case ZWLR_OUTPUT_POWER_V1_MODE_OFF:
|
||||
oc->power = 0;
|
||||
|
|
@ -694,5 +723,5 @@ void handle_output_power_manager_set_mode(struct wl_listener *listener,
|
|||
break;
|
||||
}
|
||||
store_output_config(oc);
|
||||
request_modeset(output->server);
|
||||
request_modeset();
|
||||
}
|
||||
|
|
|
|||
64
sway/desktop/tearing.c
Normal file
64
sway/desktop/tearing.c
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#include <wayland-server-core.h>
|
||||
#include <wlr/types/wlr_tearing_control_v1.h>
|
||||
#include "sway/server.h"
|
||||
#include "sway/tree/view.h"
|
||||
#include "sway/output.h"
|
||||
#include "log.h"
|
||||
|
||||
struct sway_tearing_controller {
|
||||
struct wlr_tearing_control_v1 *tearing_control;
|
||||
struct wl_listener set_hint;
|
||||
struct wl_listener destroy;
|
||||
|
||||
struct wl_list link; // sway_server::tearing_controllers
|
||||
};
|
||||
|
||||
static void handle_tearing_controller_set_hint(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct sway_tearing_controller *controller =
|
||||
wl_container_of(listener, controller, set_hint);
|
||||
|
||||
struct sway_view *view = view_from_wlr_surface(
|
||||
controller->tearing_control->surface);
|
||||
if (view) {
|
||||
view->tearing_hint = controller->tearing_control->current;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_tearing_controller_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct sway_tearing_controller *controller =
|
||||
wl_container_of(listener, controller, destroy);
|
||||
wl_list_remove(&controller->set_hint.link);
|
||||
wl_list_remove(&controller->destroy.link);
|
||||
wl_list_remove(&controller->link);
|
||||
free(controller);
|
||||
}
|
||||
|
||||
void handle_new_tearing_hint(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct sway_server *server =
|
||||
wl_container_of(listener, server, tearing_control_new_object);
|
||||
struct wlr_tearing_control_v1 *tearing_control = data;
|
||||
|
||||
enum wp_tearing_control_v1_presentation_hint hint =
|
||||
wlr_tearing_control_manager_v1_surface_hint_from_surface(
|
||||
server->tearing_control_v1, tearing_control->surface);
|
||||
sway_log(SWAY_DEBUG, "New presentation hint %d received for surface %p",
|
||||
hint, tearing_control->surface);
|
||||
|
||||
struct sway_tearing_controller *controller =
|
||||
calloc(1, sizeof(struct sway_tearing_controller));
|
||||
if (!controller) {
|
||||
return;
|
||||
}
|
||||
|
||||
controller->tearing_control = tearing_control;
|
||||
controller->set_hint.notify = handle_tearing_controller_set_hint;
|
||||
wl_signal_add(&tearing_control->events.set_hint, &controller->set_hint);
|
||||
controller->destroy.notify = handle_tearing_controller_destroy;
|
||||
wl_signal_add(&tearing_control->events.destroy, &controller->destroy);
|
||||
wl_list_init(&controller->link);
|
||||
|
||||
wl_list_insert(&server->tearing_controllers, &controller->link);
|
||||
}
|
||||
|
|
@ -309,12 +309,13 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
|
|||
arrange_title_bar(child, title_offset, -title_bar_height,
|
||||
next_title_offset - title_offset, title_bar_height);
|
||||
wlr_scene_node_set_enabled(&child->border.tree->node, activated);
|
||||
wlr_scene_node_set_enabled(&child->scene_tree->node, true);
|
||||
wlr_scene_node_set_position(&child->scene_tree->node, 0, title_bar_height);
|
||||
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
||||
|
||||
if (activated) {
|
||||
arrange_container(child, width, height - title_bar_height,
|
||||
title_bar_height == 0, 0);
|
||||
int net_height = height - title_bar_height;
|
||||
if (activated && width > 0 && net_height > 0) {
|
||||
arrange_container(child, width, net_height, title_bar_height == 0, 0);
|
||||
} else {
|
||||
disable_container(child);
|
||||
}
|
||||
|
|
@ -338,12 +339,13 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
|
|||
|
||||
arrange_title_bar(child, 0, y - title_height, width, title_bar_height);
|
||||
wlr_scene_node_set_enabled(&child->border.tree->node, activated);
|
||||
wlr_scene_node_set_enabled(&child->scene_tree->node, true);
|
||||
wlr_scene_node_set_position(&child->scene_tree->node, 0, title_height);
|
||||
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
||||
|
||||
if (activated) {
|
||||
arrange_container(child, width, height - title_height,
|
||||
title_bar_height == 0, 0);
|
||||
int net_height = height - title_height;
|
||||
if (activated && width > 0 && net_height > 0) {
|
||||
arrange_container(child, width, net_height, title_bar_height == 0, 0);
|
||||
} else {
|
||||
disable_container(child);
|
||||
}
|
||||
|
|
@ -359,8 +361,12 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
|
|||
wlr_scene_node_set_enabled(&child->border.tree->node, true);
|
||||
wlr_scene_node_set_position(&child->scene_tree->node, 0, off);
|
||||
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
||||
if (width > 0 && cheight > 0) {
|
||||
arrange_container(child, width, cheight, true, gaps);
|
||||
off += cheight + gaps;
|
||||
} else {
|
||||
disable_container(child);
|
||||
}
|
||||
}
|
||||
} else if (layout == L_HORIZ) {
|
||||
int off = 0;
|
||||
|
|
@ -371,8 +377,12 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
|
|||
wlr_scene_node_set_enabled(&child->border.tree->node, true);
|
||||
wlr_scene_node_set_position(&child->scene_tree->node, off, 0);
|
||||
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
||||
if (cwidth > 0 && height > 0) {
|
||||
arrange_container(child, cwidth, height, true, gaps);
|
||||
off += cwidth + gaps;
|
||||
} else {
|
||||
disable_container(child);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sway_assert(false, "unreachable");
|
||||
|
|
@ -424,13 +434,14 @@ static void arrange_container(struct sway_container *con,
|
|||
int border_bottom = con->current.border_bottom ? border_width : 0;
|
||||
int border_left = con->current.border_left ? border_width : 0;
|
||||
int border_right = con->current.border_right ? border_width : 0;
|
||||
int vert_border_height = MAX(0, height - border_top - border_bottom);
|
||||
|
||||
wlr_scene_rect_set_size(con->border.top, width, border_top);
|
||||
wlr_scene_rect_set_size(con->border.bottom, width, border_bottom);
|
||||
wlr_scene_rect_set_size(con->border.left,
|
||||
border_left, height - border_top - border_bottom);
|
||||
border_left, vert_border_height);
|
||||
wlr_scene_rect_set_size(con->border.right,
|
||||
border_right, height - border_top - border_bottom);
|
||||
border_right, vert_border_height);
|
||||
|
||||
wlr_scene_node_set_position(&con->border.top->node, 0, 0);
|
||||
wlr_scene_node_set_position(&con->border.bottom->node,
|
||||
|
|
@ -523,6 +534,7 @@ static void arrange_workspace_floating(struct sway_workspace *ws) {
|
|||
wlr_scene_node_set_position(&floater->scene_tree->node,
|
||||
floater->current.x, floater->current.y);
|
||||
wlr_scene_node_set_enabled(&floater->scene_tree->node, true);
|
||||
wlr_scene_node_set_enabled(&floater->border.tree->node, true);
|
||||
|
||||
arrange_container(floater, floater->current.width, floater->current.height,
|
||||
true, ws->gaps_inner);
|
||||
|
|
@ -559,7 +571,7 @@ static void arrange_output(struct sway_output *output, int width, int height) {
|
|||
for (int i = 0; i < output->current.workspaces->length; i++) {
|
||||
struct sway_workspace *child = output->current.workspaces->items[i];
|
||||
|
||||
bool activated = output->current.active_workspace == child;
|
||||
bool activated = output->current.active_workspace == child && output->wlr_output->enabled;
|
||||
|
||||
wlr_scene_node_reparent(&child->layers.tiling->node, output->layers.tiling);
|
||||
wlr_scene_node_reparent(&child->layers.fullscreen->node, output->layers.fullscreen);
|
||||
|
|
@ -575,15 +587,16 @@ static void arrange_output(struct sway_output *output, int width, int height) {
|
|||
wlr_scene_node_set_enabled(&child->layers.tiling->node, !fs);
|
||||
wlr_scene_node_set_enabled(&child->layers.fullscreen->node, fs);
|
||||
|
||||
arrange_workspace_floating(child);
|
||||
|
||||
wlr_scene_node_set_enabled(&output->layers.shell_background->node, !fs);
|
||||
wlr_scene_node_set_enabled(&output->layers.shell_bottom->node, !fs);
|
||||
wlr_scene_node_set_enabled(&output->layers.fullscreen->node, fs);
|
||||
|
||||
if (fs) {
|
||||
disable_workspace(child);
|
||||
|
||||
wlr_scene_rect_set_size(output->fullscreen_background, width, height);
|
||||
|
||||
arrange_workspace_floating(child);
|
||||
arrange_fullscreen(child->layers.fullscreen, fs, child,
|
||||
width, height);
|
||||
} else {
|
||||
|
|
@ -596,6 +609,7 @@ static void arrange_output(struct sway_output *output, int width, int height) {
|
|||
arrange_workspace_tiling(child,
|
||||
area->width - gaps->left - gaps->right,
|
||||
area->height - gaps->top - gaps->bottom);
|
||||
arrange_workspace_floating(child);
|
||||
}
|
||||
} else {
|
||||
wlr_scene_node_set_enabled(&child->layers.tiling->node, false);
|
||||
|
|
@ -612,11 +626,13 @@ void arrange_popups(struct wlr_scene_tree *popups) {
|
|||
struct sway_popup_desc *popup = scene_descriptor_try_get(node,
|
||||
SWAY_SCENE_DESC_POPUP);
|
||||
|
||||
if (popup) {
|
||||
int lx, ly;
|
||||
wlr_scene_node_coords(popup->relative, &lx, &ly);
|
||||
wlr_scene_node_set_position(node, lx, ly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void arrange_root(struct sway_root *root) {
|
||||
struct sway_container *fs = root->fullscreen_global;
|
||||
|
|
@ -632,6 +648,15 @@ static void arrange_root(struct sway_root *root) {
|
|||
for (int i = 0; i < root->scratchpad->length; i++) {
|
||||
struct sway_container *con = root->scratchpad->items[i];
|
||||
|
||||
// When a container is moved to a scratchpad, it's possible that it
|
||||
// was moved into a floating container as part of the same transaction.
|
||||
// In this case, we need to make sure we reparent all the container's
|
||||
// children so that disabling the container will disable all descendants.
|
||||
if (!con->view) for (int ii = 0; ii < con->current.children->length; ii++) {
|
||||
struct sway_container *child = con->current.children->items[ii];
|
||||
wlr_scene_node_reparent(&child->scene_tree->node, con->content_tree);
|
||||
}
|
||||
|
||||
wlr_scene_node_set_enabled(&con->scene_tree->node, false);
|
||||
}
|
||||
|
||||
|
|
@ -640,6 +665,15 @@ static void arrange_root(struct sway_root *root) {
|
|||
struct sway_output *output = root->outputs->items[i];
|
||||
struct sway_workspace *ws = output->current.active_workspace;
|
||||
|
||||
wlr_scene_output_set_position(output->scene_output, output->lx, output->ly);
|
||||
|
||||
// disable all workspaces to get to a known state
|
||||
for (int j = 0; j < output->current.workspaces->length; j++) {
|
||||
struct sway_workspace *workspace = output->current.workspaces->items[j];
|
||||
disable_workspace(workspace);
|
||||
}
|
||||
|
||||
// arrange the active workspace
|
||||
if (ws) {
|
||||
arrange_workspace_floating(ws);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/types/wlr_xdg_shell.h>
|
||||
#include <wlr/types/wlr_xdg_toplevel_tag_v1.h>
|
||||
#include <wlr/util/edges.h>
|
||||
#include "log.h"
|
||||
#include "sway/decoration.h"
|
||||
|
|
@ -20,13 +21,13 @@
|
|||
|
||||
static struct sway_xdg_popup *popup_create(
|
||||
struct wlr_xdg_popup *wlr_popup, struct sway_view *view,
|
||||
struct wlr_scene_tree *parent);
|
||||
struct wlr_scene_tree *parent, struct wlr_scene_tree *image_capture_parent);
|
||||
|
||||
static void popup_handle_new_popup(struct wl_listener *listener, void *data) {
|
||||
struct sway_xdg_popup *popup =
|
||||
wl_container_of(listener, popup, new_popup);
|
||||
struct wlr_xdg_popup *wlr_popup = data;
|
||||
popup_create(wlr_popup, popup->view, popup->xdg_surface_tree);
|
||||
popup_create(wlr_popup, popup->view, popup->xdg_surface_tree, popup->image_capture_tree);
|
||||
}
|
||||
|
||||
static void popup_handle_destroy(struct wl_listener *listener, void *data) {
|
||||
|
|
@ -77,7 +78,8 @@ static void popup_handle_reposition(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
|
||||
static struct sway_xdg_popup *popup_create(struct wlr_xdg_popup *wlr_popup,
|
||||
struct sway_view *view, struct wlr_scene_tree *parent) {
|
||||
struct sway_view *view, struct wlr_scene_tree *parent,
|
||||
struct wlr_scene_tree *image_capture_parent) {
|
||||
struct wlr_xdg_surface *xdg_surface = wlr_popup->base;
|
||||
|
||||
struct sway_xdg_popup *popup = calloc(1, sizeof(struct sway_xdg_popup));
|
||||
|
|
@ -113,6 +115,11 @@ static struct sway_xdg_popup *popup_create(struct wlr_xdg_popup *wlr_popup,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
popup->image_capture_tree = wlr_scene_xdg_surface_create(image_capture_parent, xdg_surface);
|
||||
if (popup->image_capture_tree == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
popup->wlr_xdg_popup = xdg_surface->popup;
|
||||
struct sway_xdg_shell_view *shell_view =
|
||||
wl_container_of(view, shell_view, view);
|
||||
|
|
@ -151,7 +158,8 @@ static void get_constraints(struct sway_view *view, double *min_width,
|
|||
|
||||
static const char *get_string_prop(struct sway_view *view,
|
||||
enum sway_view_prop prop) {
|
||||
if (xdg_shell_view_from_view(view) == NULL) {
|
||||
struct sway_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view);
|
||||
if (xdg_shell_view == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
switch (prop) {
|
||||
|
|
@ -159,6 +167,8 @@ static const char *get_string_prop(struct sway_view *view,
|
|||
return view->wlr_xdg_toplevel->title;
|
||||
case VIEW_PROP_APP_ID:
|
||||
return view->wlr_xdg_toplevel->app_id;
|
||||
case VIEW_PROP_TAG:
|
||||
return xdg_shell_view->tag;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -259,6 +269,7 @@ static void destroy(struct sway_view *view) {
|
|||
if (xdg_shell_view == NULL) {
|
||||
return;
|
||||
}
|
||||
free(xdg_shell_view->tag);
|
||||
free(xdg_shell_view);
|
||||
}
|
||||
|
||||
|
|
@ -290,7 +301,7 @@ static void handle_commit(struct wl_listener *listener, void *data) {
|
|||
// XXX: https://github.com/swaywm/sway/issues/2176
|
||||
wlr_xdg_surface_schedule_configure(xdg_surface);
|
||||
wlr_xdg_toplevel_set_wm_capabilities(view->wlr_xdg_toplevel,
|
||||
XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
|
||||
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
|
||||
// TODO: wlr_xdg_toplevel_set_bounds()
|
||||
return;
|
||||
}
|
||||
|
|
@ -299,18 +310,17 @@ static void handle_commit(struct wl_listener *listener, void *data) {
|
|||
return;
|
||||
}
|
||||
|
||||
struct wlr_box new_geo;
|
||||
wlr_xdg_surface_get_geometry(xdg_surface, &new_geo);
|
||||
bool new_size = new_geo.width != view->geometry.width ||
|
||||
new_geo.height != view->geometry.height ||
|
||||
new_geo.x != view->geometry.x ||
|
||||
new_geo.y != view->geometry.y;
|
||||
struct wlr_box *new_geo = &xdg_surface->geometry;
|
||||
bool new_size = new_geo->width != view->geometry.width ||
|
||||
new_geo->height != view->geometry.height ||
|
||||
new_geo->x != view->geometry.x ||
|
||||
new_geo->y != view->geometry.y;
|
||||
|
||||
if (new_size) {
|
||||
// The client changed its surface size in this commit. For floating
|
||||
// containers, we resize the container to match. For tiling containers,
|
||||
// we only recenter the surface.
|
||||
memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box));
|
||||
memcpy(&view->geometry, new_geo, sizeof(struct wlr_box));
|
||||
if (container_is_floating(view->container)) {
|
||||
view_update_size(view);
|
||||
// Only set the toplevel size the current container actually has a size.
|
||||
|
|
@ -360,7 +370,7 @@ static void handle_new_popup(struct wl_listener *listener, void *data) {
|
|||
struct wlr_xdg_popup *wlr_popup = data;
|
||||
|
||||
struct sway_xdg_popup *popup = popup_create(wlr_popup,
|
||||
&xdg_shell_view->view, root->layers.popup);
|
||||
&xdg_shell_view->view, root->layers.popup, xdg_shell_view->image_capture_tree);
|
||||
if (!popup) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -463,12 +473,8 @@ static void handle_map(struct wl_listener *listener, void *data) {
|
|||
struct sway_view *view = &xdg_shell_view->view;
|
||||
struct wlr_xdg_toplevel *toplevel = view->wlr_xdg_toplevel;
|
||||
|
||||
view->natural_width = toplevel->base->current.geometry.width;
|
||||
view->natural_height = toplevel->base->current.geometry.height;
|
||||
if (!view->natural_width && !view->natural_height) {
|
||||
view->natural_width = toplevel->base->surface->current.width;
|
||||
view->natural_height = toplevel->base->surface->current.height;
|
||||
}
|
||||
view->natural_width = toplevel->base->geometry.width;
|
||||
view->natural_height = toplevel->base->geometry.height;
|
||||
|
||||
bool csd = false;
|
||||
|
||||
|
|
@ -575,6 +581,17 @@ void handle_xdg_shell_toplevel(struct wl_listener *listener, void *data) {
|
|||
wl_signal_add(&xdg_toplevel->events.destroy, &xdg_shell_view->destroy);
|
||||
|
||||
wlr_scene_xdg_surface_create(xdg_shell_view->view.content_tree, xdg_toplevel->base);
|
||||
xdg_shell_view->image_capture_tree =
|
||||
wlr_scene_xdg_surface_create(&xdg_shell_view->view.image_capture_scene->tree, xdg_toplevel->base);
|
||||
|
||||
xdg_toplevel->base->data = xdg_shell_view;
|
||||
}
|
||||
|
||||
void xdg_toplevel_tag_manager_v1_handle_set_tag(struct wl_listener *listener, void *data) {
|
||||
const struct wlr_xdg_toplevel_tag_manager_v1_set_tag_event *event = data;
|
||||
struct sway_view *view = view_from_wlr_xdg_surface(event->toplevel->base);
|
||||
struct sway_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view);
|
||||
free(xdg_shell_view->tag);
|
||||
xdg_shell_view->tag = strdup(event->tag);
|
||||
view_execute_criteria(view);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ static void unmanaged_handle_map(struct wl_listener *listener, void *data) {
|
|||
surface->set_geometry.notify = unmanaged_handle_set_geometry;
|
||||
}
|
||||
|
||||
if (wlr_xwayland_or_surface_wants_focus(xsurface)) {
|
||||
if (wlr_xwayland_surface_override_redirect_wants_focus(xsurface)) {
|
||||
struct sway_seat *seat = input_manager_current_seat();
|
||||
struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland;
|
||||
wlr_xwayland_set_seat(xwayland, seat->wlr_seat);
|
||||
|
|
@ -96,7 +96,7 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) {
|
|||
// This simply returns focus to the parent surface if there's one available.
|
||||
// This seems to handle JetBrains issues.
|
||||
if (xsurface->parent && xsurface->parent->surface
|
||||
&& wlr_xwayland_or_surface_wants_focus(xsurface->parent)) {
|
||||
&& wlr_xwayland_surface_override_redirect_wants_focus(xsurface->parent)) {
|
||||
seat_set_focus_surface(seat, xsurface->parent->surface, false);
|
||||
return;
|
||||
}
|
||||
|
|
@ -289,7 +289,6 @@ static void set_activated(struct sway_view *view, bool activated) {
|
|||
}
|
||||
|
||||
wlr_xwayland_surface_activate(surface, activated);
|
||||
wlr_xwayland_surface_restack(surface, NULL, XCB_STACK_MODE_ABOVE);
|
||||
}
|
||||
|
||||
static void set_tiled(struct sway_view *view, bool tiled) {
|
||||
|
|
@ -297,7 +296,7 @@ static void set_tiled(struct sway_view *view, bool tiled) {
|
|||
return;
|
||||
}
|
||||
struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface;
|
||||
wlr_xwayland_surface_set_maximized(surface, tiled);
|
||||
wlr_xwayland_surface_set_maximized(surface, tiled, tiled);
|
||||
}
|
||||
|
||||
static void set_fullscreen(struct sway_view *view, bool fullscreen) {
|
||||
|
|
@ -498,6 +497,9 @@ static void handle_unmap(struct wl_listener *listener, void *data) {
|
|||
wl_list_remove(&xwayland_view->commit.link);
|
||||
wl_list_remove(&xwayland_view->surface_tree_destroy.link);
|
||||
|
||||
wlr_scene_node_destroy(&xwayland_view->image_capture_scene_surface->buffer->node);
|
||||
xwayland_view->image_capture_scene_surface = NULL;
|
||||
|
||||
if (xwayland_view->surface_tree) {
|
||||
wlr_scene_node_destroy(&xwayland_view->surface_tree->node);
|
||||
xwayland_view->surface_tree = NULL;
|
||||
|
|
@ -538,6 +540,9 @@ static void handle_map(struct wl_listener *listener, void *data) {
|
|||
&xwayland_view->surface_tree_destroy);
|
||||
}
|
||||
|
||||
xwayland_view->image_capture_scene_surface =
|
||||
wlr_scene_surface_create(&xwayland_view->view.image_capture_scene->tree, xsurface->surface);
|
||||
|
||||
transaction_commit_dirty();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,12 +32,6 @@
|
|||
#include "sway/tree/workspace.h"
|
||||
#include "wlr-layer-shell-unstable-v1-protocol.h"
|
||||
|
||||
static uint32_t get_current_time_msec(void) {
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
return now.tv_sec * 1000 + now.tv_nsec / 1000000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node at the cursor's position. If there is a surface at that
|
||||
* location, it is stored in **surface (it may not be a view).
|
||||
|
|
@ -144,7 +138,7 @@ struct sway_node *node_at_coords(
|
|||
}
|
||||
|
||||
void cursor_rebase(struct sway_cursor *cursor) {
|
||||
uint32_t time_msec = get_current_time_msec();
|
||||
uint32_t time_msec = get_current_time_in_msec();
|
||||
seatop_rebase(cursor->seat, time_msec);
|
||||
}
|
||||
|
||||
|
|
@ -359,7 +353,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
|
|||
struct wlr_input_device *device, uint32_t time_msec, uint32_t button,
|
||||
enum wl_pointer_button_state state) {
|
||||
if (time_msec == 0) {
|
||||
time_msec = get_current_time_msec();
|
||||
time_msec = get_current_time_in_msec();
|
||||
}
|
||||
|
||||
seatop_button(cursor->seat, time_msec, device, button, state);
|
||||
|
|
@ -578,12 +572,13 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor,
|
|||
// tablet events until the drag is released, even if we are now over a
|
||||
// non-tablet surface.
|
||||
if (!cursor->simulating_pointer_from_tool_tip &&
|
||||
((surface && wlr_surface_accepts_tablet_v2(tablet->tablet_v2, surface)) ||
|
||||
((surface && wlr_surface_accepts_tablet_v2(surface, tablet->tablet_v2)) ||
|
||||
wlr_tablet_tool_v2_has_implicit_grab(tool->tablet_v2_tool))) {
|
||||
seatop_tablet_tool_motion(seat, tool, time_msec);
|
||||
} else {
|
||||
wlr_tablet_v2_tablet_tool_notify_proximity_out(tool->tablet_v2_tool);
|
||||
pointer_motion(cursor, time_msec, input_device->wlr_device, dx, dy, dx, dy);
|
||||
wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -664,7 +659,7 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) {
|
|||
dispatch_cursor_button(cursor, &event->tablet->base, event->time_msec,
|
||||
BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
|
||||
wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
|
||||
} else if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) {
|
||||
} else if (!surface || !wlr_surface_accepts_tablet_v2(surface, tablet_v2)) {
|
||||
// If we started holding the tool tip down on a surface that accepts
|
||||
// tablet v2, we should notify that surface if it gets released over a
|
||||
// surface that doesn't support v2.
|
||||
|
|
@ -749,7 +744,7 @@ static void handle_tool_button(struct wl_listener *listener, void *data) {
|
|||
bool mod_pressed = modifiers & config->floating_mod;
|
||||
|
||||
bool surface_supports_tablet_events =
|
||||
surface && wlr_surface_accepts_tablet_v2(tablet_v2, surface);
|
||||
surface && wlr_surface_accepts_tablet_v2(surface, tablet_v2);
|
||||
|
||||
// Simulate pointer when:
|
||||
// 1. The modifier key is pressed, OR
|
||||
|
|
@ -1047,6 +1042,7 @@ void sway_cursor_destroy(struct sway_cursor *cursor) {
|
|||
wl_list_remove(&cursor->touch_frame.link);
|
||||
wl_list_remove(&cursor->tool_axis.link);
|
||||
wl_list_remove(&cursor->tool_tip.link);
|
||||
wl_list_remove(&cursor->tool_proximity.link);
|
||||
wl_list_remove(&cursor->tool_button.link);
|
||||
wl_list_remove(&cursor->request_set_cursor.link);
|
||||
|
||||
|
|
@ -1212,7 +1208,7 @@ uint32_t get_mouse_bindsym(const char *name, char **error) {
|
|||
SWAY_SCROLL_UP, SWAY_SCROLL_DOWN, SWAY_SCROLL_LEFT,
|
||||
SWAY_SCROLL_RIGHT, BTN_SIDE, BTN_EXTRA};
|
||||
return buttons[number - 1];
|
||||
} else if (strncmp(name, "BTN_", strlen("BTN_")) == 0) {
|
||||
} else if (has_prefix(name, "BTN_")) {
|
||||
// Get event code from name
|
||||
int code = libevdev_event_code_from_name(EV_KEY, name);
|
||||
if (code == -1) {
|
||||
|
|
@ -1237,7 +1233,7 @@ uint32_t get_mouse_bindcode(const char *name, char **error) {
|
|||
return 0;
|
||||
}
|
||||
const char *event = libevdev_event_code_get_name(EV_KEY, code);
|
||||
if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) {
|
||||
if (!event || !has_prefix(event, "BTN_")) {
|
||||
*error = format_str("Event code %d (%s) is not a button",
|
||||
code, event ? event : "(null)");
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include <wlr/config.h>
|
||||
#include <wlr/backend/libinput.h>
|
||||
#include <wlr/types/wlr_cursor.h>
|
||||
#include <wlr/types/wlr_keyboard_group.h>
|
||||
#include <wlr/types/wlr_virtual_keyboard_v1.h>
|
||||
|
|
@ -494,6 +493,14 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) {
|
|||
return input;
|
||||
}
|
||||
|
||||
void input_manager_finish(struct sway_input_manager *input) {
|
||||
wl_list_remove(&input->new_input.link);
|
||||
wl_list_remove(&input->virtual_keyboard_new.link);
|
||||
wl_list_remove(&input->virtual_pointer_new.link);
|
||||
wl_list_remove(&input->keyboard_shortcuts_inhibit_new_inhibitor.link);
|
||||
wl_list_remove(&input->transient_seat_create.link);
|
||||
}
|
||||
|
||||
bool input_manager_has_focus(struct sway_node *node) {
|
||||
struct sway_seat *seat = NULL;
|
||||
wl_list_for_each(seat, &server.input->seats, link) {
|
||||
|
|
@ -578,7 +585,7 @@ void input_manager_configure_all_input_mappings(void) {
|
|||
void input_manager_apply_input_config(struct input_config *input_config) {
|
||||
struct sway_input_device *input_device = NULL;
|
||||
bool wildcard = strcmp(input_config->identifier, "*") == 0;
|
||||
bool type_wildcard = strncmp(input_config->identifier, "type:", 5) == 0;
|
||||
bool type_wildcard = has_prefix(input_config->identifier, "type:");
|
||||
wl_list_for_each(input_device, &server.input->devices, link) {
|
||||
bool type_matches = type_wildcard &&
|
||||
strcmp(input_device_get_type(input_device), input_config->identifier + 5) == 0;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <wlr/config.h>
|
||||
#include <wlr/backend/multi.h>
|
||||
#include <wlr/interfaces/wlr_keyboard.h>
|
||||
#include <wlr/types/wlr_cursor.h>
|
||||
#include <wlr/types/wlr_keyboard.h>
|
||||
#include <wlr/types/wlr_keyboard_group.h>
|
||||
#include <xkbcommon/xkbcommon-names.h>
|
||||
|
|
@ -267,6 +268,7 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard,
|
|||
const xkb_keysym_t *pressed_keysyms, uint32_t modifiers, size_t keysyms_len) {
|
||||
for (size_t i = 0; i < keysyms_len; ++i) {
|
||||
xkb_keysym_t keysym = pressed_keysyms[i];
|
||||
|
||||
if (keysym >= XKB_KEY_XF86Switch_VT_1 &&
|
||||
keysym <= XKB_KEY_XF86Switch_VT_12) {
|
||||
#if WLR_HAS_SESSION
|
||||
|
|
@ -282,6 +284,36 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard,
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool keyboard_execute_pointer_keysyms(struct sway_keyboard *keyboard,
|
||||
uint32_t time, const xkb_keysym_t *pressed_keysyms, size_t keysyms_len,
|
||||
enum wl_keyboard_key_state state) {
|
||||
struct sway_cursor *cursor = keyboard->seat_device->sway_seat->cursor;
|
||||
|
||||
for (size_t i = 0; i < keysyms_len; ++i) {
|
||||
xkb_keysym_t keysym = pressed_keysyms[i];
|
||||
|
||||
uint32_t button = wlr_keyboard_keysym_to_pointer_button(keysym);
|
||||
if (button != 0) {
|
||||
dispatch_cursor_button(cursor, &keyboard->wlr->base, time, button,
|
||||
(enum wl_pointer_button_state)state);
|
||||
wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
|
||||
return true;
|
||||
}
|
||||
|
||||
int dx, dy;
|
||||
wlr_keyboard_keysym_to_pointer_motion(keysym, &dx, &dy);
|
||||
if (state == WL_KEYBOARD_KEY_STATE_PRESSED && (dx != 0 || dy != 0)) {
|
||||
dx *= 10;
|
||||
dy *= 10;
|
||||
pointer_motion(cursor, time, &keyboard->wlr->base, dx, dy, dx, dy);
|
||||
wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get keysyms and modifiers from the keyboard as xkb sees them.
|
||||
*
|
||||
|
|
@ -507,6 +539,11 @@ static void handle_key_event(struct sway_keyboard *keyboard,
|
|||
keyboard, keyinfo.raw_keysyms, keyinfo.raw_modifiers,
|
||||
keyinfo.raw_keysyms_len);
|
||||
}
|
||||
if (!handled) {
|
||||
handled = keyboard_execute_pointer_keysyms(keyboard, event->time_msec,
|
||||
keyinfo.translated_keysyms, keyinfo.translated_keysyms_len,
|
||||
event->state);
|
||||
}
|
||||
|
||||
if (event->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
|
||||
// If the pressed event was sent to a client and we have a focused
|
||||
|
|
@ -1028,13 +1065,6 @@ static void sway_keyboard_set_layout(struct sway_keyboard *keyboard,
|
|||
}
|
||||
}
|
||||
|
||||
// If the seat has no active keyboard, set this one
|
||||
struct wlr_seat *seat = keyboard->seat_device->sway_seat->wlr_seat;
|
||||
struct wlr_keyboard *current_keyboard = seat->keyboard_state.keyboard;
|
||||
if (current_keyboard == NULL) {
|
||||
wlr_seat_set_keyboard(seat, keyboard->wlr);
|
||||
}
|
||||
|
||||
if (keymap_changed) {
|
||||
ipc_event_input("xkb_keymap",
|
||||
keyboard->seat_device->input_device);
|
||||
|
|
@ -1078,6 +1108,13 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) {
|
|||
sway_keyboard_set_layout(keyboard, input_config);
|
||||
}
|
||||
|
||||
// If the seat has no active keyboard, set this one
|
||||
struct wlr_seat *seat = keyboard->seat_device->sway_seat->wlr_seat;
|
||||
struct wlr_keyboard *current_keyboard = seat->keyboard_state.keyboard;
|
||||
if (current_keyboard == NULL) {
|
||||
wlr_seat_set_keyboard(seat, keyboard->wlr);
|
||||
}
|
||||
|
||||
wl_list_remove(&keyboard->keyboard_key.link);
|
||||
wl_signal_add(&keyboard->wlr->events.key, &keyboard->keyboard_key);
|
||||
keyboard->keyboard_key.notify = handle_keyboard_key;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue