diff options
50 files changed, 1551 insertions, 298 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index a4bf351b..95f539e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,11 +12,6 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-parameter") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-result") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") -if (CMAKE_COMPILER_IS_GNUCC) - if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 7.0) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wimplicit-fallthrough=0") - endif() -endif() list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/CMake @@ -95,7 +90,7 @@ endif() if (enable-tray) if (DBUS_FOUND) - set(ENABLE_TRAY) + set(ENABLE_TRAY TRUE) add_definitions(-DENABLE_TRAY) else() message(WARNING "Tray required but DBus was not found. Tray will not be included") diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index aa3a632b..8a6c0208 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ Contributing just involves sending a pull request. You will probably be more successful with your contribution if you visit the [IRC -channel](http://webchat.freenode.net/?channels=sway&uio=d4) upfront and discuss +channel](http://webchat.freenode.net/?channels=sway-devel&uio=d4) upfront and discuss your plans. ## Release Cycle @@ -34,7 +34,7 @@ upstream. Try this: 1. Fork sway 2. Clone your fork -3. git remote add upstream git://github.com/SirCmpwn/sway.git +3. git remote add upstream git://github.com/swaywm/sway.git You only need to do this once. You're never going to use your fork's master branch. Instead, when you start working on a feature, do this: diff --git a/README.de.md b/README.de.md new file mode 100644 index 00000000..92a15b99 --- /dev/null +++ b/README.de.md @@ -0,0 +1,101 @@ +# sway [](https://travis-ci.org/swaywm/sway) [](https://drewdevault.com/donate?project=4) + +Der Fortschritt dieser Übersetzung kann [hier](https://github.com/swaywm/sway/issues/1318) +eingesehen werden. + +"**S**irCmpwn's **Way**land compositor" ist ein i3-kompatibler +[Wayland](http://wayland.freedesktop.org/)-Kompositor. Lies die +[FAQ](https://github.com/swaywm/sway/wiki#faq). Tritt dem +[IRC-Channel](http://webchat.freenode.net/?channels=sway&uio=d4) bei (#sway in irc.freenode.net). + +[](https://sr.ht/ICd5.png) + +Falls du die Sway Entwicklung unterstützen möchtest, kannst du das auf der +[Patreonseite](https://patreon.com/sircmpwn) tun, oder indem du zu +[Entwicklungsprämien](https://github.com/swaywm/sway/issues/986) +bestimmter Features beiträgst. Jeder ist dazu eingeladen, eine Prämie in Anspruch +zu nehmen oder für gewünschte Features bereitzustellen. Patreon ist eher dafür +gedacht, Sways Wartung und das Projekt generell zu unterstützen. + +## Deutscher Support + +refacto(UTC+2) bietet Support im IRC (unter dem Namen azarus) und auf Github an. +ParadoxSpiral(UTC+2) bietet Support im IRC und auf Github an. + +## Releasesignaturen + +Neue Versionen werden mit +[B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +signiert und [auf Github](https://github.com/swaywm/sway/releases) veröffentlicht. + +## Status + +- [i3-Features](https://github.com/swaywm/sway/issues/2) +- [IPC-Features](https://github.com/swaywm/sway/issues/98) +- [i3bar-Features](https://github.com/swaywm/sway/issues/343) +- [i3-gaps-Features](https://github.com/swaywm/sway/issues/307) +- [Sicherheitsfeatures](https://github.com/swaywm/sway/issues/984) + +## Installation + +### Als Paket + +Sway ist in vielen Distributionen verfügbar: versuche einfach, das "sway"-Paket +zu installieren. Falls es nicht vorhanden ist, schau dir +[diese Wikiseite](https://github.com/swaywm/sway/wiki/Unsupported-packages) für +distributionsspezifische Installationsinformationen an. + +Wenn du Interesse hast, Sway für deine Distribution als Paket bereitzustellen, +schau im IRC-Channel vorbei oder schreibe eine e-Mail an [email protected] (nur englischsprachig). + +### Kompilieren des Quellcodes + +Abhängigkeiten: + +* cmake +* [wlc](https://github.com/Cloudef/wlc) +* wayland +* xwayland +* libinput >= 1.6.0 +* libcap +* asciidoc +* pcre +* json-c +* pango +* cairo +* gdk-pixbuf2 * +* pam ** +* imagemagick (erforderlich für Bildaufnahme mit swaygrab) +* ffmpeg (erforderlich für Videoaufnahme swaygrab) + +_\*Nur erforderlich für swaybar, swaybg, und swaylock_ + +_\*\*Nur erforderlich für swaylock_ + +Führe diese Befehle aus: + + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc .. + make + sudo make install + +In Systemen mit logind musst du `sway` einige Capabilities geben: + + sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/bin/sway + +In Systemen ohne logind musst du `sway` das suid-Flag geben: + + sudo chmod a+s /usr/local/bin/sway + +## Konfiguration + +Wenn du schon i3 benutzt, kopiere einfach deine i3 Konfiguration nach +`~/.config/sway/config`. Falls nicht, kannst du die Beispielkonfiguration +benutzen. Die befindet sich normalerweise unter `/etc/sway/config`. +Um mehr Informationen über die Konfiguration zu erhalten, führe `man 5 sway` aus. + +## Verwendung + +Führe `sway` von einem TTY aus. Manche Displaymanager könnten funktionieren, werden aber +nicht von Sway unterstützt (gdm scheint relativ gut zu funktionieren). diff --git a/README.el.md b/README.el.md new file mode 100644 index 00000000..1e5b8358 --- /dev/null +++ b/README.el.md @@ -0,0 +1,91 @@ +# sway [](https://travis-ci.org/swaywm/sway) [](https://drewdevault.com/donate?project=4) + +"Ο Sway (**S**irCmpwn's **Way**land) είναι ένας **υπό ανάπτυξη** [Wayland](http://wayland.freedesktop.org/) διαχειριστής παραθύρων συμβατός με τον αντίστοιχο διαχειριστή παραθύρων i3 για τον X11. +Διαβάστε τις [Συνήθεις Ερωτήσεις](https://github.com/swaywm/sway/wiki). Συνδεθείτε στο [κανάλι μας στο IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway στο +irc.freenode.net). + +[](https://sr.ht/ICd5.png) + + +### Η ελληνική μετάφραση ενδέχεται να είναι ελλειπής! + +Η τεκμηρίωση του Sway ξεκινάει πάντα από τα Αγγλικά και στη συνέχεια μεταφράζεται, γι' αυτό ενδέχεται τα ελληνικά κείμενα να μην είναι πάντα διαθέσιμα ή ενημερωμένα. +Μπορείτε πάντα να υποδεικνύετε σφάλματα και να κάνετε ερωτήσεις σχετικά με τις ελληνικές μεταφράσεις στο [IRC](http://webchat.freenode.net/?channels=sway&uio=d4). +To username μου στο Freenode είναι kon14 και θα με βρείτε στο IRC σε ώρες GMT+2. +Δείτε [εδώ](https://github.com/swaywm/sway/issues/1318) πως μπορείτε και οι ίδιοι να βοηθήσετε στη μετάφραση του Sway. + +Αν θέλετε να υποστηρίξετε την ανάπτυξη του Sway, μπορείτε να συμβάλετε στη [σελίδα Patreon του SirCmpwn](https://patreon.com/sircmpwn) +ή να επιδοτήσετε τις [αμοιβές](https://github.com/swaywm/sway/issues/986) για υλοποίηση συγκεκριμένων δυνατοτήτων. +Ο καθένας μπορεί να διεκδικήσει μια αμοιβή και μπορείτε να προσθέσετε μια αμοιβή για οποιαδήποτε δυνατότητα θέλετε. +Προτιμήστε το Patreon αν θέλετε να υποστήριξετε την συνολική ανάπτυξη και διατήρηση του Sway. + +## Υπογραφές Έκδοσης + +Οι εκδόσεις υπογράφονται ως [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) και δημοσιεύονται στο [GitHub](https://github.com/swaywm/sway/releases). + +## Κατάσταση + +- [Υποστήριξη δυνατοτήτων του i3](https://github.com/swaywm/sway/issues/2) +- [Υποστήριξη δυνατοτήτων IPC](https://github.com/swaywm/sway/issues/98) +- [Υποστήριξη δυνατοτήτων i3bar](https://github.com/swaywm/sway/issues/343) +- [Υποστήριξη δυνατοτήτων i3-gaps](https://github.com/swaywm/sway/issues/307) +- [Δυνατότητες Ασφαλείας](https://github.com/swaywm/sway/issues/984) + +## Εγκατάσταση + +### Από Πακέτα + +Ο Sway είναι διαθέσιμος για εγκατάσταση μέσω του διαχειριστή πακέτων σε διάφορες διανομές. +Δοκιμάστε να εγκαταστήσετε το πακέτο ονομαζόμενο ως "sway" για τη δική σας. +Αν δεν είναι διαθέσιμο, μεταβείτε στη [σελίδα τεκμηρίωσης](https://github.com/swaywm/sway/wiki/Unsupported-packages) για πληροφορίες σχετικά με την εγκατάσταση για τη διανομή σας. + +Αν ενδιαφέρεστε να δημιουργήσετε ένα πακέτο του Sway για τη διανομή σας, περάστε απο το κανάλι μας στο IRC ή στείλτε ένα email, στα **Αγγλικά**, στο [email protected] για συμβουλές. + +### Compile από Πηγαίο Κώδικα + +Εγκατάσταση εξαρτήσεων: + +* cmake +* [wlc](https://github.com/Cloudef/wlc) +* wayland +* xwayland +* libinput >= 1.6.0 +* libcap +* asciidoc +* pcre +* json-c +* pango +* cairo +* gdk-pixbuf2 * +* pam ** +* imagemagick (αναγκαίο για καταγραφή εικόνας μέσω του swaygrab) +* ffmpeg (αναγκαίο για καταγραφή video μέσω του swaygrab) + +_\*Απαιτείται μόνο για swaybar, swaybg, and swaylock_ + +_\*\*Απαιτείται μόνο για swaylock_ + +Εκτελέστε αυτές τις εντολές: + + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc .. + make + sudo make install + +Σε συστήματα με logind, χρειάζεται να ορίσετε μερικά δικαιώματα caps στο εκτελέσιμο αρχείο: + + sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/bin/sway + +Σε συστήματα χωρίς logind, χρειάζεται να θέσετε το suid bit στο εκτελέσιμο αρχείο: + + sudo chmod a+s /usr/local/bin/sway + +## Παραμετροποίηση + +Αν είστε ήδη χρήστης του i3, τότε απλά αντιγράψτε το αρχείο ρυθμίσεων σας στο `~/.config/sway/config` και θα είναι όλα έτοιμα για χρήση. +Διαφορετικά, αντιγράψτε το συνοδευόμενο δείγμα ρυθμίσεων, το οποίο θα βρείτε τυπικά στο `/etc/sway/config`, και μεταφέρετε το στην τοποθεσία `~/.config/sway/config`. Εκτελέστε `man 5 sway` για πληροφορίες σχετικά με την παραμετροποίηση των ρυθμίσεων σας. + +## Εκτέλεση + +Εκτελέστε `sway` απο ένα TTY. Μερικοί γραφικοί διαχειριστές σύνδεσης ενδέχεται να δουλεύουν, αλλά δεν υποστηρίζονται επίσημα (ο GDM "προτείνεται" ως λειτουργικός). diff --git a/README.fr.md b/README.fr.md new file mode 100644 index 00000000..03b5a803 --- /dev/null +++ b/README.fr.md @@ -0,0 +1,100 @@ +# sway [](https://travis-ci.org/swaywm/sway) [](https://drewdevault.com/donate?project=4) + +"**S**irCmpwn's **Way**land compositor" est un compositeur [Wayland](http://wayland.freedesktop.org/) +compatible avec i3, **en cours de développement**. +Lisez la [FAQ](https://github.com/swaywm/sway/wiki). Rejoignez le +[canal IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway sur +irc.freenode.net). + +[](https://sr.ht/ICd5.png) + +Si vous souhaitez soutenir le développement de Sway, vous pouvez contribuer à [ma page +Patreon](https://patreon.com/sircmpwn) ou aux [primes](https://github.com/swaywm/sway/issues/986) +pour des fonctionnalités spécifiques. +Tout le monde est invité à réclamer une prime et vous pouvez donner une prime pour n'importe quelle +fonctionnalité souhaitée. Patreon est plus utile pour supporter l'état général et la +maintenance de Sway. + +## Aide en français + +[abdelq](//github.com/abdelq) fournit du support en français sur IRC et Github, dans le fuseau horaire UTC-4 (EST). + +## Signatures de nouvelles versions + +Les nouvelles versions sont signées avec [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +et publiées [sur GitHub](https://github.com/swaywm/sway/releases). + +## Statut + +- [support des fonctionnalités d'i3](https://github.com/swaywm/sway/issues/2) +- [support des fonctionnalités d'IPC](https://github.com/swaywm/sway/issues/98) +- [support des fonctionnalités d'i3bar](https://github.com/swaywm/sway/issues/343) +- [support des fonctionnalités d'i3-gaps](https://github.com/swaywm/sway/issues/307) +- [fonctionnalités de sécurité](https://github.com/swaywm/sway/issues/984) + +## Installation + +### À partir de paquets + +Sway est disponible sur plusieurs distributions. Essayez d'installer le paquet "sway" pour +la vôtre. Si ce n'est pas disponible, consultez [cette page wiki](https://github.com/swaywm/sway/wiki/Unsupported-packages) +pour de l'information sur l'installation pour vos distributions. + +Si vous êtes intéressé à maintenir Sway pour votre distribution, passez par le canal +IRC ou envoyez un e-mail à [email protected] (en anglais seulement) pour des conseils. + +### Compilation depuis la source + +Installez les dépendances : + +* cmake +* [wlc](https://github.com/Cloudef/wlc) +* wayland +* xwayland +* libinput >= 1.6.0 +* libcap +* asciidoc +* pcre +* json-c +* pango +* cairo +* gdk-pixbuf2 * +* pam ** +* imagemagick (requis pour la capture d'image avec swaygrab) +* ffmpeg (requis pour la capture vidéo avec swaygrab) + +_\*Uniquement requis pour swaybar, swaybg, and swaylock_ + +_\*\*Uniquement requis pour swaylock_ + +Exécutez ces commandes : + + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc .. + make + sudo make install + +Sur les systèmes avec logind, vous devez définir quelques caps sur le binaire : + + sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/bin/sway + +Sur les systèmes sans logind, vous devez suid le binaire de sway : + + sudo chmod a+s /usr/local/bin/sway + +## Configuration + +Si vous utilisez déjà i3, copiez votre configuration i3 à `~/.config/sway/config` et +cela va fonctionner. Sinon, copiez l'exemple de fichier de configuration à +`~/.config/sway/config`. Il se trouve généralement dans `/etc/sway/config`. +Exécutez `man 5 sway` pour l'information sur la configuration. + +Mes propres dotfiles sont disponibles [ici](https://git.sr.ht/~sircmpwn/dotfiles) si +vous voulez un peu d'inspiration. Je vous recommande aussi de consulter le +[wiki](https://github.com/swaywm/sway/wiki). + +## Exécution + +Exécutez `sway` à partir d'un TTY. Certains gestionnaires d'affichage peuvent fonctionner, +mais ne sont pas supportés par Sway (gdm est réputé pour assez bien fonctionner). diff --git a/README.it.md b/README.it.md new file mode 100644 index 00000000..ca3e1ea3 --- /dev/null +++ b/README.it.md @@ -0,0 +1,98 @@ +# sway [](https://travis-ci.org/swaywm/sway) [](https://drewdevault.com/donate?project=4) + +"**S**irCmpwn's **Way**land compositor" è un compositor +[Wayland](http://wayland.freedesktop.org/) **in via di sviluppo** +compatibile con i3. +Leggi le [FAQ (in Inglese)](https://github.com/swaywm/sway/wiki). Unisciti al +[canale IRC (in Inglese)](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on +irc.freenode.net). + +[](https://sr.ht/ICd5.png) + +Se vuoi supportare lo sviluppo di Sway, puoi contribuire dalla +[pagina Patreon di SirCmpwn's](https://patreon.com/sircmpwn) o con dei +[premi](https://github.com/swaywm/sway/issues/986) per finanziare lo sviluppo +di funzionalità specifiche. +Chiunque è libero di reclamare un premio o crearne uno per qualsiasi funzionalità. +Patreon è più utile al supporto e alla manutenzione generale di Sway. + +## Supporto italiano +syknro offre supporto in Italiano su GitHub nel fuso orario UTC+2. +Questa traduzione non è ancora completa. [Clicca qui per maggiori informazioni](https://github.com/swaywm/sway/issues/1318) + +## Firme digitali + +Le release sono firmate con [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +e pubblicate [su GitHub](https://github.com/swaywm/sway/releases). + +## Status + +- [supporto funzionalità i3](https://github.com/swaywm/sway/issues/2) +- [supporto funzionalità IPC](https://github.com/swaywm/sway/issues/98) +- [supporto funzionalità i3bar](https://github.com/swaywm/sway/issues/343) +- [supporto funzionalità i3-gaps](https://github.com/swaywm/sway/issues/307) +- [sicurezza](https://github.com/swaywm/sway/issues/984) + +## Installazione + +### Dai pacchetti + +Sway è disponibile in molte distribuzioni. Prova a installare il pacchetto "sway" per la tua. +Se non funziona, controlla [questa pagina (in Inglese)](https://github.com/swaywm/sway/wiki/Unsupported-packages) +per informazioni sull'installazione per le tue distribuzioni. + +Se vuoi creare un pacchetto per la tua distribuzione, passa dall'IRC o manda un email (in Inglese) + +### Compilando il codice sorgente + +Installa queste dipendenze: + +* cmake +* [wlc](https://github.com/Cloudef/wlc) +* wayland +* xwayland +* libinput >= 1.6.0 +* libcap +* asciidoc +* pcre +* json-c +* pango +* cairo +* gdk-pixbuf2 * +* pam ** +* imagemagick (richiesto per catturare immagini con swaygrab) +* ffmpeg (rrichiesto per catturare video con swaygrab) + +_\*Richiesto solo per swaybar, swaybg, e swaylock_ + +_\*\*Richiesto solo per swaylock_ + +Esegui questi comandi: + + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc .. + make + sudo make install + +Per i sistemi con logind, devi impostare un paio di caps sull'eseguibile: + + sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/bin/sway + +Per i sistemi senza logind, devi cambiare i permessi (suid): + + sudo chmod a+s /usr/local/bin/sway + +## Configurazione + +Se usi i3, copia la tua configurazione in `~/.config/sway/config` e +funzionerà direttamente. +Altrimenti copia in `~/.config/sway/config` la configurazione di esempio, +solitamente si trova in `/etc/sway/config`. +Esegui `man 5 sway` per informazioni sulla configurazione. + +## Esecuzione + +Esegui `sway` da un TTY. Qualche display manager potrebbe funzionare ma non sono +ufficialmente supportati da Sway (gdm è risaputo funzionare abbastanza bene). diff --git a/README.ja.md b/README.ja.md new file mode 100644 index 00000000..7573ecc4 --- /dev/null +++ b/README.ja.md @@ -0,0 +1,90 @@ +# sway [](https://travis-ci.org/swaywm/sway) [](https://drewdevault.com/donate?project=4) + +"**S**irCmpwn's **Way**land compositor"は**開発中**の +i3互換な[Wayland](http://wayland.freedesktop.org/)コンポジタです。 +[FAQ](https://github.com/swaywm/sway/wiki)も合わせてご覧ください。 +[IRC チャンネル](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on +irc.freenode.net)もあります。 + +[](https://sr.ht/ICd5.png) + +もしSwayの開発を支援したい場合は[SirCmpwnのPatreon](https://patreon.com/sircmpwn)や +[こちら](https://github.com/swaywm/sway/issues/986)をご覧ください。 + +誰でも賞金を受け取る事ができますし、自分の欲しい機能に賞金を掛ける事が出来ます。 +PatreonはSwayの開発を支援するのにもっとも便利です。 + +## リリース + +Swayのリリースは[B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A)で書名されて +[GitHub](https://github.com/swaywm/sway/releases)で公開されています。 + +## 開発状況 + +- [i3のサポート](https://github.com/swaywm/sway/issues/2) +- [IPCのサポート](https://github.com/swaywm/sway/issues/98) +- [i3barのサポート](https://github.com/swaywm/sway/issues/343) +- [i3-gapsのサポート](https://github.com/swaywm/sway/issues/307) +- [セキュリティ対応](https://github.com/swaywm/sway/issues/984) + +## インストール + +### パッケージから + +Swayは沢山のディストリビューションで提供されています。"sway"パッケージをインストールしてみてください。 +もし、パッケージが存在しないならば、[このページ](https://github.com/swaywm/sway/wiki/Unsupported-packages) +を参照してインストールしてみてください。 + +もし、Swayのパッケージを提供したいならば、SwayのIRCチャンネルか"[email protected]"に連絡してください。 + +### ソースコードから + +まずはコンパイルや実行に必要なソフトウェアやライブラリをインストールしてください。: + +* cmake +* [wlc](https://github.com/Cloudef/wlc) +* wayland +* xwayland +* libinput >= 1.6.0 +* libcap +* asciidoc +* pcre +* json-c +* pango +* cairo +* gdk-pixbuf2 * +* pam ** +* imagemagick (swaygrabでスクリーンショットを撮るのに必要です) +* ffmpeg (swaygrabで画面を録画するのに必要です) + +_\*swaybar,swaybg,swaylockが使用します_ + +_\*\*swaylockが使用します_ + +ターミナルで次のコマンドを実行してください: + + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc .. + make + sudo make install + +logindを使用している場合はバイナリにcapを設定してください: + + sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/bin/sway + +logindを使用していない場合はバイナリにsuidを設定してください: + + sudo chmod a+s /usr/local/bin/sway + +## 設定 + +もし、既にi3を使用しているなら、i3のコンフィグファイルを`~/.config/sway/config`にコピーすれば動きます。 +そうでないならば、サンプルのコンフィグファイルを`~/.config/sway/config`にコピーしてください。 +サンプルのコンフィグファイルは基本的には`/etc/sway/config`にあります。 +`man 5 sway`で各種設定について確認できます。 + +## 実行 + +`sway`をTTYから実行してください。いくつかのDesktopManagerはSwayからサポートされていませんが、動く場合もあります(gdmは特にSwayと相性が良いそうです)。 + @@ -1,16 +1,19 @@ -# sway [](https://travis-ci.org/SirCmpwn/sway) [](https://drewdevault.com/donate?project=4) +# sway [](https://travis-ci.org/swaywm/sway) [](https://drewdevault.com/donate?project=4) + +[**English**](https://github.com/swaywm/sway/blob/master/README.md#sway--) - [日本語](https://github.com/swaywm/sway/blob/master/README.ja.md#sway--) - [Deutsch](https://github.com/swaywm/sway/blob/master/README.de.md#sway--) - [Ελληνικά](https://github.com/swaywm/sway/blob/master/README.el.md#sway--) - [Français](https://github.com/swaywm/sway/blob/master/README.fr.md#sway--) - [Español](https://github.com/swaywm/sway/blob/master/README.es.md#sway--) - [Українська](https://github.com/swaywm/sway/blob/master/README.uk.md#sway--) - [Italiano](https://github.com/swaywm/sway/blob/master/README.it.md#sway--) - [Português](https://github.com/swaywm/sway/blob/master/README.pt.md#sway--) - +[Русский](https://github.com/swaywm/sway/blob/master/README.ru.md#sway--) "**S**irCmpwn's **Way**land compositor" is a **work in progress** i3-compatible [Wayland](http://wayland.freedesktop.org/) compositor. -Read the [FAQ](https://github.com/SirCmpwn/sway/wiki). Join the +Read the [FAQ](https://github.com/swaywm/sway/wiki). Join the [IRC channel](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on irc.freenode.net). [](https://sr.ht/ICd5.png) -If you'd like to support Sway development, you can contribute to [my Patreon -page](https://patreon.com/sircmpwn) or you can contribute to -[bounties](https://github.com/SirCmpwn/sway/issues/986) for specific features. +If you'd like to support Sway development, you can contribute to [SirCmpwn's +Patreon page](https://patreon.com/sircmpwn) or you can contribute to +[bounties](https://github.com/swaywm/sway/issues/986) for specific features. Anyone is welcome to claim a bounty and you can make a bounty for any feature you wish, and Patreon is more useful for supporting the overall health and maintenance of Sway. @@ -18,22 +21,22 @@ maintenance of Sway. ## Release Signatures Releases are signed with [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) -and published [on GitHub](https://github.com/SirCmpwn/sway/releases). +and published [on GitHub](https://github.com/swaywm/sway/releases). ## Status -- [i3 feature support](https://github.com/SirCmpwn/sway/issues/2) -- [IPC feature support](https://github.com/SirCmpwn/sway/issues/98) -- [i3bar feature support](https://github.com/SirCmpwn/sway/issues/343) -- [i3-gaps feature support](https://github.com/SirCmpwn/sway/issues/307) -- [security features](https://github.com/SirCmpwn/sway/issues/984) +- [i3 feature support](https://github.com/swaywm/sway/issues/2) +- [IPC feature support](https://github.com/swaywm/sway/issues/98) +- [i3bar feature support](https://github.com/swaywm/sway/issues/343) +- [i3-gaps feature support](https://github.com/swaywm/sway/issues/307) +- [security features](https://github.com/swaywm/sway/issues/984) ## Installation ### From Packages Sway is available in many distributions. Try installing the "sway" package for -yours. If it's not available, check out [this wiki page](https://github.com/SirCmpwn/sway/wiki/Unsupported-packages) +yours. If it's not available, check out [this wiki page](https://github.com/swaywm/sway/wiki/Unsupported-packages) for information on installation for your distributions. If you're interested in packaging Sway for your distribution, stop by the IRC @@ -73,8 +76,7 @@ Run these commands: On systems with logind, you need to set a few caps on the binary: - sudo setcap cap_sys_ptrace=eip /usr/local/bin/sway - sudo setcap cap_sys_tty_config=eip /usr/local/bin/sway + sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/bin/sway On systems without logind, you need to suid the sway binary: @@ -87,11 +89,7 @@ it'll work out of the box. Otherwise, copy the sample configuration file to `~/.config/sway/config`. It is usually located at `/etc/sway/config`. Run `man 5 sway` for information on the configuration. -My own dotfiles are available [here](https://git.sr.ht/~sircmpwn/dotfiles) if -you want some inspiration, and definitely check out the -[wiki](https://github.com/SirCmpwn/sway/wiki) as well. - ## Running -Instead of running `startx`, run `sway`. You can run `sway` from within X as -well, which is useful for testing. +Run `sway` from a TTY. Some display managers may work but are not supported by +Sway (gdm is known to work fairly well). diff --git a/README.pt.md b/README.pt.md new file mode 100644 index 00000000..96827623 --- /dev/null +++ b/README.pt.md @@ -0,0 +1,105 @@ +# sway [](https://travis-ci.org/swaywm/sway) [](https://drewdevault.com/donate?project=4) + +"**S**irCmpwn's **Way**land compositor" é um compositor [Wayland](http://wayland.freedesktop.org/) +compatível com o i3. Leia o [FAQ](https://github.com/swaywm/sway/wiki). Participe do +[canal IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway no +irc.freenode.net). + +[](https://sr.ht/ICd5.png) + +Se você deseja apoiar o desenvolvimento do Sway, você pode contribuir com o +SirCmpwn em sua [página no Patreon](https://patreon.com/sircmpwn) ou você +pode colaborar com [premiações](https://github.com/swaywm/sway/issues/986) +para recursos específicos. Qualquer um pode requerer uma premiação ao implementar +o recurso especificado, e você pode criar uma premiação para qualquer recurso que desejar. +O Patreon é melhor direcionado para a manutenção a longo prazo do Sway. + +## Ajuda em português + +No momento, o suporte em português no canal do IRC **não está ativo**. Em caso de problemas, +use as [*issues*](https://github.com/swaywm/sway/issues/) do Github (*em inglês*). + +A tradução para português é um *trabalho em progresso*, no momento. Caso encontre algum erro +ou queira colaborar com a tradução, visite +[essa *issue*](https://github.com/swaywm/sway/issues/1318) para mais informações e não +exite em enviar quaisquer correções necessárias. + +## Assinaturas dos *Releases* + +*Releases* são assinadas com a chave +[B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +e publicadas [no GitHub](https://github.com/swaywm/sway/releases). + +## Status + +- [Suporte aos recursos do i3](https://github.com/swaywm/sway/issues/2) +- [Suporte aos recursos IPC](https://github.com/swaywm/sway/issues/98) +- [Suporte aos recursos do i3bar](https://github.com/swaywm/sway/issues/343) +- [Suporte aos recursos do i3-gaps](https://github.com/swaywm/sway/issues/307) +- [Recursos de segurança](https://github.com/swaywm/sway/issues/984) + +## Instalação + +### A partir de pacotes + +Sway está disponível em várias distribuições. Verifique se o pacote "sway" está +disponível a partir do gerenciador de pacotes da sua distribuição. Caso não esteja, +procure por informações sobre como instalar o Sway na sua distribuição +[aqui](https://github.com/swaywm/sway/wiki/Unsupported-packages). + +Se você está interessado em manter um pacote do Sway para a sua distribuição, +visite o canal no IRC ou mande um email para [email protected] (*em inglês*). + +### A partir do código-fonte + +Antes de iniciar a compilação, instale as dependências: + +* cmake +* [wlc](https://github.com/Cloudef/wlc) +* wayland +* xwayland +* libinput >= 1.6.0 +* libcap +* asciidoc +* pcre +* json-c +* pango +* cairo +* gdk-pixbuf2 * +* pam ** +* imagemagick (capturar imagem com o swaygrab) +* ffmpeg (capturar vídeo com o swaygrab) + +_\*Dependência apenas de swaybar, swaybg, e swaylock_ + +_\*\*Dependência apenas de swaylock_ + +Para compilar, execute estes comandos: + + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc .. + make + sudo make install + +Em sistemas com logind, configure as seguintes capacidades para o arquivo binário: + + sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/bin/sway + +Em sistemas sem logind, ative a *flag* de *suid* do arquivo binário: + + sudo chmod a+s /usr/local/bin/sway + +## Configuração + +Se você já usa o i3, copie o arquivo de configuração do i3 para `~/.config/sway/config`; +o Sway lerá o arquivo normalmente. Senão, copie o arquivo de configuração de exemplo +para `~/.config/sway/config`. É comum esse arquivo estar localizado em +`/etc/sway/config`. Veja `man 5 sway` para informações sobre configuração. + +## Executando + +Execute `sway` a partir de um terminal do Linux. Alguns gerenciadores de *display* +podem funcionar, porém o Sway não procura manter compatibilidade com esses (segundo +relatos, o gdm funciona bem com o Sway). + diff --git a/README.ru.md b/README.ru.md new file mode 100644 index 00000000..891adf99 --- /dev/null +++ b/README.ru.md @@ -0,0 +1,94 @@ +# sway [](https://travis-ci.org/swaywm/sway) [](https://drewdevault.com/donate?project=4) + +"**S**irCmpwn's **Way**land compositor" на данный момент **(в разработке)** +i3-совместимый [Wayland](http://wayland.freedesktop.org/) композитор. +Прочитайте [FAQ](https://github.com/swaywm/sway/wiki). Присоединяйтесь к +[IRC каналу](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway на +irc.freenode.net). + +[](https://sr.ht/ICd5.png) + +При желании поддержать разработку Sway вы можете пожертвовать [автору +на его Patreon странице](https://patreon.com/sircmpwn) или взяться +за разработку определённых целей в обмен на [награду](https://github.com/swaywm/sway/issues/986). + +Вы также можете объявить свою награду за определённую цель и больше всего для этого подходит Patreon. + +## Помощь + +DarkReef оказывает поддержку на русском языке в IRC канале и на GitHub в часовом поясе UTC +05:00. +Если у вас есть желанием помочь с переводом на русский языке, то, пожалуйста, ознакомьтесь с [подсказками для переводчиков](https://github.com/swaywm/sway/issues/1318). На этой же странице можно узнать [статус перевода](https://github.com/swaywm/sway/issues/1318#issuecomment-326913020). + +## Подпись версий + +Версии подписаны ключом [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +и опубликованы [на GitHub'е](https://github.com/swaywm/sway/releases). + +## Статус + +- [Поддержка i3](https://github.com/swaywm/sway/issues/2) +- [Поддержка i3-bar](https://github.com/swaywm/sway/issues/343) +- [Поддержка i3-gaps](https://github.com/swaywm/sway/issues/307) +- [Поддержка IPC](https://github.com/swaywm/sway/issues/98) +- [Безопасность](https://github.com/swaywm/sway/issues/984) + +## Установка + +### Из пакета + +Sway доступен во многих дистрибутивах и находится в официальных репозиториях. Попробуйте установить "sway" через ваш пакетный менеджер. +В случае, если это не представляется возможным, то обратитесь к [этой странице](https://github.com/swaywm/sway/wiki/Unsupported-packages) +для получения инструкций по установке для вашего дистрибутива. + +Если вы заинтересованы в создании пакета "sway" в вашем дистрибутиве, то сообщите об этом в IRC +канале или отправьте письмо [email protected]. + +### Сборка из исходников + +Установите следующие пакеты: + +* cmake +* [wlc](https://github.com/Cloudef/wlc) +* wayland +* xwayland +* libinput >= 1.6.0 +* libcap +* asciidoc +* pcre +* json-c +* pango +* cairo +* gdk-pixbuf2 * +* pam ** +* imagemagick (требуется для захвата изображений через swaygrab) +* ffmpeg (требуется для захвата видео через swaygrab) + +_\*Требуется только для swaybar, swaybg и swaylock_ + +_\*\*Требуется только для swaylock_ + +Выполните следующие команды: + + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc .. + make + sudo make install + +Если у вас logind: + + sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/bin/sway + +Иначе: + + sudo chmod a+s /usr/local/bin/sway + +## Настройка + +Если вы уже используете i3, тогда просто скопируйте ваш конфиг в `~/.config/sway/config`. +В любом другом случае, скопируйте `/etc/sway/config` в `~/.config/sway/config`. +Для более детальной информации о настройке: `man 5 sway`. + +## Запуск + +Выполните 'sway' в терминале. **Некоторые** менеджеры сессий могут работать, но не поддерживаются sway (К примеру, gdm работает со sway без проблем). diff --git a/README.uk.md b/README.uk.md new file mode 100644 index 00000000..02b64804 --- /dev/null +++ b/README.uk.md @@ -0,0 +1,105 @@ +# sway [](https://travis-ci.org/swaywm/sway) [](https://drewdevault.com/donate?project=4) + +**Sway** ("**S**irCmpwn's **Way**land compositor") це сумісний з i3 композитор +[Wayland](http://wayland.freedesktop.org/) (**у стані розробки**). +Ознайомтесь з [ЧаПами](https://github.com/swaywm/sway/wiki). +Приєднуйтесь до [спільноти в IRC](http://webchat.freenode.net/?channels=sway&uio=d4) +(#sway на irc.freenode.net). + +[](https://sr.ht/ICd5.png) + +Якщо ви хочете підтримати розробку Sway, ви можете зробити свій внесок у +[SirCmpwn'ову сторінку Patreon](https://patreon.com/sircmpwn) або до +[фонду винагород](https://github.com/swaywm/sway/issues/986) за реалізацію +певного функціоналу. +Кожен може виставити винагороду за реалізацію довільної функції +(і, відповідно, забрати її собі, виконавши це завдання); +кошти від сторінки Patreon підтримують загальну розробку та підтримку Sway. + +## Підтримка українською мовою + +Якщо ви хочете отримати підтримку українською мовою, можете звернутись до користувача +Hummer12007 у IRC-спільноті. Будьте терплячі, вам обов'язково допоможуть. + +Наразі переклад Sway українською ще не завершено (він неповний), проте у вас є шанс долучитись, +детальніше див. [статус](https://github.com/swaywm/sway/issues/1318#issuecomment-322277382). + +## Підписи випусків + +Випуски підписані ключем [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +та публікуються на сторінці [GitHub](https://github.com/swaywm/sway/releases). + +## Стан розробки + +- [Підтримка функцій i3](https://github.com/swaywm/sway/issues/2) +- [Реалізація IPC-протоколу i3](https://github.com/swaywm/sway/issues/98) +- [Підтримка функцій i3bar](https://github.com/swaywm/sway/issues/343) +- [Підтримка функцій i3-gaps](https://github.com/swaywm/sway/issues/307) +- [Функції безпеки](https://github.com/swaywm/sway/issues/984) + +## Встановлення + +### З пакунків + +Sway доступний у багатьох дистрибутивах Linux (а також у FreeBSD). +Спробуйте встановити пакунок `sway` у вашому. +Якщо він недоступний, перегляньте цю [сторінку Wiki](https://github.com/swaywm/sway/wiki/Unsupported-packages) +для інформації щодо встановлення на вашому дистрибутиві. + +Якщо ви готові та зацікавлені запакувати і підтримувати Sway у вашому +дистрибутиві, будемо раді вас бачити у нашому каналі IRC. Ви також можете +спитати порад за адресою [email protected]. + +### З вихідного коду + +Встановіть залежності: + +* cmake +* [wlc](https://github.com/Cloudef/wlc) +* wayland +* xwayland +* libinput >= 1.6.0 +* libcap +* asciidoc +* pcre +* json-c +* pango +* cairo +* gdk-pixbuf2 * +* pam ** +* imagemagick (для захоплення зображень за допомогою swaygrab) +* ffmpeg (для захоплення відео за допомогою swaygrab) + +_\*Лише для swaybar, swaybg та swaylock_ + +_\*\*Лише для swaylock_ + +Виконайте ці команди: + + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc .. + make + sudo make install + +На системах **з** logind, варто встановити декілька можливостей (caps) +на виконуваний файл sway: + + sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/bin/sway + +На системах **без** logind, необхідно встановити біт SUID на виконуваний файл sway: + + sudo chmod a+s /usr/local/bin/sway + +## Налаштування + +Якщо ви вже використовуєте i3, скопіюйте свій файл налаштувань +до `~/.config/sway/config`, він має запрацювати. Інакше, скопіюйте +туди файл-зразок (зазвичай знаходиться у `/etc/sway/config`), і налаштуйте під себе. + +Більше інформації щодо налаштувань можете знайти, виконавши `man 5 sway`. + +## Запуск + +Виконайте `sway` у TTY. Деякі дисплейні менеджери (менеджери сеансу/стільниць) +можуть працювати, але офіційно не підтримуються (проте сумісніть із gdm достатньо висока). diff --git a/include/sway/input_state.h b/include/sway/input_state.h index 903301fb..fd5a3a25 100644 --- a/include/sway/input_state.h +++ b/include/sway/input_state.h @@ -69,7 +69,7 @@ enum modifier_state { MOD_STATE_RELEASED = 2 }; -void pointer_position_set(struct wlc_origin *new_origin, bool force_focus); +void pointer_position_set(double new_x, double new_y, bool force_focus); void center_pointer_on(swayc_t *view); // on button release unset mode depending on the button. diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 010e1f84..50d36e76 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -14,6 +14,7 @@ struct bar { int ipc_event_socketfd; int ipc_socketfd; int status_read_fd; + int status_write_fd; pid_t status_command_pid; }; diff --git a/include/swaybar/status_line.h b/include/swaybar/status_line.h index 9b77e8a7..0664ddee 100644 --- a/include/swaybar/status_line.h +++ b/include/swaybar/status_line.h @@ -13,6 +13,7 @@ struct status_line { list_t *block_line; const char *text_line; command_protocol protocol; + bool click_events; }; struct status_block { @@ -31,6 +32,10 @@ struct status_block { int border_bottom; int border_left; int border_right; + + // Set during rendering + int x; + int width; }; /** @@ -44,6 +49,11 @@ struct status_line *init_status_line(); bool handle_status_line(struct bar *bar); /** + * Handle mouse clicks. + */ +bool status_line_mouse_event(struct bar *bar, int x, int y, uint32_t button); + +/** * Free status line struct. */ void free_status_line(struct status_line *line); diff --git a/include/swaybar/tray/sni.h b/include/swaybar/tray/sni.h index 83809b2d..c2544e2a 100644 --- a/include/swaybar/tray/sni.h +++ b/include/swaybar/tray/sni.h @@ -28,6 +28,7 @@ void sni_icon_ref_free(struct sni_icon_ref *sni_ref); /** * Will return a new item and get its icon. (see warning below) + * May return `NULL` if `name` is not valid. */ struct StatusNotifierItem *sni_create(const char *name); diff --git a/include/swaylock/swaylock.h b/include/swaylock/swaylock.h index 06533108..eeed094e 100644 --- a/include/swaylock/swaylock.h +++ b/include/swaylock/swaylock.h @@ -56,6 +56,9 @@ struct lock_config { struct lock_colors validating; struct lock_colors invalid; } colors; + + int radius; + int thickness; }; void render(struct render_data* render_data, struct lock_config *config); diff --git a/security.d/10-freebsd.in b/security.d/10-freebsd.in new file mode 100644 index 00000000..533b526a --- /dev/null +++ b/security.d/10-freebsd.in @@ -0,0 +1,19 @@ +# sway security rules +# +# FreeBSD does not support getting client PID from server side +# so we can not know the path to the client's binary. +# +# The solution for now is to be permissive and allow all +# features by default for any client. + +# Configures enabled compositor features for specific programs +permit * fullscreen keyboard mouse background screenshot panel lock + +ipc * { + * enabled + events { + * enabled + } +} + + diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt index 11bec4df..48f7a7a8 100644 --- a/sway/CMakeLists.txt +++ b/sway/CMakeLists.txt @@ -94,6 +94,10 @@ endfunction() add_config(config config sway) add_config(00-defaults security.d/00-defaults sway/security.d) +if (CMAKE_SYSTEM_NAME STREQUAL FreeBSD) + add_config(10-freebsd security.d/10-freebsd sway/security.d) +endif (CMAKE_SYSTEM_NAME STREQUAL FreeBSD) + if (A2X_FOUND) add_manpage(sway 1) add_manpage(sway 5) diff --git a/sway/commands.c b/sway/commands.c index d55d9a96..c7dbf731 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -458,7 +458,11 @@ struct cmd_results *handle_command(char *_exec, enum command_context context) { if (!containers) { current_container = get_focused_container(&root_container); } else if (containers->length == 0) { - break; + if (results) { + free_cmd_results(results); + } + results = cmd_results_new(CMD_FAILURE, argv[0], "No matching container"); + goto cleanup; } else { current_container = (swayc_t *)containers->items[i]; } diff --git a/sway/commands/bind.c b/sway/commands/bind.c index af5a01e5..d9ea37b7 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -61,10 +61,11 @@ struct cmd_results *cmd_bindsym(int argc, char **argv) { sym = ((char *)split->items[i])[strlen("button")] - '1' + M_LEFT_CLICK; } if (!sym) { + struct cmd_results *ret = cmd_results_new(CMD_INVALID, "bindsym", + "Unknown key '%s'", (char *)split->items[i]); free_sway_binding(binding); free_flat_list(split); - return cmd_results_new(CMD_INVALID, "bindsym", "Unknown key '%s'", - (char *)split->items[i]); + return ret; } xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t)); if (!key) { diff --git a/sway/commands/move.c b/sway/commands/move.c index a38687c1..8d89f2ef 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -7,6 +7,7 @@ #include "sway/output.h" #include "sway/workspace.h" #include "list.h" +#include "stringop.h" struct cmd_results *cmd_move(int argc, char **argv) { struct cmd_results *error = NULL; @@ -59,18 +60,23 @@ struct cmd_results *cmd_move(int argc, char **argv) { return cmd_results_new(CMD_FAILURE, "move", "Can only move containers and views."); } - const char *ws_name = argv[3]; swayc_t *ws; - if (argc == 5 && strcasecmp(ws_name, "number") == 0) { + const char *num_name = NULL; + char *ws_name = NULL; + if (argc == 5 && strcasecmp(argv[3], "number") == 0) { // move "container to workspace number x" - ws_name = argv[4]; - ws = workspace_by_number(ws_name); + num_name = argv[4]; + ws = workspace_by_number(num_name); } else { + ws_name = join_args(argv + 3, argc - 3); ws = workspace_by_name(ws_name); } if (ws == NULL) { - ws = workspace_create(ws_name); + ws = workspace_create(ws_name ? ws_name : num_name); + } + if (ws_name) { + free(ws_name); } move_container_to(view, get_focused_container(ws)); } else if (strcasecmp(argv[1], "to") == 0 && strcasecmp(argv[2], "output") == 0) { @@ -161,11 +167,11 @@ struct cmd_results *cmd_move(int argc, char **argv) { wlc_view_get_visible_geometry(view->handle, &g); const struct wlc_size *size = wlc_output_get_resolution(output->handle); - struct wlc_point origin; - wlc_pointer_get_position(&origin); + double x_pos, y_pos; + wlc_pointer_get_position_v2(&x_pos, &y_pos); - int32_t x = origin.x - g.size.w / 2; - int32_t y = origin.y - g.size.h / 2; + int32_t x = x_pos - g.size.w / 2; + int32_t y = y_pos - g.size.h / 2; uint32_t w = size->w - g.size.w; uint32_t h = size->h - g.size.h; diff --git a/sway/commands/output.c b/sway/commands/output.c index e5d4b317..911391d2 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -46,7 +46,8 @@ struct cmd_results *cmd_output(int argc, char **argv) { output->enabled = 0; } else if (strcasecmp(command, "resolution") == 0 || strcasecmp(command, "res") == 0) { if (++i >= argc) { - return cmd_results_new(CMD_INVALID, "output", "Missing resolution argument."); + error = cmd_results_new(CMD_INVALID, "output", "Missing resolution argument."); + goto fail; } char *res = argv[i]; char *x = strchr(res, 'x'); @@ -61,7 +62,8 @@ struct cmd_results *cmd_output(int argc, char **argv) { // Format is 1234 4321 width = atoi(res); if (++i >= argc) { - return cmd_results_new(CMD_INVALID, "output", "Missing resolution argument (height)."); + error = cmd_results_new(CMD_INVALID, "output", "Missing resolution argument (height)."); + goto fail; } res = argv[i]; height = atoi(res); @@ -70,7 +72,8 @@ struct cmd_results *cmd_output(int argc, char **argv) { output->height = height; } else if (strcasecmp(command, "position") == 0 || strcasecmp(command, "pos") == 0) { if (++i >= argc) { - return cmd_results_new(CMD_INVALID, "output", "Missing position argument."); + error = cmd_results_new(CMD_INVALID, "output", "Missing position argument."); + goto fail; } char *res = argv[i]; char *c = strchr(res, ','); @@ -85,7 +88,8 @@ struct cmd_results *cmd_output(int argc, char **argv) { // Format is 1234 4321 x = atoi(res); if (++i >= argc) { - return cmd_results_new(CMD_INVALID, "output", "Missing position argument (y)."); + error = cmd_results_new(CMD_INVALID, "output", "Missing position argument (y)."); + goto fail; } res = argv[i]; y = atoi(res); @@ -94,25 +98,49 @@ struct cmd_results *cmd_output(int argc, char **argv) { output->y = y; } else if (strcasecmp(command, "scale") == 0) { if (++i >= argc) { - return cmd_results_new(CMD_INVALID, "output", "Missing scale parameter."); + error = cmd_results_new(CMD_INVALID, "output", "Missing scale parameter."); + goto fail; } output->scale = atoi(argv[i]); } else if (strcasecmp(command, "background") == 0 || strcasecmp(command, "bg") == 0) { wordexp_t p; if (++i >= argc) { - return cmd_results_new(CMD_INVALID, "output", "Missing background file or color specification."); + error = cmd_results_new(CMD_INVALID, "output", "Missing background file or color specification."); + goto fail; } if (i + 1 >= argc) { - return cmd_results_new(CMD_INVALID, "output", "Missing background scaling mode or `solid_color`."); + error = cmd_results_new(CMD_INVALID, "output", "Missing background scaling mode or `solid_color`."); + goto fail; } - if (strcasecmp(argv[argc - 1], "solid_color") == 0) { + if (strcasecmp(argv[i + 1], "solid_color") == 0) { output->background = strdup(argv[argc - 2]); output->background_option = strdup("solid_color"); } else { - char *src = join_args(argv + i, argc - i - 1); - char *mode = argv[argc - 1]; + // argv[i+j]=bg_option + bool valid = false; + char *mode; + size_t j; + for (j = 0; j < (size_t) (argc - i); ++j) { + mode = argv[i + j]; + for (size_t k = 0; k < sizeof(bg_options) / sizeof(char *); ++k) { + if (strcasecmp(mode, bg_options[k]) == 0) { + valid = true; + break; + } + } + if (valid) { + break; + } + } + if (!valid) { + error = cmd_results_new(CMD_INVALID, "output", "Missing background scaling mode."); + goto fail; + } + + char *src = join_args(argv + i, j); if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) { - return cmd_results_new(CMD_INVALID, "output", "Invalid syntax (%s)", src); + error = cmd_results_new(CMD_INVALID, "output", "Invalid syntax (%s)", src); + goto fail; } free(src); src = p.we_wordv[0]; @@ -132,27 +160,19 @@ struct cmd_results *cmd_output(int argc, char **argv) { } } if (!src || access(src, F_OK) == -1) { - return cmd_results_new(CMD_INVALID, "output", "Background file unreadable (%s)", src); - } - for (char *m = mode; *m; ++m) *m = tolower(*m); - // Check mode - bool valid = false; - size_t j; - for (j = 0; j < sizeof(bg_options) / sizeof(char *); ++j) { - if (strcasecmp(mode, bg_options[j]) == 0) { - valid = true; - break; - } - } - if (!valid) { - return cmd_results_new(CMD_INVALID, "output", "Invalid background scaling mode."); + error = cmd_results_new(CMD_INVALID, "output", "Background file unreadable (%s)", src); + wordfree(&p); + goto fail; } + output->background = strdup(src); output->background_option = strdup(mode); if (src != p.we_wordv[0]) { free(src); } wordfree(&p); + + i += j; } } } @@ -192,4 +212,8 @@ struct cmd_results *cmd_output(int argc, char **argv) { } return cmd_results_new(CMD_SUCCESS, NULL, NULL); + +fail: + free_output_config(output); + return error; } diff --git a/sway/commands/set.c b/sway/commands/set.c index e3d08dd3..46fc6d38 100644 --- a/sway/commands/set.c +++ b/sway/commands/set.c @@ -30,7 +30,7 @@ struct cmd_results *cmd_set(int argc, char **argv) { if (!tmp) { return cmd_results_new(CMD_FAILURE, "set", "Not possible to create variable $'%s'", argv[0]); } - snprintf(tmp, size, "$%s", argv[0]); + snprintf(tmp, size+1, "$%s", argv[0]); argv[0] = tmp; } diff --git a/sway/config.c b/sway/config.c index e0b65615..5b2b6569 100644 --- a/sway/config.c +++ b/sway/config.c @@ -128,6 +128,8 @@ void free_output_config(struct output_config *oc) { return; } free(oc->name); + free(oc->background); + free(oc->background_option); free(oc); } @@ -548,9 +550,12 @@ bool load_main_config(const char *file, bool is_active) { strcpy(_path, base); strcat(_path, ent->d_name); lstat(_path, &s); - if (S_ISREG(s.st_mode)) { + if (S_ISREG(s.st_mode) && ent->d_name[0] != '.') { list_add(secconfigs, _path); } + else { + free(_path); + } ent = readdir(dir); } closedir(dir); diff --git a/sway/container.c b/sway/container.c index 358ba767..718608ff 100644 --- a/sway/container.c +++ b/sway/container.c @@ -516,11 +516,11 @@ swayc_t *destroy_view(swayc_t *view) { return NULL; } sway_log(L_DEBUG, "Destroying view '%p'", view); - swayc_t *parent = view->parent; free_swayc(view); // Destroy empty containers - if (parent->type == C_CONTAINER) { + swayc_t *parent = view->parent; + if (parent && parent->type == C_CONTAINER) { return destroy_container(parent); } return parent; @@ -707,8 +707,10 @@ swayc_t *container_under_pointer(void) { if (lookup->children && !lookup->unmanaged) { return NULL; } - struct wlc_point origin; - wlc_pointer_get_position(&origin); + double x, y; + wlc_pointer_get_position_v2(&x, &y); + struct wlc_point origin = { .x = x, .y = y }; + while (lookup && lookup->type != C_VIEW) { int i; int len; @@ -847,7 +849,6 @@ int swayc_gap(swayc_t *container) { void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { if (container) { - f(container, data); int i; if (container->children) { for (i = 0; i < container->children->length; ++i) { @@ -861,6 +862,7 @@ void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), voi container_map(child, f, data); } } + f(container, data); } } diff --git a/sway/criteria.c b/sway/criteria.c index 04683f66..f5fe40cb 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -12,9 +12,12 @@ enum criteria_type { // *must* keep in sync with criteria_strings[] CRIT_CLASS, + CRIT_CON_ID, CRIT_CON_MARK, + CRIT_FLOATING, CRIT_ID, CRIT_INSTANCE, + CRIT_TILING, CRIT_TITLE, CRIT_URGENT, CRIT_WINDOW_ROLE, @@ -25,9 +28,12 @@ enum criteria_type { // *must* keep in sync with criteria_strings[] static const char * const criteria_strings[CRIT_LAST] = { [CRIT_CLASS] = "class", + [CRIT_CON_ID] = "con_id", [CRIT_CON_MARK] = "con_mark", + [CRIT_FLOATING] = "floating", [CRIT_ID] = "id", [CRIT_INSTANCE] = "instance", + [CRIT_TILING] = "tiling", [CRIT_TITLE] = "title", [CRIT_URGENT] = "urgent", // either "latest" or "oldest" ... [CRIT_WINDOW_ROLE] = "window_role", @@ -108,6 +114,7 @@ static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str char **argv = *buf = calloc(max_tokens, sizeof(char*)); argv[0] = base; // this needs to be freed by caller + bool quoted = true; *argc = 1; // uneven = name, even = value while (*head && *argc < max_tokens) { @@ -128,7 +135,8 @@ static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str if (*(namep) == ' ') { namep = strrchr(namep, ' ') + 1; } - argv[(*argc)++] = namep; + argv[*argc] = namep; + *argc += 1; } } else if (*head == '"') { if (*argc % 2 != 0) { @@ -137,21 +145,38 @@ static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str "Found quoted value where it was not expected"); } else if (!valp) { // value starts here valp = head + 1; + quoted = true; } else { // value ends here - argv[(*argc)++] = valp; + argv[*argc] = valp; + *argc += 1; *head = '\0'; valp = NULL; namep = head + 1; } - } else if (*argc % 2 == 0 && !valp && *head != ' ') { - // We're expecting a quoted value, haven't found one yet, and this - // is not an empty space. - return strdup("Unable to parse criteria: " - "Names must be unquoted, values must be quoted"); + } else if (*argc % 2 == 0 && *head != ' ') { + // parse unquoted values + if (!valp) { + quoted = false; + valp = head; // value starts here + } + } else if (valp && !quoted && *head == ' ') { + // value ends here + argv[*argc] = valp; + *argc += 1; + *head = '\0'; + valp = NULL; + namep = head + 1; } head++; } + + // catch last unquoted value if needed + if (valp && !quoted && !*head) { + argv[*argc] = valp; + *argc += 1; + } + return NULL; } @@ -263,6 +288,15 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) { matches++; } break; + case CRIT_CON_ID: { + char *endptr; + size_t crit_id = strtoul(crit->raw, &endptr, 10); + + if (*endptr == 0 && cont->id == crit_id) { + ++matches; + } + break; + } case CRIT_CON_MARK: if (crit->regex && cont->marks && (list_seq_find(cont->marks, (int (*)(const void *, const void *))regex_cmp, crit->regex) != -1)) { // Make sure it isn't matching the NUL string @@ -271,6 +305,11 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) { } } break; + case CRIT_FLOATING: + if (cont->is_floating) { + matches++; + } + break; case CRIT_ID: if (!cont->app_id) { // ignore @@ -290,6 +329,11 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) { matches++; } break; + case CRIT_TILING: + if (!cont->is_floating) { + matches++; + } + break; case CRIT_TITLE: if (!cont->name) { // ignore diff --git a/sway/handlers.c b/sway/handlers.c index 052789ca..d37142a9 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -452,6 +452,7 @@ static bool handle_view_created(wlc_handle handle) { wlc_view_focus(handle); wlc_view_bring_to_front(handle); newview = new_floating_view(handle); + /* fallthrough */ case WLC_BIT_POPUP: wlc_view_bring_to_front(handle); break; @@ -552,21 +553,24 @@ static void handle_view_destroyed(wlc_handle handle) { bool fullscreen = swayc_is_fullscreen(view); remove_view_from_scratchpad(view); swayc_t *parent = destroy_view(view); - if (fullscreen) { - parent->fullscreen = NULL; - } + if (parent) { + if (fullscreen) { + parent->fullscreen = NULL; + } - // Destroy empty workspaces - if (parent->type == C_WORKSPACE && - parent->children->length == 0 && - parent->floating->length == 0 && - swayc_active_workspace() != parent && - !parent->visible) { - parent = destroy_workspace(parent); - } + ipc_event_window(parent, "close"); - arrange_windows(parent, -1, -1); - ipc_event_window(parent, "close"); + // Destroy empty workspaces + if (parent->type == C_WORKSPACE && + parent->children->length == 0 && + parent->floating->length == 0 && + swayc_active_workspace() != parent && + !parent->visible) { + parent = destroy_workspace(parent); + } + + arrange_windows(parent, -1, -1); + } } else { // Is it unmanaged? int i; @@ -582,6 +586,15 @@ static void handle_view_destroyed(wlc_handle handle) { } } } + // Is it in the scratchpad? + for (i = 0; i < scratchpad->length; ++i) { + swayc_t *item = scratchpad->items[i]; + if (item->handle == handle) { + list_del(scratchpad, i); + destroy_view(item); + break; + } + } } set_focused_container(get_focused_view(&root_container)); } @@ -805,11 +818,11 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier struct sway_binding *binding = mode->bindings->items[i]; if ((modifiers->mods ^ binding->modifiers) == 0) { switch (state) { - case WLC_KEY_STATE_PRESSED: { + case WLC_KEY_STATE_PRESSED: if (!binding->release && valid_bindsym(binding)) { list_add(candidates, binding); } - } + break; case WLC_KEY_STATE_RELEASED: if (binding->release && handle_bindsym_release(binding)) { list_free(candidates); @@ -842,12 +855,13 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier return EVENT_PASSTHROUGH; } -static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_point *origin) { +static bool handle_pointer_motion(wlc_handle handle, uint32_t time, double x, double y) { if (desktop_shell.is_locked) { return EVENT_PASSTHROUGH; } - struct wlc_point new_origin = *origin; + double new_x = x; + double new_y = y; // Switch to adjacent output if touching output edge. // // Since this doesn't currently support moving windows between outputs we @@ -856,45 +870,43 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct !pointer_state.left.held && !pointer_state.right.held && !pointer_state.scroll.held) { swayc_t *output = swayc_active_output(), *adjacent = NULL; - struct wlc_point abs_pos = *origin; - abs_pos.x += output->x; - abs_pos.y += output->y; - if (origin->x == 0) { // Left edge + struct wlc_point abs_pos = { .x = x + output->x, .y = y + output->y }; + if (x <= 0) { // Left edge if ((adjacent = swayc_adjacent_output(output, MOVE_LEFT, &abs_pos, false))) { if (workspace_switch(swayc_active_workspace_for(adjacent))) { - new_origin.x = adjacent->width; + new_x = adjacent->width; // adjust for differently aligned outputs (well, this is // only correct when the two outputs have the same // resolution or the same dpi I guess, it should take // physical attributes into account) - new_origin.y += (output->y - adjacent->y); + new_y += (output->y - adjacent->y); } } - } else if ((double)origin->x == output->width) { // Right edge + } else if (x >= output->width) { // Right edge if ((adjacent = swayc_adjacent_output(output, MOVE_RIGHT, &abs_pos, false))) { if (workspace_switch(swayc_active_workspace_for(adjacent))) { - new_origin.x = 0; - new_origin.y += (output->y - adjacent->y); + new_x = 0; + new_y += (output->y - adjacent->y); } } - } else if (origin->y == 0) { // Top edge + } else if (y <= 0) { // Top edge if ((adjacent = swayc_adjacent_output(output, MOVE_UP, &abs_pos, false))) { if (workspace_switch(swayc_active_workspace_for(adjacent))) { - new_origin.y = adjacent->height; - new_origin.x += (output->x - adjacent->x); + new_y = adjacent->height; + new_x += (output->x - adjacent->x); } } - } else if ((double)origin->y == output->height) { // Bottom edge + } else if (y >= output->height) { // Bottom edge if ((adjacent = swayc_adjacent_output(output, MOVE_DOWN, &abs_pos, false))) { if (workspace_switch(swayc_active_workspace_for(adjacent))) { - new_origin.y = 0; - new_origin.x += (output->x - adjacent->x); + new_y = 0; + new_x += (output->x - adjacent->x); } } } } - pointer_position_set(&new_origin, false); + pointer_position_set(new_x, new_y, false); swayc_t *focused = get_focused_container(&root_container); if (focused->type == C_VIEW) { @@ -935,15 +947,15 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w struct sway_binding *binding = mode->bindings->items[i]; if ((modifiers->mods ^ binding->modifiers) == 0) { switch (state) { - case WLC_BUTTON_STATE_PRESSED: { - if (!binding->release && handle_bindsym(binding, button, 0)) { - return EVENT_HANDLED; - } + case WLC_BUTTON_STATE_PRESSED: + if (!binding->release && handle_bindsym(binding, button, 0)) { + return EVENT_HANDLED; + } + break; + case WLC_BUTTON_STATE_RELEASED: + if (binding->release && handle_bindsym(binding, button, 0)) { + return EVENT_HANDLED; } - case WLC_BUTTON_STATE_RELEASED: - if (binding->release && handle_bindsym(binding, button, 0)) { - return EVENT_HANDLED; - } break; } } @@ -1084,16 +1096,8 @@ bool handle_pointer_scroll(wlc_handle view, uint32_t time, const struct wlc_modi return EVENT_PASSTHROUGH; } -static void clip_test_cb(void *data, const char *type, int fd) { - const char *str = data; - write(fd, str, strlen(str)); - close(fd); -} - static void handle_wlc_ready(void) { sway_log(L_DEBUG, "Compositor is ready, executing cmds in queue"); - const char *type = "text/plain;charset=utf-8"; - wlc_set_selection("test", &type, 1, &clip_test_cb); // Execute commands until there are none left config->active = true; while (config->cmd_queue->length) { @@ -1122,7 +1126,7 @@ void register_wlc_handlers() { wlc_set_view_request_state_cb(handle_view_state_request); wlc_set_view_properties_updated_cb(handle_view_properties_updated); wlc_set_keyboard_key_cb(handle_key); - wlc_set_pointer_motion_cb(handle_pointer_motion); + wlc_set_pointer_motion_cb_v2(handle_pointer_motion); wlc_set_pointer_button_cb(handle_pointer_button); wlc_set_pointer_scroll_cb(handle_pointer_scroll); wlc_set_compositor_ready_cb(handle_wlc_ready); diff --git a/sway/input_state.c b/sway/input_state.c index 68df17de..04aafd37 100644 --- a/sway/input_state.c +++ b/sway/input_state.c @@ -202,13 +202,13 @@ static void reset_initial_sibling(void) { pointer_state.mode = 0; } -void pointer_position_set(struct wlc_point *new_origin, bool force_focus) { - struct wlc_point origin; - wlc_pointer_get_position(&origin); - pointer_state.delta.x = new_origin->x - origin.x; - pointer_state.delta.y = new_origin->y - origin.y; +void pointer_position_set(double new_x, double new_y, bool force_focus) { + double x, y; + wlc_pointer_get_position_v2(&x, &y); + pointer_state.delta.x = new_x - x; + pointer_state.delta.y = new_y - y; - wlc_pointer_set_position(new_origin); + wlc_pointer_set_position_v2(new_x, new_y); // Update view under pointer swayc_t *prev_view = pointer_state.view; @@ -226,10 +226,7 @@ void pointer_position_set(struct wlc_point *new_origin, bool force_focus) { } void center_pointer_on(swayc_t *view) { - struct wlc_point new_origin; - new_origin.x = view->x + view->width/2; - new_origin.y = view->y + view->height/2; - pointer_position_set(&new_origin, true); + pointer_position_set(view->x + view->width/2, view->y + view->height/2, true); } // Mode set left/right click @@ -269,10 +266,10 @@ static void pointer_mode_set_resizing(void) { int midway_x = initial.ptr->x + initial.ptr->width/2; int midway_y = initial.ptr->y + initial.ptr->height/2; - struct wlc_point origin; - wlc_pointer_get_position(&origin); - lock.left = origin.x > midway_x; - lock.top = origin.y > midway_y; + double x, y; + wlc_pointer_get_position_v2(&x, &y); + lock.left = x > midway_x; + lock.top = y > midway_y; if (initial.ptr->is_floating) { pointer_state.mode = M_RESIZING | M_FLOATING; @@ -346,10 +343,10 @@ void pointer_mode_update(void) { pointer_state.mode = 0; return; } - struct wlc_point origin; - wlc_pointer_get_position(&origin); - int dx = origin.x; - int dy = origin.y; + double x, y; + wlc_pointer_get_position_v2(&x, &y); + int dx = x; + int dy = y; switch (pointer_state.mode) { case M_FLOATING | M_DRAGGING: diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 31de53f0..6ab63c75 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -138,7 +138,6 @@ static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object) json_object_object_add(object, "num", json_object_new_int(num)); json_object_object_add(object, "output", (workspace->parent) ? json_object_new_string(workspace->parent->name) : NULL); - json_object_object_add(object, "urgent", json_object_new_boolean(false)); json_object_object_add(object, "type", json_object_new_string("workspace")); json_object_object_add(object, "layout", (strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout)); } @@ -156,38 +155,14 @@ static const char *ipc_json_get_scratchpad_state(swayc_t *c) { static void ipc_json_describe_view(swayc_t *c, json_object *object) { json_object *props = json_object_new_object(); - float percent = ipc_json_child_percentage(c); - const char *layout = (c->parent->type == C_CONTAINER) ? - ipc_json_layout_description(c->parent->layout) : "none"; - const char *last_layout = (c->parent->type == C_CONTAINER) ? - ipc_json_layout_description(c->parent->prev_layout) : "none"; - wlc_handle parent = wlc_view_get_parent(c->handle); - json_object_object_add(object, "type", json_object_new_string((c->is_floating) ? "floating_con" : "con")); + wlc_handle parent = wlc_view_get_parent(c->handle); json_object_object_add(object, "scratchpad_state", json_object_new_string(ipc_json_get_scratchpad_state(c))); - json_object_object_add(object, "percent", (percent > 0) ? json_object_new_double(percent) : NULL); - // TODO: make urgency actually work once Sway supports it - json_object_object_add(object, "urgent", json_object_new_boolean(false)); - json_object_object_add(object, "layout", - (strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout)); - json_object_object_add(object, "last_split_layout", - (strcmp(last_layout, "null") == 0) ? NULL : json_object_new_string(last_layout)); - json_object_object_add(object, "workspace_layout", - json_object_new_string(ipc_json_layout_description(swayc_parent_by_type(c, C_WORKSPACE)->workspace_layout))); - - json_object_object_add(object, "border", json_object_new_string(ipc_json_border_description(c))); - json_object_object_add(object, "current_border_width", json_object_new_int(c->border_thickness)); - - json_object_object_add(object, "rect", ipc_json_create_rect(c)); - json_object_object_add(object, "deco_rect", ipc_json_create_rect_from_geometry(c->title_bar_geometry)); - json_object_object_add(object, "geometry", ipc_json_create_rect_from_geometry(c->cached_geometry)); - json_object_object_add(object, "window_rect", ipc_json_create_rect_from_geometry(c->actual_geometry)); json_object_object_add(object, "name", (c->name) ? json_object_new_string(c->name) : NULL); - json_object_object_add(object, "window", json_object_new_int(c->handle)); // for the sake of i3 compat json_object_object_add(props, "class", c->class ? json_object_new_string(c->class) : c->app_id ? json_object_new_string(c->app_id) : NULL); json_object_object_add(props, "instance", c->instance ? json_object_new_string(c->instance) : @@ -203,9 +178,29 @@ static void ipc_json_describe_view(swayc_t *c, json_object *object) { c->is_floating ? "auto_on" : "auto_off")); // we can't state the cause json_object_object_add(object, "app_id", c->app_id ? json_object_new_string(c->app_id) : NULL); + + if (c->parent) { + const char *layout = (c->parent->type == C_CONTAINER) ? + ipc_json_layout_description(c->parent->layout) : "none"; + const char *last_layout = (c->parent->type == C_CONTAINER) ? + ipc_json_layout_description(c->parent->prev_layout) : "none"; + json_object_object_add(object, "layout", + (strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout)); + json_object_object_add(object, "last_split_layout", + (strcmp(last_layout, "null") == 0) ? NULL : json_object_new_string(last_layout)); + json_object_object_add(object, "workspace_layout", + json_object_new_string(ipc_json_layout_description(swayc_parent_by_type(c, C_WORKSPACE)->workspace_layout))); + } +} + +static void ipc_json_describe_root(swayc_t *c, json_object *object) { + json_object_object_add(object, "type", json_object_new_string("root")); + json_object_object_add(object, "layout", json_object_new_string("splith")); } json_object *ipc_json_describe_container(swayc_t *c) { + float percent = ipc_json_child_percentage(c); + if (!(sway_assert(c, "Container must not be null."))) { return NULL; } @@ -218,9 +213,19 @@ json_object *ipc_json_describe_container(swayc_t *c) { json_object_object_add(object, "visible", json_object_new_boolean(c->visible)); json_object_object_add(object, "focused", json_object_new_boolean(c == current_focus)); + json_object_object_add(object, "border", json_object_new_string(ipc_json_border_description(c))); + json_object_object_add(object, "window_rect", ipc_json_create_rect_from_geometry(c->actual_geometry)); + json_object_object_add(object, "deco_rect", ipc_json_create_rect_from_geometry(c->title_bar_geometry)); + json_object_object_add(object, "geometry", ipc_json_create_rect_from_geometry(c->cached_geometry)); + json_object_object_add(object, "percent", (percent > 0) ? json_object_new_double(percent) : NULL); + json_object_object_add(object, "window", json_object_new_int(c->handle)); // for the sake of i3 compat + // TODO: make urgency actually work once Sway supports it + json_object_object_add(object, "urgent", json_object_new_boolean(false)); + json_object_object_add(object, "current_border_width", json_object_new_int(c->border_thickness)); + switch (c->type) { case C_ROOT: - json_object_object_add(object, "type", json_object_new_string("root")); + ipc_json_describe_root(c, object); break; case C_OUTPUT: @@ -451,21 +456,50 @@ json_object *ipc_json_describe_container_recursive(swayc_t *c) { int i; json_object *floating = json_object_new_array(); - if (c->type != C_VIEW && c->floating && c->floating->length > 0) { + if (c->type != C_VIEW && c->floating) { for (i = 0; i < c->floating->length; ++i) { - json_object_array_add(floating, ipc_json_describe_container_recursive(c->floating->items[i])); + swayc_t *item = c->floating->items[i]; + json_object_array_add(floating, ipc_json_describe_container_recursive(item)); } } json_object_object_add(object, "floating_nodes", floating); json_object *children = json_object_new_array(); - if (c->type != C_VIEW && c->children && c->children->length > 0) { + if (c->type != C_VIEW && c->children) { for (i = 0; i < c->children->length; ++i) { json_object_array_add(children, ipc_json_describe_container_recursive(c->children->items[i])); } } json_object_object_add(object, "nodes", children); + json_object *focus = json_object_new_array(); + if (c->type != C_VIEW) { + if (c->focused) { + json_object_array_add(focus, json_object_new_double(c->focused->id)); + } + if (c->floating) { + for (i = 0; i < c->floating->length; ++i) { + swayc_t *item = c->floating->items[i]; + if (item == c->focused) { + continue; + } + + json_object_array_add(focus, json_object_new_double(item->id)); + } + } + if (c->children) { + for (i = 0; i < c->children->length; ++i) { + swayc_t *item = c->children->items[i]; + if (item == c->focused) { + continue; + } + + json_object_array_add(focus, json_object_new_double(item->id)); + } + } + } + json_object_object_add(object, "focus", focus); + if (c->type == C_ROOT) { json_object *scratchpad_json = json_object_new_array(); if (scratchpad->length > 0) { diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 5e1e93ce..4ce2b7eb 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -41,11 +41,15 @@ static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; struct ipc_client { struct wlc_event_source *event_source; + struct wlc_event_source *writable_event_source; int fd; uint32_t payload_length; uint32_t security_policy; enum ipc_command_type current_command; enum ipc_command_type subscribed_events; + size_t write_buffer_len; + size_t write_buffer_size; + char *write_buffer; }; static list_t *ipc_get_pixel_requests = NULL; @@ -72,6 +76,7 @@ struct get_clipboard_request { struct sockaddr_un *ipc_user_sockaddr(void); int ipc_handle_connection(int fd, uint32_t mask, void *data); int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data); +int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data); void ipc_client_disconnect(struct ipc_client *client); void ipc_client_handle_command(struct ipc_client *client); bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length); @@ -182,6 +187,12 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { close(client_fd); return 0; } + if ((flags = fcntl(client_fd, F_GETFL)) == -1 + || fcntl(client_fd, F_SETFL, flags|O_NONBLOCK) == -1) { + sway_log_errno(L_ERROR, "Unable to set NONBLOCK on IPC client socket"); + close(client_fd); + return 0; + } struct ipc_client* client = malloc(sizeof(struct ipc_client)); if (!client) { @@ -193,10 +204,22 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { client->fd = client_fd; client->subscribed_events = 0; client->event_source = wlc_event_loop_add_fd(client_fd, WLC_EVENT_READABLE, ipc_client_handle_readable, client); + client->writable_event_source = NULL; + + client->write_buffer_size = 128; + client->write_buffer_len = 0; + client->write_buffer = malloc(client->write_buffer_size); + if (!client->write_buffer) { + sway_log(L_ERROR, "Unable to allocate ipc client write buffer"); + close(client_fd); + return 0; + } pid_t pid = get_client_pid(client->fd); client->security_policy = get_ipc_policy_mask(pid); + sway_log(L_DEBUG, "New client: fd %d, pid %d", client_fd, pid); + list_add(ipc_client_list, client); return 0; @@ -219,6 +242,8 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { return 0; } + sway_log(L_DEBUG, "Client %d readable", client->fd); + int read_available; if (ioctl(client_fd, FIONREAD, &read_available) == -1) { sway_log_errno(L_INFO, "Unable to read IPC socket buffer size"); @@ -240,6 +265,7 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { uint8_t buf[ipc_header_size]; uint32_t *buf32 = (uint32_t*)(buf + sizeof(ipc_magic)); + // Should be fully available, because read_available >= ipc_header_size ssize_t received = recv(client_fd, buf, ipc_header_size, 0); if (received == -1) { sway_log_errno(L_INFO, "Unable to receive header from IPC client"); @@ -263,6 +289,48 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { return 0; } +int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { + struct ipc_client *client = data; + + if (mask & WLC_EVENT_ERROR) { + sway_log(L_ERROR, "IPC Client socket error, removing client"); + ipc_client_disconnect(client); + return 0; + } + + if (mask & WLC_EVENT_HANGUP) { + sway_log(L_DEBUG, "Client %d hung up", client->fd); + ipc_client_disconnect(client); + return 0; + } + + if (client->write_buffer_len <= 0) { + return 0; + } + + sway_log(L_DEBUG, "Client %d writable", client->fd); + + ssize_t written = write(client->fd, client->write_buffer, client->write_buffer_len); + + if (written == -1 && errno == EAGAIN) { + return 0; + } else if (written == -1) { + sway_log_errno(L_INFO, "Unable to send data from queue to IPC client"); + ipc_client_disconnect(client); + return 0; + } + + memmove(client->write_buffer, client->write_buffer + written, client->write_buffer_len - written); + client->write_buffer_len -= written; + + if (client->write_buffer_len == 0 && client->writable_event_source) { + wlc_event_source_remove(client->writable_event_source); + client->writable_event_source = NULL; + } + + return 0; +} + void ipc_client_disconnect(struct ipc_client *client) { if (!sway_assert(client != NULL, "client != NULL")) { return; @@ -274,9 +342,13 @@ void ipc_client_disconnect(struct ipc_client *client) { sway_log(L_INFO, "IPC Client %d disconnected", client->fd); wlc_event_source_remove(client->event_source); + if (client->writable_event_source) { + wlc_event_source_remove(client->writable_event_source); + } int i = 0; while (i < ipc_client_list->length && ipc_client_list->items[i] != client) i++; list_del(ipc_client_list, i); + free(client->write_buffer); close(client->fd); free(client); } @@ -608,6 +680,7 @@ void ipc_client_handle_command(struct ipc_client *client) { return; } if (client->payload_length > 0) { + // Payload should be fully available ssize_t received = recv(client->fd, buf, client->payload_length, 0); if (received == -1) { @@ -874,17 +947,36 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay data32[0] = payload_length; data32[1] = client->current_command; - if (write(client->fd, data, ipc_header_size) == -1) { - sway_log_errno(L_INFO, "Unable to send header to IPC client"); + while (client->write_buffer_len + ipc_header_size + payload_length >= + client->write_buffer_size) { + client->write_buffer_size *= 2; + } + + // TODO: reduce the limit back to 4 MB when screenshooter is implemented + if (client->write_buffer_size > (1 << 28)) { // 256 MB + sway_log(L_ERROR, "Client write buffer too big, disconnecting client"); + ipc_client_disconnect(client); return false; } - if (write(client->fd, payload, payload_length) == -1) { - sway_log_errno(L_INFO, "Unable to send payload to IPC client"); + char *new_buffer = realloc(client->write_buffer, client->write_buffer_size); + if (!new_buffer) { + sway_log(L_ERROR, "Unable to reallocate ipc client write buffer"); + ipc_client_disconnect(client); return false; } + client->write_buffer = new_buffer; + + memcpy(client->write_buffer + client->write_buffer_len, data, ipc_header_size); + client->write_buffer_len += ipc_header_size; + memcpy(client->write_buffer + client->write_buffer_len, payload, payload_length); + client->write_buffer_len += payload_length; + + if (!client->writable_event_source) { + client->writable_event_source = wlc_event_loop_add_fd(client->fd, WLC_EVENT_WRITABLE, ipc_client_handle_writable, client); + } - sway_log(L_DEBUG, "Send IPC reply: %s", payload); + sway_log(L_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload); return true; } @@ -984,11 +1076,7 @@ void ipc_event_window(swayc_t *window, const char *change) { sway_log(L_DEBUG, "Sending window::%s event", change); json_object *obj = json_object_new_object(); json_object_object_add(obj, "change", json_object_new_string(change)); - if (strcmp(change, "close") == 0 || !window) { - json_object_object_add(obj, "container", NULL); - } else { - json_object_object_add(obj, "container", ipc_json_describe_container(window)); - } + json_object_object_add(obj, "container", ipc_json_describe_container_recursive(window)); const char *json_string = json_object_to_json_string(obj); ipc_send_event(json_string, IPC_EVENT_WINDOW); diff --git a/sway/main.c b/sway/main.c index 82375e0b..6d13955c 100644 --- a/sway/main.c +++ b/sway/main.c @@ -53,6 +53,46 @@ static void wlc_log_handler(enum wlc_log_type type, const char *str) { } } +void detect_raspi() { + bool raspi = false; + FILE *f = fopen("/sys/firmware/devicetree/base/model", "r"); + if (!f) { + return; + } + char *line; + while(!feof(f)) { + if (!(line = read_line(f))) { + break; + } + if (strstr(line, "Raspberry Pi")) { + raspi = true; + } + free(line); + } + fclose(f); + FILE *g = fopen("/proc/modules", "r"); + if (!g) { + return; + } + bool vc4 = false; + while (!feof(g)) { + if (!(line = read_line(g))) { + break; + } + if (strstr(line, "vc4")) { + vc4 = true; + } + free(line); + } + fclose(g); + if (!vc4 && raspi) { + fprintf(stderr, "\x1B[1;31mWarning: You have a " + "Raspberry Pi, but the vc4 Module is " + "not loaded! Set 'dtoverlay=vc4-kms-v3d'" + "in /boot/config.txt and reboot.\x1B[0m\n"); + } +} + void detect_proprietary() { FILE *f = fopen("/proc/modules", "r"); if (!f) { @@ -366,6 +406,7 @@ int main(int argc, char **argv) { log_distro(); log_env(); detect_proprietary(); + detect_raspi(); input_devices = create_list(); diff --git a/sway/sway-security.7.txt b/sway/sway-security.7.txt index ec6df1f3..aee3793c 100644 --- a/sway/sway-security.7.txt +++ b/sway/sway-security.7.txt @@ -237,4 +237,4 @@ Authors ------- Maintained by Drew DeVault <[email protected]>, who is assisted by other open source contributors. For more information about sway development, see -<https://github.com/SirCmpwn/sway>. +<https://github.com/swaywm/sway>. diff --git a/sway/sway.1.txt b/sway/sway.1.txt index bc827bd5..4a1aef99 100644 --- a/sway/sway.1.txt +++ b/sway/sway.1.txt @@ -119,7 +119,7 @@ Authors Maintained by Drew DeVault <[email protected]>, who is assisted by other open source contributors. For more information about sway development, see -<https://github.com/SirCmpwn/sway>. +<https://github.com/swaywm/sway>. See Also -------- diff --git a/sway/workspace.c b/sway/workspace.c index 29cacce9..e0367190 100644 --- a/sway/workspace.c +++ b/sway/workspace.c @@ -61,7 +61,7 @@ char *workspace_next_name(const char *output_name) { // workspace n char *cmd = argsep(&cmdlist, " "); if (cmdlist) { - name = argsep(&cmdlist, " ,;"); + name = argsep(&cmdlist, ",;"); } if (strcmp("workspace", cmd) == 0 && name) { diff --git a/swaybar/CMakeLists.txt b/swaybar/CMakeLists.txt index 373719de..48ededdd 100644 --- a/swaybar/CMakeLists.txt +++ b/swaybar/CMakeLists.txt @@ -7,7 +7,7 @@ include_directories( ${XKBCOMMON_INCLUDE_DIRS} ${DBUS_INCLUDE_DIRS} ) -if (enable-tray) +if (ENABLE_TRAY) file(GLOB tray tray/*.c ) diff --git a/swaybar/bar.c b/swaybar/bar.c index 5e87eac9..f8dc3a1f 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -7,6 +7,7 @@ #include <sys/wait.h> #include <signal.h> #include <poll.h> +#include <linux/input-event-codes.h> #ifdef ENABLE_TRAY #include <dbus/dbus.h> #include "swaybar/tray/sni_watcher.h" @@ -31,16 +32,30 @@ static void bar_init(struct bar *bar) { static void spawn_status_cmd_proc(struct bar *bar) { if (bar->config->status_command) { - int pipefd[2]; - if (pipe(pipefd) != 0) { - sway_log(L_ERROR, "Unable to create pipe for status_command fork"); + int pipe_read_fd[2]; + int pipe_write_fd[2]; + + if (pipe(pipe_read_fd) != 0) { + sway_log(L_ERROR, "Unable to create pipes for status_command fork"); + return; + } + if (pipe(pipe_write_fd) != 0) { + sway_log(L_ERROR, "Unable to create pipe for status_command fork (write)"); + close(pipe_read_fd[0]); + close(pipe_read_fd[1]); return; } + bar->status_command_pid = fork(); if (bar->status_command_pid == 0) { - close(pipefd[0]); - dup2(pipefd[1], STDOUT_FILENO); - close(pipefd[1]); + close(pipe_read_fd[0]); + dup2(pipe_read_fd[1], STDOUT_FILENO); + close(pipe_read_fd[1]); + + dup2(pipe_write_fd[0], STDIN_FILENO); + close(pipe_write_fd[0]); + close(pipe_write_fd[1]); + char *const cmd[] = { "sh", "-c", @@ -51,9 +66,13 @@ static void spawn_status_cmd_proc(struct bar *bar) { return; } - close(pipefd[1]); - bar->status_read_fd = pipefd[0]; + close(pipe_read_fd[1]); + bar->status_read_fd = pipe_read_fd[0]; fcntl(bar->status_read_fd, F_SETFL, O_NONBLOCK); + + close(pipe_write_fd[0]); + bar->status_write_fd = pipe_write_fd[1]; + fcntl(bar->status_write_fd, F_SETFL, O_NONBLOCK); } } @@ -103,14 +122,46 @@ static void mouse_button_notify(struct window *window, int x, int y, } } + switch (button) { + case BTN_LEFT: + status_line_mouse_event(&swaybar, x, y, 1); + break; + case BTN_MIDDLE: + status_line_mouse_event(&swaybar, x, y, 2); + break; + case BTN_RIGHT: + status_line_mouse_event(&swaybar, x, y, 3); + break; + } + #ifdef ENABLE_TRAY tray_mouse_event(clicked_output, x, y, button, state_w); #endif + } static void mouse_scroll_notify(struct window *window, enum scroll_direction direction) { sway_log(L_DEBUG, "Mouse wheel scrolled %s", direction == SCROLL_UP ? "up" : "down"); + // If there are status blocks and click_events are enabled + // check if the position is within the status area and if so + // tell the status line to output the event and skip workspace + // switching below. + int num_blocks = swaybar.status->block_line->length; + if (swaybar.status->click_events && num_blocks > 0) { + struct status_block *first_block = swaybar.status->block_line->items[0]; + int x = window->pointer_input.last_x; + int y = window->pointer_input.last_y; + if (x > first_block->x) { + if (direction == SCROLL_UP) { + status_line_mouse_event(&swaybar, x, y, 4); + } else { + status_line_mouse_event(&swaybar, x, y, 5); + } + return; + } + } + if (!swaybar.config->wrap_scroll) { // Find output this window lives on int i; @@ -318,6 +369,10 @@ void bar_teardown(struct bar *bar) { close(bar->status_read_fd); } + if (bar->status_write_fd) { + close(bar->status_write_fd); + } + if (bar->ipc_socketfd) { close(bar->ipc_socketfd); } diff --git a/swaybar/event_loop.c b/swaybar/event_loop.c index 80655d8b..0d1be1da 100644 --- a/swaybar/event_loop.c +++ b/swaybar/event_loop.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 #include <stdlib.h> #include <stdbool.h> #include <string.h> @@ -96,7 +96,7 @@ bool remove_event(int fd) { static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) { const struct timer_item *timer_item = _timer_item; const timer_t *timer = _timer; - if (timer_item->timer == timer) { + if (timer_item->timer == *timer) { return 0; } else { return -1; @@ -105,6 +105,7 @@ static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) { bool remove_timer(timer_t timer) { int index = list_seq_find(event_loop.timers, timer_item_timer_cmp, &timer); if (index != -1) { + free(event_loop.timers->items[index]); list_del(event_loop.timers, index); return true; } diff --git a/swaybar/render.c b/swaybar/render.c index 6ec47e79..6fc09078 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -94,6 +94,9 @@ static void render_block(struct window *window, struct config *config, struct st double pos = *x; + block->x = (int)pos; + block->width = (int)block_width; + // render background if (block->background != 0x0) { cairo_set_source_u32(window->cairo, block->background); diff --git a/swaybar/status_line.c b/swaybar/status_line.c index 83e8ce2c..e0564c26 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c @@ -27,6 +27,8 @@ struct { static char line[1024]; static char line_rest[1024]; +static char event_buff[1024]; + static void free_status_block(void *item) { if (!item) { return; @@ -391,6 +393,66 @@ static int i3json_handle_fd(struct bar *bar) { return i3json_parse(bar); } +bool status_line_mouse_event(struct bar *bar, int x, int y, uint32_t button) { + sway_log(L_DEBUG, "status_line_mouse_event."); + if (!bar->status->click_events) { + sway_log(L_DEBUG, "click_events are not enabled."); + return false; + } + + if (bar->status->protocol == I3BAR) { + sway_log(L_DEBUG, "Sending click event."); + + // find clicked block + struct status_block *clicked_block = NULL; + struct status_block *current_block = NULL; + int num_blocks = bar->status->block_line->length; + + if (num_blocks == 0) { + return false; + } else { + current_block = bar->status->block_line->items[0]; + if (x < current_block->x) { + return false; + } + } + + for (int i = 0; i < num_blocks; i++) { + current_block = bar->status->block_line->items[i]; + if (x < (current_block->x + current_block->width)) { + clicked_block = current_block; + break; + } + } + + if (!clicked_block || !clicked_block->name) { + return false; + } + + // event example {"name":"capture","instance":"label","button":1,"x":3431,"y":18} + + struct json_object *event_json = json_object_new_object(); + json_object_object_add(event_json, "name", json_object_new_string(clicked_block->name)); + if (clicked_block->instance) { + json_object_object_add(event_json, "instance", json_object_new_string(clicked_block->instance)); + } + json_object_object_add(event_json, "button", json_object_new_int(button)); + json_object_object_add(event_json, "x", json_object_new_int(x)); + json_object_object_add(event_json, "y", json_object_new_int(y)); + + int len = snprintf(event_buff, sizeof(event_buff), "%s,\n", json_object_to_json_string(event_json)); + + json_object_put(event_json); + + if (len <= (int)sizeof(event_buff)) { // if not truncated + write(bar->status_write_fd, event_buff, len); + return true; + } + } + + return false; +} + bool handle_status_line(struct bar *bar) { bool dirty = false; @@ -418,15 +480,29 @@ bool handle_status_line(struct bar *bar) { if (line[0] == '{') { // detect i3bar json protocol json_object *proto = json_tokener_parse(line); - json_object *version; if (proto) { + + json_object *version; if (json_object_object_get_ex(proto, "version", &version) && json_object_get_int(version) == 1 ) { sway_log(L_DEBUG, "Switched to i3bar protocol."); bar->status->protocol = I3BAR; - i3json_handle_data(bar, line_rest); } + + json_object *click_events; + if (json_object_object_get_ex(proto, "click_events", &click_events) + && json_object_get_boolean(click_events)) { + + sway_log(L_DEBUG, "Enabling click events."); + bar->status->click_events = true; + + const char *events_array = "[\n"; + write(bar->status_write_fd, events_array, strlen(events_array)); + } + + i3json_handle_data(bar, line_rest); + json_object_put(proto); } } @@ -441,6 +517,7 @@ struct status_line *init_status_line() { line->block_line = create_list(); line->text_line = NULL; line->protocol = UNDEF; + line->click_events = false; return line; } diff --git a/swaybar/tray/dbus.c b/swaybar/tray/dbus.c index 22531aa6..8e719fd9 100644 --- a/swaybar/tray/dbus.c +++ b/swaybar/tray/dbus.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 #include <stdio.h> #include <stdlib.h> #include <stdint.h> @@ -108,7 +108,7 @@ static dbus_bool_t add_timeout(DBusTimeout *timeout, void *_data) { timer_settime(*timer, 0, &time, NULL); - dbus_timeout_set_data(timeout, timer, free); + dbus_timeout_set_data(timeout, timer, NULL); sway_log(L_DEBUG, "Adding DBus timeout. Interval: %ds %dms", interval_sec, interval_msec); add_timer(*timer, dispatch_timeout, timeout); @@ -121,6 +121,8 @@ static void remove_timeout(DBusTimeout *timeout, void *_data) { if (timer) { remove_timer(*timer); + timer_delete(*timer); + free(timer); } } @@ -136,7 +138,7 @@ static void dispatch_status(DBusConnection *connection, DBusDispatchStatus new_s /* Public functions below */ void dispatch_dbus() { - if (!should_dispatch) { + if (!should_dispatch || !conn) { return; } diff --git a/swaybar/tray/icon.c b/swaybar/tray/icon.c index 1c69ba72..c146bf32 100644 --- a/swaybar/tray/icon.c +++ b/swaybar/tray/icon.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 #define _POSIX_C_SOURCE 200809L #include <stdio.h> #include <stdlib.h> diff --git a/swaybar/tray/sni.c b/swaybar/tray/sni.c index 0c46d5c0..c9d00657 100644 --- a/swaybar/tray/sni.c +++ b/swaybar/tray/sni.c @@ -160,6 +160,7 @@ static void reply_icon(DBusPendingCall *pending, void *_data) { dirty = true; dbus_message_unref(reply); + dbus_pending_call_unref(pending); return; } else { sway_log(L_ERROR, "Could not create image surface"); @@ -170,6 +171,7 @@ bail: if (reply) { dbus_message_unref(reply); } + dbus_pending_call_unref(pending); sway_log(L_ERROR, "Could not get icon from item"); return; } @@ -266,6 +268,7 @@ static void reply_icon_name(DBusPendingCall *pending, void *_data) { dirty = true; dbus_message_unref(reply); + dbus_pending_call_unref(pending); return; } @@ -273,6 +276,7 @@ bail: if (reply) { dbus_message_unref(reply); } + dbus_pending_call_unref(pending); // Now try the pixmap send_icon_msg(item); return; @@ -413,6 +417,12 @@ static void get_unique_name(struct StatusNotifierItem *item) { } struct StatusNotifierItem *sni_create(const char *name) { + // Make sure `name` is well formed + if (!dbus_validate_bus_name(name, NULL)) { + sway_log(L_INFO, "Name (%s) is not a bus name. We cannot create an item.", name); + return NULL; + } + struct StatusNotifierItem *item = malloc(sizeof(struct StatusNotifierItem)); item->name = strdup(name); item->unique_name = NULL; diff --git a/swaybar/tray/sni_watcher.c b/swaybar/tray/sni_watcher.c index 388e181d..86453e70 100644 --- a/swaybar/tray/sni_watcher.c +++ b/swaybar/tray/sni_watcher.c @@ -150,10 +150,14 @@ static void register_item(DBusConnection *connection, DBusMessage *message) { sway_log(L_ERROR, "Error parsing method args: %s\n", error.message); } - name = strdup(name); sway_log(L_INFO, "RegisterStatusNotifierItem called with \"%s\"\n", name); // Don't add duplicate or not real item + if (!dbus_validate_bus_name(name, NULL)) { + sway_log(L_INFO, "This item is not valid, we cannot keep track of it."); + return; + } + if (list_seq_find(items, (int (*)(const void *, const void *))strcmp, name) != -1) { return; } @@ -161,7 +165,7 @@ static void register_item(DBusConnection *connection, DBusMessage *message) { return; } - list_add(items, name); + list_add(items, strdup(name)); item_registered_signal(connection, name); // It's silly, but xembedsniproxy wants a reply for this function @@ -184,6 +188,12 @@ static void register_host(DBusConnection *connection, DBusMessage *message) { sway_log(L_INFO, "RegisterStatusNotifierHost called with \"%s\"\n", name); // Don't add duplicate or not real host + if (!dbus_validate_bus_name(name, NULL)) { + sway_log(L_INFO, "This item is not valid, we cannot keep track of it."); + return; + } + + if (list_seq_find(hosts, (int (*)(const void *, const void *))strcmp, name) != -1) { return; } diff --git a/swaybar/tray/tray.c b/swaybar/tray/tray.c index 00f1a44f..91c3af06 100644 --- a/swaybar/tray/tray.c +++ b/swaybar/tray/tray.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 500 +#define _XOPEN_SOURCE 700 #include <unistd.h> #include <stdlib.h> #include <string.h> @@ -90,13 +90,16 @@ static void get_items_reply(DBusPendingCall *pending, void *_data) { struct StatusNotifierItem *item = sni_create(name); - sway_log(L_DEBUG, "Item registered with host: %s", name); - list_add(tray->items, item); - dirty = true; + if (item) { + sway_log(L_DEBUG, "Item registered with host: %s", name); + list_add(tray->items, item); + dirty = true; + } } bail: dbus_message_unref(reply); + dbus_pending_call_unref(pending); return; } static void get_items() { @@ -141,8 +144,10 @@ static DBusHandlerResult signal_handler(DBusConnection *connection, if (list_seq_find(tray->items, sni_str_cmp, name) == -1) { struct StatusNotifierItem *item = sni_create(name); - list_add(tray->items, item); - dirty = true; + if (item) { + list_add(tray->items, item); + dirty = true; + } } return DBUS_HANDLER_RESULT_HANDLED; diff --git a/swaygrab/main.c b/swaygrab/main.c index c437653d..1b699bb9 100644 --- a/swaygrab/main.c +++ b/swaygrab/main.c @@ -9,6 +9,7 @@ #include <stdint.h> #include <math.h> #include <time.h> +#include <sys/wait.h> #include <json-c/json.h> #include "log.h" #include "ipc-client.h" @@ -47,17 +48,32 @@ void grab_and_apply_magick(const char *file, const char *payload, return; } - const char *fmt = "convert -depth 8 -size %dx%d+0 rgba:- -flip %s"; - char *cmd = malloc(strlen(fmt) - 6 /*args*/ - + numlen(width) + numlen(height) + strlen(file) + 1); - sprintf(cmd, fmt, width, height, file); + char size[10 + 1 + 10 + 2 + 1]; // int32_t are max 10 digits + sprintf(size, "%dx%d+0", width, height); - FILE *f = popen(cmd, "w"); - fwrite(pixels, 1, len, f); - fflush(f); - fclose(f); - free(pixels - 9); - free(cmd); + pid_t child; + int fd[2]; + pipe(fd); + + if ((child = fork()) < 0) { + sway_log(L_ERROR, "Swaygrab failed to fork."); + exit(EXIT_FAILURE); + } else if (child != 0) { + close(fd[0]); + write(fd[1], pixels, len); + close(fd[1]); + free(pixels - 9); + waitpid(child, NULL, 0); + } else { + close(fd[1]); + if (dup2(fd[0], 0) != 0) { + sway_log(L_ERROR, "Could not fdup the pipe"); + } + close(fd[0]); + execlp("convert", "convert", "-depth", "8", "-size", size, "rgba:-", "-flip", file, NULL); + sway_log(L_ERROR, "Swaygrab could not run convert."); + exit(EXIT_FAILURE); + } } void grab_and_apply_movie_magic(const char *file, const char *payload, @@ -93,7 +109,7 @@ void grab_and_apply_movie_magic(const char *file, const char *payload, "-video_size %dx%d -pixel_format argb " "-i pipe:0 -r %d -vf vflip %s"; char *cmd = malloc(strlen(fmt) - 8 /*args*/ - + strlen(ffmpeg_opts) + numlen(width) + numlen(height) + + strlen(ffmpeg_opts) + numlen(width) + numlen(height) + numlen(framerate) * 2 + strlen(file) + 1); sprintf(cmd, fmt, ffmpeg_opts, framerate, width, height, framerate, file); diff --git a/swaygrab/swaygrab.1.txt b/swaygrab/swaygrab.1.txt index 1da56db8..8faf43f5 100644 --- a/swaygrab/swaygrab.1.txt +++ b/swaygrab/swaygrab.1.txt @@ -73,4 +73,4 @@ Authors Maintained by Drew DeVault <[email protected]>, who is assisted by other open source contributors. For more information about sway development, see -<https://github.com/SirCmpwn/sway>. +<https://github.com/swaywm/sway>. diff --git a/swaylock/main.c b/swaylock/main.c index 47592409..c2615951 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -81,6 +81,9 @@ struct lock_config *init_config() { config->colors.invalid.inner_ring = 0xFA0000BF; config->colors.invalid.outer_ring = 0x7D3300FF; + config->radius = 50; + config->thickness = 10; + return config; } @@ -149,10 +152,11 @@ bool verify_password() { void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t code, uint32_t codepoint) { int redraw_screen = 0; char *password_realloc; + int i; if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { switch (sym) { - case XKB_KEY_KP_Enter: // fallthrough + case XKB_KEY_KP_Enter: case XKB_KEY_Return: render_data.auth_state = AUTH_STATE_VALIDATING; @@ -163,6 +167,7 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod if (verify_password()) { exit(0); } + render_data.auth_state = AUTH_STATE_INVALID; redraw_screen = 1; @@ -171,73 +176,65 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod password[0] = '\0'; break; case XKB_KEY_BackSpace: - { - int i = strlen(password); - if (i > 0) { - password[i - 1] = '\0'; - render_data.auth_state = AUTH_STATE_BACKSPACE; - redraw_screen = 1; - } - break; + i = strlen(password); + if (i > 0) { + password[i - 1] = '\0'; + render_data.auth_state = AUTH_STATE_BACKSPACE; + redraw_screen = 1; } - case XKB_KEY_Control_L: // fallthrough - case XKB_KEY_Control_R: // fallthrough - case XKB_KEY_Shift_L: // fallthrough - case XKB_KEY_Shift_R: // fallthrough - case XKB_KEY_Caps_Lock: // fallthrough - case XKB_KEY_Shift_Lock: // fallthrough - case XKB_KEY_Meta_L: // fallthrough - case XKB_KEY_Meta_R: // fallthrough - case XKB_KEY_Alt_L: // fallthrough - case XKB_KEY_Alt_R: // fallthrough - case XKB_KEY_Super_L: // fallthrough - case XKB_KEY_Super_R: // fallthrough - case XKB_KEY_Hyper_L: // fallthrough + break; + case XKB_KEY_Control_L: + case XKB_KEY_Control_R: + case XKB_KEY_Shift_L: + case XKB_KEY_Shift_R: + case XKB_KEY_Caps_Lock: + case XKB_KEY_Shift_Lock: + case XKB_KEY_Meta_L: + case XKB_KEY_Meta_R: + case XKB_KEY_Alt_L: + case XKB_KEY_Alt_R: + case XKB_KEY_Super_L: + case XKB_KEY_Super_R: + case XKB_KEY_Hyper_L: case XKB_KEY_Hyper_R: - { - // don't draw screen on modifier keys - break; - } - case XKB_KEY_Escape: // fallthrough - case XKB_KEY_u: // fallthrough + break; // don't draw screen on modifier keys + case XKB_KEY_Escape: + case XKB_KEY_u: case XKB_KEY_U: - { - // clear password buffer on ctrl-u (or escape for i3lock compatibility) - if (sym == XKB_KEY_Escape || xkb_state_mod_name_is_active(registry->input->xkb.state, - XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE) > 0) { - render_data.auth_state = AUTH_STATE_BACKSPACE; - redraw_screen = 1; + // clear password buffer on ctrl-u (or escape for i3lock compatibility) + if (sym == XKB_KEY_Escape || xkb_state_mod_name_is_active(registry->input->xkb.state, + XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE) > 0) { + render_data.auth_state = AUTH_STATE_BACKSPACE; + redraw_screen = 1; + password_size = 1024; + free(password); + password = malloc(password_size); + password[0] = '\0'; + break; + } + /* fallthrough */ + default: + render_data.auth_state = AUTH_STATE_INPUT; + redraw_screen = 1; + i = strlen(password); + if (i + 1 == password_size) { + password_size += 1024; + password_realloc = realloc(password, password_size); + // reset password if realloc fails. + if (password_realloc == NULL) { password_size = 1024; free(password); password = malloc(password_size); password[0] = '\0'; break; + } else { + password = password_realloc; } } - default: - { - render_data.auth_state = AUTH_STATE_INPUT; - redraw_screen = 1; - int i = strlen(password); - if (i + 1 == password_size) { - password_size += 1024; - password_realloc = realloc(password, password_size); - // reset password if realloc fails. - if (password_realloc == NULL) { - password_size = 1024; - free(password); - password = malloc(password_size); - password[0] = '\0'; - break; - } else { - password = password_realloc; - } - } - password[i] = (char)codepoint; - password[i + 1] = '\0'; - break; - } + password[i] = (char)codepoint; + password[i + 1] = '\0'; + break; } if (redraw_screen) { render(&render_data, config); @@ -383,6 +380,8 @@ int main(int argc, char **argv) { {"separatorcolor", required_argument, NULL, 0}, {"keyhlcolor", required_argument, NULL, 0}, {"bshlcolor", required_argument, NULL, 0}, + {"indicator-radius", required_argument, NULL, 0}, + {"indicator-thickness", required_argument, NULL, 0}, {0, 0, 0, 0} }; @@ -509,6 +508,10 @@ int main(int argc, char **argv) { config->colors.input_cursor = parse_color(optarg); } else if (strcmp(long_options[option_index].name, "bshlcolor") == 0) { config->colors.backspace_cursor = parse_color(optarg); + } else if (strcmp(long_options[option_index].name, "indicator-radius") == 0) { + config->radius = atoi(optarg); + } else if (strcmp(long_options[option_index].name, "indicator-thickness") == 0) { + config->thickness = atoi(optarg); } break; default: @@ -678,16 +681,14 @@ void render(struct render_data *render_data, struct lock_config *config) { cairo_identity_matrix(window->cairo); // Draw specific values (copied from i3) - const int ARC_RADIUS = 50; - const int ARC_THICKNESS = 10; const float TYPE_INDICATOR_RANGE = M_PI / 3.0f; const float TYPE_INDICATOR_BORDER_THICKNESS = M_PI / 128.0f; // Add visual indicator if (show_indicator && render_data->auth_state != AUTH_STATE_IDLE) { // Draw circle - cairo_set_line_width(window->cairo, ARC_THICKNESS); - cairo_arc(window->cairo, wwidth/2, wheight/2, ARC_RADIUS, 0, 2 * M_PI); + cairo_set_line_width(window->cairo, config->thickness); + cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius, 0, 2 * M_PI); switch (render_data->auth_state) { case AUTH_STATE_INPUT: case AUTH_STATE_BACKSPACE: { @@ -715,7 +716,7 @@ void render(struct render_data *render_data, struct lock_config *config) { char *text = NULL; cairo_set_source_u32(window->cairo, config->colors.text); cairo_select_font_face(window->cairo, config->font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_font_size(window->cairo, ARC_RADIUS/3.0f); + cairo_set_font_size(window->cairo, config->radius/3.0f); switch (render_data->auth_state) { case AUTH_STATE_VALIDATING: text = "verifying"; @@ -744,7 +745,7 @@ void render(struct render_data *render_data, struct lock_config *config) { if (render_data->auth_state == AUTH_STATE_INPUT || render_data->auth_state == AUTH_STATE_BACKSPACE) { static double highlight_start = 0; highlight_start += (rand() % (int)(M_PI * 100)) / 100.0 + M_PI * 0.5; - cairo_arc(window->cairo, wwidth/2, wheight/2, ARC_RADIUS, highlight_start, highlight_start + TYPE_INDICATOR_RANGE); + cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius, highlight_start, highlight_start + TYPE_INDICATOR_RANGE); if (render_data->auth_state == AUTH_STATE_INPUT) { cairo_set_source_u32(window->cairo, config->colors.input_cursor); } else { @@ -754,10 +755,10 @@ void render(struct render_data *render_data, struct lock_config *config) { // Draw borders cairo_set_source_u32(window->cairo, config->colors.separator); - cairo_arc(window->cairo, wwidth/2, wheight/2, ARC_RADIUS, highlight_start, highlight_start + TYPE_INDICATOR_BORDER_THICKNESS); + cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius, highlight_start, highlight_start + TYPE_INDICATOR_BORDER_THICKNESS); cairo_stroke(window->cairo); - cairo_arc(window->cairo, wwidth/2, wheight/2, ARC_RADIUS, highlight_start + TYPE_INDICATOR_RANGE, (highlight_start + TYPE_INDICATOR_RANGE) + TYPE_INDICATOR_BORDER_THICKNESS); + cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius, highlight_start + TYPE_INDICATOR_RANGE, (highlight_start + TYPE_INDICATOR_RANGE) + TYPE_INDICATOR_BORDER_THICKNESS); cairo_stroke(window->cairo); } @@ -793,9 +794,9 @@ void render(struct render_data *render_data, struct lock_config *config) { } // Draw inner + outer border of the circle cairo_set_line_width(window->cairo, 2.0); - cairo_arc(window->cairo, wwidth/2, wheight/2, ARC_RADIUS - ARC_THICKNESS/2, 0, 2*M_PI); + cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius - config->thickness/2, 0, 2*M_PI); cairo_stroke(window->cairo); - cairo_arc(window->cairo, wwidth/2, wheight/2, ARC_RADIUS + ARC_THICKNESS/2, 0, 2*M_PI); + cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius + config->thickness/2, 0, 2*M_PI); cairo_stroke(window->cairo); } window_render(window); diff --git a/swaylock/swaylock.1.txt b/swaylock/swaylock.1.txt index 0e503f29..2a6fa372 100644 --- a/swaylock/swaylock.1.txt +++ b/swaylock/swaylock.1.txt @@ -95,10 +95,18 @@ Appearance *--textcolor* <rrggbb[aa]>:: Sets the color of the text inside the indicator. +*--indicator-radius* <radius>:: + Sets the radius of the indicator to _radius_ pixels. The default value is + 50. + +*--indicator-thickness* <thickness>:: + Sets the thickness of the indicator to _thickness_ pixels. The default value + is 10. + Authors ------- Maintained by Drew DeVault <[email protected]>, who is assisted by other open source contributors. For more information about sway development, see -<https://github.com/SirCmpwn/sway>. +<https://github.com/swaywm/sway>. diff --git a/swaymsg/swaymsg.1.txt b/swaymsg/swaymsg.1.txt index 6fd08e81..27813588 100644 --- a/swaymsg/swaymsg.1.txt +++ b/swaymsg/swaymsg.1.txt @@ -76,7 +76,7 @@ Authors Maintained by Drew DeVault <[email protected]>, who is assisted by other open source contributors. For more information about sway development, see -<https://github.com/SirCmpwn/sway>. +<https://github.com/swaywm/sway>. See Also -------- diff --git a/wayland/registry.c b/wayland/registry.c index 2df605a8..bbb43ad9 100644 --- a/wayland/registry.c +++ b/wayland/registry.c @@ -19,7 +19,7 @@ static void display_handle_mode(void *data, struct wl_output *wl_output, state->flags = flags; state->width = width; state->height = height; - sway_log(L_DEBUG, "Got mode %dx%x:0x%X for output %p", + sway_log(L_DEBUG, "Got mode %dx%d:0x%X for output %p", width, height, flags, data); } } |