This commit is contained in:
kaiserschmarrn_ 2021-05-05 13:12:55 -07:00
commit 5d60ebf743
29 changed files with 367 additions and 223 deletions

View file

@ -6,6 +6,7 @@ packages:
- json-c-dev
- libevdev-dev
- libinput-dev
- libseat-dev
- libxcb-dev
- libxkbcommon-dev
- mesa-dev
@ -16,6 +17,7 @@ packages:
- wayland-dev
- wayland-protocols
- xcb-util-image-dev
- xcb-util-wm-dev
- xwayland
sources:
- https://github.com/swaywm/sway

View file

@ -13,7 +13,9 @@ packages:
- wayland
- wayland-protocols
- xcb-util-image
- xcb-util-wm
- xorg-xwayland
- seatd
sources:
- https://github.com/swaywm/sway
- https://github.com/swaywm/wlroots

View file

@ -19,6 +19,7 @@ packages:
- devel/libudev-devd
- graphics/libdrm
- graphics/mesa-libs
- sysutils/seatd
- x11/libinput
- x11/libX11
- x11/pixman

View file

@ -8,7 +8,6 @@ labels: 'bug'
### Please read the following before submitting:
- Please do NOT submit bug reports for questions. Ask questions on IRC at #sway on irc.freenode.net.
- Proprietary graphics drivers, including nvidia, are not supported. Please use the open source equivalents, such as nouveau, if you would like to use Sway.
- Problems with the Wayland version of Firefox are likely to be Firefox bugs. Start by submitting your issue to the Firefox Bugzilla and come back here only after they confirm otherwise.
- Please do NOT submit issues for information from the github wiki. The github wiki is community maintained and therefore may contain outdated information, scripts that don't work or obsolete workarounds.
If you fix a script or find outdated information, don't hesitate to adjust the wiki page.

77
README.hu.md Normal file
View file

