mirror of
https://github.com/swaywm/sway.git
synced 2024-11-27 18:31:28 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
c6066ac7e4
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -6,6 +6,7 @@ bin/
|
|||
test/
|
||||
build/
|
||||
build-*/
|
||||
.cache/
|
||||
.lvimrc
|
||||
config-debug
|
||||
wayland-*-protocol.*
|
||||
|
|
91
README.ar.md
Normal file
91
README.ar.md
Normal file
|
@ -0,0 +1,91 @@
|
|||
# sway
|
||||
|
||||
sway
|
||||
|
||||
هو مدير للمجموعات المركبة لـ[Wayland] متوافق مع [i3] -
|
||||
|
||||
إقرأ [الأسئلة الشائعة](https://github.com/swaywm/sway/wiki)
|
||||
|
||||
انضم الى [قناة IRC](https://web.libera.chat/gamja/?channels=#sway)
|
||||
|
||||
|
||||
## تواقيع الإصدار
|
||||
تٌوقع الإصدارات بـواسطة [E88F5E48] و تُنشر على [GitHub](https://github.com/swaywm/sway/releases)
|
||||
|
||||
## التثبيت
|
||||
|
||||
### بإستخدام الحزم
|
||||
|
||||
يتوفر Sway للعديد من التوزيعات، حاول تثبيت حزمة "sway" لتوزيعتك
|
||||
### التجميع من المصدر
|
||||
إطلع على [صفحة الويكي هذه](https://github.com/swaywm/sway/wiki/Development-Setup) إذا أردت بناء الـHEAD من sway و wlroots لأغراض الفحص والتطوير
|
||||
|
||||
تثبيت اللوازم:
|
||||
* meson \*
|
||||
* [wlroots]
|
||||
* wayland
|
||||
* wayland-protocols \*
|
||||
* pcre2
|
||||
* json-c
|
||||
* pango
|
||||
* cairo
|
||||
* gdk-pixbuf2 (optional: system tray)
|
||||
* [scdoc] (optional: man pages) \*
|
||||
* git (optional: version info) \*
|
||||
|
||||
_\* Compile-time dep_
|
||||
|
||||
نفذ هذه الأوامر:
|
||||
|
||||
meson build/
|
||||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
## الإعدادات
|
||||
|
||||
إذا كنت بالفعل تستخدم i3، فعليك نسخ إعدادات i3 لديك إلى `~/.config/sway/config` وسوف تعمل تلقائياً.
|
||||
|
||||
و إلا عليك نسخ ملف الإعدادات النموذج إلى `config/sway/config` الموجود عادةً في `/etc/sway/config.`
|
||||
|
||||
|
||||
## التشغيل
|
||||
|
||||
شغل `sway` بإستخدام أمر TTY.
|
||||
قد يعمل بعض مدراء العرض مع أنهم غير مدعومون من sway
|
||||
(gdm مثلاً يعمل بشكل جيد إلى حد ما)
|
||||
|
||||
[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
|
||||
[ge]: README.ge.md
|
||||
[gr]: README.gr.md
|
||||
[hi]: README.hi.md
|
||||
[hu]: README.hu.md
|
||||
[ir]: README.ir.md
|
||||
[it]: README.it.md
|
||||
[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
|
||||
[zh-TW]: README.zh-TW.md
|
||||
[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
|
||||
[scdoc]: https://git.sr.ht/~sircmpwn/scdoc
|
|
@ -43,12 +43,6 @@ Spusťte tyto příkazy:
|
|||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
Na systémech bez logind či seatd musíte binární soubor sway nastavit jako suid:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
Sway svá root oprávnění zruší krátce po spuštění.
|
||||
|
||||
## Konfigurace
|
||||
|
||||
Pokud již používáte i3, zkopírujte svou konfiguraci i3 do `~/.config/sway/config`
|
||||
|
|
18
README.de.md
18
README.de.md
|
@ -5,13 +5,13 @@
|
|||
Sway ist ein [i3](https://i3wm.org/)-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] signiert und auf GitHub veröffentlicht.
|
||||
Jedes Release wird mit dem PGP-Schlüssel [E88F5E48] signiert und auf GitHub veröffentlicht signiert und [auf GitHub][GitHub releases] veröffentlicht..
|
||||
|
||||
## Installation
|
||||
### Mit der Paketverwaltung
|
||||
Sway kann in vielen Distributionen direkt durch die Paketverwaltung installiert werden. Das Paket sollte "sway" heißen. Falls es kein solches Paket gibt, kannst du im [Wiki](https://github.com/swaywm/sway/wiki/Unsupported-packages) (englisch) nach mehr Informationen bezüglich deiner Distribution suchen.
|
||||
|
||||
Falls du sway für deine eigene Distribution als Paket bereitstellen möchtest, solltest du die Entwickler per IRC oder E-Mail (sir@cmpwn.com) kontaktieren.
|
||||
### Über die Paketverwaltung
|
||||
|
||||
Sway kann in vielen Distributionen direkt durch die Paketverwaltung installiert werden. Versuche einfach das Packet "sway" zu installieren.
|
||||
|
||||
### Quellcode selbst kompilieren
|
||||
|
||||
|
@ -26,8 +26,8 @@ sway benötigt die folgenden Pakete:
|
|||
* pango
|
||||
* cairo
|
||||
* gdk-pixbuf2 (Optional, wird für das Benachrichtigungsfeld (System Tray) benötigt)
|
||||
* [scdoc]\* (Optional, wird für die Dokumentation (Man Pages) benötigt)
|
||||
* git\*
|
||||
* [scdoc] (Optional, wird für die Dokumentation (Man Pages) benötigt)\*
|
||||
* git (Optional: Versionsinfo)\*
|
||||
|
||||
_\*Werden nur während des Kompilierens benötigt_
|
||||
|
||||
|
@ -37,12 +37,6 @@ Führe die folgenden Befehle aus:
|
|||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
Falls dein System nicht logind benutzt, musst du sway noch die passenden Berechtigungen geben:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
Sway läuft nur in der Startphase mit Root-Rechten.
|
||||
|
||||
## 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`.
|
||||
|
|
|
@ -47,12 +47,6 @@ Kør følgende kommandoer:
|
|||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
På systemer uden logind eller seatd skal du sætte SUID bit på sway filen:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
Sway dropper 'root' tilladelser kort efter opstart.
|
||||
|
||||
## Konfiguration
|
||||
|
||||
Hvis du allerede bruger i3 kan du bare kopiere din i3 konfiguration til
|
||||
|
|
|
@ -46,12 +46,6 @@ Desde su consola, ejecute las órdenes:
|
|||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
En sistemas sin `logind`, necesitará cambiar los permisos del archivo compilado de sway:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
Sway abandonará los permisos de super-usuario al poco de arrancar.
|
||||
|
||||
## Configuración
|
||||
|
||||
Si ya utiliza i3, copie su archivo de configuración de i3 a `~/.config/sway/config` y
|
||||
|
|
|
@ -53,12 +53,6 @@ Exécutez ces commandes :
|
|||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
Sur les systèmes sans logind, vous devez suid le binaire de sway :
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
Sway se débarassera des permissions *root* peu de temps après le démarrage.
|
||||
|
||||
## Configuration
|
||||
|
||||
Si vous utilisez déjà i3, copiez votre configuration i3 vers
|
||||
|
|
61
README.ge.md
Normal file
61
README.ge.md
Normal file
|
@ -0,0 +1,61 @@
|
|||
# sway
|
||||
|
||||
sway არის [i3]-თავსებადი [Wayland]-ის კომპოზიტორი. მეტი ინფორმაციისთვის იხილეთ
|
||||
[FAQ]. დაუკავშირდით [IRC არხს][IRC channel] \(#sway irc.libera.chat-ზე).
|
||||
|
||||
## გამოშვების ხელმოწერები
|
||||
|
||||
გამოშვებები ხელმოწერილია [E88F5E48]-ით და გამოქვეყნებულია [GitHub-ზე][GitHub releases].
|
||||
|
||||
## ინსტალაცია
|
||||
|
||||
### რეპოზიტორიიდან
|
||||
|
||||
Sway არის ხელმისაწვდომი ბევრი დისტრიბუტაციისთვის. ცადეთ "sway" პაკეტის ინსტალაცია თქვენთვის.
|
||||
|
||||
### კოდის კომპილაცია
|
||||
|
||||
იხილეთ [ეს ვიკი გვერდი][Development setup] თუ გინდათ რომ ააწყოთ sway და wlroots სატესტოდ ან დეველოპმენტისთვის.
|
||||
|
||||
დააინსტალირეთ დამოკიდებულებები:
|
||||
|
||||
* meson \*
|
||||
* [wlroots]
|
||||
* wayland
|
||||
* wayland-protocols \*
|
||||
* pcre2
|
||||
* json-c
|
||||
* pango
|
||||
* cairo
|
||||
* gdk-pixbuf2 (ასევე არჩევითია: system tray)
|
||||
* [scdoc] (ასევე არჩევითია: man pages) \*
|
||||
* git (ასევე არჩევითია: version info) \*
|
||||
|
||||
_\* Compile-time dep_
|
||||
|
||||
გაუშვით ეს ბრძანებები:
|
||||
|
||||
meson 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-ისთვის. ზოგიერთმა ლოგინ მენეჯერმა შეიძლება იმუშავოს, მაგრამ არ
|
||||
არის მხარდაჭერილი sway-სგან (როგორც წესი კარგად მუშაობს gdm).
|
||||
|
||||
[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
|
||||
[scdoc]: https://git.sr.ht/~sircmpwn/scdoc
|
|
@ -46,12 +46,6 @@ _\*Compile-time dep_
|
|||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
Σε συστήματα χωρίς logind ή seatd, πρέπει να κάνετε suid το sway binary:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
Το Sway θα κάνει drop root δικαιώματα λίγο μετά την εκκίνηση.
|
||||
|
||||
## Configuration
|
||||
|
||||
Εάν ήδη χρησιμοποιήτε το i3, αντιγράψτε το i3 config σας στο `~/.config/sway/config` και
|
||||
|
|
|
@ -50,13 +50,6 @@ _\* Compilation के समय आवश्यक_
|
|||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
उन systems पर जिनमें ना तो logind है, ना ही seatd है, आपको sway की binary
|
||||
को suid करना पडेगा:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
Sway अपनी root अनुमतियां प्रारंभ होने के कुछ ही देर बाद छोड़ देगी।
|
||||
|
||||
## Configuration
|
||||
|
||||
अगर आप पहले से ही i3 का उपयोग करते हैं तो अपने i3 config को
|
||||
|
|
|
@ -46,13 +46,6 @@ Futtasd ezeket a parancsokat:
|
|||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
Ha `logind` nélküli rendszert használsz, akkor be kell állítanod a `suid` bitet
|
||||
a futtaható állományon:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
A Sway indulás után nem sokkal el fogja engedni a root jogosultságait.
|
||||
|
||||
## Konfiguráció
|
||||
|
||||
Ha előzőleg i3-mat használtál, akkor átmásolhatod az i3 beállításaidat a
|
||||
|
|
|
@ -47,12 +47,6 @@ _\*نیازمندیهای زمان کامپایل برنامه_
|
|||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
روی سیستمهای بدون logind، باید فرمان زیر را برای suid کردن باینری sway اجرا کنید:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
‏sway پس از startup مجوزهای دسترسی root را رها میکند.
|
||||
|
||||
### شخصی سازی و تنظیمات
|
||||
|
||||
اگر در حال حاضر از i3 استفاده میکنید، تنظیمات i3 خودتان را در فایل `~/.config/sway/config` کپی کنید و بدون نیاز به تغییر کار خواهد کرد. در غیر اینصورت، فایل نمونه تنظیمات را استفاده کنید. این فایل عموما در `/etc/sway/config` قرار دارد. برای آگاهی بیشتر `man 5 sway` را اجرا کنید.
|
||||
|
|
|
@ -44,13 +44,6 @@ Esegui questi comandi:
|
|||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
Nei sistemi in cui non sono disponibili né logind né seatd, è necessario
|
||||
impostare il permesso suid al binario di sway:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
Sway rinuncerà ai permessi di root poco dopo l'avvio.
|
||||
|
||||
## Configurazione
|
||||
|
||||
Se hai già usato i3, copia il tuo file di configurazione in
|
||||
|
|
|
@ -45,12 +45,6 @@ _\*컴파일 떄 필요_
|
|||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
logind를 사용하고 있지 않는 시스템에서는, 바이너리에 suid를 설정할 필요가 있습니다:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
Sway는 시작 후에 root 권한을 drop할 것 입니다.
|
||||
|
||||
## 설정
|
||||
|
||||
i3를 이미 사용 중이라면, i3 config을 `~/.config/sway/config`로 복사하세요.
|
||||
|
|
10
README.md
10
README.md
|
@ -1,6 +1,6 @@
|
|||
# sway
|
||||
|
||||
**[English][en]** - [Česky][cs] - [Deutsch][de] - [Dansk][dk] - [Español][es] - [Français][fr] - [Ελληνικά][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] - [Č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]
|
||||
|
||||
sway is an [i3]-compatible [Wayland] compositor. Read the [FAQ]. Join the
|
||||
[IRC channel] \(#sway on irc.libera.chat).
|
||||
|
@ -43,12 +43,6 @@ Run these commands:
|
|||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
On systems without logind nor seatd, you need to suid the sway binary:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
Sway will drop root permissions shortly after startup.
|
||||
|
||||
## Configuration
|
||||
|
||||
If you already use i3, then copy your i3 config to `~/.config/sway/config` and
|
||||
|
@ -62,11 +56,13 @@ Run `sway` from a TTY. Some display managers may work but are not supported by
|
|||
sway (gdm is known to work fairly well).
|
||||
|
||||
[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
|
||||
[ge]: README.ge.md
|
||||
[gr]: README.gr.md
|
||||
[hi]: README.hi.md
|
||||
[hu]: README.hu.md
|
||||
|
|
|
@ -46,12 +46,6 @@ Voer deze opdrachten uit:
|
|||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
Op systemen zonder logind, moet je bij het binaire bestand het suid bit instellen:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
Sway zal root-rechten kort na het opstarten loslaten.
|
||||
|
||||
## Configuratie
|
||||
|
||||
Als je al i3 gebruikt, kopieer dan je i3-configuratie naar `~/.config/sway/config` en
|
||||
|
|
|
@ -46,12 +46,6 @@ Wykonaj następujące polecenia:
|
|||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
Na systemach bez logind należy wykonać polecenie suid na pliku wykonywalnym sway:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
Sway pozbędzie się uprawnień roota tuż po wystartowaniu.
|
||||
|
||||
## Konfiguracja
|
||||
|
||||
Jeśli już korzystasz z i3, skopiuj swoją konfigurację i3 do katalogu `~/.config/sway/config` i
|
||||
|
|
|
@ -48,12 +48,6 @@ Execute esses comandos:
|
|||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
Em sistemas sem logind, você precisa preparar o binário do sway:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
O sway perderá as privilégios de de root logo após o início do sistema.
|
||||
|
||||
## Configuração
|
||||
|
||||
Se você já utiliza o i3, então copie os seus arquivos de configuração para `~/.config/sway/config` e
|
||||
|
|
|
@ -45,14 +45,6 @@ Rulați aceste comenzi:
|
|||
sudo ninja -C build install
|
||||
```
|
||||
|
||||
Pe sisteme fără logind, trebuie să folosiți următoarea comandă pentru a marca binarul de Sway ca suid:
|
||||
|
||||
```
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
```
|
||||
|
||||
Imediat după pornire, Sway va renunța la permisiunile de root.
|
||||
|
||||
## Configurare
|
||||
|
||||
Dacă folosiți deja i3, copiați fișierul de configurare din i3 în `~/.config/sway/config`, și va funcționa fără a necesita nici o modificare. In caz contrar, copiați exemplul de configurare (disponibil de obicei în `/etc/sway/config`) în `~/.config/sway/config`.
|
||||
|
|
|
@ -47,12 +47,6 @@ _\*Зависимости для сборки_
|
|||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
На системах без logind вам понадобится добавить suid к файлу программы sway:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
sway сбросит root-права при запуске.
|
||||
|
||||
## Настройка
|
||||
|
||||
Если вы уже используете i3, скопируйте ваш конфигурационный файл i3 в `~/.config/sway/config`, и
|
||||
|
|
|
@ -41,12 +41,6 @@ Kör dessa kommandon:
|
|||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
På system utan logind eller seatd måste du ge sways exekverbara fil root-privilegier:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
Sway kommer att överge sina root-privilegier kort efter uppstart.
|
||||
|
||||
## Konfiguration
|
||||
|
||||
Ifall du redan använder i3 så kan du kopiera din konfigurationsfil till `~/.config/sway/config` och det kommer då att fungera som det ska.
|
||||
|
|
|
@ -43,12 +43,6 @@ _\*Derleme-anı bağımlılıkları_
|
|||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
logind olmayan sistemlerde, sway ikilisine (binary) izin vermeniz (suid) gerekir:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
Sway, başlangıçtan kısa bir süre sonra kök(root) izinlerini bırakacaktır.
|
||||
|
||||
## Yapılandırma
|
||||
|
||||
Zaten i3 kullanıyorsanız, i3 yapılandırmanızı `~/.config/sway/config` konumuna kopyalayın ve kutudan çıktığı gibi çalışacaktır. Aksi takdirde, örnek yapılandırma dosyasını `~/.config/sway/config` konumuna kopyalayın. Genellikle `/etc/sway/config` konumunda bulunur.
|
||||
|
|
|
@ -57,12 +57,6 @@ _\*Лише для компіляції_
|
|||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
На системах без logind, необхідно встановити біт SUID на виконуваний файл sway:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
Sway втратить права доступу root незабаром після запуску.
|
||||
|
||||
## Налаштування
|
||||
|
||||
Якщо ви вже використовуєте i3, скопіюйте свій файл налаштувань
|
||||
|
|
|
@ -41,12 +41,6 @@ _\*编译时依赖_
|
|||
ninja -C build/
|
||||
sudo ninja -C build/ install
|
||||
|
||||
在没有logind或seatd的系统上, 你需要给sway二进制文件设置suid:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
启动后,Sway会尽快放弃root权限。
|
||||
|
||||
## 配置
|
||||
|
||||
如果你已经在使用i3,直接复制i3配置文件到 `~/.config/sway/config`,这是开箱即用的。或者,你可以复制配置样例到`~/.config/sway/config`。它通常位于 `/etc/sway/config`。
|
||||
|
|
|
@ -46,12 +46,6 @@ _\*編譯時相依_
|
|||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
在沒有 logind 的系統上,你需要為 sway 的執行檔加上 suid。
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
Sway 在啟動不久後就會放棄 root 權限。
|
||||
|
||||
## 設定檔
|
||||
|
||||
如果你已經在使用 i3,你可以直接將你的 i3 設定檔複製到 `~/.config/sway/config` 然後就能直接使用。
|
||||
|
|
|
@ -12,23 +12,6 @@
|
|||
|
||||
const uint8_t GESTURE_FINGERS_ANY = 0;
|
||||
|
||||
// Helper to easily allocate and format string
|
||||
static char *strformat(const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int length = vsnprintf(NULL, 0, format, args) + 1;
|
||||
va_end(args);
|
||||
|
||||
char *result = malloc(length);
|
||||
if (result) {
|
||||
va_start(args, format);
|
||||
vsnprintf(result, length, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char *gesture_parse(const char *input, struct gesture *output) {
|
||||
// Clear output in case of failure
|
||||
output->type = GESTURE_TYPE_NONE;
|
||||
|
@ -38,7 +21,7 @@ char *gesture_parse(const char *input, struct gesture *output) {
|
|||
// Split input type, fingers and directions
|
||||
list_t *split = split_string(input, ":");
|
||||
if (split->length < 1 || split->length > 3) {
|
||||
return strformat(
|
||||
return format_str(
|
||||
"expected <gesture>[:<fingers>][:direction], got %s",
|
||||
input);
|
||||
}
|
||||
|
@ -51,8 +34,8 @@ char *gesture_parse(const char *input, struct gesture *output) {
|
|||
} else if (strcmp(split->items[0], "swipe") == 0) {
|
||||
output->type = GESTURE_TYPE_SWIPE;
|
||||
} else {
|
||||
return strformat("expected hold|pinch|swipe, got %s",
|
||||
split->items[0]);
|
||||
return format_str("expected hold|pinch|swipe, got %s",
|
||||
(const char *)split->items[0]);
|
||||
}
|
||||
|
||||
// Parse optional arguments
|
||||
|
@ -67,7 +50,7 @@ char *gesture_parse(const char *input, struct gesture *output) {
|
|||
next = split->length == 3 ? split->items[2] : NULL;
|
||||
} else if (split->length == 3) {
|
||||
// Fail here if argument can only be finger count
|
||||
return strformat("expected 1-9, got %s", next);
|
||||
return format_str("expected 1-9, got %s", next);
|
||||
}
|
||||
|
||||
// If there is an argument left, try to parse as direction
|
||||
|
@ -95,7 +78,7 @@ char *gesture_parse(const char *input, struct gesture *output) {
|
|||
} else if (strcmp(item, "counterclockwise") == 0) {
|
||||
output->directions |= GESTURE_DIRECTION_COUNTERCLOCKWISE;
|
||||
} else {
|
||||
return strformat("expected direction, got %s", item);
|
||||
return format_str("expected direction, got %s", item);
|
||||
}
|
||||
}
|
||||
list_free_items_and_destroy(directions);
|
||||
|
@ -163,7 +146,7 @@ static char *gesture_directions_to_string(uint32_t directions) {
|
|||
if (!result) {
|
||||
result = strdup(name);
|
||||
} else {
|
||||
char *new = strformat("%s+%s", result, name);
|
||||
char *new = format_str("%s+%s", result, name);
|
||||
free(result);
|
||||
result = new;
|
||||
}
|
||||
|
@ -179,7 +162,7 @@ static char *gesture_directions_to_string(uint32_t directions) {
|
|||
|
||||
char *gesture_to_string(struct gesture *gesture) {
|
||||
char *directions = gesture_directions_to_string(gesture->directions);
|
||||
char *result = strformat("%s:%u:%s",
|
||||
char *result = format_str("%s:%u:%s",
|
||||
gesture_type_string(gesture->type),
|
||||
gesture->fingers, directions);
|
||||
free(directions);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
lib_sway_common = static_library(
|
||||
'sway-common',
|
||||
files(
|
||||
'background-image.c',
|
||||
'cairo.c',
|
||||
'gesture.c',
|
||||
'ipc-client.c',
|
||||
|
@ -14,7 +13,6 @@ lib_sway_common = static_library(
|
|||
),
|
||||
dependencies: [
|
||||
cairo,
|
||||
gdk_pixbuf,
|
||||
pango,
|
||||
pangocairo,
|
||||
wayland_client.partial_dependency(compile_args: true)
|
||||
|
|
|
@ -84,18 +84,11 @@ void get_text_size(cairo_t *cairo, const PangoFontDescription *desc, int *width,
|
|||
int *baseline, double scale, bool markup, const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
// Add one since vsnprintf excludes null terminator.
|
||||
int length = vsnprintf(NULL, 0, fmt, args) + 1;
|
||||
char *buf = vformat_str(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
char *buf = malloc(length);
|
||||
if (buf == NULL) {
|
||||
sway_log(SWAY_ERROR, "Failed to allocate memory");
|
||||
return;
|
||||
}
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buf, length, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
PangoLayout *layout = get_pango_layout(cairo, desc, buf, scale, markup);
|
||||
pango_cairo_update_layout(cairo, layout);
|
||||
|
@ -104,6 +97,7 @@ void get_text_size(cairo_t *cairo, const PangoFontDescription *desc, int *width,
|
|||
*baseline = pango_layout_get_baseline(layout) / PANGO_SCALE;
|
||||
}
|
||||
g_object_unref(layout);
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
|
@ -125,18 +119,11 @@ void render_text(cairo_t *cairo, const PangoFontDescription *desc,
|
|||
double scale, bool markup, const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
// Add one since vsnprintf excludes null terminator.
|
||||
int length = vsnprintf(NULL, 0, fmt, args) + 1;
|
||||
char *buf = vformat_str(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
char *buf = malloc(length);
|
||||
if (buf == NULL) {
|
||||
sway_log(SWAY_ERROR, "Failed to allocate memory");
|
||||
return;
|
||||
}
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buf, length, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
PangoLayout *layout = get_pango_layout(cairo, desc, buf, scale, markup);
|
||||
cairo_font_options_t *fo = cairo_font_options_create();
|
||||
|
@ -146,5 +133,6 @@ void render_text(cairo_t *cairo, const PangoFontDescription *desc,
|
|||
pango_cairo_update_layout(cairo, layout);
|
||||
pango_cairo_show_layout(cairo, layout);
|
||||
g_object_unref(layout);
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -328,3 +329,35 @@ bool expand_path(char **path) {
|
|||
wordfree(&p);
|
||||
return true;
|
||||
}
|
||||
|
||||
char *vformat_str(const char *fmt, va_list args) {
|
||||
char *str = NULL;
|
||||
va_list args_copy;
|
||||
va_copy(args_copy, args);
|
||||
|
||||
int len = vsnprintf(NULL, 0, fmt, args);
|
||||
if (len < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "vsnprintf(\"%s\") failed", fmt);
|
||||
goto out;
|
||||
}
|
||||
|
||||
str = malloc(len + 1);
|
||||
if (str == NULL) {
|
||||
sway_log_errno(SWAY_ERROR, "malloc() failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
vsnprintf(str, len + 1, fmt, args_copy);
|
||||
|
||||
out:
|
||||
va_end(args_copy);
|
||||
return str;
|
||||
}
|
||||
|
||||
char *format_str(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
char *str = vformat_str(fmt, args);
|
||||
va_end(args);
|
||||
return str;
|
||||
}
|
||||
|
|
|
@ -205,7 +205,7 @@ bar {
|
|||
|
||||
# When the status_command prints a new line to stdout, swaybar updates.
|
||||
# The default just shows the current date and time.
|
||||
status_command while date +'%Y-%m-%d %I:%M:%S %p'; do sleep 1; done
|
||||
status_command while date +'%Y-%m-%d %X'; do sleep 1; done
|
||||
|
||||
colors {
|
||||
statusline #ffffff
|
||||
|
|
|
@ -1,124 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# This script requires i3ipc-python package (install it from a system package manager
|
||||
# or pip).
|
||||
# It adds icons to the workspace name for each open window.
|
||||
# Set your keybindings like this: set $workspace1 workspace number 1
|
||||
# Add your icons to WINDOW_ICONS.
|
||||
# Based on https://github.com/maximbaz/dotfiles/blob/master/bin/i3-autoname-workspaces
|
||||
|
||||
import argparse
|
||||
import i3ipc
|
||||
import logging
|
||||
import re
|
||||
import signal
|
||||
import sys
|
||||
|
||||
WINDOW_ICONS = {
|
||||
"firefox": "",
|
||||
}
|
||||
|
||||
DEFAULT_ICON = ""
|
||||
|
||||
|
||||
def icon_for_window(window):
|
||||
name = None
|
||||
if window.app_id is not None and len(window.app_id) > 0:
|
||||
name = window.app_id.lower()
|
||||
elif window.window_class is not None and len(window.window_class) > 0:
|
||||
name = window.window_class.lower()
|
||||
|
||||
if name in WINDOW_ICONS:
|
||||
return WINDOW_ICONS[name]
|
||||
|
||||
logging.info("No icon available for window with name: %s" % str(name))
|
||||
return DEFAULT_ICON
|
||||
|
||||
def rename_workspaces(ipc):
|
||||
for workspace in ipc.get_tree().workspaces():
|
||||
name_parts = parse_workspace_name(workspace.name)
|
||||
icon_tuple = ()
|
||||
for w in workspace:
|
||||
if w.app_id is not None or w.window_class is not None:
|
||||
icon = icon_for_window(w)
|
||||
if not ARGUMENTS.duplicates and icon in icon_tuple:
|
||||
continue
|
||||
icon_tuple += (icon,)
|
||||
name_parts["icons"] = " ".join(icon_tuple) + " "
|
||||
new_name = construct_workspace_name(name_parts)
|
||||
ipc.command('rename workspace "%s" to "%s"' % (workspace.name, new_name))
|
||||
|
||||
|
||||
def undo_window_renaming(ipc):
|
||||
for workspace in ipc.get_tree().workspaces():
|
||||
name_parts = parse_workspace_name(workspace.name)
|
||||
name_parts["icons"] = None
|
||||
new_name = construct_workspace_name(name_parts)
|
||||
ipc.command('rename workspace "%s" to "%s"' % (workspace.name, new_name))
|
||||
ipc.main_quit()
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def parse_workspace_name(name):
|
||||
return re.match(
|
||||
"(?P<num>[0-9]+):?(?P<shortname>\w+)? ?(?P<icons>.+)?", name
|
||||
).groupdict()
|
||||
|
||||
|
||||
def construct_workspace_name(parts):
|
||||
new_name = str(parts["num"])
|
||||
if parts["shortname"] or parts["icons"]:
|
||||
new_name += ":"
|
||||
|
||||
if parts["shortname"]:
|
||||
new_name += parts["shortname"]
|
||||
|
||||
if parts["icons"]:
|
||||
new_name += " " + parts["icons"]
|
||||
|
||||
return new_name
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
description="This script automatically changes the workspace name in sway depending on your open applications."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--duplicates",
|
||||
"-d",
|
||||
action="store_true",
|
||||
help="Set it when you want an icon for each instance of the same application per workspace.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--logfile",
|
||||
"-l",
|
||||
type=str,
|
||||
default="/tmp/sway-autoname-workspaces.log",
|
||||
help="Path for the logfile.",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
global ARGUMENTS
|
||||
ARGUMENTS = args
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
filename=ARGUMENTS.logfile,
|
||||
filemode="w",
|
||||
format="%(message)s",
|
||||
)
|
||||
|
||||
ipc = i3ipc.Connection()
|
||||
|
||||
for sig in [signal.SIGINT, signal.SIGTERM]:
|
||||
signal.signal(sig, lambda signal, frame: undo_window_renaming(ipc))
|
||||
|
||||
def window_event_handler(ipc, e):
|
||||
if e.change in ["new", "close", "move"]:
|
||||
rename_workspaces(ipc)
|
||||
|
||||
ipc.on("window", window_event_handler)
|
||||
|
||||
rename_workspaces(ipc)
|
||||
|
||||
ipc.main()
|
||||
|
168
contrib/grimshot
168
contrib/grimshot
|
@ -1,168 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
## Grimshot: a helper for screenshots within sway
|
||||
## Requirements:
|
||||
## - `grim`: screenshot utility for wayland
|
||||
## - `slurp`: to select an area
|
||||
## - `swaymsg`: to read properties of current window
|
||||
## - `wl-copy`: clipboard utility
|
||||
## - `jq`: json utility to parse swaymsg output
|
||||
## - `notify-send`: to show notifications
|
||||
## Those are needed to be installed, if unsure, run `grimshot check`
|
||||
##
|
||||
## See `man 1 grimshot` or `grimshot usage` for further details.
|
||||
|
||||
getTargetDirectory() {
|
||||
test -f "${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs" && \
|
||||
. "${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs"
|
||||
|
||||
echo "${XDG_SCREENSHOTS_DIR:-${XDG_PICTURES_DIR:-$HOME}}"
|
||||
}
|
||||
|
||||
NOTIFY=no
|
||||
CURSOR=
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
key="$1"
|
||||
|
||||
case $key in
|
||||
-n|--notify)
|
||||
NOTIFY=yes
|
||||
shift # past argument
|
||||
;;
|
||||
-c|--cursor)
|
||||
CURSOR=yes
|
||||
shift # past argument
|
||||
;;
|
||||
*) # unknown option
|
||||
break # done with parsing --flags
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
ACTION=${1:-usage}
|
||||
SUBJECT=${2:-screen}
|
||||
FILE=${3:-$(getTargetDirectory)/$(date -Ins).png}
|
||||
|
||||
if [ "$ACTION" != "save" ] && [ "$ACTION" != "copy" ] && [ "$ACTION" != "check" ]; then
|
||||
echo "Usage:"
|
||||
echo " grimshot [--notify] [--cursor] (copy|save) [active|screen|output|area|window] [FILE|-]"
|
||||
echo " grimshot check"
|
||||
echo " grimshot usage"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " copy: Copy the screenshot data into the clipboard."
|
||||
echo " save: Save the screenshot to a regular file or '-' to pipe to STDOUT."
|
||||
echo " check: Verify if required tools are installed and exit."
|
||||
echo " usage: Show this message and exit."
|
||||
echo ""
|
||||
echo "Targets:"
|
||||
echo " active: Currently active window."
|
||||
echo " screen: All visible outputs."
|
||||
echo " output: Currently active output."
|
||||
echo " area: Manually select a region."
|
||||
echo " window: Manually select a window."
|
||||
exit
|
||||
fi
|
||||
|
||||
notify() {
|
||||
notify-send -t 3000 -a grimshot "$@"
|
||||
}
|
||||
notifyOk() {
|
||||
[ "$NOTIFY" = "no" ] && return
|
||||
|
||||
TITLE=${2:-"Screenshot"}
|
||||
MESSAGE=${1:-"OK"}
|
||||
notify "$TITLE" "$MESSAGE"
|
||||
}
|
||||
notifyError() {
|
||||
if [ $NOTIFY = "yes" ]; then
|
||||
TITLE=${2:-"Screenshot"}
|
||||
MESSAGE=${1:-"Error taking screenshot with grim"}
|
||||
notify -u critical "$TITLE" "$MESSAGE"
|
||||
else
|
||||
echo "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
die() {
|
||||
MSG=${1:-Bye}
|
||||
notifyError "Error: $MSG"
|
||||
exit 2
|
||||
}
|
||||
|
||||
check() {
|
||||
COMMAND=$1
|
||||
if command -v "$COMMAND" > /dev/null 2>&1; then
|
||||
RESULT="OK"
|
||||
else
|
||||
RESULT="NOT FOUND"
|
||||
fi
|
||||
echo " $COMMAND: $RESULT"
|
||||
}
|
||||
|
||||
takeScreenshot() {
|
||||
FILE=$1
|
||||
GEOM=$2
|
||||
OUTPUT=$3
|
||||
if [ -n "$OUTPUT" ]; then
|
||||
grim ${CURSOR:+-c} -o "$OUTPUT" "$FILE" || die "Unable to invoke grim"
|
||||
elif [ -z "$GEOM" ]; then
|
||||
grim ${CURSOR:+-c} "$FILE" || die "Unable to invoke grim"
|
||||
else
|
||||
grim ${CURSOR:+-c} -g "$GEOM" "$FILE" || die "Unable to invoke grim"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "$ACTION" = "check" ] ; then
|
||||
echo "Checking if required tools are installed. If something is missing, install it to your system and make it available in PATH..."
|
||||
check grim
|
||||
check slurp
|
||||
check swaymsg
|
||||
check wl-copy
|
||||
check jq
|
||||
check notify-send
|
||||
exit
|
||||
elif [ "$SUBJECT" = "area" ] ; then
|
||||
GEOM=$(slurp -d)
|
||||
# Check if user exited slurp without selecting the area
|
||||
if [ -z "$GEOM" ]; then
|
||||
exit 1
|
||||
fi
|
||||
WHAT="Area"
|
||||
elif [ "$SUBJECT" = "active" ] ; then
|
||||
FOCUSED=$(swaymsg -t get_tree | jq -r 'recurse(.nodes[]?, .floating_nodes[]?) | select(.focused)')
|
||||
GEOM=$(echo "$FOCUSED" | jq -r '.rect | "\(.x),\(.y) \(.width)x\(.height)"')
|
||||
APP_ID=$(echo "$FOCUSED" | jq -r '.app_id')
|
||||
WHAT="$APP_ID window"
|
||||
elif [ "$SUBJECT" = "screen" ] ; then
|
||||
GEOM=""
|
||||
WHAT="Screen"
|
||||
elif [ "$SUBJECT" = "output" ] ; then
|
||||
GEOM=""
|
||||
OUTPUT=$(swaymsg -t get_outputs | jq -r '.[] | select(.focused)' | jq -r '.name')
|
||||
WHAT="$OUTPUT"
|
||||
elif [ "$SUBJECT" = "window" ] ; then
|
||||
GEOM=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | .rect | "\(.x),\(.y) \(.width)x\(.height)"' | slurp)
|
||||
# Check if user exited slurp without selecting the area
|
||||
if [ -z "$GEOM" ]; then
|
||||
exit 1
|
||||
fi
|
||||
WHAT="Window"
|
||||
else
|
||||
die "Unknown subject to take a screen shot from" "$SUBJECT"
|
||||
fi
|
||||
|
||||
if [ "$ACTION" = "copy" ] ; then
|
||||
takeScreenshot - "$GEOM" "$OUTPUT" | wl-copy --type image/png || die "Clipboard error"
|
||||
notifyOk "$WHAT copied to buffer"
|
||||
else
|
||||
if takeScreenshot "$FILE" "$GEOM" "$OUTPUT"; then
|
||||
TITLE="Screenshot of $SUBJECT"
|
||||
MESSAGE=$(basename "$FILE")
|
||||
notifyOk "$MESSAGE" "$TITLE"
|
||||
echo "$FILE"
|
||||
else
|
||||
notifyError "Error taking screenshot with grim"
|
||||
fi
|
||||
fi
|
|
@ -1,109 +0,0 @@
|
|||
.\" Generated by scdoc 1.11.2
|
||||
.\" Complete documentation for this program is not available as a GNU info page
|
||||
.ie \n(.g .ds Aq \(aq
|
||||
.el .ds Aq '
|
||||
.nh
|
||||
.ad l
|
||||
.\" Begin generated content:
|
||||
.TH "grimshot" "1" "2022-03-31"
|
||||
.P
|
||||
.SH NAME
|
||||
.P
|
||||
grimshot - a helper for screenshots within sway
|
||||
.P
|
||||
.SH SYNOPSIS
|
||||
.P
|
||||
\fBgrimshot\fR [--notify] [--cursor] (copy|save) [TARGET] [FILE]
|
||||
.br
|
||||
\fBgrimshot\fR check
|
||||
.br
|
||||
\fBgrimshot\fR usage
|
||||
.P
|
||||
.SH OPTIONS
|
||||
.P
|
||||
\fB--notify\fR
|
||||
.RS 4
|
||||
Show notifications to the user that a screenshot has been taken.\&
|
||||
.P
|
||||
.RE
|
||||
\fB--cursor\fR
|
||||
.RS 4
|
||||
Include cursors in the screenshot.\&
|
||||
.P
|
||||
.RE
|
||||
\fBsave\fR
|
||||
.RS 4
|
||||
Save the screenshot into a regular file.\& Grimshot will write images
|
||||
files to \fBXDG_SCREENSHOTS_DIR\fR if this is set (or defined
|
||||
in \fBuser-dirs.\&dir\fR), or otherwise fall back to \fBXDG_PICTURES_DIR\fR.\&
|
||||
Set FILE to '\&-'\& to pipe the output to STDOUT.\&
|
||||
.P
|
||||
.RE
|
||||
\fBcopy\fR
|
||||
.RS 4
|
||||
Copy the screenshot data (as image/png) into the clipboard.\&
|
||||
.P
|
||||
.RE
|
||||
.SH DESCRIPTION
|
||||
.P
|
||||
Grimshot is an easy-to-use screenshot utility for sway.\& It provides a
|
||||
convenient interface over grim, slurp and jq, and supports storing the
|
||||
screenshot either directly to the clipboard using wl-copy or to a file.\&
|
||||
.P
|
||||
.SH EXAMPLES
|
||||
.P
|
||||
An example usage pattern is to add these bindings to your sway config:
|
||||
.P
|
||||
.nf
|
||||
.RS 4
|
||||
# Screenshots:
|
||||
# Super+P: Current window
|
||||
# Super+Shift+p: Select area
|
||||
# Super+Alt+p Current output
|
||||
# Super+Ctrl+p Select a window
|
||||
|
||||
bindsym Mod4+p exec grimshot save active
|
||||
bindsym Mod4+Shift+p exec grimshot save area
|
||||
bindsym Mod4+Mod1+p exec grimshot save output
|
||||
bindsym Mod4+Ctrl+p exec grimshot save window
|
||||
.fi
|
||||
.RE
|
||||
.P
|
||||
.SH TARGETS
|
||||
.P
|
||||
grimshot can capture the following named targets:
|
||||
.P
|
||||
\fIactive\fR
|
||||
.RS 4
|
||||
Captures the currently active window.\&
|
||||
.P
|
||||
.RE
|
||||
\fIscreen\fR
|
||||
.RS 4
|
||||
Captures the entire screen.\& This includes all visible outputs.\&
|
||||
.P
|
||||
.RE
|
||||
\fIarea\fR
|
||||
.RS 4
|
||||
Allows manually selecting a rectangular region, and captures that.\&
|
||||
.P
|
||||
.RE
|
||||
\fIwindow\fR
|
||||
.RS 4
|
||||
Allows manually selecting a single window (by clicking on it), and
|
||||
captures it.\&
|
||||
.P
|
||||
.RE
|
||||
\fIoutput\fR
|
||||
.RS 4
|
||||
Captures the currently active output.\&
|
||||
.P
|
||||
.RE
|
||||
.SH OUTPUT
|
||||
.P
|
||||
Grimshot will print the filename of the captured screenshot to stdout if called
|
||||
with the \fIsave\fR subcommand.\&
|
||||
.P
|
||||
.SH SEE ALSO
|
||||
.P
|
||||
\fBgrim\fR(1)
|
|
@ -1,80 +0,0 @@
|
|||
grimshot(1)
|
||||
|
||||
# NAME
|
||||
|
||||
grimshot - a helper for screenshots within sway
|
||||
|
||||
# SYNOPSIS
|
||||
|
||||
*grimshot* [--notify] [--cursor] (copy|save) [TARGET] [FILE]++
|
||||
*grimshot* check++
|
||||
*grimshot* usage
|
||||
|
||||
# OPTIONS
|
||||
|
||||
*--notify*
|
||||
Show notifications to the user that a screenshot has been taken.
|
||||
|
||||
*--cursor*
|
||||
Include cursors in the screenshot.
|
||||
|
||||
*save*
|
||||
Save the screenshot into a regular file. Grimshot will write image
|
||||
files to *XDG_SCREENSHOTS_DIR* if this is set (or defined
|
||||
in *user-dirs.dir*), or otherwise fall back to *XDG_PICTURES_DIR*.
|
||||
Set FILE to '-' to pipe the output to STDOUT.
|
||||
|
||||
*copy*
|
||||
Copy the screenshot data (as image/png) into the clipboard.
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
Grimshot is an easy-to-use screenshot utility for sway. It provides a
|
||||
convenient interface over grim, slurp and jq, and supports storing the
|
||||
screenshot either directly to the clipboard using wl-copy or to a file.
|
||||
|
||||
# EXAMPLES
|
||||
|
||||
An example usage pattern is to add these bindings to your sway config:
|
||||
|
||||
```
|
||||
# Screenshots:
|
||||
# Super+P: Current window
|
||||
# Super+Shift+p: Select area
|
||||
# Super+Alt+p Current output
|
||||
# Super+Ctrl+p Select a window
|
||||
|
||||
bindsym Mod4+p exec grimshot save active
|
||||
bindsym Mod4+Shift+p exec grimshot save area
|
||||
bindsym Mod4+Mod1+p exec grimshot save output
|
||||
bindsym Mod4+Ctrl+p exec grimshot save window
|
||||
```
|
||||
|
||||
# TARGETS
|
||||
|
||||
grimshot can capture the following named targets:
|
||||
|
||||
_active_
|
||||
Captures the currently active window.
|
||||
|
||||
_screen_
|
||||
Captures the entire screen. This includes all visible outputs.
|
||||
|
||||
_area_
|
||||
Allows manually selecting a rectangular region, and captures that.
|
||||
|
||||
_window_
|
||||
Allows manually selecting a single window (by clicking on it), and
|
||||
captures it.
|
||||
|
||||
_output_
|
||||
Captures the currently active output.
|
||||
|
||||
# OUTPUT
|
||||
|
||||
Grimshot will print the filename of the captured screenshot to stdout if called
|
||||
with the _save_ subcommand.
|
||||
|
||||
# SEE ALSO
|
||||
|
||||
*grim*(1)
|
|
@ -1,69 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# This script requires i3ipc-python package (install it from a system package manager
|
||||
# or pip).
|
||||
# It makes inactive windows transparent. Use `transparency_val` variable to control
|
||||
# transparency strength in range of 0…1 or use the command line argument -o.
|
||||
|
||||
import argparse
|
||||
import i3ipc
|
||||
import signal
|
||||
import sys
|
||||
from functools import partial
|
||||
|
||||
def on_window_focus(inactive_opacity, ipc, event):
|
||||
global prev_focused
|
||||
global prev_workspace
|
||||
|
||||
focused_workspace = ipc.get_tree().find_focused()
|
||||
|
||||
if focused_workspace == None:
|
||||
return
|
||||
|
||||
focused = event.container
|
||||
workspace = focused_workspace.workspace().num
|
||||
|
||||
if focused.id != prev_focused.id: # https://github.com/swaywm/sway/issues/2859
|
||||
focused.command("opacity 1")
|
||||
if workspace == prev_workspace:
|
||||
prev_focused.command("opacity " + inactive_opacity)
|
||||
prev_focused = focused
|
||||
prev_workspace = workspace
|
||||
|
||||
|
||||
def remove_opacity(ipc):
|
||||
for workspace in ipc.get_tree().workspaces():
|
||||
for w in workspace:
|
||||
w.command("opacity 1")
|
||||
ipc.main_quit()
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
transparency_val = "0.80"
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description="This script allows you to set the transparency of unfocused windows in sway."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--opacity",
|
||||
"-o",
|
||||
type=str,
|
||||
default=transparency_val,
|
||||
help="set opacity value in range 0...1",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
ipc = i3ipc.Connection()
|
||||
prev_focused = None
|
||||
prev_workspace = ipc.get_tree().find_focused().workspace().num
|
||||
|
||||
for window in ipc.get_tree():
|
||||
if window.focused:
|
||||
prev_focused = window
|
||||
else:
|
||||
window.command("opacity " + args.opacity)
|
||||
for sig in [signal.SIGINT, signal.SIGTERM]:
|
||||
signal.signal(sig, lambda signal, frame: remove_opacity(ipc))
|
||||
ipc.on("window::focus", partial(on_window_focus, args.opacity))
|
||||
ipc.main()
|
|
@ -1,20 +0,0 @@
|
|||
#ifndef _SWAY_BACKGROUND_IMAGE_H
|
||||
#define _SWAY_BACKGROUND_IMAGE_H
|
||||
#include "cairo_util.h"
|
||||
|
||||
enum background_mode {
|
||||
BACKGROUND_MODE_STRETCH,
|
||||
BACKGROUND_MODE_FILL,
|
||||
BACKGROUND_MODE_FIT,
|
||||
BACKGROUND_MODE_CENTER,
|
||||
BACKGROUND_MODE_TILE,
|
||||
BACKGROUND_MODE_SOLID_COLOR,
|
||||
BACKGROUND_MODE_INVALID,
|
||||
};
|
||||
|
||||
enum background_mode parse_background_mode(const char *mode);
|
||||
cairo_surface_t *load_background_image(const char *path);
|
||||
void render_background_image(cairo_t *cairo, cairo_surface_t *image,
|
||||
enum background_mode mode, int buffer_width, int buffer_height);
|
||||
|
||||
#endif
|
|
@ -5,6 +5,7 @@
|
|||
#include <stdint.h>
|
||||
#include <cairo.h>
|
||||
#include <pango/pangocairo.h>
|
||||
#include "stringop.h"
|
||||
|
||||
/**
|
||||
* Utility function which escape characters a & < > ' ".
|
||||
|
@ -16,9 +17,9 @@ size_t escape_markup_text(const char *src, char *dest);
|
|||
PangoLayout *get_pango_layout(cairo_t *cairo, const PangoFontDescription *desc,
|
||||
const char *text, double scale, bool markup);
|
||||
void get_text_size(cairo_t *cairo, const PangoFontDescription *desc, int *width, int *height,
|
||||
int *baseline, double scale, bool markup, const char *fmt, ...);
|
||||
int *baseline, double scale, bool markup, const char *fmt, ...) _SWAY_ATTRIB_PRINTF(8, 9);
|
||||
void get_text_metrics(const PangoFontDescription *desc, int *height, int *baseline);
|
||||
void render_text(cairo_t *cairo, PangoFontDescription *desc,
|
||||
double scale, bool markup, const char *fmt, ...);
|
||||
double scale, bool markup, const char *fmt, ...) _SWAY_ATTRIB_PRINTF(5, 6);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,6 +5,12 @@
|
|||
#include <stddef.h>
|
||||
#include "list.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define _SWAY_ATTRIB_PRINTF(start, end) __attribute__((format(printf, start, end)))
|
||||
#else
|
||||
#define _SWAY_ATTRIB_PRINTF(start, end)
|
||||
#endif
|
||||
|
||||
void strip_whitespace(char *str);
|
||||
void strip_quotes(char *str);
|
||||
|
||||
|
@ -31,4 +37,7 @@ char *argsep(char **stringp, const char *delim, char *matched_delim);
|
|||
// Expand a path using shell replacements such as $HOME and ~
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <wlr/util/edges.h>
|
||||
#include "config.h"
|
||||
#include "stringop.h"
|
||||
|
||||
struct sway_container;
|
||||
|
||||
|
@ -76,7 +77,7 @@ struct cmd_results *config_commands_command(char *exec);
|
|||
/**
|
||||
* Allocates a cmd_results object.
|
||||
*/
|
||||
struct cmd_results *cmd_results_new(enum cmd_status status, const char *error, ...);
|
||||
struct cmd_results *cmd_results_new(enum cmd_status status, const char *error, ...) _SWAY_ATTRIB_PRINTF(2, 3);
|
||||
/**
|
||||
* Frees a cmd_results object.
|
||||
*/
|
||||
|
@ -265,6 +266,7 @@ sway_cmd input_cmd_scroll_factor;
|
|||
sway_cmd input_cmd_repeat_delay;
|
||||
sway_cmd input_cmd_repeat_rate;
|
||||
sway_cmd input_cmd_scroll_button;
|
||||
sway_cmd input_cmd_scroll_button_lock;
|
||||
sway_cmd input_cmd_scroll_method;
|
||||
sway_cmd input_cmd_tap;
|
||||
sway_cmd input_cmd_tap_button_map;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "../include/config.h"
|
||||
#include "gesture.h"
|
||||
#include "list.h"
|
||||
#include "stringop.h"
|
||||
#include "swaynag.h"
|
||||
#include "tree/container.h"
|
||||
#include "sway/input/tablet.h"
|
||||
|
@ -160,6 +161,7 @@ struct input_config {
|
|||
int repeat_delay;
|
||||
int repeat_rate;
|
||||
int scroll_button;
|
||||
int scroll_button_lock;
|
||||
int scroll_method;
|
||||
int send_events;
|
||||
int tap;
|
||||
|
@ -625,7 +627,7 @@ void run_deferred_bindings(void);
|
|||
/**
|
||||
* Adds a warning entry to the swaynag instance used for errors.
|
||||
*/
|
||||
void config_add_swaynag_warning(char *fmt, ...);
|
||||
void config_add_swaynag_warning(char *fmt, ...) _SWAY_ATTRIB_PRINTF(1, 2);
|
||||
|
||||
/**
|
||||
* Free config struct
|
||||
|
|
|
@ -43,6 +43,7 @@ struct criteria {
|
|||
struct pattern *window_role;
|
||||
enum atom_name window_type;
|
||||
#endif
|
||||
bool all;
|
||||
bool floating;
|
||||
bool tiling;
|
||||
char urgent; // 'l' for latest or 'o' for oldest
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#ifndef _SWAY_DESKTOP_IDLE_INHIBIT_V1_H
|
||||
#define _SWAY_DESKTOP_IDLE_INHIBIT_V1_H
|
||||
#include <wlr/types/wlr_idle_inhibit_v1.h>
|
||||
#include <wlr/types/wlr_idle.h>
|
||||
#include "sway/server.h"
|
||||
|
||||
enum sway_idle_inhibit_mode {
|
||||
INHIBIT_IDLE_APPLICATION, // Application set inhibitor (when visible)
|
||||
|
@ -16,12 +14,9 @@ struct sway_idle_inhibit_manager_v1 {
|
|||
struct wlr_idle_inhibit_manager_v1 *wlr_manager;
|
||||
struct wl_listener new_idle_inhibitor_v1;
|
||||
struct wl_list inhibitors;
|
||||
|
||||
struct wlr_idle *idle;
|
||||
};
|
||||
|
||||
struct sway_idle_inhibitor_v1 {
|
||||
struct sway_idle_inhibit_manager_v1 *manager;
|
||||
struct wlr_idle_inhibitor_v1 *wlr_inhibitor;
|
||||
struct sway_view *view;
|
||||
enum sway_idle_inhibit_mode mode;
|
||||
|
@ -33,8 +28,7 @@ struct sway_idle_inhibitor_v1 {
|
|||
bool sway_idle_inhibit_v1_is_active(
|
||||
struct sway_idle_inhibitor_v1 *inhibitor);
|
||||
|
||||
void sway_idle_inhibit_v1_check_active(
|
||||
struct sway_idle_inhibit_manager_v1 *manager);
|
||||
void sway_idle_inhibit_v1_check_active(void);
|
||||
|
||||
void sway_idle_inhibit_v1_user_inhibitor_register(struct sway_view *view,
|
||||
enum sway_idle_inhibit_mode mode);
|
||||
|
@ -48,6 +42,6 @@ struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_application_inhibitor_for_vi
|
|||
void sway_idle_inhibit_v1_user_inhibitor_destroy(
|
||||
struct sway_idle_inhibitor_v1 *inhibitor);
|
||||
|
||||
struct sway_idle_inhibit_manager_v1 *sway_idle_inhibit_manager_v1_create(
|
||||
struct wl_display *wl_display, struct wlr_idle *idle);
|
||||
bool sway_idle_inhibit_manager_v1_init(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,7 +35,6 @@ struct sway_cursor {
|
|||
pixman_region32_t confine; // invalid if active_constraint == NULL
|
||||
bool active_confine_requires_warp;
|
||||
|
||||
struct wlr_pointer_gestures_v1 *pointer_gestures;
|
||||
struct wl_listener hold_begin;
|
||||
struct wl_listener hold_end;
|
||||
struct wl_listener pinch_begin;
|
||||
|
@ -53,6 +52,7 @@ struct sway_cursor {
|
|||
|
||||
struct wl_listener touch_down;
|
||||
struct wl_listener touch_up;
|
||||
struct wl_listener touch_cancel;
|
||||
struct wl_listener touch_motion;
|
||||
struct wl_listener touch_frame;
|
||||
bool simulating_pointer_from_touch;
|
||||
|
@ -145,4 +145,6 @@ uint32_t get_mouse_button(const char *name, char **error);
|
|||
|
||||
const char *get_mouse_button_name(uint32_t button);
|
||||
|
||||
void handle_request_set_cursor_shape(struct wl_listener *listener, void *data);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef _SWAY_INPUT_INPUT_MANAGER_H
|
||||
#define _SWAY_INPUT_INPUT_MANAGER_H
|
||||
#include <libinput.h>
|
||||
#include <wlr/types/wlr_input_inhibitor.h>
|
||||
#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h>
|
||||
#include <wlr/types/wlr_virtual_keyboard_v1.h>
|
||||
#include <wlr/types/wlr_virtual_pointer_v1.h>
|
||||
|
@ -21,10 +20,10 @@ struct sway_input_manager {
|
|||
struct wl_list devices;
|
||||
struct wl_list seats;
|
||||
|
||||
struct wlr_input_inhibit_manager *inhibit;
|
||||
struct wlr_keyboard_shortcuts_inhibit_manager_v1 *keyboard_shortcuts_inhibit;
|
||||
struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard;
|
||||
struct wlr_virtual_pointer_manager_v1 *virtual_pointer;
|
||||
struct wlr_pointer_gestures_v1 *pointer_gestures;
|
||||
|
||||
struct wl_listener new_input;
|
||||
struct wl_listener inhibit_activate;
|
||||
|
@ -44,7 +43,7 @@ void input_manager_configure_xcursor(void);
|
|||
|
||||
void input_manager_apply_input_config(struct input_config *input_config);
|
||||
|
||||
void input_manager_configure_all_inputs(void);
|
||||
void input_manager_configure_all_input_mappings(void);
|
||||
|
||||
void input_manager_reset_input(struct sway_input_device *input_device);
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "sway/input/text_input.h"
|
||||
|
||||
struct sway_seat;
|
||||
struct render_context;
|
||||
|
||||
struct sway_seatop_impl {
|
||||
void (*button)(struct sway_seat *seat, uint32_t time_msec,
|
||||
|
@ -43,14 +44,15 @@ struct sway_seatop_impl {
|
|||
struct wlr_touch_up_event *event);
|
||||
void (*touch_down)(struct sway_seat *seat,
|
||||
struct wlr_touch_down_event *event, double lx, double ly);
|
||||
void (*touch_cancel)(struct sway_seat *seat,
|
||||
struct wlr_touch_cancel_event *event);
|
||||
void (*tablet_tool_motion)(struct sway_seat *seat,
|
||||
struct sway_tablet_tool *tool, uint32_t time_msec);
|
||||
void (*tablet_tool_tip)(struct sway_seat *seat, struct sway_tablet_tool *tool,
|
||||
uint32_t time_msec, enum wlr_tablet_tool_tip_state state);
|
||||
void (*end)(struct sway_seat *seat);
|
||||
void (*unref)(struct sway_seat *seat, struct sway_container *con);
|
||||
void (*render)(struct sway_seat *seat, struct sway_output *output,
|
||||
const pixman_region32_t *damage);
|
||||
void (*render)(struct sway_seat *seat, struct render_context *ctx);
|
||||
bool allow_set_cursor;
|
||||
};
|
||||
|
||||
|
@ -102,8 +104,9 @@ struct sway_seat {
|
|||
struct sway_workspace *workspace;
|
||||
char *prev_workspace_name; // for workspace back_and_forth
|
||||
|
||||
// If the focused layer is set, views cannot receive keyboard focus
|
||||
struct wlr_layer_surface_v1 *focused_layer;
|
||||
// If the exclusive layer is set, views cannot receive keyboard focus
|
||||
bool has_exclusive_layer;
|
||||
|
||||
// If exclusive_client is set, no other clients will receive input events
|
||||
struct wl_client *exclusive_client;
|
||||
|
@ -165,6 +168,9 @@ void seat_add_device(struct sway_seat *seat,
|
|||
void seat_configure_device(struct sway_seat *seat,
|
||||
struct sway_input_device *device);
|
||||
|
||||
void seat_configure_device_mapping(struct sway_seat *seat,
|
||||
struct sway_input_device *input_device);
|
||||
|
||||
void seat_reset_device(struct sway_seat *seat,
|
||||
struct sway_input_device *input_device);
|
||||
|
||||
|
@ -338,6 +344,9 @@ void seatop_touch_up(struct sway_seat *seat,
|
|||
void seatop_touch_down(struct sway_seat *seat,
|
||||
struct wlr_touch_down_event *event, double lx, double ly);
|
||||
|
||||
void seatop_touch_cancel(struct sway_seat *seat,
|
||||
struct wlr_touch_cancel_event *event);
|
||||
|
||||
void seatop_rebase(struct sway_seat *seat, uint32_t time_msec);
|
||||
|
||||
/**
|
||||
|
@ -356,8 +365,7 @@ void seatop_unref(struct sway_seat *seat, struct sway_container *con);
|
|||
* Instructs a seatop to render anything that it needs to render
|
||||
* (eg. dropzone for move-tiling)
|
||||
*/
|
||||
void seatop_render(struct sway_seat *seat, struct sway_output *output,
|
||||
const pixman_region32_t *damage);
|
||||
void seatop_render(struct sway_seat *seat, struct render_context *ctx);
|
||||
|
||||
bool seatop_allows_set_cursor(struct sway_seat *seat);
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
/**
|
||||
* The relay structure manages the relationship between text-input and
|
||||
* input_method interfaces on a given seat. Multiple text-input interfaces may
|
||||
* be bound to a relay, but at most one will be focused (reveiving events) at
|
||||
* be bound to a relay, but at most one will be focused (receiving events) at
|
||||
* a time. At most one input-method interface may be bound to the seat. The
|
||||
* relay manages life cycle of both sides. When both sides are present and
|
||||
* focused, the relay passes messages between them.
|
||||
|
|
|
@ -55,6 +55,10 @@ struct sway_layer_subsurface {
|
|||
};
|
||||
|
||||
struct sway_output;
|
||||
|
||||
struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface(
|
||||
struct wlr_surface *surface);
|
||||
|
||||
void arrange_layers(struct sway_output *output);
|
||||
|
||||
struct sway_layer_surface *layer_from_wlr_layer_surface_v1(
|
||||
|
|
|
@ -33,8 +33,6 @@ struct sway_output {
|
|||
int width, height; // transformed buffer size
|
||||
enum wl_output_subpixel detected_subpixel;
|
||||
enum scale_filter_mode scale_filter;
|
||||
// last applied mode when the output is powered off
|
||||
struct wlr_output_mode *current_mode;
|
||||
|
||||
bool enabling, enabled;
|
||||
list_t *workspaces;
|
||||
|
@ -57,6 +55,7 @@ struct sway_output {
|
|||
uint32_t refresh_nsec;
|
||||
int max_render_time; // In milliseconds
|
||||
struct wl_event_source *repaint_timer;
|
||||
bool gamma_lut_changed;
|
||||
};
|
||||
|
||||
struct sway_output_non_desktop {
|
||||
|
@ -65,6 +64,14 @@ struct sway_output_non_desktop {
|
|||
struct wl_listener destroy;
|
||||
};
|
||||
|
||||
struct render_context {
|
||||
struct sway_output *output;
|
||||
struct wlr_renderer *renderer;
|
||||
const pixman_region32_t *output_damage;
|
||||
|
||||
struct wlr_render_pass *pass;
|
||||
};
|
||||
|
||||
struct sway_output *output_create(struct wlr_output *wlr_output);
|
||||
|
||||
void output_destroy(struct sway_output *output);
|
||||
|
@ -96,6 +103,9 @@ void output_damage_box(struct sway_output *output, struct wlr_box *box);
|
|||
void output_damage_whole_container(struct sway_output *output,
|
||||
struct sway_container *con);
|
||||
|
||||
bool output_match_name_or_id(struct sway_output *output,
|
||||
const char *name_or_id);
|
||||
|
||||
// this ONLY includes the enabled outputs
|
||||
struct sway_output *output_by_name_or_id(const char *name_or_id);
|
||||
|
||||
|
@ -112,7 +122,7 @@ bool output_has_opaque_overlay_layer_surface(struct sway_output *output);
|
|||
|
||||
struct sway_workspace *output_get_active_workspace(struct sway_output *output);
|
||||
|
||||
void output_render(struct sway_output *output, pixman_region32_t *damage);
|
||||
void output_render(struct render_context *ctx);
|
||||
|
||||
void output_surface_for_each_surface(struct sway_output *output,
|
||||
struct wlr_surface *surface, double ox, double oy,
|
||||
|
@ -165,8 +175,7 @@ void output_get_box(struct sway_output *output, struct wlr_box *box);
|
|||
enum sway_container_layout output_get_default_layout(
|
||||
struct sway_output *output);
|
||||
|
||||
void render_rect(struct sway_output *output,
|
||||
const pixman_region32_t *output_damage, const struct wlr_box *_box,
|
||||
void render_rect(struct render_context *ctx, const struct wlr_box *_box,
|
||||
float color[static 4]);
|
||||
|
||||
void premultiply_alpha(float color[4], float opacity);
|
||||
|
@ -177,6 +186,8 @@ 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);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <wlr/types/wlr_xdg_shell.h>
|
||||
#include "config.h"
|
||||
#include "list.h"
|
||||
#include "sway/desktop/idle_inhibit_v1.h"
|
||||
#if HAVE_XWAYLAND
|
||||
#include "sway/xwayland.h"
|
||||
#endif
|
||||
|
@ -51,15 +52,14 @@ struct sway_server {
|
|||
struct wl_listener new_output;
|
||||
struct wl_listener output_layout_change;
|
||||
|
||||
struct wlr_idle *idle;
|
||||
struct wlr_idle_notifier_v1 *idle_notifier_v1;
|
||||
struct sway_idle_inhibit_manager_v1 *idle_inhibit_manager_v1;
|
||||
struct sway_idle_inhibit_manager_v1 idle_inhibit_manager_v1;
|
||||
|
||||
struct wlr_layer_shell_v1 *layer_shell;
|
||||
struct wl_listener layer_shell_surface;
|
||||
|
||||
struct wlr_xdg_shell *xdg_shell;
|
||||
struct wl_listener xdg_shell_surface;
|
||||
struct wl_listener xdg_shell_toplevel;
|
||||
|
||||
struct wlr_tablet_manager_v2 *tablet_v2;
|
||||
|
||||
|
@ -91,6 +91,9 @@ struct sway_server {
|
|||
struct wl_listener output_manager_apply;
|
||||
struct wl_listener output_manager_test;
|
||||
|
||||
struct wlr_gamma_control_manager_v1 *gamma_control_manager_v1;
|
||||
struct wl_listener gamma_control_set_gamma;
|
||||
|
||||
struct {
|
||||
bool locked;
|
||||
struct wlr_session_lock_manager_v1 *manager;
|
||||
|
@ -111,11 +114,17 @@ struct sway_server {
|
|||
struct wlr_text_input_manager_v3 *text_input;
|
||||
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_screencopy_manager_v1 *screencopy_manager_v1;
|
||||
struct wlr_export_dmabuf_manager_v1 *export_dmabuf_manager_v1;
|
||||
struct wlr_security_context_manager_v1 *security_context_manager_v1;
|
||||
|
||||
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 request_set_cursor_shape;
|
||||
|
||||
struct wl_list pending_launcher_ctxs; // launcher_ctx::link
|
||||
|
||||
// The timeout for transactions, after which a transaction is applied
|
||||
|
@ -167,7 +176,7 @@ void handle_new_output(struct wl_listener *listener, void *data);
|
|||
void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data);
|
||||
void handle_layer_shell_surface(struct wl_listener *listener, void *data);
|
||||
void sway_session_lock_init(void);
|
||||
void handle_xdg_shell_surface(struct wl_listener *listener, void *data);
|
||||
void handle_xdg_shell_toplevel(struct wl_listener *listener, void *data);
|
||||
#if HAVE_XWAYLAND
|
||||
void handle_xwayland_surface(struct wl_listener *listener, void *data);
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef _SWAY_SWAYNAG_H
|
||||
#define _SWAY_SWAYNAG_H
|
||||
#include <wayland-server-core.h>
|
||||
#include "stringop.h"
|
||||
|
||||
struct swaynag_instance {
|
||||
struct wl_client *client;
|
||||
|
@ -21,7 +22,7 @@ bool swaynag_spawn(const char *swaynag_command,
|
|||
// Write a log message to swaynag->fd[1]. This will fail when swaynag->detailed
|
||||
// is false.
|
||||
void swaynag_log(const char *swaynag_command, struct swaynag_instance *swaynag,
|
||||
const char *fmt, ...);
|
||||
const char *fmt, ...) _SWAY_ATTRIB_PRINTF(3, 4);
|
||||
|
||||
// If swaynag->detailed, close swaynag->fd[1] so swaynag displays
|
||||
void swaynag_show(struct swaynag_instance *swaynag);
|
||||
|
|
|
@ -41,7 +41,7 @@ struct sway_root {
|
|||
} events;
|
||||
};
|
||||
|
||||
struct sway_root *root_create(void);
|
||||
struct sway_root *root_create(struct wl_display *display);
|
||||
|
||||
void root_destroy(struct sway_root *root);
|
||||
|
||||
|
|
|
@ -160,6 +160,8 @@ struct sway_xwayland_view {
|
|||
struct wl_listener set_window_type;
|
||||
struct wl_listener set_hints;
|
||||
struct wl_listener set_decorations;
|
||||
struct wl_listener associate;
|
||||
struct wl_listener dissociate;
|
||||
struct wl_listener map;
|
||||
struct wl_listener unmap;
|
||||
struct wl_listener destroy;
|
||||
|
@ -177,6 +179,8 @@ struct sway_xwayland_unmanaged {
|
|||
struct wl_listener request_fullscreen;
|
||||
struct wl_listener commit;
|
||||
struct wl_listener set_geometry;
|
||||
struct wl_listener associate;
|
||||
struct wl_listener dissociate;
|
||||
struct wl_listener map;
|
||||
struct wl_listener unmap;
|
||||
struct wl_listener destroy;
|
||||
|
@ -222,6 +226,7 @@ struct sway_xdg_popup {
|
|||
|
||||
struct wlr_xdg_popup *wlr_xdg_popup;
|
||||
|
||||
struct wl_listener surface_commit;
|
||||
struct wl_listener new_popup;
|
||||
struct wl_listener destroy;
|
||||
};
|
||||
|
|
|
@ -16,4 +16,6 @@ struct sway_xdg_decoration {
|
|||
struct sway_xdg_decoration *xdg_decoration_from_surface(
|
||||
struct wlr_surface *surface);
|
||||
|
||||
void set_xdg_decoration_mode(struct sway_xdg_decoration *deco);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "config.h"
|
||||
#include "input.h"
|
||||
#include "pool-buffer.h"
|
||||
#include "cursor-shape-v1-client-protocol.h"
|
||||
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
|
||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||
|
||||
|
@ -30,6 +31,7 @@ struct swaybar {
|
|||
struct wl_compositor *compositor;
|
||||
struct zwlr_layer_shell_v1 *layer_shell;
|
||||
struct zxdg_output_manager_v1 *xdg_output_manager;
|
||||
struct wp_cursor_shape_manager_v1 *cursor_shape_manager;
|
||||
struct wl_shm *shm;
|
||||
|
||||
struct swaybar_config *config;
|
||||
|
|
7
include/swaybar/image.h
Normal file
7
include/swaybar/image.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#ifndef _SWAYBAR_IMAGE_H
|
||||
#define _SWAYBAR_IMAGE_H
|
||||
#include <cairo.h>
|
||||
|
||||
cairo_surface_t *load_image(const char *path);
|
||||
|
||||
#endif
|
|
@ -4,6 +4,8 @@
|
|||
#include <strings.h>
|
||||
#include "list.h"
|
||||
#include "pool-buffer.h"
|
||||
#include "cursor-shape-v1-client-protocol.h"
|
||||
|
||||
#include "swaynag/types.h"
|
||||
|
||||
#define SWAYNAG_MAX_HEIGHT 500
|
||||
|
@ -85,6 +87,7 @@ struct swaynag {
|
|||
struct swaynag_output *output;
|
||||
struct zwlr_layer_shell_v1 *layer_shell;
|
||||
struct zwlr_layer_surface_v1 *layer_surface;
|
||||
struct wp_cursor_shape_manager_v1 *cursor_shape_manager;
|
||||
struct wl_surface *surface;
|
||||
|
||||
uint32_t width;
|
||||
|
|
|
@ -18,6 +18,7 @@ add_project_arguments(
|
|||
'-Wno-unused-parameter',
|
||||
'-Wno-unused-result',
|
||||
'-Wno-missing-braces',
|
||||
'-Wno-format-zero-length',
|
||||
'-Wundef',
|
||||
'-Wvla',
|
||||
],
|
||||
|
@ -36,7 +37,7 @@ if is_freebsd
|
|||
endif
|
||||
|
||||
# Execute the wlroots subproject, if any
|
||||
wlroots_version = ['>=0.17.0', '<0.18.0']
|
||||
wlroots_version = ['>=0.18.0', '<0.19.0']
|
||||
subproject(
|
||||
'wlroots',
|
||||
default_options: ['examples=false'],
|
||||
|
@ -47,7 +48,6 @@ wlroots = dependency('wlroots', version: wlroots_version)
|
|||
wlroots_features = {
|
||||
'xwayland': false,
|
||||
'libinput_backend': false,
|
||||
'gles2_renderer': false,
|
||||
'session': false,
|
||||
}
|
||||
foreach name, _ : wlroots_features
|
||||
|
@ -74,7 +74,6 @@ pango = dependency('pango')
|
|||
pangocairo = dependency('pangocairo')
|
||||
gdk_pixbuf = dependency('gdk-pixbuf-2.0', required: get_option('gdk-pixbuf'))
|
||||
pixman = dependency('pixman-1')
|
||||
glesv2 = wlroots_features['gles2_renderer'] ? dependency('glesv2') : null_dep
|
||||
libevdev = dependency('libevdev')
|
||||
libinput = wlroots_features['libinput_backend'] ? dependency('libinput', version: '>=1.21.0') : null_dep
|
||||
xcb = dependency('xcb', required: get_option('xwayland'))
|
||||
|
|
|
@ -2,7 +2,7 @@ wl_protocol_dir = wayland_protos.get_variable('pkgdatadir')
|
|||
|
||||
wayland_scanner_dep = dependency('wayland-scanner', native: true)
|
||||
wayland_scanner = find_program(
|
||||
wayland_scanner_dep.get_variable(pkgconfig: 'wayland_scanner'),
|
||||
wayland_scanner_dep.get_variable('wayland_scanner'),
|
||||
native: true,
|
||||
)
|
||||
|
||||
|
@ -13,9 +13,9 @@ protocols = [
|
|||
wl_protocol_dir / 'unstable/tablet/tablet-unstable-v2.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',
|
||||
'wlr-layer-shell-unstable-v1.xml',
|
||||
'idle.xml',
|
||||
'wlr-input-inhibitor-unstable-v1.xml',
|
||||
'wlr-output-power-management-unstable-v1.xml',
|
||||
]
|
||||
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="wlr_input_inhibit_unstable_v1">
|
||||
<copyright>
|
||||
Copyright © 2018 Drew DeVault
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that copyright notice and this permission
|
||||
notice appear in supporting documentation, and that the name of
|
||||
the copyright holders not be used in advertising or publicity
|
||||
pertaining to distribution of the software without specific,
|
||||
written prior permission. The copyright holders make no
|
||||
representations about the suitability of this software for any
|
||||
purpose. It is provided "as is" without express or implied
|
||||
warranty.
|
||||
|
||||
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="zwlr_input_inhibit_manager_v1" version="1">
|
||||
<description summary="inhibits input events to other clients">
|
||||
Clients can use this interface to prevent input events from being sent to
|
||||
any surfaces but its own, which is useful for example in lock screen
|
||||
software. It is assumed that access to this interface will be locked down
|
||||
to whitelisted clients by the compositor.
|
||||
</description>
|
||||
|
||||
<request name="get_inhibitor">
|
||||
<description summary="inhibit input to other clients">
|
||||
Activates the input inhibitor. As long as the inhibitor is active, the
|
||||
compositor will not send input events to other clients.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zwlr_input_inhibitor_v1"/>
|
||||
</request>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="already_inhibited" value="0" summary="an input inhibitor is already in use on the compositor"/>
|
||||
</enum>
|
||||
</interface>
|
||||
|
||||
<interface name="zwlr_input_inhibitor_v1" version="1">
|
||||
<description summary="inhibits input to other clients">
|
||||
While this resource exists, input to clients other than the owner of the
|
||||
inhibitor resource will not receive input events. The client that owns
|
||||
this resource will receive all input events normally. The compositor will
|
||||
also disable all of its own input processing (such as keyboard shortcuts)
|
||||
while the inhibitor is active.
|
||||
|
||||
The compositor may continue to send input events to selected clients,
|
||||
such as an on-screen keyboard (via the input-method protocol).
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the input inhibitor object">
|
||||
Destroy the inhibitor and allow other clients to receive input.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
|
@ -381,10 +381,13 @@ struct cmd_results *config_command(char *exec, char **new_block) {
|
|||
sway_log(SWAY_INFO, "Config command: %s", exec);
|
||||
const struct cmd_handler *handler = find_core_handler(argv[0]);
|
||||
if (!handler || !handler->handle) {
|
||||
const char *error = handler
|
||||
? "Command '%s' is shimmed, but unimplemented"
|
||||
: "Unknown/invalid command '%s'";
|
||||
results = cmd_results_new(CMD_INVALID, error, argv[0]);
|
||||
if (handler) {
|
||||
results = cmd_results_new(CMD_INVALID,
|
||||
"Command '%s' is shimmed, but unimplemented", argv[0]);
|
||||
} else {
|
||||
results = cmd_results_new(CMD_INVALID,
|
||||
"Unknown/invalid command '%s'", argv[0]);
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
@ -486,20 +489,10 @@ struct cmd_results *cmd_results_new(enum cmd_status status,
|
|||
}
|
||||
results->status = status;
|
||||
if (format) {
|
||||
char *error = NULL;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int slen = vsnprintf(NULL, 0, format, args);
|
||||
results->error = vformat_str(format, args);
|
||||
va_end(args);
|
||||
if (slen > 0) {
|
||||
error = malloc(slen + 1);
|
||||
if (error != NULL) {
|
||||
va_start(args, format);
|
||||
vsnprintf(error, slen + 1, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
results->error = error;
|
||||
} else {
|
||||
results->error = NULL;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ struct cmd_results *cmd_assign(int argc, char **argv) {
|
|||
char *err_str = NULL;
|
||||
struct criteria *criteria = criteria_parse(argv[0], &err_str);
|
||||
if (!criteria) {
|
||||
error = cmd_results_new(CMD_INVALID, err_str);
|
||||
error = cmd_results_new(CMD_INVALID, "%s", err_str);
|
||||
free(err_str);
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -73,12 +73,10 @@ struct cmd_results *cmd_bar(int argc, char **argv) {
|
|||
}
|
||||
++argv; --argc;
|
||||
} else if (config->reading && !config->current_bar) {
|
||||
int len = snprintf(NULL, 0, "bar-%d", config->bars->length) + 1;
|
||||
id = malloc(len * sizeof(char));
|
||||
id = format_str("bar-%d", config->bars->length);
|
||||
if (!id) {
|
||||
return cmd_results_new(CMD_FAILURE, "Unable to allocate bar id");
|
||||
}
|
||||
snprintf(id, len, "bar-%d", config->bars->length);
|
||||
} else if (!config->reading && strcmp(argv[0], "mode") != 0 &&
|
||||
strcmp(argv[0], "hidden_state") != 0) {
|
||||
if (is_subcommand(argv[0])) {
|
||||
|
|
|
@ -96,7 +96,7 @@ static struct cmd_results *bar_cmd_bind(int argc, char **argv, bool code,
|
|||
}
|
||||
if (message) {
|
||||
free_bar_binding(binding);
|
||||
error = cmd_results_new(CMD_INVALID, message);
|
||||
error = cmd_results_new(CMD_INVALID, "%s", message);
|
||||
free(message);
|
||||
return error;
|
||||
} else if (!binding->button) {
|
||||
|
|
|
@ -26,7 +26,7 @@ static struct cmd_results *tray_bind(int argc, char **argv, bool code) {
|
|||
}
|
||||
if (message) {
|
||||
free(binding);
|
||||
error = cmd_results_new(CMD_INVALID, message);
|
||||
error = cmd_results_new(CMD_INVALID, "%s", message);
|
||||
free(message);
|
||||
return error;
|
||||
} else if (!binding->button) {
|
||||
|
|
|
@ -127,7 +127,7 @@ static struct cmd_results *identify_key(const char* name, bool first_key,
|
|||
if (!button) {
|
||||
if (message) {
|
||||
struct cmd_results *error =
|
||||
cmd_results_new(CMD_INVALID, message);
|
||||
cmd_results_new(CMD_INVALID, "%s", message);
|
||||
free(message);
|
||||
return error;
|
||||
} else {
|
||||
|
@ -143,7 +143,7 @@ static struct cmd_results *identify_key(const char* name, bool first_key,
|
|||
if (!button) {
|
||||
if (message) {
|
||||
struct cmd_results *error =
|
||||
cmd_results_new(CMD_INVALID, message);
|
||||
cmd_results_new(CMD_INVALID, "%s", message);
|
||||
free(message);
|
||||
return error;
|
||||
} else {
|
||||
|
@ -182,7 +182,7 @@ static struct cmd_results *identify_key(const char* name, bool first_key,
|
|||
uint32_t button = get_mouse_bindsym(name, &message);
|
||||
if (message) {
|
||||
struct cmd_results *error =
|
||||
cmd_results_new(CMD_INVALID, message);
|
||||
cmd_results_new(CMD_INVALID, "%s", message);
|
||||
free(message);
|
||||
return error;
|
||||
} else if (button) {
|
||||
|
@ -539,7 +539,7 @@ struct cmd_results *cmd_bind_or_unbind_switch(int argc, char **argv,
|
|||
free_switch_binding(binding);
|
||||
return cmd_results_new(CMD_FAILURE,
|
||||
"Invalid %s command (expected binding with the form "
|
||||
"<switch>:<state>)", bindtype, argc);
|
||||
"<switch>:<state>)", bindtype);
|
||||
}
|
||||
if (strcmp(split->items[0], "tablet") == 0) {
|
||||
binding->type = WLR_SWITCH_TYPE_TABLET_MODE;
|
||||
|
@ -549,7 +549,8 @@ struct cmd_results *cmd_bind_or_unbind_switch(int argc, char **argv,
|
|||
free_switch_binding(binding);
|
||||
return cmd_results_new(CMD_FAILURE,
|
||||
"Invalid %s command (expected switch binding: "
|
||||
"unknown switch %s)", bindtype, split->items[0]);
|
||||
"unknown switch %s)", bindtype,
|
||||
(const char *)split->items[0]);
|
||||
}
|
||||
if (strcmp(split->items[1], "on") == 0) {
|
||||
binding->trigger = SWAY_SWITCH_TRIGGER_ON;
|
||||
|
@ -562,7 +563,7 @@ struct cmd_results *cmd_bind_or_unbind_switch(int argc, char **argv,
|
|||
return cmd_results_new(CMD_FAILURE,
|
||||
"Invalid %s command "
|
||||
"(expected switch state: unknown state %s)",
|
||||
bindtype, split->items[1]);
|
||||
bindtype, (const char *)split->items[1]);
|
||||
}
|
||||
list_free_items_and_destroy(split);
|
||||
|
||||
|
|
|
@ -23,16 +23,16 @@ static struct cmd_results *handle_command(int argc, char **argv, char *cmd_name,
|
|||
char *err;
|
||||
int width = (int)strtol(argv[0], &err, 10);
|
||||
if (*err) {
|
||||
return cmd_results_new(CMD_INVALID, cmd_name, usage);
|
||||
return cmd_results_new(CMD_INVALID, "%s", usage);
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "x") != 0) {
|
||||
return cmd_results_new(CMD_INVALID, cmd_name, usage);
|
||||
return cmd_results_new(CMD_INVALID, "%s", usage);
|
||||
}
|
||||
|
||||
int height = (int)strtol(argv[2], &err, 10);
|
||||
if (*err) {
|
||||
return cmd_results_new(CMD_INVALID, cmd_name, usage);
|
||||
return cmd_results_new(CMD_INVALID, "%s", usage);
|
||||
}
|
||||
|
||||
*config_width = width;
|
||||
|
|
|
@ -14,7 +14,7 @@ struct cmd_results *cmd_for_window(int argc, char **argv) {
|
|||
char *err_str = NULL;
|
||||
struct criteria *criteria = criteria_parse(argv[0], &err_str);
|
||||
if (!criteria) {
|
||||
error = cmd_results_new(CMD_INVALID, err_str);
|
||||
error = cmd_results_new(CMD_INVALID, "%s", err_str);
|
||||
free(err_str);
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ struct cmd_results *cmd_hide_edge_borders(int argc, char **argv) {
|
|||
}
|
||||
|
||||
if (!argc) {
|
||||
return cmd_results_new(CMD_INVALID, expected_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
|
||||
}
|
||||
|
||||
if (strcmp(argv[0], "none") == 0) {
|
||||
|
@ -38,7 +38,7 @@ struct cmd_results *cmd_hide_edge_borders(int argc, char **argv) {
|
|||
config->hide_edge_borders = E_NONE;
|
||||
config->hide_edge_borders_smart = ESMART_NO_GAPS;
|
||||
} else {
|
||||
return cmd_results_new(CMD_INVALID, expected_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
|
||||
}
|
||||
config->hide_lone_tab = hide_lone_tab;
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ struct cmd_results *cmd_inhibit_idle(int argc, char **argv) {
|
|||
sway_idle_inhibit_v1_user_inhibitor_destroy(inhibitor);
|
||||
} else {
|
||||
inhibitor->mode = mode;
|
||||
sway_idle_inhibit_v1_check_active(server.idle_inhibit_manager_v1);
|
||||
sway_idle_inhibit_v1_check_active();
|
||||
}
|
||||
} else if (!clear) {
|
||||
sway_idle_inhibit_v1_user_inhibitor_register(con->view, mode);
|
||||
|
|
|
@ -27,6 +27,7 @@ static const struct cmd_handler input_handlers[] = {
|
|||
{ "repeat_rate", input_cmd_repeat_rate },
|
||||
{ "rotation_angle", input_cmd_rotation_angle },
|
||||
{ "scroll_button", input_cmd_scroll_button },
|
||||
{ "scroll_button_lock", input_cmd_scroll_button_lock },
|
||||
{ "scroll_factor", input_cmd_scroll_factor },
|
||||
{ "scroll_method", input_cmd_scroll_method },
|
||||
{ "tap", input_cmd_tap },
|
||||
|
|
|
@ -11,11 +11,21 @@ static bool parse_coords(const char *str, double *x, double *y, bool *mm) {
|
|||
*mm = false;
|
||||
|
||||
char *end;
|
||||
*x = strtod(str, &end);
|
||||
if (end[0] != 'x') {
|
||||
return false;
|
||||
|
||||
// Check for "0x" prefix to avoid strtod treating the string as hex
|
||||
if (str[0] == '0' && str[1] == 'x') {
|
||||
if (strlen(str) < 3) {
|
||||
return false;
|
||||
}
|
||||
*x = 0;
|
||||
end = (char *)str + 2;
|
||||
} else {
|
||||
*x = strtod(str, &end);
|
||||
if (end[0] != 'x') {
|
||||
return false;
|
||||
}
|
||||
++end;
|
||||
}
|
||||
++end;
|
||||
|
||||
*y = strtod(end, &end);
|
||||
if (end[0] == 'm') {
|
||||
|
|
|
@ -49,5 +49,5 @@ struct cmd_results *input_cmd_map_to_region(int argc, char **argv) {
|
|||
error:
|
||||
free(ic->mapped_to_region);
|
||||
ic->mapped_to_region = NULL;
|
||||
return cmd_results_new(CMD_FAILURE, errstr);
|
||||
return cmd_results_new(CMD_FAILURE, "%s", errstr);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ struct cmd_results *input_cmd_scroll_button(int argc, char **argv) {
|
|||
char *message = NULL;
|
||||
uint32_t button = get_mouse_button(*argv, &message);
|
||||
if (message) {
|
||||
error = cmd_results_new(CMD_INVALID, message);
|
||||
error = cmd_results_new(CMD_INVALID, "%s", message);
|
||||
free(message);
|
||||
return error;
|
||||
} else if (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN
|
||||
|
|
26
sway/commands/input/scroll_button_lock.c
Normal file
26
sway/commands/input/scroll_button_lock.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
#include <libinput.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include "sway/config.h"
|
||||
#include "sway/commands.h"
|
||||
#include "sway/input/input-manager.h"
|
||||
#include "util.h"
|
||||
|
||||
struct cmd_results *input_cmd_scroll_button_lock(int argc, char **argv) {
|
||||
struct cmd_results *error = NULL;
|
||||
if ((error = checkarg(argc, "scroll_button_lock", EXPECTED_AT_LEAST, 1))) {
|
||||
return error;
|
||||
}
|
||||
struct input_config *ic = config->handler_context.input_config;
|
||||
if (!ic) {
|
||||
return cmd_results_new(CMD_FAILURE, "No input device defined.");
|
||||
}
|
||||
|
||||
if (parse_boolean(argv[0], true)) {
|
||||
ic->scroll_button_lock = LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED;
|
||||
} else {
|
||||
ic->scroll_button_lock = LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED;
|
||||
}
|
||||
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
}
|
|
@ -153,7 +153,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
|
|||
workspace->output);
|
||||
}
|
||||
if (new_layout == L_NONE) {
|
||||
return cmd_results_new(CMD_INVALID, expected_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
|
||||
}
|
||||
if (new_layout != old_layout) {
|
||||
if (container) {
|
||||
|
|
|
@ -470,7 +470,7 @@ static struct cmd_results *cmd_move_container(bool no_auto_back_and_forth,
|
|||
if (strcasecmp(argv[1], "number") == 0) {
|
||||
// move [window|container] [to] "workspace number x"
|
||||
if (argc < 3) {
|
||||
return cmd_results_new(CMD_INVALID, expected_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
|
||||
}
|
||||
if (!isdigit(argv[2][0])) {
|
||||
return cmd_results_new(CMD_INVALID,
|
||||
|
@ -530,7 +530,7 @@ static struct cmd_results *cmd_move_container(bool no_auto_back_and_forth,
|
|||
}
|
||||
destination = &dest_con->node;
|
||||
} else {
|
||||
return cmd_results_new(CMD_INVALID, expected_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
|
||||
}
|
||||
|
||||
if (destination->type == N_CONTAINER &&
|
||||
|
@ -829,7 +829,7 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
|
|||
}
|
||||
|
||||
if (!argc) {
|
||||
return cmd_results_new(CMD_INVALID, expected_position_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax);
|
||||
}
|
||||
|
||||
bool absolute = false;
|
||||
|
@ -839,19 +839,19 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
|
|||
++argv;
|
||||
}
|
||||
if (!argc) {
|
||||
return cmd_results_new(CMD_INVALID, expected_position_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax);
|
||||
}
|
||||
if (strcmp(argv[0], "position") == 0) {
|
||||
--argc;
|
||||
++argv;
|
||||
}
|
||||
if (!argc) {
|
||||
return cmd_results_new(CMD_INVALID, expected_position_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax);
|
||||
}
|
||||
if (strcmp(argv[0], "cursor") == 0 || strcmp(argv[0], "mouse") == 0 ||
|
||||
strcmp(argv[0], "pointer") == 0) {
|
||||
if (absolute) {
|
||||
return cmd_results_new(CMD_INVALID, expected_position_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax);
|
||||
}
|
||||
return cmd_move_to_position_pointer(container);
|
||||
} else if (strcmp(argv[0], "center") == 0) {
|
||||
|
@ -873,7 +873,7 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
|
|||
}
|
||||
|
||||
if (argc < 2) {
|
||||
return cmd_results_new(CMD_FAILURE, expected_position_syntax);
|
||||
return cmd_results_new(CMD_FAILURE, "%s", expected_position_syntax);
|
||||
}
|
||||
|
||||
struct movement_amount lx = { .amount = 0, .unit = MOVEMENT_UNIT_INVALID };
|
||||
|
@ -886,7 +886,7 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
|
|||
}
|
||||
|
||||
if (argc < 1) {
|
||||
return cmd_results_new(CMD_FAILURE, expected_position_syntax);
|
||||
return cmd_results_new(CMD_FAILURE, "%s", expected_position_syntax);
|
||||
}
|
||||
|
||||
struct movement_amount ly = { .amount = 0, .unit = MOVEMENT_UNIT_INVALID };
|
||||
|
@ -895,7 +895,7 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
|
|||
argc -= num_consumed_args;
|
||||
argv += num_consumed_args;
|
||||
if (argc > 0) {
|
||||
return cmd_results_new(CMD_INVALID, expected_position_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax);
|
||||
}
|
||||
if (ly.unit == MOVEMENT_UNIT_INVALID) {
|
||||
return cmd_results_new(CMD_INVALID, "Invalid y position specified");
|
||||
|
@ -1041,13 +1041,13 @@ struct cmd_results *cmd_move(int argc, char **argv) {
|
|||
}
|
||||
|
||||
if (!argc) {
|
||||
return cmd_results_new(CMD_INVALID, expected_full_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_full_syntax);
|
||||
}
|
||||
|
||||
// Only `move [window|container] [to] workspace` supports
|
||||
// `--no-auto-back-and-forth` so treat others as invalid syntax
|
||||
if (no_auto_back_and_forth && strcasecmp(argv[0], "workspace") != 0) {
|
||||
return cmd_results_new(CMD_INVALID, expected_full_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_full_syntax);
|
||||
}
|
||||
|
||||
if (strcasecmp(argv[0], "workspace") == 0 ||
|
||||
|
@ -1061,5 +1061,5 @@ struct cmd_results *cmd_move(int argc, char **argv) {
|
|||
strcasecmp(argv[1], "position") == 0)) {
|
||||
return cmd_move_to_position(argc, argv);
|
||||
}
|
||||
return cmd_results_new(CMD_INVALID, expected_full_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_full_syntax);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ struct cmd_results *cmd_no_focus(int argc, char **argv) {
|
|||
char *err_str = NULL;
|
||||
struct criteria *criteria = criteria_parse(argv[0], &err_str);
|
||||
if (!criteria) {
|
||||
error = cmd_results_new(CMD_INVALID, err_str);
|
||||
error = cmd_results_new(CMD_INVALID, "%s", err_str);
|
||||
free(err_str);
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <string.h>
|
||||
#include <wlr/util/transform.h>
|
||||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
#include "log.h"
|
||||
|
|
|
@ -26,7 +26,7 @@ struct cmd_results *cmd_rename(int argc, char **argv) {
|
|||
"Can't run this command while there's no outputs connected.");
|
||||
}
|
||||
if (strcasecmp(argv[0], "workspace") != 0) {
|
||||
return cmd_results_new(CMD_INVALID, expected_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
|
||||
}
|
||||
|
||||
int argn = 1;
|
||||
|
@ -65,7 +65,7 @@ struct cmd_results *cmd_rename(int argc, char **argv) {
|
|||
++argn; // move past "to"
|
||||
|
||||
if (argn >= argc) {
|
||||
return cmd_results_new(CMD_INVALID, expected_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
|
||||
}
|
||||
|
||||
char *new_name = join_args(argv + argn, argc - argn);
|
||||
|
|
|
@ -75,6 +75,10 @@ void container_resize_tiled(struct sway_container *con,
|
|||
return;
|
||||
}
|
||||
|
||||
if (container_is_scratchpad_hidden_or_child(con)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -249,16 +253,35 @@ static struct cmd_results *resize_adjust_tiled(uint32_t axis,
|
|||
struct movement_amount *amount) {
|
||||
struct sway_container *current = config->handler_context.container;
|
||||
|
||||
if (container_is_scratchpad_hidden_or_child(current)) {
|
||||
return cmd_results_new(CMD_FAILURE, "Cannot resize a hidden scratchpad container");
|
||||
}
|
||||
|
||||
if (amount->unit == MOVEMENT_UNIT_DEFAULT) {
|
||||
amount->unit = MOVEMENT_UNIT_PPT;
|
||||
}
|
||||
if (amount->unit == MOVEMENT_UNIT_PPT) {
|
||||
struct sway_container *parent = current->pending.parent;
|
||||
float pct = amount->amount / 100.0f;
|
||||
|
||||
if (is_horizontal(axis)) {
|
||||
amount->amount = (float)current->pending.width * pct;
|
||||
while (parent && parent->pending.layout != L_HORIZ) {
|
||||
parent = parent->pending.parent;
|
||||
}
|
||||
if (parent) {
|
||||
amount->amount = (float)parent->pending.width * pct;
|
||||
} else {
|
||||
amount->amount = (float)current->pending.workspace->width * pct;
|
||||
}
|
||||
} else {
|
||||
amount->amount = (float)current->pending.height * pct;
|
||||
while (parent && parent->pending.layout != L_VERT) {
|
||||
parent = parent->pending.parent;
|
||||
}
|
||||
if (parent) {
|
||||
amount->amount = (float)parent->pending.height * pct;
|
||||
} else {
|
||||
amount->amount = (float)current->pending.workspace->height * pct;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,6 +300,11 @@ static struct cmd_results *resize_adjust_tiled(uint32_t axis,
|
|||
*/
|
||||
static struct cmd_results *resize_set_tiled(struct sway_container *con,
|
||||
struct movement_amount *width, struct movement_amount *height) {
|
||||
|
||||
if (container_is_scratchpad_hidden_or_child(con)) {
|
||||
return cmd_results_new(CMD_FAILURE, "Cannot resize a hidden scratchpad container");
|
||||
}
|
||||
|
||||
if (width->amount) {
|
||||
if (width->unit == MOVEMENT_UNIT_PPT ||
|
||||
width->unit == MOVEMENT_UNIT_DEFAULT) {
|
||||
|
@ -415,7 +443,7 @@ static struct cmd_results *cmd_resize_set(int argc, char **argv) {
|
|||
argc -= num_consumed_args;
|
||||
argv += num_consumed_args;
|
||||
if (width.unit == MOVEMENT_UNIT_INVALID) {
|
||||
return cmd_results_new(CMD_INVALID, usage);
|
||||
return cmd_results_new(CMD_INVALID, "%s", usage);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -427,10 +455,10 @@ static struct cmd_results *cmd_resize_set(int argc, char **argv) {
|
|||
}
|
||||
int num_consumed_args = parse_movement_amount(argc, argv, &height);
|
||||
if (argc > num_consumed_args) {
|
||||
return cmd_results_new(CMD_INVALID, usage);
|
||||
return cmd_results_new(CMD_INVALID, "%s", usage);
|
||||
}
|
||||
if (width.unit == MOVEMENT_UNIT_INVALID) {
|
||||
return cmd_results_new(CMD_INVALID, usage);
|
||||
return cmd_results_new(CMD_INVALID, "%s", usage);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -462,7 +490,7 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv,
|
|||
"[<amount> px|ppt [or <amount> px|ppt]]'";
|
||||
uint32_t axis = parse_resize_axis(*argv);
|
||||
if (axis == WLR_EDGE_NONE) {
|
||||
return cmd_results_new(CMD_INVALID, usage);
|
||||
return cmd_results_new(CMD_INVALID, "%s", usage);
|
||||
}
|
||||
--argc; ++argv;
|
||||
|
||||
|
@ -473,7 +501,7 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv,
|
|||
argc -= num_consumed_args;
|
||||
argv += num_consumed_args;
|
||||
if (first_amount.unit == MOVEMENT_UNIT_INVALID) {
|
||||
return cmd_results_new(CMD_INVALID, usage);
|
||||
return cmd_results_new(CMD_INVALID, "%s", usage);
|
||||
}
|
||||
} else {
|
||||
first_amount.amount = 10;
|
||||
|
@ -483,7 +511,7 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv,
|
|||
// "or"
|
||||
if (argc) {
|
||||
if (strcmp(*argv, "or") != 0) {
|
||||
return cmd_results_new(CMD_INVALID, usage);
|
||||
return cmd_results_new(CMD_INVALID, "%s", usage);
|
||||
}
|
||||
--argc; ++argv;
|
||||
}
|
||||
|
@ -493,10 +521,10 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv,
|
|||
if (argc) {
|
||||
int num_consumed_args = parse_movement_amount(argc, argv, &second_amount);
|
||||
if (argc > num_consumed_args) {
|
||||
return cmd_results_new(CMD_INVALID, usage);
|
||||
return cmd_results_new(CMD_INVALID, "%s", usage);
|
||||
}
|
||||
if (second_amount.unit == MOVEMENT_UNIT_INVALID) {
|
||||
return cmd_results_new(CMD_INVALID, usage);
|
||||
return cmd_results_new(CMD_INVALID, "%s", usage);
|
||||
}
|
||||
} else {
|
||||
second_amount.amount = 0;
|
||||
|
@ -566,5 +594,5 @@ struct cmd_results *cmd_resize(int argc, char **argv) {
|
|||
const char usage[] = "Expected 'resize <shrink|grow> "
|
||||
"<width|height|up|down|left|right> [<amount>] [px|ppt]'";
|
||||
|
||||
return cmd_results_new(CMD_INVALID, usage);
|
||||
return cmd_results_new(CMD_INVALID, "%s", usage);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ static struct cmd_results *handle_command(struct sway_cursor *cursor,
|
|||
int argc, char **argv) {
|
||||
if (strcasecmp(argv[0], "move") == 0) {
|
||||
if (argc < 3) {
|
||||
return cmd_results_new(CMD_INVALID, expected_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
|
||||
}
|
||||
int delta_x = strtol(argv[1], NULL, 10);
|
||||
int delta_y = strtol(argv[2], NULL, 10);
|
||||
|
@ -27,7 +27,7 @@ static struct cmd_results *handle_command(struct sway_cursor *cursor,
|
|||
wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
|
||||
} else if (strcasecmp(argv[0], "set") == 0) {
|
||||
if (argc < 3) {
|
||||
return cmd_results_new(CMD_INVALID, expected_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
|
||||
}
|
||||
// map absolute coords (0..1,0..1) to root container coords
|
||||
float x = strtof(argv[1], NULL) / root->width;
|
||||
|
@ -37,7 +37,7 @@ static struct cmd_results *handle_command(struct sway_cursor *cursor,
|
|||
wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
|
||||
} else {
|
||||
if (argc < 2) {
|
||||
return cmd_results_new(CMD_INVALID, expected_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
|
||||
}
|
||||
struct cmd_results *error = NULL;
|
||||
if ((error = press_or_release(cursor, argv[0], argv[1]))) {
|
||||
|
@ -92,14 +92,14 @@ static struct cmd_results *press_or_release(struct sway_cursor *cursor,
|
|||
} else if (strcasecmp(action, "release") == 0) {
|
||||
state = WLR_BUTTON_RELEASED;
|
||||
} else {
|
||||
return cmd_results_new(CMD_INVALID, expected_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
|
||||
}
|
||||
|
||||
char *message = NULL;
|
||||
button = get_mouse_button(button_str, &message);
|
||||
if (message) {
|
||||
struct cmd_results *error =
|
||||
cmd_results_new(CMD_INVALID, message);
|
||||
cmd_results_new(CMD_INVALID, "%s", message);
|
||||
free(message);
|
||||
return error;
|
||||
} else if (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <stdint.h>
|
||||
#include "log.h"
|
||||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
#include "sway/input/seat.h"
|
||||
|
@ -69,5 +70,10 @@ struct cmd_results *seat_cmd_idle_wake(int argc, char **argv) {
|
|||
return cmd_results_new(CMD_FAILURE, "Invalid idle source");
|
||||
}
|
||||
config->handler_context.seat_config->idle_wake_sources = sources;
|
||||
sway_log(SWAY_INFO, "Warning: seat idle_wake is deprecated");
|
||||
if (config->reading) {
|
||||
config_add_swaynag_warning("seat idle_wake is deprecated. "
|
||||
"Only seat idle_inhibit is supported.");
|
||||
}
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ static struct cmd_results *do_split(int layout) {
|
|||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
}
|
||||
|
||||
static struct cmd_results *do_unsplit() {
|
||||
static struct cmd_results *do_unsplit(void) {
|
||||
struct sway_container *con = config->handler_context.container;
|
||||
struct sway_workspace *ws = config->handler_context.workspace;
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ struct cmd_results *cmd_swap(int argc, char **argv) {
|
|||
}
|
||||
|
||||
if (strcasecmp(argv[0], "container") || strcasecmp(argv[1], "with")) {
|
||||
return cmd_results_new(CMD_INVALID, expected_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
|
||||
}
|
||||
|
||||
struct sway_container *current = config->handler_context.container;
|
||||
|
@ -65,7 +65,7 @@ struct cmd_results *cmd_swap(int argc, char **argv) {
|
|||
other = root_find_container(test_mark, value);
|
||||
} else {
|
||||
free(value);
|
||||
return cmd_results_new(CMD_INVALID, expected_syntax);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
|
||||
}
|
||||
|
||||
if (!other) {
|
||||
|
|
|
@ -61,7 +61,7 @@ static struct cmd_results *cmd_workspace_gaps(int argc, char **argv,
|
|||
const char expected[] = "Expected 'workspace <name> gaps "
|
||||
"inner|outer|horizontal|vertical|top|right|bottom|left <px>'";
|
||||
if (gaps_location == 0) {
|
||||
return cmd_results_new(CMD_INVALID, expected);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected);
|
||||
}
|
||||
struct cmd_results *error = NULL;
|
||||
if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO,
|
||||
|
@ -79,7 +79,7 @@ static struct cmd_results *cmd_workspace_gaps(int argc, char **argv,
|
|||
char *end;
|
||||
int amount = strtol(argv[gaps_location + 2], &end, 10);
|
||||
if (strlen(end)) {
|
||||
return cmd_results_new(CMD_FAILURE, expected);
|
||||
return cmd_results_new(CMD_FAILURE, "%s", expected);
|
||||
}
|
||||
|
||||
bool valid = false;
|
||||
|
@ -110,7 +110,7 @@ static struct cmd_results *cmd_workspace_gaps(int argc, char **argv,
|
|||
}
|
||||
}
|
||||
if (!valid) {
|
||||
return cmd_results_new(CMD_INVALID, expected);
|
||||
return cmd_results_new(CMD_INVALID, "%s", expected);
|
||||
}
|
||||
|
||||
// Prevent invalid gaps configurations.
|
||||
|
@ -174,7 +174,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
|
|||
}
|
||||
|
||||
if (root->fullscreen_global) {
|
||||
return cmd_results_new(CMD_FAILURE, "workspace",
|
||||
return cmd_results_new(CMD_FAILURE,
|
||||
"Can't switch workspaces while fullscreen global");
|
||||
}
|
||||
|
||||
|
|
|
@ -924,23 +924,18 @@ void config_add_swaynag_warning(char *fmt, ...) {
|
|||
if (config->reading && !config->validating) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
size_t length = vsnprintf(NULL, 0, fmt, args) + 1;
|
||||
char *str = vformat_str(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
char *temp = malloc(length + 1);
|
||||
if (!temp) {
|
||||
sway_log(SWAY_ERROR, "Failed to allocate buffer for warning.");
|
||||
if (str == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
va_start(args, fmt);
|
||||
vsnprintf(temp, length, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
swaynag_log(config->swaynag_command, &config->swaynag_config_errors,
|
||||
"Warning on line %i (%s) '%s': %s",
|
||||
config->current_config_line_number, config->current_config_path,
|
||||
config->current_config_line, temp);
|
||||
config->current_config_line, str);
|
||||
|
||||
free(str);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ struct input_config *new_input_config(const char* identifier) {
|
|||
input->pointer_accel = FLT_MIN;
|
||||
input->scroll_factor = FLT_MIN;
|
||||
input->scroll_button = INT_MIN;
|
||||
input->scroll_button_lock = INT_MIN;
|
||||
input->scroll_method = INT_MIN;
|
||||
input->left_handed = INT_MIN;
|
||||
input->repeat_delay = INT_MIN;
|
||||
|
@ -96,6 +97,9 @@ void merge_input_config(struct input_config *dst, struct input_config *src) {
|
|||
if (src->scroll_button != INT_MIN) {
|
||||
dst->scroll_button = src->scroll_button;
|
||||
}
|
||||
if (src->scroll_button_lock != INT_MIN) {
|
||||
dst->scroll_button_lock = src->scroll_button_lock;
|
||||
}
|
||||
if (src->send_events != INT_MIN) {
|
||||
dst->send_events = src->send_events;
|
||||
}
|
||||
|
|
|
@ -153,25 +153,16 @@ static void merge_wildcard_on_all(struct output_config *wildcard) {
|
|||
}
|
||||
|
||||
static void merge_id_on_name(struct output_config *oc) {
|
||||
char *id_on_name = NULL;
|
||||
char id[128];
|
||||
char *name = NULL;
|
||||
struct sway_output *output;
|
||||
wl_list_for_each(output, &root->all_outputs, link) {
|
||||
name = output->wlr_output->name;
|
||||
output_get_identifier(id, sizeof(id), output);
|
||||
if (strcmp(name, oc->name) == 0 || strcmp(id, oc->name) == 0) {
|
||||
size_t length = snprintf(NULL, 0, "%s on %s", id, name) + 1;
|
||||
id_on_name = malloc(length);
|
||||
if (!id_on_name) {
|
||||
sway_log(SWAY_ERROR, "Failed to allocate id on name string");
|
||||
return;
|
||||
}
|
||||
snprintf(id_on_name, length, "%s on %s", id, name);
|
||||
break;
|
||||
}
|
||||
struct sway_output *output = all_output_by_name_or_id(oc->name);
|
||||
if (output == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *name = output->wlr_output->name;
|
||||
char id[128];
|
||||
output_get_identifier(id, sizeof(id), output);
|
||||
|
||||
char *id_on_name = format_str("%s on %s", id, name);
|
||||
if (!id_on_name) {
|
||||
return;
|
||||
}
|
||||
|
@ -258,6 +249,8 @@ static void set_mode(struct wlr_output *output, struct wlr_output_state *pending
|
|||
// as (int)(1000 * mHz / 1000.f)
|
||||
// round() the result to avoid any error
|
||||
int mhz = (int)roundf(refresh_rate * 1000);
|
||||
// If no target refresh rate is given, match highest available
|
||||
mhz = mhz <= 0 ? INT_MAX : mhz;
|
||||
|
||||
if (wl_list_empty(&output->modes) || custom) {
|
||||
sway_log(SWAY_DEBUG, "Assigning custom mode to %s", output->name);
|
||||
|
@ -267,23 +260,28 @@ static void set_mode(struct wlr_output *output, struct wlr_output_state *pending
|
|||
}
|
||||
|
||||
struct wlr_output_mode *mode, *best = NULL;
|
||||
int best_diff_mhz = INT_MAX;
|
||||
wl_list_for_each(mode, &output->modes, link) {
|
||||
if (mode->width == width && mode->height == height) {
|
||||
if (mode->refresh == mhz) {
|
||||
best = mode;
|
||||
break;
|
||||
}
|
||||
if (best == NULL || mode->refresh > best->refresh) {
|
||||
int diff_mhz = abs(mode->refresh - mhz);
|
||||
if (diff_mhz < best_diff_mhz) {
|
||||
best_diff_mhz = diff_mhz;
|
||||
best = mode;
|
||||
if (best_diff_mhz == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!best) {
|
||||
sway_log(SWAY_ERROR, "Configured mode for %s not available", output->name);
|
||||
sway_log(SWAY_INFO, "Picking preferred mode instead");
|
||||
best = wlr_output_preferred_mode(output);
|
||||
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 {
|
||||
sway_log(SWAY_DEBUG, "Assigning configured mode to %s", output->name);
|
||||
best = wlr_output_preferred_mode(output);
|
||||
sway_log(SWAY_INFO, "Configured mode (%dx%d@%.3fHz) not available, "
|
||||
"applying preferred mode (%dx%d@%.3fHz)",
|
||||
width, height, refresh_rate,
|
||||
best->width, best->height, best->refresh / 1000.f);
|
||||
}
|
||||
wlr_output_state_set_mode(pending, best);
|
||||
}
|
||||
|
@ -519,10 +517,6 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) {
|
|||
struct wlr_output_state pending = {0};
|
||||
queue_output_config(oc, output, &pending);
|
||||
|
||||
if (!oc || oc->power != 0) {
|
||||
output->current_mode = pending.mode;
|
||||
}
|
||||
|
||||
sway_log(SWAY_DEBUG, "Committing output %s", wlr_output->name);
|
||||
if (!wlr_output_commit_state(wlr_output, &pending)) {
|
||||
// Failed to commit output changes, maybe the output is missing a CRTC.
|
||||
|
@ -596,7 +590,7 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) {
|
|||
// Reconfigure all devices, since input config may have been applied before
|
||||
// this output came online, and some config items (like map_to_output) are
|
||||
// dependent on an output being present.
|
||||
input_manager_configure_all_inputs();
|
||||
input_manager_configure_all_input_mappings();
|
||||
// Reconfigure the cursor images, since the scale may have changed.
|
||||
input_manager_configure_xcursor();
|
||||
return true;
|
||||
|
@ -639,9 +633,7 @@ static struct output_config *get_output_config(char *identifier,
|
|||
struct output_config *oc_name = NULL;
|
||||
struct output_config *oc_id = NULL;
|
||||
|
||||
size_t length = snprintf(NULL, 0, "%s on %s", identifier, name) + 1;
|
||||
char *id_on_name = malloc(length);
|
||||
snprintf(id_on_name, length, "%s on %s", identifier, name);
|
||||
char *id_on_name = format_str("%s on %s", identifier, name);
|
||||
int i = list_seq_find(config->output_configs, output_name_cmp, id_on_name);
|
||||
if (i >= 0) {
|
||||
oc_id_on_name = config->output_configs->items[i];
|
||||
|
@ -728,12 +720,11 @@ void apply_output_config_to_outputs(struct output_config *oc) {
|
|||
// this is during startup then there will be no container and config
|
||||
// will be applied during normal "new output" event from wlroots.
|
||||
bool wildcard = strcmp(oc->name, "*") == 0;
|
||||
char id[128];
|
||||
struct sway_output *sway_output, *tmp;
|
||||
wl_list_for_each_safe(sway_output, tmp, &root->all_outputs, link) {
|
||||
char *name = sway_output->wlr_output->name;
|
||||
output_get_identifier(id, sizeof(id), sway_output);
|
||||
if (wildcard || !strcmp(name, oc->name) || !strcmp(id, oc->name)) {
|
||||
if (output_match_name_or_id(sway_output, oc->name)) {
|
||||
char id[128];
|
||||
output_get_identifier(id, sizeof(id), sway_output);
|
||||
struct output_config *current = get_output_config(id, sway_output);
|
||||
if (!current) {
|
||||
// No stored output config matched, apply oc directly
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
bool criteria_is_empty(struct criteria *criteria) {
|
||||
return !criteria->title
|
||||
&& !criteria->shell
|
||||
&& !criteria->all
|
||||
&& !criteria->app_id
|
||||
&& !criteria->con_mark
|
||||
&& !criteria->con_id
|
||||
|
@ -456,6 +457,7 @@ static enum atom_name parse_window_type(const char *type) {
|
|||
#endif
|
||||
|
||||
enum criteria_token {
|
||||
T_ALL,
|
||||
T_APP_ID,
|
||||
T_CON_ID,
|
||||
T_CON_MARK,
|
||||
|
@ -478,7 +480,9 @@ enum criteria_token {
|
|||
};
|
||||
|
||||
static enum criteria_token token_from_name(char *name) {
|
||||
if (strcmp(name, "app_id") == 0) {
|
||||
if (strcmp(name, "all") == 0) {
|
||||
return T_ALL;
|
||||
} else if (strcmp(name, "app_id") == 0) {
|
||||
return T_APP_ID;
|
||||
} else if (strcmp(name, "con_id") == 0) {
|
||||
return T_CON_ID;
|
||||
|
@ -524,8 +528,8 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Require value, unless token is floating or tiled
|
||||
if (!value && token != T_FLOATING && token != T_TILING) {
|
||||
// Require value, unless token is all, floating or tiled
|
||||
if (!value && token != T_ALL && token != T_FLOATING && token != T_TILING) {
|
||||
const char *fmt = "Token '%s' requires a value";
|
||||
int len = strlen(fmt) + strlen(name) - 1;
|
||||
error = malloc(len);
|
||||
|
@ -535,6 +539,9 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) {
|
|||
|
||||
char *endptr = NULL;
|
||||
switch (token) {
|
||||
case T_ALL:
|
||||
criteria->all = true;
|
||||
break;
|
||||
case T_TITLE:
|
||||
pattern_create(&criteria->title, value);
|
||||
break;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include <stdlib.h>
|
||||
#include <wlr/types/wlr_idle.h>
|
||||
#include <wlr/types/wlr_idle_notify_v1.h>
|
||||
#include "log.h"
|
||||
#include "sway/desktop/idle_inhibit_v1.h"
|
||||
|
@ -12,7 +11,7 @@
|
|||
static void destroy_inhibitor(struct sway_idle_inhibitor_v1 *inhibitor) {
|
||||
wl_list_remove(&inhibitor->link);
|
||||
wl_list_remove(&inhibitor->destroy.link);
|
||||
sway_idle_inhibit_v1_check_active(inhibitor->manager);
|
||||
sway_idle_inhibit_v1_check_active();
|
||||
free(inhibitor);
|
||||
}
|
||||
|
||||
|
@ -35,7 +34,6 @@ void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) {
|
|||
return;
|
||||
}
|
||||
|
||||
inhibitor->manager = manager;
|
||||
inhibitor->mode = INHIBIT_IDLE_APPLICATION;
|
||||
inhibitor->wlr_inhibitor = wlr_inhibitor;
|
||||
wl_list_insert(&manager->inhibitors, &inhibitor->link);
|
||||
|
@ -43,33 +41,34 @@ void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) {
|
|||
inhibitor->destroy.notify = handle_destroy;
|
||||
wl_signal_add(&wlr_inhibitor->events.destroy, &inhibitor->destroy);
|
||||
|
||||
sway_idle_inhibit_v1_check_active(manager);
|
||||
sway_idle_inhibit_v1_check_active();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
struct sway_idle_inhibitor_v1 *inhibitor =
|
||||
calloc(1, sizeof(struct sway_idle_inhibitor_v1));
|
||||
if (!inhibitor) {
|
||||
return;
|
||||
}
|
||||
|
||||
inhibitor->manager = server.idle_inhibit_manager_v1;
|
||||
inhibitor->mode = mode;
|
||||
inhibitor->view = view;
|
||||
wl_list_insert(&inhibitor->manager->inhibitors, &inhibitor->link);
|
||||
wl_list_insert(&manager->inhibitors, &inhibitor->link);
|
||||
|
||||
inhibitor->destroy.notify = handle_destroy;
|
||||
wl_signal_add(&view->events.unmap, &inhibitor->destroy);
|
||||
|
||||
sway_idle_inhibit_v1_check_active(inhibitor->manager);
|
||||
sway_idle_inhibit_v1_check_active();
|
||||
}
|
||||
|
||||
struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_user_inhibitor_for_view(
|
||||
struct sway_view *view) {
|
||||
struct sway_idle_inhibit_manager_v1 *manager = &server.idle_inhibit_manager_v1;
|
||||
struct sway_idle_inhibitor_v1 *inhibitor;
|
||||
wl_list_for_each(inhibitor, &server.idle_inhibit_manager_v1->inhibitors,
|
||||
link) {
|
||||
wl_list_for_each(inhibitor, &manager->inhibitors, link) {
|
||||
if (inhibitor->mode != INHIBIT_IDLE_APPLICATION &&
|
||||
inhibitor->view == view) {
|
||||
return inhibitor;
|
||||
|
@ -80,9 +79,9 @@ struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_user_inhibitor_for_view(
|
|||
|
||||
struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_application_inhibitor_for_view(
|
||||
struct sway_view *view) {
|
||||
struct sway_idle_inhibit_manager_v1 *manager = &server.idle_inhibit_manager_v1;
|
||||
struct sway_idle_inhibitor_v1 *inhibitor;
|
||||
wl_list_for_each(inhibitor, &server.idle_inhibit_manager_v1->inhibitors,
|
||||
link) {
|
||||
wl_list_for_each(inhibitor, &manager->inhibitors, link) {
|
||||
if (inhibitor->mode == INHIBIT_IDLE_APPLICATION &&
|
||||
view_from_wlr_surface(inhibitor->wlr_inhibitor->surface) == view) {
|
||||
return inhibitor;
|
||||
|
@ -131,8 +130,8 @@ bool sway_idle_inhibit_v1_is_active(struct sway_idle_inhibitor_v1 *inhibitor) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void sway_idle_inhibit_v1_check_active(
|
||||
struct sway_idle_inhibit_manager_v1 *manager) {
|
||||
void sway_idle_inhibit_v1_check_active(void) {
|
||||
struct sway_idle_inhibit_manager_v1 *manager = &server.idle_inhibit_manager_v1;
|
||||
struct sway_idle_inhibitor_v1 *inhibitor;
|
||||
bool inhibited = false;
|
||||
wl_list_for_each(inhibitor, &manager->inhibitors, link) {
|
||||
|
@ -140,28 +139,21 @@ void sway_idle_inhibit_v1_check_active(
|
|||
break;
|
||||
}
|
||||
}
|
||||
wlr_idle_set_enabled(manager->idle, NULL, !inhibited);
|
||||
wlr_idle_notifier_v1_set_inhibited(server.idle_notifier_v1, inhibited);
|
||||
}
|
||||
|
||||
struct sway_idle_inhibit_manager_v1 *sway_idle_inhibit_manager_v1_create(
|
||||
struct wl_display *wl_display, struct wlr_idle *idle) {
|
||||
struct sway_idle_inhibit_manager_v1 *manager =
|
||||
calloc(1, sizeof(struct sway_idle_inhibit_manager_v1));
|
||||
if (!manager) {
|
||||
return NULL;
|
||||
bool sway_idle_inhibit_manager_v1_init(void) {
|
||||
struct sway_idle_inhibit_manager_v1 *manager = &server.idle_inhibit_manager_v1;
|
||||
|
||||
manager->wlr_manager = wlr_idle_inhibit_v1_create(server.wl_display);
|
||||
if (!manager->wlr_manager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
manager->wlr_manager = wlr_idle_inhibit_v1_create(wl_display);
|
||||
if (!manager->wlr_manager) {
|
||||
free(manager);
|
||||
return NULL;
|
||||
}
|
||||
manager->idle = idle;
|
||||
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_list_init(&manager->inhibitors);
|
||||
|
||||
return manager;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -228,7 +228,7 @@ struct launcher_ctx *launcher_ctx_create(struct wlr_xdg_activation_token_v1 *tok
|
|||
}
|
||||
|
||||
// Creates a context with a new token for the internal launcher
|
||||
struct launcher_ctx *launcher_ctx_create_internal() {
|
||||
struct launcher_ctx *launcher_ctx_create_internal(void) {
|
||||
struct sway_seat *seat = input_manager_current_seat();
|
||||
struct sway_workspace *ws = seat_get_focused_workspace(seat);
|
||||
if (!ws) {
|
||||
|
|
|
@ -17,6 +17,39 @@
|
|||
#include "sway/tree/arrange.h"
|
||||
#include "sway/tree/workspace.h"
|
||||
|
||||
struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface(
|
||||
struct wlr_surface *surface) {
|
||||
struct wlr_layer_surface_v1 *layer;
|
||||
do {
|
||||
if (!surface) {
|
||||
return NULL;
|
||||
}
|
||||
// Topmost layer surface
|
||||
if ((layer = wlr_layer_surface_v1_try_from_wlr_surface(surface))) {
|
||||
return layer;
|
||||
}
|
||||
// Layer subsurface
|
||||
if (wlr_subsurface_try_from_wlr_surface(surface)) {
|
||||
surface = wlr_surface_get_root_surface(surface);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Layer surface popup
|
||||
struct wlr_xdg_surface *xdg_surface = NULL;
|
||||
if ((xdg_surface = wlr_xdg_surface_try_from_wlr_surface(surface)) &&
|
||||
xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP && xdg_surface->popup != NULL) {
|
||||
if (!xdg_surface->popup->parent) {
|
||||
return NULL;
|
||||
}
|
||||
surface = wlr_surface_get_root_surface(xdg_surface->popup->parent);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Return early if the surface is not a layer/xdg_popup/sub surface
|
||||
return NULL;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
static void apply_exclusive(struct wlr_box *usable_area,
|
||||
uint32_t anchor, int32_t exclusive,
|
||||
int32_t margin_top, int32_t margin_right,
|
||||
|
@ -218,8 +251,9 @@ void arrange_layers(struct sway_output *output) {
|
|||
for (size_t i = 0; i < nlayers; ++i) {
|
||||
wl_list_for_each_reverse(layer,
|
||||
&output->layers[layers_above_shell[i]], link) {
|
||||
if (layer->layer_surface->current.keyboard_interactive &&
|
||||
layer->layer_surface->mapped) {
|
||||
if (layer->layer_surface->current.keyboard_interactive
|
||||
== ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE &&
|
||||
layer->layer_surface->surface->mapped) {
|
||||
topmost = layer;
|
||||
break;
|
||||
}
|
||||
|
@ -231,10 +265,12 @@ void arrange_layers(struct sway_output *output) {
|
|||
|
||||
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) {
|
||||
seat->focused_layer->current.keyboard_interactive
|
||||
!= ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) {
|
||||
seat_set_focus_layer(seat, NULL);
|
||||
}
|
||||
}
|
||||
|
@ -253,7 +289,7 @@ static struct sway_layer_surface *find_mapped_layer_by_client(
|
|||
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], link) {
|
||||
struct wl_resource *resource = lsurface->layer_surface->resource;
|
||||
if (wl_resource_get_client(resource) == client
|
||||
&& lsurface->layer_surface->mapped) {
|
||||
&& lsurface->layer_surface->surface->mapped) {
|
||||
return lsurface;
|
||||
}
|
||||
}
|
||||
|
@ -293,8 +329,8 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
|
|||
|
||||
bool layer_changed = false;
|
||||
if (layer_surface->current.committed != 0
|
||||
|| layer->mapped != layer_surface->mapped) {
|
||||
layer->mapped = layer_surface->mapped;
|
||||
|| layer->mapped != layer_surface->surface->mapped) {
|
||||
layer->mapped = layer_surface->surface->mapped;
|
||||
layer_changed = layer->layer != layer_surface->current.layer;
|
||||
if (layer_changed) {
|
||||
wl_list_remove(&layer->link);
|
||||
|
@ -312,6 +348,8 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
|
|||
bool extent_changed =
|
||||
memcmp(&old_extent, &layer->extent, sizeof(struct wlr_box)) != 0;
|
||||
if (extent_changed || layer_changed) {
|
||||
old_extent.x += output->lx;
|
||||
old_extent.y += output->ly;
|
||||
output_damage_box(output, &old_extent);
|
||||
output_damage_surface(output, layer->geo.x, layer->geo.y,
|
||||
layer_surface->surface, true);
|
||||
|
@ -347,7 +385,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
|
|||
wl_container_of(listener, sway_layer, destroy);
|
||||
sway_log(SWAY_DEBUG, "Layer surface destroyed (%s)",
|
||||
sway_layer->layer_surface->namespace);
|
||||
if (sway_layer->layer_surface->mapped) {
|
||||
if (sway_layer->layer_surface->surface->mapped) {
|
||||
unmap(sway_layer);
|
||||
}
|
||||
|
||||
|
@ -452,9 +490,9 @@ static struct sway_layer_subsurface *create_subsurface(
|
|||
wl_list_insert(&layer_surface->subsurfaces, &subsurface->link);
|
||||
|
||||
subsurface->map.notify = subsurface_handle_map;
|
||||
wl_signal_add(&wlr_subsurface->events.map, &subsurface->map);
|
||||
wl_signal_add(&wlr_subsurface->surface->events.map, &subsurface->map);
|
||||
subsurface->unmap.notify = subsurface_handle_unmap;
|
||||
wl_signal_add(&wlr_subsurface->events.unmap, &subsurface->unmap);
|
||||
wl_signal_add(&wlr_subsurface->surface->events.unmap, &subsurface->unmap);
|
||||
subsurface->destroy.notify = subsurface_handle_destroy;
|
||||
wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy);
|
||||
subsurface->commit.notify = subsurface_handle_commit;
|
||||
|
@ -504,36 +542,6 @@ static void popup_damage(struct sway_layer_popup *layer_popup, bool whole) {
|
|||
output_damage_surface(output, ox, oy, surface, whole);
|
||||
}
|
||||
|
||||
static void popup_handle_map(struct wl_listener *listener, void *data) {
|
||||
struct sway_layer_popup *popup = wl_container_of(listener, popup, map);
|
||||
struct sway_layer_surface *layer = popup_get_layer(popup);
|
||||
struct wlr_output *wlr_output = layer->layer_surface->output;
|
||||
sway_assert(wlr_output, "wlr_layer_surface_v1 has null output");
|
||||
surface_enter_output(popup->wlr_popup->base->surface, wlr_output->data);
|
||||
popup_damage(popup, true);
|
||||
}
|
||||
|
||||
static void popup_handle_unmap(struct wl_listener *listener, void *data) {
|
||||
struct sway_layer_popup *popup = wl_container_of(listener, popup, unmap);
|
||||
popup_damage(popup, true);
|
||||
}
|
||||
|
||||
static void popup_handle_commit(struct wl_listener *listener, void *data) {
|
||||
struct sway_layer_popup *popup = wl_container_of(listener, popup, commit);
|
||||
popup_damage(popup, false);
|
||||
}
|
||||
|
||||
static void popup_handle_destroy(struct wl_listener *listener, void *data) {
|
||||
struct sway_layer_popup *popup =
|
||||
wl_container_of(listener, popup, destroy);
|
||||
|
||||
wl_list_remove(&popup->map.link);
|
||||
wl_list_remove(&popup->unmap.link);
|
||||
wl_list_remove(&popup->destroy.link);
|
||||
wl_list_remove(&popup->commit.link);
|
||||
free(popup);
|
||||
}
|
||||
|
||||
static void popup_unconstrain(struct sway_layer_popup *popup) {
|
||||
struct sway_layer_surface *layer = popup_get_layer(popup);
|
||||
struct wlr_xdg_popup *wlr_popup = popup->wlr_popup;
|
||||
|
@ -554,6 +562,39 @@ static void popup_unconstrain(struct sway_layer_popup *popup) {
|
|||
wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box);
|
||||
}
|
||||
|
||||
static void popup_handle_map(struct wl_listener *listener, void *data) {
|
||||
struct sway_layer_popup *popup = wl_container_of(listener, popup, map);
|
||||
struct sway_layer_surface *layer = popup_get_layer(popup);
|
||||
struct wlr_output *wlr_output = layer->layer_surface->output;
|
||||
sway_assert(wlr_output, "wlr_layer_surface_v1 has null output");
|
||||
surface_enter_output(popup->wlr_popup->base->surface, wlr_output->data);
|
||||
popup_damage(popup, true);
|
||||
}
|
||||
|
||||
static void popup_handle_unmap(struct wl_listener *listener, void *data) {
|
||||
struct sway_layer_popup *popup = wl_container_of(listener, popup, unmap);
|
||||
popup_damage(popup, true);
|
||||
}
|
||||
|
||||
static void popup_handle_commit(struct wl_listener *listener, void *data) {
|
||||
struct sway_layer_popup *popup = wl_container_of(listener, popup, commit);
|
||||
if (popup->wlr_popup->base->initial_commit) {
|
||||
popup_unconstrain(popup);
|
||||
}
|
||||
popup_damage(popup, false);
|
||||
}
|
||||
|
||||
static void popup_handle_destroy(struct wl_listener *listener, void *data) {
|
||||
struct sway_layer_popup *popup =
|
||||
wl_container_of(listener, popup, destroy);
|
||||
|
||||
wl_list_remove(&popup->map.link);
|
||||
wl_list_remove(&popup->unmap.link);
|
||||
wl_list_remove(&popup->destroy.link);
|
||||
wl_list_remove(&popup->commit.link);
|
||||
free(popup);
|
||||
}
|
||||
|
||||
static void popup_handle_new_popup(struct wl_listener *listener, void *data);
|
||||
|
||||
static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup,
|
||||
|
@ -569,9 +610,9 @@ static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup,
|
|||
popup->parent_layer = parent;
|
||||
|
||||
popup->map.notify = popup_handle_map;
|
||||
wl_signal_add(&wlr_popup->base->events.map, &popup->map);
|
||||
wl_signal_add(&wlr_popup->base->surface->events.map, &popup->map);
|
||||
popup->unmap.notify = popup_handle_unmap;
|
||||
wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap);
|
||||
wl_signal_add(&wlr_popup->base->surface->events.unmap, &popup->unmap);
|
||||
popup->destroy.notify = popup_handle_destroy;
|
||||
wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
|
||||
popup->commit.notify = popup_handle_commit;
|
||||
|
@ -579,8 +620,6 @@ static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup,
|
|||
popup->new_popup.notify = popup_handle_new_popup;
|
||||
wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
|
||||
|
||||
popup_unconstrain(popup);
|
||||
|
||||
return popup;
|
||||
}
|
||||
|
||||
|
@ -659,9 +698,9 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
|
|||
sway_layer->destroy.notify = handle_destroy;
|
||||
wl_signal_add(&layer_surface->events.destroy, &sway_layer->destroy);
|
||||
sway_layer->map.notify = handle_map;
|
||||
wl_signal_add(&layer_surface->events.map, &sway_layer->map);
|
||||
wl_signal_add(&layer_surface->surface->events.map, &sway_layer->map);
|
||||
sway_layer->unmap.notify = handle_unmap;
|
||||
wl_signal_add(&layer_surface->events.unmap, &sway_layer->unmap);
|
||||
wl_signal_add(&layer_surface->surface->events.unmap, &sway_layer->unmap);
|
||||
sway_layer->new_popup.notify = handle_new_popup;
|
||||
wl_signal_add(&layer_surface->events.new_popup, &sway_layer->new_popup);
|
||||
sway_layer->new_subsurface.notify = handle_new_subsurface;
|
||||
|
|
|
@ -6,14 +6,17 @@
|
|||
#include <wayland-server-core.h>
|
||||
#include <wlr/config.h>
|
||||
#include <wlr/backend/headless.h>
|
||||
#include <wlr/render/swapchain.h>
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
#include <wlr/types/wlr_buffer.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.h>
|
||||
#include <wlr/types/wlr_presentation_time.h>
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/util/region.h>
|
||||
#include <wlr/util/transform.h>
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "sway/config.h"
|
||||
|
@ -36,13 +39,22 @@
|
|||
#include <wlr/types/wlr_drm_lease_v1.h>
|
||||
#endif
|
||||
|
||||
bool output_match_name_or_id(struct sway_output *output,
|
||||
const char *name_or_id) {
|
||||
if (strcmp(name_or_id, "*") == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
char identifier[128];
|
||||
output_get_identifier(identifier, sizeof(identifier), output);
|
||||
return strcasecmp(identifier, name_or_id) == 0
|
||||
|| strcasecmp(output->wlr_output->name, name_or_id) == 0;
|
||||
}
|
||||
|
||||
struct sway_output *output_by_name_or_id(const char *name_or_id) {
|
||||
for (int i = 0; i < root->outputs->length; ++i) {
|
||||
struct sway_output *output = root->outputs->items[i];
|
||||
char identifier[128];
|
||||
output_get_identifier(identifier, sizeof(identifier), output);
|
||||
if (strcasecmp(identifier, name_or_id) == 0
|
||||
|| strcasecmp(output->wlr_output->name, name_or_id) == 0) {
|
||||
if (output_match_name_or_id(output, name_or_id)) {
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
@ -52,10 +64,7 @@ struct sway_output *output_by_name_or_id(const char *name_or_id) {
|
|||
struct sway_output *all_output_by_name_or_id(const char *name_or_id) {
|
||||
struct sway_output *output;
|
||||
wl_list_for_each(output, &root->all_outputs, link) {
|
||||
char identifier[128];
|
||||
output_get_identifier(identifier, sizeof(identifier), output);
|
||||
if (strcasecmp(identifier, name_or_id) == 0
|
||||
|| strcasecmp(output->wlr_output->name, name_or_id) == 0) {
|
||||
if (output_match_name_or_id(output, name_or_id)) {
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
@ -258,7 +267,7 @@ void output_drag_icons_for_each_surface(struct sway_output *output,
|
|||
double ox = drag_icon->x - output->lx;
|
||||
double oy = drag_icon->y - output->ly;
|
||||
|
||||
if (drag_icon->wlr_drag_icon->mapped) {
|
||||
if (drag_icon->wlr_drag_icon->surface->mapped) {
|
||||
output_surface_for_each_surface(output,
|
||||
drag_icon->wlr_drag_icon->surface, ox, oy,
|
||||
iterator, user_data);
|
||||
|
@ -288,7 +297,7 @@ static void output_for_each_surface(struct sway_output *output,
|
|||
if (lock_surface->output != output->wlr_output) {
|
||||
continue;
|
||||
}
|
||||
if (!lock_surface->mapped) {
|
||||
if (!lock_surface->surface->mapped) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -450,7 +459,7 @@ static void count_surface_iterator(struct sway_output *output,
|
|||
}
|
||||
|
||||
static bool scan_out_fullscreen_view(struct sway_output *output,
|
||||
struct sway_view *view) {
|
||||
struct wlr_output_state *pending, struct sway_view *view) {
|
||||
struct wlr_output *wlr_output = output->wlr_output;
|
||||
struct sway_workspace *workspace = output->current.active_workspace;
|
||||
if (!sway_assert(workspace, "Expected an active workspace")) {
|
||||
|
@ -512,15 +521,20 @@ static bool scan_out_fullscreen_view(struct sway_output *output,
|
|||
return false;
|
||||
}
|
||||
|
||||
wlr_output_attach_buffer(wlr_output, &surface->buffer->base);
|
||||
if (!wlr_output_test(wlr_output)) {
|
||||
if (!wlr_output_is_direct_scanout_allowed(wlr_output)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wlr_presentation_surface_sampled_on_output(server.presentation, surface,
|
||||
wlr_output_state_set_buffer(pending, &surface->buffer->base);
|
||||
|
||||
if (!wlr_output_test_state(wlr_output, pending)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wlr_presentation_surface_scanned_out_on_output(server.presentation, surface,
|
||||
wlr_output);
|
||||
|
||||
return wlr_output_commit(wlr_output);
|
||||
return wlr_output_commit_state(wlr_output, pending);
|
||||
}
|
||||
|
||||
static void get_frame_damage(struct sway_output *output,
|
||||
|
@ -552,6 +566,12 @@ static int output_repaint_timer_handler(void *data) {
|
|||
|
||||
wlr_output->frame_pending = false;
|
||||
|
||||
if (!wlr_output->needs_frame &&
|
||||
!output->gamma_lut_changed &&
|
||||
!pixman_region32_not_empty(&output->damage_ring.current)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sway_workspace *workspace = output->current.active_workspace;
|
||||
if (workspace == NULL) {
|
||||
return 0;
|
||||
|
@ -562,11 +582,31 @@ static int output_repaint_timer_handler(void *data) {
|
|||
fullscreen_con = workspace->current.fullscreen;
|
||||
}
|
||||
|
||||
struct wlr_output_state pending = {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, wlr_output);
|
||||
if (!wlr_gamma_control_v1_apply(gamma_control, &pending)) {
|
||||
goto out;
|
||||
}
|
||||
if (!wlr_output_test_state(wlr_output, &pending)) {
|
||||
wlr_output_state_finish(&pending);
|
||||
pending = (struct wlr_output_state){0};
|
||||
wlr_gamma_control_v1_send_failed_and_destroy(gamma_control);
|
||||
}
|
||||
}
|
||||
|
||||
pending.committed |= WLR_OUTPUT_STATE_DAMAGE;
|
||||
get_frame_damage(output, &pending.damage);
|
||||
|
||||
if (fullscreen_con && fullscreen_con->view && !debug.noscanout) {
|
||||
// Try to scan-out the fullscreen view
|
||||
static bool last_scanned_out = false;
|
||||
bool scanned_out =
|
||||
scan_out_fullscreen_view(output, fullscreen_con->view);
|
||||
scan_out_fullscreen_view(output, &pending, fullscreen_con->view);
|
||||
|
||||
if (scanned_out && !last_scanned_out) {
|
||||
sway_log(SWAY_DEBUG, "Scanning out fullscreen view on %s",
|
||||
|
@ -580,43 +620,68 @@ static int output_repaint_timer_handler(void *data) {
|
|||
last_scanned_out = scanned_out;
|
||||
|
||||
if (scanned_out) {
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!output->wlr_output->needs_frame &&
|
||||
!pixman_region32_not_empty(&output->damage_ring.current)) {
|
||||
return 0;
|
||||
if (!wlr_output_configure_primary_swapchain(wlr_output, &pending, &wlr_output->swapchain)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
int buffer_age;
|
||||
if (!wlr_output_attach_render(output->wlr_output, &buffer_age)) {
|
||||
return 0;
|
||||
struct wlr_buffer *buffer = wlr_swapchain_acquire(wlr_output->swapchain, &buffer_age);
|
||||
if (buffer == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
struct wlr_render_pass *render_pass = wlr_renderer_begin_buffer_pass(
|
||||
wlr_output->renderer, buffer, NULL);
|
||||
if (render_pass == NULL) {
|
||||
wlr_buffer_unlock(buffer);
|
||||
goto out;
|
||||
}
|
||||
|
||||
pixman_region32_t damage;
|
||||
pixman_region32_init(&damage);
|
||||
wlr_damage_ring_get_buffer_damage(&output->damage_ring, buffer_age, &damage);
|
||||
|
||||
if (debug.damage == DAMAGE_RERENDER) {
|
||||
int width, height;
|
||||
wlr_output_transformed_resolution(wlr_output, &width, &height);
|
||||
pixman_region32_union_rect(&damage, &damage, 0, 0, width, height);
|
||||
}
|
||||
|
||||
struct render_context ctx = {
|
||||
.output_damage = &damage,
|
||||
.renderer = wlr_output->renderer,
|
||||
.output = output,
|
||||
.pass = render_pass,
|
||||
};
|
||||
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
|
||||
output_render(output, &damage);
|
||||
output_render(&ctx);
|
||||
|
||||
pixman_region32_fini(&damage);
|
||||
|
||||
pixman_region32_t frame_damage;
|
||||
get_frame_damage(output, &frame_damage);
|
||||
wlr_output_set_damage(wlr_output, &frame_damage);
|
||||
pixman_region32_fini(&frame_damage);
|
||||
if (!wlr_render_pass_submit(render_pass)) {
|
||||
wlr_buffer_unlock(buffer);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!wlr_output_commit(wlr_output)) {
|
||||
return 0;
|
||||
wlr_output_state_set_buffer(&pending, buffer);
|
||||
wlr_buffer_unlock(buffer);
|
||||
|
||||
if (!wlr_output_commit_state(wlr_output, &pending)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
wlr_damage_ring_rotate(&output->damage_ring);
|
||||
output->last_frame = now;
|
||||
|
||||
out:
|
||||
wlr_output_state_finish(&pending);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -642,9 +707,7 @@ static void handle_frame(struct wl_listener *listener, void *user_data) {
|
|||
|
||||
if (output->max_render_time != 0) {
|
||||
struct timespec now;
|
||||
clockid_t presentation_clock
|
||||
= wlr_backend_get_presentation_clock(server.backend);
|
||||
clock_gettime(presentation_clock, &now);
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
|
||||
const long NSEC_IN_SECONDS = 1000000000;
|
||||
struct timespec predicted_refresh = output->last_presentation;
|
||||
|
@ -819,12 +882,9 @@ static void update_output_manager_config(struct sway_server *server) {
|
|||
wlr_output_layout_get_box(root->output_layout,
|
||||
output->wlr_output, &output_box);
|
||||
// We mark the output enabled when it's switched off but not disabled
|
||||
config_head->state.enabled = output->current_mode != NULL && output->enabled;
|
||||
config_head->state.mode = output->current_mode;
|
||||
if (!wlr_box_empty(&output_box)) {
|
||||
config_head->state.x = output_box.x;
|
||||
config_head->state.y = output_box.y;
|
||||
}
|
||||
config_head->state.enabled = !wlr_box_empty(&output_box);
|
||||
config_head->state.x = output_box.x;
|
||||
config_head->state.y = output_box.y;
|
||||
}
|
||||
|
||||
wlr_output_manager_v1_set_configuration(server->output_manager_v1, config);
|
||||
|
@ -862,36 +922,6 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
|
|||
update_output_manager_config(server);
|
||||
}
|
||||
|
||||
static void handle_mode(struct sway_output *output) {
|
||||
if (!output->enabled && !output->enabling) {
|
||||
struct output_config *oc = find_output_config(output);
|
||||
if (output->wlr_output->current_mode != NULL &&
|
||||
(!oc || oc->enabled)) {
|
||||
// We want to enable this output, but it didn't work last time,
|
||||
// possibly because we hadn't enough CRTCs. Try again now that the
|
||||
// output has a mode.
|
||||
sway_log(SWAY_DEBUG, "Output %s has gained a CRTC, "
|
||||
"trying to enable it", output->wlr_output->name);
|
||||
apply_output_config(oc, output);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!output->enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
arrange_layers(output);
|
||||
arrange_output(output);
|
||||
transaction_commit_dirty();
|
||||
|
||||
int width, height;
|
||||
wlr_output_transformed_resolution(output->wlr_output, &width, &height);
|
||||
wlr_damage_ring_set_bounds(&output->damage_ring, width, height);
|
||||
wlr_output_schedule_frame(output->wlr_output);
|
||||
|
||||
update_output_manager_config(output->server);
|
||||
}
|
||||
|
||||
static void update_textures(struct sway_container *con, void *data) {
|
||||
container_update_title_textures(con);
|
||||
container_update_marks_textures(con);
|
||||
|
@ -907,20 +937,19 @@ 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 (event->committed & WLR_OUTPUT_STATE_MODE) {
|
||||
handle_mode(output);
|
||||
}
|
||||
|
||||
if (!output->enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event->committed & WLR_OUTPUT_STATE_SCALE) {
|
||||
if (event->state->committed & WLR_OUTPUT_STATE_SCALE) {
|
||||
output_for_each_container(output, update_textures, NULL);
|
||||
output_for_each_surface(output, update_output_scale_iterator, NULL);
|
||||
}
|
||||
|
||||
if (event->committed & (WLR_OUTPUT_STATE_TRANSFORM | WLR_OUTPUT_STATE_SCALE)) {
|
||||
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();
|
||||
|
@ -928,12 +957,19 @@ static void handle_commit(struct wl_listener *listener, void *data) {
|
|||
update_output_manager_config(output->server);
|
||||
}
|
||||
|
||||
if (event->committed & (WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_TRANSFORM)) {
|
||||
if (event->state->committed & (
|
||||
WLR_OUTPUT_STATE_MODE |
|
||||
WLR_OUTPUT_STATE_TRANSFORM)) {
|
||||
int width, height;
|
||||
wlr_output_transformed_resolution(output->wlr_output, &width, &height);
|
||||
wlr_damage_ring_set_bounds(&output->damage_ring, width, height);
|
||||
wlr_output_schedule_frame(output->wlr_output);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
@ -999,9 +1035,6 @@ void handle_new_output(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
output->server = server;
|
||||
wlr_damage_ring_init(&output->damage_ring);
|
||||
int width, height;
|
||||
wlr_output_transformed_resolution(output->wlr_output, &width, &height);
|
||||
wlr_damage_ring_set_bounds(&output->damage_ring, width, height);
|
||||
|
||||
wl_signal_add(&wlr_output->events.destroy, &output->destroy);
|
||||
output->destroy.notify = handle_destroy;
|
||||
|
@ -1027,6 +1060,9 @@ void handle_new_output(struct wl_listener *listener, void *data) {
|
|||
|
||||
transaction_commit_dirty();
|
||||
|
||||
int width, height;
|
||||
wlr_output_transformed_resolution(output->wlr_output, &width, &height);
|
||||
wlr_damage_ring_set_bounds(&output->damage_ring, width, height);
|
||||
update_output_manager_config(server);
|
||||
}
|
||||
|
||||
|
@ -1037,6 +1073,21 @@ void handle_output_layout_change(struct wl_listener *listener,
|
|||
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);
|
||||
}
|
||||
|
||||
static void output_manager_apply(struct sway_server *server,
|
||||
struct wlr_output_configuration_v1 *config, bool test_only) {
|
||||
// TODO: perform atomic tests on the whole backend atomically
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -56,6 +56,7 @@ void surface_update_outputs(struct wlr_surface *surface) {
|
|||
}
|
||||
}
|
||||
wlr_fractional_scale_v1_notify_scale(surface, scale);
|
||||
wlr_surface_set_preferred_buffer_scale(surface, ceil(scale));
|
||||
}
|
||||
|
||||
void surface_enter_output(struct wlr_surface *surface,
|
||||
|
|
|
@ -344,7 +344,7 @@ static void transaction_progress(void) {
|
|||
server.queued_transaction = NULL;
|
||||
|
||||
if (!server.pending_transaction) {
|
||||
sway_idle_inhibit_v1_check_active(server.idle_inhibit_manager_v1);
|
||||
sway_idle_inhibit_v1_check_active();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ static void popup_destroy(struct sway_view_child *child) {
|
|||
return;
|
||||
}
|
||||
struct sway_xdg_popup *popup = (struct sway_xdg_popup *)child;
|
||||
wl_list_remove(&popup->surface_commit.link);
|
||||
wl_list_remove(&popup->new_popup.link);
|
||||
wl_list_remove(&popup->destroy.link);
|
||||
free(popup);
|
||||
|
@ -51,23 +52,17 @@ static const struct sway_view_child_impl popup_impl = {
|
|||
static struct sway_xdg_popup *popup_create(
|
||||
struct wlr_xdg_popup *wlr_popup, struct sway_view *view);
|
||||
|
||||
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->child.view);
|
||||
}
|
||||
|
||||
static void popup_handle_destroy(struct wl_listener *listener, void *data) {
|
||||
struct sway_xdg_popup *popup = wl_container_of(listener, popup, destroy);
|
||||
view_child_destroy(&popup->child);
|
||||
}
|
||||
|
||||
static void popup_unconstrain(struct sway_xdg_popup *popup) {
|
||||
struct sway_view *view = popup->child.view;
|
||||
struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_popup;
|
||||
|
||||
struct sway_output *output = view->container->pending.workspace->output;
|
||||
struct sway_workspace *workspace = view->container->pending.workspace;
|
||||
if (!workspace) {
|
||||
// is null if in the scratchpad
|
||||
return;
|
||||
}
|
||||
|
||||
struct sway_output *output = workspace->output;
|
||||
|
||||
// the output box expressed in the coordinate system of the toplevel parent
|
||||
// of the popup
|
||||
|
@ -81,6 +76,25 @@ static void popup_unconstrain(struct sway_xdg_popup *popup) {
|
|||
wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box);
|
||||
}
|
||||
|
||||
static void popup_handle_surface_commit(struct wl_listener *listener, void *data) {
|
||||
struct sway_xdg_popup *popup = wl_container_of(listener, popup, surface_commit);
|
||||
if (popup->wlr_xdg_popup->base->initial_commit) {
|
||||
popup_unconstrain(popup);
|
||||
}
|
||||
}
|
||||
|
||||
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->child.view);
|
||||
}
|
||||
|
||||
static void popup_handle_destroy(struct wl_listener *listener, void *data) {
|
||||
struct sway_xdg_popup *popup = wl_container_of(listener, popup, destroy);
|
||||
view_child_destroy(&popup->child);
|
||||
}
|
||||
|
||||
static struct sway_xdg_popup *popup_create(
|
||||
struct wlr_xdg_popup *wlr_popup, struct sway_view *view) {
|
||||
struct wlr_xdg_surface *xdg_surface = wlr_popup->base;
|
||||
|
@ -91,22 +105,21 @@ static struct sway_xdg_popup *popup_create(
|
|||
return NULL;
|
||||
}
|
||||
view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface);
|
||||
popup->wlr_xdg_popup = xdg_surface->popup;
|
||||
popup->wlr_xdg_popup = wlr_popup;
|
||||
|
||||
wl_signal_add(&xdg_surface->surface->events.commit, &popup->surface_commit);
|
||||
popup->surface_commit.notify = popup_handle_surface_commit;
|
||||
wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup);
|
||||
popup->new_popup.notify = popup_handle_new_popup;
|
||||
wl_signal_add(&xdg_surface->events.destroy, &popup->destroy);
|
||||
wl_signal_add(&wlr_popup->events.destroy, &popup->destroy);
|
||||
popup->destroy.notify = popup_handle_destroy;
|
||||
|
||||
wl_signal_add(&xdg_surface->events.map, &popup->child.surface_map);
|
||||
wl_signal_add(&xdg_surface->events.unmap, &popup->child.surface_unmap);
|
||||
|
||||
popup_unconstrain(popup);
|
||||
wl_signal_add(&xdg_surface->surface->events.map, &popup->child.surface_map);
|
||||
wl_signal_add(&xdg_surface->surface->events.unmap, &popup->child.surface_unmap);
|
||||
|
||||
return popup;
|
||||
}
|
||||
|
||||
|
||||
static struct sway_xdg_shell_view *xdg_shell_view_from_view(
|
||||
struct sway_view *view) {
|
||||
if (!sway_assert(view->type == SWAY_VIEW_XDG_SHELL,
|
||||
|
@ -163,12 +176,19 @@ static void set_tiled(struct sway_view *view, bool tiled) {
|
|||
if (xdg_shell_view_from_view(view) == NULL) {
|
||||
return;
|
||||
}
|
||||
enum wlr_edges edges = WLR_EDGE_NONE;
|
||||
if (tiled) {
|
||||
edges = WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP |
|
||||
WLR_EDGE_BOTTOM;
|
||||
if (wl_resource_get_version(view->wlr_xdg_toplevel->resource) >=
|
||||
XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION) {
|
||||
enum wlr_edges edges = WLR_EDGE_NONE;
|
||||
if (tiled) {
|
||||
edges = WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP |
|
||||
WLR_EDGE_BOTTOM;
|
||||
}
|
||||
wlr_xdg_toplevel_set_tiled(view->wlr_xdg_toplevel, edges);
|
||||
} else {
|
||||
// The version is too low for the tiled state; configure as maximized instead
|
||||
// to stop the client from drawing decorations outside of the toplevel geometry.
|
||||
wlr_xdg_toplevel_set_maximized(view->wlr_xdg_toplevel, tiled);
|
||||
}
|
||||
wlr_xdg_toplevel_set_tiled(view->wlr_xdg_toplevel, edges);
|
||||
}
|
||||
|
||||
static void set_fullscreen(struct sway_view *view, bool fullscreen) {
|
||||
|
@ -273,6 +293,19 @@ static void handle_commit(struct wl_listener *listener, void *data) {
|
|||
struct sway_view *view = &xdg_shell_view->view;
|
||||
struct wlr_xdg_surface *xdg_surface = view->wlr_xdg_toplevel->base;
|
||||
|
||||
if (xdg_surface->initial_commit) {
|
||||
if (view->xdg_decoration != NULL) {
|
||||
set_xdg_decoration_mode(view->xdg_decoration);
|
||||
}
|
||||
// XXX: https://github.com/swaywm/sway/issues/2176
|
||||
wlr_xdg_surface_schedule_configure(xdg_surface);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!xdg_surface->surface->mapped) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_box new_geo;
|
||||
wlr_xdg_surface_get_geometry(xdg_surface, &new_geo);
|
||||
bool new_size = new_geo.width != view->geometry.width ||
|
||||
|
@ -288,6 +321,11 @@ static void handle_commit(struct wl_listener *listener, void *data) {
|
|||
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.
|
||||
if (view->container->current.width) {
|
||||
wlr_xdg_toplevel_set_size(view->wlr_xdg_toplevel, view->geometry.width,
|
||||
view->geometry.height);
|
||||
}
|
||||
transaction_commit_dirty_client();
|
||||
} else {
|
||||
view_center_surface(view);
|
||||
|
@ -338,7 +376,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
|
|||
struct wlr_xdg_toplevel *toplevel = xdg_shell_view->view.wlr_xdg_toplevel;
|
||||
struct sway_view *view = &xdg_shell_view->view;
|
||||
|
||||
if (!toplevel->base->mapped) {
|
||||
if (!toplevel->base->surface->mapped) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -403,7 +441,6 @@ static void handle_unmap(struct wl_listener *listener, void *data) {
|
|||
|
||||
view_unmap(view);
|
||||
|
||||
wl_list_remove(&xdg_shell_view->commit.link);
|
||||
wl_list_remove(&xdg_shell_view->new_popup.link);
|
||||
wl_list_remove(&xdg_shell_view->request_maximize.link);
|
||||
wl_list_remove(&xdg_shell_view->request_fullscreen.link);
|
||||
|
@ -446,10 +483,6 @@ static void handle_map(struct wl_listener *listener, void *data) {
|
|||
|
||||
transaction_commit_dirty();
|
||||
|
||||
xdg_shell_view->commit.notify = handle_commit;
|
||||
wl_signal_add(&toplevel->base->surface->events.commit,
|
||||
&xdg_shell_view->commit);
|
||||
|
||||
xdg_shell_view->new_popup.notify = handle_new_popup;
|
||||
wl_signal_add(&toplevel->base->events.new_popup,
|
||||
&xdg_shell_view->new_popup);
|
||||
|
@ -489,6 +522,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
|
|||
wl_list_remove(&xdg_shell_view->destroy.link);
|
||||
wl_list_remove(&xdg_shell_view->map.link);
|
||||
wl_list_remove(&xdg_shell_view->unmap.link);
|
||||
wl_list_remove(&xdg_shell_view->commit.link);
|
||||
view->wlr_xdg_toplevel = NULL;
|
||||
if (view->xdg_decoration) {
|
||||
view->xdg_decoration->view = NULL;
|
||||
|
@ -501,17 +535,12 @@ struct sway_view *view_from_wlr_xdg_surface(
|
|||
return xdg_surface->data;
|
||||
}
|
||||
|
||||
void handle_xdg_shell_surface(struct wl_listener *listener, void *data) {
|
||||
struct wlr_xdg_surface *xdg_surface = data;
|
||||
|
||||
if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
|
||||
sway_log(SWAY_DEBUG, "New xdg_shell popup");
|
||||
return;
|
||||
}
|
||||
void handle_xdg_shell_toplevel(struct wl_listener *listener, void *data) {
|
||||
struct wlr_xdg_toplevel *xdg_toplevel = data;
|
||||
|
||||
sway_log(SWAY_DEBUG, "New xdg_shell toplevel title='%s' app_id='%s'",
|
||||
xdg_surface->toplevel->title, xdg_surface->toplevel->app_id);
|
||||
wlr_xdg_surface_ping(xdg_surface);
|
||||
xdg_toplevel->title, xdg_toplevel->app_id);
|
||||
wlr_xdg_surface_ping(xdg_toplevel->base);
|
||||
|
||||
struct sway_xdg_shell_view *xdg_shell_view =
|
||||
calloc(1, sizeof(struct sway_xdg_shell_view));
|
||||
|
@ -520,16 +549,20 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
|
||||
view_init(&xdg_shell_view->view, SWAY_VIEW_XDG_SHELL, &view_impl);
|
||||
xdg_shell_view->view.wlr_xdg_toplevel = xdg_surface->toplevel;
|
||||
xdg_shell_view->view.wlr_xdg_toplevel = xdg_toplevel;
|
||||
|
||||
xdg_shell_view->map.notify = handle_map;
|
||||
wl_signal_add(&xdg_surface->events.map, &xdg_shell_view->map);
|
||||
wl_signal_add(&xdg_toplevel->base->surface->events.map, &xdg_shell_view->map);
|
||||
|
||||
xdg_shell_view->unmap.notify = handle_unmap;
|
||||
wl_signal_add(&xdg_surface->events.unmap, &xdg_shell_view->unmap);
|
||||
wl_signal_add(&xdg_toplevel->base->surface->events.unmap, &xdg_shell_view->unmap);
|
||||
|
||||
xdg_shell_view->commit.notify = handle_commit;
|
||||
wl_signal_add(&xdg_toplevel->base->surface->events.commit,
|
||||
&xdg_shell_view->commit);
|
||||
|
||||
xdg_shell_view->destroy.notify = handle_destroy;
|
||||
wl_signal_add(&xdg_surface->events.destroy, &xdg_shell_view->destroy);
|
||||
wl_signal_add(&xdg_toplevel->events.destroy, &xdg_shell_view->destroy);
|
||||
|
||||
xdg_surface->data = xdg_shell_view;
|
||||
xdg_toplevel->base->data = xdg_shell_view;
|
||||
}
|
||||
|
|
|
@ -125,8 +125,10 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
|
||||
static void unmanaged_handle_request_activate(struct wl_listener *listener, void *data) {
|
||||
struct wlr_xwayland_surface *xsurface = data;
|
||||
if (!xsurface->mapped) {
|
||||
struct sway_xwayland_unmanaged *surface =
|
||||
wl_container_of(listener, surface, request_activate);
|
||||
struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
|
||||
if (xsurface->surface == NULL || !xsurface->surface->mapped) {
|
||||
return;
|
||||
}
|
||||
struct sway_seat *seat = input_manager_current_seat();
|
||||
|
@ -138,12 +140,29 @@ static void unmanaged_handle_request_activate(struct wl_listener *listener, void
|
|||
seat_set_focus_surface(seat, xsurface->surface, false);
|
||||
}
|
||||
|
||||
static void unmanaged_handle_associate(struct wl_listener *listener, void *data) {
|
||||
struct sway_xwayland_unmanaged *surface =
|
||||
wl_container_of(listener, surface, associate);
|
||||
struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
|
||||
wl_signal_add(&xsurface->surface->events.map, &surface->map);
|
||||
surface->map.notify = unmanaged_handle_map;
|
||||
wl_signal_add(&xsurface->surface->events.unmap, &surface->unmap);
|
||||
surface->unmap.notify = unmanaged_handle_unmap;
|
||||
}
|
||||
|
||||
static void unmanaged_handle_dissociate(struct wl_listener *listener, void *data) {
|
||||
struct sway_xwayland_unmanaged *surface =
|
||||
wl_container_of(listener, surface, dissociate);
|
||||
wl_list_remove(&surface->map.link);
|
||||
wl_list_remove(&surface->unmap.link);
|
||||
}
|
||||
|
||||
static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) {
|
||||
struct sway_xwayland_unmanaged *surface =
|
||||
wl_container_of(listener, surface, destroy);
|
||||
wl_list_remove(&surface->request_configure.link);
|
||||
wl_list_remove(&surface->map.link);
|
||||
wl_list_remove(&surface->unmap.link);
|
||||
wl_list_remove(&surface->associate.link);
|
||||
wl_list_remove(&surface->dissociate.link);
|
||||
wl_list_remove(&surface->destroy.link);
|
||||
wl_list_remove(&surface->override_redirect.link);
|
||||
wl_list_remove(&surface->request_activate.link);
|
||||
|
@ -159,7 +178,7 @@ static void unmanaged_handle_override_redirect(struct wl_listener *listener, voi
|
|||
wl_container_of(listener, surface, override_redirect);
|
||||
struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
|
||||
|
||||
bool mapped = xsurface->mapped;
|
||||
bool mapped = xsurface->surface != NULL && xsurface->surface->mapped;
|
||||
if (mapped) {
|
||||
unmanaged_handle_unmap(&surface->unmap, NULL);
|
||||
}
|
||||
|
@ -186,10 +205,10 @@ static struct sway_xwayland_unmanaged *create_unmanaged(
|
|||
wl_signal_add(&xsurface->events.request_configure,
|
||||
&surface->request_configure);
|
||||
surface->request_configure.notify = unmanaged_handle_request_configure;
|
||||
wl_signal_add(&xsurface->events.map, &surface->map);
|
||||
surface->map.notify = unmanaged_handle_map;
|
||||
wl_signal_add(&xsurface->events.unmap, &surface->unmap);
|
||||
surface->unmap.notify = unmanaged_handle_unmap;
|
||||
wl_signal_add(&xsurface->events.associate, &surface->associate);
|
||||
surface->associate.notify = unmanaged_handle_associate;
|
||||
wl_signal_add(&xsurface->events.dissociate, &surface->dissociate);
|
||||
surface->dissociate.notify = unmanaged_handle_dissociate;
|
||||
wl_signal_add(&xsurface->events.destroy, &surface->destroy);
|
||||
surface->destroy.notify = unmanaged_handle_destroy;
|
||||
wl_signal_add(&xsurface->events.set_override_redirect, &surface->override_redirect);
|
||||
|
@ -472,8 +491,8 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
|
|||
wl_list_remove(&xwayland_view->set_window_type.link);
|
||||
wl_list_remove(&xwayland_view->set_hints.link);
|
||||
wl_list_remove(&xwayland_view->set_decorations.link);
|
||||
wl_list_remove(&xwayland_view->map.link);
|
||||
wl_list_remove(&xwayland_view->unmap.link);
|
||||
wl_list_remove(&xwayland_view->associate.link);
|
||||
wl_list_remove(&xwayland_view->dissociate.link);
|
||||
wl_list_remove(&xwayland_view->override_redirect.link);
|
||||
view_begin_destroy(&xwayland_view->view);
|
||||
}
|
||||
|
@ -495,8 +514,8 @@ static void handle_unmap(struct wl_listener *listener, void *data) {
|
|||
static void handle_map(struct wl_listener *listener, void *data) {
|
||||
struct sway_xwayland_view *xwayland_view =
|
||||
wl_container_of(listener, xwayland_view, map);
|
||||
struct wlr_xwayland_surface *xsurface = data;
|
||||
struct sway_view *view = &xwayland_view->view;
|
||||
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
|
||||
|
||||
view->natural_width = xsurface->width;
|
||||
view->natural_height = xsurface->height;
|
||||
|
@ -515,10 +534,10 @@ static void handle_map(struct wl_listener *listener, void *data) {
|
|||
static void handle_override_redirect(struct wl_listener *listener, void *data) {
|
||||
struct sway_xwayland_view *xwayland_view =
|
||||
wl_container_of(listener, xwayland_view, override_redirect);
|
||||
struct wlr_xwayland_surface *xsurface = data;
|
||||
struct sway_view *view = &xwayland_view->view;
|
||||
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
|
||||
|
||||
bool mapped = xsurface->mapped;
|
||||
bool mapped = xsurface->surface != NULL && xsurface->surface->mapped;
|
||||
if (mapped) {
|
||||
handle_unmap(&xwayland_view->unmap, NULL);
|
||||
}
|
||||
|
@ -537,7 +556,7 @@ static void handle_request_configure(struct wl_listener *listener, void *data) {
|
|||
struct wlr_xwayland_surface_configure_event *ev = data;
|
||||
struct sway_view *view = &xwayland_view->view;
|
||||
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
|
||||
if (!xsurface->mapped) {
|
||||
if (xsurface->surface == NULL || !xsurface->surface->mapped) {
|
||||
wlr_xwayland_surface_configure(xsurface, ev->x, ev->y,
|
||||
ev->width, ev->height);
|
||||
return;
|
||||
|
@ -566,7 +585,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
|
|||
wl_container_of(listener, xwayland_view, request_fullscreen);
|
||||
struct sway_view *view = &xwayland_view->view;
|
||||
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
|
||||
if (!xsurface->mapped) {
|
||||
if (xsurface->surface == NULL || !xsurface->surface->mapped) {
|
||||
return;
|
||||
}
|
||||
container_set_fullscreen(view->container, xsurface->fullscreen);
|
||||
|
@ -580,7 +599,7 @@ static void handle_request_minimize(struct wl_listener *listener, void *data) {
|
|||
wl_container_of(listener, xwayland_view, request_minimize);
|
||||
struct sway_view *view = &xwayland_view->view;
|
||||
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
|
||||
if (!xsurface->mapped) {
|
||||
if (xsurface->surface == NULL || !xsurface->surface->mapped) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -595,7 +614,7 @@ static void handle_request_move(struct wl_listener *listener, void *data) {
|
|||
wl_container_of(listener, xwayland_view, request_move);
|
||||
struct sway_view *view = &xwayland_view->view;
|
||||
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
|
||||
if (!xsurface->mapped) {
|
||||
if (xsurface->surface == NULL || !xsurface->surface->mapped) {
|
||||
return;
|
||||
}
|
||||
if (!container_is_floating(view->container) ||
|
||||
|
@ -611,7 +630,7 @@ static void handle_request_resize(struct wl_listener *listener, void *data) {
|
|||
wl_container_of(listener, xwayland_view, request_resize);
|
||||
struct sway_view *view = &xwayland_view->view;
|
||||
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
|
||||
if (!xsurface->mapped) {
|
||||
if (xsurface->surface == NULL || !xsurface->surface->mapped) {
|
||||
return;
|
||||
}
|
||||
if (!container_is_floating(view->container)) {
|
||||
|
@ -627,7 +646,7 @@ static void handle_request_activate(struct wl_listener *listener, void *data) {
|
|||
wl_container_of(listener, xwayland_view, request_activate);
|
||||
struct sway_view *view = &xwayland_view->view;
|
||||
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
|
||||
if (!xsurface->mapped) {
|
||||
if (xsurface->surface == NULL || !xsurface->surface->mapped) {
|
||||
return;
|
||||
}
|
||||
view_request_activate(view, NULL);
|
||||
|
@ -640,7 +659,7 @@ static void handle_set_title(struct wl_listener *listener, void *data) {
|
|||
wl_container_of(listener, xwayland_view, set_title);
|
||||
struct sway_view *view = &xwayland_view->view;
|
||||
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
|
||||
if (!xsurface->mapped) {
|
||||
if (xsurface->surface == NULL || !xsurface->surface->mapped) {
|
||||
return;
|
||||
}
|
||||
view_update_title(view, false);
|
||||
|
@ -652,7 +671,7 @@ static void handle_set_class(struct wl_listener *listener, void *data) {
|
|||
wl_container_of(listener, xwayland_view, set_class);
|
||||
struct sway_view *view = &xwayland_view->view;
|
||||
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
|
||||
if (!xsurface->mapped) {
|
||||
if (xsurface->surface == NULL || !xsurface->surface->mapped) {
|
||||
return;
|
||||
}
|
||||
view_execute_criteria(view);
|
||||
|
@ -663,7 +682,7 @@ static void handle_set_role(struct wl_listener *listener, void *data) {
|
|||
wl_container_of(listener, xwayland_view, set_role);
|
||||
struct sway_view *view = &xwayland_view->view;
|
||||
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
|
||||
if (!xsurface->mapped) {
|
||||
if (xsurface->surface == NULL || !xsurface->surface->mapped) {
|
||||
return;
|
||||
}
|
||||
view_execute_criteria(view);
|
||||
|
@ -699,7 +718,7 @@ static void handle_set_window_type(struct wl_listener *listener, void *data) {
|
|||
wl_container_of(listener, xwayland_view, set_window_type);
|
||||
struct sway_view *view = &xwayland_view->view;
|
||||
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
|
||||
if (!xsurface->mapped) {
|
||||
if (xsurface->surface == NULL || !xsurface->surface->mapped) {
|
||||
return;
|
||||
}
|
||||
view_execute_criteria(view);
|
||||
|
@ -710,7 +729,7 @@ static void handle_set_hints(struct wl_listener *listener, void *data) {
|
|||
wl_container_of(listener, xwayland_view, set_hints);
|
||||
struct sway_view *view = &xwayland_view->view;
|
||||
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
|
||||
if (!xsurface->mapped) {
|
||||
if (xsurface->surface == NULL || !xsurface->surface->mapped) {
|
||||
return;
|
||||
}
|
||||
const bool hints_urgency = xcb_icccm_wm_hints_get_urgency(xsurface->hints);
|
||||
|
@ -725,6 +744,24 @@ static void handle_set_hints(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
}
|
||||
|
||||
static void handle_associate(struct wl_listener *listener, void *data) {
|
||||
struct sway_xwayland_view *xwayland_view =
|
||||
wl_container_of(listener, xwayland_view, associate);
|
||||
struct wlr_xwayland_surface *xsurface =
|
||||
xwayland_view->view.wlr_xwayland_surface;
|
||||
wl_signal_add(&xsurface->surface->events.unmap, &xwayland_view->unmap);
|
||||
xwayland_view->unmap.notify = handle_unmap;
|
||||
wl_signal_add(&xsurface->surface->events.map, &xwayland_view->map);
|
||||
xwayland_view->map.notify = handle_map;
|
||||
}
|
||||
|
||||
static void handle_dissociate(struct wl_listener *listener, void *data) {
|
||||
struct sway_xwayland_view *xwayland_view =
|
||||
wl_container_of(listener, xwayland_view, dissociate);
|
||||
wl_list_remove(&xwayland_view->map.link);
|
||||
wl_list_remove(&xwayland_view->unmap.link);
|
||||
}
|
||||
|
||||
struct sway_view *view_from_wlr_xwayland_surface(
|
||||
struct wlr_xwayland_surface *xsurface) {
|
||||
return xsurface->data;
|
||||
|
@ -794,11 +831,11 @@ struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsu
|
|||
&xwayland_view->set_decorations);
|
||||
xwayland_view->set_decorations.notify = handle_set_decorations;
|
||||
|
||||
wl_signal_add(&xsurface->events.unmap, &xwayland_view->unmap);
|
||||
xwayland_view->unmap.notify = handle_unmap;
|
||||
wl_signal_add(&xsurface->events.associate, &xwayland_view->associate);
|
||||
xwayland_view->associate.notify = handle_associate;
|
||||
|
||||
wl_signal_add(&xsurface->events.map, &xwayland_view->map);
|
||||
xwayland_view->map.notify = handle_map;
|
||||
wl_signal_add(&xsurface->events.dissociate, &xwayland_view->dissociate);
|
||||
xwayland_view->dissociate.notify = handle_dissociate;
|
||||
|
||||
wl_signal_add(&xsurface->events.set_override_redirect,
|
||||
&xwayland_view->override_redirect);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <time.h>
|
||||
#include <strings.h>
|
||||
#include <wlr/types/wlr_cursor.h>
|
||||
#include <wlr/types/wlr_idle.h>
|
||||
#include <wlr/types/wlr_cursor_shape_v1.h>
|
||||
#include <wlr/types/wlr_pointer.h>
|
||||
#include <wlr/types/wlr_touch.h>
|
||||
#include <wlr/types/wlr_tablet_v2.h>
|
||||
|
@ -55,7 +55,8 @@ static struct wlr_surface *layer_surface_at(struct sway_output *output,
|
|||
static bool surface_is_xdg_popup(struct wlr_surface *surface) {
|
||||
struct wlr_xdg_surface *xdg_surface =
|
||||
wlr_xdg_surface_try_from_wlr_surface(surface);
|
||||
return xdg_surface != NULL && xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP;
|
||||
return xdg_surface != NULL && xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP &&
|
||||
xdg_surface->popup != NULL;
|
||||
}
|
||||
|
||||
static struct wlr_surface *layer_surface_popup_at(struct sway_output *output,
|
||||
|
@ -236,7 +237,7 @@ void cursor_update_image(struct sway_cursor *cursor,
|
|||
// Try a node's resize edge
|
||||
enum wlr_edges edge = find_resize_edge(node->sway_container, NULL, cursor);
|
||||
if (edge == WLR_EDGE_NONE) {
|
||||
cursor_set_image(cursor, "left_ptr", NULL);
|
||||
cursor_set_image(cursor, "default", NULL);
|
||||
} else if (container_is_floating(node->sway_container)) {
|
||||
cursor_set_image(cursor, wlr_xcursor_get_resize_name(edge), NULL);
|
||||
} else {
|
||||
|
@ -247,12 +248,12 @@ void cursor_update_image(struct sway_cursor *cursor,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
cursor_set_image(cursor, "left_ptr", NULL);
|
||||
cursor_set_image(cursor, "default", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void cursor_hide(struct sway_cursor *cursor) {
|
||||
wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0);
|
||||
wlr_cursor_unset_image(cursor->cursor);
|
||||
cursor->hidden = true;
|
||||
wlr_seat_pointer_notify_clear_focus(cursor->seat->wlr_seat);
|
||||
}
|
||||
|
@ -509,6 +510,24 @@ static void handle_touch_up(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
}
|
||||
|
||||
static void handle_touch_cancel(struct wl_listener *listener, void *data) {
|
||||
struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_cancel);
|
||||
struct wlr_touch_cancel_event *event = data;
|
||||
cursor_handle_activity_from_device(cursor, &event->touch->base);
|
||||
|
||||
struct sway_seat *seat = cursor->seat;
|
||||
|
||||
if (cursor->simulating_pointer_from_touch) {
|
||||
if (cursor->pointer_touch_id == cursor->seat->touch_id) {
|
||||
cursor->pointer_touch_up = true;
|
||||
dispatch_cursor_button(cursor, &event->touch->base,
|
||||
event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED);
|
||||
}
|
||||
} else {
|
||||
seatop_touch_cancel(seat, event);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_touch_motion(struct wl_listener *listener, void *data) {
|
||||
struct sway_cursor *cursor =
|
||||
wl_container_of(listener, cursor, touch_motion);
|
||||
|
@ -1050,10 +1069,9 @@ void cursor_set_image(struct sway_cursor *cursor, const char *image,
|
|||
}
|
||||
|
||||
if (!image) {
|
||||
wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0);
|
||||
wlr_cursor_unset_image(cursor->cursor);
|
||||
} else if (!current_image || strcmp(current_image, image) != 0) {
|
||||
wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, image,
|
||||
cursor->cursor);
|
||||
wlr_cursor_set_xcursor(cursor->cursor, cursor->xcursor_manager, image);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1100,6 +1118,7 @@ void sway_cursor_destroy(struct sway_cursor *cursor) {
|
|||
wl_list_remove(&cursor->frame.link);
|
||||
wl_list_remove(&cursor->touch_down.link);
|
||||
wl_list_remove(&cursor->touch_up.link);
|
||||
wl_list_remove(&cursor->touch_cancel.link);
|
||||
wl_list_remove(&cursor->touch_motion.link);
|
||||
wl_list_remove(&cursor->touch_frame.link);
|
||||
wl_list_remove(&cursor->tool_axis.link);
|
||||
|
@ -1136,9 +1155,6 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) {
|
|||
wl_list_init(&cursor->image_surface_destroy.link);
|
||||
cursor->image_surface_destroy.notify = handle_image_surface_destroy;
|
||||
|
||||
// gesture events
|
||||
cursor->pointer_gestures = wlr_pointer_gestures_v1_create(server.wl_display);
|
||||
|
||||
wl_signal_add(&wlr_cursor->events.hold_begin, &cursor->hold_begin);
|
||||
cursor->hold_begin.notify = handle_pointer_hold_begin;
|
||||
wl_signal_add(&wlr_cursor->events.hold_end, &cursor->hold_end);
|
||||
|
@ -1181,6 +1197,9 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) {
|
|||
wl_signal_add(&wlr_cursor->events.touch_up, &cursor->touch_up);
|
||||
cursor->touch_up.notify = handle_touch_up;
|
||||
|
||||
wl_signal_add(&wlr_cursor->events.touch_cancel, &cursor->touch_cancel);
|
||||
cursor->touch_cancel.notify = handle_touch_cancel;
|
||||
|
||||
wl_signal_add(&wlr_cursor->events.touch_motion,
|
||||
&cursor->touch_motion);
|
||||
cursor->touch_motion.notify = handle_touch_motion;
|
||||
|
@ -1273,11 +1292,7 @@ uint32_t get_mouse_bindsym(const char *name, char **error) {
|
|||
// Get event code from name
|
||||
int code = libevdev_event_code_from_name(EV_KEY, name);
|
||||
if (code == -1) {
|
||||
size_t len = snprintf(NULL, 0, "Unknown event %s", name) + 1;
|
||||
*error = malloc(len);
|
||||
if (*error) {
|
||||
snprintf(*error, len, "Unknown event %s", name);
|
||||
}
|
||||
*error = format_str("Unknown event %s", name);
|
||||
return 0;
|
||||
}
|
||||
return code;
|
||||
|
@ -1299,13 +1314,8 @@ uint32_t get_mouse_bindcode(const char *name, char **error) {
|
|||
}
|
||||
const char *event = libevdev_event_code_get_name(EV_KEY, code);
|
||||
if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) {
|
||||
size_t len = snprintf(NULL, 0, "Event code %d (%s) is not a button",
|
||||
code, event ? event : "(null)") + 1;
|
||||
*error = malloc(len);
|
||||
if (*error) {
|
||||
snprintf(*error, len, "Event code %d (%s) is not a button",
|
||||
code, event ? event : "(null)");
|
||||
}
|
||||
*error = format_str("Event code %d (%s) is not a button",
|
||||
code, event ? event : "(null)");
|
||||
return 0;
|
||||
}
|
||||
return code;
|
||||
|
@ -1458,3 +1468,26 @@ void sway_cursor_constrain(struct sway_cursor *cursor,
|
|||
wl_signal_add(&constraint->surface->events.commit,
|
||||
&cursor->constraint_commit);
|
||||
}
|
||||
|
||||
void handle_request_set_cursor_shape(struct wl_listener *listener, void *data) {
|
||||
const struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data;
|
||||
struct sway_seat *seat = event->seat_client->seat->data;
|
||||
|
||||
if (!seatop_allows_set_cursor(seat)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wl_client *focused_client = NULL;
|
||||
struct wlr_surface *focused_surface = seat->wlr_seat->pointer_state.focused_surface;
|
||||
if (focused_surface != NULL) {
|
||||
focused_client = wl_resource_get_client(focused_surface->resource);
|
||||
}
|
||||
|
||||
// TODO: check cursor mode
|
||||
if (focused_client == NULL || event->seat_client->client != focused_client) {
|
||||
sway_log(SWAY_DEBUG, "denying request to set cursor from unfocused client");
|
||||
return;
|
||||
}
|
||||
|
||||
cursor_set_image(seat->cursor, wlr_cursor_shape_v1_name(event->shape), focused_client);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <wlr/config.h>
|
||||
#include <wlr/types/wlr_cursor.h>
|
||||
#include <wlr/types/wlr_keyboard_group.h>
|
||||
#include <wlr/types/wlr_input_inhibitor.h>
|
||||
#include <wlr/types/wlr_virtual_keyboard_v1.h>
|
||||
#include <wlr/types/wlr_virtual_pointer_v1.h>
|
||||
#include "sway/config.h"
|
||||
|
@ -80,15 +79,7 @@ char *input_device_get_identifier(struct wlr_input_device *device) {
|
|||
}
|
||||
}
|
||||
|
||||
const char *fmt = "%d:%d:%s";
|
||||
int len = snprintf(NULL, 0, fmt, vendor, product, name) + 1;
|
||||
char *identifier = malloc(len);
|
||||
if (!identifier) {
|
||||
sway_log(SWAY_ERROR, "Unable to allocate unique input device name");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snprintf(identifier, len, fmt, vendor, product, name);
|
||||
char *identifier = format_str("%d:%d:%s", vendor, product, name);
|
||||
free(name);
|
||||
return identifier;
|
||||
}
|
||||
|
@ -292,34 +283,6 @@ static void handle_new_input(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
}
|
||||
|
||||
static void handle_inhibit_activate(struct wl_listener *listener, void *data) {
|
||||
struct sway_input_manager *input_manager = wl_container_of(
|
||||
listener, input_manager, inhibit_activate);
|
||||
struct sway_seat *seat;
|
||||
wl_list_for_each(seat, &input_manager->seats, link) {
|
||||
seat_set_exclusive_client(seat, input_manager->inhibit->active_client);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_inhibit_deactivate(struct wl_listener *listener, void *data) {
|
||||
struct sway_input_manager *input_manager = wl_container_of(
|
||||
listener, input_manager, inhibit_deactivate);
|
||||
struct sway_seat *seat;
|
||||
if (server.session_lock.locked) {
|
||||
// Don't deactivate the grab of a screenlocker
|
||||
return;
|
||||
}
|
||||
wl_list_for_each(seat, &input_manager->seats, link) {
|
||||
seat_set_exclusive_client(seat, NULL);
|
||||
struct sway_node *previous = seat_get_focus(seat);
|
||||
if (previous) {
|
||||
// Hack to get seat to re-focus the return value of get_focus
|
||||
seat_set_focus(seat, NULL);
|
||||
seat_set_focus(seat, previous);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_keyboard_shortcuts_inhibitor_destroy(
|
||||
struct wl_listener *listener, void *data) {
|
||||
struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor =
|
||||
|
@ -488,14 +451,6 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) {
|
|||
&input->virtual_pointer_new);
|
||||
input->virtual_pointer_new.notify = handle_virtual_pointer;
|
||||
|
||||
input->inhibit = wlr_input_inhibit_manager_create(server->wl_display);
|
||||
input->inhibit_activate.notify = handle_inhibit_activate;
|
||||
wl_signal_add(&input->inhibit->events.activate,
|
||||
&input->inhibit_activate);
|
||||
input->inhibit_deactivate.notify = handle_inhibit_deactivate;
|
||||
wl_signal_add(&input->inhibit->events.deactivate,
|
||||
&input->inhibit_deactivate);
|
||||
|
||||
input->keyboard_shortcuts_inhibit =
|
||||
wlr_keyboard_shortcuts_inhibit_v1_create(server->wl_display);
|
||||
input->keyboard_shortcuts_inhibit_new_inhibitor.notify =
|
||||
|
@ -503,6 +458,8 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) {
|
|||
wl_signal_add(&input->keyboard_shortcuts_inhibit->events.new_inhibitor,
|
||||
&input->keyboard_shortcuts_inhibit_new_inhibitor);
|
||||
|
||||
input->pointer_gestures = wlr_pointer_gestures_v1_create(server->wl_display);
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
|
@ -540,6 +497,18 @@ static void retranslate_keysyms(struct input_config *input_config) {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < config->input_type_configs->length; ++i) {
|
||||
struct input_config *ic = config->input_type_configs->items[i];
|
||||
if (ic->xkb_layout || ic->xkb_file) {
|
||||
// this is the first config with xkb_layout or xkb_file
|
||||
if (ic->identifier == input_config->identifier) {
|
||||
translate_keysyms(ic);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void input_manager_configure_input(
|
||||
|
@ -558,10 +527,13 @@ static void input_manager_configure_input(
|
|||
}
|
||||
}
|
||||
|
||||
void input_manager_configure_all_inputs(void) {
|
||||
struct sway_input_device *input_device = NULL;
|
||||
void input_manager_configure_all_input_mappings(void) {
|
||||
struct sway_input_device *input_device;
|
||||
wl_list_for_each(input_device, &server.input->devices, link) {
|
||||
input_manager_configure_input(input_device);
|
||||
struct sway_seat *seat;
|
||||
wl_list_for_each(seat, &server.input->seats, link) {
|
||||
seat_configure_device_mapping(seat, input_device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue