diff -Nru sway-1.6.1/.builds/alpine.yml sway-1.7/.builds/alpine.yml --- sway-1.6.1/.builds/alpine.yml 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/.builds/alpine.yml 2022-01-22 22:55:11.000000000 +0000 @@ -21,7 +21,7 @@ - xwayland sources: - https://github.com/swaywm/sway - - https://github.com/swaywm/wlroots#0.14.0 + - https://gitlab.freedesktop.org/wlroots/wlroots.git#0.15.0 tasks: - wlroots: | cd wlroots @@ -30,7 +30,7 @@ sudo ninja -C build install - setup: | cd sway - meson build -Dauto_features=enabled -Dtray=disabled + meson build --fatal-meson-warnings -Dauto_features=enabled -Dtray=disabled - build: | cd sway ninja -C build @@ -43,5 +43,5 @@ mkdir subprojects ln -s ../../wlroots subprojects/wlroots rm -rf build - meson build --default-library=static --force-fallback-for=wlroots + meson build --fatal-meson-warnings --default-library=static --force-fallback-for=wlroots ninja -C build diff -Nru sway-1.6.1/.builds/archlinux.yml sway-1.7/.builds/archlinux.yml --- sway-1.6.1/.builds/archlinux.yml 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/.builds/archlinux.yml 2022-01-22 22:55:11.000000000 +0000 @@ -18,7 +18,7 @@ - seatd sources: - https://github.com/swaywm/sway - - https://github.com/swaywm/wlroots#0.14.0 + - https://gitlab.freedesktop.org/wlroots/wlroots.git#0.15.0 tasks: - wlroots: | cd wlroots @@ -27,7 +27,7 @@ sudo ninja -C build install - setup: | cd sway - meson build -Dauto_features=enabled -Dsd-bus-provider=libsystemd + meson build --fatal-meson-warnings -Dauto_features=enabled -Dsd-bus-provider=libsystemd - build: | cd sway ninja -C build diff -Nru sway-1.6.1/.builds/freebsd.yml sway-1.7/.builds/freebsd.yml --- sway-1.6.1/.builds/freebsd.yml 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/.builds/freebsd.yml 2022-01-22 22:55:11.000000000 +0000 @@ -26,7 +26,7 @@ - x11/xcb-util-wm sources: - https://github.com/swaywm/sway -- https://github.com/swaywm/wlroots#0.14.0 +- https://gitlab.freedesktop.org/wlroots/wlroots.git#0.15.0 tasks: - setup: | cd sway @@ -34,7 +34,7 @@ cd subprojects ln -s ../../wlroots wlroots cd .. - meson build -Dtray=enabled -Dsd-bus-provider=basu + meson build --fatal-meson-warnings -Dtray=enabled -Dsd-bus-provider=basu - build: | cd sway ninja -C build diff -Nru sway-1.6.1/.clang-format sway-1.7/.clang-format --- sway-1.6.1/.clang-format 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/.clang-format 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -BasedOnStyle: LLVM -IndentWidth: 4 -TabWidth: 4 -UseTab: Always -BreakBeforeBraces: Attach -AllowShortIfStatementsOnASingleLine: false -IndentCaseLabels: false -SortIncludes: false -ColumnLimit: 80 -AlignAfterOpenBracket: DontAlign -BinPackParameters: false -BinPackArguments: false -ContinuationIndentWidth: 8 -AllowAllParametersOfDeclarationOnNextLine: false -AllowShortLoopsOnASingleLine: true -ReflowComments: false diff -Nru sway-1.6.1/common/pango.c sway-1.7/common/pango.c --- sway-1.6.1/common/pango.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/common/pango.c 2022-01-22 22:55:11.000000000 +0000 @@ -109,7 +109,23 @@ free(buf); } -void pango_printf(cairo_t *cairo, const char *font, +void get_text_metrics(const char *font, int *height, int *baseline) { + cairo_t *cairo = cairo_create(NULL); + PangoContext *pango = pango_cairo_create_context(cairo); + PangoFontDescription *description = pango_font_description_from_string(font); + // When passing NULL as a language, pango uses the current locale. + PangoFontMetrics *metrics = pango_context_get_metrics(pango, description, NULL); + + *baseline = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE; + *height = *baseline + pango_font_metrics_get_descent(metrics) / PANGO_SCALE; + + pango_font_metrics_unref(metrics); + pango_font_description_free(description); + g_object_unref(pango); + cairo_destroy(cairo); +} + +void render_text(cairo_t *cairo, const char *font, double scale, bool markup, const char *fmt, ...) { va_list args; va_start(args, fmt); diff -Nru sway-1.6.1/common/util.c sway-1.7/common/util.c --- sway-1.6.1/common/util.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/common/util.c 2022-01-22 22:55:11.000000000 +0000 @@ -80,6 +80,12 @@ int parse_movement_amount(int argc, char **argv, struct movement_amount *amount) { + if (!sway_assert(argc > 0, "Expected args in parse_movement_amount")) { + amount->amount = 0; + amount->unit = MOVEMENT_UNIT_INVALID; + return 0; + } + char *err; amount->amount = (int)strtol(argv[0], &err, 10); if (*err) { diff -Nru sway-1.6.1/config.in sway-1.7/config.in --- sway-1.6.1/config.in 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/config.in 2022-01-22 22:55:11.000000000 +0000 @@ -14,7 +14,7 @@ set $up k set $right l # Your preferred terminal emulator -set $term alacritty +set $term foot # Your preferred application launcher # Note: pass the final command to swaymsg so that the resulting window can be opened # on the original workspace that the command was run on. @@ -82,7 +82,7 @@ bindsym $mod+Shift+c reload # Exit sway (logs you out of your Wayland session) - bindsym $mod+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -b 'Yes, exit sway' 'swaymsg exit' + bindsym $mod+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -B 'Yes, exit sway' 'swaymsg exit' # # Moving around: # @@ -205,7 +205,7 @@ # When the status_command prints a new line to stdout, swaybar updates. # The default just shows the current date and time. - status_command while date +'%Y-%m-%d %l:%M:%S %p'; do sleep 1; done + status_command while date +'%Y-%m-%d %I:%M:%S %p'; do sleep 1; done colors { statusline #ffffff diff -Nru sway-1.6.1/contrib/autoname-workspaces.py sway-1.7/contrib/autoname-workspaces.py --- sway-1.6.1/contrib/autoname-workspaces.py 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/contrib/autoname-workspaces.py 2022-01-22 22:55:11.000000000 +0000 @@ -22,24 +22,17 @@ 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 @@ rename_workspaces(ipc) ipc.main() + diff -Nru sway-1.6.1/contrib/grimshot sway-1.7/contrib/grimshot --- sway-1.6.1/contrib/grimshot 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/contrib/grimshot 2022-01-22 22:55:11.000000000 +0000 @@ -113,7 +113,7 @@ GEOM=$(slurp -d) # Check if user exited slurp without selecting the area if [ -z "$GEOM" ]; then - exit + exit 1 fi WHAT="Area" elif [ "$SUBJECT" = "active" ] ; then @@ -132,7 +132,7 @@ GEOM=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | .rect | "\(.x),\(.y) \(.width)x\(.height)"' | slurp) # Check if user exited slurp without selecting the area if [ -z "$GEOM" ]; then - exit + exit 1 fi WHAT="Window" else diff -Nru sway-1.6.1/contrib/_incr_version sway-1.7/contrib/_incr_version --- sway-1.6.1/contrib/_incr_version 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/contrib/_incr_version 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -#!/bin/sh -eu -old_version="$1" -new_version="$2" - -if [ "$new_version" != "${new_version#v}" ] -then - echo "Error: The new version shouldn't be prefixed with a \"v\"." >&2 - exit 1 -fi - -sed -i meson.build -e "s/^ version: .*#release_version/ version: '$new_version', #release_version/g" - -printf "Minimum wlroots version? " -read wlr_version_min -printf "Maximum wlroots version? " -read wlr_version_max - -sed -i meson.build -e "s/wlroots_version =.*/wlroots_version = ['>=$wlr_version_min', '<$wlr_version_max']/" - -git add meson.build -git commit -m "Update version to $new_version" diff -Nru sway-1.6.1/CONTRIBUTING.md sway-1.7/CONTRIBUTING.md --- sway-1.6.1/CONTRIBUTING.md 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/CONTRIBUTING.md 2022-01-22 22:55:11.000000000 +0000 @@ -1,9 +1,8 @@ # Contributing to sway Contributing just involves sending a pull request. You will probably be more -successful with your contribution if you visit -[#sway-devel](https://webchat.freenode.net/?channels=sway-devel) on -irc.freenode.net upfront and discuss your plans. +successful with your contribution if you visit #sway-devel on Libera Chat +upfront and discuss your plans. Note: rules are made to be broken. Adjust or ignore any/all of these as you see fit, but be prepared to justify it to your peers. diff -Nru sway-1.6.1/debian/changelog sway-1.7/debian/changelog --- sway-1.6.1/debian/changelog 2021-12-17 06:42:23.000000000 +0000 +++ sway-1.7/debian/changelog 2022-02-16 09:00:35.000000000 +0000 @@ -1,3 +1,15 @@ +sway (1.7-1) experimental; urgency=medium + + * New upstream release. + * Bump min. version of wlroots build dependency to 0.15 + * Bump min. version of wayland-protocols to 1.24 + * Set min version of libwayland-dev to 1.20 + * Drop filenamemangle option from d/watch + * Update patch for default configuration file + * Update year range in d/copyright stanza for debian/* + + -- Birger Schacht Wed, 16 Feb 2022 10:00:35 +0100 + sway (1.6.1-2) unstable; urgency=medium * Replace dependency on pcre with pcre2 (Closes: #999950) diff -Nru sway-1.6.1/debian/control sway-1.7/debian/control --- sway-1.6.1/debian/control 2021-12-17 06:42:23.000000000 +0000 +++ sway-1.7/debian/control 2022-02-16 09:00:35.000000000 +0000 @@ -18,15 +18,15 @@ libpixman-1-dev, libseat-dev, libsystemd-dev (>= 239) | libelogind-dev (>= 239), - libwayland-dev, + libwayland-dev (>= 1.20.0), libwayland-egl1, - libwlroots-dev (>= 0.14.0), + libwlroots-dev (>= 0.15.0), libxkbcommon-dev, meson (>=0.48), pkgconf, scdoc (>= 1.9.2), tree, - wayland-protocols (>= 1.14) + wayland-protocols (>= 1.24) Standards-Version: 4.6.0.1 Homepage: http://swaywm.org Vcs-Browser: https://salsa.debian.org/swaywm-team/sway diff -Nru sway-1.6.1/debian/copyright sway-1.7/debian/copyright --- sway-1.6.1/debian/copyright 2021-12-17 06:42:23.000000000 +0000 +++ sway-1.7/debian/copyright 2022-02-16 09:00:35.000000000 +0000 @@ -23,7 +23,7 @@ Files: debian/* Copyright: © 2018 Nicolas Braud-Santoni - © 2018-2021 Birger Schacht + © 2018-2022 Birger Schacht License: Expat License: LGPL-2.1+ diff -Nru sway-1.6.1/debian/patches/0002-Modify-default-configuration-for-Debian.patch sway-1.7/debian/patches/0002-Modify-default-configuration-for-Debian.patch --- sway-1.6.1/debian/patches/0002-Modify-default-configuration-for-Debian.patch 2021-12-17 06:42:23.000000000 +0000 +++ sway-1.7/debian/patches/0002-Modify-default-configuration-for-Debian.patch 2022-02-16 09:00:35.000000000 +0000 @@ -1,24 +1,17 @@ -From a5d3402a4464eea5879dace2cdd95eb3ac064e60 Mon Sep 17 00:00:00 2001 -From: Birger Schacht +From 6505312841f4ced790ad46ba2d89c387bd932107 Mon Sep 17 00:00:00 2001 +From: Birger Schacht Date: Thu, 5 Nov 2020 22:28:39 +0100 Subject: [PATCH] Modify default configuration for Debian --- - config.in | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) + config.in | 2 ++ + 1 file changed, 2 insertions(+) diff --git a/config.in b/config.in -index 08703bef..31ec6def 100644 +index 94050ba6..19d3ecb3 100644 --- a/config.in +++ b/config.in -@@ -14,12 +14,14 @@ set $down j - set $up k - set $right l - # Your preferred terminal emulator --set $term alacritty -+set $term foot - # Your preferred application launcher - # Note: pass the final command to swaymsg so that the resulting window can be opened +@@ -20,6 +20,8 @@ set $term foot # on the original workspace that the command was run on. set $menu dmenu_path | dmenu | xargs swaymsg exec -- @@ -28,5 +21,5 @@ # # Default wallpaper (more resolutions are available in @datadir@/backgrounds/sway/) -- -2.29.2 +2.34.1 diff -Nru sway-1.6.1/debian/watch sway-1.7/debian/watch --- sway-1.6.1/debian/watch 2021-12-17 06:42:23.000000000 +0000 +++ sway-1.7/debian/watch 2022-02-16 09:00:35.000000000 +0000 @@ -1,5 +1,4 @@ version=4 opts=uversionmangle=s/(\d)[_\.\-\+]?((rc|beta|alpha)[\d.]*)$/$1~$2/,\ -filenamemangle=s/.+\/v?(\d\S+)\.tar\.gz/sway-$1\.tar\.gz/,\ pgpsigurlmangle=s/archive\/v?(\d\S+)\.tar\.gz/releases\/download\/$1\/sway-$1\.tar\.gz\.sig/ \ https://github.com/swaywm/sway/releases .*/archive/refs/tags/v?(\d\S+)\.tar\.gz diff -Nru sway-1.6.1/.github/ISSUE_TEMPLATE/bug_report.md sway-1.7/.github/ISSUE_TEMPLATE/bug_report.md --- sway-1.6.1/.github/ISSUE_TEMPLATE/bug_report.md 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/.github/ISSUE_TEMPLATE/bug_report.md 2022-01-22 22:55:11.000000000 +0000 @@ -6,9 +6,8 @@ --- ### Please read the following before submitting: -- Please do NOT submit bug reports for questions. Ask questions on IRC at #sway on irc.freenode.net. +- Please do NOT submit bug reports for questions. Ask questions on IRC at #sway on Libera Chat. - 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. @@ -19,6 +18,7 @@ - **Debug Log:** - Run `sway -d 2> ~/sway.log` from a TTY and upload it to a pastebin, such as gist.github.com. - This will record information about sway's activity. Please try to keep the reproduction as brief as possible and exit sway. + - Attach the **full** file, do not truncate it. - **Configuration File:** - Please try to produce with the default configuration. diff -Nru sway-1.6.1/.github/ISSUE_TEMPLATE/config.yml sway-1.7/.github/ISSUE_TEMPLATE/config.yml --- sway-1.6.1/.github/ISSUE_TEMPLATE/config.yml 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/.github/ISSUE_TEMPLATE/config.yml 2022-01-22 22:55:11.000000000 +0000 @@ -1,5 +1,5 @@ blank_issues_enabled: false contact_links: - name: Questions - url: "http://webchat.freenode.net/?channels=sway&uio=d4" - about: "Please ask questions on IRC in #sway on irc.freenode.net" + url: "https://libera.chat" + about: "Please ask questions on IRC in #sway on Libera Chat" diff -Nru sway-1.6.1/include/ipc-client.h sway-1.7/include/ipc-client.h --- sway-1.6.1/include/ipc-client.h 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/include/ipc-client.h 2022-01-22 22:55:11.000000000 +0000 @@ -1,6 +1,9 @@ #ifndef _SWAY_IPC_CLIENT_H #define _SWAY_IPC_CLIENT_H +// arbitrary number, it's probably sufficient, higher number = more memory usage +#define JSON_MAX_DEPTH 512 + #include #include #include diff -Nru sway-1.6.1/include/pango.h sway-1.7/include/pango.h --- sway-1.6.1/include/pango.h 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/include/pango.h 2022-01-22 22:55:11.000000000 +0000 @@ -17,7 +17,8 @@ const char *text, double scale, bool markup); void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, int *baseline, double scale, bool markup, const char *fmt, ...); -void pango_printf(cairo_t *cairo, const char *font, +void get_text_metrics(const char *font, int *height, int *baseline); +void render_text(cairo_t *cairo, const char *font, double scale, bool markup, const char *fmt, ...); #endif diff -Nru sway-1.6.1/include/sway/commands.h sway-1.7/include/sway/commands.h --- sway-1.6.1/include/sway/commands.h 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/include/sway/commands.h 2022-01-22 22:55:11.000000000 +0000 @@ -112,6 +112,7 @@ sway_cmd cmd_client_noop; sway_cmd cmd_client_focused; sway_cmd cmd_client_focused_inactive; +sway_cmd cmd_client_focused_tab_title; sway_cmd cmd_client_unfocused; sway_cmd cmd_client_urgent; sway_cmd cmd_client_placeholder; @@ -282,7 +283,9 @@ sway_cmd output_cmd_enable; sway_cmd output_cmd_max_render_time; sway_cmd output_cmd_mode; +sway_cmd output_cmd_modeline; sway_cmd output_cmd_position; +sway_cmd output_cmd_render_bit_depth; sway_cmd output_cmd_scale; sway_cmd output_cmd_scale_filter; sway_cmd output_cmd_subpixel; diff -Nru sway-1.6.1/include/sway/config.h sway-1.7/include/sway/config.h --- sway-1.6.1/include/sway/config.h 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/include/sway/config.h 2022-01-22 22:55:11.000000000 +0000 @@ -5,9 +5,10 @@ #include #include #include -#include #include +#include #include +#include #include "../include/config.h" #include "list.h" #include "swaynag.h" @@ -246,6 +247,12 @@ SCALE_FILTER_SMART, }; +enum render_bit_depth { + RENDER_BIT_DEPTH_DEFAULT, // the default is currently 8 + RENDER_BIT_DEPTH_8, + RENDER_BIT_DEPTH_10, +}; + /** * Size and position configuration for a particular output. * @@ -257,6 +264,7 @@ int width, height; float refresh_rate; int custom_mode; + drmModeModeInfo drm_mode; int x, y; float scale; enum scale_filter_mode scale_filter; @@ -264,6 +272,7 @@ enum wl_output_subpixel subpixel; int max_render_time; // In milliseconds int adaptive_sync; + enum render_bit_depth render_bit_depth; char *background; char *background_option; @@ -281,6 +290,12 @@ int left; }; +enum smart_gaps_mode { + SMART_GAPS_OFF, + SMART_GAPS_ON, + SMART_GAPS_INVERSE_OUTER, +}; + /** * Stores configuration for a workspace, regardless of whether the workspace * exists. @@ -292,6 +307,12 @@ struct side_gaps gaps_outer; }; +enum pango_markup_config { + PANGO_MARKUP_DISABLED = false, + PANGO_MARKUP_ENABLED = true, + PANGO_MARKUP_DEFAULT // The default is font dependent ("pango:" prefix) +}; + struct bar_config { char *swaybar_command; struct wl_client *client; @@ -323,7 +344,7 @@ char *position; list_t *bindings; char *status_command; - bool pango_markup; + enum pango_markup_config pango_markup; char *font; int height; // -1 not defined bool workspace_buttons; @@ -410,14 +431,6 @@ POPUP_LEAVE, }; -enum command_context { - CONTEXT_CONFIG = 1 << 0, - CONTEXT_BINDING = 1 << 1, - CONTEXT_IPC = 1 << 2, - CONTEXT_CRITERIA = 1 << 3, - CONTEXT_ALL = 0xFFFFFFFF, -}; - enum focus_follows_mouse_mode { FOLLOWS_NO, FOLLOWS_YES, @@ -480,8 +493,8 @@ enum sway_container_layout default_orientation; enum sway_container_layout default_layout; char *font; - size_t font_height; - size_t font_baseline; + int font_height; + int font_baseline; bool pango_markup; int titlebar_border_thickness; int titlebar_h_padding; @@ -512,7 +525,7 @@ bool tiling_drag; int tiling_drag_threshold; - bool smart_gaps; + enum smart_gaps_mode smart_gaps; int gaps_inner; struct side_gaps gaps_outer; @@ -535,12 +548,15 @@ struct { struct border_colors focused; struct border_colors focused_inactive; + struct border_colors focused_tab_title; struct border_colors unfocused; struct border_colors urgent; struct border_colors placeholder; float background[4]; } border_colors; + bool has_focused_tab_title; + // floating view int32_t floating_maximum_width; int32_t floating_maximum_height; @@ -690,14 +706,13 @@ void free_workspace_config(struct workspace_config *wsc); /** - * Updates the value of config->font_height based on the max title height - * reported by each container. If recalculate is true, the containers will - * recalculate their heights before reporting. - * + * Updates the value of config->font_height based on the metrics for title's + * font as reported by pango. + * * If the height has changed, all containers will be rearranged to take on the * new size. */ -void config_update_font_height(bool recalculate); +void config_update_font_height(void); /** * Convert bindsym into bindcode using the first configured layout. diff -Nru sway-1.6.1/include/sway/input/cursor.h sway-1.7/include/sway/input/cursor.h --- sway-1.6.1/include/sway/input/cursor.h 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/include/sway/input/cursor.h 2022-01-22 22:55:11.000000000 +0000 @@ -52,7 +52,9 @@ struct wl_listener touch_down; struct wl_listener touch_up; struct wl_listener touch_motion; + struct wl_listener touch_frame; bool simulating_pointer_from_touch; + bool pointer_touch_up; int32_t pointer_touch_id; struct wl_listener tool_axis; diff -Nru sway-1.6.1/include/sway/input/seat.h sway-1.7/include/sway/input/seat.h --- sway-1.6.1/include/sway/input/seat.h 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/include/sway/input/seat.h 2022-01-22 22:55:11.000000000 +0000 @@ -239,7 +239,10 @@ void seatop_begin_default(struct sway_seat *seat); void seatop_begin_down(struct sway_seat *seat, struct sway_container *con, - uint32_t time_msec, int sx, int sy); + uint32_t time_msec, double sx, double sy); + +void seatop_begin_down_on_surface(struct sway_seat *seat, + struct wlr_surface *surface, uint32_t time_msec, double sx, double sy); void seatop_begin_move_floating(struct sway_seat *seat, struct sway_container *con); diff -Nru sway-1.6.1/include/sway/layers.h sway-1.7/include/sway/layers.h --- sway-1.6.1/include/sway/layers.h 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/include/sway/layers.h 2022-01-22 22:55:11.000000000 +0000 @@ -1,7 +1,6 @@ #ifndef _SWAY_LAYERS_H #define _SWAY_LAYERS_H #include -#include #include #include @@ -23,7 +22,11 @@ struct wl_listener new_subsurface; struct wlr_box geo; + bool mapped; + struct wlr_box extent; enum zwlr_layer_shell_v1_layer layer; + + struct wl_list subsurfaces; }; struct sway_layer_popup { @@ -43,6 +46,7 @@ struct sway_layer_subsurface { struct wlr_subsurface *wlr_subsurface; struct sway_layer_surface *layer_surface; + struct wl_list link; struct wl_listener map; struct wl_listener unmap; diff -Nru sway-1.6.1/include/sway/output.h sway-1.7/include/sway/output.h --- sway-1.6.1/include/sway/output.h 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/include/sway/output.h 2022-01-22 22:55:11.000000000 +0000 @@ -3,7 +3,6 @@ #include #include #include -#include #include #include "config.h" #include "sway/tree/node.h" @@ -49,7 +48,7 @@ struct wl_listener damage_frame; struct { - struct wl_signal destroy; + struct wl_signal disable; } events; struct timespec last_presentation; @@ -72,8 +71,8 @@ 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); diff -Nru sway-1.6.1/include/sway/server.h sway-1.7/include/sway/server.h --- sway-1.6.1/include/sway/server.h 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/include/sway/server.h 2022-01-22 22:55:11.000000000 +0000 @@ -4,11 +4,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -31,13 +33,16 @@ const char *socket; struct wlr_backend *backend; - struct wlr_backend *noop_backend; // secondary headless backend used for creating virtual outputs on-the-fly struct wlr_backend *headless_backend; + struct wlr_renderer *renderer; + struct wlr_allocator *allocator; struct wlr_compositor *compositor; struct wl_listener compositor_new_surface; + struct wlr_linux_dmabuf_v1 *linux_dmabuf_v1; + struct wlr_data_device_manager *data_device_manager; struct sway_input_manager *input; @@ -72,6 +77,9 @@ struct wl_listener xdg_decoration; struct wl_list xdg_decorations; // sway_xdg_decoration::link + struct wlr_drm_lease_v1_manager *drm_lease_manager; + struct wl_listener drm_lease_request; + struct wlr_presentation *presentation; struct wlr_pointer_constraints_v1 *pointer_constraints; @@ -87,6 +95,9 @@ struct wlr_text_input_manager_v3 *text_input; struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager; + struct wlr_xdg_activation_v1 *xdg_activation_v1; + struct wl_listener xdg_activation_v1_request_activate; + // The timeout for transactions, after which a transaction is applied // regardless of readiness. size_t txn_timeout_ms; @@ -112,6 +123,7 @@ bool noatomic; // Ignore atomic layout updates bool txn_timings; // Log verbose messages about transactions bool txn_wait; // Always wait for the timeout before applying + bool noscanout; // Disable direct scan-out enum { DAMAGE_DEFAULT, // Default behaviour @@ -129,6 +141,8 @@ bool server_start(struct sway_server *server); void server_run(struct sway_server *server); +void restore_nofile_limit(void); + void handle_compositor_new_surface(struct wl_listener *listener, void *data); void handle_new_output(struct wl_listener *listener, void *data); @@ -141,5 +155,7 @@ void handle_server_decoration(struct wl_listener *listener, void *data); void handle_xdg_decoration(struct wl_listener *listener, void *data); void handle_pointer_constraint(struct wl_listener *listener, void *data); +void xdg_activation_v1_handle_request_activate(struct wl_listener *listener, + void *data); #endif diff -Nru sway-1.6.1/include/sway/tree/container.h sway-1.7/include/sway/tree/container.h --- sway-1.6.1/include/sway/tree/container.h 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/include/sway/tree/container.h 2022-01-22 22:55:11.000000000 +0000 @@ -2,7 +2,6 @@ #define _SWAY_CONTAINER_H #include #include -#include #include #include "list.h" #include "sway/tree/node.h" @@ -118,14 +117,14 @@ struct wlr_texture *title_focused; struct wlr_texture *title_focused_inactive; + struct wlr_texture *title_focused_tab_title; struct wlr_texture *title_unfocused; struct wlr_texture *title_urgent; - size_t title_height; - size_t title_baseline; list_t *marks; // char * struct wlr_texture *marks_focused; struct wlr_texture *marks_focused_inactive; + struct wlr_texture *marks_focused_tab_title; struct wlr_texture *marks_unfocused; struct wlr_texture *marks_urgent; @@ -184,11 +183,6 @@ void container_update_title_textures(struct sway_container *container); -/** - * Calculate the container's title_height property. - */ -void container_calculate_title_height(struct sway_container *container); - size_t container_build_representation(enum sway_container_layout layout, list_t *children, char *buffer); diff -Nru sway-1.6.1/include/sway/tree/root.h sway-1.7/include/sway/tree/root.h --- sway-1.6.1/include/sway/tree/root.h 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/include/sway/tree/root.h 2022-01-22 22:55:11.000000000 +0000 @@ -31,7 +31,7 @@ list_t *scratchpad; // struct sway_container // For when there's no connected outputs - struct sway_output *noop_output; + struct sway_output *fallback_output; struct sway_container *fullscreen_global; diff -Nru sway-1.6.1/include/sway/tree/view.h sway-1.7/include/sway/tree/view.h --- sway-1.6.1/include/sway/tree/view.h 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/include/sway/tree/view.h 2022-01-22 22:55:11.000000000 +0000 @@ -112,7 +112,6 @@ #if HAVE_XWAYLAND struct wlr_xwayland_surface *wlr_xwayland_surface; #endif - struct wlr_wl_shell_surface *wlr_wl_shell_surface; }; struct { @@ -132,7 +131,6 @@ struct wl_listener commit; struct wl_listener request_move; struct wl_listener request_resize; - struct wl_listener request_maximize; struct wl_listener request_fullscreen; struct wl_listener set_title; struct wl_listener set_app_id; @@ -184,7 +182,7 @@ struct sway_view_child; struct sway_view_child_impl { - void (*get_root_coords)(struct sway_view_child *child, int *sx, int *sy); + void (*get_view_coords)(struct sway_view_child *child, int *sx, int *sy); void (*destroy)(struct sway_view_child *child); }; @@ -311,6 +309,15 @@ void view_begin_destroy(struct sway_view *view); +/** + * Map a view, ie. make it visible in the tree. + * + * `fullscreen` should be set to true (and optionally `fullscreen_output` + * should be populated) if the view should be made fullscreen immediately. + * + * `decoration` should be set to true if the client prefers CSD. The client's + * preference may be ignored. + */ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, bool fullscreen, struct wlr_output *fullscreen_output, bool decoration); diff -Nru sway-1.6.1/include/sway/tree/workspace.h sway-1.7/include/sway/tree/workspace.h --- sway-1.6.1/include/sway/tree/workspace.h 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/include/sway/tree/workspace.h 2022-01-22 22:55:11.000000000 +0000 @@ -60,20 +60,20 @@ char *workspace_next_name(const char *output_name); -bool workspace_switch(struct sway_workspace *workspace, - bool no_auto_back_and_forth); +struct sway_workspace *workspace_auto_back_and_forth( + struct sway_workspace *workspace); + +bool workspace_switch(struct sway_workspace *workspace); 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, bool create); +struct sway_workspace *workspace_output_next(struct sway_workspace *current); struct sway_workspace *workspace_next(struct sway_workspace *current); -struct sway_workspace *workspace_output_prev( - struct sway_workspace *current, bool create); +struct sway_workspace *workspace_output_prev(struct sway_workspace *current); struct sway_workspace *workspace_prev(struct sway_workspace *current); diff -Nru sway-1.6.1/include/swaybar/i3bar.h sway-1.7/include/swaybar/i3bar.h --- sway-1.6.1/include/swaybar/i3bar.h 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/include/swaybar/i3bar.h 2022-01-22 22:55:11.000000000 +0000 @@ -19,6 +19,7 @@ // Airblader features uint32_t background; uint32_t border; + bool border_set; int border_top; int border_bottom; int border_left; diff -Nru sway-1.6.1/include/swaynag/swaynag.h sway-1.7/include/swaynag/swaynag.h --- sway-1.6.1/include/swaynag/swaynag.h 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/include/swaynag/swaynag.h 2022-01-22 22:55:11.000000000 +0000 @@ -5,7 +5,6 @@ #include "list.h" #include "pool-buffer.h" #include "swaynag/types.h" -#include "xdg-output-unstable-v1-client-protocol.h" #define SWAYNAG_MAX_HEIGHT 500 @@ -75,13 +74,11 @@ struct swaynag { bool run_display; - int querying_outputs; struct wl_display *display; struct wl_compositor *compositor; struct wl_seat *seat; struct wl_shm *shm; - struct zxdg_output_manager_v1 *xdg_output_manager; struct wl_list outputs; // swaynag_output::link struct wl_list seats; // swaynag_seat::link struct swaynag_output *output; diff -Nru sway-1.6.1/include/swaynag/types.h sway-1.7/include/swaynag/types.h --- sway-1.6.1/include/swaynag/types.h 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/include/swaynag/types.h 2022-01-22 22:55:11.000000000 +0000 @@ -7,6 +7,7 @@ char *font; char *output; uint32_t anchors; + int32_t layer; // enum zwlr_layer_shell_v1_layer or -1 if unset // Colors uint32_t button_text; diff -Nru sway-1.6.1/meson.build sway-1.7/meson.build --- sway-1.6.1/meson.build 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/meson.build 2022-01-22 22:55:11.000000000 +0000 @@ -1,9 +1,9 @@ project( 'sway', 'c', - version: '1.6.1', + version: '1.7', license: 'MIT', - meson_version: '>=0.53.0', + meson_version: '>=0.60.0', default_options: [ 'c_std=c11', 'warning_level=2', @@ -37,11 +37,11 @@ jsonc = dependency('json-c', version: '>=0.13') pcre = dependency('libpcre') -wayland_server = dependency('wayland-server') +wayland_server = dependency('wayland-server', version: '>=1.20.0') wayland_client = dependency('wayland-client') wayland_cursor = dependency('wayland-cursor') wayland_egl = dependency('wayland-egl') -wayland_protos = dependency('wayland-protocols', version: '>=1.14') +wayland_protos = dependency('wayland-protocols', version: '>=1.24') xkbcommon = dependency('xkbcommon') cairo = dependency('cairo') pango = dependency('pango') @@ -61,7 +61,7 @@ rt = cc.find_library('rt') # Try first to find wlroots as a subproject, then as a system dependency -wlroots_version = ['>=0.14.0', '<0.15.0'] +wlroots_version = ['>=0.15.0', '<0.16.0'] wlroots_proj = subproject( 'wlroots', default_options: ['examples=false'], @@ -92,19 +92,11 @@ if not get_option('tray').disabled() assert(get_option('auto_features').auto(), 'sd-bus-provider must not be set to auto since auto_features != auto') endif - sdbus = dependency('libsystemd', + sdbus = dependency(['libsystemd', 'libelogind'], required: false, version: '>=239', - not_found_message: 'libsystemd not found, trying libelogind', ) if not sdbus.found() - sdbus = dependency('libelogind', - required: false, - version: '>=239', - not_found_message: 'libelogind not found, trying basu', - ) - endif - if not sdbus.found() sdbus = dependency('basu', required: false) endif else @@ -128,8 +120,7 @@ scdoc = dependency('scdoc', version: '>=1.9.2', native: true, required: get_option('man-pages')) if scdoc.found() - scdoc_prog = find_program(scdoc.get_pkgconfig_variable('scdoc'), native: true) - sh = find_program('sh', native: true) + scdoc_prog = find_program(scdoc.get_variable(pkgconfig: 'scdoc'), native: true) mandir = get_option('mandir') man_files = [ 'sway/sway.1.scd', @@ -140,9 +131,15 @@ 'sway/sway-output.5.scd', 'swaybar/swaybar-protocol.7.scd', 'swaymsg/swaymsg.1.scd', - 'swaynag/swaynag.1.scd', - 'swaynag/swaynag.5.scd', ] + + if get_option('swaynag') + man_files += [ + 'swaynag/swaynag.1.scd', + 'swaynag/swaynag.5.scd', + ] + endif + foreach filename : man_files topic = filename.split('.')[-3].split('/')[-1] section = filename.split('.')[-2] @@ -152,10 +149,10 @@ output, input: filename, output: output, - command: [ - sh, '-c', '@0@ < @INPUT@ > @1@'.format(scdoc_prog.path(), output) - ], + command: scdoc_prog, install: true, + feed: true, + capture: true, install_dir: '@0@/man@1@'.format(mandir, section) ) endforeach @@ -166,8 +163,8 @@ version = '"@0@"'.format(meson.project_version()) git = find_program('git', native: true, required: false) if git.found() - git_commit = run_command([git, 'rev-parse', '--short', 'HEAD']) - git_branch = run_command([git, 'rev-parse', '--abbrev-ref', 'HEAD']) + git_commit = run_command([git, 'rev-parse', '--short', 'HEAD'], check: false) + git_branch = run_command([git, 'rev-parse', '--abbrev-ref', 'HEAD'], check: false) if git_commit.returncode() == 0 and git_branch.returncode() == 0 version = '"@0@-@1@ (" __DATE__ ", branch \'@2@\')"'.format( meson.project_version(), @@ -180,7 +177,7 @@ # Compute the relative path used by compiler invocations. source_root = meson.current_source_dir().split('/') -build_root = meson.build_root().split('/') +build_root = meson.global_build_root().split('/') relative_dir_parts = [] i = 0 in_prefix = true @@ -224,9 +221,15 @@ subdir('sway') subdir('swaymsg') -subdir('client') -subdir('swaybar') -subdir('swaynag') +if get_option('swaybar') or get_option('swaynag') + subdir('client') +endif +if get_option('swaybar') + subdir('swaybar') +endif +if get_option('swaynag') + subdir('swaynag') +endif config = configuration_data() config.set('datadir', join_paths(prefix, datadir)) @@ -274,13 +277,17 @@ if get_option('bash-completions') bash_files = files( 'completions/bash/sway', - 'completions/bash/swaybar', 'completions/bash/swaymsg', ) + + if get_option('swaybar') + bash_files += files('completions/bash/swaybar') + endif + if bash_comp.found() - bash_install_dir = bash_comp.get_pkgconfig_variable( - 'completionsdir', - define_variable: ['datadir', datadir] + bash_install_dir = bash_comp.get_variable( + pkgconfig: 'completionsdir', + pkgconfig_define: ['datadir', datadir] ) else bash_install_dir = join_paths(datadir, 'bash-completion', 'completions') @@ -293,12 +300,16 @@ fish_files = files( 'completions/fish/sway.fish', 'completions/fish/swaymsg.fish', - 'completions/fish/swaynag.fish', ) + + if get_option('swaynag') + fish_files += files('completions/fish/swaynag.fish') + endif + if fish_comp.found() - fish_install_dir = fish_comp.get_pkgconfig_variable( - 'completionsdir', - define_variable: ['datadir', datadir] + fish_install_dir = fish_comp.get_variable( + pkgconfig: 'completionsdir', + pkgconfig_define: ['datadir', datadir] ) else fish_install_dir = join_paths(datadir, 'fish', 'vendor_completions.d') @@ -310,7 +321,6 @@ summary({ 'xwayland': have_xwayland, 'gdk-pixbuf': gdk_pixbuf.found(), - 'sd-bus': sdbus.found(), 'tray': have_tray, 'man-pages': scdoc.found(), }, bool_yn: true) diff -Nru sway-1.6.1/meson_options.txt sway-1.7/meson_options.txt --- sway-1.6.1/meson_options.txt 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/meson_options.txt 2022-01-22 22:55:11.000000000 +0000 @@ -2,6 +2,8 @@ option('zsh-completions', type: 'boolean', value: true, description: 'Install zsh shell completions.') option('bash-completions', type: 'boolean', value: true, description: 'Install bash shell completions.') option('fish-completions', type: 'boolean', value: true, description: 'Install fish shell completions.') +option('swaybar', type: 'boolean', value: true, description: 'Enable support for swaybar') +option('swaynag', type: 'boolean', value: true, description: 'Enable support for swaynag') option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications') option('tray', type: 'feature', value: 'auto', description: 'Enable support for swaybar tray') option('gdk-pixbuf', type: 'feature', value: 'auto', description: 'Enable support for more image formats in swaybg') diff -Nru sway-1.6.1/protocols/meson.build sway-1.7/protocols/meson.build --- sway-1.6.1/protocols/meson.build 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/protocols/meson.build 2022-01-22 22:55:11.000000000 +0000 @@ -1,9 +1,9 @@ -wl_protocol_dir = wayland_protos.get_pkgconfig_variable('pkgdatadir') +wl_protocol_dir = wayland_protos.get_variable('pkgdatadir') wayland_scanner_dep = dependency('wayland-scanner', required: false, native: true) if wayland_scanner_dep.found() wayland_scanner = find_program( - wayland_scanner_dep.get_pkgconfig_variable('wayland_scanner'), + wayland_scanner_dep.get_variable(pkgconfig: 'wayland_scanner'), native: true, ) else @@ -15,6 +15,7 @@ [wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'], [wl_protocol_dir, 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'], [wl_protocol_dir, 'unstable/tablet/tablet-unstable-v2.xml'], + [wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'], ['wlr-layer-shell-unstable-v1.xml'], ['idle.xml'], ['wlr-input-inhibitor-unstable-v1.xml'], diff -Nru sway-1.6.1/README.de.md sway-1.7/README.de.md --- sway-1.6.1/README.de.md 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/README.de.md 2022-01-22 22:55:11.000000000 +0000 @@ -1,8 +1,8 @@ # Sway -Sway ist ein [i3](https://i3wm.org/)-kompatibler [Wayland](http://wayland.freedesktop.org/)-Compositor. Lies die [FAQ](https://github.com/swaywm/sway/wiki). Tritt dem [IRC Channel](http://webchat.freenode.net/?channels=sway&uio=d4) bei (#sway on irc.freenode.net; Englisch). +Sway ist ein [i3](https://i3wm.org/)-kompatibler [Wayland](http://wayland.freedesktop.org/)-Compositor. Lies die [FAQ](https://github.com/swaywm/sway/wiki). Tritt dem [IRC Channel](https://web.libera.chat/gamja/?channels=#sway) bei (#sway on irc.libera.chat; Englisch). ## Signaturen -Jedes Release wird mit dem PGP-Schlüssel [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) signiert und auf GitHub veröffentlicht. +Jedes Release wird mit dem PGP-Schlüssel [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) signiert und auf GitHub veröffentlicht. ## Installation ### Mit der Paketverwaltung @@ -15,7 +15,7 @@ sway benötigt die folgenden Pakete: * meson\* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols\* * pcre diff -Nru sway-1.6.1/README.dk.md sway-1.7/README.dk.md --- sway-1.6.1/README.dk.md 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/README.dk.md 2022-01-22 22:55:11.000000000 +0000 @@ -1,41 +1,43 @@ # Sway -Sway er en [i3](https://i3wm.org/)-kompatibel [Wayland](http://wayland.freedesktop.org/) compositor. -Læs [Ofte stillede spørgsmål](https://github.com/swaywm/sway/wiki). -Deltag på [IRC kanalen](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway på irc.freenode.net). +Sway er en [i3]-kompatibel [Wayland] compositor. Læs [Ofte stillede spørgsmål]. +Deltag på [IRC kanalen][IRC kanal] \(#sway på irc.libera.chat). ## Udgivelses Signaturer -Udgivelser er signeret med [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) -og publiseret på [GitHub](https://github.com/swaywm/sway/releases). +Udgivelser er signeret med [E88F5E48] og publiceret [på GitHub][GitHub +releases]. ## Installation -### Fra Pakker +### Fra pakker -Sway er tilgængelig i mange distributioner. Prøv at installere pakken "sway". Hvis den ikke er tilgængelig, så tjek [denne wiki-side](https://github.com/swaywm/sway/wiki/Unsupported-packages) -for information om installation til din(e) distribution(er). +Sway er tilgængelig i mange distributioner. Prøv at installere "sway" pakken +fra din. -Hvis du er interesseret i at lave en Sway pakke til din distribution, burde du besøge IRC -kanalen eller sende en e-mail til sir@cmpwn.com for rådgivning. +Hvis du er interesseret i at pakke Sway til din distribution, kan du tage forbi +IRC kanalen eller sende en email til sir@cmpwn.com for rådgivning. ### Kompilering fra kildekode -Installation afhænger af følgende programmer: +Se [denne wiki-side][Opsætning til udvikling] hvis du vil bygge HEAD af sway og +wlroots til test eller udvikling. + +Installationsafhængigheder: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots] * wayland * wayland-protocols \* * pcre * json-c * pango * cairo -* gdk-pixbuf2 (valgfrit tillæg: system tray) -* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (valgfrit tillæg: man pages) \* +* gdk-pixbuf2 (valgfrit: system tray) +* [scdoc] (valgfrit: man pages) \* * git \* -_\*Kompiler krav_ +_\*Kompileringsafhængighed_ Kør følgende kommandoer: @@ -43,21 +45,30 @@ ninja -C build sudo ninja -C build install -På systemer uden 'logind', behøver du at sætte ejerens bruger-id for Sways eksekverbare filer - såkaldt SUID (Set owner User ID): +På systemer uden logind eller seatd skal du sætte SUID bit på sway filen: sudo chmod a+s /usr/local/bin/sway -Sway vil frasige sig 'root' tilladelser kort efter opstart +Sway dropper 'root' tilladelser kort efter opstart. ## Konfiguration -Hvis du allerede bruger i3, bør du kopiere din i3-konfiguration til `~/.config/sway/config` og -det vil bare fungerer. Ellers skal du kopiere eksempel konfigurations filen til -`~/.config/sway/config`. Den er normalt placeret i `/etc/sway/config`. -Kør `man 5 sway` for at få oplysninger om konfigurationen. - -## Kører - -Kør `sway` fra en TTY. Nogle display managers fungerer muligvis, men understøttes ikke af -Sway (gdm er kendt for at fungere temmelig godt). - +Hvis du allerede bruger i3 kan du bare kopiere din i3 konfiguration til +`~/.config/sway/config`. Ellers skal du kopiere eksempelkonfigurationsfilen til +`~/.config/sway/config`. Den er normalt placeret i `/etc/sway/config`. Kør +`man 5 sway` for at få oplysninger om konfigurationen. + +## Eksekvering + +Kør `sway` fra en TTY. Nogle display managers kan fungere, men Sway yder ikke +support til dem (gdm er kendt for at fungere temmelig godt). + +[i3]: https://i3wm.org/ +[Wayland]: http://wayland.freedesktop.org/ +[Ofte stillede spørgsmål]: https://github.com/swaywm/sway/wiki +[IRC kanal]: https://web.libera.chat/gamja/?channels=#sway +[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 +[GitHub releases]: https://github.com/swaywm/sway/releases +[Opsætning til udvikling]: https://github.com/swaywm/sway/wiki/Development-Setup +[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots +[scdoc]: https://git.sr.ht/~sircmpwn/scdoc diff -Nru sway-1.6.1/README.es.md sway-1.7/README.es.md --- sway-1.6.1/README.es.md 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/README.es.md 2022-01-22 22:55:11.000000000 +0000 @@ -1,12 +1,12 @@ # sway sway es un compositor de [Wayland](http://wayland.freedesktop.org/) compatible con [i3](https://i3wm.org/). -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). +Lea el [FAQ](https://github.com/swaywm/sway/wiki). Únase al [canal de IRC](https://web.libera.chat/gamja/?channels=#sway) (#sway on +irc.libera.chat). ## Firmas de las versiones -Las distintas versiones están firmadas con [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +Las distintas versiones están firmadas con [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) y publicadas [en GitHub](https://github.com/swaywm/sway/releases). ## Instalación @@ -25,7 +25,7 @@ Instale las dependencias: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff -Nru sway-1.6.1/README.fr.md sway-1.7/README.fr.md --- sway-1.6.1/README.fr.md 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/README.fr.md 2022-01-22 22:55:11.000000000 +0000 @@ -1,7 +1,7 @@ # sway Sway est un compositeur [Wayland] compatible avec [i3]. Lisez la -[FAQ]. Rejoignez le [canal IRC] (#sway sur irc.freenode.net). +[FAQ]. Rejoignez le [canal IRC] (#sway sur irc.libera.chat). ## Aide en français @@ -74,10 +74,10 @@ [Wayland]: http://wayland.freedesktop.org/ [i3]: https://i3wm.org/ [FAQ]: https://github.com/swaywm/sway/wiki -[canal IRC]: http://webchat.freenode.net/?channels=sway&uio=d4 +[canal IRC]: https://web.libera.chat/gamja/?channels=#sway [abdelq]: https://github.com/abdelq [E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48 [versions GitHub]: https://github.com/swaywm/sway/releases [Configuration de développement]: https://github.com/swaywm/sway/wiki/Development-Setup -[wlroots]: https://github.com/swaywm/wlroots +[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots [scdoc]: https://git.sr.ht/~sircmpwn/scdoc diff -Nru sway-1.6.1/README.gr.md sway-1.7/README.gr.md --- sway-1.6.1/README.gr.md 1970-01-01 00:00:00.000000000 +0000 +++ sway-1.7/README.gr.md 2022-01-22 22:55:11.000000000 +0000 @@ -0,0 +1,73 @@ +# Sway + +Το sway ένα [i3]-συμβατό [Wayland] compositor. Διαβάστε το [FAQ]. Μπείτε στο +[IRC channel] \(#sway on irc.libera.chat). + +## Υπογραφές δημοσιεύσεων + +Οι εκδόσεις είναι υπογεραμμένες με [E88F5E48] και δημοσιευμένες [στο GitHub][GitHub releases]. + +## Εγκατάσταση + +### Από πακέτα + +Το Sway είναι διαθέσιμο σε πολλά distributions. Δοκιμάστε εγκαταστώντας το "sway" package για +το δικό σας. + +Εάν ενδιαφέρεστε για packaging του sway για το distribution σας, να πάτε στο IRC +channel ή στείλτε ένα email στο sir@cmpwn.com για συμβουλές. + +### Compiling από πηγή + +Τσεκάρετε [αυτό το wiki page][Development setup] εάμα θέλετε να κάνετε build το HEAD του +sway και wlroots γιά τεστάρισμα ή development. + +Εγκατάσταση των dependencies: + +* meson \* +* [wlroots] +* wayland +* wayland-protocols \* +* pcre +* json-c +* pango +* cairo +* gdk-pixbuf2 (προαιρετικό: system tray) +* [scdoc] (προαιρετικό: man pages) \* +* git (προαιρετικό: πληροφορίες εκδώσεων) \* + +_\*Compile-time dep_ + +Τρέξτε αυτά τα commands: + + meson build/ + ninja -C build/ + sudo ninja -C build/ install + +Σε συστήματα χωρίς logind ή seatd, πρέπει να κάνετε suid το sway binary: + + sudo chmod a+s /usr/local/bin/sway + +Το Sway θα κάνει drop root δικαιώματα λίγο μετά την εκκίνηση. + +## Configuration + +Εάν ήδη χρησιμοποιήτε το i3, αντιγράψτε το i3 config σας στο `~/.config/sway/config` και +θα δουλέψει out of the box. Αλλιώς, αντιγράψτε το sample configuration αρχείο στο +`~/.config/sway/config`. Το οποίο συνήθως βρίσκεται στο `/etc/sway/config`. +Κάντε run `man 5 sway` για πληροφορίες τού configuration. + +## Τρέχοντας + +Τρέξτε `sway` από ένα TTY. Μερίκα display managers μπορεί να δουλέψουν αλλά δέν είναι συμβατά με +το sway (το gdm γνωρίζεται να δουλέβει σχετικά καλά). + +[i3]: https://i3wm.org/ +[Wayland]: http://wayland.freedesktop.org/ +[FAQ]: https://github.com/swaywm/sway/wiki +[IRC channel]: https://web.libera.chat/gamja/?channels=#sway +[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://gitlab.freedesktop.org/wlroots/wlroots +[scdoc]: https://git.sr.ht/~sircmpwn/scdoc \ No newline at end of file diff -Nru sway-1.6.1/README.hu.md sway-1.7/README.hu.md --- sway-1.6.1/README.hu.md 1970-01-01 00:00:00.000000000 +0000 +++ sway-1.7/README.hu.md 2022-01-22 22:55:11.000000000 +0000 @@ -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.libera.chat`-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]: https://web.libera.chat/gamja/?channels=#sway +[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://gitlab.freedesktop.org/wlroots/wlroots +[scdoc]: https://git.sr.ht/~sircmpwn/scdoc diff -Nru sway-1.6.1/README.ir.md sway-1.7/README.ir.md --- sway-1.6.1/README.ir.md 1970-01-01 00:00:00.000000000 +0000 +++ sway-1.7/README.ir.md 2022-01-22 22:55:11.000000000 +0000 @@ -0,0 +1,60 @@ +# sway + +‏sway یک کامپوزیتور الهام گرفته از [i3](https://i3wm.org/) بر روی [Wayland](http://wayland.freedesktop.org/) است. [سوال‌های متداول](https://github.com/swaywm/sway/wiki) را بخوانید. در [کانال +IRC](http://web.libera.chat/gamja/?channels=sway&uio=d4) عضو شوید (‎#sway‏ در +irc.libera.chat). + +برای حمایت از تیم توسعه sway به [صفحه +Patreon با نام کاربری SirCmpwn](https://patreon.com/sircmpwn) مراجعه کنید. + +## امضای نسخه‌ها + +امضای نسخه‌ها با [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) در [GitHub](https://github.com/swaywm/sway/releases) منتشر می‌شود. + +## شیوه نصب + +### از بسته‌های رسمی + +‏sway در بسته‌های رسمی توزیع‌های مختلف وجود دارد. بسته «sway» را نصب کنید. در صورتی که بسته رسمی وجود نداشت، برای آگاهی بیشتر درباره نصب روی توزیعتان به این [صفحه راهنما](https://github.com/swaywm/sway/wiki/Unsupported-packages) مراجعه کنید. + +اگر به ایجاد بسته sway برای توزیعتان علاقه‌مند هستید، از کانال IRC استفاده کنید یا به sir@cmpwn.com ایمیل بزنید. + +### کامپایل کردن کد + +چنانچه می‌خواهید آخرین نسخه کد sway و wlroots را برای آزمایش یا توسعه بسازید به این [صفحه راهنما](https://github.com/swaywm/sway/wiki/Development-Setup) مراجعه کنید. + +بسته‌های مورد نیاز: + +* meson \* +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) +* wayland +* wayland-protocols \* +* pcre +* json-c +* pango +* cairo +* gdk-pixbuf2 (انتخابی: برای system tray) +* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (انتخابی: برای صفحه‌های راهنما) \* +* git (انتخابی: برای اطلاع در خصوص نسخه‌ها) \* + +_\*نیازمندی‌های زمان کامپایل برنامه_ + +این فرمان‌ها را اجرا کنید: + + meson build + ninja -C build + sudo ninja -C build install + +روی سیستم‌های بدون logind، باید فرمان زیر را برای suid کردن باینری sway اجرا کنید: + + sudo chmod a+s /usr/local/bin/sway + +‏sway پس از startup مجوزهای دسترسی root را رها می‌کند. + +### شخصی سازی و تنظیمات + +اگر در حال حاضر از i3 استفاده می‌کنید، تنظیمات i3 خودتان را در فایل ‪`~/.config/sway/config`‬ کپی کنید و بدون نیاز به تغییر کار خواهد کرد. در غیر این‌صورت، فایل نمونه تنظیمات را استفاده کنید. این فایل عموما در ‪`/etc/sway/config`‬ قرار دارد. برای آگاهی بیشتر `man 5 sway` را اجرا کنید. + +## اجرا + +در محیط TTY کافیست `sway` را اجرا کنید. ممکن است ابزارهای مدیریت نمایشگری نیز برای این کار وجود داشته باشند اما از طرف sway پشتیبانی نمی‌شوند (gdm عملکرد خوبی در این زمینه دارد). diff -Nru sway-1.6.1/README.ja.md sway-1.7/README.ja.md --- sway-1.6.1/README.ja.md 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/README.ja.md 2022-01-22 22:55:11.000000000 +0000 @@ -2,7 +2,7 @@ Swayは[i3](https://i3wm.org/)互換な[Wayland](http://wayland.freedesktop.org/)コンポジタです。 [FAQ](https://github.com/swaywm/sway/wiki)も合わせてご覧ください。 -[IRC チャンネル](http://webchat.freenode.net/?channels=sway&uio=d4) (irc.freenode.netの#sway)もあります。 +[IRC チャンネル](https://web.libera.chat/gamja/?channels=#sway) (irc.libera.chatの#sway)もあります。 [![](https://sr.ht/ICd5.png)](https://sr.ht/ICd5.png) @@ -12,7 +12,7 @@ ## リリースの署名 -Swayのリリースは[B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A)で署名され、[GitHub](https://github.com/swaywm/sway/releases)で公開されています。 +Swayのリリースは[E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48)で署名され、[GitHub](https://github.com/swaywm/sway/releases)で公開されています。 ## インストール @@ -27,7 +27,7 @@ 次の依存パッケージをインストールしてください: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff -Nru sway-1.6.1/README.ko.md sway-1.7/README.ko.md --- sway-1.6.1/README.ko.md 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/README.ko.md 2022-01-22 22:55:11.000000000 +0000 @@ -1,11 +1,11 @@ # sway sway는 [i3](https://i3wm.org/)-호환 [Wayland](http://wayland.freedesktop.org/) 컴포지터입니다. -[FAQ](https://github.com/swaywm/sway/wiki)를 읽어보세요. [IRC 채널](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway on irc.freenode.net)도 있습니다. +[FAQ](https://github.com/swaywm/sway/wiki)를 읽어보세요. [IRC 채널](https://web.libera.chat/gamja/?channels=#sway) (#sway on irc.libera.chat)도 있습니다. ## 릴리즈 서명 -릴리즈는 [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A)에서 서명되고, +릴리즈는 [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48)에서 서명되고, [GitHub에서](https://github.com/swaywm/sway/releases) 공개되고 있습니다. ## 설치 @@ -24,7 +24,7 @@ 다음 의존 패키지들을 설치해 주세요: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff -Nru sway-1.6.1/README.md sway-1.7/README.md --- sway-1.6.1/README.md 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/README.md 2022-01-22 22:55:11.000000000 +0000 @@ -1,9 +1,9 @@ # 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] - [Dansk][dk] - [한국어][ko] - [Română][ro] - [Magyar][hu] - [Türkçe][tr] - [فارسی][ir] - [Ελληνικά][gr] sway is an [i3]-compatible [Wayland] compositor. Read the [FAQ]. Join the -[IRC channel] \(#sway on irc.freenode.net). +[IRC channel] \(#sway on irc.libera.chat). ## Release Signatures @@ -16,9 +16,6 @@ Sway is available in many distributions. Try installing the "sway" package for yours. -If you're interested in packaging sway for your distribution, stop by the IRC -channel or shoot an email to sir@cmpwn.com for advice. - ### Compiling from Source Check out [this wiki page][Development setup] if you want to build the HEAD of @@ -38,15 +35,15 @@ * [scdoc] (optional: man pages) \* * git (optional: version info) \* -_\*Compile-time dep_ +_\* 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: +On systems without logind nor seatd, you need to suid the sway binary: sudo chmod a+s /usr/local/bin/sway @@ -79,12 +76,16 @@ [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 +[ir]: https://github.com/swaywm/sway/blob/master/README.ir.md +[gr]: https://github.com/swaywm/sway/blob/master/README.gr.md [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 +[IRC channel]: https://web.libera.chat/gamja/?channels=#sway [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 +[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots [scdoc]: https://git.sr.ht/~sircmpwn/scdoc diff -Nru sway-1.6.1/README.nl.md sway-1.7/README.nl.md --- sway-1.6.1/README.nl.md 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/README.nl.md 2022-01-22 22:55:11.000000000 +0000 @@ -2,12 +2,12 @@ Sway is een [i3](https://i3wm.org/)-compatibele [Wayland](http://wayland.freedesktop.org/) compositor. Lees de [FAQ](https://github.com/swaywm/sway/wiki). Word lid van het [IRC -kanaal](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway op -irc.freenode.net). +kanaal](https://web.libera.chat/gamja/?channels=#sway) (#sway op +irc.libera.chat). ## Releasehandtekeningen -Releases worden ondertekend met [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +Releases worden ondertekend met [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) en gepubliceerd [op GitHub](https://github.com/swaywm/sway/releases). ## Installatie @@ -25,7 +25,7 @@ Afhankelijkheden installeren: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff -Nru sway-1.6.1/README.pl.md sway-1.7/README.pl.md --- sway-1.6.1/README.pl.md 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/README.pl.md 2022-01-22 22:55:11.000000000 +0000 @@ -1,12 +1,12 @@ # sway sway jest kompozytorem [Wayland](http://wayland.freedesktop.org/) kompatybilnym z [i3](https://i3wm.org/). -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). +Przeczytaj [FAQ](https://github.com/swaywm/sway/wiki). Dołącz do [kanału IRC](https://web.libera.chat/gamja/?channels=#sway) +(#sway na irc.libera.chat). ## Podpisy cyfrowe wydań -Wydania są podpisywane przy pomocy klucza [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +Wydania są podpisywane przy pomocy klucza [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) i publikowane [na GitHubie](https://github.com/swaywm/sway/releases). ## Instalacja @@ -25,7 +25,7 @@ Zainstaluj zależności: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff -Nru sway-1.6.1/README.pt.md sway-1.7/README.pt.md --- sway-1.6.1/README.pt.md 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/README.pt.md 2022-01-22 22:55:11.000000000 +0000 @@ -2,12 +2,12 @@ O sway é um compositor do [Wayland](http://wayland.freedesktop.org/) compatível com o [i3](https://i3wm.org/). Leia o [FAQ](https://github.com/swaywm/sway/wiki). Junte-se ao [canal do -IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway em -irc.freenode.net). +IRC](https://web.libera.chat/gamja/?channels=#sway) (#sway em +irc.libera.chat). ## Assinatura das versões -As versões são assinadas com [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +As versões são assinadas com [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) e publicadas [no GitHub](https://github.com/swaywm/sway/releases). ## Instalação @@ -27,7 +27,7 @@ Instale as dependências: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff -Nru sway-1.6.1/README.ro.md sway-1.7/README.ro.md --- sway-1.6.1/README.ro.md 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/README.ro.md 2022-01-22 22:55:11.000000000 +0000 @@ -1,11 +1,11 @@ # sway sway este un compositor pentru [Wayland](http://wayland.freedesktop.org/) compatibil cu [i3](https://i3wm.org/). -Citiți [FAQ](https://github.com/swaywm/sway/wiki)-ul. Connectați-vă la canalul nostru [IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway pe irc.freenode.net). +Citiți [FAQ](https://github.com/swaywm/sway/wiki)-ul. Connectați-vă la canalul nostru [IRC](https://web.libera.chat/gamja/?channels=#sway) (#sway pe irc.libera.chat). ## Semnarea digitală -Noile versiuni sunt semnate cu [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +Noile versiuni sunt semnate cu [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) și postate [pe GitHub](https://github.com/swaywm/sway/releases). ## Instalare @@ -22,7 +22,7 @@ Dependențe pentru instalare: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff -Nru sway-1.6.1/README.ru.md sway-1.7/README.ru.md --- sway-1.6.1/README.ru.md 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/README.ru.md 2022-01-22 22:55:11.000000000 +0000 @@ -3,7 +3,7 @@ sway - это [i3]-совместимый композитор [Wayland]. Больше информации в [FAQ]. Присоединяйтесь к [IRC-каналу][IRC channel] (#sway на -irc.freenode.net). +irc.libera.chat). ## Подписи релизов @@ -66,9 +66,9 @@ [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 +[IRC channel]: https://web.libera.chat/gamja/?channels=#sway [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 +[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots [scdoc]: https://git.sr.ht/~sircmpwn/scdoc diff -Nru sway-1.6.1/README.tr.md sway-1.7/README.tr.md --- sway-1.6.1/README.tr.md 1970-01-01 00:00:00.000000000 +0000 +++ sway-1.7/README.tr.md 2022-01-22 22:55:11.000000000 +0000 @@ -0,0 +1,68 @@ +# sway + + +Sway, [i3]-uyumlu bir [Wayland] dizgicisidir. [SSS][FAQ]'yi okuyun. +[IRC kanalı][IRC channel]na katılın \(irc.libera.chat'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]: https://web.libera.chat/gamja/?channels=#sway +[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://gitlab.freedesktop.org/wlroots/wlroots +[scdoc]: https://git.sr.ht/~sircmpwn/scdoc diff -Nru sway-1.6.1/README.uk.md sway-1.7/README.uk.md --- sway-1.6.1/README.uk.md 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/README.uk.md 2022-01-22 22:55:11.000000000 +0000 @@ -2,8 +2,8 @@ Sway це сумісний з [i3](https://i3wm.org/) композитор [Wayland](http://wayland.freedesktop.org/). Ознайомтесь з [ЧаПами](https://github.com/swaywm/sway/wiki). Приєднуйтесь до [спільноти в -IRC](http://webchat.freenode.net/?channels=sway&uio=d4) (#sway на -irc.freenode.net). +IRC](https://web.libera.chat/gamja/?channels=#sway) (#sway на +irc.libera.chat). ## Підтримка українською мовою @@ -15,7 +15,7 @@ ## Підписи випусків -Випуски підписані ключем [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) +Випуски підписані ключем [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) та публікуються на сторінці [GitHub](https://github.com/swaywm/sway/releases). ## Встановлення @@ -36,7 +36,7 @@ Встановіть залежності: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff -Nru sway-1.6.1/README.zh-CN.md sway-1.7/README.zh-CN.md --- sway-1.6.1/README.zh-CN.md 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/README.zh-CN.md 2022-01-22 22:55:11.000000000 +0000 @@ -2,12 +2,12 @@ sway 是和 [i3](https://i3wm.org/) 兼容的 [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). +频道](https://web.libera.chat/gamja/?channels=#sway) (#sway on +irc.libera.chat). ## 发布签名 -发布是以 [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) 签名 +发布是以 [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) 签名 并发布在 [GitHub](https://github.com/swaywm/sway/releases). ## 安装 @@ -25,7 +25,7 @@ 安装依赖: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff -Nru sway-1.6.1/README.zh-TW.md sway-1.7/README.zh-TW.md --- sway-1.6.1/README.zh-TW.md 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/README.zh-TW.md 2022-01-22 22:55:11.000000000 +0000 @@ -2,12 +2,12 @@ sway 是一個與 [i3](https://i3wm.org/) 相容的 [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) +頻道](https://web.libera.chat/gamja/?channels=#sway) (#sway on +irc.libera.chat) ## 發行簽章 -所有發行的版本都會以 [B22DA89A](http://pgp.mit.edu/pks/lookup?op=vindex&search=0x52CB6609B22DA89A) 簽署 +所有發行的版本都會以 [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) 簽署 並發佈於 [GitHub](https://github.com/swaywm/sway/releases) ## 安裝 @@ -25,7 +25,7 @@ 相依套件: * meson \* -* [wlroots](https://github.com/swaywm/wlroots) +* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) * wayland * wayland-protocols \* * pcre diff -Nru sway-1.6.1/sway/commands/bar/font.c sway-1.7/sway/commands/bar/font.c --- sway-1.6.1/sway/commands/bar/font.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/bar/font.c 2022-01-22 22:55:11.000000000 +0000 @@ -11,7 +11,20 @@ } char *font = join_args(argv, argc); free(config->current_bar->font); - config->current_bar->font = font; + + if (strncmp(font, "pango:", 6) == 0) { + if (config->current_bar->pango_markup == PANGO_MARKUP_DEFAULT) { + config->current_bar->pango_markup = true; + } + config->current_bar->font = strdup(font + 6); + } else { + if (config->current_bar->pango_markup == PANGO_MARKUP_DEFAULT) { + config->current_bar->pango_markup = false; + } + config->current_bar->font = strdup(font); + } + + free(font); sway_log(SWAY_DEBUG, "Settings font '%s' for bar: %s", config->current_bar->font, config->current_bar->id); return cmd_results_new(CMD_SUCCESS, NULL); diff -Nru sway-1.6.1/sway/commands/bar/hidden_state.c sway-1.7/sway/commands/bar/hidden_state.c --- sway-1.6.1/sway/commands/bar/hidden_state.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/bar/hidden_state.c 2022-01-22 22:55:11.000000000 +0000 @@ -54,7 +54,7 @@ } const char *state = argv[0]; - if (config->reading) { + if (config->current_bar) { error = bar_set_hidden_state(config->current_bar, state); } else { const char *id = argc == 2 ? argv[1] : NULL; diff -Nru sway-1.6.1/sway/commands/bar/mode.c sway-1.7/sway/commands/bar/mode.c --- sway-1.6.1/sway/commands/bar/mode.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/bar/mode.c 2022-01-22 22:55:11.000000000 +0000 @@ -58,7 +58,7 @@ } const char *mode = argv[0]; - if (config->reading) { + if (config->current_bar) { error = bar_set_mode(config->current_bar, mode); } else { const char *id = argc == 2 ? argv[1] : NULL; diff -Nru sway-1.6.1/sway/commands/bind.c sway-1.7/sway/commands/bind.c --- sway-1.6.1/sway/commands/bind.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/bind.c 2022-01-22 22:55:11.000000000 +0000 @@ -560,8 +560,8 @@ free_switch_binding(binding); return cmd_results_new(CMD_FAILURE, "Invalid %s command " - "(expected switch state: unknown state %d)", - bindtype, split->items[0]); + "(expected switch state: unknown state %s)", + bindtype, split->items[1]); } list_free_items_and_destroy(split); diff -Nru sway-1.6.1/sway/commands/client.c sway-1.7/sway/commands/client.c --- sway-1.6.1/sway/commands/client.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/client.c 2022-01-22 22:55:11.000000000 +0000 @@ -18,6 +18,12 @@ return error; } + if (argc > 3 && strcmp(cmd_name, "client.focused_tab_title") == 0) { + sway_log(SWAY_ERROR, + "Warning: indicator and child_border colors have no effect for %s", + cmd_name); + } + struct border_colors colors = {0}; const char *ind_hex = argc > 3 ? argv[3] : default_indicator; const char *child_hex = argc > 4 ? argv[4] : argv[1]; // def to background @@ -80,3 +86,13 @@ sway_log(SWAY_INFO, "Warning: %s is ignored by sway", argv[-1]); return cmd_results_new(CMD_SUCCESS, NULL); } + +struct cmd_results *cmd_client_focused_tab_title(int argc, char **argv) { + struct cmd_results *result = handle_command(argc, argv, + "client.focused_tab_title", + &config->border_colors.focused_tab_title, "#2e9ef4ff"); + if (result && result->status == CMD_SUCCESS) { + config->has_focused_tab_title = true; + } + return result; +} diff -Nru sway-1.6.1/sway/commands/exec_always.c sway-1.7/sway/commands/exec_always.c --- sway-1.6.1/sway/commands/exec_always.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/exec_always.c 2022-01-22 22:55:11.000000000 +0000 @@ -7,6 +7,7 @@ #include #include "sway/commands.h" #include "sway/config.h" +#include "sway/server.h" #include "sway/tree/container.h" #include "sway/tree/root.h" #include "sway/tree/workspace.h" @@ -26,7 +27,7 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) { struct cmd_results *error = NULL; - char *tmp = NULL; + char *cmd = NULL; if (strcmp(argv[0], "--no-startup-id") == 0) { sway_log(SWAY_INFO, "exec switch '--no-startup-id' not supported, ignored."); --argc; ++argv; @@ -36,17 +37,12 @@ } if (argc == 1 && (argv[0][0] == '\'' || argv[0][0] == '"')) { - tmp = strdup(argv[0]); - strip_quotes(tmp); + cmd = strdup(argv[0]); + strip_quotes(cmd); } else { - tmp = join_args(argv, argc); + cmd = join_args(argv, argc); } - // Put argument into cmd array - char cmd[4096]; - strncpy(cmd, tmp, sizeof(cmd) - 1); - cmd[sizeof(cmd) - 1] = 0; - free(tmp); sway_log(SWAY_DEBUG, "Executing %s", cmd); int fd[2]; @@ -58,15 +54,18 @@ // Fork process if ((pid = fork()) == 0) { // Fork child process again + restore_nofile_limit(); setsid(); sigset_t set; sigemptyset(&set); sigprocmask(SIG_SETMASK, &set, NULL); + signal(SIGPIPE, SIG_DFL); 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)) { @@ -75,10 +74,12 @@ close(fd[1]); _exit(0); // Close child process } else if (pid < 0) { + free(cmd); close(fd[0]); close(fd[1]); return cmd_results_new(CMD_FAILURE, "fork() failed"); } + free(cmd); close(fd[1]); // close write ssize_t s = 0; while ((size_t)s < sizeof(pid_t)) { diff -Nru sway-1.6.1/sway/commands/focus.c sway-1.7/sway/commands/focus.c --- sway-1.6.1/sway/commands/focus.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/focus.c 2022-01-22 22:55:11.000000000 +0000 @@ -267,6 +267,11 @@ new_focus = seat_get_focus_inactive_tiling(seat, ws); } if (new_focus) { + struct sway_container *new_focus_view = + seat_get_focus_inactive_view(seat, &new_focus->node); + if (new_focus_view) { + new_focus = new_focus_view; + } seat_set_focus_container(seat, new_focus); // If we're on the floating layer and the floating container area @@ -446,7 +451,8 @@ return cmd_results_new(CMD_FAILURE, ""); } struct sway_node *next_focus = NULL; - if (container_is_floating(container)) { + if (container_is_floating(container) && + container->pending.fullscreen_mode == FULLSCREEN_NONE) { next_focus = node_get_in_direction_floating(container, seat, direction); } else { next_focus = node_get_in_direction_tiling(container, seat, direction, descend); diff -Nru sway-1.6.1/sway/commands/font.c sway-1.7/sway/commands/font.c --- sway-1.6.1/sway/commands/font.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/font.c 2022-01-22 22:55:11.000000000 +0000 @@ -22,6 +22,6 @@ } free(font); - config_update_font_height(true); + config_update_font_height(); return cmd_results_new(CMD_SUCCESS, NULL); } diff -Nru sway-1.6.1/sway/commands/fullscreen.c sway-1.7/sway/commands/fullscreen.c --- sway-1.6.1/sway/commands/fullscreen.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/fullscreen.c 2022-01-22 22:55:11.000000000 +0000 @@ -18,30 +18,19 @@ return cmd_results_new(CMD_FAILURE, "Can't run this command while there's no outputs connected."); } - struct sway_node *node = config->handler_context.node; struct sway_container *container = config->handler_context.container; - struct sway_workspace *workspace = config->handler_context.workspace; - if (node->type == N_WORKSPACE && workspace->tiling->length == 0) { - return cmd_results_new(CMD_FAILURE, - "Can't fullscreen an empty workspace"); - } - // If in the scratchpad, operate on the highest container - if (container && !container->pending.workspace) { + if (!container) { + // If the focus is not a container, do nothing successfully + return cmd_results_new(CMD_SUCCESS, NULL); + } else if (!container->pending.workspace) { + // If in the scratchpad, operate on the highest container while (container->pending.parent) { container = container->pending.parent; } } - 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; @@ -57,13 +46,6 @@ global = strcasecmp(argv[1], "global") == 0; } - if (enable && node->type == N_WORKSPACE) { - // Wrap the workspace's children in a container so we can fullscreen it - container = workspace_wrap_children(workspace); - workspace->layout = L_HORIZ; - seat_set_focus_container(config->handler_context.seat, container); - } - enum sway_fullscreen_mode mode = FULLSCREEN_NONE; if (enable) { mode = global ? FULLSCREEN_GLOBAL : FULLSCREEN_WORKSPACE; diff -Nru sway-1.6.1/sway/commands/gaps.c sway-1.7/sway/commands/gaps.c --- sway-1.6.1/sway/commands/gaps.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/gaps.c 2022-01-22 22:55:11.000000000 +0000 @@ -11,7 +11,8 @@ enum gaps_op { GAPS_OP_SET, GAPS_OP_ADD, - GAPS_OP_SUBTRACT + GAPS_OP_SUBTRACT, + GAPS_OP_TOGGLE }; struct gaps_data { @@ -102,6 +103,9 @@ case GAPS_OP_SUBTRACT: *prop -= amount; break; + case GAPS_OP_TOGGLE: + *prop = *prop ? 0 : amount; + break; } } @@ -133,9 +137,9 @@ } // gaps inner|outer|horizontal|vertical|top|right|bottom|left current|all -// set|plus|minus +// set|plus|minus|toggle static const char expected_runtime[] = "'gaps inner|outer|horizontal|vertical|" - "top|right|bottom|left current|all set|plus|minus '"; + "top|right|bottom|left current|all set|plus|minus|toggle '"; static struct cmd_results *gaps_set_runtime(int argc, char **argv) { struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 4); if (error) { @@ -180,6 +184,8 @@ data.operation = GAPS_OP_ADD; } else if (strcasecmp(argv[2], "minus") == 0) { data.operation = GAPS_OP_SUBTRACT; + } else if (strcasecmp(argv[2], "toggle") == 0) { + data.operation = GAPS_OP_TOGGLE; } else { return cmd_results_new(CMD_INVALID, "Expected %s", expected_runtime); } @@ -200,7 +206,7 @@ } // gaps inner|outer|| - sets defaults for workspaces -// gaps inner|outer|| current|all set|plus|minus - runtime only +// gaps inner|outer|| current|all set|plus|minus|toggle - runtime only // = horizontal|vertical // = top|right|bottom|left struct cmd_results *cmd_gaps(int argc, char **argv) { diff -Nru sway-1.6.1/sway/commands/input/map_to_region.c sway-1.7/sway/commands/input/map_to_region.c --- sway-1.6.1/sway/commands/input/map_to_region.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/input/map_to_region.c 2022-01-22 22:55:11.000000000 +0000 @@ -1,7 +1,6 @@ #define _POSIX_C_SOURCE 200809L #include #include -#include #include "sway/commands.h" #include "sway/config.h" diff -Nru sway-1.6.1/sway/commands/move.c sway-1.7/sway/commands/move.c --- sway-1.6.1/sway/commands/move.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/move.c 2022-01-22 22:55:11.000000000 +0000 @@ -874,6 +874,10 @@ return cmd_results_new(CMD_INVALID, "Invalid x position specified"); } + if (argc < 1) { + return cmd_results_new(CMD_FAILURE, expected_position_syntax); + } + struct movement_amount ly = { .amount = 0, .unit = MOVEMENT_UNIT_INVALID }; // Y direction num_consumed_args = parse_movement_amount(argc, argv, &ly); diff -Nru sway-1.6.1/sway/commands/output/dpms.c sway-1.7/sway/commands/output/dpms.c --- sway-1.6.1/sway/commands/output/dpms.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/output/dpms.c 2022-01-22 22:55:11.000000000 +0000 @@ -1,6 +1,8 @@ #include "sway/commands.h" #include "sway/config.h" +#include "sway/output.h" #include "util.h" +#include struct cmd_results *output_cmd_dpms(int argc, char **argv) { if (!config->handler_context.output_config) { @@ -10,7 +12,28 @@ 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; diff -Nru sway-1.6.1/sway/commands/output/mode.c sway-1.7/sway/commands/output/mode.c --- sway-1.6.1/sway/commands/output/mode.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/output/mode.c 2022-01-22 22:55:11.000000000 +0000 @@ -20,6 +20,9 @@ output->custom_mode = 0; } + // Reset custom modeline, if any + output->drm_mode.type = 0; + char *end; output->width = strtol(*argv, &end, 10); if (*end) { @@ -58,3 +61,58 @@ return NULL; } +static bool parse_modeline(char **argv, drmModeModeInfo *mode) { + mode->type = DRM_MODE_TYPE_USERDEF; + mode->clock = strtof(argv[0], NULL) * 1000; + mode->hdisplay = strtol(argv[1], NULL, 10); + mode->hsync_start = strtol(argv[2], NULL, 10); + mode->hsync_end = strtol(argv[3], NULL, 10); + mode->htotal = strtol(argv[4], NULL, 10); + mode->vdisplay = strtol(argv[5], NULL, 10); + mode->vsync_start = strtol(argv[6], NULL, 10); + mode->vsync_end = strtol(argv[7], NULL, 10); + mode->vtotal = strtol(argv[8], NULL, 10); + + mode->vrefresh = mode->clock * 1000.0 * 1000.0 + / mode->htotal / mode->vtotal; + if (strcasecmp(argv[9], "+hsync") == 0) { + mode->flags |= DRM_MODE_FLAG_PHSYNC; + } else if (strcasecmp(argv[9], "-hsync") == 0) { + mode->flags |= DRM_MODE_FLAG_NHSYNC; + } else { + return false; + } + + if (strcasecmp(argv[10], "+vsync") == 0) { + mode->flags |= DRM_MODE_FLAG_PVSYNC; + } else if (strcasecmp(argv[10], "-vsync") == 0) { + mode->flags |= DRM_MODE_FLAG_NVSYNC; + } else { + return false; + } + + snprintf(mode->name, sizeof(mode->name), "%dx%d@%d", + mode->hdisplay, mode->vdisplay, mode->vrefresh / 1000); + + return true; +} + +struct cmd_results *output_cmd_modeline(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 modeline argument."); + } + + struct output_config *output = config->handler_context.output_config; + + if (argc != 11 || !parse_modeline(argv, &output->drm_mode)) { + return cmd_results_new(CMD_INVALID, "Invalid modeline"); + } + + config->handler_context.leftovers.argc = argc - 12; + config->handler_context.leftovers.argv = argv + 12; + return NULL; +} + diff -Nru sway-1.6.1/sway/commands/output/render_bit_depth.c sway-1.7/sway/commands/output/render_bit_depth.c --- sway-1.6.1/sway/commands/output/render_bit_depth.c 1970-01-01 00:00:00.000000000 +0000 +++ sway-1.7/sway/commands/output/render_bit_depth.c 2022-01-22 22:55:11.000000000 +0000 @@ -0,0 +1,29 @@ +#include +#include +#include "sway/commands.h" +#include "sway/config.h" + +struct cmd_results *output_cmd_render_bit_depth(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 bit depth argument."); + } + + if (strcmp(*argv, "8") == 0) { + config->handler_context.output_config->render_bit_depth = + RENDER_BIT_DEPTH_8; + } else if (strcmp(*argv, "10") == 0) { + config->handler_context.output_config->render_bit_depth = + RENDER_BIT_DEPTH_10; + } else { + return cmd_results_new(CMD_INVALID, + "Invalid bit depth. Must be a value in (8|10)."); + } + + config->handler_context.leftovers.argc = argc - 1; + config->handler_context.leftovers.argv = argv + 1; + return NULL; +} + diff -Nru sway-1.6.1/sway/commands/output.c sway-1.7/sway/commands/output.c --- sway-1.6.1/sway/commands/output.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/output.c 2022-01-22 22:55:11.000000000 +0000 @@ -15,8 +15,10 @@ { "enable", output_cmd_enable }, { "max_render_time", output_cmd_max_render_time }, { "mode", output_cmd_mode }, + { "modeline", output_cmd_modeline }, { "pos", output_cmd_position }, { "position", output_cmd_position }, + { "render_bit_depth", output_cmd_render_bit_depth }, { "res", output_cmd_mode }, { "resolution", output_cmd_mode }, { "scale", output_cmd_scale }, @@ -32,9 +34,9 @@ return error; } - // The NOOP-1 output is a dummy output used when there's no outputs + // The HEADLESS-1 output is a dummy output used when there's no outputs // connected. It should never be configured. - if (strcasecmp(argv[0], root->noop_output->wlr_output->name) == 0) { + if (strcasecmp(argv[0], root->fallback_output->wlr_output->name) == 0) { return cmd_results_new(CMD_FAILURE, "Refusing to configure the no op output"); } @@ -51,7 +53,7 @@ if (!sway_output) { return cmd_results_new(CMD_FAILURE, "Unknown output"); } - if (sway_output == root->noop_output) { + if (sway_output == root->fallback_output) { return cmd_results_new(CMD_FAILURE, "Refusing to configure the no op output"); } diff -Nru sway-1.6.1/sway/commands/reload.c sway-1.7/sway/commands/reload.c --- sway-1.6.1/sway/commands/reload.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/reload.c 2022-01-22 22:55:11.000000000 +0000 @@ -48,7 +48,6 @@ } list_free_items_and_destroy(bar_ids); - config_update_font_height(true); root_for_each_container(rebuild_textures_iterator, NULL); arrange_root(); diff -Nru sway-1.6.1/sway/commands/smart_gaps.c sway-1.7/sway/commands/smart_gaps.c --- sway-1.6.1/sway/commands/smart_gaps.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/smart_gaps.c 2022-01-22 22:55:11.000000000 +0000 @@ -15,7 +15,12 @@ return error; } - config->smart_gaps = parse_boolean(argv[0], config->smart_gaps); + if (strcmp(argv[0], "inverse_outer") == 0) { + config->smart_gaps = SMART_GAPS_INVERSE_OUTER; + } else { + config->smart_gaps = parse_boolean(argv[0], config->smart_gaps) + ? SMART_GAPS_ON : SMART_GAPS_OFF; + } arrange_root(); diff -Nru sway-1.6.1/sway/commands/split.c sway-1.7/sway/commands/split.c --- sway-1.6.1/sway/commands/split.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/split.c 2022-01-22 22:55:11.000000000 +0000 @@ -32,6 +32,24 @@ return cmd_results_new(CMD_SUCCESS, NULL); } +static struct cmd_results *do_unsplit() { + struct sway_container *con = config->handler_context.container; + struct sway_workspace *ws = config->handler_context.workspace; + + if (con && con->pending.parent && con->pending.parent->pending.children->length == 1) { + container_flatten(con->pending.parent); + } else { + return cmd_results_new(CMD_FAILURE, "Can only flatten a child container with no siblings"); + } + + if (root->fullscreen_global) { + arrange_root(); + } else { + arrange_workspace(ws); + } + return cmd_results_new(CMD_SUCCESS, NULL); +} + struct cmd_results *cmd_split(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "split", EXPECTED_EQUAL_TO, 1))) { @@ -55,6 +73,9 @@ } else { return do_split(L_VERT); } + } else if (strcasecmp(argv[0], "n") == 0 || + strcasecmp(argv[0], "none") == 0) { + return do_unsplit(); } else { return cmd_results_new(CMD_FAILURE, "Invalid split command (expected either horizontal or vertical)."); diff -Nru sway-1.6.1/sway/commands/swap.c sway-1.7/sway/commands/swap.c --- sway-1.6.1/sway/commands/swap.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/swap.c 2022-01-22 22:55:11.000000000 +0000 @@ -126,10 +126,10 @@ } enum sway_fullscreen_mode fs1 = con1->pending.fullscreen_mode; - enum sway_fullscreen_mode fs2 = con2->pending.fullscreen_mode; if (fs1) { container_fullscreen_disable(con1); } + enum sway_fullscreen_mode fs2 = con2->pending.fullscreen_mode; if (fs2) { container_fullscreen_disable(con2); } @@ -247,6 +247,9 @@ } else if (!current) { error = cmd_results_new(CMD_FAILURE, "Can only swap with containers and views"); + } else if (current == other) { + error = cmd_results_new(CMD_FAILURE, + "Cannot swap a container with itself"); } else if (container_has_ancestor(current, other) || container_has_ancestor(other, current)) { error = cmd_results_new(CMD_FAILURE, diff -Nru sway-1.6.1/sway/commands/title_format.c sway-1.7/sway/commands/title_format.c --- sway-1.6.1/sway/commands/title_format.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/title_format.c 2022-01-22 22:55:11.000000000 +0000 @@ -23,6 +23,5 @@ } view->title_format = format; view_update_title(view, true); - config_update_font_height(true); return cmd_results_new(CMD_SUCCESS, NULL); } diff -Nru sway-1.6.1/sway/commands/workspace.c sway-1.7/sway/commands/workspace.c --- sway-1.6.1/sway/commands/workspace.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands/workspace.c 2022-01-22 22:55:11.000000000 +0000 @@ -178,21 +178,16 @@ "Can't switch workspaces while fullscreen global"); } - bool no_auto_back_and_forth = false; + bool auto_back_and_forth = true; while (strcasecmp(argv[0], "--no-auto-back-and-forth") == 0) { - no_auto_back_and_forth = true; + auto_back_and_forth = false; if ((error = checkarg(--argc, "workspace", EXPECTED_AT_LEAST, 1))) { return error; } ++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); - if (!current) { - return cmd_results_new(CMD_FAILURE, "No workspace to switch from"); - } struct sway_workspace *ws = NULL; if (strcasecmp(argv[0], "number") == 0) { @@ -209,14 +204,15 @@ ws = workspace_create(NULL, name); free(name); } + if (ws && auto_back_and_forth) { + ws = workspace_auto_back_and_forth(ws); + } } 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) { if (!seat->prev_workspace_name) { return cmd_results_new(CMD_INVALID, @@ -231,11 +227,14 @@ ws = workspace_create(NULL, name); } free(name); + if (ws && auto_back_and_forth) { + ws = workspace_auto_back_and_forth(ws); + } } if (!ws) { return cmd_results_new(CMD_FAILURE, "No workspace to switch to"); } - workspace_switch(ws, no_auto_back_and_forth); + workspace_switch(ws); seat_consider_warp_to_focus(seat); } return cmd_results_new(CMD_SUCCESS, NULL); diff -Nru sway-1.6.1/sway/commands.c sway-1.7/sway/commands.c --- sway-1.6.1/sway/commands.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/commands.c 2022-01-22 22:55:11.000000000 +0000 @@ -51,6 +51,7 @@ { "client.background", cmd_client_noop }, { "client.focused", cmd_client_focused }, { "client.focused_inactive", cmd_client_focused_inactive }, + { "client.focused_tab_title", cmd_client_focused_tab_title }, { "client.placeholder", cmd_client_noop }, { "client.unfocused", cmd_client_unfocused }, { "client.urgent", cmd_client_urgent }, @@ -465,34 +466,6 @@ goto cleanup; } - enum command_context context = 0; - - struct { - char *name; - enum command_context context; - } context_names[] = { - { "config", CONTEXT_CONFIG }, - { "binding", CONTEXT_BINDING }, - { "ipc", CONTEXT_IPC }, - { "criteria", CONTEXT_CRITERIA }, - { "all", CONTEXT_ALL }, - }; - - for (int i = 1; i < argc; ++i) { - size_t j; - for (j = 0; j < sizeof(context_names) / sizeof(context_names[0]); ++j) { - if (strcmp(context_names[j].name, argv[i]) == 0) { - break; - } - } - if (j == sizeof(context_names) / sizeof(context_names[0])) { - results = cmd_results_new(CMD_INVALID, - "Invalid command context %s", argv[i]); - goto cleanup; - } - context |= context_names[j].context; - } - results = cmd_results_new(CMD_SUCCESS, NULL); cleanup: diff -Nru sway-1.6.1/sway/config/bar.c sway-1.7/sway/config/bar.c --- sway-1.6.1/sway/config/bar.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/config/bar.c 2022-01-22 22:55:11.000000000 +0000 @@ -91,7 +91,7 @@ } bar->outputs = NULL; bar->position = strdup("bottom"); - bar->pango_markup = false; + bar->pango_markup = PANGO_MARKUP_DEFAULT; bar->swaybar_command = NULL; bar->font = NULL; bar->height = 0; @@ -217,6 +217,9 @@ sigset_t set; sigemptyset(&set); sigprocmask(SIG_SETMASK, &set, NULL); + signal(SIGPIPE, SIG_DFL); + + restore_nofile_limit(); pid = fork(); if (pid < 0) { diff -Nru sway-1.6.1/sway/config/output.c sway-1.7/sway/config/output.c --- sway-1.6.1/sway/config/output.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/config/output.c 2022-01-22 22:55:11.000000000 +0000 @@ -1,5 +1,6 @@ #define _POSIX_C_SOURCE 200809L #include +#include #include #include #include @@ -8,6 +9,7 @@ #include #include #include +#include #include "sway/config.h" #include "sway/input/cursor.h" #include "sway/output.h" @@ -58,6 +60,7 @@ oc->width = oc->height = -1; oc->refresh_rate = -1; oc->custom_mode = -1; + oc->drm_mode.type = -1; oc->x = oc->y = -1; oc->scale = -1; oc->scale_filter = SCALE_FILTER_DEFAULT; @@ -65,6 +68,7 @@ oc->subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN; oc->max_render_time = -1; oc->adaptive_sync = -1; + oc->render_bit_depth = RENDER_BIT_DEPTH_DEFAULT; return oc; } @@ -99,6 +103,9 @@ if (src->custom_mode != -1) { dst->custom_mode = src->custom_mode; } + if (src->drm_mode.type != (uint32_t) -1) { + memcpy(&dst->drm_mode, &src->drm_mode, sizeof(src->drm_mode)); + } if (src->transform != -1) { dst->transform = src->transform; } @@ -108,6 +115,9 @@ if (src->adaptive_sync != -1) { dst->adaptive_sync = src->adaptive_sync; } + if (src->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) { + dst->render_bit_depth = src->render_bit_depth; + } if (src->background) { free(dst->background); dst->background = strdup(src->background); @@ -271,6 +281,18 @@ wlr_output_set_mode(output, best); } +static void set_modeline(struct wlr_output *output, drmModeModeInfo *drm_mode) { + if (!wlr_output_is_drm(output)) { + sway_log(SWAY_ERROR, "Modeline can only be set to DRM output"); + return; + } + sway_log(SWAY_DEBUG, "Assigning custom modeline to %s", output->name); + struct wlr_output_mode *mode = wlr_drm_connector_add_mode(output, drm_mode); + if (mode) { + wlr_output_set_mode(output, mode); + } +} + /* Some manufacturers hardcode the aspect-ratio of the output in the physical * size field. */ static bool phys_size_is_aspect_ratio(struct wlr_output *output) { @@ -334,9 +356,26 @@ return 2; } +/* Lists of formats to try, in order, when a specific render bit depth has + * been asked for. The second to last format in each list should always + * be XRGB8888, as a reliable backup in case the others are not available; + * the last should be DRM_FORMAT_INVALID, to indicate the end of the list. */ +static const uint32_t *bit_depth_preferences[] = { + [RENDER_BIT_DEPTH_8] = (const uint32_t []){ + DRM_FORMAT_XRGB8888, + DRM_FORMAT_INVALID, + }, + [RENDER_BIT_DEPTH_10] = (const uint32_t []){ + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_INVALID, + }, +}; + static void queue_output_config(struct output_config *oc, struct sway_output *output) { - if (output == root->noop_output) { + if (output == root->fallback_output) { return; } @@ -351,14 +390,36 @@ sway_log(SWAY_DEBUG, "Turning on output %s", wlr_output->name); wlr_output_enable(wlr_output, true); - if (oc && oc->width > 0 && oc->height > 0) { + if (oc && oc->drm_mode.type != 0 && oc->drm_mode.type != (uint32_t) -1) { + sway_log(SWAY_DEBUG, "Set %s modeline", + wlr_output->name); + set_modeline(wlr_output, &oc->drm_mode); + } else if (oc && oc->width > 0 && oc->height > 0) { sway_log(SWAY_DEBUG, "Set %s mode to %dx%d (%f Hz)", wlr_output->name, oc->width, oc->height, oc->refresh_rate); set_mode(wlr_output, oc->width, oc->height, oc->refresh_rate, oc->custom_mode == 1); } else if (!wl_list_empty(&wlr_output->modes)) { - struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output); - wlr_output_set_mode(wlr_output, mode); + sway_log(SWAY_DEBUG, "Set preferred mode"); + struct wlr_output_mode *preferred_mode = + wlr_output_preferred_mode(wlr_output); + wlr_output_set_mode(wlr_output, preferred_mode); + + if (!wlr_output_test(wlr_output)) { + sway_log(SWAY_DEBUG, "Preferred mode rejected, " + "falling back to another mode"); + struct wlr_output_mode *mode; + wl_list_for_each(mode, &wlr_output->modes, link) { + if (mode == preferred_mode) { + continue; + } + + wlr_output_set_mode(wlr_output, mode); + if (wlr_output_test(wlr_output)) { + break; + } + } + } } if (oc && (oc->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN || config->reloading)) { @@ -367,9 +428,16 @@ wlr_output_set_subpixel(wlr_output, oc->subpixel); } + enum wl_output_transform tr = WL_OUTPUT_TRANSFORM_NORMAL; 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); + tr = oc->transform; + } else if (wlr_output_is_drm(wlr_output)) { + tr = wlr_drm_connector_get_panel_orientation(wlr_output); + sway_log(SWAY_DEBUG, "Auto-detected output transform: %d", tr); + } + if (wlr_output->transform != tr) { + sway_log(SWAY_DEBUG, "Set %s transform to %d", oc->name, tr); + wlr_output_set_transform(wlr_output, tr); } // Apply the scale last before the commit, because the scale auto-detection @@ -391,10 +459,26 @@ oc->adaptive_sync); wlr_output_enable_adaptive_sync(wlr_output, oc->adaptive_sync == 1); } + + if (oc && oc->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) { + const uint32_t *fmts = bit_depth_preferences[oc->render_bit_depth]; + assert(fmts); + + for (size_t i = 0; fmts[i] != DRM_FORMAT_INVALID; i++) { + wlr_output_set_render_format(wlr_output, fmts[i]); + if (wlr_output_test(wlr_output)) { + break; + } + + sway_log(SWAY_DEBUG, "Preferred output format 0x%08x " + "failed to work, falling back to next in " + "list, 0x%08x", fmts[i], fmts[i + 1]); + } + } } bool apply_output_config(struct output_config *oc, struct sway_output *output) { - if (output == root->noop_output) { + if (output == root->fallback_output) { return false; } @@ -489,7 +573,7 @@ } bool test_output_config(struct output_config *oc, struct sway_output *output) { - if (output == root->noop_output) { + if (output == root->fallback_output) { return false; } @@ -704,6 +788,8 @@ sway_log_errno(SWAY_ERROR, "fork failed"); return false; } else if (pid == 0) { + restore_nofile_limit(); + pid = fork(); if (pid < 0) { sway_log_errno(SWAY_ERROR, "fork failed"); diff -Nru sway-1.6.1/sway/config.c sway-1.7/sway/config.c --- sway-1.6.1/sway/config.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/config.c 2022-01-22 22:55:11.000000000 +0000 @@ -236,7 +236,6 @@ config->default_layout = L_NONE; config->default_orientation = L_NONE; if (!(config->font = strdup("monospace 10"))) goto cleanup; - config->font_height = 17; // height of monospace 10 config->urgent_timeout = 500; config->focus_on_window_activation = FOWA_URGENT; config->popup_during_fullscreen = POPUP_SMART; @@ -267,7 +266,7 @@ config->tiling_drag = true; config->tiling_drag_threshold = 9; - config->smart_gaps = false; + config->smart_gaps = SMART_GAPS_OFF; config->gaps_inner = 0; config->gaps_outer.top = 0; config->gaps_outer.right = 0; @@ -291,6 +290,8 @@ config->hide_edge_borders_smart = ESMART_OFF; config->hide_lone_tab = false; + config->has_focused_tab_title = false; + // border colors color_to_rgba(config->border_colors.focused.border, 0x4C7899FF); color_to_rgba(config->border_colors.focused.background, 0x285577FF); @@ -354,12 +355,14 @@ static char *get_config_path(void) { 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); + char *config_home_fallback = NULL; const char *config_home = getenv("XDG_CONFIG_HOME"); - if (config_home == NULL || config_home[0] == '\0') { + if ((config_home == NULL || config_home[0] == '\0') && home != NULL) { + size_t size_fallback = 1 + strlen(home) + strlen("/.config"); + config_home_fallback = calloc(size_fallback, sizeof(char)); + if (config_home_fallback != NULL) + snprintf(config_home_fallback, size_fallback, "%s/.config", home); config_home = config_home_fallback; } @@ -539,6 +542,9 @@ return success; } + // Only really necessary if not explicitly `font` is set in the config. + config_update_font_height(); + if (is_active && !validating) { input_manager_verify_fallback_seat(); @@ -989,31 +995,11 @@ return lenient_strcmp(wsa->workspace, wsb->workspace); } -static void find_font_height_iterator(struct sway_container *con, void *data) { - size_t amount_below_baseline = con->title_height - con->title_baseline; - size_t extended_height = config->font_baseline + amount_below_baseline; - if (extended_height > config->font_height) { - config->font_height = extended_height; - } -} - -static void find_baseline_iterator(struct sway_container *con, void *data) { - bool *recalculate = data; - if (*recalculate) { - container_calculate_title_height(con); - } - if (con->title_baseline > config->font_baseline) { - config->font_baseline = con->title_baseline; - } -} -void config_update_font_height(bool recalculate) { - size_t prev_max_height = config->font_height; - config->font_height = 0; - config->font_baseline = 0; +void config_update_font_height(void) { + int prev_max_height = config->font_height; - root_for_each_container(find_baseline_iterator, &recalculate); - root_for_each_container(find_font_height_iterator, NULL); + get_text_metrics(config->font, &config->font_height, &config->font_baseline); if (config->font_height != prev_max_height) { arrange_root(); diff -Nru sway-1.6.1/sway/desktop/idle_inhibit_v1.c sway-1.7/sway/desktop/idle_inhibit_v1.c --- sway-1.6.1/sway/desktop/idle_inhibit_v1.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/desktop/idle_inhibit_v1.c 2022-01-22 22:55:11.000000000 +0000 @@ -69,8 +69,8 @@ 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) { + if (inhibitor->mode != INHIBIT_IDLE_APPLICATION && + inhibitor->view == view) { return inhibitor; } } @@ -82,8 +82,8 @@ 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) { + if (inhibitor->mode == INHIBIT_IDLE_APPLICATION && + view_from_wlr_surface(inhibitor->wlr_inhibitor->surface) == view) { return inhibitor; } } diff -Nru sway-1.6.1/sway/desktop/layer_shell.c sway-1.7/sway/desktop/layer_shell.c --- sway-1.6.1/sway/desktop/layer_shell.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/desktop/layer_shell.c 2022-01-22 22:55:11.000000000 +0000 @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include @@ -163,9 +162,8 @@ } else if ((state->anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { box.y -= state->margin.bottom; } - if (box.width < 0 || box.height < 0) { - // TODO: Bubble up a protocol error? - wlr_layer_surface_v1_close(layer); + if (!sway_assert(box.width >= 0 && box.height >= 0, + "Expected layer surface to have positive size")) { continue; } // Apply @@ -199,7 +197,7 @@ 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], @@ -285,7 +283,7 @@ } sway_layer->layer_surface->output = NULL; - wlr_layer_surface_v1_close(sway_layer->layer_surface); + wlr_layer_surface_v1_destroy(sway_layer->layer_surface); } static void handle_surface_commit(struct wl_listener *listener, void *data) { @@ -298,21 +296,30 @@ } struct sway_output *output = wlr_output->data; - struct wlr_box old_geo = layer->geo; - arrange_layers(output); + struct wlr_box old_extent = layer->extent; - bool geo_changed = - memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0; - bool layer_changed = layer->layer != layer_surface->current.layer; - if (layer_changed) { - wl_list_remove(&layer->link); - wl_list_insert(&output->layers[layer_surface->current.layer], - &layer->link); - layer->layer = layer_surface->current.layer; - } - if (geo_changed || layer_changed) { - output_damage_surface(output, old_geo.x, old_geo.y, - layer_surface->surface, true); + bool layer_changed = false; + if (layer_surface->current.committed != 0 + || layer->mapped != layer_surface->mapped) { + layer->mapped = layer_surface->mapped; + layer_changed = layer->layer != layer_surface->current.layer; + if (layer_changed) { + wl_list_remove(&layer->link); + wl_list_insert(&output->layers[layer_surface->current.layer], + &layer->link); + layer->layer = layer_surface->current.layer; + } + arrange_layers(output); + } + + wlr_surface_get_extends(layer_surface->surface, &layer->extent); + layer->extent.x += layer->geo.x; + layer->extent.y += layer->geo.y; + + bool extent_changed = + memcmp(&old_extent, &layer->extent, sizeof(struct wlr_box)) != 0; + if (extent_changed || layer_changed) { + output_damage_box(output, &old_extent); output_damage_surface(output, layer->geo.x, layer->geo.y, layer_surface->surface, true); } else { @@ -345,6 +352,8 @@ sway_layer->layer_surface->surface, true); } +static void layer_subsurface_destroy(struct sway_layer_subsurface *subsurface); + static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_layer_surface *sway_layer = wl_container_of(listener, sway_layer, destroy); @@ -353,6 +362,12 @@ if (sway_layer->layer_surface->mapped) { unmap(sway_layer); } + + struct sway_layer_subsurface *subsurface, *subsurface_tmp; + wl_list_for_each_safe(subsurface, subsurface_tmp, &sway_layer->subsurfaces, link) { + layer_subsurface_destroy(subsurface); + } + wl_list_remove(&sway_layer->link); wl_list_remove(&sway_layer->destroy.link); wl_list_remove(&sway_layer->map.link); @@ -421,11 +436,8 @@ subsurface_damage(subsurface, false); } -static void subsurface_handle_destroy(struct wl_listener *listener, - void *data) { - struct sway_layer_subsurface *subsurface = - wl_container_of(listener, subsurface, destroy); - +static void layer_subsurface_destroy(struct sway_layer_subsurface *subsurface) { + wl_list_remove(&subsurface->link); wl_list_remove(&subsurface->map.link); wl_list_remove(&subsurface->unmap.link); wl_list_remove(&subsurface->destroy.link); @@ -433,6 +445,13 @@ free(subsurface); } +static void subsurface_handle_destroy(struct wl_listener *listener, + void *data) { + struct sway_layer_subsurface *subsurface = + wl_container_of(listener, subsurface, destroy); + layer_subsurface_destroy(subsurface); +} + static struct sway_layer_subsurface *create_subsurface( struct wlr_subsurface *wlr_subsurface, struct sway_layer_surface *layer_surface) { @@ -444,6 +463,7 @@ subsurface->wlr_subsurface = wlr_subsurface; subsurface->layer_surface = layer_surface; + wl_list_insert(&layer_surface->subsurfaces, &subsurface->link); subsurface->map.notify = subsurface_handle_map; wl_signal_add(&wlr_subsurface->events.map, &subsurface->map); @@ -476,8 +496,8 @@ static void popup_damage(struct sway_layer_popup *layer_popup, bool whole) { struct wlr_xdg_popup *popup = layer_popup->wlr_popup; struct wlr_surface *surface = popup->base->surface; - int popup_sx = popup->geometry.x - popup->base->geometry.x; - int popup_sy = popup->geometry.y - popup->base->geometry.y; + int popup_sx = popup->geometry.x - popup->base->current.geometry.x; + int popup_sy = popup->geometry.y - popup->base->current.geometry.y; int ox = popup_sx, oy = popup_sy; struct sway_layer_surface *layer; while (true) { @@ -598,14 +618,14 @@ sway_log(SWAY_DEBUG, "new layer surface: namespace %s layer %d anchor %" PRIu32 " size %" PRIu32 "x%" PRIu32 " margin %" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",", layer_surface->namespace, - layer_surface->client_pending.layer, - layer_surface->client_pending.anchor, - layer_surface->client_pending.desired_width, - layer_surface->client_pending.desired_height, - layer_surface->client_pending.margin.top, - layer_surface->client_pending.margin.right, - layer_surface->client_pending.margin.bottom, - layer_surface->client_pending.margin.left); + layer_surface->pending.layer, + layer_surface->pending.anchor, + layer_surface->pending.desired_width, + layer_surface->pending.desired_height, + layer_surface->pending.margin.top, + layer_surface->pending.margin.right, + layer_surface->pending.margin.bottom, + layer_surface->pending.margin.left); if (!layer_surface->output) { // Assign last active output @@ -617,12 +637,12 @@ output = ws->output; } } - if (!output || output == root->noop_output) { + if (!output || output == root->fallback_output) { if (!root->outputs->length) { sway_log(SWAY_ERROR, "no output to auto-assign layer surface '%s' to", layer_surface->namespace); - wlr_layer_surface_v1_close(layer_surface); + wlr_layer_surface_v1_destroy(layer_surface); return; } output = root->outputs->items[0]; @@ -636,6 +656,8 @@ return; } + wl_list_init(&sway_layer->subsurfaces); + sway_layer->surface_commit.notify = handle_surface_commit; wl_signal_add(&layer_surface->surface->events.commit, &sway_layer->surface_commit); @@ -657,15 +679,15 @@ struct sway_output *output = layer_surface->output->data; sway_layer->output_destroy.notify = handle_output_destroy; - wl_signal_add(&output->events.destroy, &sway_layer->output_destroy); + wl_signal_add(&output->events.disable, &sway_layer->output_destroy); - wl_list_insert(&output->layers[layer_surface->client_pending.layer], + wl_list_insert(&output->layers[layer_surface->pending.layer], &sway_layer->link); - // Temporarily set the layer's current state to client_pending + // Temporarily set the layer's current state to pending // So that we can easily arrange it struct wlr_layer_surface_v1_state old_state = layer_surface->current; - layer_surface->current = layer_surface->client_pending; + layer_surface->current = layer_surface->pending; arrange_layers(output); layer_surface->current = old_state; } diff -Nru sway-1.6.1/sway/desktop/output.c sway-1.7/sway/desktop/output.c --- sway-1.6.1/sway/desktop/output.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/desktop/output.c 2022-01-22 22:55:11.000000000 +0000 @@ -4,9 +4,11 @@ #include #include #include +#include +#include #include -#include #include +#include #include #include #include @@ -56,26 +58,6 @@ 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 +66,6 @@ struct sway_view *view; double ox, oy; int width, height; - float rotation; }; static bool get_surface_box(struct surface_iterator_data *data, @@ -99,14 +80,9 @@ int sw = surface->current.width; int sh = surface->current.height; - double _sx = sx; - double _sy = 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 +90,13 @@ 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 +109,7 @@ 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 +125,6 @@ .oy = oy, .width = surface->current.width, .height = surface->current.height, - .rotation = 0, }; wlr_surface_for_each_surface(surface, @@ -173,7 +145,6 @@ - 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 +164,6 @@ - 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 +186,6 @@ .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 +223,6 @@ .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 +394,9 @@ 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 +419,9 @@ 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)++; } @@ -540,7 +508,7 @@ fullscreen_con = workspace->current.fullscreen; } - if (fullscreen_con && fullscreen_con->view) { + if (fullscreen_con && fullscreen_con->view && !debug.noscanout) { // Try to scan-out the fullscreen view static bool last_scanned_out = false; bool scanned_out = @@ -657,38 +625,30 @@ } } -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); - wlr_surface_get_effective_damage(surface, &damage); - wlr_region_scale(&damage, &damage, output->wlr_output->scale); - if (ceil(output->wlr_output->scale) > surface->current.scale) { - // When scaling up a surface, it'll become blurry so we need to - // expand the damage region - wlr_region_expand(&damage, &damage, - 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); + pixman_region32_t damage; + pixman_region32_init(&damage); + wlr_surface_get_effective_damage(surface, &damage); + wlr_region_scale(&damage, &damage, output->wlr_output->scale); + if (ceil(output->wlr_output->scale) > surface->current.scale) { + // When scaling up a surface, it'll become blurry so we need to + // expand the damage region + wlr_region_expand(&damage, &damage, + ceil(output->wlr_output->scale) - surface->current.scale); } + pixman_region32_translate(&damage, box.x, box.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); } @@ -772,7 +732,7 @@ struct sway_output *output; wl_list_for_each(output, &root->all_outputs, link) { - if (output == root->noop_output) { + if (output == root->fallback_output) { continue; } struct wlr_output_configuration_head_v1 *config_head = @@ -794,18 +754,22 @@ static void handle_destroy(struct wl_listener *listener, void *data) { struct sway_output *output = wl_container_of(listener, output, destroy); struct sway_server *server = output->server; - wl_signal_emit(&output->events.destroy, output); + output_begin_destroy(output); if (output->enabled) { output_disable(output); } - output_begin_destroy(output); + + wl_list_remove(&output->link); wl_list_remove(&output->destroy.link); wl_list_remove(&output->commit.link); wl_list_remove(&output->mode.link); wl_list_remove(&output->present.link); + output->wlr_output->data = NULL; + output->wlr_output = NULL; + transaction_commit_dirty(); update_output_manager_config(server); @@ -866,7 +830,7 @@ struct sway_output *output = wl_container_of(listener, output, present); struct wlr_output_event_present *output_event = data; - if (!output->enabled) { + if (!output->enabled || !output_event->presented) { return; } @@ -874,10 +838,39 @@ output->refresh_nsec = output_event->refresh; } +static unsigned int last_headless_num = 0; + void handle_new_output(struct wl_listener *listener, void *data) { struct sway_server *server = wl_container_of(listener, server, new_output); struct wlr_output *wlr_output = data; - sway_log(SWAY_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); + + if (wlr_output == root->fallback_output->wlr_output) { + return; + } + + if (wlr_output_is_headless(wlr_output)) { + char name[64]; + snprintf(name, sizeof(name), "HEADLESS-%u", ++last_headless_num); + wlr_output_set_name(wlr_output, name); + } + + sway_log(SWAY_DEBUG, "New output %p: %s (non-desktop: %d)", + wlr_output, wlr_output->name, wlr_output->non_desktop); + + if (wlr_output->non_desktop) { + sway_log(SWAY_DEBUG, "Not configuring non-desktop output"); + if (server->drm_lease_manager) { + wlr_drm_lease_v1_manager_offer_output(server->drm_lease_manager, + wlr_output); + } + return; + } + + if (!wlr_output_init_render(wlr_output, server->allocator, + server->renderer)) { + sway_log(SWAY_ERROR, "Failed to init output render"); + return; + } struct sway_output *output = output_create(wlr_output); if (!output) { diff -Nru sway-1.6.1/sway/desktop/render.c sway-1.7/sway/desktop/render.c --- sway-1.6.1/sway/desktop/render.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/desktop/render.c 2022-01-22 22:55:11.000000000 +0000 @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -53,7 +52,7 @@ static void scissor_output(struct wlr_output *wlr_output, pixman_box32_t *rect) { - struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); + struct wlr_renderer *renderer = wlr_output->renderer; assert(renderer); struct wlr_box box = { @@ -101,13 +100,9 @@ pixman_region32_t *output_damage, struct wlr_texture *texture, const struct wlr_fbox *src_box, const struct wlr_box *dst_box, const float matrix[static 9], float alpha) { - struct wlr_renderer *renderer = - wlr_backend_get_renderer(wlr_output->backend); + struct wlr_renderer *renderer = wlr_output->renderer; 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 +129,9 @@ 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,7 +151,7 @@ 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; @@ -222,8 +217,7 @@ pixman_region32_t *output_damage, const struct wlr_box *_box, float color[static 4]) { struct wlr_output *wlr_output = output->wlr_output; - struct wlr_renderer *renderer = - wlr_backend_get_renderer(wlr_output->backend); + struct wlr_renderer *renderer = wlr_output->renderer; struct wlr_box box; memcpy(&box, _box, sizeof(struct wlr_box)); @@ -563,8 +557,7 @@ // The title texture might be shorter than the config->font_height, // in which case we need to pad it above and below. - int ob_padding_above = round((config->font_baseline - - con->title_baseline + titlebar_v_padding - + int ob_padding_above = round((titlebar_v_padding - titlebar_border_thickness) * output_scale); int ob_padding_below = ob_bg_height - ob_padding_above - texture_box.height; @@ -769,6 +762,14 @@ } } +static bool container_is_focused(struct sway_container *con, void *data) { + return con->current.focused; +} + +static bool container_has_focused_child(struct sway_container *con) { + return container_find_child(con, container_is_focused, NULL); +} + /** * Render a container's children using the L_TABBED layout. */ @@ -800,6 +801,10 @@ colors = &config->border_colors.focused; title_texture = child->title_focused; marks_texture = child->marks_focused; + } else if (config->has_focused_tab_title && container_has_focused_child(child)) { + colors = &config->border_colors.focused_tab_title; + title_texture = child->title_focused_tab_title; + marks_texture = child->marks_focused_tab_title; } else if (child == parent->active_child) { colors = &config->border_colors.focused_inactive; title_texture = child->title_focused_inactive; @@ -865,7 +870,11 @@ colors = &config->border_colors.focused; title_texture = child->title_focused; marks_texture = child->marks_focused; - } else if (child == parent->active_child) { + } else if (config->has_focused_tab_title && container_has_focused_child(child)) { + colors = &config->border_colors.focused_tab_title; + title_texture = child->title_focused_tab_title; + marks_texture = child->marks_focused_tab_title; + } else if (child == parent->active_child) { colors = &config->border_colors.focused_inactive; title_texture = child->title_focused_inactive; marks_texture = child->marks_focused_inactive; @@ -1018,13 +1027,7 @@ void output_render(struct sway_output *output, struct timespec *when, pixman_region32_t *damage) { struct wlr_output *wlr_output = output->wlr_output; - - struct wlr_renderer *renderer = - wlr_backend_get_renderer(wlr_output->backend); - if (!sway_assert(renderer != NULL, - "expected the output backend to have a renderer")) { - return; - } + struct wlr_renderer *renderer = output->server->renderer; struct sway_workspace *workspace = output->current.active_workspace; if (workspace == NULL) { @@ -1038,6 +1041,12 @@ wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height); + if (debug.damage == DAMAGE_RERENDER) { + int width, height; + wlr_output_transformed_resolution(wlr_output, &width, &height); + pixman_region32_union_rect(damage, damage, 0, 0, width, height); + } + if (!pixman_region32_not_empty(damage)) { // Output isn't damaged but needs buffer swap goto renderer_end; @@ -1045,10 +1054,6 @@ if (debug.damage == DAMAGE_HIGHLIGHT) { wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1}); - } else if (debug.damage == DAMAGE_RERENDER) { - int width, height; - wlr_output_transformed_resolution(wlr_output, &width, &height); - pixman_region32_union_rect(damage, damage, 0, 0, width, height); } if (output_has_opaque_overlay_layer_surface(output)) { @@ -1149,7 +1154,7 @@ wlr_region_transform(&frame_damage, &output->damage->current, transform, width, height); - if (debug.damage == DAMAGE_HIGHLIGHT) { + if (debug.damage != DAMAGE_DEFAULT) { pixman_region32_union_rect(&frame_damage, &frame_damage, 0, 0, wlr_output->width, wlr_output->height); } diff -Nru sway-1.6.1/sway/desktop/transaction.c sway-1.7/sway/desktop/transaction.c --- sway-1.6.1/sway/desktop/transaction.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/desktop/transaction.c 2022-01-22 22:55:11.000000000 +0000 @@ -402,7 +402,7 @@ struct sway_transaction_instruction *instruction = transaction->instructions->items[i]; struct sway_node *node = instruction->node; - bool hidden = node_is_view(node) && + bool hidden = node_is_view(node) && !node->destroying && !view_is_visible(node->sway_container->view); if (should_configure(node, instruction)) { instruction->serial = view_configure(node->sway_container->view, diff -Nru sway-1.6.1/sway/desktop/xdg_shell.c sway-1.7/sway/desktop/xdg_shell.c --- sway-1.6.1/sway/desktop/xdg_shell.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/desktop/xdg_shell.c 2022-01-22 22:55:11.000000000 +0000 @@ -21,18 +21,15 @@ static const struct sway_view_child_impl popup_impl; -static void popup_get_root_coords(struct sway_view_child *child, - int *root_sx, int *root_sy) { +static void popup_get_view_coords(struct sway_view_child *child, + int *sx, int *sy) { struct sway_xdg_popup *popup = (struct sway_xdg_popup *)child; struct wlr_xdg_surface *surface = popup->wlr_xdg_surface; - int x_offset = -child->view->geometry.x - surface->geometry.x; - int y_offset = -child->view->geometry.y - surface->geometry.y; - wlr_xdg_popup_get_toplevel_coords(surface->popup, - x_offset + surface->popup->geometry.x, - y_offset + surface->popup->geometry.y, - root_sx, root_sy); + surface->popup->geometry.x - surface->current.geometry.x, + surface->popup->geometry.y - surface->current.geometry.y, + sx, sy); } static void popup_destroy(struct sway_view_child *child) { @@ -47,7 +44,7 @@ } static const struct sway_view_child_impl popup_impl = { - .get_root_coords = popup_get_root_coords, + .get_view_coords = popup_get_view_coords, .destroy = popup_destroy, }; @@ -75,8 +72,8 @@ // the output box expressed in the coordinate system of the toplevel parent // of the popup struct wlr_box output_toplevel_sx_box = { - .x = output->lx - view->container->pending.content_x, - .y = output->ly - view->container->pending.content_y, + .x = output->lx - view->container->pending.content_x + view->geometry.x, + .y = output->ly - view->container->pending.content_y + view->geometry.y, .width = output->width, .height = output->height, }; @@ -309,7 +306,7 @@ if (view->container->node.instruction) { transaction_notify_view_ready_by_serial(view, - xdg_surface->configure_serial); + xdg_surface->current.configure_serial); } view_damage_from(view); @@ -358,7 +355,8 @@ 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 { @@ -373,11 +371,6 @@ transaction_commit_dirty(); } -static void handle_request_maximize(struct wl_listener *listener, void *data) { - struct wlr_xdg_surface *surface = data; - wlr_xdg_surface_schedule_configure(surface); -} - static void handle_request_move(struct wl_listener *listener, void *data) { struct sway_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, request_move); @@ -420,7 +413,6 @@ wl_list_remove(&xdg_shell_view->commit.link); wl_list_remove(&xdg_shell_view->new_popup.link); wl_list_remove(&xdg_shell_view->request_fullscreen.link); - wl_list_remove(&xdg_shell_view->request_maximize.link); wl_list_remove(&xdg_shell_view->request_move.link); wl_list_remove(&xdg_shell_view->request_resize.link); wl_list_remove(&xdg_shell_view->set_title.link); @@ -433,8 +425,8 @@ struct sway_view *view = &xdg_shell_view->view; struct wlr_xdg_surface *xdg_surface = view->wlr_xdg_surface; - view->natural_width = view->wlr_xdg_surface->geometry.width; - view->natural_height = view->wlr_xdg_surface->geometry.height; + view->natural_width = view->wlr_xdg_surface->current.geometry.width; + view->natural_height = view->wlr_xdg_surface->current.geometry.height; if (!view->natural_width && !view->natural_height) { view->natural_width = view->wlr_xdg_surface->surface->current.width; view->natural_height = view->wlr_xdg_surface->surface->current.height; @@ -442,17 +434,20 @@ bool csd = false; - if (!view->xdg_decoration) { + if (view->xdg_decoration) { + enum wlr_xdg_toplevel_decoration_v1_mode mode = + view->xdg_decoration->wlr_xdg_decoration->requested_mode; + csd = mode == WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; + } else { struct sway_server_decoration *deco = decoration_from_surface(xdg_surface->surface); csd = !deco || deco->wlr_server_decoration->mode == WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT; - } view_map(view, view->wlr_xdg_surface->surface, - xdg_surface->toplevel->client_pending.fullscreen, - xdg_surface->toplevel->client_pending.fullscreen_output, + xdg_surface->toplevel->requested.fullscreen, + xdg_surface->toplevel->requested.fullscreen_output, csd); transaction_commit_dirty(); @@ -469,10 +464,6 @@ wl_signal_add(&xdg_surface->toplevel->events.request_fullscreen, &xdg_shell_view->request_fullscreen); - xdg_shell_view->request_maximize.notify = handle_request_maximize; - wl_signal_add(&xdg_surface->toplevel->events.request_maximize, - &xdg_shell_view->request_maximize); - xdg_shell_view->request_move.notify = handle_request_move; wl_signal_add(&xdg_surface->toplevel->events.request_move, &xdg_shell_view->request_move); diff -Nru sway-1.6.1/sway/desktop/xwayland.c sway-1.7/sway/desktop/xwayland.c --- sway-1.6.1/sway/desktop/xwayland.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/desktop/xwayland.c 2022-01-22 22:55:11.000000000 +0000 @@ -254,6 +254,7 @@ } wlr_xwayland_surface_activate(surface, activated); + wlr_xwayland_surface_restack(surface, NULL, XCB_STACK_MODE_ABOVE); } static void set_tiled(struct sway_view *view, bool tiled) { @@ -435,6 +436,8 @@ wl_list_remove(&xwayland_view->commit.link); } + xwayland_view->view.wlr_xwayland_surface = NULL; + wl_list_remove(&xwayland_view->destroy.link); wl_list_remove(&xwayland_view->request_configure.link); wl_list_remove(&xwayland_view->request_fullscreen.link); diff -Nru sway-1.6.1/sway/input/cursor.c sway-1.7/sway/input/cursor.c --- sway-1.6.1/sway/input/cursor.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/input/cursor.c 2022-01-22 22:55:11.000000000 +0000 @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -84,7 +83,28 @@ struct sway_node *node_at_coords( struct sway_seat *seat, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { - // check for unmanaged views first + // find the output the cursor is on + struct wlr_output *wlr_output = wlr_output_layout_output_at( + root->output_layout, lx, ly); + if (wlr_output == NULL) { + return NULL; + } + struct sway_output *output = wlr_output->data; + if (!output || !output->enabled) { + // output is being destroyed or is being enabled + return NULL; + } + double ox = lx, oy = ly; + wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy); + + // layer surfaces on the overlay layer are rendered on top + if ((*surface = layer_surface_at(output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], + ox, oy, sx, sy))) { + return NULL; + } + + // check for unmanaged views #if HAVE_XWAYLAND struct wl_list *unmanaged = &root->xwayland_unmanaged; struct sway_xwayland_unmanaged *unmanaged_surface; @@ -102,19 +122,6 @@ } } #endif - // find the output the cursor is on - struct wlr_output *wlr_output = wlr_output_layout_output_at( - root->output_layout, lx, ly); - if (wlr_output == NULL) { - return NULL; - } - struct sway_output *output = wlr_output->data; - if (!output || !output->enabled) { - // output is being destroyed or is being enabled - return NULL; - } - double ox = lx, oy = ly; - wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy); if (root->fullscreen_global) { // Try fullscreen container @@ -132,11 +139,6 @@ return NULL; } - if ((*surface = layer_surface_at(output, - &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], - ox, oy, sx, sy))) { - return NULL; - } if (ws->fullscreen) { // Try transient containers for (int i = 0; i < ws->floating->length; ++i) { @@ -496,7 +498,6 @@ pointer_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy); dispatch_cursor_button(cursor, event->device, event->time_msec, BTN_LEFT, WLR_BUTTON_PRESSED); - wlr_seat_pointer_notify_frame(wlr_seat); } } @@ -509,10 +510,9 @@ if (cursor->simulating_pointer_from_touch) { if (cursor->pointer_touch_id == cursor->seat->touch_id) { - cursor->simulating_pointer_from_touch = false; + cursor->pointer_touch_up = true; dispatch_cursor_button(cursor, event->device, event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED); - wlr_seat_pointer_notify_frame(wlr_seat); } } else { wlr_seat_touch_notify_up(wlr_seat, event->time_msec, event->touch_id); @@ -560,6 +560,24 @@ } } +static void handle_touch_frame(struct wl_listener *listener, void *data) { + struct sway_cursor *cursor = + wl_container_of(listener, cursor, touch_frame); + + struct wlr_seat *wlr_seat = cursor->seat->wlr_seat; + + if (cursor->simulating_pointer_from_touch) { + wlr_seat_pointer_notify_frame(wlr_seat); + + if (cursor->pointer_touch_up) { + cursor->pointer_touch_up = false; + cursor->simulating_pointer_from_touch = false; + } + } else { + wlr_seat_touch_notify_frame(wlr_seat); + } +} + static double apply_mapping_from_coord(double low, double high, double value) { if (isnan(value)) { return value; @@ -909,6 +927,7 @@ struct sway_cursor *cursor = wl_container_of( listener, cursor, pinch_begin); struct wlr_event_pointer_pinch_begin *event = data; + cursor_handle_activity_from_device(cursor, event->device); wlr_pointer_gestures_v1_send_pinch_begin( cursor->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->fingers); @@ -918,6 +937,7 @@ struct sway_cursor *cursor = wl_container_of( listener, cursor, pinch_update); struct wlr_event_pointer_pinch_update *event = data; + cursor_handle_activity_from_device(cursor, event->device); wlr_pointer_gestures_v1_send_pinch_update( cursor->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->dx, event->dy, @@ -928,6 +948,7 @@ struct sway_cursor *cursor = wl_container_of( listener, cursor, pinch_end); struct wlr_event_pointer_pinch_end *event = data; + cursor_handle_activity_from_device(cursor, event->device); wlr_pointer_gestures_v1_send_pinch_end( cursor->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->cancelled); @@ -937,6 +958,7 @@ struct sway_cursor *cursor = wl_container_of( listener, cursor, swipe_begin); struct wlr_event_pointer_swipe_begin *event = data; + cursor_handle_activity_from_device(cursor, event->device); wlr_pointer_gestures_v1_send_swipe_begin( cursor->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->fingers); @@ -946,6 +968,7 @@ struct sway_cursor *cursor = wl_container_of( listener, cursor, swipe_update); struct wlr_event_pointer_swipe_update *event = data; + cursor_handle_activity_from_device(cursor, event->device); wlr_pointer_gestures_v1_send_swipe_update( cursor->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->dx, event->dy); @@ -955,6 +978,7 @@ struct sway_cursor *cursor = wl_container_of( listener, cursor, swipe_end); struct wlr_event_pointer_swipe_end *event = data; + cursor_handle_activity_from_device(cursor, event->device); wlr_pointer_gestures_v1_send_swipe_end( cursor->pointer_gestures, cursor->seat->wlr_seat, event->time_msec, event->cancelled); @@ -1045,6 +1069,7 @@ wl_list_remove(&cursor->touch_down.link); wl_list_remove(&cursor->touch_up.link); wl_list_remove(&cursor->touch_motion.link); + wl_list_remove(&cursor->touch_frame.link); wl_list_remove(&cursor->tool_axis.link); wl_list_remove(&cursor->tool_tip.link); wl_list_remove(&cursor->tool_button.link); @@ -1120,6 +1145,9 @@ &cursor->touch_motion); cursor->touch_motion.notify = handle_touch_motion; + wl_signal_add(&wlr_cursor->events.touch_frame, &cursor->touch_frame); + cursor->touch_frame.notify = handle_touch_frame; + wl_signal_add(&wlr_cursor->events.tablet_tool_axis, &cursor->tool_axis); cursor->tool_axis.notify = handle_tool_axis; @@ -1327,7 +1355,7 @@ wl_signal_add(&constraint->events.destroy, &sway_constraint->destroy); struct sway_node *focus = seat_get_focus(seat); - if (focus && focus->type == N_CONTAINER && focus->sway_container->view) { + if (focus && node_is_view(focus)) { struct wlr_surface *surface = focus->sway_container->view->surface; if (surface == constraint->surface) { sway_cursor_constrain(seat->cursor, constraint); diff -Nru sway-1.6.1/sway/input/libinput.c sway-1.7/sway/input/libinput.c --- sway-1.6.1/sway/input/libinput.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/input/libinput.c 2022-01-22 22:55:11.000000000 +0000 @@ -332,6 +332,13 @@ return false; } - const char prefix[] = "platform-"; - return strncmp(id_path, prefix, strlen(prefix)) == 0; + const char prefix_platform[] = "platform-"; + if (strncmp(id_path, prefix_platform, strlen(prefix_platform)) != 0) { + return false; + } + + const char prefix_pci[] = "pci-"; + const char infix_platform[] = "-platform-"; + return (strncmp(id_path, prefix_pci, strlen(prefix_pci)) == 0) && + strstr(id_path, infix_platform); } diff -Nru sway-1.6.1/sway/input/seat.c sway-1.7/sway/input/seat.c --- sway-1.6.1/sway/input/seat.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/input/seat.c 2022-01-22 22:55:11.000000000 +0000 @@ -51,6 +51,16 @@ static void seat_node_destroy(struct sway_seat_node *seat_node) { wl_list_remove(&seat_node->destroy.link); wl_list_remove(&seat_node->link); + + /* + * This is the only time we remove items from the focus stack without + * immediately re-adding them. If we just removed the last thing, + * mark that nothing has focus anymore. + */ + if (wl_list_empty(&seat_node->seat->focus_stack)) { + seat_node->seat->has_focus = false; + } + free(seat_node); } @@ -210,14 +220,13 @@ struct sway_container *seat_get_focus_inactive_view(struct sway_seat *seat, struct sway_node *ancestor) { - if (ancestor->type == N_CONTAINER && ancestor->sway_container->view) { + if (node_is_view(ancestor)) { return ancestor->sway_container; } struct sway_seat_node *current; wl_list_for_each(current, &seat->focus_stack, link) { struct sway_node *node = current->node; - if (node->type == N_CONTAINER && node->sway_container->view && - node_has_ancestor(node, ancestor)) { + if (node_is_view(node) && node_has_ancestor(node, ancestor)) { return node->sway_container; } } @@ -1416,9 +1425,8 @@ if (!seat->has_focus) { return NULL; } - if (wl_list_empty(&seat->focus_stack)) { - return NULL; - } + sway_assert(!wl_list_empty(&seat->focus_stack), + "focus_stack is empty, but has_focus is true"); struct sway_seat_node *current = wl_container_of(seat->focus_stack.next, current, link); return current->node; diff -Nru sway-1.6.1/sway/input/seatop_default.c sway-1.7/sway/input/seatop_default.c --- sway-1.6.1/sway/input/seatop_default.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/input/seatop_default.c 2022-01-22 22:55:11.000000000 +0000 @@ -373,6 +373,9 @@ seat_set_focus_layer(seat, layer); transaction_commit_dirty(); } + if (state == WLR_BUTTON_PRESSED) { + seatop_begin_down_on_surface(seat, surface, time_msec, sx, sy); + } seat_pointer_notify_button(seat, time_msec, button, state); return; } diff -Nru sway-1.6.1/sway/input/seatop_down.c sway-1.7/sway/input/seatop_down.c --- sway-1.6.1/sway/input/seatop_down.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/input/seatop_down.c 2022-01-22 22:55:11.000000000 +0000 @@ -10,6 +10,9 @@ struct seatop_down_event { struct sway_container *con; + struct sway_seat *seat; + struct wl_listener surface_destroy; + struct wlr_surface *surface; double ref_lx, ref_ly; // cursor's x/y at start of op double ref_con_lx, ref_con_ly; // container's x/y at start of op }; @@ -40,8 +43,7 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { struct seatop_down_event *e = seat->seatop_data; - struct sway_container *con = e->con; - if (seat_is_input_allowed(seat, con->view->surface)) { + if (seat_is_input_allowed(seat, e->surface)) { double moved_x = seat->cursor->cursor->x - e->ref_lx; double moved_y = seat->cursor->cursor->y - e->ref_ly; double sx = e->ref_con_lx + moved_x; @@ -62,8 +64,7 @@ static void handle_tablet_tool_motion(struct sway_seat *seat, struct sway_tablet_tool *tool, uint32_t time_msec) { struct seatop_down_event *e = seat->seatop_data; - struct sway_container *con = e->con; - if (seat_is_input_allowed(seat, con->view->surface)) { + if (seat_is_input_allowed(seat, e->surface)) { double moved_x = seat->cursor->cursor->x - e->ref_lx; double moved_y = seat->cursor->cursor->y - e->ref_ly; double sx = e->ref_con_lx + moved_x; @@ -72,6 +73,14 @@ } } +static void handle_destroy(struct wl_listener *listener, void *data) { + struct seatop_down_event *e = + wl_container_of(listener, e, surface_destroy); + if (e) { + seatop_begin_default(e->seat); + } +} + static void handle_unref(struct sway_seat *seat, struct sway_container *con) { struct seatop_down_event *e = seat->seatop_data; if (e->con == con) { @@ -79,6 +88,11 @@ } } +static void handle_end(struct sway_seat *seat) { + struct seatop_down_event *e = seat->seatop_data; + wl_list_remove(&e->surface_destroy.link); +} + static const struct sway_seatop_impl seatop_impl = { .button = handle_button, .pointer_motion = handle_pointer_motion, @@ -86,11 +100,22 @@ .tablet_tool_tip = handle_tablet_tool_tip, .tablet_tool_motion = handle_tablet_tool_motion, .unref = handle_unref, + .end = handle_end, .allow_set_cursor = true, }; void seatop_begin_down(struct sway_seat *seat, struct sway_container *con, - uint32_t time_msec, int sx, int sy) { + uint32_t time_msec, double sx, double sy) { + seatop_begin_down_on_surface(seat, con->view->surface, time_msec, sx, sy); + struct seatop_down_event *e = seat->seatop_data; + e->con = con; + + container_raise_floating(con); + transaction_commit_dirty(); +} + +void seatop_begin_down_on_surface(struct sway_seat *seat, + struct wlr_surface *surface, uint32_t time_msec, double sx, double sy) { seatop_end(seat); struct seatop_down_event *e = @@ -98,7 +123,11 @@ if (!e) { return; } - e->con = con; + e->con = NULL; + e->seat = seat; + e->surface = surface; + wl_signal_add(&e->surface->events.destroy, &e->surface_destroy); + e->surface_destroy.notify = handle_destroy; e->ref_lx = seat->cursor->cursor->x; e->ref_ly = seat->cursor->cursor->y; e->ref_con_lx = sx; @@ -106,7 +135,4 @@ seat->seatop_impl = &seatop_impl; seat->seatop_data = e; - - container_raise_floating(con); - transaction_commit_dirty(); } diff -Nru sway-1.6.1/sway/input/seatop_move_tiling.c sway-1.7/sway/input/seatop_move_tiling.c --- sway-1.6.1/sway/input/seatop_move_tiling.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/input/seatop_move_tiling.c 2022-01-22 22:55:11.000000000 +0000 @@ -16,6 +16,10 @@ // Thickness of the dropzone when dragging to the edge of a layout container #define DROP_LAYOUT_BORDER 30 +// Thickness of indicator when dropping onto a titlebar. This should be a +// multiple of 2. +#define DROP_SPLIT_INDICATOR 10 + struct seatop_move_tiling_event { struct sway_container *con; struct sway_node *target_node; @@ -23,6 +27,8 @@ struct wlr_box drop_box; double ref_lx, ref_ly; // cursor's x/y at start of op bool threshold_reached; + bool split_target; + bool insert_after_target; }; static void handle_render(struct sway_seat *seat, @@ -92,8 +98,76 @@ } } +static void split_border(double pos, int offset, int len, int n_children, + int avoid, int *out_pos, bool *out_after) { + int region = 2 * n_children * (pos - offset) / len; + // If the cursor is over the right side of a left-adjacent titlebar, or the + // left side of a right-adjacent titlebar, it's position when dropped will + // be the same. To avoid this, shift the region for adjacent containers. + if (avoid >= 0) { + if (region == 2 * avoid - 1 || region == 2 * avoid) { + region--; + } else if (region == 2 * avoid + 1 || region == 2 * avoid + 2) { + region++; + } + } + + int child_index = (region + 1) / 2; + *out_after = region % 2; + // When dropping at the beginning or end of a container, show the drop + // region within the container boundary, otherwise show it on top of the + // border between two titlebars. + if (child_index == 0) { + *out_pos = offset; + } else if (child_index == n_children) { + *out_pos = offset + len - DROP_SPLIT_INDICATOR; + } else { + *out_pos = offset + child_index * len / n_children - + DROP_SPLIT_INDICATOR / 2; + } +} + +static bool split_titlebar(struct sway_node *node, struct sway_container *avoid, + struct wlr_cursor *cursor, struct wlr_box *title_box, bool *after) { + struct sway_container *con = node->sway_container; + struct sway_node *parent = &con->pending.parent->node; + int title_height = container_titlebar_height(); + struct wlr_box box; + int n_children, avoid_index; + enum sway_container_layout layout = + parent ? node_get_layout(parent) : L_NONE; + if (layout == L_TABBED || layout == L_STACKED) { + node_get_box(parent, &box); + n_children = node_get_children(parent)->length; + avoid_index = list_find(node_get_children(parent), avoid); + } else { + node_get_box(node, &box); + n_children = 1; + avoid_index = -1; + } + if (layout == L_STACKED && cursor->y < box.y + title_height * n_children) { + // Drop into stacked titlebars. + title_box->width = box.width; + title_box->height = DROP_SPLIT_INDICATOR; + title_box->x = box.x; + split_border(cursor->y, box.y, title_height * n_children, + n_children, avoid_index, &title_box->y, after); + return true; + } else if (layout != L_STACKED && cursor->y < box.y + title_height) { + // Drop into side-by-side titlebars. + title_box->width = DROP_SPLIT_INDICATOR; + title_box->height = title_height; + title_box->y = box.y; + split_border(cursor->x, box.x, box.width, n_children, + avoid_index, &title_box->x, after); + return true; + } + return false; +} + static void handle_motion_postthreshold(struct sway_seat *seat) { struct seatop_move_tiling_event *e = seat->seatop_data; + e->split_target = false; struct wlr_surface *surface = NULL; double sx, sy; struct sway_cursor *cursor = seat->cursor; @@ -127,27 +201,53 @@ return; } + // Check if the cursor is over a tilebar only if the destination + // container is not a descendant of the source container. + if (!surface && !container_has_ancestor(con, e->con) && + split_titlebar(node, e->con, cursor->cursor, + &e->drop_box, &e->insert_after_target)) { + // Don't allow dropping over the source container's titlebar + // to give users a chance to cancel a drag operation. + if (con == e->con) { + e->target_node = NULL; + } else { + e->target_node = node; + e->split_target = true; + } + e->target_edge = WLR_EDGE_NONE; + return; + } + // Traverse the ancestors, trying to find a layout container perpendicular // to the edge. Eg. close to the top or bottom of a horiz layout. + int thresh_top = con->pending.content_y + DROP_LAYOUT_BORDER; + int thresh_bottom = con->pending.content_y + + con->pending.content_height - DROP_LAYOUT_BORDER; + int thresh_left = con->pending.content_x + DROP_LAYOUT_BORDER; + int thresh_right = con->pending.content_x + + con->pending.content_width - DROP_LAYOUT_BORDER; while (con) { enum wlr_edges edge = WLR_EDGE_NONE; enum sway_container_layout layout = container_parent_layout(con); - struct wlr_box parent; - con->pending.parent ? container_get_box(con->pending.parent, &parent) : - workspace_get_box(con->pending.workspace, &parent); + struct wlr_box box; + node_get_box(node_get_parent(&con->node), &box); if (layout == L_HORIZ || layout == L_TABBED) { - if (cursor->cursor->y < parent.y + DROP_LAYOUT_BORDER) { + if (cursor->cursor->y < thresh_top) { edge = WLR_EDGE_TOP; - } else if (cursor->cursor->y > parent.y + parent.height - - DROP_LAYOUT_BORDER) { + box.height = thresh_top - box.y; + } else if (cursor->cursor->y > thresh_bottom) { edge = WLR_EDGE_BOTTOM; + box.height = box.y + box.height - thresh_bottom; + box.y = thresh_bottom; } } else if (layout == L_VERT || layout == L_STACKED) { - if (cursor->cursor->x < parent.x + DROP_LAYOUT_BORDER) { + if (cursor->cursor->x < thresh_left) { edge = WLR_EDGE_LEFT; - } else if (cursor->cursor->x > parent.x + parent.width - - DROP_LAYOUT_BORDER) { + box.width = thresh_left - box.x; + } else if (cursor->cursor->x > thresh_right) { edge = WLR_EDGE_RIGHT; + box.width = box.x + box.width - thresh_right; + box.x = thresh_right; } } if (edge) { @@ -156,8 +256,7 @@ 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); + e->drop_box = box; desktop_damage_box(&e->drop_box); return; } @@ -241,7 +340,8 @@ target_node->sway_workspace : target_node->sway_container->pending.workspace; enum wlr_edges edge = e->target_edge; int after = edge != WLR_EDGE_TOP && edge != WLR_EDGE_LEFT; - bool swap = edge == WLR_EDGE_NONE && target_node->type == N_CONTAINER; + bool swap = edge == WLR_EDGE_NONE && target_node->type == N_CONTAINER && + !e->split_target; if (!swap) { container_detach(con); @@ -250,6 +350,14 @@ // Moving container into empty workspace if (target_node->type == N_WORKSPACE && edge == WLR_EDGE_NONE) { con = workspace_add_tiling(new_ws, con); + } else if (e->split_target) { + struct sway_container *target = target_node->sway_container; + enum sway_container_layout layout = container_parent_layout(target); + if (layout != L_TABBED && layout != L_STACKED) { + container_split(target, L_TABBED); + } + container_add_sibling(target, con, e->insert_after_target); + ipc_event_window(con, "move"); } else if (target_node->type == N_CONTAINER) { // Moving container before/after another struct sway_container *target = target_node->sway_container; diff -Nru sway-1.6.1/sway/input/seatop_resize_floating.c sway-1.7/sway/input/seatop_resize_floating.c --- sway-1.6.1/sway/input/seatop_resize_floating.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/input/seatop_resize_floating.c 2022-01-22 22:55:11.000000000 +0000 @@ -80,17 +80,25 @@ double height = e->ref_height + grow_height; int min_width, max_width, min_height, max_height; floating_calculate_constraints(&min_width, &max_width, - &min_height, &max_height); - width = fmax(min_width + border_width, fmin(width, max_width)); - height = fmax(min_height + border_height, fmin(height, max_height)); + &min_height, &max_height); + width = fmin(width, max_width - border_width); + width = fmax(width, min_width + border_width); + width = fmax(width, 1); + height = fmin(height, max_height - border_height); + height = fmax(height, min_height + border_height); + height = fmax(height, 1); // Apply the view's min/max size if (con->view) { double view_min_width, view_max_width, view_min_height, view_max_height; view_get_constraints(con->view, &view_min_width, &view_max_width, &view_min_height, &view_max_height); - width = fmax(view_min_width + border_width, fmin(width, view_max_width)); - height = fmax(view_min_height + border_height, fmin(height, view_max_height)); + width = fmin(width, view_max_width - border_width); + width = fmax(width, view_min_width + border_width); + width = fmax(width, 1); + height = fmin(height, view_max_height - border_height); + height = fmax(height, view_min_height + border_height); + height = fmax(height, 1); } diff -Nru sway-1.6.1/sway/ipc-json.c sway-1.7/sway/ipc-json.c --- sway-1.6.1/sway/ipc-json.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/ipc-json.c 2022-01-22 22:55:11.000000000 +0000 @@ -1,7 +1,11 @@ +#include +#include #include #include #include -#include +#include +#include +#include #include "config.h" #include "log.h" #include "sway/config.h" @@ -13,10 +17,6 @@ #include "sway/input/input-manager.h" #include "sway/input/cursor.h" #include "sway/input/seat.h" -#include -#include -#include -#include #include "wlr-layer-shell-unstable-v1-protocol.h" #include "sway/desktop/idle_inhibit_v1.h" @@ -1002,6 +1002,17 @@ } } + 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); @@ -1115,7 +1126,9 @@ json_object_object_add(json, "verbose", json_object_new_boolean(bar->verbose)); json_object_object_add(json, "pango_markup", - json_object_new_boolean(bar->pango_markup)); + json_object_new_boolean(bar->pango_markup == PANGO_MARKUP_DEFAULT + ? config->pango_markup + : bar->pango_markup)); json_object *colors = json_object_new_object(); json_object_object_add(colors, "background", diff -Nru sway-1.6.1/sway/ipc-server.c sway-1.7/sway/ipc-server.c --- sway-1.6.1/sway/ipc-server.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/ipc-server.c 2022-01-22 22:55:11.000000000 +0000 @@ -687,7 +687,7 @@ } struct sway_output *output; wl_list_for_each(output, &root->all_outputs, link) { - if (!output->enabled && output != root->noop_output) { + if (!output->enabled && output != root->fallback_output) { json_object_array_add(outputs, ipc_json_describe_disabled_output(output)); } diff -Nru sway-1.6.1/sway/main.c sway-1.7/sway/main.c --- sway-1.6.1/sway/main.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/main.c 2022-01-22 22:55:11.000000000 +0000 @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,7 @@ static bool terminate_request = false; static int exit_value = 0; +static struct rlimit original_nofile_rlimit = {0}; struct sway_server server = {0}; struct sway_debug debug = {0}; @@ -47,43 +49,6 @@ 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) { @@ -100,7 +65,7 @@ sway_log(SWAY_ERROR, "Proprietary Nvidia drivers are NOT supported. " "Use Nouveau. To launch sway anyway, launch with " - "--my-next-gpu-wont-be-nvidia and DO NOT report issues."); + "--unsupported-gpu and DO NOT report issues."); exit(EXIT_FAILURE); } break; @@ -188,6 +153,9 @@ static bool drop_permissions(void) { if (getuid() != geteuid() || getgid() != getegid()) { + sway_log(SWAY_ERROR, "!!! DEPRECATION WARNING: " + "SUID privilege drop will be removed in a future release, please migrate to seatd-launch"); + // Set the gid and uid in the correct order. if (setgid(getgid()) != 0) { sway_log(SWAY_ERROR, "Unable to drop root group, refusing to start"); @@ -206,6 +174,33 @@ return true; } +static void increase_nofile_limit(void) { + if (getrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) { + sway_log_errno(SWAY_ERROR, "Failed to bump max open files limit: " + "getrlimit(NOFILE) failed"); + return; + } + + struct rlimit new_rlimit = original_nofile_rlimit; + new_rlimit.rlim_cur = new_rlimit.rlim_max; + if (setrlimit(RLIMIT_NOFILE, &new_rlimit) != 0) { + sway_log_errno(SWAY_ERROR, "Failed to bump max open files limit: " + "setrlimit(NOFILE) failed"); + sway_log(SWAY_INFO, "Running with %d max open files", + (int)original_nofile_rlimit.rlim_cur); + } +} + +void restore_nofile_limit(void) { + if (original_nofile_rlimit.rlim_cur == 0) { + return; + } + if (setrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) { + sway_log_errno(SWAY_ERROR, "Failed to restore max open files limit: " + "setrlimit(NOFILE) failed"); + } +} + void enable_debug_flag(const char *flag) { if (strcmp(flag, "damage=highlight") == 0) { debug.damage = DAMAGE_HIGHLIGHT; @@ -219,6 +214,8 @@ debug.txn_timings = true; } else if (strncmp(flag, "txn-timeout=", 12) == 0) { server.txn_timeout_ms = atoi(&flag[12]); + } else if (strcmp(flag, "noscanout") == 0) { + debug.noscanout = true; } else { sway_log(SWAY_ERROR, "Unknown debug flag: %s", flag); } @@ -255,7 +252,6 @@ {"verbose", no_argument, NULL, 'V'}, {"get-socketpath", no_argument, NULL, 'p'}, {"unsupported-gpu", no_argument, NULL, 'u'}, - {"my-next-gpu-wont-be-nvidia", no_argument, NULL, 'u'}, {0, 0, 0, 0} }; @@ -349,8 +345,6 @@ log_kernel(); log_distro(); log_env(); - detect_proprietary(allow_unsupported_gpu); - detect_raspi(); if (optind < argc) { // Behave as IPC client if (optind != 1) { @@ -377,6 +371,8 @@ return 0; } + detect_proprietary(allow_unsupported_gpu); + if (!server_privileged_prepare(&server)) { return 1; } @@ -386,6 +382,8 @@ exit(EXIT_FAILURE); } + increase_nofile_limit(); + // handle SIGTERM signals signal(SIGTERM, sig_handler); signal(SIGINT, sig_handler); diff -Nru sway-1.6.1/sway/meson.build sway-1.7/sway/meson.build --- sway-1.6.1/sway/meson.build 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/meson.build 2022-01-22 22:55:11.000000000 +0000 @@ -8,6 +8,7 @@ 'main.c', 'server.c', 'swaynag.c', + 'xdg_activation_v1.c', 'xdg_decoration.c', 'desktop/desktop.c', @@ -187,6 +188,7 @@ 'commands/output/max_render_time.c', 'commands/output/mode.c', 'commands/output/position.c', + 'commands/output/render_bit_depth.c', 'commands/output/scale.c', 'commands/output/scale_filter.c', 'commands/output/subpixel.c', diff -Nru sway-1.6.1/sway/server.c sway-1.7/sway/server.c --- sway-1.6.1/sway/server.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/server.c 2022-01-22 22:55:11.000000000 +0000 @@ -7,16 +7,18 @@ #include #include #include -#include #include #include #include #include #include +#include +#include #include #include #include #include +#include #include #include #include @@ -25,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -56,15 +59,44 @@ return true; } +static void handle_drm_lease_request(struct wl_listener *listener, void *data) { + /* We only offer non-desktop outputs, but in the future we might want to do + * more logic here. */ + + struct wlr_drm_lease_request_v1 *req = data; + struct wlr_drm_lease_v1 *lease = wlr_drm_lease_request_v1_grant(req); + if (!lease) { + sway_log(SWAY_ERROR, "Failed to grant lease request"); + wlr_drm_lease_request_v1_reject(req); + } +} + bool server_init(struct sway_server *server) { sway_log(SWAY_DEBUG, "Initializing Wayland server"); - struct wlr_renderer *renderer = wlr_backend_get_renderer(server->backend); - assert(renderer); + server->renderer = wlr_renderer_autocreate(server->backend); + if (!server->renderer) { + sway_log(SWAY_ERROR, "Failed to create renderer"); + return false; + } + + wlr_renderer_init_wl_shm(server->renderer, server->wl_display); + + if (wlr_renderer_get_dmabuf_texture_formats(server->renderer) != NULL) { + wlr_drm_create(server->wl_display, server->renderer); + server->linux_dmabuf_v1 = + wlr_linux_dmabuf_v1_create(server->wl_display, server->renderer); + } - wlr_renderer_init_wl_display(renderer, server->wl_display); + server->allocator = wlr_allocator_autocreate(server->backend, + server->renderer); + if (!server->allocator) { + sway_log(SWAY_ERROR, "Failed to create allocator"); + return false; + } - server->compositor = wlr_compositor_create(server->wl_display, renderer); + server->compositor = wlr_compositor_create(server->wl_display, + server->renderer); server->compositor_new_surface.notify = handle_compositor_new_surface; wl_signal_add(&server->compositor->events.new_surface, &server->compositor_new_surface); @@ -148,6 +180,17 @@ server->foreign_toplevel_manager = wlr_foreign_toplevel_manager_v1_create(server->wl_display); + server->drm_lease_manager= + wlr_drm_lease_v1_manager_create(server->wl_display, server->backend); + if (server->drm_lease_manager) { + server->drm_lease_request.notify = handle_drm_lease_request; + wl_signal_add(&server->drm_lease_manager->events.request, + &server->drm_lease_request); + } else { + sway_log(SWAY_DEBUG, "Failed to create wlr_drm_lease_device_v1"); + sway_log(SWAY_INFO, "VR will not be available"); + } + 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); @@ -159,6 +202,12 @@ wlr_xdg_foreign_v1_create(server->wl_display, foreign_registry); wlr_xdg_foreign_v2_create(server->wl_display, foreign_registry); + server->xdg_activation_v1 = wlr_xdg_activation_v1_create(server->wl_display); + server->xdg_activation_v1_request_activate.notify = + xdg_activation_v1_handle_request_activate; + wl_signal_add(&server->xdg_activation_v1->events.request_activate, + &server->xdg_activation_v1_request_activate); + // Avoid using "wayland-0" as display socket char name_candidate[16]; for (int i = 1; i <= 32; ++i) { @@ -175,20 +224,20 @@ return false; } - server->noop_backend = wlr_noop_backend_create(server->wl_display); - - struct wlr_output *wlr_output = wlr_noop_add_output(server->noop_backend); - root->noop_output = output_create(wlr_output); - - server->headless_backend = - wlr_headless_backend_create_with_renderer(server->wl_display, renderer); + server->headless_backend = wlr_headless_backend_create(server->wl_display); if (!server->headless_backend) { - sway_log(SWAY_INFO, "Failed to create secondary headless backend, " - "starting without it"); + sway_log(SWAY_ERROR, "Failed to create secondary headless backend"); + wlr_backend_destroy(server->backend); + return false; } else { wlr_multi_backend_add(server->backend, server->headless_backend); } + struct wlr_output *wlr_output = + wlr_headless_add_output(server->headless_backend, 800, 600); + wlr_output_set_name(wlr_output, "FALLBACK"); + root->fallback_output = output_create(wlr_output); + // This may have been set already via -Dtxn-timeout if (!server->txn_timeout_ms) { server->txn_timeout_ms = 200; @@ -245,6 +294,7 @@ wlr_backend_destroy(server->backend); return false; } + return true; } diff -Nru sway-1.6.1/sway/sway.5.scd sway-1.7/sway/sway.5.scd --- sway-1.6.1/sway/sway.5.scd 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/sway.5.scd 2022-01-22 22:55:11.000000000 +0000 @@ -155,7 +155,7 @@ is specified, the view will be fullscreen across all outputs. *gaps* inner|outer|horizontal|vertical|top|right|bottom|left all|current -set|plus|minus +set|plus|minus|toggle Changes the _inner_ or _outer_ gaps for either _all_ workspaces or the _current_ workspace. _outer_ gaps can be altered per side with _top_, _right_, _bottom_, and _left_ or per direction with _horizontal_ and @@ -215,7 +215,7 @@ If unspecified, the default is 10 pixels. Pixels are ignored when moving tiled containers. -*move* [absolute] position [px|ppt] [px|ptt] +*move* [absolute] position [px|ppt] [px|ppt] Moves the focused container to the specified position in the workspace. The position can be specified in pixels or percentage points, omitting the unit defaults to pixels. If _absolute_ is used, the position is @@ -319,8 +319,10 @@ established by the *seat* subcommand of the same name. See *sway-input*(5) for more ways to affect inhibitors. -*split* vertical|v|horizontal|h|toggle|t - Splits the current container, vertically or horizontally. When _toggle_ is +*split* vertical|v|horizontal|h|none|n|toggle|t + Splits the current container, vertically or horizontally. When _none_ is + specified, the effect of a previous split is undone if the current + container is the only child of a split parent. When _toggle_ is specified, the current container is split opposite to the parent container's layout. @@ -404,7 +406,7 @@ a keyboard shortcuts inhibitor is active for the currently focused window. Such inhibitors are usually requested by remote desktop and virtualization software to enable the user to send keyboard shortcuts - to the remote or virtual session. The _--inhibited_ flag allows to + to the remote or virtual session. The _--inhibited_ flag allows one to define bindings which will be exempt from pass-through to such software. The same preference logic as for _--locked_ applies. @@ -497,6 +499,12 @@ *client.focused_inactive* The most recently focused view within a container which is not focused. + *client.focused_tab_title* + A view that has focused descendant container. + Tab or stack container title that is the parent of the focused container + but is not directly focused. Defaults to focused_inactive if not + specified and does not use the indicator and child_border colors. + *client.placeholder* Ignored (present for i3 compatibility). @@ -552,6 +560,12 @@ : #ffffff : #484e50 : #5f676a +| *focused_tab_title* +: #333333 +: #5f676a +: #ffffff +: n/a +: n/a | *unfocused* : #333333 : #222222 @@ -630,14 +644,14 @@ should be used instead. Regardless of whether pango markup is enabled, _font_ should be specified as a pango font description. For more information on pango font descriptions, see - https://developer.gnome.org/pango/stable/pango-Fonts.html#pango-font-description-from-string + https://docs.gtk.org/Pango/type_func.FontDescription.from_string.html#description *force_display_urgency_hint* [ms] If an application on another workspace sets an urgency hint, switching to this workspace may lead to immediate focus of the application, which also means the - window decoration color would be immediately resetted to *client.focused*. This + window decoration color would be immediately reset to *client.focused*. This may make it unnecessarily hard to tell which window originally raised the - event. This option allows to set a _timeout_ in ms to delay the urgency hint reset. + event. This option allows one to set a _timeout_ in ms to delay the urgency hint reset. *titlebar_border_thickness* Thickness of the titlebar border in pixels @@ -690,9 +704,10 @@ borders will only be enabled if the workspace has more than one visible child and gaps equal to zero. -*smart_gaps* on|off +*smart_gaps* on|off|toggle|inverse_outer If smart_gaps are _on_ gaps will only be enabled if a workspace has more - than one child. + than one child. If smart_gaps are _inverse_outer_ outer gaps will only + be enabled if a workspace has exactly one child. *mark* --add|--replace [--toggle] Marks are arbitrary labels that can be used to identify certain windows and diff -Nru sway-1.6.1/sway/sway-bar.5.scd sway-1.7/sway/sway-bar.5.scd --- sway-1.6.1/sway/sway-bar.5.scd 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/sway-bar.5.scd 2022-01-22 22:55:11.000000000 +0000 @@ -40,7 +40,7 @@ *font* Specifies the font to be used in the bar. _font_ should be specified as a pango font description. For more information on pango font descriptions, - see https://developer.gnome.org/pango/stable/pango-Fonts.html#pango-font-description-from-string + see https://docs.gtk.org/Pango/type_func.FontDescription.from_string.html#description *gaps* | | Sets the gaps from the edge of the screen for the bar. Gaps can either be diff -Nru sway-1.6.1/sway/sway-input.5.scd sway-1.7/sway/sway-input.5.scd --- sway-1.6.1/sway/sway-input.5.scd 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/sway-input.5.scd 2022-01-22 22:55:11.000000000 +0000 @@ -233,7 +233,7 @@ not explicitly attached to another seat (similar to a "default" seat). *seat* hide_cursor |when-typing [enable|disable] - Hides the cursor image after the specified event occured. + Hides the cursor image after the specified event occurred. If _timeout_ is specified, then the cursor will be hidden after _timeout_ (in milliseconds) has elapsed with no activity on the cursor. A timeout of 0 @@ -277,7 +277,7 @@ whether future inhibitors are honoured by default, i.e. activated automatically, the default being _enable_. When used at runtime, _disable_ also disables any currently active inhibitors. _activate_, - _deactivate_ and _toggle_ are only useable at runtime and change the + _deactivate_ and _toggle_ are only usable at runtime and change the state of a potentially existing inhibitor on the currently focused window. This can be used with the current seat alias (_-_) to affect only the currently focused window of the current seat. Subcommand diff -Nru sway-1.6.1/sway/sway-ipc.7.scd sway-1.7/sway/sway-ipc.7.scd --- sway-1.6.1/sway/sway-ipc.7.scd 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/sway-ipc.7.scd 2022-01-22 22:55:11.000000000 +0000 @@ -294,7 +294,7 @@ Retrieve a JSON representation of the tree *REPLY*++ -An array of object the represent the current tree. Each object represents one +An array of objects that represent the current tree. Each object represents one node and will have the following properties: [- *PROPERTY* @@ -1131,6 +1131,9 @@ |- 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. diff -Nru sway-1.6.1/sway/swaynag.c sway-1.7/sway/swaynag.c --- sway-1.6.1/sway/swaynag.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/swaynag.c 2022-01-22 22:55:11.000000000 +0000 @@ -64,6 +64,8 @@ sway_log(SWAY_ERROR, "Failed to create fork for swaynag"); goto failed; } else if (pid == 0) { + restore_nofile_limit(); + pid = fork(); if (pid < 0) { sway_log_errno(SWAY_ERROR, "fork failed"); @@ -87,8 +89,8 @@ 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); diff -Nru sway-1.6.1/sway/sway-output.5.scd sway-1.7/sway/sway-output.5.scd --- sway-1.6.1/sway/sway-output.5.scd 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/sway-output.5.scd 2022-01-22 22:55:11.000000000 +0000 @@ -40,6 +40,16 @@ output HDMI-A-1 mode 1920x1080@60Hz +*output* modeline + Configures the specified output to use the given modeline. It can be + generated using *cvt*(1) and *gtf*(1) commands. See *xorg.conf*(5). + Only supported on DRM backend. + + Example: + + output HDMI-A-1 modeline 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync + + *output* position|pos Places the specified output at the specific position in the global coordinate space. The cursor may only be moved between immediately @@ -112,7 +122,7 @@ *output* toggle Toggle the specified output. -*output* dpms on|off +*output* 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. @@ -142,11 +152,26 @@ Enables or disables adaptive synchronization (often referred to as Variable Refresh Rate, or by the vendor-specific names FreeSync/G-Sync). - Adaptive sync allows clients to submit frames a little to late without + Adaptive sync allows clients to submit frames a little too late without having to wait a whole refresh period to display it on screen. Enabling adaptive sync can improve latency, but can cause flickering on some hardware. +*output* render_bit_depth 8|10 + Controls the color channel bit depth at which frames are rendered; the + default is currently 8 bits per channel. + + Setting higher values will not have an effect if hardware and software lack + support for such bit depths. Successfully increasing the render bit depth + will not necessarily increase the bit depth of the frames sent to a display. + An increased render bit depth may provide smoother rendering of gradients, + and screenshots which can more precisely store the colors of programs + which display high bit depth colors. + + Warnings: this can break screenshot/screencast programs which have not been + updated to work with different bit depths. This command is experimental, + and may be removed or changed in the future. + # SEE ALSO *sway*(5) *sway-input*(5) diff -Nru sway-1.6.1/sway/tree/container.c sway-1.7/sway/tree/container.c --- sway-1.6.1/sway/tree/container.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/tree/container.c 2022-01-22 22:55:11.000000000 +0000 @@ -5,8 +5,12 @@ #include #include #include +#include #include +#include #include +#include +#include "linux-dmabuf-unstable-v1-protocol.h" #include "cairo_util.h" #include "pango.h" #include "sway/config.h" @@ -20,6 +24,7 @@ #include "sway/tree/arrange.h" #include "sway/tree/view.h" #include "sway/tree/workspace.h" +#include "sway/xdg_decoration.h" #include "list.h" #include "log.h" #include "stringop.h" @@ -63,6 +68,7 @@ wlr_texture_destroy(con->title_focused_inactive); wlr_texture_destroy(con->title_unfocused); wlr_texture_destroy(con->title_urgent); + wlr_texture_destroy(con->title_focused_tab_title); list_free(con->pending.children); list_free(con->current.children); list_free(con->outputs); @@ -72,11 +78,10 @@ wlr_texture_destroy(con->marks_focused_inactive); wlr_texture_destroy(con->marks_unfocused); wlr_texture_destroy(con->marks_urgent); + wlr_texture_destroy(con->marks_focused_tab_title); - if (con->view) { - if (con->view->container == con) { - con->view->container = NULL; - } + if (con->view && con->view->container == con) { + con->view->container = NULL; if (con->view->destroying) { view_destroy(con->view); } @@ -320,10 +325,10 @@ struct sway_container *container = parent->sway_container; struct wlr_box box = { - .x = container->pending.content_x, - .y = container->pending.content_y, - .width = container->pending.content_width, - .height = container->pending.content_height, + .x = container->pending.content_x, + .y = container->pending.content_y, + .width = container->pending.content_width, + .height = container->pending.content_height, }; if (wlr_box_contains_point(&box, lx, ly)) { @@ -343,10 +348,10 @@ struct sway_container *container = parent->sway_container; struct wlr_box box = { - .x = container->pending.x, - .y = container->pending.y, - .width = container->pending.width, - .height = container->pending.height, + .x = container->pending.x, + .y = container->pending.y, + .width = container->pending.width, + .height = container->pending.height, }; if (wlr_box_contains_point(&box, lx, ly)) { @@ -381,19 +386,17 @@ } static bool surface_is_popup(struct wlr_surface *surface) { - if (wlr_surface_is_xdg_surface(surface)) { - struct wlr_xdg_surface *xdg_surface = - wlr_xdg_surface_from_wlr_surface(surface); - while (xdg_surface && xdg_surface->role != WLR_XDG_SURFACE_ROLE_NONE) { - if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { - return true; - } - xdg_surface = xdg_surface->toplevel->parent; - } - return false; - } - - return false; + while (!wlr_surface_is_xdg_surface(surface)) { + if (!wlr_surface_is_subsurface(surface)) { + return false; + } + struct wlr_subsurface *subsurface = + wlr_subsurface_from_wlr_surface(surface); + surface = subsurface->parent; + } + struct wlr_xdg_surface *xdg_surface = + wlr_xdg_surface_from_wlr_surface(surface); + return xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP; } struct sway_container *container_at(struct sway_workspace *workspace, @@ -492,23 +495,13 @@ return con->outputs->items[con->outputs->length - 1]; } -static void update_title_texture(struct sway_container *con, - struct wlr_texture **texture, struct border_colors *class) { - struct sway_output *output = container_get_effective_output(con); - if (!output) { - return; - } - if (*texture) { - wlr_texture_destroy(*texture); - *texture = NULL; - } - if (!con->formatted_title) { - return; - } - +static void render_titlebar_text_texture(struct sway_output *output, + struct sway_container *con, struct wlr_texture **texture, + struct border_colors *class, bool pango_markup, char *text) { double scale = output->wlr_output->scale; int width = 0; - int height = con->title_height * scale; + int height = config->font_height * scale; + int baseline; // We must use a non-nil cairo_t for cairo_set_font_options to work. // Therefore, we cannot use cairo_create(NULL). @@ -526,8 +519,8 @@ to_cairo_subpixel_order(output->wlr_output->subpixel)); } cairo_set_font_options(c, fo); - get_text_size(c, config->font, &width, NULL, NULL, scale, - config->pango_markup, "%s", con->formatted_title); + get_text_size(c, config->font, &width, NULL, &baseline, scale, + config->pango_markup, "%s", text); cairo_surface_destroy(dummy_surface); cairo_destroy(c); @@ -535,8 +528,19 @@ return; } + if (height > config->font_height * scale) { + height = config->font_height * scale; + } + cairo_surface_t *surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, width, height); + cairo_status_t status = cairo_surface_status(surface); + if (status != CAIRO_STATUS_SUCCESS) { + sway_log(SWAY_ERROR, "cairo_image_surface_create failed: %s", + cairo_status_to_string(status)); + return; + } + cairo_t *cairo = cairo_create(surface); cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); cairo_set_font_options(cairo, fo); @@ -547,16 +551,14 @@ PangoContext *pango = pango_cairo_create_context(cairo); cairo_set_source_rgba(cairo, class->text[0], class->text[1], class->text[2], class->text[3]); - cairo_move_to(cairo, 0, 0); + cairo_move_to(cairo, 0, config->font_baseline * scale - baseline); - pango_printf(cairo, config->font, scale, config->pango_markup, - "%s", con->formatted_title); + render_text(cairo, config->font, scale, pango_markup, "%s", text); cairo_surface_flush(surface); unsigned char *data = cairo_image_surface_get_data(surface); - int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); - struct wlr_renderer *renderer = wlr_backend_get_renderer( - output->wlr_output->backend); + int stride = cairo_image_surface_get_stride(surface); + struct wlr_renderer *renderer = output->wlr_output->renderer; *texture = wlr_texture_from_pixels( renderer, DRM_FORMAT_ARGB8888, stride, width, height, data); cairo_surface_destroy(surface); @@ -564,6 +566,24 @@ cairo_destroy(cairo); } +static void update_title_texture(struct sway_container *con, + struct wlr_texture **texture, struct border_colors *class) { + struct sway_output *output = container_get_effective_output(con); + if (!output) { + return; + } + if (*texture) { + wlr_texture_destroy(*texture); + *texture = NULL; + } + if (!con->formatted_title) { + return; + } + + render_titlebar_text_texture(output, con, texture, class, + config->pango_markup, con->formatted_title); +} + void container_update_title_textures(struct sway_container *container) { update_title_texture(container, &container->title_focused, &config->border_colors.focused); @@ -573,24 +593,11 @@ &config->border_colors.unfocused); update_title_texture(container, &container->title_urgent, &config->border_colors.urgent); + update_title_texture(container, &container->title_focused_tab_title, + &config->border_colors.focused_tab_title); container_damage_whole(container); } -void container_calculate_title_height(struct sway_container *container) { - if (!container->formatted_title) { - container->title_height = 0; - return; - } - cairo_t *cairo = cairo_create(NULL); - int height; - int baseline; - get_text_size(cairo, config->font, NULL, &height, &baseline, 1, - config->pango_markup, "%s", container->formatted_title); - cairo_destroy(cairo); - container->title_height = height; - container->title_baseline = baseline; -} - /** * Calculate and return the length of the tree representation. * An example tree representation is: V[Terminal, Firefox] @@ -656,7 +663,6 @@ } container_build_representation(con->pending.layout, con->pending.children, con->formatted_title); - container_calculate_title_height(con); container_update_title_textures(con); } if (con->pending.parent) { @@ -825,6 +831,8 @@ 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; @@ -833,12 +841,22 @@ if (container->view) { view_set_tiled(container->view, false); if (container->view->using_csd) { + container->saved_border = container->pending.border; container->pending.border = B_CSD; + if (container->view->xdg_decoration) { + struct sway_xdg_decoration *deco = container->view->xdg_decoration; + wlr_xdg_toplevel_decoration_v1_set_mode(deco->wlr_xdg_decoration, + WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE); + } } } 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 { @@ -850,7 +868,11 @@ 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 { @@ -863,6 +885,11 @@ view_set_tiled(container->view, true); if (container->view->using_csd) { container->pending.border = container->saved_border; + if (container->view->xdg_decoration) { + struct sway_xdg_decoration *deco = container->view->xdg_decoration; + wlr_xdg_toplevel_decoration_v1_set_mode(deco->wlr_xdg_decoration, + WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); + } } } container->width_fraction = 0; @@ -884,7 +911,7 @@ size_t border_width = 0; size_t top = 0; - if (con->pending.border != B_CSD) { + if (con->pending.border != B_CSD && !con->pending.fullscreen_mode) { border_width = con->pending.border_thickness * (con->pending.border != B_NONE); top = con->pending.border == B_NORMAL ? container_titlebar_height() : border_width; @@ -1033,18 +1060,96 @@ } } -static void set_fullscreen_iterator(struct sway_container *con, void *data) { +static bool devid_from_fd(int fd, dev_t *devid) { + struct stat stat; + if (fstat(fd, &stat) != 0) { + sway_log_errno(SWAY_ERROR, "fstat failed"); + return false; + } + *devid = stat.st_rdev; + return true; +} + +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); } } + + if (!server.linux_dmabuf_v1 || !con->view->surface) { + return; + } + if (!enable) { + wlr_linux_dmabuf_v1_set_surface_feedback(server.linux_dmabuf_v1, + con->view->surface, NULL); + return; + } + + if (!con->pending.workspace || !con->pending.workspace->output) { + return; + } + + struct sway_output *output = con->pending.workspace->output; + struct wlr_output *wlr_output = output->wlr_output; + + // TODO: add wlroots helpers for all of this stuff + + const struct wlr_drm_format_set *renderer_formats = + wlr_renderer_get_dmabuf_texture_formats(server.renderer); + assert(renderer_formats); + + int renderer_drm_fd = wlr_renderer_get_drm_fd(server.renderer); + int backend_drm_fd = wlr_backend_get_drm_fd(wlr_output->backend); + if (renderer_drm_fd < 0 || backend_drm_fd < 0) { + return; + } + + dev_t render_dev, scanout_dev; + if (!devid_from_fd(renderer_drm_fd, &render_dev) || + !devid_from_fd(backend_drm_fd, &scanout_dev)) { + return; + } + + const struct wlr_drm_format_set *output_formats = + wlr_output_get_primary_formats(output->wlr_output, + WLR_BUFFER_CAP_DMABUF); + if (!output_formats) { + return; + } + + struct wlr_drm_format_set scanout_formats = {0}; + if (!wlr_drm_format_set_intersect(&scanout_formats, + output_formats, renderer_formats)) { + return; + } + + struct wlr_linux_dmabuf_feedback_v1_tranche tranches[] = { + { + .target_device = scanout_dev, + .flags = ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT, + .formats = &scanout_formats, + }, + { + .target_device = render_dev, + .formats = renderer_formats, + }, + }; + + const struct wlr_linux_dmabuf_feedback_v1 feedback = { + .main_device = render_dev, + .tranches = tranches, + .tranches_len = sizeof(tranches) / sizeof(tranches[0]), + }; + wlr_linux_dmabuf_v1_set_surface_feedback(server.linux_dmabuf_v1, + con->view->surface, &feedback); + + wlr_drm_format_set_finish(&scanout_formats); } static void container_fullscreen_workspace(struct sway_container *con) { @@ -1052,9 +1157,7 @@ "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; @@ -1088,9 +1191,7 @@ "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; @@ -1116,9 +1217,7 @@ "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; @@ -1382,10 +1481,6 @@ 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); @@ -1615,43 +1710,8 @@ } free(part); - double scale = output->wlr_output->scale; - int width = 0; - int height = con->title_height * scale; - - cairo_t *c = cairo_create(NULL); - get_text_size(c, config->font, &width, NULL, NULL, scale, false, - "%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); - cairo_set_source_rgba(cairo, class->background[0], class->background[1], - class->background[2], class->background[3]); - cairo_paint(cairo); - PangoContext *pango = pango_cairo_create_context(cairo); - cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); - cairo_set_source_rgba(cairo, class->text[0], class->text[1], - class->text[2], class->text[3]); - cairo_move_to(cairo, 0, 0); - - pango_printf(cairo, config->font, scale, false, "%s", buffer); + render_titlebar_text_texture(output, con, texture, class, false, buffer); - cairo_surface_flush(surface); - unsigned char *data = cairo_image_surface_get_data(surface); - int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); - struct wlr_renderer *renderer = wlr_backend_get_renderer( - output->wlr_output->backend); - *texture = wlr_texture_from_pixels( - renderer, DRM_FORMAT_ARGB8888, stride, width, height, data); - cairo_surface_destroy(surface); - g_object_unref(pango); - cairo_destroy(cairo); free(buffer); } @@ -1667,6 +1727,8 @@ &config->border_colors.unfocused); update_marks_texture(con, &con->marks_urgent, &config->border_colors.urgent); + update_marks_texture(con, &con->marks_focused_tab_title, + &config->border_colors.focused_tab_title); container_damage_whole(con); } diff -Nru sway-1.6.1/sway/tree/output.c sway-1.7/sway/tree/output.c --- sway-1.6.1/sway/tree/output.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/tree/output.c 2022-01-22 22:55:11.000000000 +0000 @@ -56,8 +56,8 @@ } // Saved workspaces - while (root->noop_output->workspaces->length) { - struct sway_workspace *ws = root->noop_output->workspaces->items[0]; + while (root->fallback_output->workspaces->length) { + struct sway_workspace *ws = root->fallback_output->workspaces->items[0]; workspace_detach(ws); output_add_workspace(output, ws); @@ -95,7 +95,7 @@ output->detected_subpixel = wlr_output->subpixel; output->scale_filter = SCALE_FILTER_NEAREST; - wl_signal_init(&output->events.destroy); + wl_signal_init(&output->events.disable); wl_list_insert(&root->all_outputs, &output->link); @@ -192,7 +192,7 @@ new_output = fallback_output; } if (!new_output) { - new_output = root->noop_output; + new_output = root->fallback_output; } struct sway_workspace *new_output_ws = @@ -262,7 +262,7 @@ } sway_log(SWAY_DEBUG, "Disabling output '%s'", output->wlr_output->name); - wl_signal_emit(&output->events.destroy, output); + wl_signal_emit(&output->events.disable, output); output_evacuate(output); @@ -286,13 +286,10 @@ return; } sway_log(SWAY_DEBUG, "Destroying output '%s'", output->wlr_output->name); + wl_signal_emit(&output->node.events.destroy, &output->node); output->node.destroying = true; node_set_dirty(&output->node); - - wl_list_remove(&output->link); - output->wlr_output->data = NULL; - output->wlr_output = NULL; } struct sway_output *output_from_wlr_output(struct wlr_output *output) { diff -Nru sway-1.6.1/sway/tree/root.c sway-1.7/sway/tree/root.c --- sway-1.6.1/sway/tree/root.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/tree/root.c 2022-01-22 22:55:11.000000000 +0000 @@ -374,8 +374,8 @@ } // Saved workspaces - for (int i = 0; i < root->noop_output->workspaces->length; ++i) { - struct sway_workspace *ws = root->noop_output->workspaces->items[i]; + for (int i = 0; i < root->fallback_output->workspaces->length; ++i) { + struct sway_workspace *ws = root->fallback_output->workspaces->items[i]; workspace_for_each_container(ws, f, data); } } @@ -427,8 +427,8 @@ } // Saved workspaces - for (int i = 0; i < root->noop_output->workspaces->length; ++i) { - struct sway_workspace *ws = root->noop_output->workspaces->items[i]; + for (int i = 0; i < root->fallback_output->workspaces->length; ++i) { + struct sway_workspace *ws = root->fallback_output->workspaces->items[i]; if ((result = workspace_find_container(ws, test, data))) { return result; } diff -Nru sway-1.6.1/sway/tree/view.c sway-1.7/sway/tree/view.c --- sway-1.6.1/sway/tree/view.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/tree/view.c 2022-01-22 22:55:11.000000000 +0000 @@ -262,7 +262,7 @@ con->pending.border_left = con->pending.border_right = true; double y_offset = 0; - if (!container_is_floating(con) && ws) { + if (!container_is_floating_or_child(con) && ws) { if (config->hide_edge_borders == E_BOTH || config->hide_edge_borders == E_VERTICAL) { con->pending.border_left = con->pending.x != ws->x; @@ -281,14 +281,15 @@ (config->hide_edge_borders_smart == ESMART_NO_GAPS && !gaps_to_edge(view)); if (smart) { - bool show_border = container_is_floating_or_child(con) || - !view_is_only_visible(view); + bool show_border = !view_is_only_visible(view); con->pending.border_left &= show_border; con->pending.border_right &= show_border; con->pending.border_top &= show_border; con->pending.border_bottom &= show_border; } + } + if (!container_is_floating(con)) { // In a tabbed or stacked container, the container's y is the top of the // title area. We have to offset the surface y by the height of the title, // bar, and disable any top border because we'll always have the title bar. @@ -728,10 +729,29 @@ } struct sway_seat *seat = input_manager_current_seat(); - struct sway_node *node = ws ? seat_get_focus_inactive(seat, &ws->node) - : seat_get_focus_inactive(seat, &root->node); - struct sway_container *target_sibling = node->type == N_CONTAINER ? - node->sway_container : NULL; + struct sway_node *node = + seat_get_focus_inactive(seat, ws ? &ws->node : &root->node); + struct sway_container *target_sibling = NULL; + if (node && node->type == N_CONTAINER) { + if (container_is_floating(node->sway_container)) { + // If we're about to launch the view into the floating container, then + // launch it as a tiled view instead. + if (ws) { + target_sibling = seat_get_focus_inactive_tiling(seat, ws); + if (target_sibling) { + struct sway_container *con = + seat_get_focus_inactive_view(seat, &target_sibling->node); + if (con) { + target_sibling = con; + } + } + } else { + ws = seat_get_last_known_workspace(seat); + } + } else { + target_sibling = node->sway_container; + } + } view->foreign_toplevel = wlr_foreign_toplevel_handle_v1_create(server.foreign_toplevel_manager); @@ -748,13 +768,6 @@ wl_signal_add(&view->foreign_toplevel->events.destroy, &view->foreign_destroy); - // If we're about to launch the view into the floating container, then - // launch it as a tiled view in the root of the workspace instead. - if (target_sibling && container_is_floating(target_sibling)) { - target_sibling = NULL; - ws = seat_get_last_known_workspace(seat); - } - struct sway_container *container = view->container; if (target_sibling) { container_add_sibling(target_sibling, container, 1); @@ -900,30 +913,19 @@ static const struct sway_view_child_impl subsurface_impl; -static void subsurface_get_root_coords(struct sway_view_child *child, - int *root_sx, int *root_sy) { +static void subsurface_get_view_coords(struct sway_view_child *child, + int *sx, int *sy) { struct wlr_surface *surface = child->surface; - *root_sx = -child->view->geometry.x; - *root_sy = -child->view->geometry.y; - if (child->parent && child->parent->impl && - child->parent->impl->get_root_coords) { - int sx, sy; - child->parent->impl->get_root_coords(child->parent, &sx, &sy); - *root_sx += sx; - *root_sy += sy; + child->parent->impl->get_view_coords) { + child->parent->impl->get_view_coords(child->parent, sx, sy); } else { - 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; - } + *sx = *sy = 0; } + struct wlr_subsurface *subsurface = + wlr_subsurface_from_wlr_surface(surface); + *sx += subsurface->current.x; + *sy += subsurface->current.y; } static void subsurface_destroy(struct sway_view_child *child) { @@ -937,7 +939,7 @@ } static const struct sway_view_child_impl subsurface_impl = { - .get_root_coords = subsurface_get_root_coords, + .get_view_coords = subsurface_get_view_coords, .destroy = subsurface_destroy, }; @@ -1006,10 +1008,12 @@ return; } int sx, sy; - child->impl->get_root_coords(child, &sx, &sy); + child->impl->get_view_coords(child, &sx, &sy); desktop_damage_surface(child->surface, - child->view->container->pending.content_x + sx, - child->view->container->pending.content_y + sy, whole); + child->view->container->pending.content_x - + child->view->geometry.x + sx, + child->view->container->pending.content_y - + child->view->geometry.y + sy, whole); } static void view_child_handle_surface_commit(struct wl_listener *listener, @@ -1037,10 +1041,12 @@ static void view_init_subsurfaces(struct sway_view *view, struct wlr_surface *surface) { struct wlr_subsurface *subsurface; - wl_list_for_each(subsurface, &surface->subsurfaces_below, parent_link) { + wl_list_for_each(subsurface, &surface->current.subsurfaces_below, + current.link) { view_subsurface_create(view, subsurface); } - wl_list_for_each(subsurface, &surface->subsurfaces_above, parent_link) { + wl_list_for_each(subsurface, &surface->current.subsurfaces_above, + current.link) { view_subsurface_create(view, subsurface); } } @@ -1048,10 +1054,12 @@ static void view_child_init_subsurfaces(struct sway_view_child *view_child, struct wlr_surface *surface) { struct wlr_subsurface *subsurface; - wl_list_for_each(subsurface, &surface->subsurfaces_below, parent_link) { + wl_list_for_each(subsurface, &surface->current.subsurfaces_below, + current.link) { view_child_subsurface_create(view_child, subsurface); } - wl_list_for_each(subsurface, &surface->subsurfaces_above, parent_link) { + wl_list_for_each(subsurface, &surface->current.subsurfaces_above, + current.link) { view_child_subsurface_create(view_child, subsurface); } } @@ -1106,9 +1114,12 @@ wl_signal_add(&view->events.unmap, &child->view_unmap); child->view_unmap.notify = view_child_handle_view_unmap; - struct sway_workspace *workspace = child->view->container->pending.workspace; - if (workspace) { - wlr_surface_send_enter(child->surface, workspace->output->wlr_output); + struct sway_container *container = child->view->container; + if (container != NULL) { + struct sway_workspace *workspace = container->pending.workspace; + if (workspace) { + wlr_surface_send_enter(child->surface, workspace->output->wlr_output); + } } view_child_init_subsurfaces(child, surface); @@ -1284,8 +1295,6 @@ view->container->title = NULL; view->container->formatted_title = NULL; } - container_calculate_title_height(view->container); - config_update_font_height(false); // Update title after the global font height is updated container_update_title_textures(view->container); @@ -1401,7 +1410,7 @@ saved_buffer->y = view->container->surface_y + sy; saved_buffer->transform = surface->current.transform; wlr_surface_get_buffer_source_box(surface, &saved_buffer->source_box); - wl_list_insert(&view->saved_buffers, &saved_buffer->link); + wl_list_insert(view->saved_buffers.prev, &saved_buffer->link); } } diff -Nru sway-1.6.1/sway/tree/workspace.c sway-1.7/sway/tree/workspace.c --- sway-1.6.1/sway/tree/workspace.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/tree/workspace.c 2022-01-22 22:55:11.000000000 +0000 @@ -50,8 +50,8 @@ } else if (focus && focus->type == N_CONTAINER) { return focus->sway_container->pending.workspace->output; } - // Fallback to the first output or noop output for headless - return root->outputs->length ? root->outputs->items[0] : root->noop_output; + // Fallback to the first output or the headless output + return root->outputs->length ? root->outputs->items[0] : root->fallback_output; } struct sway_workspace *workspace_create(struct sway_output *output, @@ -222,10 +222,8 @@ // not a command about workspaces if (strcmp(_target, "next") == 0 || strcmp(_target, "prev") == 0 || - strncmp(_target, "next_on_output", - strlen("next_on_output")) == 0 || - strncmp(_target, "prev_on_output", - strlen("next_on_output")) == 0 || + strcmp(_target, "next_on_output") == 0 || + strcmp(_target, "prev_on_output") == 0 || strcmp(_target, "number") == 0 || strcmp(_target, "back_and_forth") == 0 || strcmp(_target, "current") == 0) { @@ -363,11 +361,11 @@ if (current && strcmp(name, "prev") == 0) { return workspace_prev(current); } else if (current && strcmp(name, "prev_on_output") == 0) { - return workspace_output_prev(current, false); + return workspace_output_prev(current); } else if (current && strcmp(name, "next") == 0) { return workspace_next(current); } else if (current && strcmp(name, "next_on_output") == 0) { - return workspace_output_next(current, false); + return workspace_output_next(current); } else if (strcmp(name, "current") == 0) { return current; } else if (strcasecmp(name, "back_and_forth") == 0) { @@ -530,7 +528,7 @@ * otherwise the next one is returned. */ static struct sway_workspace *workspace_output_prev_next_impl( - struct sway_output *output, int dir, bool create) { + struct sway_output *output, int dir) { struct sway_seat *seat = input_manager_current_seat(); struct sway_workspace *workspace = seat_get_focused_workspace(seat); if (!workspace) { @@ -540,29 +538,21 @@ } 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]; } -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_output_next(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_output_prev(struct sway_workspace *current) { + return workspace_output_prev_next_impl(current->output, -1); } -bool workspace_switch(struct sway_workspace *workspace, - bool no_auto_back_and_forth) { +struct sway_workspace *workspace_auto_back_and_forth( + struct sway_workspace *workspace) { struct sway_seat *seat = input_manager_current_seat(); struct sway_workspace *active_ws = NULL; struct sway_node *focus = seat_get_focus_inactive(seat, &root->node); @@ -572,14 +562,19 @@ active_ws = focus->sway_container->pending.workspace; } - if (!no_auto_back_and_forth && config->auto_back_and_forth && active_ws - && active_ws == workspace && seat->prev_workspace_name) { + if (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); workspace = new_ws ? new_ws : workspace_create(NULL, seat->prev_workspace_name); } + return workspace; +} + +bool workspace_switch(struct sway_workspace *workspace) { + struct sway_seat *seat = input_manager_current_seat(); sway_log(SWAY_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); @@ -849,24 +844,36 @@ return con; } +bool workspace_has_single_visible_container(struct sway_workspace *ws) { + struct sway_seat *seat = input_manager_get_default_seat(); + struct sway_container *focus = + seat_get_focus_inactive_tiling(seat, ws); + if (focus && !focus->view) { + focus = seat_get_focus_inactive_view(seat, &focus->node); + } + return (focus && focus->view && view_ancestor_is_only_visible(focus->view)); +} + void workspace_add_gaps(struct sway_workspace *ws) { - if (config->smart_gaps) { - struct sway_seat *seat = input_manager_get_default_seat(); - struct sway_container *focus = - seat_get_focus_inactive_tiling(seat, ws); - if (focus && !focus->view) { - focus = seat_get_focus_inactive_view(seat, &focus->node); - } - if (focus && focus->view && view_ancestor_is_only_visible(focus->view)) { - ws->current_gaps.top = 0; - ws->current_gaps.right = 0; - ws->current_gaps.bottom = 0; - ws->current_gaps.left = 0; - return; - } + if (config->smart_gaps == SMART_GAPS_ON + && workspace_has_single_visible_container(ws)) { + ws->current_gaps.top = 0; + ws->current_gaps.right = 0; + ws->current_gaps.bottom = 0; + ws->current_gaps.left = 0; + return; + } + + if (config->smart_gaps == SMART_GAPS_INVERSE_OUTER + && !workspace_has_single_visible_container(ws)) { + ws->current_gaps.top = 0; + ws->current_gaps.right = 0; + ws->current_gaps.bottom = 0; + ws->current_gaps.left = 0; + } else { + ws->current_gaps = ws->gaps_outer; } - ws->current_gaps = ws->gaps_outer; // Add inner gaps and make sure we don't turn out negative ws->current_gaps.top = fmax(0, ws->current_gaps.top + ws->gaps_inner); ws->current_gaps.right = fmax(0, ws->current_gaps.right + ws->gaps_inner); diff -Nru sway-1.6.1/sway/xdg_activation_v1.c sway-1.7/sway/xdg_activation_v1.c --- sway-1.6.1/sway/xdg_activation_v1.c 1970-01-01 00:00:00.000000000 +0000 +++ sway-1.7/sway/xdg_activation_v1.c 2022-01-22 22:55:11.000000000 +0000 @@ -0,0 +1,20 @@ +#include +#include "sway/tree/view.h" + +void xdg_activation_v1_handle_request_activate(struct wl_listener *listener, + void *data) { + const struct wlr_xdg_activation_v1_request_activate_event *event = data; + + if (!wlr_surface_is_xdg_surface(event->surface)) { + return; + } + + struct wlr_xdg_surface *xdg_surface = + wlr_xdg_surface_from_wlr_surface(event->surface); + struct sway_view *view = xdg_surface->data; + if (!xdg_surface->mapped || view == NULL) { + return; + } + + view_request_activate(view); +} diff -Nru sway-1.6.1/sway/xdg_decoration.c sway-1.7/sway/xdg_decoration.c --- sway-1.6.1/sway/xdg_decoration.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/sway/xdg_decoration.c 2022-01-22 22:55:11.000000000 +0000 @@ -10,7 +10,7 @@ void *data) { struct sway_xdg_decoration *deco = wl_container_of(listener, deco, destroy); - if(deco->view) { + if (deco->view) { deco->view->xdg_decoration = NULL; } wl_list_remove(&deco->destroy.link); @@ -23,8 +23,32 @@ void *data) { struct sway_xdg_decoration *deco = wl_container_of(listener, deco, request_mode); + struct sway_view *view = deco->view; + enum wlr_xdg_toplevel_decoration_v1_mode mode = + WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE; + enum wlr_xdg_toplevel_decoration_v1_mode client_mode = + deco->wlr_xdg_decoration->requested_mode; + + bool floating; + if (view->container) { + floating = container_is_floating(view->container); + bool csd = false; + csd = client_mode == + WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; + view_update_csd_from_client(view, csd); + arrange_container(view->container); + transaction_commit_dirty(); + } else { + floating = view->impl->wants_floating && + view->impl->wants_floating(view); + } + + if (floating && client_mode) { + mode = client_mode; + } + wlr_xdg_toplevel_decoration_v1_set_mode(deco->wlr_xdg_decoration, - WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); + mode); } void handle_xdg_decoration(struct wl_listener *listener, void *data) { diff -Nru sway-1.6.1/swaybar/bar.c sway-1.7/swaybar/bar.c --- sway-1.6.1/swaybar/bar.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/swaybar/bar.c 2022-01-22 22:55:11.000000000 +0000 @@ -54,7 +54,6 @@ if (output->input_region != NULL) { wl_region_destroy(output->input_region); } - zxdg_output_v1_destroy(output->xdg_output); wl_output_destroy(output->output); destroy_buffer(&output->buffers[0]); destroy_buffer(&output->buffers[1]); @@ -172,7 +171,7 @@ if (bar->status) { sway_log(SWAY_DEBUG, "Sending %s signal to status command", visible ? "cont" : "stop"); - kill(bar->status->pid, visible ? + kill(-bar->status->pid, visible ? bar->status->cont_signal : bar->status->stop_signal); } } @@ -461,13 +460,28 @@ static void display_in(int fd, short mask, void *data) { struct swaybar *bar = data; + if (mask & (POLLHUP | POLLERR)) { + if (mask & POLLERR) { + sway_log(SWAY_ERROR, "Wayland display poll error"); + } + bar->running = false; + return; + } if (wl_display_dispatch(bar->display) == -1) { + sway_log(SWAY_ERROR, "wl_display_dispatch failed"); bar->running = false; } } static void ipc_in(int fd, short mask, void *data) { struct swaybar *bar = data; + if (mask & (POLLHUP | POLLERR)) { + if (mask & POLLERR) { + sway_log(SWAY_ERROR, "IPC poll error"); + } + bar->running = false; + return; + } if (handle_ipc_readable(bar)) { set_bar_dirty(bar); } diff -Nru sway-1.6.1/swaybar/i3bar.c sway-1.7/swaybar/i3bar.c --- sway-1.6.1/swaybar/i3bar.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/swaybar/i3bar.c 2022-01-22 22:55:11.000000000 +0000 @@ -28,6 +28,19 @@ } } +static bool i3bar_parse_json_color(json_object *json, uint32_t *color) { + if (!json) { + return false; + } + + const char *hexstring = json_object_get_string(json); + bool color_set = parse_color(hexstring, color); + if (!color_set) { + sway_log(SWAY_ERROR, "Ignoring invalid block hexadecimal color string: %s", hexstring); + } + return color_set; +} + static void i3bar_parse_json(struct status_line *status, struct json_object *json_array) { struct i3bar_block *block, *tmp; @@ -68,13 +81,7 @@ strdup(json_object_get_string(full_text)) : NULL; block->short_text = short_text ? strdup(json_object_get_string(short_text)) : NULL; - if (color) { - const char *hexstring = json_object_get_string(color); - block->color_set = parse_color(hexstring, &block->color); - if (!block->color_set) { - sway_log(SWAY_ERROR, "Invalid block color: %s", hexstring); - } - } + block->color_set = i3bar_parse_json_color(color, &block->color); if (min_width) { json_type type = json_object_get_type(min_width); if (type == json_type_int) { @@ -100,14 +107,8 @@ block->separator_block_width = separator_block_width ? json_object_get_int(separator_block_width) : 9; // Airblader features - const char *hex = background ? json_object_get_string(background) : NULL; - if (hex && !parse_color(hex, &block->background)) { - sway_log(SWAY_ERROR, "Ignoring invalid block background: %s", hex); - } - hex = border ? json_object_get_string(border) : NULL; - if (hex && !parse_color(hex, &block->border)) { - sway_log(SWAY_ERROR, "Ignoring invalid block border: %s", hex); - } + i3bar_parse_json_color(background, &block->background); + block->border_set = i3bar_parse_json_color(border, &block->border); block->border_top = border_top ? json_object_get_int(border_top) : 1; block->border_bottom = border_bottom ? json_object_get_int(border_bottom) : 1; diff -Nru sway-1.6.1/swaybar/input.c sway-1.7/swaybar/input.c --- sway-1.6.1/swaybar/input.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/swaybar/input.c 2022-01-22 22:55:11.000000000 +0000 @@ -142,13 +142,11 @@ static bool process_hotspots(struct swaybar_output *output, double x, double y, uint32_t button) { - double px = x * output->scale; - double py = y * output->scale; struct swaybar_hotspot *hotspot; wl_list_for_each(hotspot, &output->hotspots, link) { - if (px >= hotspot->x && py >= hotspot->y - && px < hotspot->x + hotspot->width - && py < hotspot->y + hotspot->height) { + if (x >= hotspot->x && y >= hotspot->y + && x < hotspot->x + hotspot->width + && y < hotspot->y + hotspot->height) { if (HOTSPOT_IGNORE == hotspot->callback(output, hotspot, x, y, button, hotspot->data)) { return true; diff -Nru sway-1.6.1/swaybar/ipc.c sway-1.7/swaybar/ipc.c --- sway-1.6.1/swaybar/ipc.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/swaybar/ipc.c 2022-01-22 22:55:11.000000000 +0000 @@ -550,7 +550,7 @@ // The default depth of 32 is too small to represent some nested layouts, but // we can't pass INT_MAX here because json-c (as of this writing) prefaults // all the memory for its stack. - json_tokener *tok = json_tokener_new_ex(256); + json_tokener *tok = json_tokener_new_ex(JSON_MAX_DEPTH); if (!tok) { sway_log_errno(SWAY_ERROR, "failed to create tokener"); free_ipc_response(resp); diff -Nru sway-1.6.1/swaybar/render.c sway-1.7/swaybar/render.c --- sway-1.6.1/swaybar/render.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/swaybar/render.c 2022-01-22 22:55:11.000000000 +0000 @@ -14,6 +14,7 @@ #include "swaybar/ipc.h" #include "swaybar/render.h" #include "swaybar/status_line.h" +#include "log.h" #if HAVE_TRAY #include "swaybar/tray/tray.h" #endif @@ -53,22 +54,21 @@ return 0; } - uint32_t height = output->height * output->scale; + uint32_t height = output->height; cairo_t *cairo = ctx->cairo; cairo_set_source_u32(cairo, 0xFF0000FF); - int margin = 3 * output->scale; - double ws_vertical_padding = - output->bar->config->status_padding * output->scale; + int margin = 3; + double ws_vertical_padding = output->bar->config->status_padding; char *font = output->bar->config->font; int text_width, text_height; get_text_size(cairo, font, &text_width, &text_height, NULL, - output->scale, false, "%s", error); + 1, false, "%s", error); uint32_t ideal_height = text_height + ws_vertical_padding * 2; - uint32_t ideal_surface_height = ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height; if (!output->bar->config->height && output->height < ideal_surface_height) { return ideal_surface_height; @@ -78,7 +78,7 @@ double text_y = height / 2.0 - text_height / 2.0; cairo_move_to(cairo, *x, (int)floor(text_y)); choose_text_aa_mode(ctx, 0xFF0000FF); - pango_printf(cairo, font, output->scale, false, "%s", error); + render_text(cairo, font, 1, false, "%s", error); *x -= margin; return output->height; } @@ -98,25 +98,24 @@ int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, NULL, - output->scale, config->pango_markup, "%s", text); + 1, config->pango_markup, "%s", text); - double ws_vertical_padding = config->status_padding * output->scale; - int margin = 3 * output->scale; + double ws_vertical_padding = config->status_padding; + int margin = 3; uint32_t ideal_height = text_height + ws_vertical_padding * 2; - uint32_t ideal_surface_height = ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height; if (!output->bar->config->height && output->height < ideal_surface_height) { return ideal_surface_height; } *x -= text_width + margin; - uint32_t height = output->height * output->scale; + uint32_t height = output->height; double text_y = height / 2.0 - text_height / 2.0; cairo_move_to(cairo, *x, (int)floor(text_y)); choose_text_aa_mode(ctx, fontcolor); - pango_printf(cairo, config->font, output->scale, - config->pango_markup, "%s", text); + render_text(cairo, config->font, 1, config->pango_markup, "%s", text); *x -= margin; return output->height; } @@ -165,10 +164,10 @@ struct i3bar_block *block = data; struct status_line *status = output->bar->status; return i3bar_block_send_click(status, block, x, y, - x - (double)hotspot->x / output->scale, - y - (double)hotspot->y / output->scale, - (double)hotspot->width / output->scale, - (double)hotspot->height / output->scale, + x - (double)hotspot->x, + y - (double)hotspot->y, + (double)hotspot->width, + (double)hotspot->height, output->scale, button); } @@ -191,17 +190,17 @@ struct swaybar_output *output = ctx->output; struct swaybar_config *config = output->bar->config; int text_width, text_height; - get_text_size(cairo, config->font, &text_width, &text_height, NULL, - output->scale, block->markup, "%s", text); + get_text_size(cairo, config->font, &text_width, &text_height, NULL, 1, + block->markup, "%s", text); - int margin = 3 * output->scale; - double ws_vertical_padding = config->status_padding * output->scale; + int margin = 3; + double ws_vertical_padding = config->status_padding; int width = text_width; if (block->min_width_str) { int w; - get_text_size(cairo, config->font, &w, NULL, NULL, - output->scale, block->markup, "%s", block->min_width_str); + get_text_size(cairo, config->font, &w, NULL, NULL, 1, block->markup, + "%s", block->min_width_str); block->min_width = w; } if (width < block->min_width) { @@ -210,20 +209,20 @@ double block_width = width; uint32_t ideal_height = text_height + ws_vertical_padding * 2; - uint32_t ideal_surface_height = ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height; if (!output->bar->config->height && output->height < ideal_surface_height) { return ideal_surface_height; } *x -= width; - if ((block->border || block->urgent) && block->border_left > 0) { - *x -= (block->border_left * output->scale + margin); - block_width += block->border_left * output->scale + margin; - } - if ((block->border || block->urgent) && block->border_right > 0) { - *x -= (block->border_right * output->scale + margin); - block_width += block->border_right * output->scale + margin; + if ((block->border_set || block->urgent) && block->border_left > 0) { + *x -= (block->border_left + margin); + block_width += block->border_left + margin; + } + if ((block->border_set || block->urgent) && block->border_right > 0) { + *x -= (block->border_right + margin); + block_width += block->border_right + margin; } int sep_width, sep_height; @@ -231,9 +230,9 @@ if (!edge) { if (config->sep_symbol) { get_text_size(cairo, config->font, &sep_width, &sep_height, NULL, - output->scale, false, "%s", config->sep_symbol); + 1, false, "%s", config->sep_symbol); uint32_t _ideal_height = sep_height + ws_vertical_padding * 2; - uint32_t _ideal_surface_height = _ideal_height / output->scale; + uint32_t _ideal_surface_height = _ideal_height; if (!output->bar->config->height && output->height < _ideal_surface_height) { return _ideal_surface_height; @@ -244,10 +243,10 @@ } *x -= sep_block_width; } else if (config->status_edge_padding) { - *x -= config->status_edge_padding * output->scale; + *x -= config->status_edge_padding; } - uint32_t height = output->height * output->scale; + uint32_t height = output->height; if (output->bar->status->click_events) { struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); hotspot->x = *x; @@ -275,19 +274,21 @@ uint32_t border_color = block->urgent ? config->colors.urgent_workspace.border : block->border; - if (border_color && block->border_top > 0) { - render_sharp_line(cairo, border_color, x_pos, y_pos, - block_width, block->border_top * output->scale); - } - if (border_color && block->border_bottom > 0) { - render_sharp_line(cairo, border_color, x_pos, - y_pos + render_height - block->border_bottom * output->scale, - block_width, block->border_bottom * output->scale); - } - if (border_color && block->border_left > 0) { - render_sharp_line(cairo, border_color, x_pos, y_pos, - block->border_left * output->scale, render_height); - x_pos += block->border_left * output->scale + margin; + if (block->border_set || block->urgent) { + if (block->border_top > 0) { + render_sharp_line(cairo, border_color, x_pos, y_pos, + block_width, block->border_top); + } + if (block->border_bottom > 0) { + render_sharp_line(cairo, border_color, x_pos, + y_pos + render_height - block->border_bottom, + block_width, block->border_bottom); + } + if (block->border_left > 0) { + render_sharp_line(cairo, border_color, x_pos, y_pos, + block->border_left, render_height); + } + x_pos += block->border_left + margin; } double offset = 0; @@ -306,15 +307,16 @@ color = block->urgent ? config->colors.urgent_workspace.text : color; cairo_set_source_u32(cairo, color); choose_text_aa_mode(ctx, color); - pango_printf(cairo, config->font, output->scale, - block->markup, "%s", text); + render_text(cairo, config->font, 1, block->markup, "%s", text); x_pos += width; - if (block->border && block->border_right > 0) { + if (block->border_set || block->urgent) { x_pos += margin; - render_sharp_line(cairo, border_color, x_pos, y_pos, - block->border_right * output->scale, render_height); - x_pos += block->border_right * output->scale; + if (block->border_right > 0) { + render_sharp_line(cairo, border_color, x_pos, y_pos, + block->border_right, render_height); + } + x_pos += block->border_right; } if (!edge && block->separator) { @@ -329,7 +331,7 @@ double sep_y = height / 2.0 - sep_height / 2.0; cairo_move_to(cairo, offset, (int)floor(sep_y)); choose_text_aa_mode(ctx, color); - pango_printf(cairo, config->font, output->scale, false, + render_text(cairo, config->font, 1, false, "%s", config->sep_symbol); } else { cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); @@ -352,18 +354,18 @@ struct swaybar_config *config = output->bar->config; int text_width, text_height; - get_text_size(cairo, config->font, &text_width, &text_height, NULL, - output->scale, block->markup, "%s", block->full_text); + get_text_size(cairo, config->font, &text_width, &text_height, NULL, 1, + block->markup, "%s", block->full_text); - int margin = 3 * output->scale; - double ws_vertical_padding = config->status_padding * output->scale; + int margin = 3; + double ws_vertical_padding = config->status_padding; int width = text_width; if (block->min_width_str) { int w; get_text_size(cairo, config->font, &w, NULL, NULL, - output->scale, block->markup, "%s", block->min_width_str); + 1, block->markup, "%s", block->min_width_str); block->min_width = w; } if (width < block->min_width) { @@ -371,18 +373,18 @@ } uint32_t ideal_height = text_height + ws_vertical_padding * 2; - uint32_t ideal_surface_height = ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height; if (!output->bar->config->height && output->height < ideal_surface_height) { return; } *x -= width; - if ((block->border || block->urgent) && block->border_left > 0) { - *x -= (block->border_left * output->scale + margin); + if ((block->border_set || block->urgent) && block->border_left > 0) { + *x -= (block->border_left + margin); } - if ((block->border || block->urgent) && block->border_right > 0) { - *x -= (block->border_right * output->scale + margin); + if ((block->border_set || block->urgent) && block->border_right > 0) { + *x -= (block->border_right + margin); } int sep_width, sep_height; @@ -390,9 +392,9 @@ if (!edge) { if (config->sep_symbol) { get_text_size(cairo, config->font, &sep_width, &sep_height, NULL, - output->scale, false, "%s", config->sep_symbol); + 1, false, "%s", config->sep_symbol); uint32_t _ideal_height = sep_height + ws_vertical_padding * 2; - uint32_t _ideal_surface_height = _ideal_height / output->scale; + uint32_t _ideal_surface_height = _ideal_height; if (!output->bar->config->height && output->height < _ideal_surface_height) { return; @@ -403,13 +405,13 @@ } *x -= sep_block_width; } else if (config->status_edge_padding) { - *x -= config->status_edge_padding * output->scale; + *x -= config->status_edge_padding; } } static double predict_status_line_pos(cairo_t *cairo, struct swaybar_output *output, double x) { - bool edge = x == output->width * output->scale; + bool edge = x == output->width; struct i3bar_block *block; wl_list_for_each(block, &output->bar->status->blocks, link) { predict_status_block_pos(cairo, output, block, &x, edge); @@ -424,24 +426,24 @@ struct swaybar_config *config = output->bar->config; int text_width, text_height; - get_text_size(cairo, config->font, &text_width, &text_height, NULL, - output->scale, config->pango_markup, "%s", ws->label); + get_text_size(cairo, config->font, &text_width, &text_height, NULL, 1, + config->pango_markup, "%s", ws->label); - int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; - int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale; - int border_width = BORDER_WIDTH * output->scale; + int ws_vertical_padding = WS_VERTICAL_PADDING; + int ws_horizontal_padding = WS_HORIZONTAL_PADDING; + int border_width = BORDER_WIDTH; uint32_t ideal_height = ws_vertical_padding * 2 + text_height + border_width * 2; - uint32_t ideal_surface_height = ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height; if (!output->bar->config->height && output->height < ideal_surface_height) { return 0; } uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; - if (width < config->workspace_min_width * output->scale) { - width = config->workspace_min_width * output->scale; + if (width < config->workspace_min_width) { + width = config->workspace_min_width; } return width; } @@ -473,23 +475,23 @@ int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, NULL, - output->scale, output->bar->mode_pango_markup, + 1, output->bar->mode_pango_markup, "%s", mode); - int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; - int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale; - int border_width = BORDER_WIDTH * output->scale; + int ws_vertical_padding = WS_VERTICAL_PADDING; + int ws_horizontal_padding = WS_HORIZONTAL_PADDING; + int border_width = BORDER_WIDTH; uint32_t ideal_height = text_height + ws_vertical_padding * 2 + border_width * 2; - uint32_t ideal_surface_height = ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height; if (!output->bar->config->height && output->height < ideal_surface_height) { return 0; } uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; - if (width < config->workspace_min_width * output->scale) { - width = config->workspace_min_width * output->scale; + if (width < config->workspace_min_width) { + width = config->workspace_min_width; } return width; } @@ -497,7 +499,7 @@ static uint32_t render_status_line_i3bar(struct render_context *ctx, double *x) { struct swaybar_output *output = ctx->output; uint32_t max_height = 0; - bool edge = *x == output->width * output->scale; + bool edge = *x == output->width; struct i3bar_block *block; bool use_short_text = false; @@ -505,7 +507,7 @@ double reserved_width = predict_workspace_buttons_length(cairo, output) + predict_binding_mode_indicator_length(cairo, output) + - 3 * output->scale; // require a bit of space for margin + 3; // require a bit of space for margin double predicted_full_pos = predict_status_line_pos(cairo, output, *x); @@ -550,26 +552,26 @@ struct swaybar_config *config = output->bar->config; int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, NULL, - output->scale, output->bar->mode_pango_markup, + 1, output->bar->mode_pango_markup, "%s", mode); - int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; - int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale; - int border_width = BORDER_WIDTH * output->scale; + int ws_vertical_padding = WS_VERTICAL_PADDING; + int ws_horizontal_padding = WS_HORIZONTAL_PADDING; + int border_width = BORDER_WIDTH; uint32_t ideal_height = text_height + ws_vertical_padding * 2 + border_width * 2; - uint32_t ideal_surface_height = ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height; if (!output->bar->config->height && output->height < ideal_surface_height) { return ideal_surface_height; } uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; - if (width < config->workspace_min_width * output->scale) { - width = config->workspace_min_width * output->scale; + if (width < config->workspace_min_width) { + width = config->workspace_min_width; } - uint32_t height = output->height * output->scale; + uint32_t height = output->height; cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); cairo_set_source_u32(cairo, config->colors.binding_mode.background); ctx->background_color = config->colors.binding_mode.background; @@ -590,8 +592,8 @@ cairo_set_source_u32(cairo, config->colors.binding_mode.text); cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y)); choose_text_aa_mode(ctx, config->colors.binding_mode.text); - pango_printf(cairo, config->font, output->scale, - output->bar->mode_pango_markup, "%s", mode); + render_text(cairo, config->font, 1, output->bar->mode_pango_markup, + "%s", mode); return output->height; } @@ -620,28 +622,28 @@ box_colors = config->colors.inactive_workspace; } - uint32_t height = output->height * output->scale; + uint32_t height = output->height; cairo_t *cairo = ctx->cairo; int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, NULL, - output->scale, config->pango_markup, "%s", ws->label); + 1, config->pango_markup, "%s", ws->label); - int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; - int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale; - int border_width = BORDER_WIDTH * output->scale; + int ws_vertical_padding = WS_VERTICAL_PADDING; + int ws_horizontal_padding = WS_HORIZONTAL_PADDING; + int border_width = BORDER_WIDTH; uint32_t ideal_height = ws_vertical_padding * 2 + text_height + border_width * 2; - uint32_t ideal_surface_height = ideal_height / output->scale; + uint32_t ideal_surface_height = ideal_height; if (!output->bar->config->height && output->height < ideal_surface_height) { return ideal_surface_height; } uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; - if (width < config->workspace_min_width * output->scale) { - width = config->workspace_min_width * output->scale; + if (width < config->workspace_min_width) { + width = config->workspace_min_width; } cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); @@ -664,7 +666,7 @@ cairo_set_source_u32(cairo, box_colors.text); cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y)); choose_text_aa_mode(ctx, box_colors.text); - pango_printf(cairo, config->font, output->scale, config->pango_markup, + render_text(cairo, config->font, 1, config->pango_markup, "%s", ws->label); struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); @@ -697,8 +699,8 @@ cairo_paint(cairo); int th; - get_text_size(cairo, config->font, NULL, &th, NULL, output->scale, false, ""); - uint32_t max_height = (th + WS_VERTICAL_PADDING * 4) / output->scale; + get_text_size(cairo, config->font, NULL, &th, NULL, 1, false, ""); + uint32_t max_height = (th + WS_VERTICAL_PADDING * 4); /* * Each render_* function takes the actual height of the bar, and returns * the ideal height. If the actual height is too short, the render function @@ -706,7 +708,7 @@ * height is too tall, the render function should adapt its drawing to * utilize the available space. */ - double x = output->width * output->scale; + double x = output->width; #if HAVE_TRAY if (bar->tray) { uint32_t h = render_tray(cairo, output, &x); @@ -762,6 +764,7 @@ cairo_surface_t *recorder = cairo_recording_surface_create( CAIRO_CONTENT_COLOR_ALPHA, NULL); cairo_t *cairo = cairo_create(recorder); + cairo_scale(cairo, output->scale, output->scale); cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); ctx.cairo = cairo; @@ -810,9 +813,7 @@ output->width * output->scale, output->height * output->scale); if (!output->current_buffer) { - cairo_surface_destroy(recorder); - cairo_destroy(cairo); - return; + goto cleanup; } cairo_t *shm = output->current_buffer->cairo; @@ -837,6 +838,7 @@ wl_surface_commit(output->surface); } +cleanup: if (ctx.textaa_sharp != ctx.textaa_safe) { cairo_font_options_destroy(ctx.textaa_sharp); } diff -Nru sway-1.6.1/swaybar/status_line.c sway-1.7/swaybar/status_line.c --- sway-1.6.1/swaybar/status_line.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/swaybar/status_line.c 2022-01-22 22:55:11.000000000 +0000 @@ -117,11 +117,11 @@ status->text = status->buffer; // intentional fall-through case PROTOCOL_TEXT: - errno = 0; while (true) { if (status->buffer[read_bytes - 1] == '\n') { status->buffer[read_bytes - 1] = '\0'; } + errno = 0; read_bytes = getline(&status->buffer, &status->buffer_size, status->read); if (errno == EAGAIN) { @@ -157,7 +157,12 @@ assert(!getenv("WAYLAND_SOCKET") && "display must be initialized before " " starting `status-command`; WAYLAND_SOCKET should not be set"); status->pid = fork(); - if (status->pid == 0) { + if (status->pid < 0) { + sway_log_errno(SWAY_ERROR, "fork failed"); + exit(1); + } else if (status->pid == 0) { + setpgid(0, 0); + dup2(pipe_read_fd[1], STDOUT_FILENO); close(pipe_read_fd[0]); close(pipe_read_fd[1]); @@ -185,8 +190,8 @@ void status_line_free(struct status_line *status) { status_line_close_fds(status); - kill(status->pid, status->cont_signal); - kill(status->pid, SIGTERM); + kill(-status->pid, status->cont_signal); + kill(-status->pid, SIGTERM); waitpid(status->pid, NULL, 0); if (status->protocol == PROTOCOL_I3BAR) { struct i3bar_block *block, *tmp; diff -Nru sway-1.6.1/swaybar/tray/item.c sway-1.7/swaybar/tray/item.c --- sway-1.6.1/swaybar/tray/item.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/swaybar/tray/item.c 2022-01-22 22:55:11.000000000 +0000 @@ -493,24 +493,36 @@ cairo_destroy(cairo_icon); } - int padded_size = icon_size + 2*padding; - *x -= padded_size; - int y = floor((height - padded_size) / 2.0); + double descaled_padding = (double)padding / output->scale; + double descaled_icon_size = (double)icon_size / output->scale; + + int size = descaled_icon_size + 2 * descaled_padding; + *x -= size; + int icon_y = floor((output->height - size) / 2.0); cairo_operator_t op = cairo_get_operator(cairo); cairo_set_operator(cairo, CAIRO_OPERATOR_OVER); - cairo_set_source_surface(cairo, icon, *x + padding, y + padding); - cairo_rectangle(cairo, *x, y, padded_size, padded_size); + + cairo_matrix_t scale_matrix; + cairo_pattern_t *icon_pattern = cairo_pattern_create_for_surface(icon); + // TODO: check cairo_pattern_status for "ENOMEM" + cairo_matrix_init_scale(&scale_matrix, output->scale, output->scale); + cairo_matrix_translate(&scale_matrix, -(*x + descaled_padding), -(icon_y + descaled_padding)); + cairo_pattern_set_matrix(icon_pattern, &scale_matrix); + cairo_set_source(cairo, icon_pattern); + cairo_rectangle(cairo, *x, icon_y, size, size); cairo_fill(cairo); + cairo_set_operator(cairo, op); + cairo_pattern_destroy(icon_pattern); cairo_surface_destroy(icon); struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); hotspot->x = *x; hotspot->y = 0; - hotspot->width = height; - hotspot->height = height; + hotspot->width = size; + hotspot->height = output->height; hotspot->callback = icon_hotspot_callback; hotspot->destroy = free; hotspot->data = strdup(sni->watcher_id); diff -Nru sway-1.6.1/swaybar/tray/tray.c sway-1.7/swaybar/tray/tray.c --- sway-1.6.1/swaybar/tray/tray.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/swaybar/tray/tray.c 2022-01-22 22:55:11.000000000 +0000 @@ -116,8 +116,8 @@ } } // else display on all - if ((int) output->height*output->scale <= 2*config->tray_padding) { - return 2*config->tray_padding + 1; + if ((int)(output->height * output->scale) <= 2 * config->tray_padding) { + return (2 * config->tray_padding + 1) / output->scale; } uint32_t max_height = 0; diff -Nru sway-1.6.1/swaymsg/main.c sway-1.7/swaymsg/main.c --- sway-1.6.1/swaymsg/main.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/swaymsg/main.c 2022-01-22 22:55:11.000000000 +0000 @@ -1,4 +1,6 @@ #define _POSIX_C_SOURCE 200809L + +#include #include #include #include @@ -480,12 +482,20 @@ char *resp = ipc_single_command(socketfd, type, command, &len); // pretty print the json - json_object *obj = json_tokener_parse(resp); - if (obj == NULL) { + json_tokener *tok = json_tokener_new_ex(JSON_MAX_DEPTH); + if (tok == NULL) { + if (quiet) { + exit(EXIT_FAILURE); + } + sway_abort("failed allocating json_tokener"); + } + json_object *obj = json_tokener_parse_ex(tok, resp, -1); + enum json_tokener_error err = json_tokener_get_error(tok); + json_tokener_free(tok); + if (obj == NULL || err != json_tokener_success) { if (!quiet) { - fprintf(stderr, "ERROR: Could not parse json response from ipc. " - "This is a bug in sway."); - printf("%s\n", resp); + sway_log(SWAY_ERROR, "failed to parse payload as json: %s", + json_tokener_error_desc(err)); } ret = 1; } else { @@ -517,13 +527,22 @@ break; } - json_object *obj = json_tokener_parse(reply->payload); - if (obj == NULL) { + json_tokener *tok = json_tokener_new_ex(JSON_MAX_DEPTH); + if (tok == NULL) { + if (quiet) { + exit(EXIT_FAILURE); + } + sway_abort("failed allocating json_tokener"); + } + json_object *obj = json_tokener_parse_ex(tok, reply->payload, -1); + enum json_tokener_error err = json_tokener_get_error(tok); + json_tokener_free(tok); + if (obj == NULL || err != json_tokener_success) { if (!quiet) { - fprintf(stderr, "ERROR: Could not parse json response from" - " ipc. This is a bug in sway."); - ret = 1; + sway_log(SWAY_ERROR, "failed to parse payload as json: %s", + json_tokener_error_desc(err)); } + ret = 1; break; } else if (quiet) { json_object_put(obj); diff -Nru sway-1.6.1/swaymsg/swaymsg.1.scd sway-1.7/swaymsg/swaymsg.1.scd --- sway-1.6.1/swaymsg/swaymsg.1.scd 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/swaymsg/swaymsg.1.scd 2022-01-22 22:55:11.000000000 +0000 @@ -21,12 +21,13 @@ *-p, --pretty* Use pretty output even when not using a tty. + Not available for all message types. *-q, --quiet* Sends the IPC message but does not print the response from sway. *-r, --raw* - Use raw output even if using a tty. + Use raw JSON output even if using a tty. *-s, --socket* Use the specified socket path. Otherwise, swaymsg will ask sway where the @@ -46,6 +47,11 @@ See *sway*(5) for a list of commands. + _swaymsg_ can return pretty printed (standalone-default) or JSON-formatted + (*--raw*) output. For detailed documentation on the returned JSON-data of + each message type listed below, refer to *sway-ipc*(7). The JSON-format can + contain more information than the pretty print. + Tips: - Command expansion is performed twice: once by swaymsg, and again by sway. If you have quoted multi-word strings in your command, enclose the entire @@ -60,20 +66,20 @@ _swaymsg -- mark --add test_ instead of _swaymsg mark --add test_. *get\_workspaces* - Gets a JSON-encoded list of workspaces and their status. + Gets a list of workspaces and their status. *get\_inputs* - Gets a JSON-encoded list of current inputs. + Gets a list of current inputs. *get\_outputs* - Gets a JSON-encoded list of current outputs. + Gets a list of current outputs. *get\_tree* Gets a JSON-encoded layout tree of all open windows, containers, outputs, workspaces, and so on. *get\_seats* - Gets a JSON-encoded list of all seats, + Gets a list of all seats, its properties and all assigned devices. *get\_marks* @@ -83,7 +89,7 @@ Get a JSON-encoded configuration for swaybar. *get\_version* - Get JSON-encoded version information for the running instance of sway. + Get version information for the running instance of sway. *get\_binding\_modes* Gets a JSON-encoded list of currently configured binding modes. @@ -92,7 +98,7 @@ Gets JSON-encoded info about the current binding state. *get\_config* - Gets a JSON-encoded copy of the current configuration. + Gets a copy of the current configuration. Doesn't expand includes. *send\_tick* Sends a tick event to all subscribed clients. diff -Nru sway-1.6.1/swaynag/config.c sway-1.7/swaynag/config.c --- sway-1.6.1/swaynag/config.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/swaynag/config.c 2022-01-22 22:55:11.000000000 +0000 @@ -59,6 +59,7 @@ {"config", required_argument, NULL, 'c'}, {"debug", no_argument, NULL, 'd'}, {"edge", required_argument, NULL, 'e'}, + {"layer", required_argument, NULL, 'y'}, {"font", required_argument, NULL, 'f'}, {"help", no_argument, NULL, 'h'}, {"detailed-message", no_argument, NULL, 'l'}, @@ -104,6 +105,8 @@ " -c, --config Path to config file.\n" " -d, --debug Enable debugging.\n" " -e, --edge top|bottom Set the edge to use.\n" + " -y, --layer overlay|top|bottom|background\n" + " Set the layer to use.\n" " -f, --font Set the font to use.\n" " -h, --help Show help message and quit.\n" " -l, --detailed-message Read a detailed message from stdin.\n" @@ -133,7 +136,7 @@ optind = 1; while (1) { - int c = getopt_long(argc, argv, "b:B:z:Z:c:de:f:hlL:m:o:s:t:v", opts, NULL); + int c = getopt_long(argc, argv, "b:B:z:Z:c:de:y:f:hlL:m:o:s:t:v", opts, NULL); if (c == -1) { break; } @@ -183,6 +186,24 @@ return EXIT_FAILURE; } } + break; + case 'y': // Layer + if (type) { + if (strcmp(optarg, "background") == 0) { + type->layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; + } else if (strcmp(optarg, "bottom") == 0) { + type->layer = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM; + } else if (strcmp(optarg, "top") == 0) { + type->layer = ZWLR_LAYER_SHELL_V1_LAYER_TOP; + } else if (strcmp(optarg, "overlay") == 0) { + type->layer = ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY; + } else { + fprintf(stderr, "Invalid layer: %s\n" + "Usage: --layer overlay|top|bottom|background\n", + optarg); + return EXIT_FAILURE; + } + } break; case 'f': // Font if (type) { diff -Nru sway-1.6.1/swaynag/render.c sway-1.7/swaynag/render.c --- sway-1.6.1/swaynag/render.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/swaynag/render.c 2022-01-22 22:55:11.000000000 +0000 @@ -10,19 +10,19 @@ static uint32_t render_message(cairo_t *cairo, struct swaynag *swaynag) { int text_width, text_height; get_text_size(cairo, swaynag->type->font, &text_width, &text_height, NULL, - swaynag->scale, true, "%s", swaynag->message); + 1, true, "%s", swaynag->message); - int padding = swaynag->type->message_padding * swaynag->scale; + int padding = swaynag->type->message_padding; uint32_t ideal_height = text_height + padding * 2; - uint32_t ideal_surface_height = ideal_height / swaynag->scale; + uint32_t ideal_surface_height = ideal_height; if (swaynag->height < ideal_surface_height) { return ideal_surface_height; } cairo_set_source_u32(cairo, swaynag->type->text); cairo_move_to(cairo, padding, (int)(ideal_height - text_height) / 2); - pango_printf(cairo, swaynag->type->font, swaynag->scale, false, + render_text(cairo, swaynag->type->font, 1, false, "%s", swaynag->message); return ideal_surface_height; @@ -32,10 +32,10 @@ struct swaynag *swaynag, struct swaynag_button *button) { int text_width, text_height; get_text_size(cairo, swaynag->type->font, &text_width, &text_height, NULL, - swaynag->scale, true, "%s", button->text); + 1, true, "%s", button->text); - int border = swaynag->type->button_border_thickness * swaynag->scale; - int padding = swaynag->type->button_padding * swaynag->scale; + int border = swaynag->type->button_border_thickness; + int padding = swaynag->type->button_padding; cairo_set_source_u32(cairo, swaynag->type->details_background); cairo_rectangle(cairo, button->x, button->y, @@ -50,7 +50,7 @@ cairo_set_source_u32(cairo, swaynag->type->button_text); cairo_move_to(cairo, button->x + border + padding, button->y + border + (button->height - text_height) / 2); - pango_printf(cairo, swaynag->type->font, swaynag->scale, true, + render_text(cairo, swaynag->type->font, 1, true, "%s", button->text); } @@ -58,33 +58,33 @@ struct swaynag *swaynag) { int up_width, down_width, temp_height; get_text_size(cairo, swaynag->type->font, &up_width, &temp_height, NULL, - swaynag->scale, true, + 1, true, "%s", swaynag->details.button_up.text); get_text_size(cairo, swaynag->type->font, &down_width, &temp_height, NULL, - swaynag->scale, true, + 1, true, "%s", swaynag->details.button_down.text); int text_width = up_width > down_width ? up_width : down_width; - int border = swaynag->type->button_border_thickness * swaynag->scale; - int padding = swaynag->type->button_padding * swaynag->scale; + int border = swaynag->type->button_border_thickness; + int padding = swaynag->type->button_padding; return text_width + border * 2 + padding * 2; } static uint32_t render_detailed(cairo_t *cairo, struct swaynag *swaynag, uint32_t y) { - uint32_t width = swaynag->width * swaynag->scale; + uint32_t width = swaynag->width; - int border = swaynag->type->details_border_thickness * swaynag->scale; - int padding = swaynag->type->message_padding * swaynag->scale; + int border = swaynag->type->details_border_thickness; + int padding = swaynag->type->message_padding; int decor = padding + border; swaynag->details.x = decor; - swaynag->details.y = y * swaynag->scale + decor; + swaynag->details.y = y + decor; swaynag->details.width = width - decor * 2; PangoLayout *layout = get_pango_layout(cairo, swaynag->type->font, - swaynag->details.message, swaynag->scale, false); + swaynag->details.message, 1, false); pango_layout_set_width(layout, (swaynag->details.width - padding * 2) * PANGO_SCALE); pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); @@ -164,7 +164,7 @@ pango_cairo_show_layout(cairo, layout); g_object_unref(layout); - return ideal_height / swaynag->scale; + return ideal_height; } static uint32_t render_button(cairo_t *cairo, struct swaynag *swaynag, @@ -173,13 +173,13 @@ int text_width, text_height; get_text_size(cairo, swaynag->type->font, &text_width, &text_height, NULL, - swaynag->scale, true, "%s", button->text); + 1, true, "%s", button->text); - int border = swaynag->type->button_border_thickness * swaynag->scale; - int padding = swaynag->type->button_padding * swaynag->scale; + int border = swaynag->type->button_border_thickness; + int padding = swaynag->type->button_padding; uint32_t ideal_height = text_height + padding * 2 + border * 2; - uint32_t ideal_surface_height = ideal_height / swaynag->scale; + uint32_t ideal_surface_height = ideal_height; if (swaynag->height < ideal_surface_height) { return ideal_surface_height; } @@ -201,7 +201,7 @@ cairo_set_source_u32(cairo, swaynag->type->button_text); cairo_move_to(cairo, button->x + padding, button->y + padding); - pango_printf(cairo, swaynag->type->font, swaynag->scale, true, + render_text(cairo, swaynag->type->font, 1, true, "%s", button->text); *x = button->x - border; @@ -220,13 +220,12 @@ max_height = h > max_height ? h : max_height; int x = swaynag->width - swaynag->type->button_margin_right; - x *= swaynag->scale; for (int i = 0; i < swaynag->buttons->length; i++) { h = render_button(cairo, swaynag, i, &x); max_height = h > max_height ? h : max_height; - x -= swaynag->type->button_gap * swaynag->scale; + x -= swaynag->type->button_gap; if (i == 0) { - x -= swaynag->type->button_gap_close * swaynag->scale; + x -= swaynag->type->button_gap_close; } } @@ -235,14 +234,14 @@ max_height = h > max_height ? h : max_height; } - int border = swaynag->type->bar_border_thickness * swaynag->scale; + int border = swaynag->type->bar_border_thickness; if (max_height > swaynag->height) { max_height += border; } cairo_set_source_u32(cairo, swaynag->type->border_bottom); cairo_rectangle(cairo, 0, - swaynag->height * swaynag->scale - border, - swaynag->width * swaynag->scale, + swaynag->height - border, + swaynag->width, border); cairo_fill(cairo); @@ -257,6 +256,7 @@ cairo_surface_t *recorder = cairo_recording_surface_create( CAIRO_CONTENT_COLOR_ALPHA, NULL); cairo_t *cairo = cairo_create(recorder); + cairo_scale(cairo, swaynag->scale, swaynag->scale); cairo_save(cairo); cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); cairo_paint(cairo); diff -Nru sway-1.6.1/swaynag/swaynag.1.scd sway-1.7/swaynag/swaynag.1.scd --- sway-1.6.1/swaynag/swaynag.1.scd 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/swaynag/swaynag.1.scd 2022-01-22 22:55:11.000000000 +0000 @@ -48,6 +48,9 @@ *-e, --edge* top|bottom Set the edge to use. +*-y, --layer* overlay|top|bottom|background + Set the layer to use. + *-f, --font* Set the font to use. diff -Nru sway-1.6.1/swaynag/swaynag.5.scd sway-1.7/swaynag/swaynag.5.scd --- sway-1.6.1/swaynag/swaynag.5.scd 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/swaynag/swaynag.5.scd 2022-01-22 22:55:11.000000000 +0000 @@ -53,7 +53,7 @@ *message-padding=* Set the padding for the message. -*details-gackground=* +*details-background=* The background color for the details. *details-border-size=* @@ -79,6 +79,9 @@ *edge=top|bottom* Set the edge to use. +*layer=overlay|top|bottom|background* + Set the layer to use. + *font=* Set the font to use. diff -Nru sway-1.6.1/swaynag/swaynag.c sway-1.7/swaynag/swaynag.c --- sway-1.6.1/swaynag/swaynag.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/swaynag/swaynag.c 2022-01-22 22:55:11.000000000 +0000 @@ -30,8 +30,8 @@ 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 @@ 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); } } @@ -200,8 +200,8 @@ return; } - double x = seat->pointer.x * swaynag->scale; - double y = seat->pointer.y * swaynag->scale; + double x = seat->pointer.x; + double y = seat->pointer.y; for (int i = 0; i < swaynag->buttons->length; i++) { struct swaynag_button *nagbutton = swaynag->buttons->items[i]; if (x >= nagbutton->x @@ -307,33 +307,25 @@ } } -static const struct wl_output_listener output_listener = { - .geometry = nop, - .mode = nop, - .done = nop, - .scale = output_scale, -}; - -static void xdg_output_handle_name(void *data, - struct zxdg_output_v1 *xdg_output, const char *name) { +static void output_name(void *data, struct wl_output *output, + const char *name) { struct swaynag_output *swaynag_output = data; - char *outname = swaynag_output->swaynag->type->output; - sway_log(SWAY_DEBUG, "Checking against output %s for %s", name, outname); - if (!swaynag_output->swaynag->output && outname && name - && strcmp(outname, name) == 0) { + swaynag_output->name = strdup(name); + + const char *outname = swaynag_output->swaynag->type->output; + if (!swaynag_output->swaynag->output && outname && + strcmp(outname, name) == 0) { sway_log(SWAY_DEBUG, "Using output %s", name); swaynag_output->swaynag->output = swaynag_output; } - swaynag_output->name = strdup(name); - zxdg_output_v1_destroy(xdg_output); - swaynag_output->swaynag->querying_outputs--; } -static const struct zxdg_output_v1_listener xdg_output_listener = { - .logical_position = nop, - .logical_size = nop, +static const struct wl_output_listener output_listener = { + .geometry = nop, + .mode = nop, .done = nop, - .name = xdg_output_handle_name, + .scale = output_scale, + .name = output_name, .description = nop, }; @@ -361,33 +353,21 @@ } else if (strcmp(interface, wl_shm_interface.name) == 0) { swaynag->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); } else if (strcmp(interface, wl_output_interface.name) == 0) { - if (!swaynag->output && swaynag->xdg_output_manager) { - swaynag->querying_outputs++; + if (!swaynag->output) { struct swaynag_output *output = calloc(1, sizeof(struct swaynag_output)); output->wl_output = wl_registry_bind(registry, name, - &wl_output_interface, 3); + &wl_output_interface, 4); output->wl_name = name; output->scale = 1; output->swaynag = swaynag; wl_list_insert(&swaynag->outputs, &output->link); wl_output_add_listener(output->wl_output, &output_listener, output); - - struct zxdg_output_v1 *xdg_output; - xdg_output = zxdg_output_manager_v1_get_xdg_output( - swaynag->xdg_output_manager, output->wl_output); - zxdg_output_v1_add_listener(xdg_output, - &xdg_output_listener, output); } } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { swaynag->layer_shell = wl_registry_bind( registry, name, &zwlr_layer_shell_v1_interface, 1); - } else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0 - && version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) { - swaynag->xdg_output_manager = wl_registry_bind(registry, name, - &zxdg_output_manager_v1_interface, - ZXDG_OUTPUT_V1_NAME_SINCE_VERSION); } } @@ -453,12 +433,11 @@ assert(swaynag->compositor && swaynag->layer_shell && swaynag->shm); - while (swaynag->querying_outputs > 0) { - if (wl_display_roundtrip(swaynag->display) < 0) { - sway_log(SWAY_ERROR, "Error during outputs init."); - swaynag_destroy(swaynag); - exit(EXIT_FAILURE); - } + // Second roundtrip to get wl_output properties + if (wl_display_roundtrip(swaynag->display) < 0) { + sway_log(SWAY_ERROR, "Error during outputs init."); + swaynag_destroy(swaynag); + exit(EXIT_FAILURE); } if (!swaynag->output && swaynag->type->output) { @@ -476,7 +455,8 @@ swaynag->layer_surface = zwlr_layer_shell_v1_get_layer_surface( swaynag->layer_shell, swaynag->surface, swaynag->output ? swaynag->output->wl_output : NULL, - ZWLR_LAYER_SHELL_V1_LAYER_TOP, "swaynag"); + swaynag->type->layer, + "swaynag"); assert(swaynag->layer_surface); zwlr_layer_surface_v1_add_listener(swaynag->layer_surface, &layer_surface_listener, swaynag); diff -Nru sway-1.6.1/swaynag/types.c sway-1.7/swaynag/types.c --- sway-1.6.1/swaynag/types.c 2021-06-24 16:26:29.000000000 +0000 +++ sway-1.7/swaynag/types.c 2022-01-22 22:55:11.000000000 +0000 @@ -26,6 +26,7 @@ type->button_gap_close = -1; type->button_margin_right = -1; type->button_padding = -1; + type->layer = -1; return type; } @@ -35,6 +36,7 @@ type_defaults->anchors = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + type_defaults->layer = ZWLR_LAYER_SHELL_V1_LAYER_TOP; type_defaults->button_background = 0x333333FF; type_defaults->details_background = 0x333333FF; type_defaults->background = 0x323232FF; @@ -100,6 +102,10 @@ dest->anchors = src->anchors; } + if (src->layer >= 0) { + dest->layer = src->layer; + } + // Colors if (src->button_background > 0) { dest->button_background = src->button_background;