@ -0,0 +1,77 @@
# sway
A Sway egy [i3]-kompatibilis [Wayland] kompozitor. Olvasd el a [Gyarkan Ismételt Kérdéseket][FAQ]. Csatlakozz az [IRC csatornához][IRC channel] \(`#sway` az `irc.freenode.net`-en).
## Csomag aláírások
A kiadott csomagok az [E88F5E48] kulccsal vannak aláírva és [GitHub-on][GitHub releases] publikálva.
## Telepítés
### Csomagból
A Sway sok disztribúció csomagkezelőjéből elérhető, próbáld meg a "sway"
csomagot telepíteni az általad használt eszközzel.
Ha szeretnél csomagot készíteni a saját disztribúciódhoz, ugorj be az IRC
csatornára, vagy küldj levelet a sir@cmpwn.com címre tanácsokért.
### Fordítás forráskódból
Olvasd el [ezt a wiki oldalt][Development setup], ha szeretnéd tesztelési vagy
fejlesztési célokból lefordítani az aktuális (HEAD) állapotát a `sway`-nek és a
`wlroots`-nak.
Telepítsd a függőségeket:
* meson \*
* [wlroots]
* wayland
* wayland-protocols \*
* pcre
* json-c
* pango
* cairo
* gdk-pixbuf2 (opcionális: system tray)
* [scdoc] (opcionális: man pages) \*
* git (opcionális: version info) \*
_\*Fordításidejű függőség_
Futtasd ezeket a parancsokat:
meson build
ninja -C build
sudo ninja -C build install
Ha `logind` nélküli rendszert használsz, akkor be kell állítanod a `suid` bitet
a futtaható állományon:
sudo chmod a+s /usr/local/bin/sway
A Sway indulás után nem sokkal el fogja engedni a root jogosultságait.
## Konfiguráció
Ha előzőleg i3-mat használtál, akkor átmásolhatod az i3 beállításaidat a
`~/.config/sway/config` file-ba és ugyanúgy működni fognak. Egyéb esetben másold
le kiindulási alapnak a mintát, ami általában az `etc/sway/config` elérési
útvonalon található.
Futtasd a `man 5 sway` parancsot további információért a konfigurációval
kapcsolatban.
## Futtatás
Futtasd a `sway` parancsot egy TTY felületről. Néhány bejelentkezéskezelő
(display manager) működhet, de alapvetően nem támogatottak a sway által. (A
gdm-ről ismeretes, hogy egész jól működik.)
[i3]: https://i3wm.org/
[Wayland]: http://wayland.freedesktop.org/
[FAQ]: https://github.com/swaywm/sway/wiki
[IRC channel]: http://webchat.freenode.net/?channels=sway&uio=d4
[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48
[GitHub releases]: https://github.com/swaywm/sway/releases
[Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup
[wlroots]: https://github.com/swaywm/wlroots
[scdoc]: https://git.sr.ht/~sircmpwn/scdoc

View file

@ -1,6 +1,6 @@
# sway
**[English][en]** - [日本語][ja] - [Français][fr] - [Українська][uk] - [Español][es] - [Polski][pl] - [中文-简体][zh-CN] - [Deutsch][de] - [Nederlands][nl] - [Русский][ru] - [中文-繁體][zh-TW] - [Português][pt] - [Danish][dk] - [한국어][ko] - [Română][ro]
**[English][en]** - [日本語][ja] - [Français][fr] - [Українська][uk] - [Español][es] - [Polski][pl] - [中文-简体][zh-CN] - [Deutsch][de] - [Nederlands][nl] - [Русский][ru] - [中文-繁體][zh-TW] - [Português][pt] - [Danish][dk] - [한국어][ko] - [Română][ro] - [Magyar][hu] - [Türkçe][tr]
sway is an [i3]-compatible [Wayland] compositor. Read the [FAQ]. Join the
[IRC channel] \(#sway on irc.freenode.net).
@ -42,9 +42,9 @@ _\*Compile-time dep_
Run these commands:
meson build
ninja -C build
sudo ninja -C build install
meson build/
ninja -C build/
sudo ninja -C build/ install
On systems without logind, you need to suid the sway binary:
@ -79,6 +79,8 @@ sway (gdm is known to work fairly well).
[dk]: https://github.com/swaywm/sway/blob/master/README.dk.md
[ko]: https://github.com/swaywm/sway/blob/master/README.ko.md
[ro]: https://github.com/swaywm/sway/blob/master/README.ro.md
[hu]: https://github.com/swaywm/sway/blob/master/README.hu.md
[tr]: https://github.com/swaywm/sway/blob/master/README.tr.md
[i3]: https://i3wm.org/
[Wayland]: http://wayland.freedesktop.org/
[FAQ]: https://github.com/swaywm/sway/wiki

68
README.tr.md Normal file
View file

@ -0,0 +1,68 @@
# sway
Sway, [i3]-uyumlu bir [Wayland] dizgicisidir. [SSS][FAQ]'yi okuyun.
[IRC kanalı][IRC channel]na katılın \(irc.freenode.net'te #sway (İngilizce)).
## Sürüm imzaları
Sürümler [E88F5E48] ile imzalandı ve [GitHub][GitHub releases]'da yayınlandı.
## Kurulum
### Paketler ile
Sway birçok dağıtımda mevcuttur. Sizinki için "sway" paketini yüklemeyi deneyin.
Dağıtımınız için sway'i paketlemekle ilgileniyorsanız, IRC kanalına uğrayın veya tavsiye için sir@cmpwn.com adresine bir e-posta gönderin.
### Kaynak koddan derleme
Test veya geliştirme için sway ve wlroots'un HEAD'ini oluşturmak istiyorsanız [bu wiki sayfası][Development setup]na göz atın.
Aşağıdaki bağımlılıkları yükleyin:
* meson \*
* [wlroots]
* wayland
* wayland-protocols \*
* pcre
* json-c
* pango
* cairo
* gdk-pixbuf2 (isteğe bağlı: system tray)
* [scdoc] (isteğe bağlı: man pages) \*
* git (isteğe bağlı: version info) \*
_\*Derleme-anı bağımlılıkları_
Şu komutları çalıştırın:
meson build
ninja -C build
sudo ninja -C build install
logind olmayan sistemlerde, sway ikilisine (binary) izin vermeniz (suid) gerekir:
sudo chmod a+s /usr/local/bin/sway
Sway, başlangıçtan kısa bir süre sonra kök(root) izinlerini bırakacaktır.
## Yapılandırma
Zaten i3 kullanıyorsanız, i3 yapılandırmanızı `~/.config/sway/config` konumuna kopyalayın ve kutudan çıktığı gibi çalışacaktır. Aksi takdirde, örnek yapılandırma dosyasını `~/.config/sway/config` konumuna kopyalayın. Genellikle `/etc/sway/config` konumunda bulunur.
Yapılandırma hakkında bilgi almak için `man 5 sway` komutunu çalıştırın.
## Çalıştırma
TTY'den `sway` çalıştırın. Bazı görüntü yöneticileriyle(display manager) çalışabilir ama Sway tarafından desteklenmez. (gdm'nin oldukça iyi çalıştığı bilinmektedir.)
[i3]: https://i3wm.org/
[Wayland]: http://wayland.freedesktop.org/
[FAQ]: https://github.com/swaywm/sway/wiki
[IRC channel]: http://webchat.freenode.net/?channels=sway&uio=d4
[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48
[GitHub releases]: https://github.com/swaywm/sway/releases
[Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup
[wlroots]: https://github.com/swaywm/wlroots
[scdoc]: https://git.sr.ht/~sircmpwn/scdoc

View file

@ -22,24 +22,17 @@ DEFAULT_ICON = "󰀏"
def icon_for_window(window):
app_id = window.app_id
if app_id is not None and len(app_id) > 0:
app_id = app_id.lower()
if app_id in WINDOW_ICONS:
return WINDOW_ICONS[app_id]
logging.info("No icon available for window with app_id: %s" % str(app_id))
else:
# xwayland support
class_name = window.window_class
if len(class_name) > 0:
class_name = class_name.lower()
if class_name in WINDOW_ICONS:
return WINDOW_ICONS[class_name]
logging.info(
"No icon available for window with class_name: %s" % str(class_name)
)
return DEFAULT_ICON
name = None
if window.app_id is not None and len(window.app_id) > 0:
name = window.app_id.lower()
elif window.window_class is not None and len(window.window_class) > 0:
name = window.window_class.lower()
if name in WINDOW_ICONS:
return WINDOW_ICONS[name]
logging.info("No icon available for window with name: %s" % str(name))
return DEFAULT_ICON
def rename_workspaces(ipc):
for workspace in ipc.get_tree().workspaces():
@ -128,3 +121,4 @@ if __name__ == "__main__":
rename_workspaces(ipc)
ipc.main()

View file

@ -72,8 +72,8 @@ struct sway_output *output_get_in_direction(struct sway_output *reference,
void output_add_workspace(struct sway_output *output,
struct sway_workspace *workspace);
typedef void (*sway_surface_iterator_func_t)(struct sway_output *output, struct sway_view *view,
struct wlr_surface *surface, struct wlr_box *box, float rotation,
typedef void (*sway_surface_iterator_func_t)(struct sway_output *output,
struct sway_view *view, struct wlr_surface *surface, struct wlr_box *box,
void *user_data);
void output_damage_whole(struct sway_output *output);

View file

@ -1,7 +1,7 @@
project(
'sway',
'c',
version: '1.6-rc1',
version: '1.6',
license: 'MIT',
meson_version: '>=0.53.0',
default_options: [
@ -61,7 +61,7 @@ math = cc.find_library('m')
rt = cc.find_library('rt')
# Try first to find wlroots as a subproject, then as a system dependency
wlroots_version = ['>=0.12.0', '<0.13.0']
wlroots_version = ['>=0.14.0', '<0.15.0']
wlroots_proj = subproject(
'wlroots',
default_options: ['examples=false'],
@ -76,9 +76,6 @@ endif
wlroots_features = {
'xwayland': false,
'systemd': false,
'elogind': false,
'libseat': false,
}
foreach name, _ : wlroots_features
var_name = 'have_' + name.underscorify()
@ -313,12 +310,7 @@ endif
summary({
'xwayland': have_xwayland,
'gdk-pixbuf': gdk_pixbuf.found(),
'sd-bus': sdbus.found(),
'tray': have_tray,
'man-pages': scdoc.found(),
}, bool_yn: true)
if not wlroots_features['systemd'] and not wlroots_features['elogind'] and not wlroots_features['libseat']
warning('The sway binary must be setuid when compiled without (e)logind or libseat')
warning('You must do this manually post-install: chmod a+s /path/to/sway')
endif

View file

@ -116,6 +116,7 @@ struct cmd_results *cmd_bar(int argc, char **argv) {
if (res && res->status != CMD_SUCCESS) {
if (id) {
free_bar_config(config->current_bar);
config->current_bar = NULL;
id = NULL;
}
return res;

View file

@ -65,8 +65,9 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) {
close(fd[0]);
if ((child = fork()) == 0) {
close(fd[1]);
execl("/bin/sh", "/bin/sh", "-c", cmd, (void *)NULL);
_exit(0);
execlp("sh", "sh", "-c", cmd, (void *)NULL);
sway_log_errno(SWAY_ERROR, "execlp failed");
_exit(1);
}
ssize_t s = 0;
while ((size_t)s < sizeof(pid_t)) {

View file

@ -33,15 +33,7 @@ struct cmd_results *cmd_fullscreen(int argc, char **argv) {
}
}
bool is_fullscreen = false;
for (struct sway_container *curr = container; curr; curr = curr->pending.parent) {
if (curr->pending.fullscreen_mode != FULLSCREEN_NONE) {
container = curr;
is_fullscreen = true;
break;
}
}
bool is_fullscreen = container->pending.fullscreen_mode != FULLSCREEN_NONE;
bool global = false;
bool enable = !is_fullscreen;

View file

@ -1,6 +1,8 @@
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/output.h"
#include "util.h"
#include <strings.h>
struct cmd_results *output_cmd_dpms(int argc, char **argv) {
if (!config->handler_context.output_config) {
@ -10,7 +12,28 @@ struct cmd_results *output_cmd_dpms(int argc, char **argv) {
return cmd_results_new(CMD_INVALID, "Missing dpms argument.");
}
if (parse_boolean(argv[0], true)) {
enum config_dpms current_dpms = DPMS_ON;
if (strcasecmp(argv[0], "toggle") == 0) {
const char *oc_name = config->handler_context.output_config->name;
if (strcmp(oc_name, "*") == 0) {
return cmd_results_new(CMD_INVALID,
"Cannot apply toggle to all outputs.");
}
struct sway_output *sway_output = all_output_by_name_or_id(oc_name);
if (!sway_output || !sway_output->wlr_output) {
return cmd_results_new(CMD_FAILURE,
"Cannot apply toggle to unknown output %s", oc_name);
}
if (sway_output->enabled && !sway_output->wlr_output->enabled) {
current_dpms = DPMS_OFF;
}
}
if (parse_boolean(argv[0], current_dpms == DPMS_ON)) {
config->handler_context.output_config->dpms_state = DPMS_ON;
} else {
config->handler_context.output_config->dpms_state = DPMS_OFF;

View file

@ -338,35 +338,60 @@ static bool file_exists(const char *path) {
return path && access(path, R_OK) != -1;
}
static char *config_path(const char *prefix, const char *config_folder) {
if (!prefix || !prefix[0] || !config_folder || !config_folder[0]) {
return NULL;
}
const char *filename = "config";
size_t size = 3 + strlen(prefix) + strlen(config_folder) + strlen(filename);
char *path = calloc(size, sizeof(char));
snprintf(path, size, "%s/%s/%s", prefix, config_folder, filename);
return path;
}
static char *get_config_path(void) {
static const char *config_paths[] = {
"$HOME/.sway/config",
"$XDG_CONFIG_HOME/sway/config",
"$HOME/.i3/config",
"$XDG_CONFIG_HOME/i3/config",
SYSCONFDIR "/sway/config",
SYSCONFDIR "/i3/config",
char *path = NULL;
const char *home = getenv("HOME");
size_t size_fallback = 1 + strlen(home) + strlen("/.config");
char *config_home_fallback = calloc(size_fallback, sizeof(char));
snprintf(config_home_fallback, size_fallback, "%s/.config", home);
const char *config_home = getenv("XDG_CONFIG_HOME");
if (config_home == NULL || config_home[0] == '\0') {
config_home = config_home_fallback;
}
struct config_path {
const char *prefix;
const char *config_folder;
};
char *config_home = getenv("XDG_CONFIG_HOME");
if (!config_home || !*config_home) {
config_paths[1] = "$HOME/.config/sway/config";
config_paths[3] = "$HOME/.config/i3/config";
}
struct config_path config_paths[] = {
{ .prefix = home, .config_folder = ".sway"},
{ .prefix = config_home, .config_folder = "sway"},
{ .prefix = home, .config_folder = ".i3"},
{ .prefix = config_home, .config_folder = "i3"},
{ .prefix = SYSCONFDIR, .config_folder = "sway"},
{ .prefix = SYSCONFDIR, .config_folder = "i3"}
};
for (size_t i = 0; i < sizeof(config_paths) / sizeof(char *); ++i) {
wordexp_t p;
if (wordexp(config_paths[i], &p, WRDE_UNDEF) == 0) {
char *path = strdup(p.we_wordv[0]);
wordfree(&p);
if (file_exists(path)) {
return path;
}
free(path);
size_t num_config_paths = sizeof(config_paths)/sizeof(config_paths[0]);
for (size_t i = 0; i < num_config_paths; i++) {
path = config_path(config_paths[i].prefix, config_paths[i].config_folder);
if (!path) {
continue;
}
if (file_exists(path)) {
break;
}
free(path);
path = NULL;
}
return NULL;
free(config_home_fallback);
return path;
}
static bool load_config(const char *path, struct sway_config *config,

View file

@ -115,9 +115,10 @@ static void arrange_layer(struct sway_output *output, struct wl_list *list,
// Horizontal axis
const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
| ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
if ((state->anchor & both_horiz) && box.width == 0) {
if (box.width == 0) {
box.x = bounds.x;
box.width = bounds.width;
} else if ((state->anchor & both_horiz) == both_horiz) {
box.x = bounds.x + ((bounds.width / 2) - (box.width / 2));
} else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
box.x = bounds.x;
} else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
@ -128,9 +129,10 @@ static void arrange_layer(struct sway_output *output, struct wl_list *list,
// Vertical axis
const uint32_t both_vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP
| ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
if ((state->anchor & both_vert) && box.height == 0) {
if (box.height == 0) {
box.y = bounds.y;
box.height = bounds.height;
} else if ((state->anchor & both_vert) == both_vert) {
box.y = bounds.y + ((bounds.height / 2) - (box.height / 2));
} else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
box.y = bounds.y;
} else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
@ -139,17 +141,23 @@ static void arrange_layer(struct sway_output *output, struct wl_list *list,
box.y = bounds.y + ((bounds.height / 2) - (box.height / 2));
}
// Margin
if ((state->anchor & both_horiz) == both_horiz) {
if (box.width == 0) {
box.x += state->margin.left;
box.width -= state->margin.left + state->margin.right;
box.width = bounds.width -
(state->margin.left + state->margin.right);
} else if ((state->anchor & both_horiz) == both_horiz) {
// don't apply margins
} else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT)) {
box.x += state->margin.left;
} else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) {
box.x -= state->margin.right;
}
if ((state->anchor & both_vert) == both_vert) {
if (box.height == 0) {
box.y += state->margin.top;
box.height -= state->margin.top + state->margin.bottom;
box.height = bounds.height -
(state->margin.top + state->margin.bottom);
} else if ((state->anchor & both_vert) == both_vert) {
// don't apply margins
} else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)) {
box.y += state->margin.top;
} else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) {
@ -191,7 +199,7 @@ void arrange_layers(struct sway_output *output) {
arrange_output(output);
}
// Arrange non-exlusive surfaces from top->bottom
// Arrange non-exclusive surfaces from top->bottom
arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
&usable_area, false);
arrange_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],

View file

@ -56,26 +56,6 @@ struct sway_output *all_output_by_name_or_id(const char *name_or_id) {
return NULL;
}
/**
* Rotate a child's position relative to a parent. The parent size is (pw, ph),
* the child position is (*sx, *sy) and its size is (sw, sh).
*/
static void rotate_child_position(double *sx, double *sy, double sw, double sh,
double pw, double ph, float rotation) {
if (rotation == 0.0f) {
return;
}
// Coordinates relative to the center of the subsurface
double ox = *sx - pw/2 + sw/2,
oy = *sy - ph/2 + sh/2;
// Rotated coordinates
double rx = cos(-rotation)*ox - sin(-rotation)*oy,
ry = cos(-rotation)*oy + sin(-rotation)*ox;
*sx = rx + pw/2 - sw/2;
*sy = ry + ph/2 - sh/2;
}
struct surface_iterator_data {
sway_surface_iterator_func_t user_iterator;
void *user_data;
@ -84,7 +64,6 @@ struct surface_iterator_data {
struct sway_view *view;
double ox, oy;
int width, height;
float rotation;
};
static bool get_surface_box(struct surface_iterator_data *data,
@ -99,14 +78,9 @@ static bool get_surface_box(struct surface_iterator_data *data,
int sw = surface->current.width;
int sh = surface->current.height;
double _sx = sx + surface->sx;
double _sy = sy + surface->sy;
rotate_child_position(&_sx, &_sy, sw, sh, data->width, data->height,
data->rotation);
struct wlr_box box = {
.x = floor(data->ox + _sx),
.y = floor(data->oy + _sy),
.x = floor(data->ox + sx),
.y = floor(data->oy + sy),
.width = sw,
.height = sh,
};
@ -114,16 +88,13 @@ static bool get_surface_box(struct surface_iterator_data *data,
memcpy(surface_box, &box, sizeof(struct wlr_box));
}
struct wlr_box rotated_box;
wlr_box_rotated_bounds(&rotated_box, &box, data->rotation);
struct wlr_box output_box = {
.width = output->width,
.height = output->height,
};
struct wlr_box intersection;
return wlr_box_intersection(&intersection, &output_box, &rotated_box);
return wlr_box_intersection(&intersection, &output_box, &box);
}
static void output_for_each_surface_iterator(struct wlr_surface *surface,
@ -136,7 +107,7 @@ static void output_for_each_surface_iterator(struct wlr_surface *surface,
return;
}
data->user_iterator(data->output, data->view, surface, &box, data->rotation,
data->user_iterator(data->output, data->view, surface, &box,
data->user_data);
}
@ -152,7 +123,6 @@ void output_surface_for_each_surface(struct sway_output *output,
.oy = oy,
.width = surface->current.width,
.height = surface->current.height,
.rotation = 0,
};
wlr_surface_for_each_surface(surface,
@ -173,7 +143,6 @@ void output_view_for_each_surface(struct sway_output *output,
- view->geometry.y,
.width = view->container->current.content_width,
.height = view->container->current.content_height,
.rotation = 0, // TODO
};
view_for_each_surface(view, output_for_each_surface_iterator, &data);
@ -193,7 +162,6 @@ void output_view_for_each_popup_surface(struct sway_output *output,
- view->geometry.y,
.width = view->container->current.content_width,
.height = view->container->current.content_height,
.rotation = 0, // TODO
};
view_for_each_popup_surface(view, output_for_each_surface_iterator, &data);
@ -216,7 +184,6 @@ void output_layer_for_each_surface(struct sway_output *output,
.oy = layer_surface->geo.y,
.width = surface->current.width,
.height = surface->current.height,
.rotation = 0,
};
wlr_layer_surface_v1_for_each_surface(wlr_layer_surface_v1,
output_for_each_surface_iterator, &data);
@ -254,7 +221,6 @@ void output_layer_for_each_popup_surface(struct sway_output *output,
.oy = layer_surface->geo.y,
.width = surface->current.width,
.height = surface->current.height,
.rotation = 0,
};
wlr_layer_surface_v1_for_each_popup_surface(wlr_layer_surface_v1,
output_for_each_surface_iterator, &data);
@ -426,9 +392,9 @@ struct send_frame_done_data {
int msec_until_refresh;
};
static void send_frame_done_iterator(struct sway_output *output, struct sway_view *view,
struct wlr_surface *surface, struct wlr_box *box, float rotation,
void *user_data) {
static void send_frame_done_iterator(struct sway_output *output,
struct sway_view *view, struct wlr_surface *surface,
struct wlr_box *box, void *user_data) {
int view_max_render_time = 0;
if (view != NULL) {
view_max_render_time = view->max_render_time;
@ -451,9 +417,9 @@ static void send_frame_done(struct sway_output *output, struct send_frame_done_d
output_for_each_surface(output, send_frame_done_iterator, data);
}
static void count_surface_iterator(struct sway_output *output, struct sway_view *view,
struct wlr_surface *surface, struct wlr_box *_box, float rotation,
void *data) {
static void count_surface_iterator(struct sway_output *output,
struct sway_view *view, struct wlr_surface *surface,
struct wlr_box *box, void *data) {
size_t *n = data;
(*n)++;
}
@ -553,6 +519,7 @@ static int output_repaint_timer_handler(void *data) {
if (last_scanned_out && !scanned_out) {
sway_log(SWAY_DEBUG, "Stopping fullscreen view scan out on %s",
output->wlr_output->name);
output_damage_whole(output);
}
last_scanned_out = scanned_out;
@ -656,18 +623,15 @@ void output_damage_whole(struct sway_output *output) {
}
}
static void damage_surface_iterator(struct sway_output *output, struct sway_view *view,
struct wlr_surface *surface, struct wlr_box *_box, float rotation,
void *_data) {
static void damage_surface_iterator(struct sway_output *output,
struct sway_view *view, struct wlr_surface *surface,
struct wlr_box *_box, void *_data) {
bool *data = _data;
bool whole = *data;
struct wlr_box box = *_box;
scale_box(&box, output->wlr_output->scale);
int center_x = box.x + box.width/2;
int center_y = box.y + box.height/2;
if (pixman_region32_not_empty(&surface->buffer_damage)) {
pixman_region32_t damage;
pixman_region32_init(&damage);
@ -680,14 +644,11 @@ static void damage_surface_iterator(struct sway_output *output, struct sway_view
ceil(output->wlr_output->scale) - surface->current.scale);
}
pixman_region32_translate(&damage, box.x, box.y);
wlr_region_rotated_bounds(&damage, &damage, rotation,
center_x, center_y);
wlr_output_damage_add(output->damage, &damage);
pixman_region32_fini(&damage);
}
if (whole) {
wlr_box_rotated_bounds(&box, &box, rotation);
wlr_output_damage_add_box(output->damage, &box);
}

View file

@ -32,7 +32,7 @@
struct render_data {
pixman_region32_t *damage;
float alpha;
struct sway_container *container;
struct wlr_box *clip_box;
};
/**
@ -105,9 +105,6 @@ static void render_texture(struct wlr_output *wlr_output,
wlr_backend_get_renderer(wlr_output->backend);
struct sway_output *output = wlr_output->data;
struct wlr_gles2_texture_attribs attribs;
wlr_gles2_texture_get_attribs(texture, &attribs);
pixman_region32_t damage;
pixman_region32_init(&damage);
pixman_region32_union_rect(&damage, &damage, dst_box->x, dst_box->y,
@ -134,9 +131,9 @@ damage_finish:
pixman_region32_fini(&damage);
}
static void render_surface_iterator(struct sway_output *output, struct sway_view *view,
struct wlr_surface *surface, struct wlr_box *_box, float rotation,
void *_data) {
static void render_surface_iterator(struct sway_output *output,
struct sway_view *view, struct wlr_surface *surface,
struct wlr_box *_box, void *_data) {
struct render_data *data = _data;
struct wlr_output *wlr_output = output->wlr_output;
pixman_region32_t *output_damage = data->damage;
@ -156,14 +153,14 @@ static void render_surface_iterator(struct sway_output *output, struct sway_view
float matrix[9];
enum wl_output_transform transform =
wlr_output_transform_invert(surface->current.transform);
wlr_matrix_project_box(matrix, &proj_box, transform, rotation,
wlr_matrix_project_box(matrix, &proj_box, transform, 0.0,
wlr_output->transform_matrix);
struct wlr_box dst_box = *_box;
struct sway_container *container = data->container;
if (container != NULL) {
dst_box.width = fmin(dst_box.width, container->current.content_width - surface->sx);
dst_box.height = fmin(dst_box.height, container->current.content_height - surface->sy);
struct wlr_box *clip_box = data->clip_box;
if (clip_box != NULL) {
dst_box.width = fmin(dst_box.width, clip_box->width);
dst_box.height = fmin(dst_box.height, clip_box->height);
}
scale_box(&dst_box, wlr_output->scale);
@ -265,8 +262,13 @@ static void render_view_toplevels(struct sway_view *view,
.damage = damage,
.alpha = alpha,
};
struct wlr_box clip_box;
if (!container_is_current_floating(view->container)) {
data.container = view->container;
// As we pass the geometry offsets to the surface iterator, we will
// need to account for the offsets in the clip dimensions.
clip_box.width = view->container->current.content_width + view->geometry.x;
clip_box.height = view->container->current.content_height + view->geometry.y;
data.clip_box = &clip_box;
}
// Render all toplevels without descending into popups
double ox = view->container->surface_x -
@ -332,10 +334,10 @@ static void render_saved_view(struct sway_view *view,
if (!floating) {
dst_box.width = fmin(dst_box.width,
view->container->current.content_width -
(saved_buf->x - view->container->current.content_x));
(saved_buf->x - view->container->current.content_x) + view->saved_geometry.x);
dst_box.height = fmin(dst_box.height,
view->container->current.content_height -
(saved_buf->y - view->container->current.content_y));
(saved_buf->y - view->container->current.content_y) + view->saved_geometry.y);
}
scale_box(&dst_box, wlr_output->scale);

View file

@ -358,7 +358,8 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
if (e->fullscreen && e->output && e->output->data) {
struct sway_output *output = e->output->data;
struct sway_workspace *ws = output_get_active_workspace(output);
if (ws && !container_is_scratchpad_hidden(container)) {
if (ws && !container_is_scratchpad_hidden(container) &&
container->pending.workspace != ws) {
if (container_is_floating(container)) {
workspace_add_floating(ws, container);
} else {

View file

@ -1,3 +1,4 @@
#include <float.h>
#include <json.h>
#include <libevdev/libevdev.h>
#include <stdio.h>
@ -1002,6 +1003,17 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) {
}
}
if (device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) {
struct input_config *ic = input_device_get_config(device);
float scroll_factor = 1.0f;
if (ic != NULL && !isnan(ic->scroll_factor) &&
ic->scroll_factor != FLT_MIN) {
scroll_factor = ic->scroll_factor;
}
json_object_object_add(object, "scroll_factor",
json_object_new_double(scroll_factor));
}
if (wlr_input_device_is_libinput(device->wlr_device)) {
struct libinput_device *libinput_dev;
libinput_dev = wlr_libinput_get_device_handle(device->wlr_device);

View file

@ -12,6 +12,7 @@
#include <sys/un.h>
#include <unistd.h>
#include <wlr/util/log.h>
#include <wlr/version.h>
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/server.h"
@ -46,43 +47,6 @@ void sig_handler(int signal) {
sway_terminate(EXIT_SUCCESS);
}
void detect_raspi(void) {
bool raspi = false;
FILE *f = fopen("/sys/firmware/devicetree/base/model", "r");
if (!f) {
return;
}
char *line = NULL;
size_t line_size = 0;
while (getline(&line, &line_size, f) != -1) {
if (strstr(line, "Raspberry Pi")) {
raspi = true;
break;
}
}
fclose(f);
FILE *g = fopen("/proc/modules", "r");
if (!g) {
free(line);
return;
}
bool vc4 = false;
while (getline(&line, &line_size, g) != -1) {
if (strstr(line, "vc4")) {
vc4 = true;
break;
}
}
free(line);
fclose(g);
if (!vc4 && raspi) {
fprintf(stderr, "\x1B[1;31mWarning: You have a "
"Raspberry Pi, but the vc4 Module is "
"not loaded! Set 'dtoverlay=vc4-kms-v3d'"
"in /boot/config.txt and reboot.\x1B[0m\n");
}
}
void detect_proprietary(int allow_unsupported_gpu) {
FILE *f = fopen("/proc/modules", "r");
if (!f) {
@ -344,11 +308,11 @@ int main(int argc, char **argv) {
}
sway_log(SWAY_INFO, "Sway version " SWAY_VERSION);
sway_log(SWAY_INFO, "wlroots version " WLR_VERSION_STR);
log_kernel();
log_distro();
log_env();
detect_proprietary(allow_unsupported_gpu);
detect_raspi();
if (optind < argc) { // Behave as IPC client
if (optind != 1) {

View file

@ -26,11 +26,9 @@
#include <wlr/types/wlr_viewporter.h>
#include <wlr/types/wlr_xcursor_manager.h>
#include <wlr/types/wlr_xdg_decoration_v1.h>
#if WLR_HAS_XDG_FOREIGN
#include <wlr/types/wlr_xdg_foreign_registry.h>
#include <wlr/types/wlr_xdg_foreign_v1.h>
#include <wlr/types/wlr_xdg_foreign_v2.h>
#endif
#include <wlr/types/wlr_xdg_output_v1.h>
#include "config.h"
#include "list.h"
@ -156,12 +154,10 @@ bool server_init(struct sway_server *server) {
wlr_primary_selection_v1_device_manager_create(server->wl_display);
wlr_viewporter_create(server->wl_display);
#if WLR_HAS_XDG_FOREIGN
struct wlr_xdg_foreign_registry *foreign_registry =
wlr_xdg_foreign_registry_create(server->wl_display);
wlr_xdg_foreign_v1_create(server->wl_display, foreign_registry);
wlr_xdg_foreign_v2_create(server->wl_display, foreign_registry);
#endif
// Avoid using "wayland-0" as display socket
char name_candidate[16];

View file

@ -1131,6 +1131,9 @@ following properties:
|- xkb_active_layout_index
: integer
: (Only keyboards) The index of the active keyboard layout in use
|- scroll_factor
: floating
: (Only pointers) Multiplier applied on scroll event values.
|- libinput
: object
: (Only libinput devices) An object describing the current device settings.

View file

@ -112,7 +112,7 @@ must be separated by one space. For example:
*output* <name> toggle
Toggle the specified output.
*output* <name> dpms on|off
*output* <name> dpms on|off|toggle
Enables or disables the specified output via DPMS. To turn an output off
(ie. blank the screen but keep workspaces as-is), one can set DPMS to off.

View file

@ -87,8 +87,8 @@ bool swaynag_spawn(const char *swaynag_command,
size_t length = strlen(swaynag_command) + strlen(swaynag->args) + 2;
char *cmd = malloc(length);
snprintf(cmd, length, "%s %s", swaynag_command, swaynag->args);
execl("/bin/sh", "/bin/sh", "-c", cmd, NULL);
sway_log_errno(SWAY_ERROR, "execl failed");
execlp("sh", "sh", "-c", cmd, NULL);
sway_log_errno(SWAY_ERROR, "execlp failed");
_exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);

View file

@ -531,6 +531,10 @@ static void update_title_texture(struct sway_container *con,
cairo_surface_destroy(dummy_surface);
cairo_destroy(c);
if (width == 0 || height == 0) {
return;
}
cairo_surface_t *surface = cairo_image_surface_create(
CAIRO_FORMAT_ARGB32, width, height);
cairo_t *cairo = cairo_create(surface);
@ -550,7 +554,7 @@ static void update_title_texture(struct sway_container *con,
cairo_surface_flush(surface);
unsigned char *data = cairo_image_surface_get_data(surface);
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
int stride = cairo_image_surface_get_stride(surface);
struct wlr_renderer *renderer = wlr_backend_get_renderer(
output->wlr_output->backend);
*texture = wlr_texture_from_pixels(
@ -821,6 +825,8 @@ void container_set_floating(struct sway_container *container, bool enable) {
struct sway_seat *seat = input_manager_current_seat();
struct sway_workspace *workspace = container->pending.workspace;
struct sway_container *focus = seat_get_focused_container(seat);
bool set_focus = focus == container;
if (enable) {
struct sway_container *old_parent = container->pending.parent;
@ -835,6 +841,10 @@ void container_set_floating(struct sway_container *container, bool enable) {
container_floating_set_default_size(container);
container_floating_resize_and_center(container);
if (old_parent) {
if (set_focus) {
seat_set_raw_focus(seat, &old_parent->node);
seat_set_raw_focus(seat, &container->node);
}
container_reap_empty(old_parent);
}
} else {
@ -846,7 +856,11 @@ void container_set_floating(struct sway_container *container, bool enable) {
struct sway_container *reference =
seat_get_focus_inactive_tiling(seat, workspace);
if (reference) {
container_add_sibling(reference, container, 1);
if (reference->view) {
container_add_sibling(reference, container, 1);
} else {
container_add_child(reference, container);
}
container->pending.width = reference->pending.width;
container->pending.height = reference->pending.height;
} else {
@ -1029,16 +1043,15 @@ void container_end_mouse_operation(struct sway_container *container) {
}
}
static void set_fullscreen_iterator(struct sway_container *con, void *data) {
static void set_fullscreen(struct sway_container *con, bool enable) {
if (!con->view) {
return;
}
if (con->view->impl->set_fullscreen) {
bool *enable = data;
con->view->impl->set_fullscreen(con->view, *enable);
con->view->impl->set_fullscreen(con->view, enable);
if (con->view->foreign_toplevel) {
wlr_foreign_toplevel_handle_v1_set_fullscreen(
con->view->foreign_toplevel, *enable);
con->view->foreign_toplevel, enable);
}
}
}
@ -1048,9 +1061,7 @@ static void container_fullscreen_workspace(struct sway_container *con) {
"Expected a non-fullscreen container")) {
return;
}
bool enable = true;
set_fullscreen_iterator(con, &enable);
container_for_each_child(con, set_fullscreen_iterator, &enable);
set_fullscreen(con, true);
con->pending.fullscreen_mode = FULLSCREEN_WORKSPACE;
con->saved_x = con->pending.x;
@ -1084,9 +1095,7 @@ static void container_fullscreen_global(struct sway_container *con) {
"Expected a non-fullscreen container")) {
return;
}
bool enable = true;
set_fullscreen_iterator(con, &enable);
container_for_each_child(con, set_fullscreen_iterator, &enable);
set_fullscreen(con, true);
root->fullscreen_global = con;
con->saved_x = con->pending.x;
@ -1112,9 +1121,7 @@ void container_fullscreen_disable(struct sway_container *con) {
"Expected a fullscreen container")) {
return;
}
bool enable = false;
set_fullscreen_iterator(con, &enable);
container_for_each_child(con, set_fullscreen_iterator, &enable);
set_fullscreen(con, false);
if (container_is_floating(con)) {
con->pending.x = con->saved_x;
@ -1378,10 +1385,6 @@ void container_add_child(struct sway_container *parent,
child->pending.parent = parent;
child->pending.workspace = parent->pending.workspace;
container_for_each_child(child, set_workspace, NULL);
bool fullscreen = child->pending.fullscreen_mode != FULLSCREEN_NONE ||
parent->pending.fullscreen_mode != FULLSCREEN_NONE;
set_fullscreen_iterator(child, &fullscreen);
container_for_each_child(child, set_fullscreen_iterator, &fullscreen);
container_handle_fullscreen_reparent(child);
container_update_representation(parent);
node_set_dirty(&child->node);
@ -1620,6 +1623,10 @@ static void update_marks_texture(struct sway_container *con,
"%s", buffer);
cairo_destroy(c);
if (width == 0 || height == 0) {
return;
}
cairo_surface_t *surface = cairo_image_surface_create(
CAIRO_FORMAT_ARGB32, width, height);
cairo_t *cairo = cairo_create(surface);
@ -1636,7 +1643,7 @@ static void update_marks_texture(struct sway_container *con,
cairo_surface_flush(surface);
unsigned char *data = cairo_image_surface_get_data(surface);
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
int stride = cairo_image_surface_get_stride(surface);
struct wlr_renderer *renderer = wlr_backend_get_renderer(
output->wlr_output->backend);
*texture = wlr_texture_from_pixels(

View file

@ -56,6 +56,7 @@ void view_destroy(struct sway_view *view) {
"(might have a pending transaction?)")) {
return;
}
wl_list_remove(&view->events.unmap.listener_list);
if (!wl_list_empty(&view->saved_buffers)) {
view_remove_saved_buffer(view);
}
@ -599,6 +600,11 @@ static bool should_focus(struct sway_view *view) {
return true;
}
// View opened "under" fullscreen view should not be given focus.
if (root->fullscreen_global || !map_ws || map_ws->fullscreen) {
return false;
}
// Views can only take focus if they are mapped into the active workspace
if (prev_ws != map_ws) {
return false;
@ -757,7 +763,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
view_init_subsurfaces(view, wlr_surface);
wl_signal_add(&wlr_surface->events.new_subsurface,
&view->surface_new_subsurface);
&view->surface_new_subsurface);
view->surface_new_subsurface.notify = view_handle_surface_new_subsurface;
if (decoration) {
@ -805,9 +811,9 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
#if HAVE_XWAYLAND
if (wlr_surface_is_xwayland_surface(wlr_surface)) {
struct wlr_xwayland_surface *xsurface =
wlr_xwayland_surface_from_wlr_surface(wlr_surface);
set_focus = (wlr_xwayland_icccm_input_model(xsurface) !=
WLR_ICCCM_INPUT_MODEL_NONE) && set_focus;
wlr_xwayland_surface_from_wlr_surface(wlr_surface);
set_focus &= wlr_xwayland_icccm_input_model(xsurface) !=
WLR_ICCCM_INPUT_MODEL_NONE;
}
#endif
@ -818,11 +824,9 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
const char *app_id;
const char *class;
if ((app_id = view_get_app_id(view)) != NULL) {
wlr_foreign_toplevel_handle_v1_set_app_id(
view->foreign_toplevel, app_id);
wlr_foreign_toplevel_handle_v1_set_app_id(view->foreign_toplevel, app_id);
} else if ((class = view_get_class(view)) != NULL) {
wlr_foreign_toplevel_handle_v1_set_app_id(
view->foreign_toplevel, class);
wlr_foreign_toplevel_handle_v1_set_app_id(view->foreign_toplevel, class);
}
}
@ -1157,6 +1161,9 @@ struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) {
if (wlr_surface_is_subsurface(wlr_surface)) {
struct wlr_subsurface *subsurface =
wlr_subsurface_from_wlr_surface(wlr_surface);
if (subsurface == NULL) {
return NULL;
}
return view_from_wlr_surface(subsurface->parent);
}
if (wlr_surface_is_layer_surface(wlr_surface)) {

View file

@ -794,7 +794,11 @@ void workspace_detach(struct sway_workspace *workspace) {
struct sway_container *workspace_add_tiling(struct sway_workspace *workspace,
struct sway_container *con) {
if (con->pending.workspace) {
struct sway_container *old_parent = con->pending.parent;
container_detach(con);
if (old_parent) {
container_reap_empty(old_parent);
}
}
if (config->default_layout != L_NONE) {
con = container_split(con, config->default_layout);

View file

@ -30,8 +30,8 @@ static bool terminal_execute(char *terminal, char *command) {
chmod(fname, S_IRUSR | S_IWUSR | S_IXUSR);
char *cmd = malloc(sizeof(char) * (strlen(terminal) + strlen(" -e ") + strlen(fname) + 1));
sprintf(cmd, "%s -e %s", terminal, fname);
execl("/bin/sh", "/bin/sh", "-c", cmd, NULL);
sway_log_errno(SWAY_ERROR, "Failed to run command, execl() returned.");
execlp("sh", "sh", "-c", cmd, NULL);
sway_log_errno(SWAY_ERROR, "Failed to run command, execlp() returned.");
free(cmd);
return false;
}
@ -69,8 +69,8 @@ static void swaynag_button_execute(struct swaynag *swaynag,
sway_log(SWAY_DEBUG,
"$TERMINAL not found. Running directly");
}
execl("/bin/sh", "/bin/sh", "-c", button->action, NULL);
sway_log_errno(SWAY_DEBUG, "execl failed");
execlp("sh", "sh", "-c", button->action, NULL);
sway_log_errno(SWAY_DEBUG, "execlp failed");
_exit(EXIT_FAILURE);
}
}