mirror of
https://github.com/swaywm/sway.git
synced 2026-04-28 06:46:26 -04:00
Merge branch 'master' into indonesian_translation
This commit is contained in:
commit
916838cd51
50 changed files with 687 additions and 198 deletions
38
.builds/alpine.yml
Normal file
38
.builds/alpine.yml
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
image: alpine/edge
|
||||
packages:
|
||||
- cairo-dev
|
||||
- eudev-dev
|
||||
- gdk-pixbuf-dev
|
||||
- json-c-dev
|
||||
- libevdev-dev
|
||||
- libinput-dev
|
||||
- libxcb-dev
|
||||
- libxkbcommon-dev
|
||||
- mesa-dev
|
||||
- meson
|
||||
- pango-dev
|
||||
- pixman-dev
|
||||
- scdoc
|
||||
- wayland-dev
|
||||
- wayland-protocols
|
||||
- xcb-util-image-dev
|
||||
- xorg-server-xwayland
|
||||
sources:
|
||||
- https://github.com/swaywm/sway
|
||||
- https://github.com/swaywm/wlroots
|
||||
tasks:
|
||||
- wlroots: |
|
||||
cd wlroots
|
||||
meson --prefix=/usr build -Drootston=false -Dexamples=false
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
- setup: |
|
||||
cd sway
|
||||
meson build
|
||||
- build: |
|
||||
cd sway
|
||||
ninja -C build
|
||||
- build-no-xwayland: |
|
||||
cd sway
|
||||
meson configure build -Dxwayland=disabled
|
||||
ninja -C build
|
||||
|
|
@ -1,25 +1,25 @@
|
|||
# vim: ft=yaml ts=2 sw=2 et :
|
||||
image: archlinux
|
||||
packages:
|
||||
- meson
|
||||
- xorg-server-xwayland
|
||||
- xcb-util-image
|
||||
- json-c
|
||||
- pango
|
||||
- cairo
|
||||
- gdk-pixbuf2
|
||||
- json-c
|
||||
- libinput
|
||||
- libxcb
|
||||
- libxkbcommon
|
||||
- meson
|
||||
- pango
|
||||
- scdoc
|
||||
- wayland
|
||||
- wayland-protocols
|
||||
- gdk-pixbuf2
|
||||
- libinput
|
||||
- libxkbcommon
|
||||
- scdoc
|
||||
- xcb-util-image
|
||||
- xorg-server-xwayland
|
||||
sources:
|
||||
- https://github.com/swaywm/sway
|
||||
- https://github.com/swaywm/wlroots
|
||||
tasks:
|
||||
- wlroots: |
|
||||
cd wlroots
|
||||
meson --prefix=/usr build
|
||||
meson --prefix=/usr build -Drootston=false -Dexamples=false
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
- setup: |
|
||||
53
.builds/freebsd.yml
Normal file
53
.builds/freebsd.yml
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
image: freebsd/latest
|
||||
packages:
|
||||
- devel/json-c
|
||||
- devel/libevdev
|
||||
- devel/meson
|
||||
- devel/pkgconf
|
||||
- graphics/cairo
|
||||
- graphics/gdk-pixbuf2
|
||||
- graphics/wayland
|
||||
- graphics/wayland-protocols
|
||||
- textproc/scdoc
|
||||
- x11-toolkits/pango
|
||||
- x11/libxcb
|
||||
- x11/libxkbcommon
|
||||
# wlroots dependencies
|
||||
- devel/evdev-proto
|
||||
- devel/libepoll-shim
|
||||
- devel/libudev-devd
|
||||
- graphics/libdrm
|
||||
- graphics/mesa-libs
|
||||
- x11/libinput
|
||||
- x11/libX11
|
||||
- x11/pixman
|
||||
- x11/xcb-util-wm
|
||||
sources:
|
||||
- https://github.com/swaywm/sway
|
||||
- https://github.com/swaywm/wlroots
|
||||
tasks:
|
||||
- fixup_epoll: |
|
||||
cat << 'EOF' | sudo tee /usr/local/libdata/pkgconfig/epoll-shim.pc
|
||||
prefix=/usr/local
|
||||
exec_prefix=\$\{\$prefix\}
|
||||
libdir=${prefix}/lib
|
||||
sharedlibdir=${prefix}/lib
|
||||
includedir=${prefix}/include/libepoll-shim
|
||||
Name: epoll-shim
|
||||
Description: epoll shim implemented using kevent
|
||||
Version: 0
|
||||
Requires:
|
||||
Libs: -L${libdir} -L${sharedlibdir} -lepoll-shim
|
||||
Libs.private: -pthread -lrt
|
||||
Cflags: -I${includedir}
|
||||
EOF
|
||||
- setup: |
|
||||
cd sway
|
||||
mkdir subprojects
|
||||
cd subprojects
|
||||
ln -s ../../wlroots wlroots
|
||||
cd ..
|
||||
meson build
|
||||
- build: |
|
||||
cd sway
|
||||
ninja -C build
|
||||
70
README.es.md
Normal file
70
README.es.md
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
# sway
|
||||
|
||||
[**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--) - [Українська](https://github.com/swaywm/sway/blob/master/README.uk.md#sway--) - [Italiano](https://github.com/swaywm/sway/blob/master/README.it.md#sway--) - [Português](https://github.com/swaywm/sway/blob/master/README.pt.md#sway--) -
|
||||
[Русский](https://github.com/swaywm/sway/blob/master/README.ru.md#sway--) - [Български](https://github.com/swaywm/sway/blob/master/README.bg.md#sway--) - [Español](https://github.com/swaywm/sway/blob/master/README.es.md#sway--)
|
||||
|
||||
sway es un compositor de [Wayland](http://wayland.freedesktop.org/) compatible con i3.
|
||||
Lea el [FAQ](https://github.com/swaywm/sway/wiki). Únase al [canal de IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on
|
||||
irc.freenode.net).
|
||||
|
||||
Si quiere apoyar el desarrollo de sway, por favor, contribuya en [la página de Patreon de SirCmpwn](https://patreon.com/sircmpwn).
|
||||
|
||||
## Firmas de las versiones
|
||||
|
||||
Las distintas versiones están firmadas con [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A)
|
||||
y publicadas [en GitHub](https://github.com/swaywm/sway/releases).
|
||||
|
||||
## Instalación
|
||||
|
||||
### Usando paquetes
|
||||
|
||||
Sway está disponible en muchas distribuciones. Pruebe instalando el paquete "sway" desde la suya.
|
||||
Si no está disponible, puede consultar [esta documentación](https://github.com/swaywm/sway/wiki/Unsupported-packages)
|
||||
y así obtener información acerca de como instalarlo.
|
||||
|
||||
Si está interesado en crear un paquete para su distribución, únase al canal de IRC o
|
||||
escriba un email a sir@cmpwn.com
|
||||
|
||||
### Compilando el código fuente
|
||||
|
||||
Instale las dependencias:
|
||||
|
||||
* meson \*
|
||||
* [wlroots](https://github.com/swaywm/wlroots)
|
||||
* wayland
|
||||
* wayland-protocols \*
|
||||
* pcre
|
||||
* json-c
|
||||
* pango
|
||||
* cairo
|
||||
* gdk-pixbuf2 \*\*
|
||||
* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) >= 1.8.1 (optional: man pages) \*
|
||||
* git \*
|
||||
|
||||
_\*Compile-time dep_
|
||||
|
||||
_\*\*opcional: necesario para swaybg_
|
||||
|
||||
Desde su consola, ejecute las órdenes:
|
||||
|
||||
meson build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
En sistemas sin `logind`, necesitará cambiar los permisos del archivo compilado de sway:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
Sway abandonará los permisos de super-usuario al poco de arrancar.
|
||||
|
||||
## Configuración
|
||||
|
||||
Si ya utiliza i3, copie su archivo de configuración de i3 a `~/.config/sway/config` y
|
||||
sway funcionará sin tener que configurar nada más. En otro caso, copie el archivo de
|
||||
configuración básico a `~/.config/sway/config`, normalmente se encuentra en `/etc/sway/config`.
|
||||
Ejecute `man 5 sway` para obtener información sobre la configuración.
|
||||
|
||||
## Ejecución
|
||||
|
||||
Ejecute `sway` desde su consola. Algunos gestores de pantalla pueden funcionar sin estar
|
||||
soportados por `sway` (sabemos que gdm funciona bastante bien).
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
# sway
|
||||
|
||||
[**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--) - [Українська](https://github.com/swaywm/sway/blob/master/README.uk.md#sway--) - [Indonesian](https://github.com/swaywm/sway/blob/master/README.id.md#sway--) - [Italiano](https://github.com/swaywm/sway/blob/master/README.it.md#sway--) - [Português](https://github.com/swaywm/sway/blob/master/README.pt.md#sway--) -
|
||||
[Русский](https://github.com/swaywm/sway/blob/master/README.ru.md#sway--) - [Български](https://github.com/swaywm/sway/blob/master/README.bg.md#sway--)
|
||||
[Русский](https://github.com/swaywm/sway/blob/master/README.ru.md#sway--) - [Български](https://github.com/swaywm/sway/blob/master/README.bg.md#sway--) - [Español](https://github.com/swaywm/sway/blob/master/README.es.md#sway--) -
|
||||
[Polski](https://github.com/swaywm/sway/blob/master/README.pl.md#sway--)
|
||||
|
||||
|
||||
sway is an i3-compatible [Wayland](http://wayland.freedesktop.org/) compositor.
|
||||
Read the [FAQ](https://github.com/swaywm/sway/wiki). Join the [IRC
|
||||
|
|
|
|||
71
README.pl.md
Normal file
71
README.pl.md
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
# sway
|
||||
|
||||
[**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--) - [Українська](https://github.com/swaywm/sway/blob/master/README.uk.md#sway--) - [Italiano](https://github.com/swaywm/sway/blob/master/README.it.md#sway--) - [Português](https://github.com/swaywm/sway/blob/master/README.pt.md#sway--) -
|
||||
[Русский](https://github.com/swaywm/sway/blob/master/README.ru.md#sway--) - [Български](https://github.com/swaywm/sway/blob/master/README.bg.md#sway--) - [Español](https://github.com/swaywm/sway/blob/master/README.es.md#sway--) -
|
||||
[Polski](https://github.com/swaywm/sway/blob/master/README.pl.md#sway--)
|
||||
|
||||
sway jest kompozytorem [Wayland](http://wayland.freedesktop.org/) kompatybilnym z i3.
|
||||
Przeczytaj [FAQ](https://github.com/swaywm/sway/wiki). Dołącz do [kanału IRC](http://webchat.freenode.net/?channels=sway&uio=d4)
|
||||
(#sway na irc.freenode.net).
|
||||
|
||||
Jeśli chcesz wesprzeć rozwój sway, rozważ wsparcie SirCmpwn na jego [stronie Patreon](https://patreon.com/sircmpwn).
|
||||
|
||||
## Podpisy cyfrowe wydań
|
||||
|
||||
Wydania są podpisywane przy pomocy klucza [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A)
|
||||
i publikowane [na GitHubie](https://github.com/swaywm/sway/releases).
|
||||
|
||||
## Instalacja
|
||||
|
||||
### Z pakietów
|
||||
|
||||
Sway jest dostępny w wielu dystybucjach. Spróbuj zainstalować pakiet "sway" w swoim
|
||||
menedżerze pakietów. Jeśli nie jest dostępny, sprawdź [tę stronę wiki](https://github.com/swaywm/sway/wiki/Unsupported-packages)
|
||||
aby uzyskać informacje dotyczące instalacji w swojej dystrybucji.
|
||||
|
||||
Jeśli chciałbyś stworzyć pakiet sway dla swojej dystrybucji, odwiedź kanał IRC lub wyślij email na
|
||||
adres sir@cmpwn.com w celu uzyskania wskazówek.
|
||||
|
||||
### Kompilacja ze Źródła
|
||||
|
||||
Zainstaluj zależności:
|
||||
|
||||
* meson \*
|
||||
* [wlroots](https://github.com/swaywm/wlroots)
|
||||
* wayland
|
||||
* wayland-protocols \*
|
||||
* pcre
|
||||
* json-c
|
||||
* pango
|
||||
* cairo
|
||||
* gdk-pixbuf2 \*\*
|
||||
* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) >= 1.8.1 (opcjonalnie: strony pomocy man) \*
|
||||
* git \*
|
||||
|
||||
_\*zależności kompilacji_
|
||||
|
||||
_\*\*opcjonalnie: wymagane dla swaybg_
|
||||
|
||||
Wykonaj następujące polecenia:
|
||||
|
||||
meson build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
Na systemach bez logind należy wykonać polecenie suid na pliku wykonywalnym sway:
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
Sway pozbędzie się uprawnień roota tuż po wystartowaniu.
|
||||
|
||||
## Konfiguracja
|
||||
|
||||
Jeśli już korzystasz z i3, skopiuj swoją konfigurację i3 do katalogu `~/.config/sway/config` i
|
||||
zadziała od ręki. W przeciwnym razie skopiuj przykładowy plik konfiguracyjny do folderu
|
||||
`~/.config/sway/config`; zazwyczaj znajduje się w `/etc/sway/config`.
|
||||
Wykonaj polecenie `man 5 sway` aby uzyskać informacje dotyczące konfiguracji.
|
||||
|
||||
## Uruchamianie
|
||||
|
||||
Wykonaj polecenie `sway` z poziomu TTY. Niektóre menedżery wyświetlania mogą umożliwiać rozruch z ich
|
||||
poziomu, ale nie jest to wspierane przez sway (w gdm podobno działa to całkiem nieźle).
|
||||
|
|
@ -112,7 +112,6 @@ sway_cmd cmd_client_placeholder;
|
|||
sway_cmd cmd_client_background;
|
||||
sway_cmd cmd_commands;
|
||||
sway_cmd cmd_create_output;
|
||||
sway_cmd cmd_debuglog;
|
||||
sway_cmd cmd_default_border;
|
||||
sway_cmd cmd_default_floating_border;
|
||||
sway_cmd cmd_default_orientation;
|
||||
|
|
|
|||
|
|
@ -586,6 +586,8 @@ struct output_config *store_output_config(struct output_config *oc);
|
|||
|
||||
void apply_output_config_to_outputs(struct output_config *oc);
|
||||
|
||||
void reset_outputs(void);
|
||||
|
||||
void free_output_config(struct output_config *oc);
|
||||
|
||||
int workspace_output_cmp_workspace(const void *a, const void *b);
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat);
|
|||
* This chooses a cursor icon and sends a motion event to the surface.
|
||||
*/
|
||||
void cursor_rebase(struct sway_cursor *cursor);
|
||||
void cursor_rebase_all(void);
|
||||
|
||||
void cursor_handle_activity(struct sway_cursor *cursor);
|
||||
void cursor_unhide(struct sway_cursor *cursor);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ struct sway_output {
|
|||
struct sway_node node;
|
||||
struct wlr_output *wlr_output;
|
||||
struct sway_server *server;
|
||||
struct wl_list link;
|
||||
|
||||
struct wl_list layers[4]; // sway_layer_surface::link
|
||||
struct wlr_box usable_area;
|
||||
|
|
@ -36,6 +37,8 @@ struct sway_output {
|
|||
|
||||
struct sway_output_state current;
|
||||
|
||||
struct wl_client *swaybg_client;
|
||||
|
||||
struct wl_listener destroy;
|
||||
struct wl_listener mode;
|
||||
struct wl_listener transform;
|
||||
|
|
@ -43,10 +46,7 @@ struct sway_output {
|
|||
struct wl_listener present;
|
||||
struct wl_listener damage_destroy;
|
||||
struct wl_listener damage_frame;
|
||||
|
||||
struct wl_list link;
|
||||
|
||||
pid_t bg_pid;
|
||||
struct wl_listener swaybg_client_destroy;
|
||||
|
||||
struct {
|
||||
struct wl_signal destroy;
|
||||
|
|
|
|||
|
|
@ -67,11 +67,13 @@ struct sway_workspace *workspace_by_number(const char* name);
|
|||
|
||||
struct sway_workspace *workspace_by_name(const char*);
|
||||
|
||||
struct sway_workspace *workspace_output_next(struct sway_workspace *current);
|
||||
struct sway_workspace *workspace_output_next(
|
||||
struct sway_workspace *current, bool create);
|
||||
|
||||
struct sway_workspace *workspace_next(struct sway_workspace *current);
|
||||
|
||||
struct sway_workspace *workspace_output_prev(struct sway_workspace *current);
|
||||
struct sway_workspace *workspace_output_prev(
|
||||
struct sway_workspace *current, bool create);
|
||||
|
||||
struct sway_workspace *workspace_prev(struct sway_workspace *current);
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ struct swaybar {
|
|||
#if HAVE_TRAY
|
||||
struct swaybar_tray *tray;
|
||||
#endif
|
||||
|
||||
bool running;
|
||||
};
|
||||
|
||||
struct swaybar_output {
|
||||
|
|
|
|||
17
meson.build
17
meson.build
|
|
@ -60,7 +60,11 @@ rt = cc.find_library('rt')
|
|||
git = find_program('git', required: false)
|
||||
|
||||
# Try first to find wlroots as a subproject, then as a system dependency
|
||||
wlroots_proj = subproject('wlroots', required: false)
|
||||
wlroots_proj = subproject(
|
||||
'wlroots',
|
||||
default_options: ['rootston=false', 'examples=false'],
|
||||
required: false,
|
||||
)
|
||||
if wlroots_proj.found()
|
||||
wlroots = wlroots_proj.get_variable('wlroots')
|
||||
wlroots_conf = wlroots_proj.get_variable('conf_data')
|
||||
|
|
@ -128,12 +132,13 @@ endif
|
|||
|
||||
add_project_arguments('-DSYSCONFDIR="/@0@"'.format(join_paths(prefix, sysconfdir)), language : 'c')
|
||||
|
||||
version = '"@0@"'.format(meson.project_version())
|
||||
if git.found()
|
||||
git_commit_hash = run_command([git.path(), 'describe', '--always', '--tags']).stdout().strip()
|
||||
git_branch = run_command([git.path(), 'rev-parse', '--abbrev-ref', 'HEAD']).stdout().strip()
|
||||
version = '"@0@ (" __DATE__ ", branch \'@1@\')"'.format(git_commit_hash, git_branch)
|
||||
else
|
||||
version = '"@0@"'.format(meson.project_version())
|
||||
git_commit_hash = run_command([git.path(), 'describe', '--always', '--tags'])
|
||||
git_branch = run_command([git.path(), 'rev-parse', '--abbrev-ref', 'HEAD'])
|
||||
if git_commit_hash.returncode() == 0 and git_branch.returncode() == 0
|
||||
version = '"@0@ (" __DATE__ ", branch \'@1@\')"'.format(git_commit_hash.stdout().strip(), git_branch.stdout().strip())
|
||||
endif
|
||||
endif
|
||||
add_project_arguments('-DSWAY_VERSION=@0@'.format(version), language: 'c')
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ static struct cmd_results *bar_set_mode(struct bar_config *bar, const char *mode
|
|||
if (strcasecmp("toggle", mode) == 0 && !config->reading) {
|
||||
if (strcasecmp("dock", bar->mode) == 0) {
|
||||
bar->mode = strdup("hide");
|
||||
} else if (strcasecmp("hide", bar->mode) == 0) {
|
||||
} else{
|
||||
bar->mode = strdup("dock");
|
||||
}
|
||||
} else if (strcasecmp("dock", mode) == 0) {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <libevdev/libevdev.h>
|
||||
#include <linux/input-event-codes.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <xkbcommon/xkbcommon-names.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <xkbcommon/xkbcommon-names.h>
|
||||
#include <wlr/types/wlr_cursor.h>
|
||||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
#include "sway/input/cursor.h"
|
||||
|
|
@ -330,7 +331,20 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) {
|
|||
void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) {
|
||||
sway_log(SWAY_DEBUG, "running command for binding: %s", binding->command);
|
||||
|
||||
list_t *res_list = execute_command(binding->command, seat, NULL);
|
||||
struct sway_container *con = NULL;
|
||||
if (binding->type == BINDING_MOUSESYM
|
||||
|| binding->type == BINDING_MOUSECODE) {
|
||||
struct wlr_surface *surface = NULL;
|
||||
double sx, sy;
|
||||
struct sway_node *node = node_at_coords(seat,
|
||||
seat->cursor->cursor->x, seat->cursor->cursor->y,
|
||||
&surface, &sx, &sy);
|
||||
if (node && node->type == N_CONTAINER) {
|
||||
con = node->sway_container;
|
||||
}
|
||||
}
|
||||
|
||||
list_t *res_list = execute_command(binding->command, seat, con);
|
||||
bool success = true;
|
||||
for (int i = 0; i < res_list->length; ++i) {
|
||||
struct cmd_results *results = res_list->items[i];
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ static struct sway_node *get_node_in_output_direction(
|
|||
struct sway_output *output, enum wlr_direction dir) {
|
||||
struct sway_seat *seat = config->handler_context.seat;
|
||||
struct sway_workspace *ws = output_get_active_workspace(output);
|
||||
if (!sway_assert(ws, "Expected output to have a workspace")) {
|
||||
return NULL;
|
||||
}
|
||||
if (ws->fullscreen) {
|
||||
return seat_get_focus_inactive(seat, &ws->fullscreen->node);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,10 +111,8 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
|
|||
"Unable to change layout of floating windows");
|
||||
}
|
||||
|
||||
// Typically we change the layout of the current container, but if the
|
||||
// current container is a view (it usually is) then we'll change the layout
|
||||
// of the parent instead, as it doesn't make sense for views to have layout.
|
||||
if (container && container->view) {
|
||||
// Operate on parent container, like i3.
|
||||
if (container) {
|
||||
container = container->parent;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -283,6 +283,9 @@ static bool container_move_in_direction(struct sway_container *container,
|
|||
return false;
|
||||
}
|
||||
struct sway_workspace *ws = output_get_active_workspace(new_output);
|
||||
if (!sway_assert(ws, "Expected output to have a workspace")) {
|
||||
return false;
|
||||
}
|
||||
container_move_to_workspace(container, ws);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -360,6 +363,9 @@ static bool container_move_in_direction(struct sway_container *container,
|
|||
output_get_in_direction(container->workspace->output, move_dir);
|
||||
if (output) {
|
||||
struct sway_workspace *ws = output_get_active_workspace(output);
|
||||
if (!sway_assert(ws, "Expected output to have a workspace")) {
|
||||
return false;
|
||||
}
|
||||
container_move_to_workspace_from_direction(container, ws, move_dir);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -516,7 +522,6 @@ static struct cmd_results *cmd_move_container(int argc, char **argv) {
|
|||
|
||||
// move container
|
||||
if (container->scratchpad) {
|
||||
root_scratchpad_remove_container(container);
|
||||
root_scratchpad_show(container);
|
||||
}
|
||||
switch (destination->type) {
|
||||
|
|
@ -526,6 +531,10 @@ static struct cmd_results *cmd_move_container(int argc, char **argv) {
|
|||
case N_OUTPUT: {
|
||||
struct sway_output *output = destination->sway_output;
|
||||
struct sway_workspace *ws = output_get_active_workspace(output);
|
||||
if (!sway_assert(ws, "Expected output to have a workspace")) {
|
||||
return cmd_results_new(CMD_FAILURE,
|
||||
"Expected output to have a workspace");
|
||||
}
|
||||
container_move_to_workspace(container, ws);
|
||||
}
|
||||
break;
|
||||
|
|
@ -539,6 +548,10 @@ static struct cmd_results *cmd_move_container(int argc, char **argv) {
|
|||
// restore focus on destination output back to its last active workspace
|
||||
struct sway_workspace *new_workspace =
|
||||
output_get_active_workspace(new_output);
|
||||
if (!sway_assert(new_workspace, "Expected output to have a workspace")) {
|
||||
return cmd_results_new(CMD_FAILURE,
|
||||
"Expected output to have a workspace");
|
||||
}
|
||||
if (new_output_last_ws && new_output_last_ws != new_workspace) {
|
||||
struct sway_node *new_output_last_focus =
|
||||
seat_get_focus_inactive(seat, &new_output_last_ws->node);
|
||||
|
|
@ -586,6 +599,9 @@ static void workspace_move_to_output(struct sway_workspace *workspace,
|
|||
workspace_detach(workspace);
|
||||
struct sway_workspace *new_output_old_ws =
|
||||
output_get_active_workspace(output);
|
||||
if (!sway_assert(new_output_old_ws, "Expected output to have a workspace")) {
|
||||
return;
|
||||
}
|
||||
|
||||
output_add_workspace(output, workspace);
|
||||
|
||||
|
|
@ -838,11 +854,11 @@ static struct cmd_results *cmd_move_to_scratchpad(void) {
|
|||
}
|
||||
}
|
||||
|
||||
if (con->scratchpad) {
|
||||
return cmd_results_new(CMD_INVALID,
|
||||
"Container is already in the scratchpad");
|
||||
if (!con->scratchpad) {
|
||||
root_scratchpad_add_container(con);
|
||||
} else if (con->workspace) {
|
||||
root_scratchpad_hide(con);
|
||||
}
|
||||
root_scratchpad_add_container(con);
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,5 +50,5 @@ struct cmd_results *cmd_seat(int argc, char **argv) {
|
|||
}
|
||||
|
||||
config->handler_context.seat_config = NULL;
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
return res ? res : cmd_results_new(CMD_SUCCESS, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ static struct cmd_results *press_or_release(struct sway_cursor *cursor,
|
|||
|
||||
static const char expected_syntax[] = "Expected 'cursor <move> <x> <y>' or "
|
||||
"'cursor <set> <x> <y>' or "
|
||||
"'curor <press|release> <button[1-9]|event-name-or-code>'";
|
||||
"'cursor <press|release> <button[1-9]|event-name-or-code>'";
|
||||
|
||||
static struct cmd_results *handle_command(struct sway_cursor *cursor,
|
||||
int argc, char **argv) {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "sway/tree/view.h"
|
||||
#include "sway/tree/workspace.h"
|
||||
#include "list.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
|
||||
struct cmd_results *cmd_sticky(int argc, char **argv) {
|
||||
|
|
@ -29,6 +30,11 @@ struct cmd_results *cmd_sticky(int argc, char **argv) {
|
|||
// move container to active workspace
|
||||
struct sway_workspace *active_workspace =
|
||||
output_get_active_workspace(container->workspace->output);
|
||||
if (!sway_assert(active_workspace,
|
||||
"Expected output to have a workspace")) {
|
||||
return cmd_results_new(CMD_FAILURE,
|
||||
"Expected output to have a workspace");
|
||||
}
|
||||
if (container->workspace != active_workspace) {
|
||||
struct sway_workspace *old_workspace = container->workspace;
|
||||
container_detach(container);
|
||||
|
|
|
|||
|
|
@ -118,6 +118,10 @@ static void container_swap(struct sway_container *con1,
|
|||
output_get_active_workspace(con1->workspace->output);
|
||||
struct sway_workspace *vis2 =
|
||||
output_get_active_workspace(con2->workspace->output);
|
||||
if (!sway_assert(vis1 && vis2, "con1 or con2 are on an output without a"
|
||||
"workspace. This should not happen")) {
|
||||
return;
|
||||
}
|
||||
|
||||
char *stored_prev_name = NULL;
|
||||
if (seat->prev_workspace_name) {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,12 @@ struct cmd_results *cmd_titlebar_border_thickness(int argc, char **argv) {
|
|||
|
||||
for (int i = 0; i < root->outputs->length; ++i) {
|
||||
struct sway_output *output = root->outputs->items[i];
|
||||
arrange_workspace(output_get_active_workspace(output));
|
||||
struct sway_workspace *ws = output_get_active_workspace(output);
|
||||
if (!sway_assert(ws, "Expected output to have a workspace")) {
|
||||
return cmd_results_new(CMD_FAILURE,
|
||||
"Expected output to have a workspace");
|
||||
}
|
||||
arrange_workspace(ws);
|
||||
output_damage_whole(output);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -181,7 +181,9 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
|
|||
++argv;
|
||||
}
|
||||
|
||||
|
||||
bool create = argc > 1 && strcasecmp(argv[1], "--create") == 0;
|
||||
struct sway_seat *seat = config->handler_context.seat;
|
||||
struct sway_workspace *current = seat_get_focused_workspace(seat);
|
||||
struct sway_workspace *ws = NULL;
|
||||
if (strcasecmp(argv[0], "number") == 0) {
|
||||
if (argc < 2) {
|
||||
|
|
@ -199,12 +201,13 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
|
|||
}
|
||||
} else if (strcasecmp(argv[0], "next") == 0 ||
|
||||
strcasecmp(argv[0], "prev") == 0 ||
|
||||
strcasecmp(argv[0], "next_on_output") == 0 ||
|
||||
strcasecmp(argv[0], "prev_on_output") == 0 ||
|
||||
strcasecmp(argv[0], "current") == 0) {
|
||||
ws = workspace_by_name(argv[0]);
|
||||
} else if (strcasecmp(argv[0], "next_on_output") == 0) {
|
||||
ws = workspace_output_next(current, create);
|
||||
} else if (strcasecmp(argv[0], "prev_on_output") == 0) {
|
||||
ws = workspace_output_prev(current, create);
|
||||
} else if (strcasecmp(argv[0], "back_and_forth") == 0) {
|
||||
struct sway_seat *seat = config->handler_context.seat;
|
||||
if (!seat->prev_workspace_name) {
|
||||
return cmd_results_new(CMD_INVALID,
|
||||
"There is no previous workspace");
|
||||
|
|
@ -220,7 +223,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
|
|||
free(name);
|
||||
}
|
||||
workspace_switch(ws, no_auto_back_and_forth);
|
||||
seat_consider_warp_to_focus(config->handler_context.seat);
|
||||
seat_consider_warp_to_focus(seat);
|
||||
}
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ void free_config(struct sway_config *config) {
|
|||
}
|
||||
list_free(config->no_focus);
|
||||
list_free(config->active_bar_modifiers);
|
||||
list_free(config->config_chain);
|
||||
list_free_items_and_destroy(config->config_chain);
|
||||
list_free(config->command_policies);
|
||||
list_free(config->feature_policies);
|
||||
list_free(config->ipc_policies);
|
||||
|
|
@ -471,9 +471,8 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
|
|||
}
|
||||
|
||||
if (is_active) {
|
||||
for (int i = 0; i < config->output_configs->length; i++) {
|
||||
apply_output_config_to_outputs(config->output_configs->items[i]);
|
||||
}
|
||||
reset_outputs();
|
||||
|
||||
config->reloading = false;
|
||||
if (config->swaynag_config_errors.pid > 0) {
|
||||
swaynag_show(&config->swaynag_config_errors);
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ void free_bar_config(struct bar_config *bar) {
|
|||
free(bar->position);
|
||||
free(bar->hidden_state);
|
||||
free(bar->status_command);
|
||||
free(bar->swaybar_command);
|
||||
free(bar->font);
|
||||
free(bar->separator_symbol);
|
||||
for (int i = 0; i < bar->bindings->length; i++) {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,17 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
#include <wlr/types/wlr_output_layout.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
#include "log.h"
|
||||
#include "sway/config.h"
|
||||
#include "sway/output.h"
|
||||
#include "sway/tree/root.h"
|
||||
#include "log.h"
|
||||
|
||||
int output_name_cmp(const void *item, const void *data) {
|
||||
const struct output_config *output = item;
|
||||
|
|
@ -165,14 +166,89 @@ static bool set_mode(struct wlr_output *output, int width, int height,
|
|||
return wlr_output_set_mode(output, best);
|
||||
}
|
||||
|
||||
void terminate_swaybg(pid_t pid) {
|
||||
int ret = kill(pid, SIGTERM);
|
||||
if (ret != 0) {
|
||||
sway_log(SWAY_ERROR, "Unable to terminate swaybg [pid: %d]", pid);
|
||||
} else {
|
||||
int status;
|
||||
waitpid(pid, &status, 0);
|
||||
static void handle_swaybg_client_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct sway_output *output =
|
||||
wl_container_of(listener, output, swaybg_client_destroy);
|
||||
wl_list_remove(&output->swaybg_client_destroy.link);
|
||||
wl_list_init(&output->swaybg_client_destroy.link);
|
||||
output->swaybg_client = NULL;
|
||||
}
|
||||
|
||||
static bool set_cloexec(int fd, bool cloexec) {
|
||||
int flags = fcntl(fd, F_GETFD);
|
||||
if (flags == -1) {
|
||||
sway_log_errno(SWAY_ERROR, "fcntl failed");
|
||||
return false;
|
||||
}
|
||||
if (cloexec) {
|
||||
flags = flags | FD_CLOEXEC;
|
||||
} else {
|
||||
flags = flags & ~FD_CLOEXEC;
|
||||
}
|
||||
if (fcntl(fd, F_SETFD, flags) == -1) {
|
||||
sway_log_errno(SWAY_ERROR, "fcntl failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool spawn_swaybg(struct sway_output *output, char *const cmd[]) {
|
||||
int sockets[2];
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) != 0) {
|
||||
sway_log_errno(SWAY_ERROR, "socketpair failed");
|
||||
return false;
|
||||
}
|
||||
if (!set_cloexec(sockets[0], true) || !set_cloexec(sockets[1], true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
output->swaybg_client = wl_client_create(server.wl_display, sockets[0]);
|
||||
if (output->swaybg_client == NULL) {
|
||||
sway_log_errno(SWAY_ERROR, "wl_client_create failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
output->swaybg_client_destroy.notify = handle_swaybg_client_destroy;
|
||||
wl_client_add_destroy_listener(output->swaybg_client,
|
||||
&output->swaybg_client_destroy);
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||
return false;
|
||||
} else if (pid == 0) {
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (pid == 0) {
|
||||
if (!set_cloexec(sockets[1], false)) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char wayland_socket_str[16];
|
||||
snprintf(wayland_socket_str, sizeof(wayland_socket_str),
|
||||
"%d", sockets[1]);
|
||||
setenv("WAYLAND_SOCKET", wayland_socket_str, true);
|
||||
|
||||
execvp(cmd[0], cmd);
|
||||
sway_log_errno(SWAY_ERROR, "execvp failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (close(sockets[1]) != 0) {
|
||||
sway_log_errno(SWAY_ERROR, "close failed");
|
||||
return false;
|
||||
}
|
||||
if (waitpid(pid, NULL, 0) < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "waitpid failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool apply_output_config(struct output_config *oc, struct sway_output *output) {
|
||||
|
|
@ -199,6 +275,11 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (oc && oc->dpms_state == DPMS_ON) {
|
||||
sway_log(SWAY_DEBUG, "Turning on screen");
|
||||
wlr_output_enable(wlr_output, true);
|
||||
}
|
||||
|
||||
bool modeset_success;
|
||||
if (oc && oc->width > 0 && oc->height > 0) {
|
||||
sway_log(SWAY_DEBUG, "Set %s mode to %dx%d (%f GHz)", oc->name, oc->width,
|
||||
|
|
@ -238,8 +319,8 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) {
|
|||
wlr_output_layout_add_auto(root->output_layout, wlr_output);
|
||||
}
|
||||
|
||||
if (output->bg_pid != 0) {
|
||||
terminate_swaybg(output->bg_pid);
|
||||
if (output->swaybg_client != NULL) {
|
||||
wl_client_destroy(output->swaybg_client);
|
||||
}
|
||||
if (oc && oc->background && config->swaybg_command) {
|
||||
sway_log(SWAY_DEBUG, "Setting background for output %s to %s",
|
||||
|
|
@ -253,29 +334,14 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) {
|
|||
oc->background_fallback ? oc->background_fallback : NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
output->bg_pid = fork();
|
||||
if (output->bg_pid < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||
} else if (output->bg_pid == 0) {
|
||||
execvp(cmd[0], cmd);
|
||||
sway_log_errno(SWAY_ERROR, "Failed to execute swaybg");
|
||||
if (!spawn_swaybg(output, cmd)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (oc) {
|
||||
switch (oc->dpms_state) {
|
||||
case DPMS_ON:
|
||||
sway_log(SWAY_DEBUG, "Turning on screen");
|
||||
wlr_output_enable(wlr_output, true);
|
||||
break;
|
||||
case DPMS_OFF:
|
||||
sway_log(SWAY_DEBUG, "Turning off screen");
|
||||
wlr_output_enable(wlr_output, false);
|
||||
break;
|
||||
case DPMS_IGNORE:
|
||||
break;
|
||||
}
|
||||
if (oc && oc->dpms_state == DPMS_OFF) {
|
||||
sway_log(SWAY_DEBUG, "Turning off screen");
|
||||
wlr_output_enable(wlr_output, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -294,6 +360,7 @@ static void default_output_config(struct output_config *oc,
|
|||
oc->x = oc->y = -1;
|
||||
oc->scale = 1;
|
||||
oc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
oc->dpms_state = DPMS_ON;
|
||||
}
|
||||
|
||||
static struct output_config *get_output_config(char *identifier,
|
||||
|
|
@ -395,6 +462,17 @@ void apply_output_config_to_outputs(struct output_config *oc) {
|
|||
}
|
||||
}
|
||||
|
||||
void reset_outputs(void) {
|
||||
struct output_config *oc = NULL;
|
||||
int i = list_seq_find(config->output_configs, output_name_cmp, "*");
|
||||
if (i >= 0) {
|
||||
oc = config->output_configs->items[i];
|
||||
} else {
|
||||
oc = store_output_config(new_output_config("*"));
|
||||
}
|
||||
apply_output_config_to_outputs(oc);
|
||||
}
|
||||
|
||||
void free_output_config(struct output_config *oc) {
|
||||
if (!oc) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@
|
|||
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||
#include <wlr/types/wlr_output_damage.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
#include "log.h"
|
||||
#include "sway/desktop/transaction.h"
|
||||
#include "sway/input/cursor.h"
|
||||
#include "sway/input/input-manager.h"
|
||||
#include "sway/input/seat.h"
|
||||
#include "sway/layers.h"
|
||||
|
|
@ -14,7 +16,6 @@
|
|||
#include "sway/server.h"
|
||||
#include "sway/tree/arrange.h"
|
||||
#include "sway/tree/workspace.h"
|
||||
#include "log.h"
|
||||
|
||||
static void apply_exclusive(struct wlr_box *usable_area,
|
||||
uint32_t anchor, int32_t exclusive,
|
||||
|
|
@ -302,6 +303,8 @@ static void unmap(struct sway_layer_surface *sway_layer) {
|
|||
if (seat->focused_layer == sway_layer->layer_surface) {
|
||||
seat_set_focus_layer(seat, NULL);
|
||||
}
|
||||
|
||||
cursor_rebase_all();
|
||||
}
|
||||
|
||||
static void handle_destroy(struct wl_listener *listener, void *data) {
|
||||
|
|
@ -321,7 +324,6 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
|
|||
struct sway_output *output = sway_layer->layer_surface->output->data;
|
||||
if (output != NULL) {
|
||||
arrange_layers(output);
|
||||
arrange_output(output);
|
||||
transaction_commit_dirty();
|
||||
}
|
||||
wl_list_remove(&sway_layer->output_destroy.link);
|
||||
|
|
@ -339,6 +341,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
|
|||
// TODO: send enter to subsurfaces and popups
|
||||
wlr_surface_send_enter(sway_layer->layer_surface->surface,
|
||||
sway_layer->layer_surface->output);
|
||||
cursor_rebase_all();
|
||||
}
|
||||
|
||||
static void handle_unmap(struct wl_listener *listener, void *data) {
|
||||
|
|
|
|||
|
|
@ -251,6 +251,9 @@ static void output_for_each_surface(struct sway_output *output,
|
|||
};
|
||||
|
||||
struct sway_workspace *workspace = output_get_active_workspace(output);
|
||||
if (!workspace) {
|
||||
return;
|
||||
}
|
||||
struct sway_container *fullscreen_con = root->fullscreen_global;
|
||||
if (fullscreen_con && container_is_scratchpad_hidden(fullscreen_con)) {
|
||||
fullscreen_con = NULL;
|
||||
|
|
@ -320,6 +323,9 @@ struct sway_workspace *output_get_active_workspace(struct sway_output *output) {
|
|||
struct sway_seat *seat = input_manager_current_seat();
|
||||
struct sway_node *focus = seat_get_active_tiling_child(seat, &output->node);
|
||||
if (!focus) {
|
||||
if (!output->workspaces->length) {
|
||||
return NULL;
|
||||
}
|
||||
return output->workspaces->items[0];
|
||||
}
|
||||
return focus->sway_workspace;
|
||||
|
|
@ -506,6 +512,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
|
|||
wl_list_remove(&output->present.link);
|
||||
wl_list_remove(&output->damage_destroy.link);
|
||||
wl_list_remove(&output->damage_frame.link);
|
||||
wl_list_remove(&output->swaybg_client_destroy.link);
|
||||
|
||||
transaction_commit_dirty();
|
||||
}
|
||||
|
|
@ -612,6 +619,7 @@ void handle_new_output(struct wl_listener *listener, void *data) {
|
|||
output->damage_frame.notify = damage_handle_frame;
|
||||
wl_signal_add(&output->damage->events.destroy, &output->damage_destroy);
|
||||
output->damage_destroy.notify = damage_handle_destroy;
|
||||
wl_list_init(&output->swaybg_client_destroy.link);
|
||||
|
||||
struct output_config *oc = output_find_config(output);
|
||||
if (!oc || oc->enabled) {
|
||||
|
|
|
|||
|
|
@ -314,14 +314,7 @@ static void transaction_apply(struct sway_transaction *transaction) {
|
|||
node->instruction = NULL;
|
||||
}
|
||||
|
||||
if (root->outputs->length) {
|
||||
struct sway_seat *seat;
|
||||
wl_list_for_each(seat, &server.input->seats, link) {
|
||||
if (!seat_doing_seatop(seat)) {
|
||||
cursor_rebase(seat->cursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
cursor_rebase_all();
|
||||
}
|
||||
|
||||
static void transaction_commit(struct sway_transaction *transaction);
|
||||
|
|
|
|||
|
|
@ -104,6 +104,9 @@ struct sway_node *node_at_coords(
|
|||
|
||||
// find the focused workspace on the output for this seat
|
||||
struct sway_workspace *ws = output_get_active_workspace(output);
|
||||
if (!ws) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((*surface = layer_surface_at(output,
|
||||
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
|
||||
|
|
@ -283,6 +286,19 @@ void cursor_rebase(struct sway_cursor *cursor) {
|
|||
cursor_do_rebase(cursor, time_msec, cursor->previous.node, surface, sx, sy);
|
||||
}
|
||||
|
||||
void cursor_rebase_all(void) {
|
||||
if (!root->outputs->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct sway_seat *seat;
|
||||
wl_list_for_each(seat, &server.input->seats, link) {
|
||||
if (!seat_doing_seatop(seat)) {
|
||||
cursor_rebase(seat->cursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int hide_notify(void *data) {
|
||||
struct sway_cursor *cursor = data;
|
||||
wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0);
|
||||
|
|
@ -408,15 +424,16 @@ static void handle_cursor_motion(struct wl_listener *listener, void *data) {
|
|||
|
||||
wlr_relative_pointer_manager_v1_send_relative_motion(
|
||||
server.relative_pointer_manager,
|
||||
cursor->seat->wlr_seat, event->time_msec, dx, dy,
|
||||
dx_unaccel, dy_unaccel);
|
||||
cursor->seat->wlr_seat, (uint64_t)event->time_msec * 1000,
|
||||
dx, dy, dx_unaccel, dy_unaccel);
|
||||
|
||||
struct wlr_surface *surface = NULL;
|
||||
struct sway_node *node = NULL;
|
||||
double sx, sy;
|
||||
struct sway_node *node = node_at_coords(cursor->seat,
|
||||
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
|
||||
|
||||
if (cursor->active_constraint) {
|
||||
node = node_at_coords(cursor->seat,
|
||||
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
|
||||
|
||||
if (cursor->active_constraint->surface != surface) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -432,8 +449,13 @@ static void handle_cursor_motion(struct wl_listener *listener, void *data) {
|
|||
}
|
||||
|
||||
wlr_cursor_move(cursor->cursor, event->device, dx, dy);
|
||||
|
||||
// Recalculate pointer location after layout checks
|
||||
node = node_at_coords(cursor->seat,
|
||||
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
|
||||
|
||||
cursor_send_pointer_motion(cursor, event->time_msec, node, surface,
|
||||
sx + dx, sy + dy);
|
||||
sx, sy);
|
||||
transaction_commit_dirty();
|
||||
}
|
||||
|
||||
|
|
@ -530,10 +552,11 @@ static void state_add_button(struct sway_cursor *cursor, uint32_t button) {
|
|||
static struct sway_binding* get_active_mouse_binding(
|
||||
const struct sway_cursor *cursor, list_t *bindings, uint32_t modifiers,
|
||||
bool release, bool on_titlebar, bool on_border, bool on_content,
|
||||
const char *identifier) {
|
||||
uint32_t click_region = (on_titlebar ? BINDING_TITLEBAR : 0) |
|
||||
(on_border ? BINDING_BORDER : 0) |
|
||||
(on_content ? BINDING_CONTENTS : 0);
|
||||
bool on_workspace, const char *identifier) {
|
||||
uint32_t click_region =
|
||||
((on_titlebar || on_workspace) ? BINDING_TITLEBAR : 0) |
|
||||
((on_border || on_workspace) ? BINDING_BORDER : 0) |
|
||||
((on_content || on_workspace) ? BINDING_CONTENTS : 0);
|
||||
|
||||
struct sway_binding *current = NULL;
|
||||
for (int i = 0; i < bindings->length; ++i) {
|
||||
|
|
@ -542,6 +565,8 @@ static struct sway_binding* get_active_mouse_binding(
|
|||
cursor->pressed_button_count != (size_t)binding->keys->length ||
|
||||
release != (binding->flags & BINDING_RELEASE) ||
|
||||
!(click_region & binding->flags) ||
|
||||
(on_workspace &&
|
||||
(click_region & binding->flags) != click_region) ||
|
||||
(strcmp(binding->input, identifier) != 0 &&
|
||||
strcmp(binding->input, "*") != 0)) {
|
||||
continue;
|
||||
|
|
@ -607,6 +632,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
|
|||
find_resize_edge(cont, cursor) : WLR_EDGE_NONE;
|
||||
bool on_border = edge != WLR_EDGE_NONE;
|
||||
bool on_contents = cont && !on_border && surface;
|
||||
bool on_workspace = node && node->type == N_WORKSPACE;
|
||||
bool on_titlebar = cont && !on_border && !surface;
|
||||
|
||||
// Handle mouse bindings
|
||||
|
|
@ -620,11 +646,13 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
|
|||
state_add_button(cursor, button);
|
||||
binding = get_active_mouse_binding(cursor,
|
||||
config->current_mode->mouse_bindings, modifiers, false,
|
||||
on_titlebar, on_border, on_contents, device_identifier);
|
||||
on_titlebar, on_border, on_contents, on_workspace,
|
||||
device_identifier);
|
||||
} else {
|
||||
binding = get_active_mouse_binding(cursor,
|
||||
config->current_mode->mouse_bindings, modifiers, true,
|
||||
on_titlebar, on_border, on_contents, device_identifier);
|
||||
on_titlebar, on_border, on_contents, on_workspace,
|
||||
device_identifier);
|
||||
state_erase_button(cursor, button);
|
||||
}
|
||||
free(device_identifier);
|
||||
|
|
@ -814,6 +842,7 @@ void dispatch_cursor_axis(struct sway_cursor *cursor,
|
|||
bool on_titlebar_border = cont && on_border &&
|
||||
cursor->cursor->y < cont->content_y;
|
||||
bool on_contents = cont && !on_border && surface;
|
||||
bool on_workspace = node && node->type == N_WORKSPACE;
|
||||
float scroll_factor =
|
||||
(ic == NULL || ic->scroll_factor == FLT_MIN) ? 1.0f : ic->scroll_factor;
|
||||
|
||||
|
|
@ -832,7 +861,7 @@ void dispatch_cursor_axis(struct sway_cursor *cursor,
|
|||
state_add_button(cursor, button);
|
||||
binding = get_active_mouse_binding(cursor,
|
||||
config->current_mode->mouse_bindings, modifiers, false,
|
||||
on_titlebar, on_border, on_contents, dev_id);
|
||||
on_titlebar, on_border, on_contents, on_workspace, dev_id);
|
||||
if (binding) {
|
||||
seat_execute_command(seat, binding);
|
||||
handled = true;
|
||||
|
|
@ -873,7 +902,7 @@ void dispatch_cursor_axis(struct sway_cursor *cursor,
|
|||
// Handle mouse bindings - x11 mouse buttons 4-7 - release event
|
||||
binding = get_active_mouse_binding(cursor,
|
||||
config->current_mode->mouse_bindings, modifiers, true,
|
||||
on_titlebar, on_border, on_contents, dev_id);
|
||||
on_titlebar, on_border, on_contents, on_workspace, dev_id);
|
||||
state_erase_button(cursor, button);
|
||||
if (binding) {
|
||||
seat_execute_command(seat, binding);
|
||||
|
|
|
|||
|
|
@ -549,13 +549,17 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) {
|
|||
wlr_keyboard_led_update(wlr_device->keyboard, leds);
|
||||
}
|
||||
|
||||
if (input_config && input_config->repeat_delay != INT_MIN
|
||||
&& input_config->repeat_rate != INT_MIN) {
|
||||
wlr_keyboard_set_repeat_info(wlr_device->keyboard,
|
||||
input_config->repeat_rate, input_config->repeat_delay);
|
||||
} else {
|
||||
wlr_keyboard_set_repeat_info(wlr_device->keyboard, 25, 600);
|
||||
int repeat_rate = 25;
|
||||
if (input_config && input_config->repeat_rate != INT_MIN) {
|
||||
repeat_rate = input_config->repeat_rate;
|
||||
}
|
||||
int repeat_delay = 600;
|
||||
if (input_config && input_config->repeat_delay != INT_MIN) {
|
||||
repeat_delay = input_config->repeat_delay;
|
||||
}
|
||||
wlr_keyboard_set_repeat_info(wlr_device->keyboard, repeat_rate,
|
||||
repeat_delay);
|
||||
|
||||
xkb_context_unref(context);
|
||||
struct wlr_seat *seat = keyboard->seat_device->sway_seat->wlr_seat;
|
||||
wlr_seat_set_keyboard(seat, wlr_device);
|
||||
|
|
|
|||
|
|
@ -287,6 +287,7 @@ static void drag_icon_handle_destroy(struct wl_listener *listener, void *data) {
|
|||
wl_list_remove(&icon->link);
|
||||
wl_list_remove(&icon->surface_commit.link);
|
||||
wl_list_remove(&icon->unmap.link);
|
||||
wl_list_remove(&icon->map.link);
|
||||
wl_list_remove(&icon->destroy.link);
|
||||
free(icon);
|
||||
}
|
||||
|
|
@ -725,6 +726,10 @@ void seat_set_raw_focus(struct sway_seat *seat, struct sway_node *node) {
|
|||
|
||||
void seat_set_focus(struct sway_seat *seat, struct sway_node *node) {
|
||||
if (seat->focused_layer) {
|
||||
struct wlr_layer_surface_v1 *layer = seat->focused_layer;
|
||||
seat_set_focus_layer(seat, NULL);
|
||||
seat_set_focus(seat, node);
|
||||
seat_set_focus_layer(seat, layer);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,9 @@ static void handle_motion_postthreshold(struct sway_seat *seat) {
|
|||
}
|
||||
if (edge) {
|
||||
e->target_node = node_get_parent(&con->node);
|
||||
if (e->target_node == &e->con->node) {
|
||||
e->target_node = node_get_parent(e->target_node);
|
||||
}
|
||||
e->target_edge = edge;
|
||||
node_get_box(e->target_node, &e->drop_box);
|
||||
resize_box(&e->drop_box, edge, DROP_LAYOUT_BORDER);
|
||||
|
|
@ -161,7 +164,8 @@ static void handle_motion_postthreshold(struct sway_seat *seat) {
|
|||
|
||||
// Use the hovered view - but we must be over the actual surface
|
||||
con = node->sway_container;
|
||||
if (!con->view->surface || node == &e->con->node) {
|
||||
if (!con->view->surface || node == &e->con->node
|
||||
|| node_has_ancestor(node, &e->con->node)) {
|
||||
e->target_node = NULL;
|
||||
e->target_edge = WLR_EDGE_NONE;
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -198,6 +198,9 @@ static void ipc_json_describe_output(struct sway_output *output,
|
|||
ipc_json_output_transform_description(wlr_output->transform)));
|
||||
|
||||
struct sway_workspace *ws = output_get_active_workspace(output);
|
||||
if (!sway_assert(ws, "Expected output to have a workspace")) {
|
||||
return;
|
||||
}
|
||||
json_object_object_add(object, "current_workspace",
|
||||
json_object_new_string(ws->name));
|
||||
|
||||
|
|
@ -344,6 +347,9 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object
|
|||
json_object_object_add(object, "app_id",
|
||||
app_id ? json_object_new_string(app_id) : NULL);
|
||||
|
||||
bool visible = view_is_visible(c->view);
|
||||
json_object_object_add(object, "visible", json_object_new_boolean(visible));
|
||||
|
||||
json_object *marks = json_object_new_array();
|
||||
list_t *con_marks = c->marks;
|
||||
for (int i = 0; i < con_marks->length; ++i) {
|
||||
|
|
@ -597,7 +603,7 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) {
|
|||
const char *layout =
|
||||
xkb_keymap_layout_get_name(keymap, layout_idx);
|
||||
json_object_object_add(object, "xkb_active_layout_name",
|
||||
json_object_new_string(layout));
|
||||
layout ? json_object_new_string(layout) : NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
10
sway/main.c
10
sway/main.c
|
|
@ -126,6 +126,7 @@ void run_as_ipc_client(char *command, char *socket_path) {
|
|||
uint32_t len = strlen(command);
|
||||
char *resp = ipc_single_command(socketfd, IPC_COMMAND, command, &len);
|
||||
printf("%s\n", resp);
|
||||
free(resp);
|
||||
close(socketfd);
|
||||
}
|
||||
|
||||
|
|
@ -299,6 +300,14 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
// Since wayland requires XDG_RUNTIME_DIR to be set, abort with just the
|
||||
// clear error message (when not running as an IPC client).
|
||||
if (!getenv("XDG_RUNTIME_DIR") && optind == argc) {
|
||||
fprintf(stderr,
|
||||
"XDG_RUNTIME_DIR is not set in the environment. Aborting.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// As the 'callback' function for wlr_log is equivalent to that for
|
||||
// sway, we do not need to override it.
|
||||
if (debug) {
|
||||
|
|
@ -339,6 +348,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
char *command = join_args(argv + optind, argc - optind);
|
||||
run_as_ipc_client(command, socket_path);
|
||||
free(command);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,13 +10,14 @@
|
|||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/types/wlr_data_control_v1.h>
|
||||
#include <wlr/types/wlr_export_dmabuf_v1.h>
|
||||
#include <wlr/types/wlr_gamma_control.h>
|
||||
#include <wlr/types/wlr_gamma_control_v1.h>
|
||||
#include <wlr/types/wlr_gamma_control.h>
|
||||
#include <wlr/types/wlr_gtk_primary_selection.h>
|
||||
#include <wlr/types/wlr_idle.h>
|
||||
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||
#include <wlr/types/wlr_relative_pointer_v1.h>
|
||||
#include <wlr/types/wlr_pointer_constraints_v1.h>
|
||||
#include <wlr/types/wlr_primary_selection_v1.h>
|
||||
#include <wlr/types/wlr_relative_pointer_v1.h>
|
||||
#include <wlr/types/wlr_screencopy_v1.h>
|
||||
#include <wlr/types/wlr_server_decoration.h>
|
||||
#include <wlr/types/wlr_xcursor_manager.h>
|
||||
|
|
@ -122,6 +123,7 @@ bool server_init(struct sway_server *server) {
|
|||
wlr_export_dmabuf_manager_v1_create(server->wl_display);
|
||||
wlr_screencopy_manager_v1_create(server->wl_display);
|
||||
wlr_data_control_manager_v1_create(server->wl_display);
|
||||
wlr_primary_selection_v1_device_manager_create(server->wl_display);
|
||||
|
||||
server->socket = wl_display_add_socket_auto(server->wl_display);
|
||||
if (!server->socket) {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,13 @@ sway-input - input configuration file and commands
|
|||
|
||||
Sway allows for configuration of devices within the sway configuration file.
|
||||
To obtain a list of available device identifiers, run *swaymsg -t get_inputs*.
|
||||
Settings can also be applied to all input devices by using the wildcard, _\*_,
|
||||
in place of _\<identifier\>_ in the commands below.
|
||||
|
||||
Tip: If the configuration settings do not appear to be taking effect, you could
|
||||
try using _\*_ instead of _\<identifier\>_. If it works with the wildcard, try
|
||||
using a different identifier from *swaymsg -t get_inputs* until you find the
|
||||
correct input device.
|
||||
|
||||
# INPUT COMMANDS
|
||||
|
||||
|
|
@ -144,7 +151,13 @@ configured. While sway is running, _-_ (hyphen) can be used as an alias for the
|
|||
current seat. Each seat has an independent keyboard focus and a separate cursor
|
||||
that is controlled by the pointer devices of the seat. This is useful for
|
||||
multiple people using the desktop at the same time with their own devices (each
|
||||
sitting in their own "seat").
|
||||
sitting in their own "seat"). The wildcard character, _\*_, can also be used in
|
||||
place of _\<identifier\>_ to change settings for all seats.
|
||||
|
||||
Tip: If the configuration settings do not appear to be taking effect, you could
|
||||
try using _\*_ instead of _\<identifier\>_. If it works with the wildcard, try
|
||||
using a different identifier from *swaymsg -t get_seats* until you find the
|
||||
correct seat.
|
||||
|
||||
*seat* <name> attach <input_identifier>
|
||||
Attach an input device to this seat by its input identifier. A special
|
||||
|
|
|
|||
|
|
@ -293,12 +293,13 @@ runtime.
|
|||
overwrite a binding, swaynag will give you a warning. To silence this, use
|
||||
the _--no-warn_ flag.
|
||||
|
||||
Mouse buttons can either be specified in the form _button[1-9]_ or by using
|
||||
the name of the event code (ex _BTN\_LEFT_ or _BTN\_RIGHT_). For the former
|
||||
option, the buttons will be mapped to their values in X11 (1=left, 2=middle,
|
||||
3=right, 4=scroll up, 5=scroll down, 6=scroll left, 7=scroll right, 8=back,
|
||||
9=forward). For the latter option, you can find the event names using
|
||||
_libinput debug-events_.
|
||||
Mouse bindings operate on the container under the cursor instead of the
|
||||
container that has focus. Mouse buttons can either be specified in the form
|
||||
_button[1-9]_ or by using the name of the event code (ex _BTN\_LEFT_ or
|
||||
_BTN\_RIGHT_). For the former option, the buttons will be mapped to their
|
||||
values in X11 (1=left, 2=middle, 3=right, 4=scroll up, 5=scroll down,
|
||||
6=scroll left, 7=scroll right, 8=back, 9=forward). For the latter option,
|
||||
you can find the event names using _libinput debug-events_.
|
||||
|
||||
_--whole-window_, _--border_, and _--exclude-titlebar_ are mouse-only options
|
||||
which affect the region in which the mouse bindings can be triggered. By
|
||||
|
|
@ -309,9 +310,9 @@ runtime.
|
|||
conjunction with any other option to specify that the titlebar should be
|
||||
excluded from the region of consideration.
|
||||
|
||||
There is currently, however, no way to execute a mouse binding over a layer
|
||||
surface (which includes the background of an empty workspace). This behaviour
|
||||
is carried over from i3.
|
||||
If _--whole-window_ is given, the command can be triggered when the cursor
|
||||
is over an empty workspace. Using a mouse binding over a layer surface's
|
||||
exclusive region is not currently possible.
|
||||
|
||||
Example:
|
||||
```
|
||||
|
|
@ -413,10 +414,6 @@ The default colors are:
|
|||
: #0c0c0c
|
||||
|
||||
|
||||
*debuglog* on|off|toggle
|
||||
Enables, disables or toggles debug logging. _toggle_ cannot be used in the
|
||||
configuration file.
|
||||
|
||||
*default_border* normal|none|pixel [<n>]
|
||||
Set default border style for new tiled windows.
|
||||
|
||||
|
|
|
|||
|
|
@ -251,10 +251,12 @@ static struct sway_container *container_at_stacked(struct sway_node *parent,
|
|||
|
||||
// Title bars
|
||||
int title_height = container_titlebar_height();
|
||||
int child_index = (ly - box.y) / title_height;
|
||||
if (child_index < children->length) {
|
||||
struct sway_container *child = children->items[child_index];
|
||||
return child;
|
||||
if (title_height > 0) {
|
||||
int child_index = (ly - box.y) / title_height;
|
||||
if (child_index < children->length) {
|
||||
struct sway_container *child = children->items[child_index];
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
||||
// Surfaces
|
||||
|
|
@ -829,7 +831,7 @@ void container_floating_move_to(struct sway_container *con,
|
|||
}
|
||||
struct sway_workspace *new_workspace =
|
||||
output_get_active_workspace(new_output);
|
||||
if (old_workspace != new_workspace) {
|
||||
if (new_workspace && old_workspace != new_workspace) {
|
||||
container_detach(con);
|
||||
workspace_add_floating(new_workspace, con);
|
||||
arrange_workspace(old_workspace);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
#include "sway/layers.h"
|
||||
#include "sway/output.h"
|
||||
#include "sway/tree/arrange.h"
|
||||
#include "sway/tree/output.h"
|
||||
#include "sway/tree/workspace.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
|
|
@ -144,6 +143,9 @@ void output_enable(struct sway_output *output, struct output_config *oc) {
|
|||
static void evacuate_sticky(struct sway_workspace *old_ws,
|
||||
struct sway_output *new_output) {
|
||||
struct sway_workspace *new_ws = output_get_active_workspace(new_output);
|
||||
if (!sway_assert(new_ws, "New output does not have a workspace")) {
|
||||
return;
|
||||
}
|
||||
while (old_ws->floating->length) {
|
||||
struct sway_container *sticky = old_ws->floating->items[0];
|
||||
container_detach(sticky);
|
||||
|
|
@ -190,10 +192,19 @@ static void output_evacuate(struct sway_output *output) {
|
|||
continue;
|
||||
}
|
||||
|
||||
struct sway_workspace *new_output_ws =
|
||||
output_get_active_workspace(new_output);
|
||||
|
||||
workspace_output_add_priority(workspace, new_output);
|
||||
output_add_workspace(new_output, workspace);
|
||||
output_sort_workspaces(new_output);
|
||||
ipc_event_workspace(NULL, workspace, "move");
|
||||
|
||||
// If there is an old workspace (the noop output may not have one),
|
||||
// check to see if it is empty and should be destroyed.
|
||||
if (new_output_ws) {
|
||||
workspace_consider_destroy(new_output_ws);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -234,9 +245,8 @@ void output_disable(struct sway_output *output) {
|
|||
|
||||
root_for_each_container(untrack_output, output);
|
||||
|
||||
if (output->bg_pid) {
|
||||
terminate_swaybg(output->bg_pid);
|
||||
output->bg_pid = 0;
|
||||
if (output->swaybg_client != NULL) {
|
||||
wl_client_destroy(output->swaybg_client);
|
||||
}
|
||||
|
||||
int index = list_find(root->outputs, output);
|
||||
|
|
|
|||
|
|
@ -664,6 +664,13 @@ void view_unmap(struct sway_view *view) {
|
|||
struct sway_seat *seat;
|
||||
wl_list_for_each(seat, &server.input->seats, link) {
|
||||
seat->cursor->image_surface = NULL;
|
||||
if (seat->cursor->active_constraint) {
|
||||
struct wlr_surface *constrain_surface =
|
||||
seat->cursor->active_constraint->surface;
|
||||
if (view_from_wlr_surface(constrain_surface) == view) {
|
||||
sway_cursor_constrain(seat->cursor, NULL);
|
||||
}
|
||||
}
|
||||
seat_consider_warp_to_focus(seat);
|
||||
}
|
||||
|
||||
|
|
@ -701,6 +708,9 @@ static void subsurface_get_root_coords(struct sway_view_child *child,
|
|||
while (surface && wlr_surface_is_subsurface(surface)) {
|
||||
struct wlr_subsurface *subsurface =
|
||||
wlr_subsurface_from_wlr_surface(surface);
|
||||
if (subsurface == NULL) {
|
||||
break;
|
||||
}
|
||||
*root_sx += subsurface->current.x;
|
||||
*root_sy += subsurface->current.y;
|
||||
surface = subsurface->parent;
|
||||
|
|
|
|||
|
|
@ -42,10 +42,16 @@ struct sway_output *workspace_get_initial_output(const char *name) {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Otherwise put it on the focused output
|
||||
// Otherwise try to put it on the focused output
|
||||
struct sway_seat *seat = input_manager_current_seat();
|
||||
struct sway_workspace *focus = seat_get_focused_workspace(seat);
|
||||
return focus->output;
|
||||
struct sway_node *focus = seat_get_focus_inactive(seat, &root->node);
|
||||
if (focus && focus->type == N_WORKSPACE) {
|
||||
return focus->sway_workspace->output;
|
||||
} else if (focus && focus->type == N_CONTAINER) {
|
||||
return focus->sway_container->workspace->output;
|
||||
}
|
||||
// Fallback to the first output or noop output for headless
|
||||
return root->outputs->length ? root->outputs->items[0] : root->noop_output;
|
||||
}
|
||||
|
||||
static void prevent_invalid_outer_gaps(struct sway_workspace *ws) {
|
||||
|
|
@ -224,8 +230,10 @@ static void workspace_name_from_binding(const struct sway_binding * binding,
|
|||
// not a command about workspaces
|
||||
if (strcmp(_target, "next") == 0 ||
|
||||
strcmp(_target, "prev") == 0 ||
|
||||
strcmp(_target, "next_on_output") == 0 ||
|
||||
strcmp(_target, "prev_on_output") == 0 ||
|
||||
strncmp(_target, "next_on_output",
|
||||
strlen("next_on_output")) == 0 ||
|
||||
strncmp(_target, "prev_on_output",
|
||||
strlen("next_on_output")) == 0 ||
|
||||
strcmp(_target, "number") == 0 ||
|
||||
strcmp(_target, "back_and_forth") == 0 ||
|
||||
strcmp(_target, "current") == 0) {
|
||||
|
|
@ -328,16 +336,13 @@ char *workspace_next_name(const char *output_name) {
|
|||
if (target != NULL) {
|
||||
return target;
|
||||
}
|
||||
// As a fall back, get the current number of active workspaces
|
||||
// and return that + 1 for the next workspace's name
|
||||
int ws_num = root->outputs->length;
|
||||
int l = snprintf(NULL, 0, "%d", ws_num);
|
||||
char *name = malloc(l + 1);
|
||||
if (!sway_assert(name, "Could not allocate workspace name")) {
|
||||
return NULL;
|
||||
}
|
||||
sprintf(name, "%d", ws_num++);
|
||||
return name;
|
||||
// As a fall back, use the next available number
|
||||
char name[12] = "";
|
||||
unsigned int ws_num = 1;
|
||||
do {
|
||||
snprintf(name, sizeof(name), "%u", ws_num++);
|
||||
} while (workspace_by_number(name));
|
||||
return strdup(name);
|
||||
}
|
||||
|
||||
static bool _workspace_by_number(struct sway_workspace *ws, void *data) {
|
||||
|
|
@ -366,11 +371,11 @@ struct sway_workspace *workspace_by_name(const char *name) {
|
|||
if (strcmp(name, "prev") == 0) {
|
||||
return workspace_prev(current);
|
||||
} else if (strcmp(name, "prev_on_output") == 0) {
|
||||
return workspace_output_prev(current);
|
||||
return workspace_output_prev(current, false);
|
||||
} else if (strcmp(name, "next") == 0) {
|
||||
return workspace_next(current);
|
||||
} else if (strcmp(name, "next_on_output") == 0) {
|
||||
return workspace_output_next(current);
|
||||
return workspace_output_next(current, false);
|
||||
} else if (strcmp(name, "current") == 0) {
|
||||
return current;
|
||||
} else if (strcasecmp(name, "back_and_forth") == 0) {
|
||||
|
|
@ -391,11 +396,18 @@ struct sway_workspace *workspace_by_name(const char *name) {
|
|||
* otherwise the next one is returned.
|
||||
*/
|
||||
static struct sway_workspace *workspace_output_prev_next_impl(
|
||||
struct sway_output *output, int dir) {
|
||||
struct sway_output *output, int dir, bool create) {
|
||||
struct sway_seat *seat = input_manager_current_seat();
|
||||
struct sway_workspace *workspace = seat_get_focused_workspace(seat);
|
||||
|
||||
int index = list_find(output->workspaces, workspace);
|
||||
if (!workspace_is_empty(workspace) && create &&
|
||||
(index + dir < 0 || index + dir == output->workspaces->length)) {
|
||||
struct sway_output *output = workspace->output;
|
||||
char *next = workspace_next_name(output->wlr_output->name);
|
||||
workspace_create(output, next);
|
||||
free(next);
|
||||
}
|
||||
size_t new_index = wrap(index + dir, output->workspaces->length);
|
||||
return output->workspaces->items[new_index];
|
||||
}
|
||||
|
|
@ -426,16 +438,18 @@ static struct sway_workspace *workspace_prev_next_impl(
|
|||
}
|
||||
}
|
||||
|
||||
struct sway_workspace *workspace_output_next(struct sway_workspace *current) {
|
||||
return workspace_output_prev_next_impl(current->output, 1);
|
||||
struct sway_workspace *workspace_output_next(
|
||||
struct sway_workspace *current, bool create) {
|
||||
return workspace_output_prev_next_impl(current->output, 1, create);
|
||||
}
|
||||
|
||||
struct sway_workspace *workspace_next(struct sway_workspace *current) {
|
||||
return workspace_prev_next_impl(current, 1);
|
||||
}
|
||||
|
||||
struct sway_workspace *workspace_output_prev(struct sway_workspace *current) {
|
||||
return workspace_output_prev_next_impl(current->output, -1);
|
||||
struct sway_workspace *workspace_output_prev(
|
||||
struct sway_workspace *current, bool create) {
|
||||
return workspace_output_prev_next_impl(current->output, -1, create);
|
||||
}
|
||||
|
||||
struct sway_workspace *workspace_prev(struct sway_workspace *current) {
|
||||
|
|
@ -445,9 +459,15 @@ struct sway_workspace *workspace_prev(struct sway_workspace *current) {
|
|||
bool workspace_switch(struct sway_workspace *workspace,
|
||||
bool no_auto_back_and_forth) {
|
||||
struct sway_seat *seat = input_manager_current_seat();
|
||||
struct sway_workspace *active_ws = seat_get_focused_workspace(seat);
|
||||
struct sway_workspace *active_ws = NULL;
|
||||
struct sway_node *focus = seat_get_focus_inactive(seat, &root->node);
|
||||
if (focus && focus->type == N_WORKSPACE) {
|
||||
active_ws = focus->sway_workspace;
|
||||
} else if (focus && focus->type == N_CONTAINER) {
|
||||
active_ws = focus->sway_container->workspace;
|
||||
}
|
||||
|
||||
if (!no_auto_back_and_forth && config->auto_back_and_forth
|
||||
if (!no_auto_back_and_forth && config->auto_back_and_forth && active_ws
|
||||
&& active_ws == workspace && seat->prev_workspace_name) {
|
||||
struct sway_workspace *new_ws =
|
||||
workspace_by_name(seat->prev_workspace_name);
|
||||
|
|
@ -456,9 +476,9 @@ bool workspace_switch(struct sway_workspace *workspace,
|
|||
workspace_create(NULL, seat->prev_workspace_name);
|
||||
}
|
||||
|
||||
if (!seat->prev_workspace_name ||
|
||||
if (active_ws && (!seat->prev_workspace_name ||
|
||||
(strcmp(seat->prev_workspace_name, active_ws->name)
|
||||
&& active_ws != workspace)) {
|
||||
&& active_ws != workspace))) {
|
||||
free(seat->prev_workspace_name);
|
||||
seat->prev_workspace_name = malloc(strlen(active_ws->name) + 1);
|
||||
if (!seat->prev_workspace_name) {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/wait.h>
|
||||
|
|
@ -403,8 +404,7 @@ bool bar_setup(struct swaybar *bar, const char *socket_path) {
|
|||
static void display_in(int fd, short mask, void *data) {
|
||||
struct swaybar *bar = data;
|
||||
if (wl_display_dispatch(bar->display) == -1) {
|
||||
bar_teardown(bar);
|
||||
exit(0);
|
||||
bar->running = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -439,7 +439,7 @@ void bar_run(struct swaybar *bar) {
|
|||
loop_add_fd(bar->eventloop, bar->tray->fd, POLLIN, tray_in, bar->tray->bus);
|
||||
}
|
||||
#endif
|
||||
while (1) {
|
||||
while (bar->running) {
|
||||
errno = 0;
|
||||
if (wl_display_flush(bar->display) == -1 && errno != EAGAIN) {
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -11,13 +11,7 @@
|
|||
static struct swaybar swaybar;
|
||||
|
||||
void sig_handler(int signal) {
|
||||
bar_teardown(&swaybar);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void sway_terminate(int code) {
|
||||
bar_teardown(&swaybar);
|
||||
exit(code);
|
||||
swaybar.running = false;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
|
@ -93,8 +87,6 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
signal(SIGTERM, sig_handler);
|
||||
|
||||
if (!bar_setup(&swaybar, socket_path)) {
|
||||
free(socket_path);
|
||||
return 1;
|
||||
|
|
@ -102,6 +94,10 @@ int main(int argc, char **argv) {
|
|||
|
||||
free(socket_path);
|
||||
|
||||
signal(SIGINT, sig_handler);
|
||||
signal(SIGTERM, sig_handler);
|
||||
|
||||
swaybar.running = true;
|
||||
bar_run(&swaybar);
|
||||
bar_teardown(&swaybar);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -189,9 +189,9 @@ bool init_host(struct swaybar_host *host, char *protocol,
|
|||
goto error;
|
||||
}
|
||||
|
||||
sd_bus_slot_set_floating(reg_slot, 1);
|
||||
sd_bus_slot_set_floating(unreg_slot, 1);
|
||||
sd_bus_slot_set_floating(watcher_slot, 1);
|
||||
sd_bus_slot_set_floating(reg_slot, 0);
|
||||
sd_bus_slot_set_floating(unreg_slot, 0);
|
||||
sd_bus_slot_set_floating(watcher_slot, 0);
|
||||
|
||||
sway_log(SWAY_DEBUG, "Registered %s", host->service);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -299,6 +299,8 @@ void destroy_sni(struct swaybar_sni *sni) {
|
|||
return;
|
||||
}
|
||||
|
||||
cairo_surface_destroy(sni->icon);
|
||||
|
||||
sd_bus_slot_unref(sni->new_icon_slot);
|
||||
sd_bus_slot_unref(sni->new_attention_icon_slot);
|
||||
sd_bus_slot_unref(sni->new_status_slot);
|
||||
|
|
@ -308,9 +310,11 @@ void destroy_sni(struct swaybar_sni *sni) {
|
|||
free(sni->path);
|
||||
free(sni->status);
|
||||
free(sni->icon_name);
|
||||
free(sni->icon_pixmap);
|
||||
list_free_items_and_destroy(sni->icon_pixmap);
|
||||
free(sni->attention_icon_name);
|
||||
list_free_items_and_destroy(sni->attention_icon_pixmap);
|
||||
free(sni->menu);
|
||||
free(sni->icon_theme_path);
|
||||
free(sni);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,10 +18,6 @@ static int cmp_id(const void *item, const void *cmp_to) {
|
|||
return strcmp(item, cmp_to);
|
||||
}
|
||||
|
||||
static int cmp_service(const void *item, const void *cmp_to) {
|
||||
return strncmp(item, cmp_to, strlen(cmp_to));
|
||||
}
|
||||
|
||||
static int handle_lost_service(sd_bus_message *msg,
|
||||
void *data, sd_bus_error *error) {
|
||||
char *service, *old_owner, *new_owner;
|
||||
|
|
@ -33,18 +29,23 @@ static int handle_lost_service(sd_bus_message *msg,
|
|||
|
||||
if (!*new_owner) {
|
||||
struct swaybar_watcher *watcher = data;
|
||||
int idx = list_seq_find(watcher->items,
|
||||
using_standard_protocol(watcher) ? cmp_id : cmp_service, service);
|
||||
if (idx != -1) {
|
||||
for (int idx = 0; idx < watcher->items->length; ++idx) {
|
||||
char *id = watcher->items->items[idx];
|
||||
sway_log(SWAY_DEBUG, "Unregistering Status Notifier Item '%s'", id);
|
||||
list_del(watcher->items, idx);
|
||||
sd_bus_emit_signal(watcher->bus, obj_path, watcher->interface,
|
||||
"StatusNotifierItemUnregistered", "s", id);
|
||||
free(id);
|
||||
int cmp_res = using_standard_protocol(watcher) ?
|
||||
cmp_id(id, service) : strncmp(id, service, strlen(service));
|
||||
if (cmp_res == 0) {
|
||||
sway_log(SWAY_DEBUG, "Unregistering Status Notifier Item '%s'", id);
|
||||
list_del(watcher->items, idx--);
|
||||
sd_bus_emit_signal(watcher->bus, obj_path, watcher->interface,
|
||||
"StatusNotifierItemUnregistered", "s", id);
|
||||
free(id);
|
||||
if (using_standard_protocol(watcher)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
idx = list_seq_find(watcher->hosts, cmp_id, service);
|
||||
int idx = list_seq_find(watcher->hosts, cmp_id, service);
|
||||
if (idx != -1) {
|
||||
sway_log(SWAY_DEBUG, "Unregistering Status Notifier Host '%s'", service);
|
||||
free(watcher->hosts->items[idx]);
|
||||
|
|
@ -185,8 +186,8 @@ struct swaybar_watcher *create_watcher(char *protocol, sd_bus *bus) {
|
|||
goto error;
|
||||
}
|
||||
|
||||
sd_bus_slot_set_floating(signal_slot, 1);
|
||||
sd_bus_slot_set_floating(vtable_slot, 1);
|
||||
sd_bus_slot_set_floating(signal_slot, 0);
|
||||
sd_bus_slot_set_floating(vtable_slot, 0);
|
||||
|
||||
watcher->bus = bus;
|
||||
watcher->hosts = create_list();
|
||||
|
|
|
|||
|
|
@ -135,8 +135,8 @@ static void pretty_print_input(json_object *i) {
|
|||
json_object_get_int(vendor));
|
||||
|
||||
if (json_object_object_get_ex(i, "xkb_active_layout_name", &kbdlayout)) {
|
||||
printf(" Active Keyboard Layout: %s\n",
|
||||
json_object_get_string(kbdlayout));
|
||||
const char *layout = json_object_get_string(kbdlayout);
|
||||
printf(" Active Keyboard Layout: %s\n", layout ? layout : "(unnamed)");
|
||||
}
|
||||
|
||||
if (json_object_object_get_ex(i, "libinput_send_events", &events)) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue