Merge branch 'master' into indonesian_translation

This commit is contained in:
Nicholas Sebastian Husin 2019-02-23 01:18:28 -06:00 committed by GitHub
commit 916838cd51
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
50 changed files with 687 additions and 198 deletions

38
.builds/alpine.yml Normal file
View 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

View file

@ -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
View 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
View 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).

View file

@ -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
View 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).

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -46,6 +46,8 @@ struct swaybar {
#if HAVE_TRAY
struct swaybar_tray *tray;
#endif
bool running;
};
struct swaybar_output {

View file

@ -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')

View file

@ -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) {

View file

@ -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];

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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) {

View file

@ -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);

View file

@ -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) {

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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++) {

View file

@ -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;

View file

@ -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) {

View file

@ -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) {

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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) {

View file

@ -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

View file

@ -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.

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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) {

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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);
}

View file

@ -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();

View file

@ -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)) {