aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt7
-rw-r--r--CONTRIBUTING.md4
-rw-r--r--README.de.md101
-rw-r--r--README.el.md91
-rw-r--r--README.fr.md100
-rw-r--r--README.it.md98
-rw-r--r--README.ja.md90
-rw-r--r--README.md38
-rw-r--r--README.pt.md105
-rw-r--r--README.ru.md94
-rw-r--r--README.uk.md105
-rw-r--r--include/sway/input_state.h2
-rw-r--r--include/swaybar/bar.h1
-rw-r--r--include/swaybar/status_line.h10
-rw-r--r--include/swaybar/tray/sni.h1
-rw-r--r--include/swaylock/swaylock.h3
-rw-r--r--security.d/10-freebsd.in19
-rw-r--r--sway/CMakeLists.txt4
-rw-r--r--sway/commands.c6
-rw-r--r--sway/commands/bind.c5
-rw-r--r--sway/commands/move.c24
-rw-r--r--sway/commands/output.c74
-rw-r--r--sway/commands/set.c2
-rw-r--r--sway/config.c7
-rw-r--r--sway/container.c12
-rw-r--r--sway/criteria.c58
-rw-r--r--sway/handlers.c104
-rw-r--r--sway/input_state.c33
-rw-r--r--sway/ipc-json.c94
-rw-r--r--sway/ipc-server.c108
-rw-r--r--sway/main.c41
-rw-r--r--sway/sway-security.7.txt2
-rw-r--r--sway/sway.1.txt2
-rw-r--r--sway/workspace.c2
-rw-r--r--swaybar/CMakeLists.txt2
-rw-r--r--swaybar/bar.c71
-rw-r--r--swaybar/event_loop.c5
-rw-r--r--swaybar/render.c3
-rw-r--r--swaybar/status_line.c81
-rw-r--r--swaybar/tray/dbus.c8
-rw-r--r--swaybar/tray/icon.c2
-rw-r--r--swaybar/tray/sni.c10
-rw-r--r--swaybar/tray/sni_watcher.c14
-rw-r--r--swaybar/tray/tray.c17
-rw-r--r--swaygrab/main.c38
-rw-r--r--swaygrab/swaygrab.1.txt2
-rw-r--r--swaylock/main.c135
-rw-r--r--swaylock/swaylock.1.txt10
-rw-r--r--swaymsg/swaymsg.1.txt2
-rw-r--r--wayland/registry.c2
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")
12set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-parameter") 12set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-parameter")
13set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-result") 13set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-result")
14set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") 14set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
15if (CMAKE_COMPILER_IS_GNUCC)
16 if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 7.0)
17 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wimplicit-fallthrough=0")
18 endif()
19endif()
20 15
21list(INSERT CMAKE_MODULE_PATH 0 16list(INSERT CMAKE_MODULE_PATH 0
22 ${CMAKE_CURRENT_SOURCE_DIR}/CMake 17 ${CMAKE_CURRENT_SOURCE_DIR}/CMake
@@ -95,7 +90,7 @@ endif()
95 90
96if (enable-tray) 91if (enable-tray)
97 if (DBUS_FOUND) 92 if (DBUS_FOUND)
98 set(ENABLE_TRAY) 93 set(ENABLE_TRAY TRUE)
99 add_definitions(-DENABLE_TRAY) 94 add_definitions(-DENABLE_TRAY)
100 else() 95 else()
101 message(WARNING "Tray required but DBus was not found. Tray will not be included") 96 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 @@
2 2
3Contributing just involves sending a pull request. You will probably be more 3Contributing just involves sending a pull request. You will probably be more
4successful with your contribution if you visit the [IRC 4successful with your contribution if you visit the [IRC
5channel](http://webchat.freenode.net/?channels=sway&uio=d4) upfront and discuss 5channel](http://webchat.freenode.net/?channels=sway-devel&uio=d4) upfront and discuss
6your plans. 6your plans.
7 7
8## Release Cycle 8## Release Cycle
@@ -34,7 +34,7 @@ upstream. Try this:
34 34
351. Fork sway 351. Fork sway
362. Clone your fork 362. Clone your fork
373. git remote add upstream git://github.com/SirCmpwn/sway.git 373. git remote add upstream git://github.com/swaywm/sway.git
38 38
39You only need to do this once. You're never going to use your fork's master 39You only need to do this once. You're never going to use your fork's master
40branch. Instead, when you start working on a feature, do this: 40branch. 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 @@
1# sway [![](https://api.travis-ci.org/swaywm/sway.svg)](https://travis-ci.org/swaywm/sway) [![Mit fosspay spenden](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4)
2
3Der Fortschritt dieser Übersetzung kann [hier](https://github.com/swaywm/sway/issues/1318)
4eingesehen werden.
5
6"**S**irCmpwn's **Way**land compositor" ist ein i3-kompatibler
7[Wayland](http://wayland.freedesktop.org/)-Kompositor. Lies die
8[FAQ](https://github.com/swaywm/sway/wiki#faq). Tritt dem
9[IRC-Channel](http://webchat.freenode.net/?channels=sway&uio=d4) bei (#sway in irc.freenode.net).
10
11[![](https://sr.ht/ICd5.png)](https://sr.ht/ICd5.png)
12
13Falls du die Sway Entwicklung unterstützen möchtest, kannst du das auf der
14[Patreonseite](https://patreon.com/sircmpwn) tun, oder indem du zu
15[Entwicklungsprämien](https://github.com/swaywm/sway/issues/986)
16bestimmter Features beiträgst. Jeder ist dazu eingeladen, eine Prämie in Anspruch
17zu nehmen oder für gewünschte Features bereitzustellen. Patreon ist eher dafür
18gedacht, Sways Wartung und das Projekt generell zu unterstützen.
19
20## Deutscher Support
21
22refacto(UTC+2) bietet Support im IRC (unter dem Namen azarus) und auf Github an.
23ParadoxSpiral(UTC+2) bietet Support im IRC und auf Github an.
24
25## Releasesignaturen
26
27Neue Versionen werden mit
28[B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A)
29signiert und [auf Github](https://github.com/swaywm/sway/releases) veröffentlicht.
30
31## Status
32
33- [i3-Features](https://github.com/swaywm/sway/issues/2)
34- [IPC-Features](https://github.com/swaywm/sway/issues/98)
35- [i3bar-Features](https://github.com/swaywm/sway/issues/343)
36- [i3-gaps-Features](https://github.com/swaywm/sway/issues/307)
37- [Sicherheitsfeatures](https://github.com/swaywm/sway/issues/984)
38
39## Installation
40
41### Als Paket
42
43Sway ist in vielen Distributionen verfügbar: versuche einfach, das "sway"-Paket
44zu installieren. Falls es nicht vorhanden ist, schau dir
45[diese Wikiseite](https://github.com/swaywm/sway/wiki/Unsupported-packages) für
46distributionsspezifische Installationsinformationen an.
47
48Wenn du Interesse hast, Sway für deine Distribution als Paket bereitzustellen,
49schau im IRC-Channel vorbei oder schreibe eine e-Mail an sir@cmpwn.com (nur englischsprachig).
50
51### Kompilieren des Quellcodes
52
53Abhängigkeiten:
54
55* cmake
56* [wlc](https://github.com/Cloudef/wlc)
57* wayland
58* xwayland
59* libinput >= 1.6.0
60* libcap
61* asciidoc
62* pcre
63* json-c
64* pango
65* cairo
66* gdk-pixbuf2 *
67* pam **
68* imagemagick (erforderlich für Bildaufnahme mit swaygrab)
69* ffmpeg (erforderlich für Videoaufnahme swaygrab)
70
71_\*Nur erforderlich für swaybar, swaybg, und swaylock_
72
73_\*\*Nur erforderlich für swaylock_
74
75Führe diese Befehle aus:
76
77 mkdir build
78 cd build
79 cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc ..
80 make
81 sudo make install
82
83In Systemen mit logind musst du `sway` einige Capabilities geben:
84
85 sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/bin/sway
86
87In Systemen ohne logind musst du `sway` das suid-Flag geben:
88
89 sudo chmod a+s /usr/local/bin/sway
90
91## Konfiguration
92
93Wenn du schon i3 benutzt, kopiere einfach deine i3 Konfiguration nach
94`~/.config/sway/config`. Falls nicht, kannst du die Beispielkonfiguration
95benutzen. Die befindet sich normalerweise unter `/etc/sway/config`.
96Um mehr Informationen über die Konfiguration zu erhalten, führe `man 5 sway` aus.
97
98## Verwendung
99
100Führe `sway` von einem TTY aus. Manche Displaymanager könnten funktionieren, werden aber
101nicht 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 @@
1# sway [![](https://api.travis-ci.org/swaywm/sway.svg)](https://travis-ci.org/swaywm/sway) [![Donate with fosspay](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4)
2
3"Ο Sway (**S**irCmpwn's **Way**land) είναι ένας **υπό ανάπτυξη** [Wayland](http://wayland.freedesktop.org/) διαχειριστής παραθύρων συμβατός με τον αντίστοιχο διαχειριστή παραθύρων i3 για τον X11.
4Διαβάστε τις [Συνήθεις Ερωτήσεις](https://github.com/swaywm/sway/wiki). Συνδεθείτε στο [κανάλι μας στο IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway στο
5irc.freenode.net).
6
7[![](https://sr.ht/ICd5.png)](https://sr.ht/ICd5.png)
8
9
10### Η ελληνική μετάφραση ενδέχεται να είναι ελλειπής!
11
12Η τεκμηρίωση του Sway ξεκινάει πάντα από τα Αγγλικά και στη συνέχεια μεταφράζεται, γι' αυτό ενδέχεται τα ελληνικά κείμενα να μην είναι πάντα διαθέσιμα ή ενημερωμένα.
13Μπορείτε πάντα να υποδεικνύετε σφάλματα και να κάνετε ερωτήσεις σχετικά με τις ελληνικές μεταφράσεις στο [IRC](http://webchat.freenode.net/?channels=sway&uio=d4).
14To username μου στο Freenode είναι kon14 και θα με βρείτε στο IRC σε ώρες GMT+2.
15Δείτε [εδώ](https://github.com/swaywm/sway/issues/1318) πως μπορείτε και οι ίδιοι να βοηθήσετε στη μετάφραση του Sway.
16
17Αν θέλετε να υποστηρίξετε την ανάπτυξη του Sway, μπορείτε να συμβάλετε στη [σελίδα Patreon του SirCmpwn](https://patreon.com/sircmpwn)
18ή να επιδοτήσετε τις [αμοιβές](https://github.com/swaywm/sway/issues/986) για υλοποίηση συγκεκριμένων δυνατοτήτων.
19Ο καθένας μπορεί να διεκδικήσει μια αμοιβή και μπορείτε να προσθέσετε μια αμοιβή για οποιαδήποτε δυνατότητα θέλετε.
20Προτιμήστε το Patreon αν θέλετε να υποστήριξετε την συνολική ανάπτυξη και διατήρηση του Sway.
21
22## Υπογραφές Έκδοσης
23
24Οι εκδόσεις υπογράφονται ως [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) και δημοσιεύονται στο [GitHub](https://github.com/swaywm/sway/releases).
25
26## Κατάσταση
27
28- [Υποστήριξη δυνατοτήτων του i3](https://github.com/swaywm/sway/issues/2)
29- [Υποστήριξη δυνατοτήτων IPC](https://github.com/swaywm/sway/issues/98)
30- [Υποστήριξη δυνατοτήτων i3bar](https://github.com/swaywm/sway/issues/343)
31- [Υποστήριξη δυνατοτήτων i3-gaps](https://github.com/swaywm/sway/issues/307)
32- [Δυνατότητες Ασφαλείας](https://github.com/swaywm/sway/issues/984)
33
34## Εγκατάσταση
35
36### Από Πακέτα
37
38Ο Sway είναι διαθέσιμος για εγκατάσταση μέσω του διαχειριστή πακέτων σε διάφορες διανομές.
39Δοκιμάστε να εγκαταστήσετε το πακέτο ονομαζόμενο ως "sway" για τη δική σας.
40Αν δεν είναι διαθέσιμο, μεταβείτε στη [σελίδα τεκμηρίωσης](https://github.com/swaywm/sway/wiki/Unsupported-packages) για πληροφορίες σχετικά με την εγκατάσταση για τη διανομή σας.
41
42Αν ενδιαφέρεστε να δημιουργήσετε ένα πακέτο του Sway για τη διανομή σας, περάστε απο το κανάλι μας στο IRC ή στείλτε ένα email, στα **Αγγλικά**, στο sir@cmpwn.com για συμβουλές.
43
44### Compile από Πηγαίο Κώδικα
45
46Εγκατάσταση εξαρτήσεων:
47
48* cmake
49* [wlc](https://github.com/Cloudef/wlc)
50* wayland
51* xwayland
52* libinput >= 1.6.0
53* libcap
54* asciidoc
55* pcre
56* json-c
57* pango
58* cairo
59* gdk-pixbuf2 *
60* pam **
61* imagemagick (αναγκαίο για καταγραφή εικόνας μέσω του swaygrab)
62* ffmpeg (αναγκαίο για καταγραφή video μέσω του swaygrab)
63
64_\*Απαιτείται μόνο για swaybar, swaybg, and swaylock_
65
66_\*\*Απαιτείται μόνο για swaylock_
67
68Εκτελέστε αυτές τις εντολές:
69
70 mkdir build
71 cd build
72 cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc ..
73 make
74 sudo make install
75
76Σε συστήματα με logind, χρειάζεται να ορίσετε μερικά δικαιώματα caps στο εκτελέσιμο αρχείο:
77
78 sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/bin/sway
79
80Σε συστήματα χωρίς logind, χρειάζεται να θέσετε το suid bit στο εκτελέσιμο αρχείο:
81
82 sudo chmod a+s /usr/local/bin/sway
83
84## Παραμετροποίηση
85
86Αν είστε ήδη χρήστης του i3, τότε απλά αντιγράψτε το αρχείο ρυθμίσεων σας στο `~/.config/sway/config` και θα είναι όλα έτοιμα για χρήση.
87Διαφορετικά, αντιγράψτε το συνοδευόμενο δείγμα ρυθμίσεων, το οποίο θα βρείτε τυπικά στο `/etc/sway/config`, και μεταφέρετε το στην τοποθεσία `~/.config/sway/config`. Εκτελέστε `man 5 sway` για πληροφορίες σχετικά με την παραμετροποίηση των ρυθμίσεων σας.
88
89## Εκτέλεση
90
91Εκτελέστε `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 @@
1# sway [![](https://api.travis-ci.org/swaywm/sway.svg)](https://travis-ci.org/swaywm/sway) [![Donate with fosspay](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4)
2
3"**S**irCmpwn's **Way**land compositor" est un compositeur [Wayland](http://wayland.freedesktop.org/)
4compatible avec i3, **en cours de développement**.
5Lisez la [FAQ](https://github.com/swaywm/sway/wiki). Rejoignez le
6[canal IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway sur
7irc.freenode.net).
8
9[![](https://sr.ht/ICd5.png)](https://sr.ht/ICd5.png)
10
11Si vous souhaitez soutenir le développement de Sway, vous pouvez contribuer à [ma page
12Patreon](https://patreon.com/sircmpwn) ou aux [primes](https://github.com/swaywm/sway/issues/986)
13pour des fonctionnalités spécifiques.
14Tout le monde est invité à réclamer une prime et vous pouvez donner une prime pour n'importe quelle
15fonctionnalité souhaitée. Patreon est plus utile pour supporter l'état général et la
16maintenance de Sway.
17
18## Aide en français
19
20[abdelq](//github.com/abdelq) fournit du support en français sur IRC et Github, dans le fuseau horaire UTC-4 (EST).
21
22## Signatures de nouvelles versions
23
24Les nouvelles versions sont signées avec [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A)
25et publiées [sur GitHub](https://github.com/swaywm/sway/releases).
26
27## Statut
28
29- [support des fonctionnalités d'i3](https://github.com/swaywm/sway/issues/2)
30- [support des fonctionnalités d'IPC](https://github.com/swaywm/sway/issues/98)
31- [support des fonctionnalités d'i3bar](https://github.com/swaywm/sway/issues/343)
32- [support des fonctionnalités d'i3-gaps](https://github.com/swaywm/sway/issues/307)
33- [fonctionnalités de sécurité](https://github.com/swaywm/sway/issues/984)
34
35## Installation
36
37### À partir de paquets
38
39Sway est disponible sur plusieurs distributions. Essayez d'installer le paquet "sway" pour
40la vôtre. Si ce n'est pas disponible, consultez [cette page wiki](https://github.com/swaywm/sway/wiki/Unsupported-packages)
41pour de l'information sur l'installation pour vos distributions.
42
43Si vous êtes intéressé à maintenir Sway pour votre distribution, passez par le canal
44IRC ou envoyez un e-mail à sir@cmpwn.com (en anglais seulement) pour des conseils.
45
46### Compilation depuis la source
47
48Installez les dépendances :
49
50* cmake
51* [wlc](https://github.com/Cloudef/wlc)
52* wayland
53* xwayland
54* libinput >= 1.6.0
55* libcap
56* asciidoc
57* pcre
58* json-c
59* pango
60* cairo
61* gdk-pixbuf2 *
62* pam **
63* imagemagick (requis pour la capture d'image avec swaygrab)
64* ffmpeg (requis pour la capture vidéo avec swaygrab)
65
66_\*Uniquement requis pour swaybar, swaybg, and swaylock_
67
68_\*\*Uniquement requis pour swaylock_
69
70Exécutez ces commandes :
71
72 mkdir build
73 cd build
74 cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc ..
75 make
76 sudo make install
77
78Sur les systèmes avec logind, vous devez définir quelques caps sur le binaire :
79
80 sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/bin/sway
81
82Sur les systèmes sans logind, vous devez suid le binaire de sway :
83
84 sudo chmod a+s /usr/local/bin/sway
85
86## Configuration
87
88Si vous utilisez déjà i3, copiez votre configuration i3 à `~/.config/sway/config` et
89cela va fonctionner. Sinon, copiez l'exemple de fichier de configuration à
90`~/.config/sway/config`. Il se trouve généralement dans `/etc/sway/config`.
91Exécutez `man 5 sway` pour l'information sur la configuration.
92
93Mes propres dotfiles sont disponibles [ici](https://git.sr.ht/~sircmpwn/dotfiles) si
94vous voulez un peu d'inspiration. Je vous recommande aussi de consulter le
95[wiki](https://github.com/swaywm/sway/wiki).
96
97## Exécution
98
99Exécutez `sway` à partir d'un TTY. Certains gestionnaires d'affichage peuvent fonctionner,
100mais 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 @@
1# sway [![](https://api.travis-ci.org/swaywm/sway.svg)](https://travis-ci.org/swaywm/sway) [![Donate with fosspay](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4)
2
3"**S**irCmpwn's **Way**land compositor" è un compositor
4[Wayland](http://wayland.freedesktop.org/) **in via di sviluppo**
5compatibile con i3.
6Leggi le [FAQ (in Inglese)](https://github.com/swaywm/sway/wiki). Unisciti al
7[canale IRC (in Inglese)](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on
8irc.freenode.net).
9
10[![](https://sr.ht/ICd5.png)](https://sr.ht/ICd5.png)
11
12Se vuoi supportare lo sviluppo di Sway, puoi contribuire dalla
13[pagina Patreon di SirCmpwn's](https://patreon.com/sircmpwn) o con dei
14[premi](https://github.com/swaywm/sway/issues/986) per finanziare lo sviluppo
15di funzionalità specifiche.
16Chiunque è libero di reclamare un premio o crearne uno per qualsiasi funzionalità.
17Patreon è più utile al supporto e alla manutenzione generale di Sway.
18
19## Supporto italiano
20syknro offre supporto in Italiano su GitHub nel fuso orario UTC+2.
21Questa traduzione non è ancora completa. [Clicca qui per maggiori informazioni](https://github.com/swaywm/sway/issues/1318)
22
23## Firme digitali
24
25Le release sono firmate con [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A)
26e pubblicate [su GitHub](https://github.com/swaywm/sway/releases).
27
28## Status
29
30- [supporto funzionalità i3](https://github.com/swaywm/sway/issues/2)
31- [supporto funzionalità IPC](https://github.com/swaywm/sway/issues/98)
32- [supporto funzionalità i3bar](https://github.com/swaywm/sway/issues/343)
33- [supporto funzionalità i3-gaps](https://github.com/swaywm/sway/issues/307)
34- [sicurezza](https://github.com/swaywm/sway/issues/984)
35
36## Installazione
37
38### Dai pacchetti
39
40Sway è disponibile in molte distribuzioni. Prova a installare il pacchetto "sway" per la tua.
41Se non funziona, controlla [questa pagina (in Inglese)](https://github.com/swaywm/sway/wiki/Unsupported-packages)
42per informazioni sull'installazione per le tue distribuzioni.
43
44Se vuoi creare un pacchetto per la tua distribuzione, passa dall'IRC o manda un email (in Inglese)
45a sir@cmpwn.com.
46
47### Compilando il codice sorgente
48
49Installa queste dipendenze:
50
51* cmake
52* [wlc](https://github.com/Cloudef/wlc)
53* wayland
54* xwayland
55* libinput >= 1.6.0
56* libcap
57* asciidoc
58* pcre
59* json-c
60* pango
61* cairo
62* gdk-pixbuf2 *
63* pam **
64* imagemagick (richiesto per catturare immagini con swaygrab)
65* ffmpeg (rrichiesto per catturare video con swaygrab)
66
67_\*Richiesto solo per swaybar, swaybg, e swaylock_
68
69_\*\*Richiesto solo per swaylock_
70
71Esegui questi comandi:
72
73 mkdir build
74 cd build
75 cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc ..
76 make
77 sudo make install
78
79Per i sistemi con logind, devi impostare un paio di caps sull'eseguibile:
80
81 sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/bin/sway
82
83Per i sistemi senza logind, devi cambiare i permessi (suid):
84
85 sudo chmod a+s /usr/local/bin/sway
86
87## Configurazione
88
89Se usi i3, copia la tua configurazione in `~/.config/sway/config` e
90funzionerà direttamente.
91Altrimenti copia in `~/.config/sway/config` la configurazione di esempio,
92solitamente si trova in `/etc/sway/config`.
93Esegui `man 5 sway` per informazioni sulla configurazione.
94
95## Esecuzione
96
97Esegui `sway` da un TTY. Qualche display manager potrebbe funzionare ma non sono
98ufficialmente 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 @@
1# sway [![](https://api.travis-ci.org/swaywm/sway.svg)](https://travis-ci.org/swaywm/sway) [![Donate with fosspay](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4)
2
3"**S**irCmpwn's **Way**land compositor"は**開発中**の
4i3互換な[Wayland](http://wayland.freedesktop.org/)コンポジタです。
5[FAQ](https://github.com/swaywm/sway/wiki)も合わせてご覧ください。
6[IRC チャンネル](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on
7irc.freenode.net)もあります。
8
9[![](https://sr.ht/ICd5.png)](https://sr.ht/ICd5.png)
10
11もしSwayの開発を支援したい場合は[SirCmpwnのPatreon](https://patreon.com/sircmpwn)や
12[こちら](https://github.com/swaywm/sway/issues/986)をご覧ください。
13
14誰でも賞金を受け取る事ができますし、自分の欲しい機能に賞金を掛ける事が出来ます。
15PatreonはSwayの開発を支援するのにもっとも便利です。
16
17## リリース
18
19Swayのリリースは[B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A)で書名されて
20[GitHub](https://github.com/swaywm/sway/releases)で公開されています。
21
22## 開発状況
23
24- [i3のサポート](https://github.com/swaywm/sway/issues/2)
25- [IPCのサポート](https://github.com/swaywm/sway/issues/98)
26- [i3barのサポート](https://github.com/swaywm/sway/issues/343)
27- [i3-gapsのサポート](https://github.com/swaywm/sway/issues/307)
28- [セキュリティ対応](https://github.com/swaywm/sway/issues/984)
29
30## インストール
31
32### パッケージから
33
34Swayは沢山のディストリビューションで提供されています。"sway"パッケージをインストールしてみてください。
35もし、パッケージが存在しないならば、[このページ](https://github.com/swaywm/sway/wiki/Unsupported-packages)
36を参照してインストールしてみてください。
37
38もし、Swayのパッケージを提供したいならば、SwayのIRCチャンネルか"sir@cmpwn.com"に連絡してください。
39
40### ソースコードから
41
42まずはコンパイルや実行に必要なソフトウェアやライブラリをインストールしてください。:
43
44* cmake
45* [wlc](https://github.com/Cloudef/wlc)
46* wayland
47* xwayland
48* libinput >= 1.6.0
49* libcap
50* asciidoc
51* pcre
52* json-c
53* pango
54* cairo
55* gdk-pixbuf2 *
56* pam **
57* imagemagick (swaygrabでスクリーンショットを撮るのに必要です)
58* ffmpeg (swaygrabで画面を録画するのに必要です)
59
60_\*swaybar,swaybg,swaylockが使用します_
61
62_\*\*swaylockが使用します_
63
64ターミナルで次のコマンドを実行してください:
65
66 mkdir build
67 cd build
68 cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc ..
69 make
70 sudo make install
71
72logindを使用している場合はバイナリにcapを設定してください:
73
74 sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/bin/sway
75
76logindを使用していない場合はバイナリにsuidを設定してください:
77
78 sudo chmod a+s /usr/local/bin/sway
79
80## 設定
81
82もし、既にi3を使用しているなら、i3のコンフィグファイルを`~/.config/sway/config`にコピーすれば動きます。
83そうでないならば、サンプルのコンフィグファイルを`~/.config/sway/config`にコピーしてください。
84サンプルのコンフィグファイルは基本的には`/etc/sway/config`にあります。
85`man 5 sway`で各種設定について確認できます。
86
87## 実行
88
89`sway`をTTYから実行してください。いくつかのDesktopManagerはSwayからサポートされていませんが、動く場合もあります(gdmは特にSwayと相性が良いそうです)。
90
diff --git a/README.md b/README.md
index 65a943d3..e1bf9590 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,19 @@
1# sway [![](https://api.travis-ci.org/SirCmpwn/sway.svg)](https://travis-ci.org/SirCmpwn/sway) [![Donate with fosspay](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4) 1# sway [![](https://api.travis-ci.org/swaywm/sway.svg)](https://travis-ci.org/swaywm/sway) [![Donate with fosspay](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4)
2
3[**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--) -
4[Русский](https://github.com/swaywm/sway/blob/master/README.ru.md#sway--)
2 5
3"**S**irCmpwn's **Way**land compositor" is a **work in progress** 6"**S**irCmpwn's **Way**land compositor" is a **work in progress**
4i3-compatible [Wayland](http://wayland.freedesktop.org/) compositor. 7i3-compatible [Wayland](http://wayland.freedesktop.org/) compositor.
5Read the [FAQ](https://github.com/SirCmpwn/sway/wiki). Join the 8Read the [FAQ](https://github.com/swaywm/sway/wiki). Join the
6[IRC channel](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on 9[IRC channel](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on
7irc.freenode.net). 10irc.freenode.net).
8 11
9[![](https://sr.ht/ICd5.png)](https://sr.ht/ICd5.png) 12[![](https://sr.ht/ICd5.png)](https://sr.ht/ICd5.png)
10 13
11If you'd like to support Sway development, you can contribute to [my Patreon 14If you'd like to support Sway development, you can contribute to [SirCmpwn's
12page](https://patreon.com/sircmpwn) or you can contribute to 15Patreon page](https://patreon.com/sircmpwn) or you can contribute to
13[bounties](https://github.com/SirCmpwn/sway/issues/986) for specific features. 16[bounties](https://github.com/swaywm/sway/issues/986) for specific features.
14Anyone is welcome to claim a bounty and you can make a bounty for any feature 17Anyone is welcome to claim a bounty and you can make a bounty for any feature
15you wish, and Patreon is more useful for supporting the overall health and 18you wish, and Patreon is more useful for supporting the overall health and
16maintenance of Sway. 19maintenance of Sway.
@@ -18,22 +21,22 @@ maintenance of Sway.
18## Release Signatures 21## Release Signatures
19 22
20Releases are signed with [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) 23Releases are signed with [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A)
21and published [on GitHub](https://github.com/SirCmpwn/sway/releases). 24and published [on GitHub](https://github.com/swaywm/sway/releases).
22 25
23## Status 26## Status
24 27
25- [i3 feature support](https://github.com/SirCmpwn/sway/issues/2) 28- [i3 feature support](https://github.com/swaywm/sway/issues/2)
26- [IPC feature support](https://github.com/SirCmpwn/sway/issues/98) 29- [IPC feature support](https://github.com/swaywm/sway/issues/98)
27- [i3bar feature support](https://github.com/SirCmpwn/sway/issues/343) 30- [i3bar feature support](https://github.com/swaywm/sway/issues/343)
28- [i3-gaps feature support](https://github.com/SirCmpwn/sway/issues/307) 31- [i3-gaps feature support](https://github.com/swaywm/sway/issues/307)
29- [security features](https://github.com/SirCmpwn/sway/issues/984) 32- [security features](https://github.com/swaywm/sway/issues/984)
30 33
31## Installation 34## Installation
32 35
33### From Packages 36### From Packages
34 37
35Sway is available in many distributions. Try installing the "sway" package for 38Sway is available in many distributions. Try installing the "sway" package for
36yours. If it's not available, check out [this wiki page](https://github.com/SirCmpwn/sway/wiki/Unsupported-packages) 39yours. If it's not available, check out [this wiki page](https://github.com/swaywm/sway/wiki/Unsupported-packages)
37for information on installation for your distributions. 40for information on installation for your distributions.
38 41
39If you're interested in packaging Sway for your distribution, stop by the IRC 42If you're interested in packaging Sway for your distribution, stop by the IRC
@@ -73,8 +76,7 @@ Run these commands:
73 76
74On systems with logind, you need to set a few caps on the binary: 77On systems with logind, you need to set a few caps on the binary:
75 78
76 sudo setcap cap_sys_ptrace=eip /usr/local/bin/sway 79 sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/bin/sway
77 sudo setcap cap_sys_tty_config=eip /usr/local/bin/sway
78 80
79On systems without logind, you need to suid the sway binary: 81On systems without logind, you need to suid the sway binary:
80 82
@@ -87,11 +89,7 @@ it'll work out of the box. Otherwise, copy the sample configuration file to
87`~/.config/sway/config`. It is usually located at `/etc/sway/config`. 89`~/.config/sway/config`. It is usually located at `/etc/sway/config`.
88Run `man 5 sway` for information on the configuration. 90Run `man 5 sway` for information on the configuration.
89 91
90My own dotfiles are available [here](https://git.sr.ht/~sircmpwn/dotfiles) if
91you want some inspiration, and definitely check out the
92[wiki](https://github.com/SirCmpwn/sway/wiki) as well.
93
94## Running 92## Running
95 93
96Instead of running `startx`, run `sway`. You can run `sway` from within X as 94Run `sway` from a TTY. Some display managers may work but are not supported by
97well, which is useful for testing. 95Sway (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 @@
1# sway [![](https://api.travis-ci.org/swaywm/sway.svg)](https://travis-ci.org/swaywm/sway) [![Doe através do fosspay](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4)
2
3"**S**irCmpwn's **Way**land compositor" é um compositor [Wayland](http://wayland.freedesktop.org/)
4compatível com o i3. Leia o [FAQ](https://github.com/swaywm/sway/wiki). Participe do
5[canal IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway no
6irc.freenode.net).
7
8[![](https://sr.ht/ICd5.png)](https://sr.ht/ICd5.png)
9
10Se você deseja apoiar o desenvolvimento do Sway, você pode contribuir com o
11SirCmpwn em sua [página no Patreon](https://patreon.com/sircmpwn) ou você
12pode colaborar com [premiações](https://github.com/swaywm/sway/issues/986)
13para recursos específicos. Qualquer um pode requerer uma premiação ao implementar
14o recurso especificado, e você pode criar uma premiação para qualquer recurso que desejar.
15O Patreon é melhor direcionado para a manutenção a longo prazo do Sway.
16
17## Ajuda em português
18
19No momento, o suporte em português no canal do IRC **não está ativo**. Em caso de problemas,
20use as [*issues*](https://github.com/swaywm/sway/issues/) do Github (*em inglês*).
21
22A tradução para português é um *trabalho em progresso*, no momento. Caso encontre algum erro
23ou queira colaborar com a tradução, visite
24[essa *issue*](https://github.com/swaywm/sway/issues/1318) para mais informações e não
25exite em enviar quaisquer correções necessárias.
26
27## Assinaturas dos *Releases*
28
29*Releases* são assinadas com a chave
30[B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A)
31e publicadas [no GitHub](https://github.com/swaywm/sway/releases).
32
33## Status
34
35- [Suporte aos recursos do i3](https://github.com/swaywm/sway/issues/2)
36- [Suporte aos recursos IPC](https://github.com/swaywm/sway/issues/98)
37- [Suporte aos recursos do i3bar](https://github.com/swaywm/sway/issues/343)
38- [Suporte aos recursos do i3-gaps](https://github.com/swaywm/sway/issues/307)
39- [Recursos de segurança](https://github.com/swaywm/sway/issues/984)
40
41## Instalação
42
43### A partir de pacotes
44
45Sway está disponível em várias distribuições. Verifique se o pacote "sway" está
46disponível a partir do gerenciador de pacotes da sua distribuição. Caso não esteja,
47procure por informações sobre como instalar o Sway na sua distribuição
48[aqui](https://github.com/swaywm/sway/wiki/Unsupported-packages).
49
50Se você está interessado em manter um pacote do Sway para a sua distribuição,
51visite o canal no IRC ou mande um email para sir@cmpwn.com (*em inglês*).
52
53### A partir do código-fonte
54
55Antes de iniciar a compilação, instale as dependências:
56
57* cmake
58* [wlc](https://github.com/Cloudef/wlc)
59* wayland
60* xwayland
61* libinput >= 1.6.0
62* libcap
63* asciidoc
64* pcre
65* json-c
66* pango
67* cairo
68* gdk-pixbuf2 *
69* pam **
70* imagemagick (capturar imagem com o swaygrab)
71* ffmpeg (capturar vídeo com o swaygrab)
72
73_\*Dependência apenas de swaybar, swaybg, e swaylock_
74
75_\*\*Dependência apenas de swaylock_
76
77Para compilar, execute estes comandos:
78
79 mkdir build
80 cd build
81 cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc ..
82 make
83 sudo make install
84
85Em sistemas com logind, configure as seguintes capacidades para o arquivo binário:
86
87 sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/bin/sway
88
89Em sistemas sem logind, ative a *flag* de *suid* do arquivo binário:
90
91 sudo chmod a+s /usr/local/bin/sway
92
93## Configuração
94
95Se você já usa o i3, copie o arquivo de configuração do i3 para `~/.config/sway/config`;
96o Sway lerá o arquivo normalmente. Senão, copie o arquivo de configuração de exemplo
97para `~/.config/sway/config`. É comum esse arquivo estar localizado em
98`/etc/sway/config`. Veja `man 5 sway` para informações sobre configuração.
99
100## Executando
101
102Execute `sway` a partir de um terminal do Linux. Alguns gerenciadores de *display*
103podem funcionar, porém o Sway não procura manter compatibilidade com esses (segundo
104relatos, o gdm funciona bem com o Sway).
105
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 @@
1# sway [![](https://api.travis-ci.org/swaywm/sway.svg)](https://travis-ci.org/swaywm/sway) [![Пожертвовать через fosspay](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4)
2
3"**S**irCmpwn's **Way**land compositor" на данный момент **(в разработке)**
4i3-совместимый [Wayland](http://wayland.freedesktop.org/) композитор.
5Прочитайте [FAQ](https://github.com/swaywm/sway/wiki). Присоединяйтесь к
6[IRC каналу](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway на
7irc.freenode.net).
8
9[![](https://sr.ht/ICd5.png)](https://sr.ht/ICd5.png)
10
11При желании поддержать разработку Sway вы можете пожертвовать [автору
12на его Patreon странице](https://patreon.com/sircmpwn) или взяться
13за разработку определённых целей в обмен на [награду](https://github.com/swaywm/sway/issues/986).
14
15Вы также можете объявить свою награду за определённую цель и больше всего для этого подходит Patreon.
16
17## Помощь
18
19DarkReef оказывает поддержку на русском языке в IRC канале и на GitHub в часовом поясе UTC +05:00.
20Если у вас есть желанием помочь с переводом на русский языке, то, пожалуйста, ознакомьтесь с [подсказками для переводчиков](https://github.com/swaywm/sway/issues/1318). На этой же странице можно узнать [статус перевода](https://github.com/swaywm/sway/issues/1318#issuecomment-326913020).
21
22## Подпись версий
23
24Версии подписаны ключом [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A)
25и опубликованы [на GitHub'е](https://github.com/swaywm/sway/releases).
26
27## Статус
28
29- [Поддержка i3](https://github.com/swaywm/sway/issues/2)
30- [Поддержка i3-bar](https://github.com/swaywm/sway/issues/343)
31- [Поддержка i3-gaps](https://github.com/swaywm/sway/issues/307)
32- [Поддержка IPC](https://github.com/swaywm/sway/issues/98)
33- [Безопасность](https://github.com/swaywm/sway/issues/984)
34
35## Установка
36
37### Из пакета
38
39Sway доступен во многих дистрибутивах и находится в официальных репозиториях. Попробуйте установить "sway" через ваш пакетный менеджер.
40В случае, если это не представляется возможным, то обратитесь к [этой странице](https://github.com/swaywm/sway/wiki/Unsupported-packages)
41для получения инструкций по установке для вашего дистрибутива.
42
43Если вы заинтересованы в создании пакета "sway" в вашем дистрибутиве, то сообщите об этом в IRC
44канале или отправьте письмо sir@cmpwn.com.
45
46### Сборка из исходников
47
48Установите следующие пакеты:
49
50* cmake
51* [wlc](https://github.com/Cloudef/wlc)
52* wayland
53* xwayland
54* libinput >= 1.6.0
55* libcap
56* asciidoc
57* pcre
58* json-c
59* pango
60* cairo
61* gdk-pixbuf2 *
62* pam **
63* imagemagick (требуется для захвата изображений через swaygrab)
64* ffmpeg (требуется для захвата видео через swaygrab)
65
66_\*Требуется только для swaybar, swaybg и swaylock_
67
68_\*\*Требуется только для swaylock_
69
70Выполните следующие команды:
71
72 mkdir build
73 cd build
74 cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc ..
75 make
76 sudo make install
77
78Если у вас logind:
79
80 sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/bin/sway
81
82Иначе:
83
84 sudo chmod a+s /usr/local/bin/sway
85
86## Настройка
87
88Если вы уже используете i3, тогда просто скопируйте ваш конфиг в `~/.config/sway/config`.
89В любом другом случае, скопируйте `/etc/sway/config` в `~/.config/sway/config`.
90Для более детальной информации о настройке: `man 5 sway`.
91
92## Запуск
93
94Выполните '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 @@
1# sway [![](https://api.travis-ci.org/swaywm/sway.svg)](https://travis-ci.org/swaywm/sway) [![Donate with fosspay](https://drewdevault.com/donate/static/donate-with-fosspay.png)](https://drewdevault.com/donate?project=4)
2
3**Sway** ("**S**irCmpwn's **Way**land compositor") це сумісний з i3 композитор
4[Wayland](http://wayland.freedesktop.org/) (**у стані розробки**).
5Ознайомтесь з [ЧаПами](https://github.com/swaywm/sway/wiki).
6Приєднуйтесь до [спільноти в IRC](http://webchat.freenode.net/?channels=sway&uio=d4)
7(#sway на irc.freenode.net).
8
9[![](https://sr.ht/ICd5.png)](https://sr.ht/ICd5.png)
10
11Якщо ви хочете підтримати розробку Sway, ви можете зробити свій внесок у
12[SirCmpwn'ову сторінку Patreon](https://patreon.com/sircmpwn) або до
13[фонду винагород](https://github.com/swaywm/sway/issues/986) за реалізацію
14певного функціоналу.
15Кожен може виставити винагороду за реалізацію довільної функції
16(і, відповідно, забрати її собі, виконавши це завдання);
17кошти від сторінки Patreon підтримують загальну розробку та підтримку Sway.
18
19## Підтримка українською мовою
20
21Якщо ви хочете отримати підтримку українською мовою, можете звернутись до користувача
22Hummer12007 у IRC-спільноті. Будьте терплячі, вам обов'язково допоможуть.
23
24Наразі переклад Sway українською ще не завершено (він неповний), проте у вас є шанс долучитись,
25детальніше див. [статус](https://github.com/swaywm/sway/issues/1318#issuecomment-322277382).
26
27## Підписи випусків
28
29Випуски підписані ключем [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A)
30та публікуються на сторінці [GitHub](https://github.com/swaywm/sway/releases).
31
32## Стан розробки
33
34- [Підтримка функцій i3](https://github.com/swaywm/sway/issues/2)
35- [Реалізація IPC-протоколу i3](https://github.com/swaywm/sway/issues/98)
36- [Підтримка функцій i3bar](https://github.com/swaywm/sway/issues/343)
37- [Підтримка функцій i3-gaps](https://github.com/swaywm/sway/issues/307)
38- [Функції безпеки](https://github.com/swaywm/sway/issues/984)
39
40## Встановлення
41
42### З пакунків
43
44Sway доступний у багатьох дистрибутивах Linux (а також у FreeBSD).
45Спробуйте встановити пакунок `sway` у вашому.
46Якщо він недоступний, перегляньте цю [сторінку Wiki](https://github.com/swaywm/sway/wiki/Unsupported-packages)
47для інформації щодо встановлення на вашому дистрибутиві.
48
49Якщо ви готові та зацікавлені запакувати і підтримувати Sway у вашому
50дистрибутиві, будемо раді вас бачити у нашому каналі IRC. Ви також можете
51спитати порад за адресою sir@cmpwn.com.
52
53### З вихідного коду
54
55Встановіть залежності:
56
57* cmake
58* [wlc](https://github.com/Cloudef/wlc)
59* wayland
60* xwayland
61* libinput >= 1.6.0
62* libcap
63* asciidoc
64* pcre
65* json-c
66* pango
67* cairo
68* gdk-pixbuf2 *
69* pam **
70* imagemagick (для захоплення зображень за допомогою swaygrab)
71* ffmpeg (для захоплення відео за допомогою swaygrab)
72
73_\*Лише для swaybar, swaybg та swaylock_
74
75_\*\*Лише для swaylock_
76
77Виконайте ці команди:
78
79 mkdir build
80 cd build
81 cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_SYSCONFDIR=/etc ..
82 make
83 sudo make install
84
85На системах **з** logind, варто встановити декілька можливостей (caps)
86на виконуваний файл sway:
87
88 sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/bin/sway
89
90На системах **без** logind, необхідно встановити біт SUID на виконуваний файл sway:
91
92 sudo chmod a+s /usr/local/bin/sway
93
94## Налаштування
95
96Якщо ви вже використовуєте i3, скопіюйте свій файл налаштувань
97до `~/.config/sway/config`, він має запрацювати. Інакше, скопіюйте
98туди файл-зразок (зазвичай знаходиться у `/etc/sway/config`), і налаштуйте під себе.
99
100Більше інформації щодо налаштувань можете знайти, виконавши `man 5 sway`.
101
102## Запуск
103
104Виконайте `sway` у TTY. Деякі дисплейні менеджери (менеджери сеансу/стільниць)
105можуть працювати, але офіційно не підтримуються (проте сумісніть із 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 {
69 MOD_STATE_RELEASED = 2 69 MOD_STATE_RELEASED = 2
70}; 70};
71 71
72void pointer_position_set(struct wlc_origin *new_origin, bool force_focus); 72void pointer_position_set(double new_x, double new_y, bool force_focus);
73void center_pointer_on(swayc_t *view); 73void center_pointer_on(swayc_t *view);
74 74
75// on button release unset mode depending on the button. 75// 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 {
14 int ipc_event_socketfd; 14 int ipc_event_socketfd;
15 int ipc_socketfd; 15 int ipc_socketfd;
16 int status_read_fd; 16 int status_read_fd;
17 int status_write_fd;
17 pid_t status_command_pid; 18 pid_t status_command_pid;
18}; 19};
19 20
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 {
13 list_t *block_line; 13 list_t *block_line;
14 const char *text_line; 14 const char *text_line;
15 command_protocol protocol; 15 command_protocol protocol;
16 bool click_events;
16}; 17};
17 18
18struct status_block { 19struct status_block {
@@ -31,6 +32,10 @@ struct status_block {
31 int border_bottom; 32 int border_bottom;
32 int border_left; 33 int border_left;
33 int border_right; 34 int border_right;
35
36 // Set during rendering
37 int x;
38 int width;
34}; 39};
35 40
36/** 41/**
@@ -44,6 +49,11 @@ struct status_line *init_status_line();
44bool handle_status_line(struct bar *bar); 49bool handle_status_line(struct bar *bar);
45 50
46/** 51/**
52 * Handle mouse clicks.
53 */
54bool status_line_mouse_event(struct bar *bar, int x, int y, uint32_t button);
55
56/**
47 * Free status line struct. 57 * Free status line struct.
48 */ 58 */
49void free_status_line(struct status_line *line); 59void 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);
28 28
29/** 29/**
30 * Will return a new item and get its icon. (see warning below) 30 * Will return a new item and get its icon. (see warning below)
31 * May return `NULL` if `name` is not valid.
31 */ 32 */
32struct StatusNotifierItem *sni_create(const char *name); 33struct StatusNotifierItem *sni_create(const char *name);
33 34
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 {
56 struct lock_colors validating; 56 struct lock_colors validating;
57 struct lock_colors invalid; 57 struct lock_colors invalid;
58 } colors; 58 } colors;
59
60 int radius;
61 int thickness;
59}; 62};
60 63
61void render(struct render_data* render_data, struct lock_config *config); 64void 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 @@
1# sway security rules
2#
3# FreeBSD does not support getting client PID from server side
4# so we can not know the path to the client's binary.
5#
6# The solution for now is to be permissive and allow all
7# features by default for any client.
8
9# Configures enabled compositor features for specific programs
10permit * fullscreen keyboard mouse background screenshot panel lock
11
12ipc * {
13 * enabled
14 events {
15 * enabled
16 }
17}
18
19
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()
94add_config(config config sway) 94add_config(config config sway)
95add_config(00-defaults security.d/00-defaults sway/security.d) 95add_config(00-defaults security.d/00-defaults sway/security.d)
96 96
97if (CMAKE_SYSTEM_NAME STREQUAL FreeBSD)
98 add_config(10-freebsd security.d/10-freebsd sway/security.d)
99endif (CMAKE_SYSTEM_NAME STREQUAL FreeBSD)
100
97if (A2X_FOUND) 101if (A2X_FOUND)
98 add_manpage(sway 1) 102 add_manpage(sway 1)
99 add_manpage(sway 5) 103 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) {
458 if (!containers) { 458 if (!containers) {
459 current_container = get_focused_container(&root_container); 459 current_container = get_focused_container(&root_container);
460 } else if (containers->length == 0) { 460 } else if (containers->length == 0) {
461 break; 461 if (results) {
462 free_cmd_results(results);
463 }
464 results = cmd_results_new(CMD_FAILURE, argv[0], "No matching container");
465 goto cleanup;
462 } else { 466 } else {
463 current_container = (swayc_t *)containers->items[i]; 467 current_container = (swayc_t *)containers->items[i];
464 } 468 }
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) {
61 sym = ((char *)split->items[i])[strlen("button")] - '1' + M_LEFT_CLICK; 61 sym = ((char *)split->items[i])[strlen("button")] - '1' + M_LEFT_CLICK;
62 } 62 }
63 if (!sym) { 63 if (!sym) {
64 struct cmd_results *ret = cmd_results_new(CMD_INVALID, "bindsym",
65 "Unknown key '%s'", (char *)split->items[i]);
64 free_sway_binding(binding); 66 free_sway_binding(binding);
65 free_flat_list(split); 67 free_flat_list(split);
66 return cmd_results_new(CMD_INVALID, "bindsym", "Unknown key '%s'", 68 return ret;
67 (char *)split->items[i]);
68 } 69 }
69 xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t)); 70 xkb_keysym_t *key = malloc(sizeof(xkb_keysym_t));
70 if (!key) { 71 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 @@
7#include "sway/output.h" 7#include "sway/output.h"
8#include "sway/workspace.h" 8#include "sway/workspace.h"
9#include "list.h" 9#include "list.h"
10#include "stringop.h"
10 11
11struct cmd_results *cmd_move(int argc, char **argv) { 12struct cmd_results *cmd_move(int argc, char **argv) {
12 struct cmd_results *error = NULL; 13 struct cmd_results *error = NULL;
@@ -59,18 +60,23 @@ struct cmd_results *cmd_move(int argc, char **argv) {
59 return cmd_results_new(CMD_FAILURE, "move", "Can only move containers and views."); 60 return cmd_results_new(CMD_FAILURE, "move", "Can only move containers and views.");
60 } 61 }
61 62
62 const char *ws_name = argv[3];
63 swayc_t *ws; 63 swayc_t *ws;
64 if (argc == 5 && strcasecmp(ws_name, "number") == 0) { 64 const char *num_name = NULL;
65 char *ws_name = NULL;
66 if (argc == 5 && strcasecmp(argv[3], "number") == 0) {
65 // move "container to workspace number x" 67 // move "container to workspace number x"
66 ws_name = argv[4]; 68 num_name = argv[4];
67 ws = workspace_by_number(ws_name); 69 ws = workspace_by_number(num_name);
68 } else { 70 } else {
71 ws_name = join_args(argv + 3, argc - 3);
69 ws = workspace_by_name(ws_name); 72 ws = workspace_by_name(ws_name);
70 } 73 }
71 74
72 if (ws == NULL) { 75 if (ws == NULL) {
73 ws = workspace_create(ws_name); 76 ws = workspace_create(ws_name ? ws_name : num_name);
77 }
78 if (ws_name) {
79 free(ws_name);
74 } 80 }
75 move_container_to(view, get_focused_container(ws)); 81 move_container_to(view, get_focused_container(ws));
76 } else if (strcasecmp(argv[1], "to") == 0 && strcasecmp(argv[2], "output") == 0) { 82 } 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) {
161 wlc_view_get_visible_geometry(view->handle, &g); 167 wlc_view_get_visible_geometry(view->handle, &g);
162 const struct wlc_size *size = wlc_output_get_resolution(output->handle); 168 const struct wlc_size *size = wlc_output_get_resolution(output->handle);
163 169
164 struct wlc_point origin; 170 double x_pos, y_pos;
165 wlc_pointer_get_position(&origin); 171 wlc_pointer_get_position_v2(&x_pos, &y_pos);
166 172
167 int32_t x = origin.x - g.size.w / 2; 173 int32_t x = x_pos - g.size.w / 2;
168 int32_t y = origin.y - g.size.h / 2; 174 int32_t y = y_pos - g.size.h / 2;
169 175
170 uint32_t w = size->w - g.size.w; 176 uint32_t w = size->w - g.size.w;
171 uint32_t h = size->h - g.size.h; 177 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) {
46 output->enabled = 0; 46 output->enabled = 0;
47 } else if (strcasecmp(command, "resolution") == 0 || strcasecmp(command, "res") == 0) { 47 } else if (strcasecmp(command, "resolution") == 0 || strcasecmp(command, "res") == 0) {
48 if (++i >= argc) { 48 if (++i >= argc) {
49 return cmd_results_new(CMD_INVALID, "output", "Missing resolution argument."); 49 error = cmd_results_new(CMD_INVALID, "output", "Missing resolution argument.");
50 goto fail;
50 } 51 }
51 char *res = argv[i]; 52 char *res = argv[i];
52 char *x = strchr(res, 'x'); 53 char *x = strchr(res, 'x');
@@ -61,7 +62,8 @@ struct cmd_results *cmd_output(int argc, char **argv) {
61 // Format is 1234 4321 62 // Format is 1234 4321
62 width = atoi(res); 63 width = atoi(res);
63 if (++i >= argc) { 64 if (++i >= argc) {
64 return cmd_results_new(CMD_INVALID, "output", "Missing resolution argument (height)."); 65 error = cmd_results_new(CMD_INVALID, "output", "Missing resolution argument (height).");
66 goto fail;
65 } 67 }
66 res = argv[i]; 68 res = argv[i];
67 height = atoi(res); 69 height = atoi(res);
@@ -70,7 +72,8 @@ struct cmd_results *cmd_output(int argc, char **argv) {
70 output->height = height; 72 output->height = height;
71 } else if (strcasecmp(command, "position") == 0 || strcasecmp(command, "pos") == 0) { 73 } else if (strcasecmp(command, "position") == 0 || strcasecmp(command, "pos") == 0) {
72 if (++i >= argc) { 74 if (++i >= argc) {
73 return cmd_results_new(CMD_INVALID, "output", "Missing position argument."); 75 error = cmd_results_new(CMD_INVALID, "output", "Missing position argument.");
76 goto fail;
74 } 77 }
75 char *res = argv[i]; 78 char *res = argv[i];
76 char *c = strchr(res, ','); 79 char *c = strchr(res, ',');
@@ -85,7 +88,8 @@ struct cmd_results *cmd_output(int argc, char **argv) {
85 // Format is 1234 4321 88 // Format is 1234 4321
86 x = atoi(res); 89 x = atoi(res);
87 if (++i >= argc) { 90 if (++i >= argc) {
88 return cmd_results_new(CMD_INVALID, "output", "Missing position argument (y)."); 91 error = cmd_results_new(CMD_INVALID, "output", "Missing position argument (y).");
92 goto fail;
89 } 93 }
90 res = argv[i]; 94 res = argv[i];
91 y = atoi(res); 95 y = atoi(res);
@@ -94,25 +98,49 @@ struct cmd_results *cmd_output(int argc, char **argv) {
94 output->y = y; 98 output->y = y;
95 } else if (strcasecmp(command, "scale") == 0) { 99 } else if (strcasecmp(command, "scale") == 0) {
96 if (++i >= argc) { 100 if (++i >= argc) {
97 return cmd_results_new(CMD_INVALID, "output", "Missing scale parameter."); 101 error = cmd_results_new(CMD_INVALID, "output", "Missing scale parameter.");
102 goto fail;
98 } 103 }
99 output->scale = atoi(argv[i]); 104 output->scale = atoi(argv[i]);
100 } else if (strcasecmp(command, "background") == 0 || strcasecmp(command, "bg") == 0) { 105 } else if (strcasecmp(command, "background") == 0 || strcasecmp(command, "bg") == 0) {
101 wordexp_t p; 106 wordexp_t p;
102 if (++i >= argc) { 107 if (++i >= argc) {
103 return cmd_results_new(CMD_INVALID, "output", "Missing background file or color specification."); 108 error = cmd_results_new(CMD_INVALID, "output", "Missing background file or color specification.");
109 goto fail;
104 } 110 }
105 if (i + 1 >= argc) { 111 if (i + 1 >= argc) {
106 return cmd_results_new(CMD_INVALID, "output", "Missing background scaling mode or `solid_color`."); 112 error = cmd_results_new(CMD_INVALID, "output", "Missing background scaling mode or `solid_color`.");
113 goto fail;
107 } 114 }
108 if (strcasecmp(argv[argc - 1], "solid_color") == 0) { 115 if (strcasecmp(argv[i + 1], "solid_color") == 0) {
109 output->background = strdup(argv[argc - 2]); 116 output->background = strdup(argv[argc - 2]);
110 output->background_option = strdup("solid_color"); 117 output->background_option = strdup("solid_color");
111 } else { 118 } else {
112 char *src = join_args(argv + i, argc - i - 1); 119 // argv[i+j]=bg_option
113 char *mode = argv[argc - 1]; 120 bool valid = false;
121 char *mode;
122 size_t j;
123 for (j = 0; j < (size_t) (argc - i); ++j) {
124 mode = argv[i + j];
125 for (size_t k = 0; k < sizeof(bg_options) / sizeof(char *); ++k) {
126 if (strcasecmp(mode, bg_options[k]) == 0) {
127 valid = true;
128 break;
129 }
130 }
131 if (valid) {
132 break;
133 }
134 }
135 if (!valid) {
136 error = cmd_results_new(CMD_INVALID, "output", "Missing background scaling mode.");
137 goto fail;
138 }
139
140 char *src = join_args(argv + i, j);
114 if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) { 141 if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) {
115 return cmd_results_new(CMD_INVALID, "output", "Invalid syntax (%s)", src); 142 error = cmd_results_new(CMD_INVALID, "output", "Invalid syntax (%s)", src);
143 goto fail;
116 } 144 }
117 free(src); 145 free(src);
118 src = p.we_wordv[0]; 146 src = p.we_wordv[0];
@@ -132,27 +160,19 @@ struct cmd_results *cmd_output(int argc, char **argv) {
132 } 160 }
133 } 161 }
134 if (!src || access(src, F_OK) == -1) { 162 if (!src || access(src, F_OK) == -1) {
135 return cmd_results_new(CMD_INVALID, "output", "Background file unreadable (%s)", src); 163 error = cmd_results_new(CMD_INVALID, "output", "Background file unreadable (%s)", src);
136 } 164 wordfree(&p);
137 for (char *m = mode; *m; ++m) *m = tolower(*m); 165 goto fail;
138 // Check mode
139 bool valid = false;
140 size_t j;
141 for (j = 0; j < sizeof(bg_options) / sizeof(char *); ++j) {
142 if (strcasecmp(mode, bg_options[j]) == 0) {
143 valid = true;
144 break;
145 }
146 }
147 if (!valid) {
148 return cmd_results_new(CMD_INVALID, "output", "Invalid background scaling mode.");
149 } 166 }
167
150 output->background = strdup(src); 168 output->background = strdup(src);
151 output->background_option = strdup(mode); 169 output->background_option = strdup(mode);
152 if (src != p.we_wordv[0]) { 170 if (src != p.we_wordv[0]) {
153 free(src); 171 free(src);
154 } 172 }
155 wordfree(&p); 173 wordfree(&p);
174
175 i += j;
156 } 176 }
157 } 177 }
158 } 178 }
@@ -192,4 +212,8 @@ struct cmd_results *cmd_output(int argc, char **argv) {
192 } 212 }
193 213
194 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 214 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
215
216fail:
217 free_output_config(output);
218 return error;
195} 219}
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) {
30 if (!tmp) { 30 if (!tmp) {
31 return cmd_results_new(CMD_FAILURE, "set", "Not possible to create variable $'%s'", argv[0]); 31 return cmd_results_new(CMD_FAILURE, "set", "Not possible to create variable $'%s'", argv[0]);
32 } 32 }
33 snprintf(tmp, size, "$%s", argv[0]); 33 snprintf(tmp, size+1, "$%s", argv[0]);
34 34
35 argv[0] = tmp; 35 argv[0] = tmp;
36 } 36 }
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) {
128 return; 128 return;
129 } 129 }
130 free(oc->name); 130 free(oc->name);
131 free(oc->background);
132 free(oc->background_option);
131 free(oc); 133 free(oc);
132} 134}
133 135
@@ -548,9 +550,12 @@ bool load_main_config(const char *file, bool is_active) {
548 strcpy(_path, base); 550 strcpy(_path, base);
549 strcat(_path, ent->d_name); 551 strcat(_path, ent->d_name);
550 lstat(_path, &s); 552 lstat(_path, &s);
551 if (S_ISREG(s.st_mode)) { 553 if (S_ISREG(s.st_mode) && ent->d_name[0] != '.') {
552 list_add(secconfigs, _path); 554 list_add(secconfigs, _path);
553 } 555 }
556 else {
557 free(_path);
558 }
554 ent = readdir(dir); 559 ent = readdir(dir);
555 } 560 }
556 closedir(dir); 561 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) {
516 return NULL; 516 return NULL;
517 } 517 }
518 sway_log(L_DEBUG, "Destroying view '%p'", view); 518 sway_log(L_DEBUG, "Destroying view '%p'", view);
519 swayc_t *parent = view->parent;
520 free_swayc(view); 519 free_swayc(view);
521 520
522 // Destroy empty containers 521 // Destroy empty containers
523 if (parent->type == C_CONTAINER) { 522 swayc_t *parent = view->parent;
523 if (parent && parent->type == C_CONTAINER) {
524 return destroy_container(parent); 524 return destroy_container(parent);
525 } 525 }
526 return parent; 526 return parent;
@@ -707,8 +707,10 @@ swayc_t *container_under_pointer(void) {
707 if (lookup->children && !lookup->unmanaged) { 707 if (lookup->children && !lookup->unmanaged) {
708 return NULL; 708 return NULL;
709 } 709 }
710 struct wlc_point origin; 710 double x, y;
711 wlc_pointer_get_position(&origin); 711 wlc_pointer_get_position_v2(&x, &y);
712 struct wlc_point origin = { .x = x, .y = y };
713
712 while (lookup && lookup->type != C_VIEW) { 714 while (lookup && lookup->type != C_VIEW) {
713 int i; 715 int i;
714 int len; 716 int len;
@@ -847,7 +849,6 @@ int swayc_gap(swayc_t *container) {
847 849
848void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { 850void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) {
849 if (container) { 851 if (container) {
850 f(container, data);
851 int i; 852 int i;
852 if (container->children) { 853 if (container->children) {
853 for (i = 0; i < container->children->length; ++i) { 854 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
861 container_map(child, f, data); 862 container_map(child, f, data);
862 } 863 }
863 } 864 }
865 f(container, data);
864 } 866 }
865} 867}
866 868
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 @@
12 12
13enum criteria_type { // *must* keep in sync with criteria_strings[] 13enum criteria_type { // *must* keep in sync with criteria_strings[]
14 CRIT_CLASS, 14 CRIT_CLASS,
15 CRIT_CON_ID,
15 CRIT_CON_MARK, 16 CRIT_CON_MARK,
17 CRIT_FLOATING,
16 CRIT_ID, 18 CRIT_ID,
17 CRIT_INSTANCE, 19 CRIT_INSTANCE,
20 CRIT_TILING,
18 CRIT_TITLE, 21 CRIT_TITLE,
19 CRIT_URGENT, 22 CRIT_URGENT,
20 CRIT_WINDOW_ROLE, 23 CRIT_WINDOW_ROLE,
@@ -25,9 +28,12 @@ enum criteria_type { // *must* keep in sync with criteria_strings[]
25 28
26static const char * const criteria_strings[CRIT_LAST] = { 29static const char * const criteria_strings[CRIT_LAST] = {
27 [CRIT_CLASS] = "class", 30 [CRIT_CLASS] = "class",
31 [CRIT_CON_ID] = "con_id",
28 [CRIT_CON_MARK] = "con_mark", 32 [CRIT_CON_MARK] = "con_mark",
33 [CRIT_FLOATING] = "floating",
29 [CRIT_ID] = "id", 34 [CRIT_ID] = "id",
30 [CRIT_INSTANCE] = "instance", 35 [CRIT_INSTANCE] = "instance",
36 [CRIT_TILING] = "tiling",
31 [CRIT_TITLE] = "title", 37 [CRIT_TITLE] = "title",
32 [CRIT_URGENT] = "urgent", // either "latest" or "oldest" ... 38 [CRIT_URGENT] = "urgent", // either "latest" or "oldest" ...
33 [CRIT_WINDOW_ROLE] = "window_role", 39 [CRIT_WINDOW_ROLE] = "window_role",
@@ -108,6 +114,7 @@ static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str
108 114
109 char **argv = *buf = calloc(max_tokens, sizeof(char*)); 115 char **argv = *buf = calloc(max_tokens, sizeof(char*));
110 argv[0] = base; // this needs to be freed by caller 116 argv[0] = base; // this needs to be freed by caller
117 bool quoted = true;
111 118
112 *argc = 1; // uneven = name, even = value 119 *argc = 1; // uneven = name, even = value
113 while (*head && *argc < max_tokens) { 120 while (*head && *argc < max_tokens) {
@@ -128,7 +135,8 @@ static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str
128 if (*(namep) == ' ') { 135 if (*(namep) == ' ') {
129 namep = strrchr(namep, ' ') + 1; 136 namep = strrchr(namep, ' ') + 1;
130 } 137 }
131 argv[(*argc)++] = namep; 138 argv[*argc] = namep;
139 *argc += 1;
132 } 140 }
133 } else if (*head == '"') { 141 } else if (*head == '"') {
134 if (*argc % 2 != 0) { 142 if (*argc % 2 != 0) {
@@ -137,21 +145,38 @@ static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str
137 "Found quoted value where it was not expected"); 145 "Found quoted value where it was not expected");
138 } else if (!valp) { // value starts here 146 } else if (!valp) { // value starts here
139 valp = head + 1; 147 valp = head + 1;
148 quoted = true;
140 } else { 149 } else {
141 // value ends here 150 // value ends here
142 argv[(*argc)++] = valp; 151 argv[*argc] = valp;
152 *argc += 1;
143 *head = '\0'; 153 *head = '\0';
144 valp = NULL; 154 valp = NULL;
145 namep = head + 1; 155 namep = head + 1;
146 } 156 }
147 } else if (*argc % 2 == 0 && !valp && *head != ' ') { 157 } else if (*argc % 2 == 0 && *head != ' ') {
148 // We're expecting a quoted value, haven't found one yet, and this 158 // parse unquoted values
149 // is not an empty space. 159 if (!valp) {
150 return strdup("Unable to parse criteria: " 160 quoted = false;
151 "Names must be unquoted, values must be quoted"); 161 valp = head; // value starts here
162 }
163 } else if (valp && !quoted && *head == ' ') {
164 // value ends here
165 argv[*argc] = valp;
166 *argc += 1;
167 *head = '\0';
168 valp = NULL;
169 namep = head + 1;
152 } 170 }
153 head++; 171 head++;
154 } 172 }
173
174 // catch last unquoted value if needed
175 if (valp && !quoted && !*head) {
176 argv[*argc] = valp;
177 *argc += 1;
178 }
179
155 return NULL; 180 return NULL;
156} 181}
157 182
@@ -263,6 +288,15 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
263 matches++; 288 matches++;
264 } 289 }
265 break; 290 break;
291 case CRIT_CON_ID: {
292 char *endptr;
293 size_t crit_id = strtoul(crit->raw, &endptr, 10);
294
295 if (*endptr == 0 && cont->id == crit_id) {
296 ++matches;
297 }
298 break;
299 }
266 case CRIT_CON_MARK: 300 case CRIT_CON_MARK:
267 if (crit->regex && cont->marks && (list_seq_find(cont->marks, (int (*)(const void *, const void *))regex_cmp, crit->regex) != -1)) { 301 if (crit->regex && cont->marks && (list_seq_find(cont->marks, (int (*)(const void *, const void *))regex_cmp, crit->regex) != -1)) {
268 // Make sure it isn't matching the NUL string 302 // Make sure it isn't matching the NUL string
@@ -271,6 +305,11 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
271 } 305 }
272 } 306 }
273 break; 307 break;
308 case CRIT_FLOATING:
309 if (cont->is_floating) {
310 matches++;
311 }
312 break;
274 case CRIT_ID: 313 case CRIT_ID:
275 if (!cont->app_id) { 314 if (!cont->app_id) {
276 // ignore 315 // ignore
@@ -290,6 +329,11 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
290 matches++; 329 matches++;
291 } 330 }
292 break; 331 break;
332 case CRIT_TILING:
333 if (!cont->is_floating) {
334 matches++;
335 }
336 break;
293 case CRIT_TITLE: 337 case CRIT_TITLE:
294 if (!cont->name) { 338 if (!cont->name) {
295 // ignore 339 // 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) {
452 wlc_view_focus(handle); 452 wlc_view_focus(handle);
453 wlc_view_bring_to_front(handle); 453 wlc_view_bring_to_front(handle);
454 newview = new_floating_view(handle); 454 newview = new_floating_view(handle);
455 /* fallthrough */
455 case WLC_BIT_POPUP: 456 case WLC_BIT_POPUP:
456 wlc_view_bring_to_front(handle); 457 wlc_view_bring_to_front(handle);
457 break; 458 break;
@@ -552,21 +553,24 @@ static void handle_view_destroyed(wlc_handle handle) {
552 bool fullscreen = swayc_is_fullscreen(view); 553 bool fullscreen = swayc_is_fullscreen(view);
553 remove_view_from_scratchpad(view); 554 remove_view_from_scratchpad(view);
554 swayc_t *parent = destroy_view(view); 555 swayc_t *parent = destroy_view(view);
555 if (fullscreen) { 556 if (parent) {
556 parent->fullscreen = NULL; 557 if (fullscreen) {
557 } 558 parent->fullscreen = NULL;
559 }
558 560
559 // Destroy empty workspaces 561 ipc_event_window(parent, "close");
560 if (parent->type == C_WORKSPACE &&
561 parent->children->length == 0 &&
562 parent->floating->length == 0 &&
563 swayc_active_workspace() != parent &&
564 !parent->visible) {
565 parent = destroy_workspace(parent);
566 }
567 562
568 arrange_windows(parent, -1, -1); 563 // Destroy empty workspaces
569 ipc_event_window(parent, "close"); 564 if (parent->type == C_WORKSPACE &&
565 parent->children->length == 0 &&
566 parent->floating->length == 0 &&
567 swayc_active_workspace() != parent &&
568 !parent->visible) {
569 parent = destroy_workspace(parent);
570 }
571
572 arrange_windows(parent, -1, -1);
573 }
570 } else { 574 } else {
571 // Is it unmanaged? 575 // Is it unmanaged?
572 int i; 576 int i;
@@ -582,6 +586,15 @@ static void handle_view_destroyed(wlc_handle handle) {
582 } 586 }
583 } 587 }
584 } 588 }
589 // Is it in the scratchpad?
590 for (i = 0; i < scratchpad->length; ++i) {
591 swayc_t *item = scratchpad->items[i];
592 if (item->handle == handle) {
593 list_del(scratchpad, i);
594 destroy_view(item);
595 break;
596 }
597 }
585 } 598 }
586 set_focused_container(get_focused_view(&root_container)); 599 set_focused_container(get_focused_view(&root_container));
587} 600}
@@ -805,11 +818,11 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier
805 struct sway_binding *binding = mode->bindings->items[i]; 818 struct sway_binding *binding = mode->bindings->items[i];
806 if ((modifiers->mods ^ binding->modifiers) == 0) { 819 if ((modifiers->mods ^ binding->modifiers) == 0) {
807 switch (state) { 820 switch (state) {
808 case WLC_KEY_STATE_PRESSED: { 821 case WLC_KEY_STATE_PRESSED:
809 if (!binding->release && valid_bindsym(binding)) { 822 if (!binding->release && valid_bindsym(binding)) {
810 list_add(candidates, binding); 823 list_add(candidates, binding);
811 } 824 }
812 } 825 break;
813 case WLC_KEY_STATE_RELEASED: 826 case WLC_KEY_STATE_RELEASED:
814 if (binding->release && handle_bindsym_release(binding)) { 827 if (binding->release && handle_bindsym_release(binding)) {
815 list_free(candidates); 828 list_free(candidates);
@@ -842,12 +855,13 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier
842 return EVENT_PASSTHROUGH; 855 return EVENT_PASSTHROUGH;
843} 856}
844 857
845static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_point *origin) { 858static bool handle_pointer_motion(wlc_handle handle, uint32_t time, double x, double y) {
846 if (desktop_shell.is_locked) { 859 if (desktop_shell.is_locked) {
847 return EVENT_PASSTHROUGH; 860 return EVENT_PASSTHROUGH;
848 } 861 }
849 862
850 struct wlc_point new_origin = *origin; 863 double new_x = x;
864 double new_y = y;
851 // Switch to adjacent output if touching output edge. 865 // Switch to adjacent output if touching output edge.
852 // 866 //
853 // Since this doesn't currently support moving windows between outputs we 867 // 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
856 !pointer_state.left.held && !pointer_state.right.held && !pointer_state.scroll.held) { 870 !pointer_state.left.held && !pointer_state.right.held && !pointer_state.scroll.held) {
857 871
858 swayc_t *output = swayc_active_output(), *adjacent = NULL; 872 swayc_t *output = swayc_active_output(), *adjacent = NULL;
859 struct wlc_point abs_pos = *origin; 873 struct wlc_point abs_pos = { .x = x + output->x, .y = y + output->y };
860 abs_pos.x += output->x; 874 if (x <= 0) { // Left edge
861 abs_pos.y += output->y;
862 if (origin->x == 0) { // Left edge
863 if ((adjacent = swayc_adjacent_output(output, MOVE_LEFT, &abs_pos, false))) { 875 if ((adjacent = swayc_adjacent_output(output, MOVE_LEFT, &abs_pos, false))) {
864 if (workspace_switch(swayc_active_workspace_for(adjacent))) { 876 if (workspace_switch(swayc_active_workspace_for(adjacent))) {
865 new_origin.x = adjacent->width; 877 new_x = adjacent->width;
866 // adjust for differently aligned outputs (well, this is 878 // adjust for differently aligned outputs (well, this is
867 // only correct when the two outputs have the same 879 // only correct when the two outputs have the same
868 // resolution or the same dpi I guess, it should take 880 // resolution or the same dpi I guess, it should take
869 // physical attributes into account) 881 // physical attributes into account)
870 new_origin.y += (output->y - adjacent->y); 882 new_y += (output->y - adjacent->y);
871 } 883 }
872 } 884 }
873 } else if ((double)origin->x == output->width) { // Right edge 885 } else if (x >= output->width) { // Right edge
874 if ((adjacent = swayc_adjacent_output(output, MOVE_RIGHT, &abs_pos, false))) { 886 if ((adjacent = swayc_adjacent_output(output, MOVE_RIGHT, &abs_pos, false))) {
875 if (workspace_switch(swayc_active_workspace_for(adjacent))) { 887 if (workspace_switch(swayc_active_workspace_for(adjacent))) {
876 new_origin.x = 0; 888 new_x = 0;
877 new_origin.y += (output->y - adjacent->y); 889 new_y += (output->y - adjacent->y);
878 } 890 }
879 } 891 }
880 } else if (origin->y == 0) { // Top edge 892 } else if (y <= 0) { // Top edge
881 if ((adjacent = swayc_adjacent_output(output, MOVE_UP, &abs_pos, false))) { 893 if ((adjacent = swayc_adjacent_output(output, MOVE_UP, &abs_pos, false))) {
882 if (workspace_switch(swayc_active_workspace_for(adjacent))) { 894 if (workspace_switch(swayc_active_workspace_for(adjacent))) {
883 new_origin.y = adjacent->height; 895 new_y = adjacent->height;
884 new_origin.x += (output->x - adjacent->x); 896 new_x += (output->x - adjacent->x);
885 } 897 }
886 } 898 }
887 } else if ((double)origin->y == output->height) { // Bottom edge 899 } else if (y >= output->height) { // Bottom edge
888 if ((adjacent = swayc_adjacent_output(output, MOVE_DOWN, &abs_pos, false))) { 900 if ((adjacent = swayc_adjacent_output(output, MOVE_DOWN, &abs_pos, false))) {
889 if (workspace_switch(swayc_active_workspace_for(adjacent))) { 901 if (workspace_switch(swayc_active_workspace_for(adjacent))) {
890 new_origin.y = 0; 902 new_y = 0;
891 new_origin.x += (output->x - adjacent->x); 903 new_x += (output->x - adjacent->x);
892 } 904 }
893 } 905 }
894 } 906 }
895 } 907 }
896 908
897 pointer_position_set(&new_origin, false); 909 pointer_position_set(new_x, new_y, false);
898 910
899 swayc_t *focused = get_focused_container(&root_container); 911 swayc_t *focused = get_focused_container(&root_container);
900 if (focused->type == C_VIEW) { 912 if (focused->type == C_VIEW) {
@@ -935,15 +947,15 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w
935 struct sway_binding *binding = mode->bindings->items[i]; 947 struct sway_binding *binding = mode->bindings->items[i];
936 if ((modifiers->mods ^ binding->modifiers) == 0) { 948 if ((modifiers->mods ^ binding->modifiers) == 0) {
937 switch (state) { 949 switch (state) {
938 case WLC_BUTTON_STATE_PRESSED: { 950 case WLC_BUTTON_STATE_PRESSED:
939 if (!binding->release && handle_bindsym(binding, button, 0)) { 951 if (!binding->release && handle_bindsym(binding, button, 0)) {
940 return EVENT_HANDLED; 952 return EVENT_HANDLED;
941 } 953 }
954 break;
955 case WLC_BUTTON_STATE_RELEASED:
956 if (binding->release && handle_bindsym(binding, button, 0)) {
957 return EVENT_HANDLED;
942 } 958 }
943 case WLC_BUTTON_STATE_RELEASED:
944 if (binding->release && handle_bindsym(binding, button, 0)) {
945 return EVENT_HANDLED;
946 }
947 break; 959 break;
948 } 960 }
949 } 961 }
@@ -1084,16 +1096,8 @@ bool handle_pointer_scroll(wlc_handle view, uint32_t time, const struct wlc_modi
1084 return EVENT_PASSTHROUGH; 1096 return EVENT_PASSTHROUGH;
1085} 1097}
1086 1098
1087static void clip_test_cb(void *data, const char *type, int fd) {
1088 const char *str = data;
1089 write(fd, str, strlen(str));
1090 close(fd);
1091}
1092
1093static void handle_wlc_ready(void) { 1099static void handle_wlc_ready(void) {
1094 sway_log(L_DEBUG, "Compositor is ready, executing cmds in queue"); 1100 sway_log(L_DEBUG, "Compositor is ready, executing cmds in queue");
1095 const char *type = "text/plain;charset=utf-8";
1096 wlc_set_selection("test", &type, 1, &clip_test_cb);
1097 // Execute commands until there are none left 1101 // Execute commands until there are none left
1098 config->active = true; 1102 config->active = true;
1099 while (config->cmd_queue->length) { 1103 while (config->cmd_queue->length) {
@@ -1122,7 +1126,7 @@ void register_wlc_handlers() {
1122 wlc_set_view_request_state_cb(handle_view_state_request); 1126 wlc_set_view_request_state_cb(handle_view_state_request);
1123 wlc_set_view_properties_updated_cb(handle_view_properties_updated); 1127 wlc_set_view_properties_updated_cb(handle_view_properties_updated);
1124 wlc_set_keyboard_key_cb(handle_key); 1128 wlc_set_keyboard_key_cb(handle_key);
1125 wlc_set_pointer_motion_cb(handle_pointer_motion); 1129 wlc_set_pointer_motion_cb_v2(handle_pointer_motion);
1126 wlc_set_pointer_button_cb(handle_pointer_button); 1130 wlc_set_pointer_button_cb(handle_pointer_button);
1127 wlc_set_pointer_scroll_cb(handle_pointer_scroll); 1131 wlc_set_pointer_scroll_cb(handle_pointer_scroll);
1128 wlc_set_compositor_ready_cb(handle_wlc_ready); 1132 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) {
202 pointer_state.mode = 0; 202 pointer_state.mode = 0;
203} 203}
204 204
205void pointer_position_set(struct wlc_point *new_origin, bool force_focus) { 205void pointer_position_set(double new_x, double new_y, bool force_focus) {
206 struct wlc_point origin; 206 double x, y;
207 wlc_pointer_get_position(&origin); 207 wlc_pointer_get_position_v2(&x, &y);
208 pointer_state.delta.x = new_origin->x - origin.x; 208 pointer_state.delta.x = new_x - x;
209 pointer_state.delta.y = new_origin->y - origin.y; 209 pointer_state.delta.y = new_y - y;
210 210
211 wlc_pointer_set_position(new_origin); 211 wlc_pointer_set_position_v2(new_x, new_y);
212 212
213 // Update view under pointer 213 // Update view under pointer
214 swayc_t *prev_view = pointer_state.view; 214 swayc_t *prev_view = pointer_state.view;
@@ -226,10 +226,7 @@ void pointer_position_set(struct wlc_point *new_origin, bool force_focus) {
226} 226}
227 227
228void center_pointer_on(swayc_t *view) { 228void center_pointer_on(swayc_t *view) {
229 struct wlc_point new_origin; 229 pointer_position_set(view->x + view->width/2, view->y + view->height/2, true);
230 new_origin.x = view->x + view->width/2;
231 new_origin.y = view->y + view->height/2;
232 pointer_position_set(&new_origin, true);
233} 230}
234 231
235// Mode set left/right click 232// Mode set left/right click
@@ -269,10 +266,10 @@ static void pointer_mode_set_resizing(void) {
269 int midway_x = initial.ptr->x + initial.ptr->width/2; 266 int midway_x = initial.ptr->x + initial.ptr->width/2;
270 int midway_y = initial.ptr->y + initial.ptr->height/2; 267 int midway_y = initial.ptr->y + initial.ptr->height/2;
271 268
272 struct wlc_point origin; 269 double x, y;
273 wlc_pointer_get_position(&origin); 270 wlc_pointer_get_position_v2(&x, &y);
274 lock.left = origin.x > midway_x; 271 lock.left = x > midway_x;
275 lock.top = origin.y > midway_y; 272 lock.top = y > midway_y;
276 273
277 if (initial.ptr->is_floating) { 274 if (initial.ptr->is_floating) {
278 pointer_state.mode = M_RESIZING | M_FLOATING; 275 pointer_state.mode = M_RESIZING | M_FLOATING;
@@ -346,10 +343,10 @@ void pointer_mode_update(void) {
346 pointer_state.mode = 0; 343 pointer_state.mode = 0;
347 return; 344 return;
348 } 345 }
349 struct wlc_point origin; 346 double x, y;
350 wlc_pointer_get_position(&origin); 347 wlc_pointer_get_position_v2(&x, &y);
351 int dx = origin.x; 348 int dx = x;
352 int dy = origin.y; 349 int dy = y;
353 350
354 switch (pointer_state.mode) { 351 switch (pointer_state.mode) {
355 case M_FLOATING | M_DRAGGING: 352 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)
138 138
139 json_object_object_add(object, "num", json_object_new_int(num)); 139 json_object_object_add(object, "num", json_object_new_int(num));
140 json_object_object_add(object, "output", (workspace->parent) ? json_object_new_string(workspace->parent->name) : NULL); 140 json_object_object_add(object, "output", (workspace->parent) ? json_object_new_string(workspace->parent->name) : NULL);
141 json_object_object_add(object, "urgent", json_object_new_boolean(false));
142 json_object_object_add(object, "type", json_object_new_string("workspace")); 141 json_object_object_add(object, "type", json_object_new_string("workspace"));
143 json_object_object_add(object, "layout", (strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout)); 142 json_object_object_add(object, "layout", (strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout));
144} 143}
@@ -156,38 +155,14 @@ static const char *ipc_json_get_scratchpad_state(swayc_t *c) {
156 155
157static void ipc_json_describe_view(swayc_t *c, json_object *object) { 156static void ipc_json_describe_view(swayc_t *c, json_object *object) {
158 json_object *props = json_object_new_object(); 157 json_object *props = json_object_new_object();
159 float percent = ipc_json_child_percentage(c);
160 const char *layout = (c->parent->type == C_CONTAINER) ?
161 ipc_json_layout_description(c->parent->layout) : "none";
162 const char *last_layout = (c->parent->type == C_CONTAINER) ?
163 ipc_json_layout_description(c->parent->prev_layout) : "none";
164 wlc_handle parent = wlc_view_get_parent(c->handle);
165
166 json_object_object_add(object, "type", json_object_new_string((c->is_floating) ? "floating_con" : "con")); 158 json_object_object_add(object, "type", json_object_new_string((c->is_floating) ? "floating_con" : "con"));
167 159
160 wlc_handle parent = wlc_view_get_parent(c->handle);
168 json_object_object_add(object, "scratchpad_state", 161 json_object_object_add(object, "scratchpad_state",
169 json_object_new_string(ipc_json_get_scratchpad_state(c))); 162 json_object_new_string(ipc_json_get_scratchpad_state(c)));
170 json_object_object_add(object, "percent", (percent > 0) ? json_object_new_double(percent) : NULL);
171 // TODO: make urgency actually work once Sway supports it
172 json_object_object_add(object, "urgent", json_object_new_boolean(false));
173 json_object_object_add(object, "layout",
174 (strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout));
175 json_object_object_add(object, "last_split_layout",
176 (strcmp(last_layout, "null") == 0) ? NULL : json_object_new_string(last_layout));
177 json_object_object_add(object, "workspace_layout",
178 json_object_new_string(ipc_json_layout_description(swayc_parent_by_type(c, C_WORKSPACE)->workspace_layout)));
179
180 json_object_object_add(object, "border", json_object_new_string(ipc_json_border_description(c)));
181 json_object_object_add(object, "current_border_width", json_object_new_int(c->border_thickness));
182
183 json_object_object_add(object, "rect", ipc_json_create_rect(c));
184 json_object_object_add(object, "deco_rect", ipc_json_create_rect_from_geometry(c->title_bar_geometry));
185 json_object_object_add(object, "geometry", ipc_json_create_rect_from_geometry(c->cached_geometry));
186 json_object_object_add(object, "window_rect", ipc_json_create_rect_from_geometry(c->actual_geometry));
187 163
188 json_object_object_add(object, "name", (c->name) ? json_object_new_string(c->name) : NULL); 164 json_object_object_add(object, "name", (c->name) ? json_object_new_string(c->name) : NULL);
189 165
190 json_object_object_add(object, "window", json_object_new_int(c->handle)); // for the sake of i3 compat
191 json_object_object_add(props, "class", c->class ? json_object_new_string(c->class) : 166 json_object_object_add(props, "class", c->class ? json_object_new_string(c->class) :
192 c->app_id ? json_object_new_string(c->app_id) : NULL); 167 c->app_id ? json_object_new_string(c->app_id) : NULL);
193 json_object_object_add(props, "instance", c->instance ? json_object_new_string(c->instance) : 168 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) {
203 c->is_floating ? "auto_on" : "auto_off")); // we can't state the cause 178 c->is_floating ? "auto_on" : "auto_off")); // we can't state the cause
204 179
205 json_object_object_add(object, "app_id", c->app_id ? json_object_new_string(c->app_id) : NULL); 180 json_object_object_add(object, "app_id", c->app_id ? json_object_new_string(c->app_id) : NULL);
181
182 if (c->parent) {
183 const char *layout = (c->parent->type == C_CONTAINER) ?
184 ipc_json_layout_description(c->parent->layout) : "none";
185 const char *last_layout = (c->parent->type == C_CONTAINER) ?
186 ipc_json_layout_description(c->parent->prev_layout) : "none";
187 json_object_object_add(object, "layout",
188 (strcmp(layout, "null") == 0) ? NULL : json_object_new_string(layout));
189 json_object_object_add(object, "last_split_layout",
190 (strcmp(last_layout, "null") == 0) ? NULL : json_object_new_string(last_layout));
191 json_object_object_add(object, "workspace_layout",
192 json_object_new_string(ipc_json_layout_description(swayc_parent_by_type(c, C_WORKSPACE)->workspace_layout)));
193 }
194}
195
196static void ipc_json_describe_root(swayc_t *c, json_object *object) {
197 json_object_object_add(object, "type", json_object_new_string("root"));
198 json_object_object_add(object, "layout", json_object_new_string("splith"));
206} 199}
207 200
208json_object *ipc_json_describe_container(swayc_t *c) { 201json_object *ipc_json_describe_container(swayc_t *c) {
202 float percent = ipc_json_child_percentage(c);
203
209 if (!(sway_assert(c, "Container must not be null."))) { 204 if (!(sway_assert(c, "Container must not be null."))) {
210 return NULL; 205 return NULL;
211 } 206 }
@@ -218,9 +213,19 @@ json_object *ipc_json_describe_container(swayc_t *c) {
218 json_object_object_add(object, "visible", json_object_new_boolean(c->visible)); 213 json_object_object_add(object, "visible", json_object_new_boolean(c->visible));
219 json_object_object_add(object, "focused", json_object_new_boolean(c == current_focus)); 214 json_object_object_add(object, "focused", json_object_new_boolean(c == current_focus));
220 215
216 json_object_object_add(object, "border", json_object_new_string(ipc_json_border_description(c)));
217 json_object_object_add(object, "window_rect", ipc_json_create_rect_from_geometry(c->actual_geometry));
218 json_object_object_add(object, "deco_rect", ipc_json_create_rect_from_geometry(c->title_bar_geometry));
219 json_object_object_add(object, "geometry", ipc_json_create_rect_from_geometry(c->cached_geometry));
220 json_object_object_add(object, "percent", (percent > 0) ? json_object_new_double(percent) : NULL);
221 json_object_object_add(object, "window", json_object_new_int(c->handle)); // for the sake of i3 compat
222 // TODO: make urgency actually work once Sway supports it
223 json_object_object_add(object, "urgent", json_object_new_boolean(false));
224 json_object_object_add(object, "current_border_width", json_object_new_int(c->border_thickness));
225
221 switch (c->type) { 226 switch (c->type) {
222 case C_ROOT: 227 case C_ROOT:
223 json_object_object_add(object, "type", json_object_new_string("root")); 228 ipc_json_describe_root(c, object);
224 break; 229 break;
225 230
226 case C_OUTPUT: 231 case C_OUTPUT:
@@ -451,21 +456,50 @@ json_object *ipc_json_describe_container_recursive(swayc_t *c) {
451 int i; 456 int i;
452 457
453 json_object *floating = json_object_new_array(); 458 json_object *floating = json_object_new_array();
454 if (c->type != C_VIEW && c->floating && c->floating->length > 0) { 459 if (c->type != C_VIEW && c->floating) {
455 for (i = 0; i < c->floating->length; ++i) { 460 for (i = 0; i < c->floating->length; ++i) {
456 json_object_array_add(floating, ipc_json_describe_container_recursive(c->floating->items[i])); 461 swayc_t *item = c->floating->items[i];
462 json_object_array_add(floating, ipc_json_describe_container_recursive(item));
457 } 463 }
458 } 464 }
459 json_object_object_add(object, "floating_nodes", floating); 465 json_object_object_add(object, "floating_nodes", floating);
460 466
461 json_object *children = json_object_new_array(); 467 json_object *children = json_object_new_array();
462 if (c->type != C_VIEW && c->children && c->children->length > 0) { 468 if (c->type != C_VIEW && c->children) {
463 for (i = 0; i < c->children->length; ++i) { 469 for (i = 0; i < c->children->length; ++i) {
464 json_object_array_add(children, ipc_json_describe_container_recursive(c->children->items[i])); 470 json_object_array_add(children, ipc_json_describe_container_recursive(c->children->items[i]));
465 } 471 }
466 } 472 }
467 json_object_object_add(object, "nodes", children); 473 json_object_object_add(object, "nodes", children);
468 474
475 json_object *focus = json_object_new_array();
476 if (c->type != C_VIEW) {
477 if (c->focused) {
478 json_object_array_add(focus, json_object_new_double(c->focused->id));
479 }
480 if (c->floating) {
481 for (i = 0; i < c->floating->length; ++i) {
482 swayc_t *item = c->floating->items[i];
483 if (item == c->focused) {
484 continue;
485 }
486
487 json_object_array_add(focus, json_object_new_double(item->id));
488 }
489 }
490 if (c->children) {
491 for (i = 0; i < c->children->length; ++i) {
492 swayc_t *item = c->children->items[i];
493 if (item == c->focused) {
494 continue;
495 }
496
497 json_object_array_add(focus, json_object_new_double(item->id));
498 }
499 }
500 }
501 json_object_object_add(object, "focus", focus);
502
469 if (c->type == C_ROOT) { 503 if (c->type == C_ROOT) {
470 json_object *scratchpad_json = json_object_new_array(); 504 json_object *scratchpad_json = json_object_new_array();
471 if (scratchpad->length > 0) { 505 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'};
41 41
42struct ipc_client { 42struct ipc_client {
43 struct wlc_event_source *event_source; 43 struct wlc_event_source *event_source;
44 struct wlc_event_source *writable_event_source;
44 int fd; 45 int fd;
45 uint32_t payload_length; 46 uint32_t payload_length;
46 uint32_t security_policy; 47 uint32_t security_policy;
47 enum ipc_command_type current_command; 48 enum ipc_command_type current_command;
48 enum ipc_command_type subscribed_events; 49 enum ipc_command_type subscribed_events;
50 size_t write_buffer_len;
51 size_t write_buffer_size;
52 char *write_buffer;
49}; 53};
50 54
51static list_t *ipc_get_pixel_requests = NULL; 55static list_t *ipc_get_pixel_requests = NULL;
@@ -72,6 +76,7 @@ struct get_clipboard_request {
72struct sockaddr_un *ipc_user_sockaddr(void); 76struct sockaddr_un *ipc_user_sockaddr(void);
73int ipc_handle_connection(int fd, uint32_t mask, void *data); 77int ipc_handle_connection(int fd, uint32_t mask, void *data);
74int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data); 78int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data);
79int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data);
75void ipc_client_disconnect(struct ipc_client *client); 80void ipc_client_disconnect(struct ipc_client *client);
76void ipc_client_handle_command(struct ipc_client *client); 81void ipc_client_handle_command(struct ipc_client *client);
77bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t payload_length); 82bool 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) {
182 close(client_fd); 187 close(client_fd);
183 return 0; 188 return 0;
184 } 189 }
190 if ((flags = fcntl(client_fd, F_GETFL)) == -1
191 || fcntl(client_fd, F_SETFL, flags|O_NONBLOCK) == -1) {
192 sway_log_errno(L_ERROR, "Unable to set NONBLOCK on IPC client socket");
193 close(client_fd);
194 return 0;
195 }
185 196
186 struct ipc_client* client = malloc(sizeof(struct ipc_client)); 197 struct ipc_client* client = malloc(sizeof(struct ipc_client));
187 if (!client) { 198 if (!client) {
@@ -193,10 +204,22 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) {
193 client->fd = client_fd; 204 client->fd = client_fd;
194 client->subscribed_events = 0; 205 client->subscribed_events = 0;
195 client->event_source = wlc_event_loop_add_fd(client_fd, WLC_EVENT_READABLE, ipc_client_handle_readable, client); 206 client->event_source = wlc_event_loop_add_fd(client_fd, WLC_EVENT_READABLE, ipc_client_handle_readable, client);
207 client->writable_event_source = NULL;
208
209 client->write_buffer_size = 128;
210 client->write_buffer_len = 0;
211 client->write_buffer = malloc(client->write_buffer_size);
212 if (!client->write_buffer) {
213 sway_log(L_ERROR, "Unable to allocate ipc client write buffer");
214 close(client_fd);
215 return 0;
216 }
196 217
197 pid_t pid = get_client_pid(client->fd); 218 pid_t pid = get_client_pid(client->fd);
198 client->security_policy = get_ipc_policy_mask(pid); 219 client->security_policy = get_ipc_policy_mask(pid);
199 220
221 sway_log(L_DEBUG, "New client: fd %d, pid %d", client_fd, pid);
222
200 list_add(ipc_client_list, client); 223 list_add(ipc_client_list, client);
201 224
202 return 0; 225 return 0;
@@ -219,6 +242,8 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) {
219 return 0; 242 return 0;
220 } 243 }
221 244
245 sway_log(L_DEBUG, "Client %d readable", client->fd);
246
222 int read_available; 247 int read_available;
223 if (ioctl(client_fd, FIONREAD, &read_available) == -1) { 248 if (ioctl(client_fd, FIONREAD, &read_available) == -1) {
224 sway_log_errno(L_INFO, "Unable to read IPC socket buffer size"); 249 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) {
240 265
241 uint8_t buf[ipc_header_size]; 266 uint8_t buf[ipc_header_size];
242 uint32_t *buf32 = (uint32_t*)(buf + sizeof(ipc_magic)); 267 uint32_t *buf32 = (uint32_t*)(buf + sizeof(ipc_magic));
268 // Should be fully available, because read_available >= ipc_header_size
243 ssize_t received = recv(client_fd, buf, ipc_header_size, 0); 269 ssize_t received = recv(client_fd, buf, ipc_header_size, 0);
244 if (received == -1) { 270 if (received == -1) {
245 sway_log_errno(L_INFO, "Unable to receive header from IPC client"); 271 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) {
263 return 0; 289 return 0;
264} 290}
265 291
292int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) {
293 struct ipc_client *client = data;
294
295 if (mask & WLC_EVENT_ERROR) {
296 sway_log(L_ERROR, "IPC Client socket error, removing client");
297 ipc_client_disconnect(client);
298 return 0;
299 }
300
301 if (mask & WLC_EVENT_HANGUP) {
302 sway_log(L_DEBUG, "Client %d hung up", client->fd);
303 ipc_client_disconnect(client);
304 return 0;
305 }
306
307 if (client->write_buffer_len <= 0) {
308 return 0;
309 }
310
311 sway_log(L_DEBUG, "Client %d writable", client->fd);
312
313 ssize_t written = write(client->fd, client->write_buffer, client->write_buffer_len);
314
315 if (written == -1 && errno == EAGAIN) {
316 return 0;
317 } else if (written == -1) {
318 sway_log_errno(L_INFO, "Unable to send data from queue to IPC client");
319 ipc_client_disconnect(client);
320 return 0;
321 }
322
323 memmove(client->write_buffer, client->write_buffer + written, client->write_buffer_len - written);
324 client->write_buffer_len -= written;
325
326 if (client->write_buffer_len == 0 && client->writable_event_source) {
327 wlc_event_source_remove(client->writable_event_source);
328 client->writable_event_source = NULL;
329 }
330
331 return 0;
332}
333
266void ipc_client_disconnect(struct ipc_client *client) { 334void ipc_client_disconnect(struct ipc_client *client) {
267 if (!sway_assert(client != NULL, "client != NULL")) { 335 if (!sway_assert(client != NULL, "client != NULL")) {
268 return; 336 return;
@@ -274,9 +342,13 @@ void ipc_client_disconnect(struct ipc_client *client) {
274 342
275 sway_log(L_INFO, "IPC Client %d disconnected", client->fd); 343 sway_log(L_INFO, "IPC Client %d disconnected", client->fd);
276 wlc_event_source_remove(client->event_source); 344 wlc_event_source_remove(client->event_source);
345 if (client->writable_event_source) {
346 wlc_event_source_remove(client->writable_event_source);
347 }
277 int i = 0; 348 int i = 0;
278 while (i < ipc_client_list->length && ipc_client_list->items[i] != client) i++; 349 while (i < ipc_client_list->length && ipc_client_list->items[i] != client) i++;
279 list_del(ipc_client_list, i); 350 list_del(ipc_client_list, i);
351 free(client->write_buffer);
280 close(client->fd); 352 close(client->fd);
281 free(client); 353 free(client);
282} 354}
@@ -608,6 +680,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
608 return; 680 return;
609 } 681 }
610 if (client->payload_length > 0) { 682 if (client->payload_length > 0) {
683 // Payload should be fully available
611 ssize_t received = recv(client->fd, buf, client->payload_length, 0); 684 ssize_t received = recv(client->fd, buf, client->payload_length, 0);
612 if (received == -1) 685 if (received == -1)
613 { 686 {
@@ -874,17 +947,36 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay
874 data32[0] = payload_length; 947 data32[0] = payload_length;
875 data32[1] = client->current_command; 948 data32[1] = client->current_command;
876 949
877 if (write(client->fd, data, ipc_header_size) == -1) { 950 while (client->write_buffer_len + ipc_header_size + payload_length >=
878 sway_log_errno(L_INFO, "Unable to send header to IPC client"); 951 client->write_buffer_size) {
952 client->write_buffer_size *= 2;
953 }
954
955 // TODO: reduce the limit back to 4 MB when screenshooter is implemented
956 if (client->write_buffer_size > (1 << 28)) { // 256 MB
957 sway_log(L_ERROR, "Client write buffer too big, disconnecting client");
958 ipc_client_disconnect(client);
879 return false; 959 return false;
880 } 960 }
881 961
882 if (write(client->fd, payload, payload_length) == -1) { 962 char *new_buffer = realloc(client->write_buffer, client->write_buffer_size);
883 sway_log_errno(L_INFO, "Unable to send payload to IPC client"); 963 if (!new_buffer) {
964 sway_log(L_ERROR, "Unable to reallocate ipc client write buffer");
965 ipc_client_disconnect(client);
884 return false; 966 return false;
885 } 967 }
968 client->write_buffer = new_buffer;
969
970 memcpy(client->write_buffer + client->write_buffer_len, data, ipc_header_size);
971 client->write_buffer_len += ipc_header_size;
972 memcpy(client->write_buffer + client->write_buffer_len, payload, payload_length);
973 client->write_buffer_len += payload_length;
974
975 if (!client->writable_event_source) {
976 client->writable_event_source = wlc_event_loop_add_fd(client->fd, WLC_EVENT_WRITABLE, ipc_client_handle_writable, client);
977 }
886 978
887 sway_log(L_DEBUG, "Send IPC reply: %s", payload); 979 sway_log(L_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload);
888 980
889 return true; 981 return true;
890} 982}
@@ -984,11 +1076,7 @@ void ipc_event_window(swayc_t *window, const char *change) {
984 sway_log(L_DEBUG, "Sending window::%s event", change); 1076 sway_log(L_DEBUG, "Sending window::%s event", change);
985 json_object *obj = json_object_new_object(); 1077 json_object *obj = json_object_new_object();
986 json_object_object_add(obj, "change", json_object_new_string(change)); 1078 json_object_object_add(obj, "change", json_object_new_string(change));
987 if (strcmp(change, "close") == 0 || !window) { 1079 json_object_object_add(obj, "container", ipc_json_describe_container_recursive(window));
988 json_object_object_add(obj, "container", NULL);
989 } else {
990 json_object_object_add(obj, "container", ipc_json_describe_container(window));
991 }
992 1080
993 const char *json_string = json_object_to_json_string(obj); 1081 const char *json_string = json_object_to_json_string(obj);
994 ipc_send_event(json_string, IPC_EVENT_WINDOW); 1082 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) {
53 } 53 }
54} 54}
55 55
56void detect_raspi() {
57 bool raspi = false;
58 FILE *f = fopen("/sys/firmware/devicetree/base/model", "r");
59 if (!f) {
60 return;
61 }
62 char *line;
63 while(!feof(f)) {
64 if (!(line = read_line(f))) {
65 break;
66 }
67 if (strstr(line, "Raspberry Pi")) {
68 raspi = true;
69 }
70 free(line);
71 }
72 fclose(f);
73 FILE *g = fopen("/proc/modules", "r");
74 if (!g) {
75 return;
76 }
77 bool vc4 = false;
78 while (!feof(g)) {
79 if (!(line = read_line(g))) {
80 break;
81 }
82 if (strstr(line, "vc4")) {
83 vc4 = true;
84 }
85 free(line);
86 }
87 fclose(g);
88 if (!vc4 && raspi) {
89 fprintf(stderr, "\x1B[1;31mWarning: You have a "
90 "Raspberry Pi, but the vc4 Module is "
91 "not loaded! Set 'dtoverlay=vc4-kms-v3d'"
92 "in /boot/config.txt and reboot.\x1B[0m\n");
93 }
94}
95
56void detect_proprietary() { 96void detect_proprietary() {
57 FILE *f = fopen("/proc/modules", "r"); 97 FILE *f = fopen("/proc/modules", "r");
58 if (!f) { 98 if (!f) {
@@ -366,6 +406,7 @@ int main(int argc, char **argv) {
366 log_distro(); 406 log_distro();
367 log_env(); 407 log_env();
368 detect_proprietary(); 408 detect_proprietary();
409 detect_raspi();
369 410
370 input_devices = create_list(); 411 input_devices = create_list();
371 412
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
237------- 237-------
238Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open 238Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open
239source contributors. For more information about sway development, see 239source contributors. For more information about sway development, see
240<https://github.com/SirCmpwn/sway>. 240<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
119 119
120Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open 120Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open
121source contributors. For more information about sway development, see 121source contributors. For more information about sway development, see
122<https://github.com/SirCmpwn/sway>. 122<https://github.com/swaywm/sway>.
123 123
124See Also 124See Also
125-------- 125--------
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) {
61 // workspace n 61 // workspace n
62 char *cmd = argsep(&cmdlist, " "); 62 char *cmd = argsep(&cmdlist, " ");
63 if (cmdlist) { 63 if (cmdlist) {
64 name = argsep(&cmdlist, " ,;"); 64 name = argsep(&cmdlist, ",;");
65 } 65 }
66 66
67 if (strcmp("workspace", cmd) == 0 && name) { 67 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(
7 ${XKBCOMMON_INCLUDE_DIRS} 7 ${XKBCOMMON_INCLUDE_DIRS}
8 ${DBUS_INCLUDE_DIRS} 8 ${DBUS_INCLUDE_DIRS}
9) 9)
10if (enable-tray) 10if (ENABLE_TRAY)
11 file(GLOB tray 11 file(GLOB tray
12 tray/*.c 12 tray/*.c
13 ) 13 )
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 @@
7#include <sys/wait.h> 7#include <sys/wait.h>
8#include <signal.h> 8#include <signal.h>
9#include <poll.h> 9#include <poll.h>
10#include <linux/input-event-codes.h>
10#ifdef ENABLE_TRAY 11#ifdef ENABLE_TRAY
11#include <dbus/dbus.h> 12#include <dbus/dbus.h>
12#include "swaybar/tray/sni_watcher.h" 13#include "swaybar/tray/sni_watcher.h"
@@ -31,16 +32,30 @@ static void bar_init(struct bar *bar) {
31 32
32static void spawn_status_cmd_proc(struct bar *bar) { 33static void spawn_status_cmd_proc(struct bar *bar) {
33 if (bar->config->status_command) { 34 if (bar->config->status_command) {
34 int pipefd[2]; 35 int pipe_read_fd[2];
35 if (pipe(pipefd) != 0) { 36 int pipe_write_fd[2];
36 sway_log(L_ERROR, "Unable to create pipe for status_command fork"); 37
38 if (pipe(pipe_read_fd) != 0) {
39 sway_log(L_ERROR, "Unable to create pipes for status_command fork");
40 return;
41 }
42 if (pipe(pipe_write_fd) != 0) {
43 sway_log(L_ERROR, "Unable to create pipe for status_command fork (write)");
44 close(pipe_read_fd[0]);
45 close(pipe_read_fd[1]);
37 return; 46 return;
38 } 47 }
48
39 bar->status_command_pid = fork(); 49 bar->status_command_pid = fork();
40 if (bar->status_command_pid == 0) { 50 if (bar->status_command_pid == 0) {
41 close(pipefd[0]); 51 close(pipe_read_fd[0]);
42 dup2(pipefd[1], STDOUT_FILENO); 52 dup2(pipe_read_fd[1], STDOUT_FILENO);
43 close(pipefd[1]); 53 close(pipe_read_fd[1]);
54
55 dup2(pipe_write_fd[0], STDIN_FILENO);
56 close(pipe_write_fd[0]);
57 close(pipe_write_fd[1]);
58
44 char *const cmd[] = { 59 char *const cmd[] = {
45 "sh", 60 "sh",
46 "-c", 61 "-c",
@@ -51,9 +66,13 @@ static void spawn_status_cmd_proc(struct bar *bar) {
51 return; 66 return;
52 } 67 }
53 68
54 close(pipefd[1]); 69 close(pipe_read_fd[1]);
55 bar->status_read_fd = pipefd[0]; 70 bar->status_read_fd = pipe_read_fd[0];
56 fcntl(bar->status_read_fd, F_SETFL, O_NONBLOCK); 71 fcntl(bar->status_read_fd, F_SETFL, O_NONBLOCK);
72
73 close(pipe_write_fd[0]);
74 bar->status_write_fd = pipe_write_fd[1];
75 fcntl(bar->status_write_fd, F_SETFL, O_NONBLOCK);
57 } 76 }
58} 77}
59 78
@@ -103,14 +122,46 @@ static void mouse_button_notify(struct window *window, int x, int y,
103 } 122 }
104 } 123 }
105 124
125 switch (button) {
126 case BTN_LEFT:
127 status_line_mouse_event(&swaybar, x, y, 1);
128 break;
129 case BTN_MIDDLE:
130 status_line_mouse_event(&swaybar, x, y, 2);
131 break;
132 case BTN_RIGHT:
133 status_line_mouse_event(&swaybar, x, y, 3);
134 break;
135 }
136
106#ifdef ENABLE_TRAY 137#ifdef ENABLE_TRAY
107 tray_mouse_event(clicked_output, x, y, button, state_w); 138 tray_mouse_event(clicked_output, x, y, button, state_w);
108#endif 139#endif
140
109} 141}
110 142
111static void mouse_scroll_notify(struct window *window, enum scroll_direction direction) { 143static void mouse_scroll_notify(struct window *window, enum scroll_direction direction) {
112 sway_log(L_DEBUG, "Mouse wheel scrolled %s", direction == SCROLL_UP ? "up" : "down"); 144 sway_log(L_DEBUG, "Mouse wheel scrolled %s", direction == SCROLL_UP ? "up" : "down");
113 145
146 // If there are status blocks and click_events are enabled
147 // check if the position is within the status area and if so
148 // tell the status line to output the event and skip workspace
149 // switching below.
150 int num_blocks = swaybar.status->block_line->length;
151 if (swaybar.status->click_events && num_blocks > 0) {
152 struct status_block *first_block = swaybar.status->block_line->items[0];
153 int x = window->pointer_input.last_x;
154 int y = window->pointer_input.last_y;
155 if (x > first_block->x) {
156 if (direction == SCROLL_UP) {
157 status_line_mouse_event(&swaybar, x, y, 4);
158 } else {
159 status_line_mouse_event(&swaybar, x, y, 5);
160 }
161 return;
162 }
163 }
164
114 if (!swaybar.config->wrap_scroll) { 165 if (!swaybar.config->wrap_scroll) {
115 // Find output this window lives on 166 // Find output this window lives on
116 int i; 167 int i;
@@ -318,6 +369,10 @@ void bar_teardown(struct bar *bar) {
318 close(bar->status_read_fd); 369 close(bar->status_read_fd);
319 } 370 }
320 371
372 if (bar->status_write_fd) {
373 close(bar->status_write_fd);
374 }
375
321 if (bar->ipc_socketfd) { 376 if (bar->ipc_socketfd) {
322 close(bar->ipc_socketfd); 377 close(bar->ipc_socketfd);
323 } 378 }
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 @@
1#define _XOPEN_SOURCE 500 1#define _XOPEN_SOURCE 700
2#include <stdlib.h> 2#include <stdlib.h>
3#include <stdbool.h> 3#include <stdbool.h>
4#include <string.h> 4#include <string.h>
@@ -96,7 +96,7 @@ bool remove_event(int fd) {
96static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) { 96static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) {
97 const struct timer_item *timer_item = _timer_item; 97 const struct timer_item *timer_item = _timer_item;
98 const timer_t *timer = _timer; 98 const timer_t *timer = _timer;
99 if (timer_item->timer == timer) { 99 if (timer_item->timer == *timer) {
100 return 0; 100 return 0;
101 } else { 101 } else {
102 return -1; 102 return -1;
@@ -105,6 +105,7 @@ static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) {
105bool remove_timer(timer_t timer) { 105bool remove_timer(timer_t timer) {
106 int index = list_seq_find(event_loop.timers, timer_item_timer_cmp, &timer); 106 int index = list_seq_find(event_loop.timers, timer_item_timer_cmp, &timer);
107 if (index != -1) { 107 if (index != -1) {
108 free(event_loop.timers->items[index]);
108 list_del(event_loop.timers, index); 109 list_del(event_loop.timers, index);
109 return true; 110 return true;
110 } 111 }
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
94 94
95 double pos = *x; 95 double pos = *x;
96 96
97 block->x = (int)pos;
98 block->width = (int)block_width;
99
97 // render background 100 // render background
98 if (block->background != 0x0) { 101 if (block->background != 0x0) {
99 cairo_set_source_u32(window->cairo, block->background); 102 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 {
27static char line[1024]; 27static char line[1024];
28static char line_rest[1024]; 28static char line_rest[1024];
29 29
30static char event_buff[1024];
31
30static void free_status_block(void *item) { 32static void free_status_block(void *item) {
31 if (!item) { 33 if (!item) {
32 return; 34 return;
@@ -391,6 +393,66 @@ static int i3json_handle_fd(struct bar *bar) {
391 return i3json_parse(bar); 393 return i3json_parse(bar);
392} 394}
393 395
396bool status_line_mouse_event(struct bar *bar, int x, int y, uint32_t button) {
397 sway_log(L_DEBUG, "status_line_mouse_event.");
398 if (!bar->status->click_events) {
399 sway_log(L_DEBUG, "click_events are not enabled.");
400 return false;
401 }
402
403 if (bar->status->protocol == I3BAR) {
404 sway_log(L_DEBUG, "Sending click event.");
405
406 // find clicked block
407 struct status_block *clicked_block = NULL;
408 struct status_block *current_block = NULL;
409 int num_blocks = bar->status->block_line->length;
410
411 if (num_blocks == 0) {
412 return false;
413 } else {
414 current_block = bar->status->block_line->items[0];
415 if (x < current_block->x) {
416 return false;
417 }
418 }
419
420 for (int i = 0; i < num_blocks; i++) {
421 current_block = bar->status->block_line->items[i];
422 if (x < (current_block->x + current_block->width)) {
423 clicked_block = current_block;
424 break;
425 }
426 }
427
428 if (!clicked_block || !clicked_block->name) {
429 return false;
430 }
431
432 // event example {"name":"capture","instance":"label","button":1,"x":3431,"y":18}
433
434 struct json_object *event_json = json_object_new_object();
435 json_object_object_add(event_json, "name", json_object_new_string(clicked_block->name));
436 if (clicked_block->instance) {
437 json_object_object_add(event_json, "instance", json_object_new_string(clicked_block->instance));
438 }
439 json_object_object_add(event_json, "button", json_object_new_int(button));
440 json_object_object_add(event_json, "x", json_object_new_int(x));
441 json_object_object_add(event_json, "y", json_object_new_int(y));
442
443 int len = snprintf(event_buff, sizeof(event_buff), "%s,\n", json_object_to_json_string(event_json));
444
445 json_object_put(event_json);
446
447 if (len <= (int)sizeof(event_buff)) { // if not truncated
448 write(bar->status_write_fd, event_buff, len);
449 return true;
450 }
451 }
452
453 return false;
454}
455
394bool handle_status_line(struct bar *bar) { 456bool handle_status_line(struct bar *bar) {
395 bool dirty = false; 457 bool dirty = false;
396 458
@@ -418,15 +480,29 @@ bool handle_status_line(struct bar *bar) {
418 if (line[0] == '{') { 480 if (line[0] == '{') {
419 // detect i3bar json protocol 481 // detect i3bar json protocol
420 json_object *proto = json_tokener_parse(line); 482 json_object *proto = json_tokener_parse(line);
421 json_object *version;
422 if (proto) { 483 if (proto) {
484
485 json_object *version;
423 if (json_object_object_get_ex(proto, "version", &version) 486 if (json_object_object_get_ex(proto, "version", &version)
424 && json_object_get_int(version) == 1 487 && json_object_get_int(version) == 1
425 ) { 488 ) {
426 sway_log(L_DEBUG, "Switched to i3bar protocol."); 489 sway_log(L_DEBUG, "Switched to i3bar protocol.");
427 bar->status->protocol = I3BAR; 490 bar->status->protocol = I3BAR;
428 i3json_handle_data(bar, line_rest);
429 } 491 }
492
493 json_object *click_events;
494 if (json_object_object_get_ex(proto, "click_events", &click_events)
495 && json_object_get_boolean(click_events)) {
496
497 sway_log(L_DEBUG, "Enabling click events.");
498 bar->status->click_events = true;
499
500 const char *events_array = "[\n";
501 write(bar->status_write_fd, events_array, strlen(events_array));
502 }
503
504 i3json_handle_data(bar, line_rest);
505
430 json_object_put(proto); 506 json_object_put(proto);
431 } 507 }
432 } 508 }
@@ -441,6 +517,7 @@ struct status_line *init_status_line() {
441 line->block_line = create_list(); 517 line->block_line = create_list();
442 line->text_line = NULL; 518 line->text_line = NULL;
443 line->protocol = UNDEF; 519 line->protocol = UNDEF;
520 line->click_events = false;
444 521
445 return line; 522 return line;
446} 523}
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 @@
1#define _XOPEN_SOURCE 500 1#define _XOPEN_SOURCE 700
2#include <stdio.h> 2#include <stdio.h>
3#include <stdlib.h> 3#include <stdlib.h>
4#include <stdint.h> 4#include <stdint.h>
@@ -108,7 +108,7 @@ static dbus_bool_t add_timeout(DBusTimeout *timeout, void *_data) {
108 108
109 timer_settime(*timer, 0, &time, NULL); 109 timer_settime(*timer, 0, &time, NULL);
110 110
111 dbus_timeout_set_data(timeout, timer, free); 111 dbus_timeout_set_data(timeout, timer, NULL);
112 112
113 sway_log(L_DEBUG, "Adding DBus timeout. Interval: %ds %dms", interval_sec, interval_msec); 113 sway_log(L_DEBUG, "Adding DBus timeout. Interval: %ds %dms", interval_sec, interval_msec);
114 add_timer(*timer, dispatch_timeout, timeout); 114 add_timer(*timer, dispatch_timeout, timeout);
@@ -121,6 +121,8 @@ static void remove_timeout(DBusTimeout *timeout, void *_data) {
121 121
122 if (timer) { 122 if (timer) {
123 remove_timer(*timer); 123 remove_timer(*timer);
124 timer_delete(*timer);
125 free(timer);
124 } 126 }
125} 127}
126 128
@@ -136,7 +138,7 @@ static void dispatch_status(DBusConnection *connection, DBusDispatchStatus new_s
136/* Public functions below */ 138/* Public functions below */
137 139
138void dispatch_dbus() { 140void dispatch_dbus() {
139 if (!should_dispatch) { 141 if (!should_dispatch || !conn) {
140 return; 142 return;
141 } 143 }
142 144
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 @@
1#define _XOPEN_SOURCE 500 1#define _XOPEN_SOURCE 700
2#define _POSIX_C_SOURCE 200809L 2#define _POSIX_C_SOURCE 200809L
3#include <stdio.h> 3#include <stdio.h>
4#include <stdlib.h> 4#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) {
160 dirty = true; 160 dirty = true;
161 161
162 dbus_message_unref(reply); 162 dbus_message_unref(reply);
163 dbus_pending_call_unref(pending);
163 return; 164 return;
164 } else { 165 } else {
165 sway_log(L_ERROR, "Could not create image surface"); 166 sway_log(L_ERROR, "Could not create image surface");
@@ -170,6 +171,7 @@ bail:
170 if (reply) { 171 if (reply) {
171 dbus_message_unref(reply); 172 dbus_message_unref(reply);
172 } 173 }
174 dbus_pending_call_unref(pending);
173 sway_log(L_ERROR, "Could not get icon from item"); 175 sway_log(L_ERROR, "Could not get icon from item");
174 return; 176 return;
175} 177}
@@ -266,6 +268,7 @@ static void reply_icon_name(DBusPendingCall *pending, void *_data) {
266 dirty = true; 268 dirty = true;
267 269
268 dbus_message_unref(reply); 270 dbus_message_unref(reply);
271 dbus_pending_call_unref(pending);
269 return; 272 return;
270 } 273 }
271 274
@@ -273,6 +276,7 @@ bail:
273 if (reply) { 276 if (reply) {
274 dbus_message_unref(reply); 277 dbus_message_unref(reply);
275 } 278 }
279 dbus_pending_call_unref(pending);
276 // Now try the pixmap 280 // Now try the pixmap
277 send_icon_msg(item); 281 send_icon_msg(item);
278 return; 282 return;
@@ -413,6 +417,12 @@ static void get_unique_name(struct StatusNotifierItem *item) {
413} 417}
414 418
415struct StatusNotifierItem *sni_create(const char *name) { 419struct StatusNotifierItem *sni_create(const char *name) {
420 // Make sure `name` is well formed
421 if (!dbus_validate_bus_name(name, NULL)) {
422 sway_log(L_INFO, "Name (%s) is not a bus name. We cannot create an item.", name);
423 return NULL;
424 }
425
416 struct StatusNotifierItem *item = malloc(sizeof(struct StatusNotifierItem)); 426 struct StatusNotifierItem *item = malloc(sizeof(struct StatusNotifierItem));
417 item->name = strdup(name); 427 item->name = strdup(name);
418 item->unique_name = NULL; 428 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) {
150 sway_log(L_ERROR, "Error parsing method args: %s\n", error.message); 150 sway_log(L_ERROR, "Error parsing method args: %s\n", error.message);
151 } 151 }
152 152
153 name = strdup(name);
154 sway_log(L_INFO, "RegisterStatusNotifierItem called with \"%s\"\n", name); 153 sway_log(L_INFO, "RegisterStatusNotifierItem called with \"%s\"\n", name);
155 154
156 // Don't add duplicate or not real item 155 // Don't add duplicate or not real item
156 if (!dbus_validate_bus_name(name, NULL)) {
157 sway_log(L_INFO, "This item is not valid, we cannot keep track of it.");
158 return;
159 }
160
157 if (list_seq_find(items, (int (*)(const void *, const void *))strcmp, name) != -1) { 161 if (list_seq_find(items, (int (*)(const void *, const void *))strcmp, name) != -1) {
158 return; 162 return;
159 } 163 }
@@ -161,7 +165,7 @@ static void register_item(DBusConnection *connection, DBusMessage *message) {
161 return; 165 return;
162 } 166 }
163 167
164 list_add(items, name); 168 list_add(items, strdup(name));
165 item_registered_signal(connection, name); 169 item_registered_signal(connection, name);
166 170
167 // It's silly, but xembedsniproxy wants a reply for this function 171 // It's silly, but xembedsniproxy wants a reply for this function
@@ -184,6 +188,12 @@ static void register_host(DBusConnection *connection, DBusMessage *message) {
184 sway_log(L_INFO, "RegisterStatusNotifierHost called with \"%s\"\n", name); 188 sway_log(L_INFO, "RegisterStatusNotifierHost called with \"%s\"\n", name);
185 189
186 // Don't add duplicate or not real host 190 // Don't add duplicate or not real host
191 if (!dbus_validate_bus_name(name, NULL)) {
192 sway_log(L_INFO, "This item is not valid, we cannot keep track of it.");
193 return;
194 }
195
196
187 if (list_seq_find(hosts, (int (*)(const void *, const void *))strcmp, name) != -1) { 197 if (list_seq_find(hosts, (int (*)(const void *, const void *))strcmp, name) != -1) {
188 return; 198 return;
189 } 199 }
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 @@
1#define _XOPEN_SOURCE 500 1#define _XOPEN_SOURCE 700
2#include <unistd.h> 2#include <unistd.h>
3#include <stdlib.h> 3#include <stdlib.h>
4#include <string.h> 4#include <string.h>
@@ -90,13 +90,16 @@ static void get_items_reply(DBusPendingCall *pending, void *_data) {
90 90
91 struct StatusNotifierItem *item = sni_create(name); 91 struct StatusNotifierItem *item = sni_create(name);
92 92
93 sway_log(L_DEBUG, "Item registered with host: %s", name); 93 if (item) {
94 list_add(tray->items, item); 94 sway_log(L_DEBUG, "Item registered with host: %s", name);
95 dirty = true; 95 list_add(tray->items, item);
96 dirty = true;
97 }
96 } 98 }
97 99
98bail: 100bail:
99 dbus_message_unref(reply); 101 dbus_message_unref(reply);
102 dbus_pending_call_unref(pending);
100 return; 103 return;
101} 104}
102static void get_items() { 105static void get_items() {
@@ -141,8 +144,10 @@ static DBusHandlerResult signal_handler(DBusConnection *connection,
141 if (list_seq_find(tray->items, sni_str_cmp, name) == -1) { 144 if (list_seq_find(tray->items, sni_str_cmp, name) == -1) {
142 struct StatusNotifierItem *item = sni_create(name); 145 struct StatusNotifierItem *item = sni_create(name);
143 146
144 list_add(tray->items, item); 147 if (item) {
145 dirty = true; 148 list_add(tray->items, item);
149 dirty = true;
150 }
146 } 151 }
147 152
148 return DBUS_HANDLER_RESULT_HANDLED; 153 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 @@
9#include <stdint.h> 9#include <stdint.h>
10#include <math.h> 10#include <math.h>
11#include <time.h> 11#include <time.h>
12#include <sys/wait.h>
12#include <json-c/json.h> 13#include <json-c/json.h>
13#include "log.h" 14#include "log.h"
14#include "ipc-client.h" 15#include "ipc-client.h"
@@ -47,17 +48,32 @@ void grab_and_apply_magick(const char *file, const char *payload,
47 return; 48 return;
48 } 49 }
49 50
50 const char *fmt = "convert -depth 8 -size %dx%d+0 rgba:- -flip %s"; 51 char size[10 + 1 + 10 + 2 + 1]; // int32_t are max 10 digits
51 char *cmd = malloc(strlen(fmt) - 6 /*args*/ 52 sprintf(size, "%dx%d+0", width, height);
52 + numlen(width) + numlen(height) + strlen(file) + 1);
53 sprintf(cmd, fmt, width, height, file);
54 53
55 FILE *f = popen(cmd, "w"); 54 pid_t child;
56 fwrite(pixels, 1, len, f); 55 int fd[2];
57 fflush(f); 56 pipe(fd);
58 fclose(f); 57
59 free(pixels - 9); 58 if ((child = fork()) < 0) {
60 free(cmd); 59 sway_log(L_ERROR, "Swaygrab failed to fork.");
60 exit(EXIT_FAILURE);
61 } else if (child != 0) {
62 close(fd[0]);
63 write(fd[1], pixels, len);
64 close(fd[1]);
65 free(pixels - 9);
66 waitpid(child, NULL, 0);
67 } else {
68 close(fd[1]);
69 if (dup2(fd[0], 0) != 0) {
70 sway_log(L_ERROR, "Could not fdup the pipe");
71 }
72 close(fd[0]);
73 execlp("convert", "convert", "-depth", "8", "-size", size, "rgba:-", "-flip", file, NULL);
74 sway_log(L_ERROR, "Swaygrab could not run convert.");
75 exit(EXIT_FAILURE);
76 }
61} 77}
62 78
63void grab_and_apply_movie_magic(const char *file, const char *payload, 79void 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,
93 "-video_size %dx%d -pixel_format argb " 109 "-video_size %dx%d -pixel_format argb "
94 "-i pipe:0 -r %d -vf vflip %s"; 110 "-i pipe:0 -r %d -vf vflip %s";
95 char *cmd = malloc(strlen(fmt) - 8 /*args*/ 111 char *cmd = malloc(strlen(fmt) - 8 /*args*/
96 + strlen(ffmpeg_opts) + numlen(width) + numlen(height) 112 + strlen(ffmpeg_opts) + numlen(width) + numlen(height)
97 + numlen(framerate) * 2 + strlen(file) + 1); 113 + numlen(framerate) * 2 + strlen(file) + 1);
98 sprintf(cmd, fmt, ffmpeg_opts, framerate, width, height, framerate, file); 114 sprintf(cmd, fmt, ffmpeg_opts, framerate, width, height, framerate, file);
99 115
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
73 73
74Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open 74Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open
75source contributors. For more information about sway development, see 75source contributors. For more information about sway development, see
76<https://github.com/SirCmpwn/sway>. 76<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() {
81 config->colors.invalid.inner_ring = 0xFA0000BF; 81 config->colors.invalid.inner_ring = 0xFA0000BF;
82 config->colors.invalid.outer_ring = 0x7D3300FF; 82 config->colors.invalid.outer_ring = 0x7D3300FF;
83 83
84 config->radius = 50;
85 config->thickness = 10;
86
84 return config; 87 return config;
85} 88}
86 89
@@ -149,10 +152,11 @@ bool verify_password() {
149void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t code, uint32_t codepoint) { 152void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t code, uint32_t codepoint) {
150 int redraw_screen = 0; 153 int redraw_screen = 0;
151 char *password_realloc; 154 char *password_realloc;
155 int i;
152 156
153 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { 157 if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
154 switch (sym) { 158 switch (sym) {
155 case XKB_KEY_KP_Enter: // fallthrough 159 case XKB_KEY_KP_Enter:
156 case XKB_KEY_Return: 160 case XKB_KEY_Return:
157 render_data.auth_state = AUTH_STATE_VALIDATING; 161 render_data.auth_state = AUTH_STATE_VALIDATING;
158 162
@@ -163,6 +167,7 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod
163 if (verify_password()) { 167 if (verify_password()) {
164 exit(0); 168 exit(0);
165 } 169 }
170
166 render_data.auth_state = AUTH_STATE_INVALID; 171 render_data.auth_state = AUTH_STATE_INVALID;
167 redraw_screen = 1; 172 redraw_screen = 1;
168 173
@@ -171,73 +176,65 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod
171 password[0] = '\0'; 176 password[0] = '\0';
172 break; 177 break;
173 case XKB_KEY_BackSpace: 178 case XKB_KEY_BackSpace:
174 { 179 i = strlen(password);
175 int i = strlen(password); 180 if (i > 0) {
176 if (i > 0) { 181 password[i - 1] = '\0';
177 password[i - 1] = '\0'; 182 render_data.auth_state = AUTH_STATE_BACKSPACE;
178 render_data.auth_state = AUTH_STATE_BACKSPACE; 183 redraw_screen = 1;
179 redraw_screen = 1;
180 }
181 break;
182 } 184 }
183 case XKB_KEY_Control_L: // fallthrough 185 break;
184 case XKB_KEY_Control_R: // fallthrough 186 case XKB_KEY_Control_L:
185 case XKB_KEY_Shift_L: // fallthrough 187 case XKB_KEY_Control_R:
186 case XKB_KEY_Shift_R: // fallthrough 188 case XKB_KEY_Shift_L:
187 case XKB_KEY_Caps_Lock: // fallthrough 189 case XKB_KEY_Shift_R:
188 case XKB_KEY_Shift_Lock: // fallthrough 190 case XKB_KEY_Caps_Lock:
189 case XKB_KEY_Meta_L: // fallthrough 191 case XKB_KEY_Shift_Lock:
190 case XKB_KEY_Meta_R: // fallthrough 192 case XKB_KEY_Meta_L:
191 case XKB_KEY_Alt_L: // fallthrough 193 case XKB_KEY_Meta_R:
192 case XKB_KEY_Alt_R: // fallthrough 194 case XKB_KEY_Alt_L:
193 case XKB_KEY_Super_L: // fallthrough 195 case XKB_KEY_Alt_R:
194 case XKB_KEY_Super_R: // fallthrough 196 case XKB_KEY_Super_L:
195 case XKB_KEY_Hyper_L: // fallthrough 197 case XKB_KEY_Super_R:
198 case XKB_KEY_Hyper_L:
196 case XKB_KEY_Hyper_R: 199 case XKB_KEY_Hyper_R:
197 { 200 break; // don't draw screen on modifier keys
198 // don't draw screen on modifier keys 201 case XKB_KEY_Escape:
199 break; 202 case XKB_KEY_u:
200 }
201 case XKB_KEY_Escape: // fallthrough
202 case XKB_KEY_u: // fallthrough
203 case XKB_KEY_U: 203 case XKB_KEY_U:
204 { 204 // clear password buffer on ctrl-u (or escape for i3lock compatibility)
205 // clear password buffer on ctrl-u (or escape for i3lock compatibility) 205 if (sym == XKB_KEY_Escape || xkb_state_mod_name_is_active(registry->input->xkb.state,
206 if (sym == XKB_KEY_Escape || xkb_state_mod_name_is_active(registry->input->xkb.state, 206 XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE) > 0) {
207 XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE) > 0) { 207 render_data.auth_state = AUTH_STATE_BACKSPACE;
208 render_data.auth_state = AUTH_STATE_BACKSPACE; 208 redraw_screen = 1;
209 redraw_screen = 1;
210 209
210 password_size = 1024;
211 free(password);
212 password = malloc(password_size);
213 password[0] = '\0';
214 break;
215 }
216 /* fallthrough */
217 default:
218 render_data.auth_state = AUTH_STATE_INPUT;
219 redraw_screen = 1;
220 i = strlen(password);
221 if (i + 1 == password_size) {
222 password_size += 1024;
223 password_realloc = realloc(password, password_size);
224 // reset password if realloc fails.
225 if (password_realloc == NULL) {
211 password_size = 1024; 226 password_size = 1024;
212 free(password); 227 free(password);
213 password = malloc(password_size); 228 password = malloc(password_size);
214 password[0] = '\0'; 229 password[0] = '\0';
215 break; 230 break;
231 } else {
232 password = password_realloc;
216 } 233 }
217 } 234 }
218 default: 235 password[i] = (char)codepoint;
219 { 236 password[i + 1] = '\0';
220 render_data.auth_state = AUTH_STATE_INPUT; 237 break;
221 redraw_screen = 1;
222 int i = strlen(password);
223 if (i + 1 == password_size) {
224 password_size += 1024;
225 password_realloc = realloc(password, password_size);
226 // reset password if realloc fails.
227 if (password_realloc == NULL) {
228 password_size = 1024;
229 free(password);
230 password = malloc(password_size);
231 password[0] = '\0';
232 break;
233 } else {
234 password = password_realloc;
235 }
236 }
237 password[i] = (char)codepoint;
238 password[i + 1] = '\0';
239 break;
240 }
241 } 238 }
242 if (redraw_screen) { 239 if (redraw_screen) {
243 render(&render_data, config); 240 render(&render_data, config);
@@ -383,6 +380,8 @@ int main(int argc, char **argv) {
383 {"separatorcolor", required_argument, NULL, 0}, 380 {"separatorcolor", required_argument, NULL, 0},
384 {"keyhlcolor", required_argument, NULL, 0}, 381 {"keyhlcolor", required_argument, NULL, 0},
385 {"bshlcolor", required_argument, NULL, 0}, 382 {"bshlcolor", required_argument, NULL, 0},
383 {"indicator-radius", required_argument, NULL, 0},
384 {"indicator-thickness", required_argument, NULL, 0},
386 {0, 0, 0, 0} 385 {0, 0, 0, 0}
387 }; 386 };
388 387
@@ -509,6 +508,10 @@ int main(int argc, char **argv) {
509 config->colors.input_cursor = parse_color(optarg); 508 config->colors.input_cursor = parse_color(optarg);
510 } else if (strcmp(long_options[option_index].name, "bshlcolor") == 0) { 509 } else if (strcmp(long_options[option_index].name, "bshlcolor") == 0) {
511 config->colors.backspace_cursor = parse_color(optarg); 510 config->colors.backspace_cursor = parse_color(optarg);
511 } else if (strcmp(long_options[option_index].name, "indicator-radius") == 0) {
512 config->radius = atoi(optarg);
513 } else if (strcmp(long_options[option_index].name, "indicator-thickness") == 0) {
514 config->thickness = atoi(optarg);
512 } 515 }
513 break; 516 break;
514 default: 517 default:
@@ -678,16 +681,14 @@ void render(struct render_data *render_data, struct lock_config *config) {
678 cairo_identity_matrix(window->cairo); 681 cairo_identity_matrix(window->cairo);
679 682
680 // Draw specific values (copied from i3) 683 // Draw specific values (copied from i3)
681 const int ARC_RADIUS = 50;
682 const int ARC_THICKNESS = 10;
683 const float TYPE_INDICATOR_RANGE = M_PI / 3.0f; 684 const float TYPE_INDICATOR_RANGE = M_PI / 3.0f;
684 const float TYPE_INDICATOR_BORDER_THICKNESS = M_PI / 128.0f; 685 const float TYPE_INDICATOR_BORDER_THICKNESS = M_PI / 128.0f;
685 686
686 // Add visual indicator 687 // Add visual indicator
687 if (show_indicator && render_data->auth_state != AUTH_STATE_IDLE) { 688 if (show_indicator && render_data->auth_state != AUTH_STATE_IDLE) {
688 // Draw circle 689 // Draw circle
689 cairo_set_line_width(window->cairo, ARC_THICKNESS); 690 cairo_set_line_width(window->cairo, config->thickness);
690 cairo_arc(window->cairo, wwidth/2, wheight/2, ARC_RADIUS, 0, 2 * M_PI); 691 cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius, 0, 2 * M_PI);
691 switch (render_data->auth_state) { 692 switch (render_data->auth_state) {
692 case AUTH_STATE_INPUT: 693 case AUTH_STATE_INPUT:
693 case AUTH_STATE_BACKSPACE: { 694 case AUTH_STATE_BACKSPACE: {
@@ -715,7 +716,7 @@ void render(struct render_data *render_data, struct lock_config *config) {
715 char *text = NULL; 716 char *text = NULL;
716 cairo_set_source_u32(window->cairo, config->colors.text); 717 cairo_set_source_u32(window->cairo, config->colors.text);
717 cairo_select_font_face(window->cairo, config->font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); 718 cairo_select_font_face(window->cairo, config->font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
718 cairo_set_font_size(window->cairo, ARC_RADIUS/3.0f); 719 cairo_set_font_size(window->cairo, config->radius/3.0f);
719 switch (render_data->auth_state) { 720 switch (render_data->auth_state) {
720 case AUTH_STATE_VALIDATING: 721 case AUTH_STATE_VALIDATING:
721 text = "verifying"; 722 text = "verifying";
@@ -744,7 +745,7 @@ void render(struct render_data *render_data, struct lock_config *config) {
744 if (render_data->auth_state == AUTH_STATE_INPUT || render_data->auth_state == AUTH_STATE_BACKSPACE) { 745 if (render_data->auth_state == AUTH_STATE_INPUT || render_data->auth_state == AUTH_STATE_BACKSPACE) {
745 static double highlight_start = 0; 746 static double highlight_start = 0;
746 highlight_start += (rand() % (int)(M_PI * 100)) / 100.0 + M_PI * 0.5; 747 highlight_start += (rand() % (int)(M_PI * 100)) / 100.0 + M_PI * 0.5;
747 cairo_arc(window->cairo, wwidth/2, wheight/2, ARC_RADIUS, highlight_start, highlight_start + TYPE_INDICATOR_RANGE); 748 cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius, highlight_start, highlight_start + TYPE_INDICATOR_RANGE);
748 if (render_data->auth_state == AUTH_STATE_INPUT) { 749 if (render_data->auth_state == AUTH_STATE_INPUT) {
749 cairo_set_source_u32(window->cairo, config->colors.input_cursor); 750 cairo_set_source_u32(window->cairo, config->colors.input_cursor);
750 } else { 751 } else {
@@ -754,10 +755,10 @@ void render(struct render_data *render_data, struct lock_config *config) {
754 755
755 // Draw borders 756 // Draw borders
756 cairo_set_source_u32(window->cairo, config->colors.separator); 757 cairo_set_source_u32(window->cairo, config->colors.separator);
757 cairo_arc(window->cairo, wwidth/2, wheight/2, ARC_RADIUS, highlight_start, highlight_start + TYPE_INDICATOR_BORDER_THICKNESS); 758 cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius, highlight_start, highlight_start + TYPE_INDICATOR_BORDER_THICKNESS);
758 cairo_stroke(window->cairo); 759 cairo_stroke(window->cairo);
759 760
760 cairo_arc(window->cairo, wwidth/2, wheight/2, ARC_RADIUS, highlight_start + TYPE_INDICATOR_RANGE, (highlight_start + TYPE_INDICATOR_RANGE) + TYPE_INDICATOR_BORDER_THICKNESS); 761 cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius, highlight_start + TYPE_INDICATOR_RANGE, (highlight_start + TYPE_INDICATOR_RANGE) + TYPE_INDICATOR_BORDER_THICKNESS);
761 cairo_stroke(window->cairo); 762 cairo_stroke(window->cairo);
762 } 763 }
763 764
@@ -793,9 +794,9 @@ void render(struct render_data *render_data, struct lock_config *config) {
793 } 794 }
794 // Draw inner + outer border of the circle 795 // Draw inner + outer border of the circle
795 cairo_set_line_width(window->cairo, 2.0); 796 cairo_set_line_width(window->cairo, 2.0);
796 cairo_arc(window->cairo, wwidth/2, wheight/2, ARC_RADIUS - ARC_THICKNESS/2, 0, 2*M_PI); 797 cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius - config->thickness/2, 0, 2*M_PI);
797 cairo_stroke(window->cairo); 798 cairo_stroke(window->cairo);
798 cairo_arc(window->cairo, wwidth/2, wheight/2, ARC_RADIUS + ARC_THICKNESS/2, 0, 2*M_PI); 799 cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius + config->thickness/2, 0, 2*M_PI);
799 cairo_stroke(window->cairo); 800 cairo_stroke(window->cairo);
800 } 801 }
801 window_render(window); 802 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
95*--textcolor* <rrggbb[aa]>:: 95*--textcolor* <rrggbb[aa]>::
96 Sets the color of the text inside the indicator. 96 Sets the color of the text inside the indicator.
97 97
98*--indicator-radius* <radius>::
99 Sets the radius of the indicator to _radius_ pixels. The default value is
100 50.
101
102*--indicator-thickness* <thickness>::
103 Sets the thickness of the indicator to _thickness_ pixels. The default value
104 is 10.
105
98Authors 106Authors
99------- 107-------
100 108
101Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open 109Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open
102source contributors. For more information about sway development, see 110source contributors. For more information about sway development, see
103<https://github.com/SirCmpwn/sway>. 111<https://github.com/swaywm/sway>.
104 112
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
76 76
77Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open 77Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open
78source contributors. For more information about sway development, see 78source contributors. For more information about sway development, see
79<https://github.com/SirCmpwn/sway>. 79<https://github.com/swaywm/sway>.
80 80
81See Also 81See Also
82-------- 82--------
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,
19 state->flags = flags; 19 state->flags = flags;
20 state->width = width; 20 state->width = width;
21 state->height = height; 21 state->height = height;
22 sway_log(L_DEBUG, "Got mode %dx%x:0x%X for output %p", 22 sway_log(L_DEBUG, "Got mode %dx%d:0x%X for output %p",
23 width, height, flags, data); 23 width, height, flags, data);
24 } 24 }
25} 25}