diff --git a/README.fr.md b/README.fr.md index ad627ba54..97c09667b 100644 --- a/README.fr.md +++ b/README.fr.md @@ -6,14 +6,8 @@ avec i3, **en cours de développement**. Lisez la IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway sur irc.freenode.net). -[![](https://sr.ht/ICd5.png)](https://sr.ht/ICd5.png) - -Si vous souhaitez soutenir le développement de Sway, vous pouvez contribuer à [ma page -Patreon](https://patreon.com/sircmpwn) ou aux [primes](https://github.com/swaywm/sway/issues/986) -pour des fonctionnalités spécifiques. -Tout le monde est invité à réclamer une prime et vous pouvez donner une prime pour n'importe quelle -fonctionnalité souhaitée. Patreon est plus utile pour supporter l'état général et la -maintenance de Sway. +Si vous souhaitez soutenir le développement de Sway, vous pouvez contribuer à [la page +Patreon de SirCmpwn](https://patreon.com/sircmpwn). ## Aide en français @@ -39,21 +33,21 @@ IRC ou envoyez un e-mail à sir@cmpwn.com (en anglais seulement) pour des consei Installez les dépendances : -* meson -* [wlc](https://github.com/Cloudef/wlc) +* meson \* +* [wlroots](https://github.com/swaywm/wlroots) * wayland -* xwayland -* libinput >= 1.6.0 -* libcap +* wayland-protocols \* * pcre -* json-c >= 0.13 +* json-c * pango * cairo -* gdk-pixbuf2 * -* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (requis pour les pages man) -* git +* gdk-pixbuf2 \*\* +* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (optionnel: requis pour les pages man) \* +* git \* -_\*Uniquement requis pour swaybar, swaybg_ +_\*Requis uniquement pour la compilation_ + +_\*\*Optionnel: requis uniquement pour swaybg_ Exécutez ces commandes : @@ -65,6 +59,8 @@ Sur les systèmes sans logind, vous devez suid le binaire de sway : sudo chmod a+s /usr/local/bin/sway +Sway se débarassera des permissions *root* peu de temps après le démarrage. + ## Configuration Si vous utilisez déjà i3, copiez votre configuration i3 à `~/.config/sway/config` et @@ -72,10 +68,6 @@ cela va fonctionner. Sinon, copiez l'exemple de fichier de configuration à `~/.config/sway/config`. Il se trouve généralement dans `/etc/sway/config`. Exécutez `man 5 sway` pour l'information sur la configuration. -Mes propres dotfiles sont disponibles [ici](https://git.sr.ht/~sircmpwn/dotfiles) si -vous voulez un peu d'inspiration. Je vous recommande aussi de consulter le -[wiki](https://github.com/swaywm/sway/wiki). - ## Exécution Exécutez `sway` à partir d'un TTY. Certains gestionnaires d'affichage peuvent fonctionner, diff --git a/README.md b/README.md index 99835d6e5..d1d78799e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [**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--) +[Polski](https://github.com/swaywm/sway/blob/master/README.pl.md#sway--) - [中文-简体](https://github.com/swaywm/sway/blob/master/README-zh-CN.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 diff --git a/README.uk.md b/README.uk.md index 4c378a89f..b0c81c512 100644 --- a/README.uk.md +++ b/README.uk.md @@ -1,20 +1,12 @@ # sway -**Sway** це сумісний з i3 композитор [Wayland](http://wayland.freedesktop.org/) -(**у стані розробки**). Ознайомтесь з -[ЧаПами](https://github.com/swaywm/sway/wiki). Приєднуйтесь до [спільноти в +Sway це сумісний з i3 композитор [Wayland](http://wayland.freedesktop.org/). +Ознайомтесь з [ЧаПами](https://github.com/swaywm/sway/wiki). Приєднуйтесь до [спільноти в IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway на irc.freenode.net). -[![](https://sr.ht/ICd5.png)](https://sr.ht/ICd5.png) - -Якщо ви хочете підтримати розробку Sway, ви можете зробити свій внесок у -[SirCmpwn'ову сторінку Patreon](https://patreon.com/sircmpwn) або до -[фонду винагород](https://github.com/swaywm/sway/issues/986) за реалізацію -певного функціоналу. -Кожен може виставити винагороду за реалізацію довільної функції -(і, відповідно, забрати її собі, виконавши це завдання); -кошти від сторінки Patreon підтримують загальну розробку та підтримку Sway. +Якщо ви маєте бажання підтримати розробку sway, ви можете зробити свій внесок на сторінці +[SirCmpwn у Patreon](https://patreon.com/sircmpwn). ## Підтримка українською мовою @@ -39,28 +31,28 @@ Sway доступний у багатьох дистрибутивах Linux (а для інформації щодо встановлення на вашому дистрибутиві. Якщо ви готові та зацікавлені запакувати і підтримувати Sway у вашому -дистрибутиві, будемо раді вас бачити у нашому каналі IRC. Ви також можете -спитати порад за адресою sir@cmpwn.com. +дистрибутиві, звертайтесь за порадами до нашого каналу в IRC або +пишіть на електронну пошту [sir@cmpwn.com](mailto:sir@cmpwn.com). ### З вихідного коду Встановіть залежності: -* meson -* [wlc](https://github.com/Cloudef/wlc) +* meson \* +* [wlroots](https://github.com/swaywm/wlroots) * wayland -* xwayland -* libinput >= 1.6.0 -* libcap +* wayland-protocols \* * pcre -* json-c >= 0.13 +* json-c * pango * cairo -* gdk-pixbuf2 * -* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (required for man pages) -* git +* gdk-pixbuf2 \*\* +* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (необов'язково, необхідно для сторінок man) \* +* git \* -_\*Лише для swaybar, swaybg_ +_\*Лише для компіляції_ + +_\*\*Необов'язково, необхідно для swaybg_ Виконайте ці команди: @@ -68,15 +60,12 @@ _\*Лише для swaybar, swaybg_ ninja -C build sudo ninja -C build install -На системах **з** logind, варто встановити декілька можливостей (caps) -на виконуваний файл sway: - - sudo setcap "cap_sys_ptrace,cap_sys_tty_config=eip" /usr/local/bin/sway - -На системах **без** logind, необхідно встановити біт SUID на виконуваний файл sway: +На системах без logind, необхідно встановити біт SUID на виконуваний файл sway: sudo chmod a+s /usr/local/bin/sway +Sway втратить права доступу root незабаром після запуску. + ## Налаштування Якщо ви вже використовуєте i3, скопіюйте свій файл налаштувань diff --git a/README.zh-CN.md b/README.zh-CN.md new file mode 100644 index 000000000..a60090f6a --- /dev/null +++ b/README.zh-CN.md @@ -0,0 +1,68 @@ +# sway + +sway 是和 i3 兼容的 [Wayland](http://wayland.freedesktop.org/) compositor. +阅读 [FAQ](https://github.com/swaywm/sway/wiki). 加入 [IRC +频道](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on +irc.freenode.net). + +如果你想要支持 sway 的发展, 请到 [SirCmpwn's +Patreon page](https://patreon.com/sircmpwn)贡献. + +## 发布签名 + +发布是以 [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) 签名 +并发布在 [GitHub](https://github.com/swaywm/sway/releases). + +## 安装 + +### 从软件包中 + +Sway 在很多发行版中可用. 尝试在你的发行版中安装 "sway" 包. +如何这不可用, 请到 [此 wiki 页](https://github.com/swaywm/sway/wiki/Unsupported-packages) +检查针对你的发行版关于安装的信息. + +如果你有兴趣给你的发行版打包 sway, 停下来到 IRC 频道或者发邮件至 sir@cmpwn.com 获取建议. + +### 从源代码编译 + +安装依赖: + +* meson \* +* [wlroots](https://github.com/swaywm/wlroots) +* wayland +* wayland-protocols \* +* pcre +* json-c +* pango +* cairo +* gdk-pixbuf2 \*\* +* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (可选的: man pages) \* +* git \* + +_\*编译时依赖_ + +_\*\*可选的: swaybg 依赖_ + +运行这些命令: + + meson build + ninja -C build + sudo ninja -C build install + +在没有 logind 的系统上, 你需要给 sway 二进制设置 suid: + + sudo chmod a+s /usr/local/bin/sway + +Sway 将会在启动后尽快丢掉 root 权限. + +## 配置 + +如果你已经在使用 i3, 接下来复制你的 i3 配置到 `~/.config/sway/config` +它可以直接工作. 或者, 复制样本配置文件到 +`~/.config/sway/config`. 它通常位于 `/etc/sway/config`. +运行 `man 5 sway` 获取关于配置的信息. + +## 运行 + +从 TTY 中运行 `sway` . 某些显示管理器可能会工作但并不被 sway 支持 +(已知的 gdm 工作得非常好). diff --git a/common/util.c b/common/util.c index edbbf3f77..c43c5ddf6 100644 --- a/common/util.c +++ b/common/util.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "log.h" #include "util.h" @@ -54,3 +55,23 @@ float parse_float(const char *value) { } return flt; } + + +const char *sway_wl_output_subpixel_to_string(enum wl_output_subpixel subpixel) { + switch (subpixel) { + case WL_OUTPUT_SUBPIXEL_UNKNOWN: + return "unknown"; + case WL_OUTPUT_SUBPIXEL_NONE: + return "none"; + case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB: + return "rgb"; + case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR: + return "bgr"; + case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB: + return "vrgb"; + case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR: + return "vbgr"; + } + sway_assert(false, "Unknown value for wl_output_subpixel."); + return NULL; +} diff --git a/include/sway/commands.h b/include/sway/commands.h index 1c147c5ab..9bd0f1cb5 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -136,6 +136,7 @@ sway_cmd cmd_fullscreen; sway_cmd cmd_gaps; sway_cmd cmd_hide_edge_borders; sway_cmd cmd_include; +sway_cmd cmd_inhibit_idle; sway_cmd cmd_input; sway_cmd cmd_seat; sway_cmd cmd_ipc; @@ -261,6 +262,7 @@ sway_cmd output_cmd_enable; sway_cmd output_cmd_mode; sway_cmd output_cmd_position; sway_cmd output_cmd_scale; +sway_cmd output_cmd_subpixel; sway_cmd output_cmd_transform; sway_cmd seat_cmd_attach; diff --git a/include/sway/config.h b/include/sway/config.h index 8970696c4..d49120a06 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -184,6 +184,7 @@ struct output_config { int x, y; float scale; int32_t transform; + enum wl_output_subpixel subpixel; char *background; char *background_option; diff --git a/include/sway/criteria.h b/include/sway/criteria.h index f7e788c8b..8a1d9e5ef 100644 --- a/include/sway/criteria.h +++ b/include/sway/criteria.h @@ -20,6 +20,7 @@ struct criteria { char *cmdlist; char *target; // workspace or output name for `assign` criteria + bool autofail; // __focused__ while no focus or n/a for focused view pcre *title; pcre *shell; pcre *app_id; diff --git a/include/sway/desktop/idle_inhibit_v1.h b/include/sway/desktop/idle_inhibit_v1.h index e5ed8a3de..4d4e59b0b 100644 --- a/include/sway/desktop/idle_inhibit_v1.h +++ b/include/sway/desktop/idle_inhibit_v1.h @@ -4,6 +4,14 @@ #include #include "sway/server.h" +enum sway_idle_inhibit_mode { + INHIBIT_IDLE_APPLICATION, // Application set inhibitor (when visible) + INHIBIT_IDLE_FOCUS, // User set inhibitor when focused + INHIBIT_IDLE_FULLSCREEN, // User set inhibitor when fullscreen + visible + INHIBIT_IDLE_OPEN, // User set inhibitor while open + INHIBIT_IDLE_VISIBLE // User set inhibitor when visible +}; + struct sway_idle_inhibit_manager_v1 { struct wlr_idle_inhibit_manager_v1 *wlr_manager; struct wl_listener new_idle_inhibitor_v1; @@ -15,14 +23,24 @@ struct sway_idle_inhibit_manager_v1 { struct sway_idle_inhibitor_v1 { struct sway_idle_inhibit_manager_v1 *manager; struct sway_view *view; + enum sway_idle_inhibit_mode mode; struct wl_list link; struct wl_listener destroy; }; -void idle_inhibit_v1_check_active( +void sway_idle_inhibit_v1_check_active( struct sway_idle_inhibit_manager_v1 *manager); +void sway_idle_inhibit_v1_user_inhibitor_register(struct sway_view *view, + enum sway_idle_inhibit_mode mode); + +struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_user_inhibitor_for_view( + struct sway_view *view); + +void sway_idle_inhibit_v1_user_inhibitor_destroy( + struct sway_idle_inhibitor_v1 *inhibitor); + struct sway_idle_inhibit_manager_v1 *sway_idle_inhibit_manager_v1_create( struct wl_display *wl_display, struct wlr_idle *idle); #endif diff --git a/include/sway/output.h b/include/sway/output.h index 8015f2110..c336c5592 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -31,6 +31,7 @@ struct sway_output { int lx, ly; // layout coords int width, height; // transformed buffer size + enum wl_output_subpixel detected_subpixel; bool enabled, configured; list_t *workspaces; diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index d25089949..8448d7059 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -215,10 +215,9 @@ size_t container_titlebar_height(void); void floating_calculate_constraints(int *min_width, int *max_width, int *min_height, int *max_height); -/** - * Resize and center the container in its workspace. - */ -void container_init_floating(struct sway_container *container); +void container_floating_resize_and_center(struct sway_container *con); + +void container_floating_set_default_size(struct sway_container *con); void container_set_floating(struct sway_container *container, bool enable); diff --git a/include/sway/tree/root.h b/include/sway/tree/root.h index 9f6cd3bb6..c4f84207d 100644 --- a/include/sway/tree/root.h +++ b/include/sway/tree/root.h @@ -85,4 +85,6 @@ struct sway_container *root_find_container( void root_get_box(struct sway_root *root, struct wlr_box *box); +void root_rename_pid_workspaces(const char *old_name, const char *new_name); + #endif diff --git a/include/util.h b/include/util.h index 1fd772c0c..6a668fd65 100644 --- a/include/util.h +++ b/include/util.h @@ -3,6 +3,7 @@ #include #include +#include /** * Wrap i into the range [0, max[ @@ -29,4 +30,6 @@ bool parse_boolean(const char *boolean, bool current); */ float parse_float(const char *value); +const char *sway_wl_output_subpixel_to_string(enum wl_output_subpixel subpixel); + #endif diff --git a/sway/commands.c b/sway/commands.c index 18b95c738..abdaa3b87 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -112,6 +112,7 @@ static struct cmd_handler command_handlers[] = { { "exit", cmd_exit }, { "floating", cmd_floating }, { "fullscreen", cmd_fullscreen }, + { "inhibit_idle", cmd_inhibit_idle }, { "kill", cmd_kill }, { "layout", cmd_layout }, { "mark", cmd_mark }, @@ -276,7 +277,6 @@ list_t *execute_command(char *_exec, struct sway_seat *seat, // Var replacement, for all but first argument of set for (int i = handler->handle == cmd_set ? 2 : 1; i < argc; ++i) { argv[i] = do_var_replacement(argv[i]); - unescape_string(argv[i]); } if (!config->handler_context.using_criteria) { diff --git a/sway/commands/bind.c b/sway/commands/bind.c index b3d391da6..9a937c611 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -316,7 +316,7 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv, struct sway_binding *config_binding = mode_bindings->items[i]; if (binding_key_compare(binding, config_binding)) { sway_log(SWAY_INFO, "Overwriting binding '%s' for device '%s' " - "from `%s` to `%s`", argv[0], binding->input, + "to `%s` from `%s`", argv[0], binding->input, binding->command, config_binding->command); if (warn) { config_add_swaynag_warning("Overwriting binding" @@ -420,7 +420,7 @@ struct cmd_results *cmd_bindswitch(int argc, char **argv) { for (int i = 0; i < mode_bindings->length; ++i) { struct sway_switch_binding *config_binding = mode_bindings->items[i]; if (binding_switch_compare(binding, config_binding)) { - sway_log(SWAY_INFO, "Overwriting binding '%s' from `%s` to `%s`", + sway_log(SWAY_INFO, "Overwriting binding '%s' to `%s` from `%s`", argv[0], binding->command, config_binding->command); if (warn) { config_add_swaynag_warning("Overwriting binding" diff --git a/sway/commands/floating.c b/sway/commands/floating.c index 821093695..5df9b1bfb 100644 --- a/sway/commands/floating.c +++ b/sway/commands/floating.c @@ -45,7 +45,10 @@ struct cmd_results *cmd_floating(int argc, char **argv) { container_set_floating(container, wants_floating); - arrange_workspace(container->workspace); + // Floating containers in the scratchpad should be ignored + if (container->workspace) { + arrange_workspace(container->workspace); + } return cmd_results_new(CMD_SUCCESS, NULL); } diff --git a/sway/commands/inhibit_idle.c b/sway/commands/inhibit_idle.c new file mode 100644 index 000000000..aebc2bf9f --- /dev/null +++ b/sway/commands/inhibit_idle.c @@ -0,0 +1,51 @@ +#include +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/desktop/idle_inhibit_v1.h" +#include "sway/tree/container.h" +#include "sway/tree/view.h" + +struct cmd_results *cmd_inhibit_idle(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "inhibit_idle", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + struct sway_container *con = config->handler_context.container; + if (!con || !con->view) { + return cmd_results_new(CMD_INVALID, + "Only views can have idle inhibitors"); + } + + bool clear = false; + enum sway_idle_inhibit_mode mode; + if (strcmp(argv[0], "focus") == 0) { + mode = INHIBIT_IDLE_FOCUS; + } else if (strcmp(argv[0], "fullscreen") == 0) { + mode = INHIBIT_IDLE_FULLSCREEN; + } else if (strcmp(argv[0], "open") == 0) { + mode = INHIBIT_IDLE_OPEN; + } else if (strcmp(argv[0], "none") == 0) { + clear = true; + } else if (strcmp(argv[0], "visible") == 0) { + mode = INHIBIT_IDLE_VISIBLE; + } else { + return cmd_results_new(CMD_INVALID, + "Expected `inhibit_idle focus|fullscreen|open|none|visible`"); + } + + struct sway_idle_inhibitor_v1 *inhibitor = + sway_idle_inhibit_v1_user_inhibitor_for_view(con->view); + if (inhibitor) { + if (clear) { + sway_idle_inhibit_v1_user_inhibitor_destroy(inhibitor); + } else { + inhibitor->mode = mode; + sway_idle_inhibit_v1_check_active(server.idle_inhibit_manager_v1); + } + } else if (!clear) { + sway_idle_inhibit_v1_user_inhibitor_register(con->view, mode); + } + + return cmd_results_new(CMD_SUCCESS, NULL); +} diff --git a/sway/commands/mode.c b/sway/commands/mode.c index 3e0ee80cb..ef2c5d794 100644 --- a/sway/commands/mode.c +++ b/sway/commands/mode.c @@ -13,7 +13,8 @@ static struct cmd_handler mode_handlers[] = { { "bindcode", cmd_bindcode }, { "bindswitch", cmd_bindswitch }, - { "bindsym", cmd_bindsym } + { "bindsym", cmd_bindsym }, + { "set", cmd_set }, }; struct cmd_results *cmd_mode(int argc, char **argv) { diff --git a/sway/commands/output.c b/sway/commands/output.c index 40dbf3ca4..44e28512f 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -18,6 +18,7 @@ static struct cmd_handler output_handlers[] = { { "res", output_cmd_mode }, { "resolution", output_cmd_mode }, { "scale", output_cmd_scale }, + { "subpixel", output_cmd_subpixel }, { "transform", output_cmd_transform }, }; diff --git a/sway/commands/output/subpixel.c b/sway/commands/output/subpixel.c new file mode 100644 index 000000000..63191ee62 --- /dev/null +++ b/sway/commands/output/subpixel.c @@ -0,0 +1,36 @@ +#include +#include "log.h" +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/output.h" + +struct cmd_results *output_cmd_subpixel(int argc, char **argv) { + if (!config->handler_context.output_config) { + return cmd_results_new(CMD_FAILURE, "Missing output config"); + } + if (!argc) { + return cmd_results_new(CMD_INVALID, "Missing subpixel argument."); + } + enum wl_output_subpixel subpixel; + + if (strcmp(*argv, "rgb") == 0) { + subpixel = WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB; + } else if (strcmp(*argv, "bgr") == 0) { + subpixel = WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR; + } else if (strcmp(*argv, "vrgb") == 0) { + subpixel = WL_OUTPUT_SUBPIXEL_VERTICAL_RGB; + } else if (strcmp(*argv, "vbgr") == 0) { + subpixel = WL_OUTPUT_SUBPIXEL_VERTICAL_BGR; + } else if (strcmp(*argv, "none") == 0) { + subpixel = WL_OUTPUT_SUBPIXEL_NONE; + } else { + return cmd_results_new(CMD_INVALID, "Invalid output subpixel."); + } + + struct output_config *oc = config->handler_context.output_config; + config->handler_context.leftovers.argc = argc - 1; + config->handler_context.leftovers.argv = argv + 1; + + oc->subpixel = subpixel; + return NULL; +} diff --git a/sway/commands/rename.c b/sway/commands/rename.c index 88377b092..3b855fdf7 100644 --- a/sway/commands/rename.c +++ b/sway/commands/rename.c @@ -9,6 +9,7 @@ #include "sway/output.h" #include "sway/tree/container.h" #include "sway/tree/workspace.h" +#include "sway/tree/root.h" static const char expected_syntax[] = "Expected 'rename workspace to ' or " @@ -89,6 +90,9 @@ struct cmd_results *cmd_rename(int argc, char **argv) { } sway_log(SWAY_DEBUG, "renaming workspace '%s' to '%s'", workspace->name, new_name); + + root_rename_pid_workspaces(workspace->name, new_name); + free(workspace->name); workspace->name = new_name; diff --git a/sway/config/output.c b/sway/config/output.c index 44aae03aa..d06051b34 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -8,10 +8,11 @@ #include #include #include -#include "log.h" #include "sway/config.h" #include "sway/output.h" #include "sway/tree/root.h" +#include "log.h" +#include "util.h" int output_name_cmp(const void *item, const void *data) { const struct output_config *output = item; @@ -43,6 +44,7 @@ struct output_config *new_output_config(const char *name) { oc->x = oc->y = -1; oc->scale = -1; oc->transform = -1; + oc->subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN; return oc; } @@ -65,6 +67,9 @@ void merge_output_config(struct output_config *dst, struct output_config *src) { if (src->scale != -1) { dst->scale = src->scale; } + if (src->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN) { + dst->subpixel = src->subpixel; + } if (src->refresh_rate != -1) { dst->refresh_rate = src->refresh_rate; } @@ -187,10 +192,10 @@ struct output_config *store_output_config(struct output_config *oc) { } sway_log(SWAY_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " - "position %d,%d scale %f transform %d) (bg %s %s) (dpms %d)", + "position %d,%d scale %f subpixel %s transform %d) (bg %s %s) (dpms %d)", oc->name, oc->enabled, oc->width, oc->height, oc->refresh_rate, - oc->x, oc->y, oc->scale, oc->transform, oc->background, - oc->background_option, oc->dpms_state); + oc->x, oc->y, oc->scale, sway_wl_output_subpixel_to_string(oc->subpixel), + oc->transform, oc->background, oc->background_option, oc->dpms_state); return oc; } @@ -363,6 +368,14 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) { sway_log(SWAY_DEBUG, "Set %s scale to %f", oc->name, oc->scale); wlr_output_set_scale(wlr_output, oc->scale); } + + if (oc && (oc->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN || config->reloading)) { + sway_log(SWAY_DEBUG, "Set %s subpixel to %s", oc->name, + sway_wl_output_subpixel_to_string(oc->subpixel)); + wlr_output_set_subpixel(wlr_output, oc->subpixel); + output_damage_whole(output); + } + if (oc && oc->transform >= 0) { sway_log(SWAY_DEBUG, "Set %s transform to %d", oc->name, oc->transform); wlr_output_set_transform(wlr_output, oc->transform); @@ -424,6 +437,8 @@ static void default_output_config(struct output_config *oc, } oc->x = oc->y = -1; oc->scale = 1; + struct sway_output *output = wlr_output->data; + oc->subpixel = output->detected_subpixel; oc->transform = WL_OUTPUT_TRANSFORM_NORMAL; oc->dpms_state = DPMS_ON; } diff --git a/sway/criteria.c b/sway/criteria.c index f2db6c184..11b41f356 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -16,7 +16,8 @@ #include "config.h" bool criteria_is_empty(struct criteria *criteria) { - return !criteria->title + return !criteria->autofail + && !criteria->title && !criteria->shell && !criteria->app_id && !criteria->con_mark @@ -98,6 +99,10 @@ static void find_urgent_iterator(struct sway_container *con, void *data) { static bool criteria_matches_view(struct criteria *criteria, struct sway_view *view) { + if (criteria->autofail) { + return false; + } + if (criteria->title) { const char *title = view_get_title(view); if (!title || regex_cmp(title, criteria->title) != 0) { @@ -366,50 +371,66 @@ static enum criteria_token token_from_name(char *name) { * using criteria via IPC. Using __focused__ in config is not useful because * criteria is only executed once per view. */ -static char *get_focused_prop(enum criteria_token token) { +static char *get_focused_prop(enum criteria_token token, bool *autofail) { struct sway_seat *seat = input_manager_current_seat(); struct sway_container *focus = seat_get_focused_container(seat); - if (!focus || !focus->view) { - return NULL; - } - struct sway_view *view = focus->view; + struct sway_view *view = focus ? focus->view : NULL; const char *value = NULL; switch (token) { case T_APP_ID: - value = view_get_app_id(view); + *autofail = true; + if (view) { + value = view_get_app_id(view); + } break; case T_SHELL: - value = view_get_shell(view); + *autofail = true; + if (view) { + value = view_get_shell(view); + } break; case T_TITLE: - value = view_get_title(view); + *autofail = true; + if (view) { + value = view_get_title(view); + } break; case T_WORKSPACE: - if (focus->workspace) { + *autofail = true; + if (focus && focus->workspace) { value = focus->workspace->name; } break; case T_CON_ID: - if (view->container == NULL) { - return NULL; + *autofail = true; + if (view && view->container) { + size_t id = view->container->node.id; + size_t id_size = snprintf(NULL, 0, "%zu", id) + 1; + char *id_str = malloc(id_size); + snprintf(id_str, id_size, "%zu", id); + value = id_str; } - size_t id = view->container->node.id; - size_t id_size = snprintf(NULL, 0, "%zu", id) + 1; - char *id_str = malloc(id_size); - snprintf(id_str, id_size, "%zu", id); - value = id_str; break; #if HAVE_XWAYLAND case T_CLASS: - value = view_get_class(view); + *autofail = true; + if (view) { + value = view_get_class(view); + } break; case T_INSTANCE: - value = view_get_instance(view); + *autofail = true; + if (view) { + value = view_get_instance(view); + } break; case T_WINDOW_ROLE: - value = view_get_window_role(view); + *autofail = true; + if (view) { + value = view_get_window_role(view); + } break; case T_WINDOW_TYPE: // These do not support __focused__ case T_ID: @@ -419,6 +440,7 @@ static char *get_focused_prop(enum criteria_token token) { case T_TILING: case T_URGENT: case T_INVALID: + *autofail = false; break; } if (value) { @@ -439,7 +461,12 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) { char *effective_value = NULL; if (value && strcmp(value, "__focused__") == 0) { - effective_value = get_focused_prop(token); + bool autofail = false; + effective_value = get_focused_prop(token, &autofail); + if (!effective_value && autofail) { + criteria->autofail = true; + return true; + } } else if (value) { effective_value = strdup(value); } diff --git a/sway/desktop/idle_inhibit_v1.c b/sway/desktop/idle_inhibit_v1.c index 87b4ef43d..b981e5e5a 100644 --- a/sway/desktop/idle_inhibit_v1.c +++ b/sway/desktop/idle_inhibit_v1.c @@ -2,18 +2,24 @@ #include #include "log.h" #include "sway/desktop/idle_inhibit_v1.h" +#include "sway/input/seat.h" +#include "sway/tree/container.h" #include "sway/tree/view.h" #include "sway/server.h" +static void destroy_inhibitor(struct sway_idle_inhibitor_v1 *inhibitor) { + wl_list_remove(&inhibitor->link); + wl_list_remove(&inhibitor->destroy.link); + sway_idle_inhibit_v1_check_active(inhibitor->manager); + free(inhibitor); +} + static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_idle_inhibitor_v1 *inhibitor = wl_container_of(listener, inhibitor, destroy); sway_log(SWAY_DEBUG, "Sway idle inhibitor destroyed"); - wl_list_remove(&inhibitor->link); - wl_list_remove(&inhibitor->destroy.link); - idle_inhibit_v1_check_active(inhibitor->manager); - free(inhibitor); + destroy_inhibitor(inhibitor); } void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) { @@ -29,28 +35,93 @@ void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) { } inhibitor->manager = manager; + inhibitor->mode = INHIBIT_IDLE_APPLICATION; inhibitor->view = view_from_wlr_surface(wlr_inhibitor->surface); wl_list_insert(&manager->inhibitors, &inhibitor->link); - inhibitor->destroy.notify = handle_destroy; wl_signal_add(&wlr_inhibitor->events.destroy, &inhibitor->destroy); - idle_inhibit_v1_check_active(manager); + sway_idle_inhibit_v1_check_active(manager); } -void idle_inhibit_v1_check_active( +void sway_idle_inhibit_v1_user_inhibitor_register(struct sway_view *view, + enum sway_idle_inhibit_mode mode) { + struct sway_idle_inhibitor_v1 *inhibitor = + calloc(1, sizeof(struct sway_idle_inhibitor_v1)); + if (!inhibitor) { + return; + } + + inhibitor->manager = server.idle_inhibit_manager_v1; + inhibitor->mode = mode; + inhibitor->view = view; + wl_list_insert(&inhibitor->manager->inhibitors, &inhibitor->link); + + inhibitor->destroy.notify = handle_destroy; + wl_signal_add(&view->events.unmap, &inhibitor->destroy); + + sway_idle_inhibit_v1_check_active(inhibitor->manager); +} + +struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_user_inhibitor_for_view( + struct sway_view *view) { + struct sway_idle_inhibitor_v1 *inhibitor; + wl_list_for_each(inhibitor, &server.idle_inhibit_manager_v1->inhibitors, + link) { + if (inhibitor->view == view && + inhibitor->mode != INHIBIT_IDLE_APPLICATION) { + return inhibitor; + } + } + return NULL; +} + +void sway_idle_inhibit_v1_user_inhibitor_destroy( + struct sway_idle_inhibitor_v1 *inhibitor) { + if (!inhibitor) { + return; + } + if (!sway_assert(inhibitor->mode != INHIBIT_IDLE_APPLICATION, + "User should not be able to destroy application inhibitor")) { + return; + } + destroy_inhibitor(inhibitor); +} + +static bool check_active(struct sway_idle_inhibitor_v1 *inhibitor) { + switch (inhibitor->mode) { + case INHIBIT_IDLE_APPLICATION: + // If there is no view associated with the inhibitor, assume visible + return !inhibitor->view || view_is_visible(inhibitor->view); + case INHIBIT_IDLE_FOCUS:; + struct sway_seat *seat = NULL; + wl_list_for_each(seat, &server.input->seats, link) { + struct sway_container *con = seat_get_focused_container(seat); + if (con && con->view && con->view == inhibitor->view) { + return true; + } + } + return false; + case INHIBIT_IDLE_FULLSCREEN: + return inhibitor->view->container && + container_is_fullscreen_or_child(inhibitor->view->container) && + view_is_visible(inhibitor->view); + case INHIBIT_IDLE_OPEN: + // Inhibitor is destroyed on unmap so it must be open/mapped + return true; + case INHIBIT_IDLE_VISIBLE: + return view_is_visible(inhibitor->view); + } + return false; +} + +void sway_idle_inhibit_v1_check_active( struct sway_idle_inhibit_manager_v1 *manager) { struct sway_idle_inhibitor_v1 *inhibitor; bool inhibited = false; wl_list_for_each(inhibitor, &manager->inhibitors, link) { - if (!inhibitor->view || !inhibitor->view->container) { - /* Cannot guess if view is visible so assume it is */ - inhibited = true; - break; - } - if (view_is_visible(inhibitor->view)) { - inhibited = true; + if ((inhibited = check_active(inhibitor))) { break; } } diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index e5f0ee3d1..51c6e7fca 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -349,7 +349,7 @@ static void transaction_progress_queue(void) { list_del(server.transactions, 0); if (!server.transactions->length) { - idle_inhibit_v1_check_active(server.idle_inhibit_manager_v1); + sway_idle_inhibit_v1_check_active(server.idle_inhibit_manager_v1); return; } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index f5ade8dcb..37d0b986a 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -435,7 +435,7 @@ static void handle_request_configure(struct wl_listener *listener, void *data) { // Respect minimum and maximum sizes view->natural_width = ev->width; view->natural_height = ev->height; - container_init_floating(view->container); + container_floating_resize_and_center(view->container); configure(view, view->container->content_x, view->container->content_y, diff --git a/sway/input/seatop_move_tiling.c b/sway/input/seatop_move_tiling.c index 0a2480919..64a16c098 100644 --- a/sway/input/seatop_move_tiling.c +++ b/sway/input/seatop_move_tiling.c @@ -108,7 +108,7 @@ static void handle_motion_postthreshold(struct sway_seat *seat) { } if (node->type == N_WORKSPACE) { - // Emtpy workspace + // Empty workspace e->target_node = node; e->target_edge = WLR_EDGE_NONE; workspace_get_box(node->sway_workspace, &e->drop_box); @@ -164,7 +164,7 @@ 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 || !con->view->surface || node == &e->con->node || node_has_ancestor(node, &e->con->node)) { e->target_node = NULL; e->target_edge = WLR_EDGE_NONE; diff --git a/sway/ipc-server.c b/sway/ipc-server.c index df57cba51..e133a5bf1 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -644,6 +644,8 @@ void ipc_client_handle_command(struct ipc_client *client) { json_object_object_add(output_json, "focused", json_object_new_boolean(focused)); + const char *subpixel = sway_wl_output_subpixel_to_string(output->wlr_output->subpixel); + json_object_object_add(output_json, "subpixel_hinting", json_object_new_string(subpixel)); json_object_array_add(outputs, output_json); } struct sway_output *output; diff --git a/sway/meson.build b/sway/meson.build index 66876bdcd..12b86efb8 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -63,6 +63,7 @@ sway_sources = files( 'commands/fullscreen.c', 'commands/gaps.c', 'commands/hide_edge_borders.c', + 'commands/inhibit_idle.c', 'commands/kill.c', 'commands/mark.c', 'commands/opacity.c', @@ -169,6 +170,7 @@ sway_sources = files( 'commands/output/mode.c', 'commands/output/position.c', 'commands/output/scale.c', + 'commands/output/subpixel.c', 'commands/output/transform.c', 'tree/arrange.c', diff --git a/sway/sway-ipc.7.scd b/sway/sway-ipc.7.scd index b43b30302..3d22008e4 100644 --- a/sway/sway-ipc.7.scd +++ b/sway/sway-ipc.7.scd @@ -211,6 +211,9 @@ following properties: |- scale : float : The scale currently in use on the output or _-1_ for disabled outputs +|- subpixel_hinting +: string +: The subpixel hinting current in use on the output. This can be _rgb_, _bgr_, _vrgb_, _vbgr_, or _none_ |- transform : string : The transform currently in use for the output. This can be _normal_, _90_, @@ -242,6 +245,7 @@ following properties: "active": true, "primary": false, "scale": 1.0, + "subpixel_hinting": "rgb", "transform": "normal", "current_workspace": "1", "modes": [ diff --git a/sway/sway-output.5.scd b/sway/sway-output.5.scd index bb3745f36..1efe2f7bf 100644 --- a/sway/sway-output.5.scd +++ b/sway/sway-output.5.scd @@ -64,6 +64,13 @@ must be separated by one space. For example: applications to taste. HiDPI isn't supported with Xwayland clients (windows will blur). +*output* subpixel rgb|bgr|vrgb|vbgr|none + Manually sets the subpixel hinting for the specified output. This value is + usually auto-detected, but some displays may misreport their subpixel + geometry. Using the correct subpixel hinting allows for sharper text. + Incorrect values will result in blurrier text. When changing this via + *swaymsg*, some applications may need to be restarted to use the new value. + *output* background|bg [] Sets the wallpaper for the given output to the specified file, using the given scaling mode (one of "stretch", "fill", "fit", "center", "tile"). If diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 18fc28a30..1650cd60c 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -146,6 +146,18 @@ set|plus|minus _right_, _bottom_, and _left_ or per direction with _horizontal_ and _vertical_. +*inhibit_idle* focus|fullscreen|open|none|visible + Set/unset an idle inhibitor for the view. _focus_ will inhibit idle when + the view is focused by any seat. _fullscreen_ will inhibit idle when the + view is fullscreen (or a descendant of a fullscreen container) and is + visible. _open_ will inhibit idle until the view is closed (or the + inhibitor is unset/changed). _visible_ will inhibit idle when the view is + visible on any output. _none_ will remove any existing idle inhibitor for + the view. + + This can also be used with criteria to set an idle inhibitor for any + existing view or with _for_window_ to set idle inhibitors for future views. + *layout* default|splith|splitv|stacking|tabbed Sets the layout mode of the focused container. @@ -573,9 +585,9 @@ The default colors are: Switches to the specified mode. The default mode _default_. *mode* [--pango_markup] - The only valid _mode-subcommands..._ are *bindsym*, *bindcode* and - *bindswitch*. If _--pango_markup_ is given, then _mode_ will be interpreted - as pango markup. + The only valid _mode-subcommands..._ are *bindsym*, *bindcode*, + *bindswitch*, and *set*. If _--pango_markup_ is given, then _mode_ will be + interpreted as pango markup. *mouse_warping* output|container|none If _output_ is specified, the mouse will be moved to new outputs as you diff --git a/sway/tree/container.c b/sway/tree/container.c index 93cff7ff5..02b4d1b0e 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -649,18 +649,45 @@ void floating_calculate_constraints(int *min_width, int *max_width, } -void container_init_floating(struct sway_container *con) { - struct sway_workspace *ws = con->workspace; +static void floating_natural_resize(struct sway_container *con) { int min_width, max_width, min_height, max_height; floating_calculate_constraints(&min_width, &max_width, &min_height, &max_height); - if (!con->view) { - con->width = max_width; - con->height = max_height; + con->width = fmax(min_width, fmin(con->width, max_width)); + con->height = fmax(min_height, fmin(con->height, max_height)); + } else { + struct sway_view *view = con->view; + con->content_width = + fmax(min_width, fmin(view->natural_width, max_width)); + con->content_height = + fmax(min_height, fmin(view->natural_height, max_height)); + container_set_geometry_from_content(con); + } +} + +void container_floating_resize_and_center(struct sway_container *con) { + struct sway_workspace *ws = con->workspace; + if (!ws) { + // On scratchpad, just resize + floating_natural_resize(con); + return; + } + + struct wlr_box *ob = wlr_output_layout_get_box(root->output_layout, + ws->output->wlr_output); + if (!ob) { + // On NOOP output. Will be called again when moved to an output + con->x = 0; + con->y = 0; + con->width = 0; + con->height = 0; + return; + } + + floating_natural_resize(con); + if (!con->view) { if (con->width > ws->width || con->height > ws->height) { - struct wlr_box *ob = wlr_output_layout_get_box(root->output_layout, - ws->output->wlr_output); con->x = ob->x + (ob->width - con->width) / 2; con->y = ob->y + (ob->height - con->height) / 2; } else { @@ -668,15 +695,8 @@ void container_init_floating(struct sway_container *con) { con->y = ws->y + (ws->height - con->height) / 2; } } else { - struct sway_view *view = con->view; - con->content_width = - fmax(min_width, fmin(view->natural_width, max_width)); - con->content_height = - fmax(min_height, fmin(view->natural_height, max_height)); if (con->content_width > ws->width || con->content_height > ws->height) { - struct wlr_box *ob = wlr_output_layout_get_box(root->output_layout, - ws->output->wlr_output); con->content_x = ob->x + (ob->width - con->content_width) / 2; con->content_y = ob->y + (ob->height - con->content_height) / 2; } else { @@ -692,6 +712,31 @@ void container_init_floating(struct sway_container *con) { } } +void container_floating_set_default_size(struct sway_container *con) { + if (!sway_assert(con->workspace, "Expected a container on a workspace")) { + return; + } + + int min_width, max_width, min_height, max_height; + floating_calculate_constraints(&min_width, &max_width, + &min_height, &max_height); + struct wlr_box *box = calloc(1, sizeof(struct wlr_box)); + workspace_get_box(con->workspace, box); + + double width = fmax(min_width, fmin(box->width * 0.5, max_width)); + double height = fmax(min_height, fmin(box->height * 0.75, max_height)); + if (!con->view) { + con->width = width; + con->height = height; + } else { + con->content_width = width; + con->content_height = height; + container_set_geometry_from_content(con); + } + + free(box); +} + void container_set_floating(struct sway_container *container, bool enable) { if (container_is_floating(container) == enable) { return; @@ -704,7 +749,8 @@ void container_set_floating(struct sway_container *container, bool enable) { struct sway_container *old_parent = container->parent; container_detach(container); workspace_add_floating(workspace, container); - container_init_floating(container); + container_floating_set_default_size(container); + container_floating_resize_and_center(container); if (container->view) { view_set_tiled(container->view, false); if (container->view->using_csd) { @@ -988,7 +1034,7 @@ void container_fullscreen_disable(struct sway_container *con) { // criteria, it needs to be reinitialized as floating to get the proper // size and location if (container_is_floating(con) && (con->width == 0 || con->height == 0)) { - container_init_floating(con); + container_floating_resize_and_center(con); } con->fullscreen_mode = FULLSCREEN_NONE; diff --git a/sway/tree/output.c b/sway/tree/output.c index 1202ba3c5..b3589be5d 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -60,6 +60,27 @@ static void restore_workspaces(struct sway_output *output) { struct sway_workspace *ws = root->noop_output->workspaces->items[0]; workspace_detach(ws); output_add_workspace(output, ws); + + // If the floater was made floating while on the NOOP output, its width + // and height will be zero and it should be reinitialized as a floating + // container to get the appropriate size and location. Additionally, if + // the floater is wider or taller than the output or is completely + // outside of the output's bounds, do the same as the output layout has + // likely changed and the maximum size needs to be checked and the + // floater re-centered + for (int i = 0; i < ws->floating->length; i++) { + struct sway_container *floater = ws->floating->items[i]; + if (floater->width == 0 || floater->height == 0 || + floater->width > output->width || + floater->height > output->height || + floater->x > output->lx + output->width || + floater->y > output->ly + output->height || + floater->x + floater->width < output->lx || + floater->y + floater->height < output->ly) { + container_floating_resize_and_center(floater); + } + } + ipc_event_workspace(NULL, ws, "move"); } @@ -71,6 +92,7 @@ struct sway_output *output_create(struct wlr_output *wlr_output) { node_init(&output->node, N_OUTPUT, output); output->wlr_output = wlr_output; wlr_output->data = output; + output->detected_subpixel = wlr_output->subpixel; wl_signal_init(&output->events.destroy); diff --git a/sway/tree/root.c b/sway/tree/root.c index 0744192b2..3d93405e4 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c @@ -62,6 +62,8 @@ void root_scratchpad_add_container(struct sway_container *con) { struct sway_container *parent = con->parent; struct sway_workspace *workspace = con->workspace; container_set_floating(con, true); + container_floating_set_default_size(con); + container_floating_move_to_center(con); container_detach(con); con->scratchpad = true; list_add(root->scratchpad, con); @@ -124,15 +126,7 @@ void root_scratchpad_show(struct sway_container *con) { struct wlr_box workspace_box; workspace_get_box(new_ws, &workspace_box); if (!wlr_box_contains_point(&workspace_box, center_lx, center_ly)) { - // Maybe resize it - if (con->width > new_ws->width || con->height > new_ws->height) { - container_init_floating(con); - } - - // Center it - double new_lx = new_ws->x + (new_ws->width - con->width) / 2; - double new_ly = new_ws->y + (new_ws->height - con->height) / 2; - container_floating_move_to(con, new_lx, new_ly); + container_floating_resize_and_center(con); } arrange_workspace(new_ws); @@ -390,3 +384,17 @@ void root_get_box(struct sway_root *root, struct wlr_box *box) { box->width = root->width; box->height = root->height; } + +void root_rename_pid_workspaces(const char *old_name, const char *new_name) { + if (!pid_workspaces.prev && !pid_workspaces.next) { + wl_list_init(&pid_workspaces); + } + + struct pid_workspace *pw = NULL; + wl_list_for_each(pw, &pid_workspaces, link) { + if (strcmp(pw->workspace, old_name) == 0) { + free(pw->workspace); + pw->workspace = strdup(new_name); + } + } +} diff --git a/swaybar/tray/icon.c b/swaybar/tray/icon.c index 8587f3f7b..56f230e14 100644 --- a/swaybar/tray/icon.c +++ b/swaybar/tray/icon.c @@ -348,6 +348,9 @@ void init_themes(list_t **themes, list_t **basedirs) { *themes = create_list(); for (int i = 0; i < (*basedirs)->length; ++i) { list_t *dir_themes = load_themes_in_dir((*basedirs)->items[i]); + if (dir_themes == NULL) { + continue; + } list_cat(*themes, dir_themes); list_free(dir_themes); } diff --git a/swaymsg/main.c b/swaymsg/main.c index 65cc4bbb1..f86000a42 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -186,11 +186,12 @@ static void pretty_print_output(json_object *o) { json_object_object_get_ex(o, "focused", &focused); json_object_object_get_ex(o, "active", &active); json_object_object_get_ex(o, "current_workspace", &ws); - json_object *make, *model, *serial, *scale, *transform; + json_object *make, *model, *serial, *scale, *subpixel, *transform; json_object_object_get_ex(o, "make", &make); json_object_object_get_ex(o, "model", &model); json_object_object_get_ex(o, "serial", &serial); json_object_object_get_ex(o, "scale", &scale); + json_object_object_get_ex(o, "subpixel_hinting", &subpixel); json_object_object_get_ex(o, "transform", &transform); json_object *x, *y; json_object_object_get_ex(rect, "x", &x); @@ -209,6 +210,7 @@ static void pretty_print_output(json_object *o) { " Current mode: %dx%d @ %f Hz\n" " Position: %d,%d\n" " Scale factor: %f\n" + " Subpixel hinting: %s\n" " Transform: %s\n" " Workspace: %s\n", json_object_get_string(name), @@ -221,6 +223,7 @@ static void pretty_print_output(json_object *o) { (float)json_object_get_int(refresh) / 1000, json_object_get_int(x), json_object_get_int(y), json_object_get_double(scale), + json_object_get_string(subpixel), json_object_get_string(transform), json_object_get_string(ws) );