commit
4660771f6a
|
@ -21,7 +21,7 @@ packages:
|
|||
- xwayland
|
||||
sources:
|
||||
- https://github.com/swaywm/sway
|
||||
- https://github.com/swaywm/wlroots
|
||||
- https://gitlab.freedesktop.org/wlroots/wlroots.git#0.15.0
|
||||
tasks:
|
||||
- wlroots: |
|
||||
cd wlroots
|
||||
|
|
|
@ -18,7 +18,7 @@ packages:
|
|||
- seatd
|
||||
sources:
|
||||
- https://github.com/swaywm/sway
|
||||
- https://github.com/swaywm/wlroots
|
||||
- https://gitlab.freedesktop.org/wlroots/wlroots.git#0.15.0
|
||||
tasks:
|
||||
- wlroots: |
|
||||
cd wlroots
|
||||
|
|
|
@ -26,7 +26,7 @@ packages:
|
|||
- x11/xcb-util-wm
|
||||
sources:
|
||||
- https://github.com/swaywm/sway
|
||||
- https://github.com/swaywm/wlroots
|
||||
- https://gitlab.freedesktop.org/wlroots/wlroots.git#0.15.0
|
||||
tasks:
|
||||
- setup: |
|
||||
cd sway
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
BasedOnStyle: LLVM
|
||||
IndentWidth: 4
|
||||
TabWidth: 4
|
||||
UseTab: Always
|
||||
BreakBeforeBraces: Attach
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
IndentCaseLabels: false
|
||||
SortIncludes: false
|
||||
ColumnLimit: 80
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
BinPackParameters: true
|
||||
BinPackArguments: true
|
||||
ContinuationIndentWidth: 8
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
ReflowComments: false
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AlignOperands: DontAlign
|
|
@ -15,7 +15,7 @@ Falls du sway für deine eigene Distribution als Paket bereitstellen möchtest,
|
|||
sway benötigt die folgenden Pakete:
|
||||
|
||||
* meson\*
|
||||
* [wlroots](https://github.com/swaywm/wlroots)
|
||||
* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots)
|
||||
* wayland
|
||||
* wayland-protocols\*
|
||||
* pcre
|
||||
|
|
|
@ -70,5 +70,5 @@ support til dem (gdm er kendt for at fungere temmelig godt).
|
|||
[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://github.com/swaywm/wlroots
|
||||
[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots
|
||||
[scdoc]: https://git.sr.ht/~sircmpwn/scdoc
|
||||
|
|
|
@ -25,7 +25,7 @@ escriba un email a sir@cmpwn.com
|
|||
Instale las dependencias:
|
||||
|
||||
* meson \*
|
||||
* [wlroots](https://github.com/swaywm/wlroots)
|
||||
* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots)
|
||||
* wayland
|
||||
* wayland-protocols \*
|
||||
* pcre
|
||||
|
|
|
@ -79,5 +79,5 @@ bien fonctionner).
|
|||
[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
|
||||
|
|
|
@ -69,5 +69,5 @@ _\*Compile-time dep_
|
|||
[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
|
|
@ -73,5 +73,5 @@ gdm-ről ismeretes, hogy egész jól működik.)
|
|||
[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
|
||||
|
|
22
README.ir.md
22
README.ir.md
|
@ -1,9 +1,7 @@
|
|||
<div dir="rtl">
|
||||
|
||||
# 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 sur
|
||||
‏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 به [صفحه
|
||||
|
@ -17,7 +15,7 @@ Patreon با نام کاربری SirCmpwn](https://patreon.com/sircmpwn) مرا
|
|||
|
||||
### از بستههای رسمی
|
||||
|
||||
sway در بستههای رسمی توزیعهای مختلف وجود دارد. بسته «sway» را نصب کنید. در صورتی که بسته رسمی وجود نداشت، برای آگاهی بیشتر درباره نصب روی توزیعتان به این [صفحه راهنما](https://github.com/swaywm/sway/wiki/Unsupported-packages) مراجعه کنید.
|
||||
‏sway در بستههای رسمی توزیعهای مختلف وجود دارد. بسته «sway» را نصب کنید. در صورتی که بسته رسمی وجود نداشت، برای آگاهی بیشتر درباره نصب روی توزیعتان به این [صفحه راهنما](https://github.com/swaywm/sway/wiki/Unsupported-packages) مراجعه کنید.
|
||||
|
||||
اگر به ایجاد بسته sway برای توزیعتان علاقهمند هستید، از کانال IRC استفاده کنید یا به sir@cmpwn.com ایمیل بزنید.
|
||||
|
||||
|
@ -28,7 +26,7 @@ sway در بستههای رسمی توزیعهای مختلف وجود د
|
|||
بستههای مورد نیاز:
|
||||
|
||||
* meson \*
|
||||
* [wlroots](https://github.com/swaywm/wlroots)
|
||||
* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots)
|
||||
* wayland
|
||||
* wayland-protocols \*
|
||||
* pcre
|
||||
|
@ -42,21 +40,16 @@ sway در بستههای رسمی توزیعهای مختلف وجود د
|
|||
_\*نیازمندیهای زمان کامپایل برنامه_
|
||||
|
||||
این فرمانها را اجرا کنید:
|
||||
</div>
|
||||
|
||||
meson build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
|
||||
<div dir="rtl">
|
||||
|
||||
روی سیستمهای بدون logind، باید فرمان زیر را برای suid کردن باینری sway اجرا کنید:
|
||||
</div>
|
||||
|
||||
sudo chmod a+s /usr/local/bin/sway
|
||||
|
||||
<div dir="rtl">
|
||||
sway پس از startup مجوزهای دسترسی root را رها میکند.
|
||||
‏sway پس از startup مجوزهای دسترسی root را رها میکند.
|
||||
|
||||
### شخصی سازی و تنظیمات
|
||||
|
||||
|
@ -64,7 +57,4 @@ sway پس از startup مجوزهای دسترسی root را رها میکن
|
|||
|
||||
## اجرا
|
||||
|
||||
در محیط TTY کافیست `sway` را اجرا کنید. ممکن است ابزارهای مدیریت نمایشگری نیز برای این کار وجود داشته باشند اما از طرف sway پشتیبانی نمیشوند (gdm عملکرد خوبی در این زمینه دارد).
|
||||
|
||||
</div>
|
||||
|
||||
در محیط TTY کافیست `sway` را اجرا کنید. ممکن است ابزارهای مدیریت نمایشگری نیز برای این کار وجود داشته باشند اما از طرف sway پشتیبانی نمیشوند (gdm عملکرد خوبی در این زمینه دارد).
|
||||
|
|
|
@ -27,7 +27,7 @@ Swayは沢山のディストリビューションで提供されています。"
|
|||
次の依存パッケージをインストールしてください:
|
||||
|
||||
* meson \*
|
||||
* [wlroots](https://github.com/swaywm/wlroots)
|
||||
* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots)
|
||||
* wayland
|
||||
* wayland-protocols \*
|
||||
* pcre
|
||||
|
|
|
@ -24,7 +24,7 @@ IRC 채널을 방문하거나 sir@cmpwn.com으로 이메일을 보내 상담 받
|
|||
다음 의존 패키지들을 설치해 주세요:
|
||||
|
||||
* meson \*
|
||||
* [wlroots](https://github.com/swaywm/wlroots)
|
||||
* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots)
|
||||
* wayland
|
||||
* wayland-protocols \*
|
||||
* pcre
|
||||
|
|
|
@ -87,5 +87,5 @@ sway (gdm is known to work fairly well).
|
|||
[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
|
||||
|
|
|
@ -25,7 +25,7 @@ kanaal of stuur een e-mail naar sir@cmpwn.com voor advies.
|
|||
Afhankelijkheden installeren:
|
||||
|
||||
* meson \*
|
||||
* [wlroots](https://github.com/swaywm/wlroots)
|
||||
* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots)
|
||||
* wayland
|
||||
* wayland-protocols \*
|
||||
* pcre
|
||||
|
|
|
@ -25,7 +25,7 @@ adres sir@cmpwn.com w celu uzyskania wskazówek.
|
|||
Zainstaluj zależności:
|
||||
|
||||
* meson \*
|
||||
* [wlroots](https://github.com/swaywm/wlroots)
|
||||
* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots)
|
||||
* wayland
|
||||
* wayland-protocols \*
|
||||
* pcre
|
||||
|
|
|
@ -27,7 +27,7 @@ Verifique [essa página da wiki](https://github.com/swaywm/sway/wiki/Development
|
|||
Instale as dependências:
|
||||
|
||||
* meson \*
|
||||
* [wlroots](https://github.com/swaywm/wlroots)
|
||||
* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots)
|
||||
* wayland
|
||||
* wayland-protocols \*
|
||||
* pcre
|
||||
|
|
|
@ -22,7 +22,7 @@ Dacă sunteți interesați in a crea pachete pentru distribuția voastră, infor
|
|||
Dependențe pentru instalare:
|
||||
|
||||
* meson \*
|
||||
* [wlroots](https://github.com/swaywm/wlroots)
|
||||
* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots)
|
||||
* wayland
|
||||
* wayland-protocols \*
|
||||
* pcre
|
||||
|
|
|
@ -70,5 +70,5 @@ sway (gdm работает довольно неплохо).
|
|||
[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
|
||||
|
|
|
@ -64,5 +64,5 @@ TTY'den `sway` çalıştırın. Bazı görüntü yöneticileriyle(display manag
|
|||
[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
|
||||
|
|
|
@ -36,7 +36,7 @@ Sway доступний у багатьох дистрибутивах Linux (а
|
|||
Встановіть залежності:
|
||||
|
||||
* meson \*
|
||||
* [wlroots](https://github.com/swaywm/wlroots)
|
||||
* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots)
|
||||
* wayland
|
||||
* wayland-protocols \*
|
||||
* pcre
|
||||
|
|
|
@ -25,7 +25,7 @@ Sway 在很多发行版中可用. 尝试在你的发行版中安装 "sway" 包.
|
|||
安装依赖:
|
||||
|
||||
* meson \*
|
||||
* [wlroots](https://github.com/swaywm/wlroots)
|
||||
* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots)
|
||||
* wayland
|
||||
* wayland-protocols \*
|
||||
* pcre
|
||||
|
|
|
@ -25,7 +25,7 @@ Sway 在許多發行版都有提供。請自己嘗試於你的發行版安裝
|
|||
相依套件:
|
||||
|
||||
* meson \*
|
||||
* [wlroots](https://github.com/swaywm/wlroots)
|
||||
* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots)
|
||||
* wayland
|
||||
* wayland-protocols \*
|
||||
* pcre
|
||||
|
|
|
@ -80,6 +80,12 @@ enum movement_unit parse_movement_unit(const char *unit) {
|
|||
|
||||
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) {
|
||||
|
|
|
@ -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 <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
|
|
|
@ -112,6 +112,7 @@ sway_cmd cmd_border;
|
|||
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;
|
||||
|
@ -284,6 +285,7 @@ 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;
|
||||
|
|
|
@ -247,6 +247,12 @@ enum scale_filter_mode {
|
|||
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.
|
||||
*
|
||||
|
@ -266,6 +272,7 @@ struct output_config {
|
|||
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;
|
||||
|
@ -283,6 +290,12 @@ struct side_gaps {
|
|||
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.
|
||||
|
@ -512,7 +525,7 @@ struct sway_config {
|
|||
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 sway_config {
|
|||
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;
|
||||
|
|
|
@ -25,6 +25,8 @@ struct sway_layer_surface {
|
|||
bool mapped;
|
||||
struct wlr_box extent;
|
||||
enum zwlr_layer_shell_v1_layer layer;
|
||||
|
||||
struct wl_list subsurfaces;
|
||||
};
|
||||
|
||||
struct sway_layer_popup {
|
||||
|
@ -44,6 +46,7 @@ struct sway_layer_popup {
|
|||
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;
|
||||
|
|
|
@ -48,7 +48,7 @@ struct sway_output {
|
|||
struct wl_listener damage_frame;
|
||||
|
||||
struct {
|
||||
struct wl_signal destroy;
|
||||
struct wl_signal disable;
|
||||
} events;
|
||||
|
||||
struct timespec last_presentation;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <wayland-server-core.h>
|
||||
#include <wlr/backend.h>
|
||||
#include <wlr/backend/session.h>
|
||||
#include <wlr/render/allocator.h>
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/types/wlr_data_device.h>
|
||||
|
@ -32,13 +33,16 @@ struct sway_server {
|
|||
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;
|
||||
|
@ -137,6 +141,8 @@ void server_fini(struct sway_server *server);
|
|||
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);
|
||||
|
||||
|
|
|
@ -117,12 +117,14 @@ struct sway_container {
|
|||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ struct sway_root {
|
|||
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;
|
||||
|
||||
|
|
|
@ -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_details {
|
|||
|
||||
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;
|
||||
|
|
22
meson.build
22
meson.build
|
@ -1,9 +1,9 @@
|
|||
project(
|
||||
'sway',
|
||||
'c',
|
||||
version: '1.6',
|
||||
version: '1.7',
|
||||
license: 'MIT',
|
||||
meson_version: '>=0.59.0',
|
||||
meson_version: '>=0.60.0',
|
||||
default_options: [
|
||||
'c_std=c11',
|
||||
'warning_level=2',
|
||||
|
@ -37,11 +37,11 @@ endif
|
|||
|
||||
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')
|
||||
|
@ -92,18 +92,10 @@ if get_option('sd-bus-provider') == 'auto'
|
|||
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
|
||||
|
@ -171,8 +163,8 @@ add_project_arguments('-DSYSCONFDIR="/@0@"'.format(join_paths(prefix, sysconfdir
|
|||
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(),
|
||||
|
|
|
@ -15,6 +15,7 @@ protocols = [
|
|||
[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'],
|
||||
|
|
|
@ -51,6 +51,7 @@ static const struct cmd_handler handlers[] = {
|
|||
{ "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 },
|
||||
|
|
|
@ -54,7 +54,7 @@ struct cmd_results *bar_cmd_hidden_state(int argc, char **argv) {
|
|||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -58,7 +58,7 @@ struct cmd_results *bar_cmd_mode(int argc, char **argv) {
|
|||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -18,6 +18,12 @@ static struct cmd_results *handle_command(int argc, char **argv, char *cmd_name,
|
|||
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 @@ struct cmd_results *cmd_client_noop(int argc, char **argv) {
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <signal.h>
|
||||
#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"
|
||||
|
@ -53,6 +54,7 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) {
|
|||
// Fork process
|
||||
if ((pid = fork()) == 0) {
|
||||
// Fork child process again
|
||||
restore_nofile_limit();
|
||||
setsid();
|
||||
sigset_t set;
|
||||
sigemptyset(&set);
|
||||
|
|
|
@ -267,6 +267,11 @@ static struct cmd_results *focus_mode(struct sway_workspace *ws,
|
|||
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 @@ struct cmd_results *cmd_focus(int argc, char **argv) {
|
|||
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);
|
||||
|
|
|
@ -874,6 +874,10 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
|
|||
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);
|
||||
|
|
|
@ -18,6 +18,7 @@ static const struct cmd_handler output_handlers[] = {
|
|||
{ "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 },
|
||||
|
@ -33,9 +34,9 @@ struct cmd_results *cmd_output(int argc, char **argv) {
|
|||
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");
|
||||
}
|
||||
|
@ -52,7 +53,7 @@ struct cmd_results *cmd_output(int argc, char **argv) {
|
|||
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");
|
||||
}
|
||||
|
|
29
sway/commands/output/render_bit_depth.c
Normal file
29
sway/commands/output/render_bit_depth.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include <drm_fourcc.h>
|
||||
#include <strings.h>
|
||||
#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;
|
||||
}
|
||||
|
|
@ -15,7 +15,12 @@ struct cmd_results *cmd_smart_gaps(int argc, char **argv) {
|
|||
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();
|
||||
|
||||
|
|
|
@ -126,10 +126,10 @@ void container_swap(struct sway_container *con1, struct sway_container *con2) {
|
|||
}
|
||||
|
||||
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 @@ struct cmd_results *cmd_swap(int argc, char **argv) {
|
|||
} 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,
|
||||
|
|
|
@ -266,7 +266,7 @@ static void config_defaults(struct sway_config *config) {
|
|||
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;
|
||||
|
@ -290,6 +290,8 @@ static void config_defaults(struct sway_config *config) {
|
|||
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);
|
||||
|
|
|
@ -219,6 +219,8 @@ static void invoke_swaybar(struct bar_config *bar) {
|
|||
sigprocmask(SIG_SETMASK, &set, NULL);
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
|
||||
restore_nofile_limit();
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <assert.h>
|
||||
#include <drm_fourcc.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
|
@ -67,6 +68,7 @@ struct output_config *new_output_config(const char *name) {
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -113,6 +115,9 @@ void merge_output_config(struct output_config *dst, struct output_config *src) {
|
|||
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);
|
||||
|
@ -351,9 +356,26 @@ static int compute_default_scale(struct wlr_output *output) {
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -437,10 +459,26 @@ static void queue_output_config(struct output_config *oc,
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -535,7 +573,7 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) {
|
|||
}
|
||||
|
||||
bool test_output_config(struct output_config *oc, struct sway_output *output) {
|
||||
if (output == root->noop_output) {
|
||||
if (output == root->fallback_output) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -750,6 +788,8 @@ static bool _spawn_swaybg(char **command) {
|
|||
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");
|
||||
|
|
|
@ -352,6 +352,8 @@ static void unmap(struct sway_layer_surface *sway_layer) {
|
|||
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);
|
||||
|
@ -360,6 +362,12 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
|
|||
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);
|
||||
|
@ -428,11 +436,8 @@ static void subsurface_handle_commit(struct wl_listener *listener, void *data) {
|
|||
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);
|
||||
|
@ -440,6 +445,13 @@ static void subsurface_handle_destroy(struct wl_listener *listener,
|
|||
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) {
|
||||
|
@ -451,6 +463,7 @@ static struct sway_layer_subsurface *create_subsurface(
|
|||
|
||||
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);
|
||||
|
@ -624,7 +637,7 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
|
|||
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",
|
||||
|
@ -643,6 +656,8 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
|
|||
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);
|
||||
|
@ -664,7 +679,7 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
|
|||
|
||||
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->pending.layer],
|
||||
&sway_layer->link);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <time.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/backend/drm.h>
|
||||
#include <wlr/backend/headless.h>
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
#include <wlr/types/wlr_buffer.h>
|
||||
#include <wlr/types/wlr_drm_lease_v1.h>
|
||||
|
@ -633,21 +634,19 @@ static void damage_surface_iterator(struct sway_output *output,
|
|||
struct wlr_box box = *_box;
|
||||
scale_box(&box, output->wlr_output->scale);
|
||||
|
||||
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_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_output_damage_add_box(output->damage, &box);
|
||||
|
@ -733,7 +732,7 @@ static void update_output_manager_config(struct sway_server *server) {
|
|||
|
||||
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 =
|
||||
|
@ -755,18 +754,22 @@ static void update_output_manager_config(struct sway_server *server) {
|
|||
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);
|
||||
|
@ -835,9 +838,22 @@ static void handle_present(struct wl_listener *listener, void *data) {
|
|||
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;
|
||||
|
||||
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);
|
||||
|
||||
|
@ -850,6 +866,12 @@ void handle_new_output(struct wl_listener *listener, void *data) {
|
|||
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) {
|
||||
return;
|
||||
|
|
|
@ -52,7 +52,7 @@ static int scale_length(int length, int offset, float scale) {
|
|||
|
||||
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 = {
|
||||
|
@ -100,8 +100,7 @@ static void render_texture(struct wlr_output *wlr_output,
|
|||
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;
|
||||
|
||||
pixman_region32_t damage;
|
||||
|
@ -218,8 +217,7 @@ void render_rect(struct sway_output *output,
|
|||
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));
|
||||
|
@ -764,6 +762,14 @@ static void render_containers_linear(struct sway_output *output,
|
|||
}
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
|
@ -795,6 +801,10 @@ static void render_containers_tabbed(struct sway_output *output,
|
|||
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;
|
||||
|
@ -860,7 +870,11 @@ static void render_containers_stacked(struct sway_output *output,
|
|||
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;
|
||||
|
@ -1013,13 +1027,7 @@ static void render_seatops(struct sway_output *output,
|
|||
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) {
|
||||
|
|
|
@ -402,7 +402,7 @@ static void transaction_commit(struct sway_transaction *transaction) {
|
|||
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,
|
||||
|
|
|
@ -72,8 +72,8 @@ static void popup_unconstrain(struct sway_xdg_popup *popup) {
|
|||
// 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,
|
||||
};
|
||||
|
|
|
@ -436,6 +436,8 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
|
|||
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);
|
||||
|
|
|
@ -83,7 +83,28 @@ static struct wlr_surface *layer_surface_popup_at(struct sway_output *output,
|
|||
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;
|
||||
|
@ -101,19 +122,6 @@ struct sway_node *node_at_coords(
|
|||
}
|
||||
}
|
||||
#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
|
||||
|
@ -131,11 +139,6 @@ struct sway_node *node_at_coords(
|
|||
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) {
|
||||
|
@ -924,6 +927,7 @@ static void handle_pointer_pinch_begin(struct wl_listener *listener, void *data)
|
|||
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);
|
||||
|
@ -933,6 +937,7 @@ static void handle_pointer_pinch_update(struct wl_listener *listener, void *data
|
|||
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,
|
||||
|
@ -943,6 +948,7 @@ static void handle_pointer_pinch_end(struct wl_listener *listener, void *data) {
|
|||
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);
|
||||
|
@ -952,6 +958,7 @@ static void handle_pointer_swipe_begin(struct wl_listener *listener, void *data)
|
|||
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);
|
||||
|
@ -961,6 +968,7 @@ static void handle_pointer_swipe_update(struct wl_listener *listener, void *data
|
|||
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);
|
||||
|
@ -970,6 +978,7 @@ static void handle_pointer_swipe_end(struct wl_listener *listener, void *data) {
|
|||
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);
|
||||
|
|
|
@ -51,6 +51,16 @@ static void seat_device_destroy(struct sway_seat_device *seat_device) {
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -1415,9 +1425,8 @@ struct sway_node *seat_get_focus(struct sway_seat *seat) {
|
|||
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;
|
||||
|
|
|
@ -80,17 +80,25 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) {
|
|||
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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -687,7 +687,7 @@ void ipc_client_handle_command(struct ipc_client *client, uint32_t payload_lengt
|
|||
}
|
||||
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));
|
||||
}
|
||||
|
|
40
sway/main.c
40
sway/main.c
|
@ -6,6 +6,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
@ -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};
|
||||
|
||||
|
@ -63,7 +65,7 @@ void detect_proprietary(int allow_unsupported_gpu) {
|
|||
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;
|
||||
|
@ -151,6 +153,9 @@ static void log_kernel(void) {
|
|||
|
||||
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");
|
||||
|
@ -169,6 +174,33 @@ static bool drop_permissions(void) {
|
|||
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;
|
||||
|
@ -220,7 +252,6 @@ int main(int argc, char **argv) {
|
|||
{"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}
|
||||
};
|
||||
|
||||
|
@ -314,7 +345,6 @@ int main(int argc, char **argv) {
|
|||
log_kernel();
|
||||
log_distro();
|
||||
log_env();
|
||||
detect_proprietary(allow_unsupported_gpu);
|
||||
|
||||
if (optind < argc) { // Behave as IPC client
|
||||
if (optind != 1) {
|
||||
|
@ -341,6 +371,8 @@ int main(int argc, char **argv) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
detect_proprietary(allow_unsupported_gpu);
|
||||
|
||||
if (!server_privileged_prepare(&server)) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -350,6 +382,8 @@ int main(int argc, char **argv) {
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
increase_nofile_limit();
|
||||
|
||||
// handle SIGTERM signals
|
||||
signal(SIGTERM, sig_handler);
|
||||
signal(SIGINT, sig_handler);
|
||||
|
|
|
@ -188,6 +188,7 @@ sway_sources = files(
|
|||
'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',
|
||||
|
|
|
@ -7,17 +7,18 @@
|
|||
#include <wlr/backend.h>
|
||||
#include <wlr/backend/headless.h>
|
||||
#include <wlr/backend/multi.h>
|
||||
#include <wlr/backend/noop.h>
|
||||
#include <wlr/backend/session.h>
|
||||
#include <wlr/config.h>
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/types/wlr_data_control_v1.h>
|
||||
#include <wlr/types/wlr_drm_lease_v1.h>
|
||||
#include <wlr/types/wlr_drm.h>
|
||||
#include <wlr/types/wlr_export_dmabuf_v1.h>
|
||||
#include <wlr/types/wlr_gamma_control_v1.h>
|
||||
#include <wlr/types/wlr_idle.h>
|
||||
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||
#include <wlr/types/wlr_linux_dmabuf_v1.h>
|
||||
#include <wlr/types/wlr_pointer_constraints_v1.h>
|
||||
#include <wlr/types/wlr_primary_selection_v1.h>
|
||||
#include <wlr/types/wlr_relative_pointer_v1.h>
|
||||
|
@ -73,12 +74,29 @@ static void handle_drm_lease_request(struct wl_listener *listener, void *data) {
|
|||
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_display(renderer, server->wl_display);
|
||||
wlr_renderer_init_wl_shm(server->renderer, server->wl_display);
|
||||
|
||||
server->compositor = wlr_compositor_create(server->wl_display, renderer);
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
server->renderer);
|
||||
server->compositor_new_surface.notify = handle_compositor_new_surface;
|
||||
wl_signal_add(&server->compositor->events.new_surface,
|
||||
&server->compositor_new_surface);
|
||||
|
@ -206,20 +224,20 @@ bool server_init(struct sway_server *server) {
|
|||
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;
|
||||
|
@ -276,6 +294,7 @@ bool server_start(struct sway_server *server) {
|
|||
wlr_backend_destroy(server->backend);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -157,6 +157,21 @@ must be separated by one space. For example:
|
|||
adaptive sync can improve latency, but can cause flickering on some
|
||||
hardware.
|
||||
|
||||
*output* <name> 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)
|
||||
|
|
|
@ -499,6 +499,12 @@ runtime.
|
|||
*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).
|
||||
|
||||
|
@ -554,6 +560,12 @@ The default colors are:
|
|||
: #ffffff
|
||||
: #484e50
|
||||
: #5f676a
|
||||
| *focused_tab_title*
|
||||
: #333333
|
||||
: #5f676a
|
||||
: #ffffff
|
||||
: n/a
|
||||
: n/a
|
||||
| *unfocused*
|
||||
: #333333
|
||||
: #222222
|
||||
|
@ -692,9 +704,10 @@ The default colors are:
|
|||
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] <identifier>
|
||||
Marks are arbitrary labels that can be used to identify certain windows and
|
||||
|
|
|
@ -64,6 +64,8 @@ bool swaynag_spawn(const char *swaynag_command,
|
|||
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");
|
||||
|
|
|
@ -5,8 +5,12 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <sys/stat.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/types/wlr_linux_dmabuf_v1.h>
|
||||
#include <wlr/types/wlr_output_layout.h>
|
||||
#include <wlr/render/drm_format_set.h>
|
||||
#include "linux-dmabuf-unstable-v1-protocol.h"
|
||||
#include "cairo_util.h"
|
||||
#include "pango.h"
|
||||
#include "sway/config.h"
|
||||
|
@ -64,6 +68,7 @@ void container_destroy(struct sway_container *con) {
|
|||
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);
|
||||
|
@ -73,11 +78,10 @@ void container_destroy(struct sway_container *con) {
|
|||
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);
|
||||
}
|
||||
|
@ -382,19 +386,17 @@ struct sway_container *tiling_container_at(struct sway_node *parent,
|
|||
}
|
||||
|
||||
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;
|
||||
while (!wlr_surface_is_xdg_surface(surface)) {
|
||||
if (!wlr_surface_is_subsurface(surface)) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
struct wlr_subsurface *subsurface =
|
||||
wlr_subsurface_from_wlr_surface(surface);
|
||||
surface = subsurface->parent;
|
||||
}
|
||||
|
||||
return false;
|
||||
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,
|
||||
|
@ -532,6 +534,13 @@ static void render_titlebar_text_texture(struct sway_output *output,
|
|||
|
||||
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);
|
||||
|
@ -549,8 +558,7 @@ static void render_titlebar_text_texture(struct sway_output *output,
|
|||
cairo_surface_flush(surface);
|
||||
unsigned char *data = cairo_image_surface_get_data(surface);
|
||||
int stride = cairo_image_surface_get_stride(surface);
|
||||
struct wlr_renderer *renderer = wlr_backend_get_renderer(
|
||||
output->wlr_output->backend);
|
||||
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);
|
||||
|
@ -585,6 +593,8 @@ void container_update_title_textures(struct sway_container *container) {
|
|||
&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);
|
||||
}
|
||||
|
||||
|
@ -1050,6 +1060,16 @@ void container_end_mouse_operation(struct sway_container *container) {
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -1061,6 +1081,75 @@ static void set_fullscreen(struct sway_container *con, bool 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) {
|
||||
|
@ -1638,6 +1727,8 @@ void container_update_marks_textures(struct sway_container *con) {
|
|||
&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);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,8 +56,8 @@ static void restore_workspaces(struct sway_output *output) {
|
|||
}
|
||||
|
||||
// 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 @@ struct sway_output *output_create(struct wlr_output *wlr_output) {
|
|||
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 @@ static void output_evacuate(struct sway_output *output) {
|
|||
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 @@ void output_disable(struct sway_output *output) {
|
|||
}
|
||||
|
||||
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 @@ void output_begin_destroy(struct sway_output *output) {
|
|||
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) {
|
||||
|
|
|
@ -374,8 +374,8 @@ void root_for_each_container(void (*f)(struct sway_container *con, void *data),
|
|||
}
|
||||
|
||||
// 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 @@ struct sway_container *root_find_container(
|
|||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
|
|
@ -752,10 +752,29 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
|
|||
}
|
||||
|
||||
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);
|
||||
|
@ -776,13 +795,6 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
|
|||
&view->foreign_minimize);
|
||||
|
||||
|
||||
// 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);
|
||||
|
@ -1129,9 +1141,12 @@ void view_child_init(struct sway_view_child *child,
|
|||
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);
|
||||
|
|
|
@ -50,8 +50,8 @@ struct sway_output *workspace_get_initial_output(const char *name) {
|
|||
} 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,
|
||||
|
@ -844,24 +844,36 @@ struct sway_container *workspace_insert_tiling(struct sway_workspace *workspace,
|
|||
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);
|
||||
|
|
|
@ -54,7 +54,6 @@ static void swaybar_output_free(struct swaybar_output *output) {
|
|||
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 @@ bool determine_bar_visibility(struct swaybar *bar, bool moving_layer) {
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -550,7 +550,7 @@ bool handle_ipc_readable(struct swaybar *bar) {
|
|||
// 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);
|
||||
|
|
|
@ -117,11 +117,11 @@ bool status_handle_readable(struct status_line *status) {
|
|||
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 @@ struct status_line *status_line_init(char *cmd) {
|
|||
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 @@ struct status_line *status_line_init(char *cmd) {
|
|||
|
||||
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;
|
||||
|
|
|
@ -493,24 +493,36 @@ uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x,
|
|||
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);
|
||||
|
|
|
@ -116,8 +116,8 @@ uint32_t render_tray(cairo_t *cairo, struct swaybar_output *output, double *x) {
|
|||
}
|
||||
} // 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;
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -480,12 +482,20 @@ int main(int argc, char **argv) {
|
|||
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 @@ int main(int argc, char **argv) {
|
|||
break;
|
||||
}
|
||||
|
||||
json_object *obj = json_tokener_parse(reply->payload);
|
||||
if (obj == NULL) {
|
||||
if (!quiet) {
|
||||
fprintf(stderr, "ERROR: Could not parse json response from"
|
||||
" ipc. This is a bug in sway.");
|
||||
ret = 1;
|
||||
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) {
|
||||
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);
|
||||
|
|
|
@ -307,33 +307,25 @@ static void output_scale(void *data, struct wl_output *output,
|
|||
}
|
||||
}
|
||||
|
||||
static void output_name(void *data, struct wl_output *output,
|
||||
const char *name) {
|
||||
struct swaynag_output *swaynag_output = data;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
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,
|
||||
.done = nop,
|
||||
.name = xdg_output_handle_name,
|
||||
.name = output_name,
|
||||
.description = nop,
|
||||
};
|
||||
|
||||
|
@ -361,33 +353,21 @@ static void handle_global(void *data, struct wl_registry *registry,
|
|||
} 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 @@ void swaynag_setup(struct swaynag *swaynag) {
|
|||
|
||||
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) {
|
||||
|
|
Loading…
Reference in a new issue