Compare commits

...

75 commits

Author SHA1 Message Date
llyyr
055be4ec35 sway/server: advertise gamma2.2 and bt1886 transfer functions 2025-10-28 23:34:18 +01:00
bonsaiiV
b7eb6177e1
sway/commands/layout: fix flatten parent once
Fixes: f50e307227 ("sway/commands/layout: flatten parent once")
2025-10-18 18:55:46 +02:00
llyyr
90d3270970 sway/input/cursor: send frame event when simulating pointer from tablet 2025-10-05 19:46:53 +02:00
Louis POIROT--HATTERMANN
ecfea6b8ae commands/scratchpad: don't hide scratchpad if no pending workspace
Fixes: https://github.com/swaywm/sway/issues/8909
2025-10-05 19:22:48 +02:00
nyxed
b4a9a1716f build: switch to explicit 'meson setup' syntax 2025-10-02 18:06:20 +02:00
llyyr
d9e615c507 sway/server: set color_manager for root scene
Chase https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5122/
2025-09-23 23:50:15 +02:00
Felix Pehla
bc96d0acdf README: update German translation
Update the information about display manager support (see #8861), as
well as markdown formatting of links and change some wording in the
German README.
2025-09-18 11:18:07 +02:00
Simon Ser
a7d9535eb3 input/text_input: stop using listener data
These are now NULL.

Fixes: aaab7f961e ("input/text_input: chase wlroots update")
Closes: https://github.com/swaywm/sway/issues/8864
References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5107
2025-09-15 07:41:51 +02:00
nortio
7c1e192ea3
Update README.it.md for Italian
Updated italian readme to follow the recent changes to the English one.
I also removed "gestore di accesso" which in theory translates to
display manager, but in practice is never used in this context. Other
wikis such as [Debian](https://wiki.debian.org/it/DisplayManager) and
[Ubuntu](https://wiki.ubuntu-it.org/AmbienteGrafico/DisplayManager) just
use the term "Display Manager" as is. Another small thing that I
corrected is "canale di IRC" which sounds a bit weird.
2025-09-14 19:38:17 +02:00
aceydot
50a8750e01
Add Serbian README 2025-09-12 19:55:36 +02:00
Martin Dørum
a41b25020d
Update Norwegian README to make it more in line with the English one, as well as improving grammar 2025-09-12 15:43:30 +02:00
Kirill Chibisov
35b69158d7 readme: sync Japanese translation 2025-09-12 15:28:31 +02:00
Kirill Chibisov
862e9b8c20 readme: sync Russian translation 2025-09-12 15:28:31 +02:00
Oto Šťáva
68ac52ffc2 readme: Update and reword Czech translation 2025-09-11 23:48:16 +02:00
Przemysław Gasiński
e6fc3ffa3f readme: Update Polish translation regarding the support of display managers 2025-09-11 23:46:57 +02:00
Martin Dørum
70c51c44f6 update danish readme to reflect that display managers are supported 2025-09-11 17:20:07 +02:00
Simon Ser
ca45c22376 readme: mark display managers as supported
It's been a long while since we've heard about issues related to
display managers. Some used to be unreliable in the past, but by
now most issues have been ironed out. Let's start supporting them
officially.

I've considered translating other languages but I'm concerned about
messing up the sentence. I've updated languages I'm comfortable
with.
2025-09-11 14:14:51 +00:00
Nikola Kocic
c5456be750 xdg-shell: fix reported WM capabilities
Previously it was reporting window_menu and maximize instead of fullscreen because wlr_xdg_toplevel_set_wm_capabilities expects a bitmask (WLR_XDG_TOPLEVEL_WM_CAPABILITIES_*), and XDG_TOPLEVEL_WM_CAPABILITIES_* are supposed to be used as values in wl_array, so the values are different:
XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN = 3
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN = 4
2025-09-09 13:55:46 +02:00
Bill Li
aaab7f961e input/text_input: chase wlroots update
References:https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5107
2025-09-08 15:54:59 +00:00
Kenny Levinsen
73c244fb48 config/output: Only error when enabling HDR
We currently emit errors about HDR support even if HDR is not being
requested, which mean errors on every regular modeset when monitors not
supporting HDR are connected.

Only emit errors when attempting to enable HDR on such device.
2025-08-22 15:49:09 +02:00
Simon Ser
b3dcde8d69 Stop generating wayland-protocols server headers
We still need to generate wlr-protocols server headers, as well as
client headers and code.

References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5075
2025-08-14 10:09:59 +02:00
Joaquim Monteiro
0770a8d643 Add wl_fixes interface 2025-08-13 22:58:21 +02:00
Tim Hallmann
340505bb6f commands/resize: make resize consider all siblings
Fixes a compatibility issue with i3 where resizing works as described
hereafter:
> Direction can either be one of up, down, left or right. Or you can be
> less specific and use width or height, in which case i3 will take/give
> space from all the other containers.

Sway previously considered only the direct neighbours, not all siblings.

Fixes #5936
2025-08-03 20:15:39 +02:00
bonsaiiV
f50e307227
sway/commands/layout: flatten parent once
Applying layout changes to the parent of the parent, in case the parent only has a single child, stops the creation of a chain of single child containers.

Closes: https://github.com/swaywm/sway/issues/7945
2025-08-03 15:25:40 +02:00
Tomasz Buczyński
87fbcf0574 Add cursor->hidden check to handle_rebase
Fixes #6245
2025-08-03 15:01:21 +02:00
Kenny Levinsen
357d341f8f tree/node: Do not mark destroying nodes as dirty
Node destruction currently runs through the transaction system such that
a particular node is only destroyed after its use in an ongoing
transaction. If a node is dirtied after the node is marked as destroying
but before it is destroyed, the pointer added to dirty_nodes would
become a dangling pointer once the node was destroyed.

Do not dirty destroying nodes, and ensure that destroying is only set
after the last dirty.
2025-07-31 15:57:28 +02:00
Simon Ser
14fbe9242f Revert drag_lock default to disabled
I misunderstood the recommendation in the libinput release notes.
Instead of making enabled_sticky the default, leave the default
set to disabled.

Fixes: bbadf9b8b1 ("Add support for LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY")
Closes: https://github.com/swaywm/sway/issues/8758
2025-07-29 09:41:19 +02:00
Fenveireth
e50b16a699 tree/view: save new wlr_scene_buffer fields
Visble flicker can occur during transactions, if these are not copied
to the 'saved' scene
2025-07-20 15:16:03 +02:00
Simon Ser
cb33701f5e Add xdg_toplevel tag to criteria 2025-07-16 10:03:09 +02:00
Simon Ser
08142c3f3a Add xdg_toplevel tag to IPC 2025-07-16 10:03:09 +02:00
Simon Ser
3826535ab0 Wire up xdg-toplevel-tag-v1 2025-07-16 10:03:09 +02:00
Nuran Askarov
f57c82a6f7 Add link to README.az.md 2025-07-09 16:57:14 +02:00
Nuran Askarov
8d7c756276 Add README.az.md 2025-07-09 16:57:14 +02:00
Simon Ser
94c819cc1f Add features.hdr to output IPC response 2025-07-09 01:25:11 +02:00
Simon Ser
6fed1f9d89 Add support for color-management-v1
References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4962
2025-07-09 01:25:11 +02:00
Simon Ser
bac8c0f4d0 Add support for HDR10 output 2025-07-09 01:25:11 +02:00
Simon Ser
c7d7d56f61 ipc-json, swaymsg: indicate when adaptive sync is unsupported 2025-07-08 15:58:53 +02:00
Simon Ser
a1ac2a2e93 Drop sway_output.events.disable
In general wl_signal isn't well-suited for Sway: Sway doesn't need
any modularity, and signals make it trickier to track down exactly
what happens down the stack.

Replace Sway's output disable signal with a simple list tracking
for the only user.
2025-07-02 21:21:53 +02:00
Kenny Levinsen
56f2db062d Revert "sway/tree: Simplify sway_node teardown"
This reverts commit e28e6484e8.

This change tried to remove nodes from all points of reference to allow
immediate destruction. However, it missed things like the children lists
cloned by transaction states of parent nodes.

Adding all that extra cleanup would not be in the spirit of a PR
claiming to simplify teardown. Let's wait for someone to come up with a
cleaner approach instead.

Fixes: https://github.com/swaywm/sway/pull/8738
2025-06-28 11:26:49 +02:00
Kenny Levinsen
0cd45d4ad2 Revert "tree/container: Remove child from all lists"
This reverts commit 3d6b9a2848.
2025-06-28 11:26:49 +02:00
Kenny Levinsen
3d6b9a2848 tree/container: Remove child from all lists
When a container is detached, we need to remove it from any lists it may
be part of. We use container_get_siblings to obtain the relevant list,
find our entry and remove it.

If the container is in a later list than the one returned by
container_get_siblings, or is in multiple lists for some reason,
container_detach will fail to remove the container, leaving a dangling
pointer when the container is freed.

Instead of calling container_get_siblings, check and remove the
container from all lists.
2025-06-26 22:05:05 +02:00
Kenny Levinsen
e28e6484e8 sway/tree: Simplify sway_node teardown
A sway_node may end up being referenced in either a queued transaction,
pending transaction or as a dirty node. To manage this, the transaction
system has been responsible for destroying containers, workspaces and
outputs at the end of their last referenced transaction.

This significantly complicates the teardown flow of surfaces and
outputs. Instead, remove the node from transactions and dirty lists so
that the callsite can remove and free the node immediately.
2025-06-26 22:05:05 +02:00
Kenny Levinsen
4f59eeef05 Remove the temporary SUID warning
A temporary SUID detection that would cause sway to exit was introduced
when SUID operation was deprecated, intended to avoid cases where a user
would not heed the deprecation notice, continued to use SUID and ended
up with sway accidentally running as root.

Remove the check, as the three years that have passed is sufficient time
for users to discover the deprecation and adapt. We did not care if
users intentionally want to run sway as root through SUID, we only
wanted to avoid surprise root.
2025-06-26 22:00:05 +02:00
Simon Ser
c2f08075ec tree/view: send event unconditionally in view_send_frame_done()
Previously, we were using wl_signal_emit_mutable() directly instead
of wlr_scene_buffer_send_frame_done(). This bypassed any visibility
checks, which matters before a surface is mapped.

Fixes flickering with an invalid size when launching new programs.

Fixes: eb8acfd7b1 ("Stop using wlr_scene_buffer_send_frame_done()")
2025-06-23 10:32:31 +02:00
Simon Ser
170c9c9525 Add support for toplevel capture
References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5078
2025-06-16 14:28:20 +02:00
Simon Ser
eb8acfd7b1 Stop using wlr_scene_buffer_send_frame_done()
That function now takes the output as input. We don't always have
the output at hand, so use the function operating on a
wlr_scene_surface instead.
2025-06-16 14:28:20 +02:00
hwsmm
25ea1a0af2 seatop_default: Call seatop_rebase with proper timestamp 2025-06-16 11:26:26 +02:00
hwsmm
4b15b3427f Rename get_current_time_msec to get_current_time_in_msec and move to util.c
get_current_time_msec conflicts with a function with the same name in wlroots.
2025-06-16 11:26:26 +02:00
Simon Ser
17f7c1b782 build: set wrap_mode=nodownload in default options
This can be surprising (e.g. in CI, this can download source code
instead of using system libraries) and users can easily turn it
back on if desired.
2025-06-16 09:31:15 +02:00
Attila Fidan
6c27c2cdf2 text_input: Don't relay IM state from unfocused windows
Otherwise, applications can enable their text input and affect IM state
while a different application is focused.
2025-06-14 09:19:17 +02:00
Attila Fidan
1ab573bf54 text_input: Ignore enable requests from unfocused windows
Unfocused windows shouldn't be allowed to activate the IM.

This fixes an issue with swaymsg invocations that contain several
commands which result in multiple swift focus changes. An application
briefly gets text input focus, sends an enable request, then sway
processes it and activates the IM only after the commands are all
finished and focus is on something else which did not send an enable
request.
2025-06-14 09:19:17 +02:00
Simon Ser
0a740a24d9 build: bump version to 1.12-dev 2025-06-09 16:27:18 +02:00
Callum Andrew
3d401d9390 config.in: bind XF86Audio* keycodes to playerctl 2025-06-09 15:56:41 +02:00
Simon Ser
6816b51c86 Remove trailing spaces 2025-06-05 18:15:56 +02:00
YaoBing Xiao
9fb9e9f7d5 server: fix socket path memory leak
The socket path allocated with strdup() in server_init() was
not being freed in server_fini().
Remove const qualifier and add proper cleanup.
2025-06-05 09:59:46 +02:00
Konstantin Pospelov
7e7994dbb2 swaybar: deduplicate mode and workspace rendering code
The render_workspace_button and render_binding_mode_indicator functions are
almost the same. This commit extracts the common rendering code into a new
render_box function.
2025-05-25 14:48:14 +02:00
Simon Ser
63689bfb83 Log message on for_window command error 2025-05-25 13:59:34 +02:00
Bonsaiiv
45267bb576 Improve example of input section in default config
Previous example included a specific device name. This can be confusing
for beginners, as the default did not work on most devices.
2025-05-24 16:29:03 +02:00
Kenny Levinsen
534491d3aa tree/workspace: Remove exclude arg from get_highest_available
workspace_output_get_highest_available took an output to exclude as
argument, meant to avoid accidentally reselecting an output we are
evacuating workspaces from.

Outputs are now removed from the list before we evacuate, making
exclusion unnecessary. Remove the argument.
2025-05-22 17:12:51 +02:00
Kenny Levinsen
005924f260 output: Minimize interaction with output after destroy
When an output is destroyed, we go through the process of disabling it.
This includes evacuating all content away from the output, which can
lead to various modifications to the scene. With the scene_output still
present, this can lead to things like output_enter events being emitted
for the output currently being destroyed.

Ensure that the scene output is destroyed first and that the output is
immediately considered disabled.

References: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3974
2025-05-22 17:12:51 +02:00
alex-huff
88c7b4a7eb transaction: fix floating fullscreen containers
8fecf3a introduced a regression where fullscreening a child of a
floating container would result in a black screen. This is because the
order of 'arrange_fullscreen' and 'arrange_worksplace_floating' was
swapped causing the fullscreen container's scene to get reparented after
it was parented in the fullscreen layer.

Fixes #8729
2025-05-21 21:38:27 -04:00
alex-huff
1b47277962 layer-shell: reclaim space from unmapped layer surfaces
wlroots resets 'initialized' when a layer surface is unmapped and sway
doesn't rearrange the layer surfaces in response to a commit of a
surface where 'initialized' is false. This results in space not getting
reclaimed from a recently unmapped layer surface until some other action
causes 'arrange_layers' to get called. This commit makes sure all layer
surfaces get rearranged when a layer surface is unmapped.
2025-05-21 20:33:27 -04:00
Simon Ser
5cfcd1c7c2 input: fix udev_device leak
libinput_device_get_udev_device() returns a ref'ed handle:
https://wayland.freedesktop.org/libinput/doc/latest/api/group__device.html#gac13c64ba19fc19094cff0e5354a2a7ce

Similar to this wlroots MR:
https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5074
2025-05-20 17:54:44 +02:00
alex-huff
8fecf3aa8c transaction: reparent scenes of containers behind fullscreen containers
Currently we do a good job of reparenting the scenes of a container when
it moves into a disabled workspace. We need to do this since normally
the scenes are reparented in the 'arrange_{children,container}'
functions but these don't get called for disabled workspaces. However,
the 'arrange_{children,container}' functions also don't get called when
there is a fullscreen container hiding them.

This commit makes sure to call 'disable_workspace' on workspaces with a
fullscreen container so that when a container is moved into the
workspace its scenes will be properly reparented. Also, when there is a
fullscreen global container 'disable_workspace' is called for all
workspaces since the scenes of a previously fullscreen global container
may still be parented in the 'fullscreen_global' layer.
Fixes #8705 #8659 #8432
2025-05-19 18:46:09 -04:00
alex-huff
fb6d61b58f transaction: fix size of child container decorations in stacking layouts
Before this commit stacking containers with more than one child sized
the active container's decorations as if there was only one titlebar.
Commit a25645a introduced the local variable 'net_height' but
incorrectly calculated it for stacking containers. Fixes #8686.
2025-05-19 12:29:09 +02:00
odyxz
810142dcc4 raise scratchpad container 2025-05-18 23:52:08 +02:00
alex-huff
a4072486de transaction: ensure border scene is enabled for floating containers
When a container that was previously an inactive child of a tabbed or
stacking layout becomes floating it's border scene-tree remains
disabled. This results in only the titlebar being rendered for the
container. This commit ensures the border scene-tree is enabled when
arranging floating containers.
Fixes #8721
2025-05-18 17:00:39 +02:00
Bill Li
652019d6da input/text_input: chase wlroots update
References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5032

Fix #8718
2025-05-15 16:31:34 +02:00
GreyXor
3fbff5b4bb build: bump wlroots version 2025-05-15 11:53:32 +02:00
alex-huff
8d3a52aa30 move: fix broken titlebar when moving child to new workspace
Before this commit, when moving a non-leaf child of a tabbed or stacking
container to a new workspace, the child would be detached from the
parent container and the grandchildren would be sent to the new
workspace but the child itself wouldn't be destroyed causing the
titlebar to still be rendered as part of the parent container.
Fixes #8648.
2025-05-08 19:20:35 +02:00
Furkan Sahin
6021f4d83f input/seatop_down: Update decorations for touchscreen inputs
fixes #8675
2025-05-06 11:22:41 +02:00
alex-huff
4ab411cab0 transaction: Ensure all tabs are visible in tabbed mode
Before this commit when a child of a tabbed or stacking container was
taken out of fullscreen and a different sibling was focused in the same
transaction, the titlebar of the previously fullscreen container would
remain hidden. This commit makes sure that scene tree for decorations is
enabled for all containers within a tabbed or stacking container when it
is arranged.
2025-05-04 18:55:57 -04:00
Kenny Levinsen
f9945d81fb config/output: Fix missing output config supersedes
color_transform and allow_tearing was not handled by
supersede_output_config which could lead to configuration being
incorrectly applied.
2025-05-01 13:08:36 +02:00
Kenny Levinsen
8ac1f72c9e config/output: Use INT_MAX as x/y unset value
We oftne use -1 to indicate unset values. In case of output (x, y), we
would consider the fields set if they are not both -1. This means that
(0, -1) and (-1, 0) are valid coordinates, but (-1, -1) is not.

We support negative output positioning, so we cannot use -1 to mean
unset. Zero is also not an option as that would disallow reverting a set
position back to (0, 0).

INT_MAX is an unreasonable output position, so use it to indicate unset
values, and only use the value when both are set.
2025-05-01 00:00:50 +02:00
Pavel 'LEdoian' Turinsky
6cac61b6b9 Fix includes with relative paths
The function `load_include_configs` already changes the directory to the
one containing the parent config. Therefore, `load_include_config`
trying to assemble the "full" path leads to repetition of path segments,
making the `realpath` call fail with ENOENT.

Just calling `realpath` on the path itself from the directory with the
parent configuration is sufficient, so there is no point in passing
`parent_dir` to `load_include_config`.
2025-04-28 23:34:23 +02:00
81 changed files with 903 additions and 476 deletions

View file

@ -29,12 +29,12 @@ sources:
tasks:
- wlroots: |
cd wlroots
meson --prefix=/usr build -Dexamples=false
meson setup --prefix=/usr build -Dexamples=false
ninja -C build
sudo ninja -C build install
- setup: |
cd sway
meson build --fatal-meson-warnings -Dauto_features=enabled -Dtray=disabled
meson setup build --fatal-meson-warnings -Dauto_features=enabled -Dtray=disabled
- build: |
cd sway
ninja -C build
@ -52,5 +52,5 @@ tasks:
mkdir subprojects
ln -s ../../wlroots subprojects/wlroots
rm -rf build
meson build --fatal-meson-warnings --default-library=static --force-fallback-for=wlroots
meson setup build --fatal-meson-warnings --default-library=static --force-fallback-for=wlroots
ninja -C build

View file

@ -26,12 +26,12 @@ sources:
tasks:
- wlroots: |
cd wlroots
meson --prefix=/usr build -Dexamples=false
meson setup --prefix=/usr build -Dexamples=false
ninja -C build
sudo ninja -C build install
- setup: |
cd sway
meson build --fatal-meson-warnings -Dauto_features=enabled -Dsd-bus-provider=libsystemd
meson setup build --fatal-meson-warnings -Dauto_features=enabled -Dsd-bus-provider=libsystemd
- build: |
cd sway
ninja -C build

View file

@ -39,7 +39,7 @@ tasks:
cd subprojects
ln -s ../../wlroots wlroots
cd ..
meson build --fatal-meson-warnings -Dtray=enabled -Dsd-bus-provider=basu
meson setup build --fatal-meson-warnings -Dtray=enabled -Dsd-bus-provider=basu
- build: |
cd sway
ninja -C build

View file

@ -37,7 +37,7 @@ _\* Compile-time dep_
نفذ هذه الأوامر:
meson build/
meson setup build/
ninja -C build/
sudo ninja -C build/ install

66
README.az.md Normal file
View file

@ -0,0 +1,66 @@
# sway
sway [i3]-ə uyğun [Wayland] kompozitorudur. [Tez-tez verilən sualları] oxuyun.
[IRC kanalına] qoşulun ("irc.libera.chat"-da #sway).
## Buraxılış İmzaları
Buraxılışlar [E88F5E48] ilə imzalanıb və [GitHub-da][GitHub releases] dərc edilib.
## Quraşdırma
### Paketlərdən
Sway bir çox distributivdə mövcuddur. Öz distributiviniz üçün
"sway" paketini quraşdırmağa çalışın.
### Mənbə kodundan kompilyasiya
Test və ya inkişaf üçün sway və wlroots-un HEAD-ini qurmaq istəyirsinizsə,
[bu viki səhifəsini][Development setup] nəzərdən keçirin.
Asılılıqları quraşdırın:
* meson \*
* [wlroots]
* wayland
* wayland-protocols \*
* pcre2
* json-c
* pango
* cairo
* gdk-pixbuf2 (ixtiyari: sistem trayı üçün əlavə şəkil formatları)
* [swaybg] (ixtiyari: divar kağızı)
* [scdoc] (ixtiyari: man səhifələri) \*
* git (ixtiyari: versiya məlumatı) \*
_\* Kompilyasiya asılılıqları_
Bu əmrləri icra edin:
meson setup build/
ninja -C build/
sudo ninja -C build/ install
## Konfiqurasiya
Əgər artıq i3-dən istifadə edirsinizsə, i3 konfiqurasiyanızı `~/.config/sway/config`
ünvanına köçürün və o, dərhal işləyəcək. Əks halda, nümunə konfiqurasiya faylını
`~/.config/sway/config` ünvanına köçürün. O, adətən `/etc/sway/config` ünvanında yerləşir.
Konfiqurasiya haqqında məlumat üçün `man 5 sway` əmrini icra edin.
## İşə Salma
TTY-dan `sway`-ı işə salın. Bəzi ekran menecerləri işləyə bilər, lakin sway tərəfindən
dəstəklənmir (gdm-in kifayət qədər yaxşı işlədiyi məlumdur).
[i3]: https://i3wm.org/
[Wayland]: http://wayland.freedesktop.org/
[Tez-tez verilən sualları]: https://github.com/swaywm/sway/wiki
[IRC kanalına]: https://web.libera.chat/gamja/?channels=#sway
[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48
[GitHub releases]: https://github.com/swaywm/sway/releases
[Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup
[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots
[swaybg]: https://github.com/swaywm/swaybg/
[scdoc]: https://git.sr.ht/~sircmpwn/scdoc

View file

@ -1,23 +1,24 @@
# sway
sway je s [i3] kompatibilní [Wayland] kompozitor. Přečtěte si [FAQ]. Připojte se na
[IRC kanál][IRC channel] \(#sway na irc.libera.chat).
sway je [waylandový][Wayland] kompozitor kompatibilní s [i3]. Přečtěte si
[FAQ (anglicky)][FAQ]. Připojte se na [IRC kanál (anglicky)][IRC channel]
\(#sway na irc.libera.chat).
## Podpisy vydání
Vydání jsou podepsána [E88F5E48] a publikována [na GitHubu][GitHub releases].
Vydané verze jsou podepsány klíčem [E88F5E48] a publikovány
[na GitHubu][GitHub releases].
## Instalace
### Z balíč
### Z balíků
Sway je dostupný ve spoustě distribucí. Zkuste nainstalovat balíček "sway" ve vaší
distribuci.
Sway je dostupný v mnoha distribucích. Zkuste v té vaší nainstalovat balík "sway".
### Kompilace ze zdrojových kódů
Podívejte se na [tuto stránku wiki][Development setup], pokud chcete sestavit HEAD
sway a wlroots pro testování nebo vývoj.
Pokud chcete sestavit HEAD repozitáře sway a wlroots pro testování nebo vývoj,
použijte návod na [této stránce na wiki (anglicky)][Development setup].
Nainstalujte závislosti:
@ -29,16 +30,16 @@ Nainstalujte závislosti:
* json-c
* pango
* cairo
* gdk-pixbuf2 (volitelné: oznamovací oblast)
* [swaybg] (volitelné: tapeta)
* [scdoc] (volitelné: manuálové stránky) \*
* gdk-pixbuf2 (volitelné: dodatečné formáty ikon pro oznamovací oblast)
* [swaybg] (volitelné: tapeta plochy)
* [scdoc] (volitelné: man stránky) \*
* git (volitelné: informace o verzi) \*
_\* Závislost pouze pro kompilaci_
Spusťte tyto příkazy:
meson build/
meson setup build/
ninja -C build/
sudo ninja -C build/ install
@ -51,8 +52,7 @@ Pro více informací o konfiguraci spusťte `man 5 sway`.
## Spuštění
Spusťte `sway` z TTY. Některé správce zobrazení mohou fungovat, ale nejsou
podporovány sway (je známo, že gdm funguje docela dobře).
Spusťte `sway` z TTY nebo ze správce displeje.
[en]: https://github.com/swaywm/sway#readme
[ar]: README.ar.md

View file

@ -1,21 +1,21 @@
# Sway
Sway ist ein [i3](https://i3wm.org/)-kompatibler [Wayland](http://wayland.freedesktop.org/)-Compositor. Lies die [FAQ](https://github.com/swaywm/sway/wiki). Tritt dem [IRC Channel](https://web.libera.chat/gamja/?channels=#sway) bei (#sway on irc.libera.chat; Englisch).
Sway ist ein [i3]-kompatibler [Wayland]-Compositor. Lies die [FAQ]. Tritt dem [IRC Channel] bei (#sway on irc.libera.chat; Englisch).
## Signaturen
Jedes Release wird mit dem PGP-Schlüssel [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) signiert und [auf GitHub](https://github.com/swaywm/sway/releases) veröffentlicht.
Jeder Release wird mit dem PGP-Schlüssel [E88F5E48] signiert und [auf GitHub][GitHub releases] veröffentlicht.
## Installation
### Über die Paketverwaltung
Sway kann in vielen Distributionen direkt durch die Paketverwaltung installiert werden. Versuche einfach das Packet "sway" zu installieren.
Sway kann in vielen Distributionen direkt durch die Paketverwaltung installiert werden. Versuche einfach das Paket "sway" zu installieren.
### Quellcode selbst kompilieren
sway benötigt die folgenden Pakete:
* meson\*
* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots)
* meson \*
* [wlroots]
* wayland
* wayland-protocols\*
* pcre2
@ -23,21 +23,34 @@ sway benötigt die folgenden Pakete:
* pango
* cairo
* gdk-pixbuf2 (Optional, wird für das Benachrichtigungsfeld (System Tray) benötigt)
* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (Optional, wird für die Dokumentation (Man Pages) benötigt)\*
* [swaybg] (Optional, wird für das Setzen von Desktophintergrundbildern benötigt)
* [scdoc] (Optional, wird für die Dokumentation (Man Pages) benötigt)\*
* git (Optional: Versionsinfo)\*
_\*Werden nur während des Kompilierens benötigt_
_\*Werden nur für das Kompilieren benötigt_
Führe die folgenden Befehle aus:
meson build
ninja -C build
sudo ninja -C build install
meson setup build/
ninja -C build/
sudo ninja -C build/ install
Schaue in das [Wiki][Development setup] (Englisch) für Informationen, falls du zum Testen oder Entwickeln den neuesten Stand (HEAD) von sway und wlroots kompilieren willst.
## Konfiguration
Falls du von i3 migrierst, kannst du deine Konfigurationsdatei nach `~/.config/sway/config` kopieren und die Einstellungen sollten ohne Weiteres funktionieren. Ansonsten kannst du die Beispielkonfiguration, die normalerweise in `/etc/sway/config` liegt, nach `~/.config/sway/config` kopieren. Die Dokumentation zur Konfigurationsdatei findest du in `man 5 sway`.
## Sway starten
Sway kann einfach mit dem Befehl `sway` vom TTY gestartet werden.
Display-Manager werden nicht offiziell unterstützt. Es gibt aber durchaus einige, die mit Sway funktionieren (z.B. gdm).
Sway kann einfach mit dem Befehl `sway` vom TTY oder mithilfe eines Displaymanagers gestartet werden.
[i3]: https://i3wm.org/
[Wayland]: http://wayland.freedesktop.org/
[FAQ]: https://github.com/swaywm/sway/wiki
[IRC channel]: https://web.libera.chat/gamja/?channels=#sway
[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48
[GitHub releases]: https://github.com/swaywm/sway/releases
[Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup
[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots
[swaybg]: https://github.com/swaywm/swaybg
[scdoc]: https://git.sr.ht/~sircmpwn/scdoc

View file

@ -41,7 +41,7 @@ _\*Kompileringsafhængighed_
Kør følgende kommandoer:
meson build
meson setup build
ninja -C build
sudo ninja -C build install
@ -54,8 +54,7 @@ Hvis du allerede bruger i3 kan du bare kopiere din i3 konfiguration til
## Eksekvering
Kør `sway` fra en TTY. Nogle display managers kan fungere, men Sway yder ikke
support til dem (gdm er kendt for at fungere temmelig godt).
Kør `sway` fra en TTY eller fra en display manager.
[i3]: https://i3wm.org/
[Wayland]: http://wayland.freedesktop.org/

View file

@ -40,7 +40,7 @@ _\*Compile-time dep_
Desde su consola, ejecute las órdenes:
meson build
meson setup build
ninja -C build
sudo ninja -C build install

View file

@ -47,7 +47,7 @@ _\* Requis uniquement pour la compilation_
Exécutez ces commandes :
meson build
meson setup build
ninja -C build
sudo ninja -C build install
@ -61,9 +61,7 @@ documentation pour la configuration de sway.
## Exécution
Exécutez `sway` à partir d'un TTY. Certains gestionnaires d'affichage peuvent
fonctionner, mais ne sont pas supportés par Sway (gdm est réputé pour assez
bien fonctionner).
Exécutez `sway` à partir d'un TTY ou d'un gestionnaires d'affichage.
[Wayland]: http://wayland.freedesktop.org/
[i3]: https://i3wm.org/

View file

@ -35,7 +35,7 @@ _\* Compile-time dep_
გაუშვით ეს ბრძანებები:
meson build/
meson setup build/
ninja -C build/
sudo ninja -C build/ install

View file

@ -40,7 +40,7 @@ _\*Compile-time dep_
Τρέξτε αυτά τα commands:
meson build/
meson setup build/
ninja -C build/
sudo ninja -C build/ install

View file

@ -44,7 +44,7 @@ _\* Compilation के समय आवश्यक_
ये commands चलाएं:
meson build/
meson setup build/
ninja -C build/
sudo ninja -C build/ install

View file

@ -40,7 +40,7 @@ _\*Fordításidejű függőség_
Futtasd ezeket a parancsokat:
meson build
meson setup build
ninja -C build
sudo ninja -C build install

View file

@ -41,7 +41,7 @@ _\*نیازمندی‌های زمان کامپایل برنامه_
این فرمان‌ها را اجرا کنید:
meson build
meson setup build
ninja -C build
sudo ninja -C build install

View file

@ -1,7 +1,7 @@
# sway
sway è un compositore di [Wayland] compatibile con [i3]. Leggi le [FAQ].
Unisciti al [canale di IRC] \(#sway su irc.libera.chat).
Unisciti al [canale IRC] \(#sway su irc.libera.chat).
## Firma delle versioni
@ -38,7 +38,7 @@ _\* Dipendenza necessaria per la compilazione_
Esegui questi comandi:
meson build/
meson setup build/
ninja -C build/
sudo ninja -C build/ install
@ -52,13 +52,12 @@ configurazione.
## Esecuzione
Lancia `sway` da un TTY. Alcuni gestori d'accesso potrebbero funzionare ma non
sono supportati da sway (gdm funziona abbastanza bene).
Lancia `sway` da un TTY o da un display manager.
[i3]: https://i3wm.org/
[Wayland]: http://wayland.freedesktop.org/
[FAQ]: https://github.com/swaywm/sway/wiki
[canale di IRC]: https://web.libera.chat/gamja/?channels=#sway
[canale IRC]: https://web.libera.chat/gamja/?channels=#sway
[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48
[GitHub releases]: https://github.com/swaywm/sway/releases
[Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup

View file

@ -42,7 +42,7 @@ _\*コンパイル時の依存_
次のコマンドを実行してください:
meson build
meson setup build
ninja -C build
sudo ninja -C build install
@ -52,5 +52,4 @@ _\*コンパイル時の依存_
## 実行
`sway`をTTYから実行してください。いくつかのディスプレイマネージャは動くかもしれませんが、Swayからサポートされていません(gdmは非常に良く動作することが知られています)。
`sway`をTTYまたはディスプレイマネージャから実行してください。

View file

@ -39,7 +39,7 @@ _\*컴파일 떄 필요_
다음 명령을 실행하세요:
meson build
meson setup build
ninja -C build
sudo ninja -C build install
@ -52,4 +52,4 @@ i3를 이미 사용 중이라면, i3 config을 `~/.config/sway/config`로 복사
## 실행
TTY에서 `sway`를 실행하세요. 일부 display manager는 작동하지만, sway로 부터 지원되지 않습니다(gdm은 상당히 잘 작동한다고 알려져 있습니다).
TTY나 display manager에서 `sway`를 실행하세요.

View file

@ -1,6 +1,6 @@
# sway
**[English][en]** - [عربي][ar] - [Česky][cs] - [Deutsch][de] - [Dansk][dk] - [Español][es] - [Français][fr] - [ქართული][ge] - [Ελληνικά][gr] - [हिन्दी][hi] - [Magyar][hu] - [فارسی][ir] - [Italiano][it] - [日本語][ja] - [한국어][ko] - [Nederlands][nl] - [Norsk][no] - [Polski][pl] - [Português][pt] - [Română][ro] - [Русский][ru] - [Svenska][sv] - [Türkçe][tr] - [Українська][uk] - [中文-简体][zh-CN] - [中文-繁體][zh-TW]
**[English][en]** - [عربي][ar] - [Azərbaycanca][az] - [Česky][cs] - [Deutsch][de] - [Dansk][dk] - [Español][es] - [Français][fr] - [ქართული][ge] - [Ελληνικά][gr] - [हिन्दी][hi] - [Magyar][hu] - [فارسی][ir] - [Italiano][it] - [日本語][ja] - [한국어][ko] - [Nederlands][nl] - [Norsk][no] - [Polski][pl] - [Português][pt] - [Română][ro] - [Русский][ru] - [Српски][sr] - [Svenska][sv] - [Türkçe][tr] - [Українська][uk] - [中文-简体][zh-CN] - [中文-繁體][zh-TW]
sway is an [i3]-compatible [Wayland] compositor. Read the [FAQ]. Join the
[IRC channel] \(#sway on irc.libera.chat).
@ -40,7 +40,7 @@ _\* Compile-time dep_
Run these commands:
meson build/
meson setup build/
ninja -C build/
sudo ninja -C build/ install
@ -53,11 +53,11 @@ Run `man 5 sway` for information on the configuration.
## Running
Run `sway` from a TTY. Some display managers may work but are not supported by
sway (gdm is known to work fairly well).
Run `sway` from a TTY or from a display manager.
[en]: https://github.com/swaywm/sway#readme
[ar]: README.ar.md
[az]: README.az.md
[cs]: README.cs.md
[de]: README.de.md
[dk]: README.dk.md
@ -77,6 +77,7 @@ sway (gdm is known to work fairly well).
[pt]: README.pt.md
[ro]: README.ro.md
[ru]: README.ru.md
[sr]: README.sr.md
[sv]: README.sv.md
[tr]: README.tr.md
[uk]: README.uk.md

View file

@ -40,7 +40,7 @@ _\* Compileerafhankelijkheden_
Voer deze opdrachten uit:
meson build
meson setup build
ninja -C build
sudo ninja -C build install

View file

@ -1,29 +1,25 @@
# Sway
Sway er en [i3]-kompatibel [Wayland] compositor. Les [Ofte stilte spørsmål].
Delta på [IRC kanalen][IRC kanal] \(#sway på irc.libera.chat).
Sway er en [i3]-kompatibel [Wayland]-compositor. Les [Ofte stilte spørsmål].
Delta på [IRC-kanalen][IRC-kanal] \(#sway på irc.libera.chat).
## Utgivelses Signaturer
## Signaturer
Utgivelser er signert med [E88F5E48] og publisert [på GitHub][GitHub
releases].
Utgivelser er signert med [E88F5E48] og publisert [på GitHub][GitHub releases].
## Installasjon
### Fra system pakker
### Fra systempakker
Sway er tilgjengelig i mange distribusjoner. Prøv å installere "sway" pakken
Sway er tilgjengelig i mange distribusjoner. Prøv å installere pakken "sway"
fra din distro sine repoer.
Er du interessert i å pakke Sway for din distribusjon kan du ta turen innom
IRC-kanalen eller send en e-post til sir@cmpwn.com for råd.
### Kompilering fra kildekode
Se [denne wiki-siden][Oppsetting for utvikling] hvis du vil bygge fra HEAD grenen av sway og
wlroots for testing eller utvikling.
Se [denne wiki-siden][Oppsetting for utvikling] hvis du vil bygge fra HEAD-grenen av
sway og wlroots for testing eller utvikling.
Installasjonsavhengigheter:
Installer avhengigheter:
* meson \*
* [wlroots]
@ -33,36 +29,37 @@ Installasjonsavhengigheter:
* json-c
* pango
* cairo
* gdk-pixbuf2 (valgfritt: system tray)
* gdk-pixbuf2 (valgfritt: støtte for ekstra bildeformater i system tray)
* [swaybg] (valgfritt: bakgrunnsbilde)
* [scdoc] (valgfritt: man pages) \*
* git \*
* git (valgfritt: versjonsinformasjon) \*
_\*Kompileringsavhengigheter_
_\* Kompileringsavhengigheter_
Kjør følgende kommandoer:
meson build
ninja -C build
sudo ninja -C build install
meson setup build/
ninja -C build/
sudo ninja -C build/ install
## Konfigurasjon
Hvis du allerede bruker i3 kan du bare kopiere din i3 konfigurasjon til
`~/.config/sway/config`. Ellers skal du kopiere eksempel konfigurasjonsfilen til
`~/.config/sway/config`. Eksempel filen er normalt plasert i `/etc/sway/config`. Kjør
`man 5 sway` for å få oplysninger om konfigurasjonen.
Hvis du allerede bruker i3 kan du bare kopiere din i3-konfigurasjon til
`~/.config/sway/config`. Ellers skal du kopiere eksempelkonfigurasjonsfilen til
`~/.config/sway/config`. Eksempelfilen er normalt plasert i `/etc/sway/config`.
Kjør `man 5 sway` for å få opplysninger om konfigurasjonen.
## Utførelse
## Kjøring
Kjør `sway` fra en TTY. Noen display managers kan fungere, men Sway har ikke
støtte for dem (gdm er kjent for å fungere ganske bra).
Kjør `sway` fra en TTY eller fra en display manager.
[i3]: https://i3wm.org/
[Wayland]: http://wayland.freedesktop.org/
[Ofte stilte spørsmål]: https://github.com/swaywm/sway/wiki
[IRC kanal]: https://web.libera.chat/gamja/?channels=#sway
[IRC-kanal]: https://web.libera.chat/gamja/?channels=#sway
[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48
[GitHub releases]: https://github.com/swaywm/sway/releases
[Oppsetting for utvikling]: https://github.com/swaywm/sway/wiki/Development-Setup
[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots
[swaybg]: https://github.com/swaywm/swaybg/
[scdoc]: https://git.sr.ht/~sircmpwn/scdoc

View file

@ -40,7 +40,7 @@ _\*zależności kompilacji_
Wykonaj następujące polecenia:
meson build
meson setup build
ninja -C build
sudo ninja -C build install
@ -53,5 +53,4 @@ Wykonaj polecenie `man 5 sway` aby uzyskać informacje dotyczące konfiguracji.
## Uruchamianie
Wykonaj polecenie `sway` z poziomu TTY. Niektóre menedżery wyświetlania mogą umożliwiać rozruch z ich
poziomu, ale nie jest to wspierane przez sway (w gdm podobno działa to całkiem nieźle).
Wykonaj polecenie `sway` z poziomu TTY lub menedżera wyświetlania.

View file

@ -42,7 +42,7 @@ _\*Dependência de tempo de compilação_
Execute esses comandos:
meson build
meson setup build
ninja -C build
sudo ninja -C build install

View file

@ -38,7 +38,7 @@ Dependențe pentru instalare:
Rulați aceste comenzi:
```
meson build
meson setup build
ninja -C build
sudo ninja -C build install
```

View file

@ -41,7 +41,7 @@ _\*Зависимости для сборки_
Выполните эти команды:
meson build
meson setup build
ninja -C build
sudo ninja -C build install
@ -54,8 +54,7 @@ _\*Зависимости для сборки_
## Запуск
Выполните команду `sway` прямо из TTY. Некоторые дисплейные менеджеры могут работать, но они не поддерживаются со стороны
sway (gdm работает довольно неплохо).
Выполните команду `sway` прямо из TTY или дисплейного менеджера.
[i3]: https://i3wm.org/
[Wayland]: http://wayland.freedesktop.org/

65
README.sr.md Normal file
View file

@ -0,0 +1,65 @@
# sway
sway је [i3]-компатибилан [Wayland] композитор. Прочитајте [FAQ]. Придружите се
[IRC каналу] \(#sway на irc.libera.chat).
## Потписи Издања
Издања су потписана са [E88F5E48] и објављена [на GitHub-у][GitHub releases].
## Инсталација
### Из пакета
Sway је доступан у многим дистрибуцијама. Покушајте да инсталирате "sway" пакет за
вашу.
### Компајлирање из Извора
Погледајте [ову вики страницу][Development setup], ако желите да компајлирате HEAD верзију
sway-а и wlroots-а за тестирање или развој.
Инсталирајте зависности:
* meson \*
* [wlroots]
* wayland
* wayland-protocols \*
* pcre2
* json-c
* pango
* cairo
* gdk-pixbuf2 (опционо: додатни формати слика за системску траку)
* [swaybg] (опционо: позадина)
* [scdoc] (опционо: man странице) \*
* git (опционо: информације о верзији) \*
_\* Потребно само за компајлирање_
Покрените следеће команде:
meson setup build/
ninja -C build/
sudo ninja -C build/ install
## Конфигурација
Ако већ користите i3, копирајте вашу i3 конфигурацију у `~/.config/sway/config` и
радиће одмах. У супротном, копирајте пример конфигурационе датотеке у
`~/.config/sway/config`. Обично се налази у `/etc/sway/config`.
Покрените `man 5 sway` за информације о конфигурацији.
## Покретање
Покрените `sway` из TTY-a или из менаџера приказа.
[i3]: https://i3wm.org/
[Wayland]: http://wayland.freedesktop.org/
[FAQ]: https://github.com/swaywm/sway/wiki
[IRC каналу]: https://web.libera.chat/gamja/?channels=#sway
[E88F5E48]: https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48
[GitHub releases]: https://github.com/swaywm/sway/releases
[Development setup]: https://github.com/swaywm/sway/wiki/Development-Setup
[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots
[swaybg]: https://github.com/swaywm/swaybg/
[scdoc]: https://git.sr.ht/~sircmpwn/scdoc

View file

@ -35,7 +35,7 @@ _\* Krav för kompilering_
Kör dessa kommandon:
meson build/
meson setup build/
ninja -C build/
sudo ninja -C build/ install

View file

@ -38,7 +38,7 @@ _\*Derleme-anı bağımlılıkları_
Şu komutları çalıştırın:
meson build
meson setup build
ninja -C build
sudo ninja -C build install

View file

@ -51,7 +51,7 @@ _\*Лише для компіляції_
Виконайте ці команди:
meson build
meson setup build
ninja -C build
sudo ninja -C build install

View file

@ -35,7 +35,7 @@ _\*编译时依赖_
运行如下命令:
meson build/
meson setup build/
ninja -C build/
sudo ninja -C build/ install

View file

@ -40,7 +40,7 @@ _\*編譯時相依_
執行這些指令:
meson build
meson setup build
ninja -C build
sudo ninja -C build install

View file

@ -141,3 +141,9 @@ bool sway_set_cloexec(int fd, bool cloexec) {
}
return true;
}
uint32_t get_current_time_in_msec(void) {
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
return now.tv_sec * 1000 + now.tv_nsec / 1000000;
}

View file

@ -46,14 +46,18 @@ output * bg @datadir@/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png fill
#
# Example configuration:
#
# input "2:14:SynPS/2_Synaptics_TouchPad" {
# input type:touchpad {
# dwt enabled
# tap enabled
# natural_scroll enabled
# middle_emulation enabled
# }
#
# You can get the names of your inputs by running: swaymsg -t get_inputs
# input type:keyboard {
# xkb_layout "eu"
# }
#
# You can also configure each device individually.
# Read `man 5 sway-input` for more information about this section.
### Key bindings
@ -201,9 +205,18 @@ bindsym $mod+r mode "resize"
bindsym --locked XF86AudioLowerVolume exec pactl set-sink-volume \@DEFAULT_SINK@ -5%
bindsym --locked XF86AudioRaiseVolume exec pactl set-sink-volume \@DEFAULT_SINK@ +5%
bindsym --locked XF86AudioMicMute exec pactl set-source-mute \@DEFAULT_SOURCE@ toggle
# Special keys to control media via playerctl
bindsym --locked XF86AudioPlay exec playerctl play-pause
bindsym --locked XF86AudioPause exec playerctl play-pause
bindsym --locked XF86AudioPrev exec playerctl previous
bindsym --locked XF86AudioNext exec playerctl next
bindsym --locked XF86AudioStop exec playerctl stop
# Special keys to adjust brightness via brightnessctl
bindsym --locked XF86MonBrightnessDown exec brightnessctl set 5%-
bindsym --locked XF86MonBrightnessUp exec brightnessctl set 5%+
# Special key to take a screenshot with grim
bindsym Print exec grim

View file

@ -290,6 +290,7 @@ sway_cmd output_cmd_color_profile;
sway_cmd output_cmd_disable;
sway_cmd output_cmd_dpms;
sway_cmd output_cmd_enable;
sway_cmd output_cmd_hdr;
sway_cmd output_cmd_max_render_time;
sway_cmd output_cmd_mode;
sway_cmd output_cmd_modeline;

View file

@ -261,7 +261,7 @@ enum scale_filter_mode {
};
enum render_bit_depth {
RENDER_BIT_DEPTH_DEFAULT, // the default is currently 8
RENDER_BIT_DEPTH_DEFAULT, // the default is currently 8 for SDR, 10 for HDR
RENDER_BIT_DEPTH_6,
RENDER_BIT_DEPTH_8,
RENDER_BIT_DEPTH_10,
@ -291,6 +291,7 @@ struct output_config {
bool set_color_transform;
struct wlr_color_transform *color_transform;
int allow_tearing;
int hdr;
char *background;
char *background_option;

View file

@ -56,6 +56,7 @@ struct criteria {
struct pattern *sandbox_engine;
struct pattern *sandbox_app_id;
struct pattern *sandbox_instance_id;
struct pattern *tag;
};
bool criteria_is_empty(struct criteria *criteria);

View file

@ -9,7 +9,6 @@ struct sway_layer_surface {
struct wl_listener map;
struct wl_listener unmap;
struct wl_listener surface_commit;
struct wl_listener output_destroy;
struct wl_listener node_destroy;
struct wl_listener new_popup;
@ -19,6 +18,8 @@ struct sway_layer_surface {
struct sway_popup_desc desc;
struct sway_output *output;
struct wl_list link; // sway_output.layer_surfaces
struct wlr_scene_layer_surface_v1 *scene;
struct wlr_scene_tree *tree;
struct wlr_layer_surface_v1 *layer_surface;
@ -41,4 +42,6 @@ struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface(
void arrange_layers(struct sway_output *output);
void destroy_layers(struct sway_output *output);
#endif

View file

@ -52,6 +52,7 @@ struct sway_output {
bool enabled;
list_t *workspaces;
struct wl_list layer_surfaces; // sway_layer_surface.link
struct sway_output_state current;
@ -61,17 +62,15 @@ struct sway_output {
struct wl_listener frame;
struct wl_listener request_state;
struct {
struct wl_signal disable;
} events;
struct wlr_color_transform *color_transform;
struct timespec last_presentation;
uint32_t refresh_nsec;
int max_render_time; // In milliseconds
struct wl_event_source *repaint_timer;
bool allow_tearing;
bool hdr;
};
struct sway_output_non_desktop {
@ -132,6 +131,8 @@ struct sway_container *output_find_container(struct sway_output *output,
void output_get_box(struct sway_output *output, struct wlr_box *box);
bool output_supports_hdr(struct wlr_output *output, const char **unsupported_reason_ptr);
enum sway_container_layout output_get_default_layout(
struct sway_output *output);

View file

@ -27,7 +27,7 @@ struct sway_session_lock {
struct sway_server {
struct wl_display *wl_display;
struct wl_event_loop *wl_event_loop;
const char *socket;
char *socket;
struct wlr_backend *backend;
struct wlr_session *session;
@ -112,12 +112,17 @@ struct sway_server {
struct wlr_export_dmabuf_manager_v1 *export_dmabuf_manager_v1;
struct wlr_security_context_manager_v1 *security_context_manager_v1;
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1 *ext_foreign_toplevel_image_capture_source_manager_v1;
struct wl_listener new_foreign_toplevel_capture_request;
struct wlr_xdg_activation_v1 *xdg_activation_v1;
struct wl_listener xdg_activation_v1_request_activate;
struct wl_listener xdg_activation_v1_new_token;
struct wl_listener xdg_toplevel_tag_manager_v1_set_tag;
struct wl_listener request_set_cursor_shape;
struct wlr_tearing_control_manager_v1 *tearing_control_v1;
struct wl_listener tearing_control_new_object;
struct wl_list tearing_controllers; // sway_tearing_controller::link

View file

@ -103,7 +103,7 @@ struct sway_container {
char *title; // The view's title (unformatted)
char *formatted_title; // The title displayed in the title bar
int title_width;
char *title_format;
enum sway_container_layout prev_split_layout;

View file

@ -25,6 +25,7 @@ enum sway_view_type {
enum sway_view_prop {
VIEW_PROP_TITLE,
VIEW_PROP_APP_ID,
VIEW_PROP_TAG,
VIEW_PROP_CLASS,
VIEW_PROP_INSTANCE,
VIEW_PROP_WINDOW_TYPE,
@ -69,6 +70,9 @@ struct sway_view {
struct wlr_scene_tree *content_tree;
struct wlr_scene_tree *saved_surface_tree;
struct wlr_scene *image_capture_scene;
struct wlr_ext_image_capture_source_v1 *image_capture_source;
struct sway_container *container; // NULL if unmapped and transactions finished
struct wlr_surface *surface; // NULL for unmapped views
struct sway_xdg_decoration *xdg_decoration;
@ -124,6 +128,9 @@ struct sway_view {
struct sway_xdg_shell_view {
struct sway_view view;
struct wlr_scene_tree *image_capture_tree;
char *tag;
struct wl_listener commit;
struct wl_listener request_move;
struct wl_listener request_resize;
@ -142,6 +149,8 @@ struct sway_xwayland_view {
struct wlr_scene_tree *surface_tree;
struct wlr_scene_surface *image_capture_scene_surface;
struct wl_listener commit;
struct wl_listener request_move;
struct wl_listener request_resize;
@ -192,10 +201,12 @@ struct sway_popup_desc {
struct sway_xdg_popup {
struct sway_view *view;
struct wlr_xdg_popup *wlr_xdg_popup;
struct wlr_scene_tree *scene_tree;
struct wlr_scene_tree *xdg_surface_tree;
struct wlr_xdg_popup *wlr_xdg_popup;
struct wlr_scene_tree *image_capture_tree;
struct sway_popup_desc desc;
@ -227,6 +238,8 @@ const char *view_get_sandbox_app_id(struct sway_view *view);
const char *view_get_sandbox_instance_id(struct sway_view *view);
const char *view_get_tag(struct sway_view *view);
const char *view_get_shell(struct sway_view *view);
void view_get_constraints(struct sway_view *view, double *min_width,
@ -351,4 +364,6 @@ void view_send_frame_done(struct sway_view *view);
bool view_can_tear(struct sway_view *view);
void xdg_toplevel_tag_manager_v1_handle_set_tag(struct wl_listener *listener, void *data);
#endif

View file

@ -96,7 +96,7 @@ void workspace_output_add_priority(struct sway_workspace *workspace,
struct sway_output *output);
struct sway_output *workspace_output_get_highest_available(
struct sway_workspace *ws, struct sway_output *exclude);
struct sway_workspace *ws);
void workspace_detect_urgent(struct sway_workspace *workspace);

View file

@ -14,6 +14,11 @@ struct box_colors {
uint32_t text;
};
struct box_size {
uint32_t width;
uint32_t height;
};
struct config_output {
struct wl_list link; // swaybar_config::outputs
char *name;

View file

@ -61,4 +61,6 @@ const char *sway_wl_output_subpixel_to_string(enum wl_output_subpixel subpixel);
bool sway_set_cloexec(int fd, bool cloexec);
uint32_t get_current_time_in_msec(void);
#endif

View file

@ -1,13 +1,14 @@
project(
'sway',
'c',
version: '1.11-rc2',
version: '1.12-dev',
license: 'MIT',
meson_version: '>=1.3',
default_options: [
'c_std=c11',
'warning_level=2',
'werror=true',
'wrap_mode=nodownload',
],
)
@ -38,14 +39,14 @@ if is_freebsd
endif
# Execute the wlroots subproject, if any
wlroots_version = ['>=0.19.0', '<0.20.0']
wlroots_version = ['>=0.20.0', '<0.21.0']
subproject(
'wlroots',
default_options: ['examples=false'],
required: false,
version: wlroots_version,
)
wlroots = dependency('wlroots-0.19', version: wlroots_version, fallback: 'wlroots')
wlroots = dependency('wlroots-0.20', version: wlroots_version, fallback: 'wlroots')
wlroots_features = {
'xwayland': false,
'libinput_backend': false,
@ -64,7 +65,7 @@ pcre2 = dependency('libpcre2-8')
wayland_server = dependency('wayland-server', version: '>=1.21.0')
wayland_client = dependency('wayland-client')
wayland_cursor = dependency('wayland-cursor')
wayland_protos = dependency('wayland-protocols', version: '>=1.24', default_options: ['tests=false'])
wayland_protos = dependency('wayland-protocols', version: '>=1.41', default_options: ['tests=false'])
xkbcommon = dependency('xkbcommon', version: '>=1.5.0')
cairo = dependency('cairo')
pango = dependency('pango')

View file

@ -9,14 +9,7 @@ wayland_scanner = find_program(
protocols = [
wl_protocol_dir / 'stable/tablet/tablet-v2.xml',
wl_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
wl_protocol_dir / 'staging/content-type/content-type-v1.xml',
wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
wl_protocol_dir / 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml',
wl_protocol_dir / 'staging/ext-image-capture-source/ext-image-capture-source-v1.xml',
wl_protocol_dir / 'staging/ext-image-copy-capture/ext-image-copy-capture-v1.xml',
wl_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml',
wl_protocol_dir / 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml',
wl_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml',
wl_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
'wlr-layer-shell-unstable-v1.xml',
'idle.xml',

View file

@ -134,6 +134,19 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
// Operate on parent container, like i3.
if (container) {
container = container->pending.parent;
// If parent has only a singe child operate on its parent and
// flatten once, like i3
if (container && container->pending.children->length == 1) {
// Also check grandparent to avoid restricting layouts
struct sway_container *parent = container->pending.parent;
if (parent && parent->pending.children->length == 1) {
struct sway_container *child = container->pending.children->items[0];
struct sway_container *parent = container->pending.parent;
container_replace(container, child);
container_begin_destroy(container);
container = parent;
}
}
}
// We could be working with a container OR a workspace. These are different

View file

@ -222,6 +222,7 @@ static void container_move_to_workspace(struct sway_container *container,
container_detach(container);
if (workspace_is_empty(workspace) && container->pending.children) {
workspace_unwrap_children(workspace, container);
container_reap_empty(container);
} else {
container->pending.width = container->pending.height = 0;
container->width_fraction = container->height_fraction = 0;

View file

@ -15,6 +15,7 @@ static const struct cmd_handler output_handlers[] = {
{ "disable", output_cmd_disable },
{ "dpms", output_cmd_dpms },
{ "enable", output_cmd_enable },
{ "hdr", output_cmd_hdr },
{ "max_render_time", output_cmd_max_render_time },
{ "mode", output_cmd_mode },
{ "modeline", output_cmd_modeline },

View file

@ -0,0 +1,37 @@
#include <strings.h>
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/output.h"
#include "util.h"
struct cmd_results *output_cmd_hdr(int argc, char **argv) {
if (!config->handler_context.output_config) {
return cmd_results_new(CMD_FAILURE, "Missing output config");
}
if (argc == 0) {
return cmd_results_new(CMD_INVALID, "Missing hdr argument");
}
bool current = false;
if (strcasecmp(argv[0], "toggle") == 0) {
const char *oc_name = config->handler_context.output_config->name;
if (strcmp(oc_name, "*") == 0) {
return cmd_results_new(CMD_INVALID,
"Cannot apply toggle to all outputs");
}
struct sway_output *output = all_output_by_name_or_id(oc_name);
if (!output) {
return cmd_results_new(CMD_FAILURE,
"Cannot apply toggle to unknown output %s", oc_name);
}
current = output->hdr;
}
config->handler_context.output_config->hdr = parse_boolean(argv[0], current);
config->handler_context.leftovers.argc = argc - 1;
config->handler_context.leftovers.argv = argv + 1;
return NULL;
}

View file

@ -80,61 +80,46 @@ void container_resize_tiled(struct sway_container *con,
}
// For HORIZONTAL or VERTICAL, we are growing in two directions so select
// both adjacent siblings. For RIGHT or DOWN, just select the next sibling.
// For LEFT or UP, convert it to a RIGHT or DOWN resize and reassign con to
// the previous sibling.
struct sway_container *prev = NULL;
struct sway_container *next = NULL;
// all adjacent siblings. For RIGHT or DOWN or LEFT or UP select just the
// previous or next sibling.
list_t *resize = create_list();
list_t *siblings = container_get_siblings(con);
int index = container_sibling_index(con);
if (axis == AXIS_HORIZONTAL || axis == AXIS_VERTICAL) {
if (index == 0) {
next = siblings->items[1];
} else if (index == siblings->length - 1) {
// Convert edge to top/left
next = con;
con = siblings->items[index - 1];
amount = -amount;
} else {
prev = siblings->items[index - 1];
next = siblings->items[index + 1];
}
list_cat(resize, siblings);
} else if (axis == WLR_EDGE_TOP || axis == WLR_EDGE_LEFT) {
if (!sway_assert(index > 0, "Didn't expect first child")) {
return;
goto cleanup;
}
next = con;
con = siblings->items[index - 1];
amount = -amount;
list_add(resize, siblings->items[index - 1]);
list_add(resize, con);
} else {
if (!sway_assert(index < siblings->length - 1,
"Didn't expect last child")) {
return;
goto cleanup;
}
next = siblings->items[index + 1];
list_add(resize, con);
list_add(resize, siblings->items[index + 1]);
}
// Apply new dimensions
int sibling_amount = prev ? ceil((double)amount / 2.0) : amount;
int sibling_amount = ceil((double)amount / (double)(resize->length - 1));
if (is_horizontal(axis)) {
if (con->pending.width + amount < MIN_SANE_W) {
return;
}
if (next->pending.width - sibling_amount < MIN_SANE_W) {
return;
}
if (prev && prev->pending.width - sibling_amount < MIN_SANE_W) {
return;
for (int i = 0; i < resize->length; i++) {
struct sway_container *sibling = resize->items[i];
double change = sibling == con ? amount : -sibling_amount;
if (sibling->pending.width + change < MIN_SANE_W) {
goto cleanup;
}
}
if (con->child_total_width <= 0) {
return;
goto cleanup;
}
// We're going to resize so snap all the width fractions to full pixels
// to avoid rounding issues
list_t *siblings = container_get_siblings(con);
for (int i = 0; i < siblings->length; ++i) {
struct sway_container *con = siblings->items[i];
con->width_fraction = con->pending.width / con->child_total_width;
@ -142,30 +127,27 @@ void container_resize_tiled(struct sway_container *con,
double amount_fraction = (double)amount / con->child_total_width;
double sibling_amount_fraction =
prev ? amount_fraction / 2.0 : amount_fraction;
amount_fraction / (double)(resize->length - 1);
con->width_fraction += amount_fraction;
next->width_fraction -= sibling_amount_fraction;
if (prev) {
prev->width_fraction -= sibling_amount_fraction;
for (int i = 0; i < resize->length; i++) {
struct sway_container *sibling = resize->items[i];
sibling->width_fraction +=
sibling == con ? amount_fraction : -sibling_amount_fraction;
}
} else {
if (con->pending.height + amount < MIN_SANE_H) {
return;
}
if (next->pending.height - sibling_amount < MIN_SANE_H) {
return;
}
if (prev && prev->pending.height - sibling_amount < MIN_SANE_H) {
return;
for (int i = 0; i < resize->length; i++) {
struct sway_container *sibling = resize->items[i];
double change = sibling == con ? amount : -sibling_amount;
if (sibling->pending.height + change < MIN_SANE_H) {
goto cleanup;
}
}
if (con->child_total_height <= 0) {
return;
goto cleanup;
}
// We're going to resize so snap all the height fractions to full pixels
// to avoid rounding issues
list_t *siblings = container_get_siblings(con);
for (int i = 0; i < siblings->length; ++i) {
struct sway_container *con = siblings->items[i];
con->height_fraction = con->pending.height / con->child_total_height;
@ -173,12 +155,12 @@ void container_resize_tiled(struct sway_container *con,
double amount_fraction = (double)amount / con->child_total_height;
double sibling_amount_fraction =
prev ? amount_fraction / 2.0 : amount_fraction;
amount_fraction / (double)(resize->length - 1);
con->height_fraction += amount_fraction;
next->height_fraction -= sibling_amount_fraction;
if (prev) {
prev->height_fraction -= sibling_amount_fraction;
for (int i = 0; i < resize->length; i++) {
struct sway_container *sibling = resize->items[i];
sibling->height_fraction +=
sibling == con ? amount_fraction : -sibling_amount_fraction;
}
}
@ -187,6 +169,9 @@ void container_resize_tiled(struct sway_container *con,
} else {
arrange_workspace(con->pending.workspace);
}
cleanup:
list_free(resize);
}
/**

View file

@ -8,7 +8,7 @@ struct cmd_results *cmd_ws_auto_back_and_forth(int argc, char **argv) {
if ((error = checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1))) {
return error;
}
config->auto_back_and_forth =
config->auto_back_and_forth =
parse_boolean(argv[0], config->auto_back_and_forth);
return cmd_results_new(CMD_SUCCESS, NULL);
}

View file

@ -552,28 +552,12 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
return success;
}
static bool load_include_config(const char *path, const char *parent_dir,
struct sway_config *config, struct swaynag_instance *swaynag) {
static bool load_include_config(const char *path, struct sway_config *config,
struct swaynag_instance *swaynag) {
// save parent config
const char *parent_config = config->current_config_path;
char *full_path;
int len = strlen(path);
if (len >= 1 && path[0] != '/') {
len = len + strlen(parent_dir) + 2;
full_path = malloc(len * sizeof(char));
if (!full_path) {
sway_log(SWAY_ERROR,
"Unable to allocate full path to included config");
return false;
}
snprintf(full_path, len, "%s/%s", parent_dir, path);
} else {
full_path = strdup(path);
}
char *real_path = realpath(full_path, NULL);
free(full_path);
char *real_path = realpath(path, NULL);
if (real_path == NULL) {
sway_log(SWAY_DEBUG, "%s not found.", path);
@ -625,7 +609,7 @@ void load_include_configs(const char *path, struct sway_config *config,
char **w = p.we_wordv;
size_t i;
for (i = 0; i < p.we_wordc; ++i) {
load_include_config(w[i], parent_dir, config, swaynag);
load_include_config(w[i], config, swaynag);
}
wordfree(&p);
}

View file

@ -67,7 +67,7 @@ struct output_config *new_output_config(const char *name) {
oc->refresh_rate = -1;
oc->custom_mode = -1;
oc->drm_mode.type = -1;
oc->x = oc->y = -1;
oc->x = oc->y = INT_MAX;
oc->scale = -1;
oc->scale_filter = SCALE_FILTER_DEFAULT;
oc->transform = -1;
@ -79,6 +79,7 @@ struct output_config *new_output_config(const char *name) {
oc->color_transform = NULL;
oc->power = -1;
oc->allow_tearing = -1;
oc->hdr = -1;
return oc;
}
@ -93,11 +94,11 @@ static void supersede_output_config(struct output_config *dst, struct output_con
if (src->height != -1) {
dst->height = -1;
}
if (src->x != -1) {
dst->x = -1;
if (src->x != INT_MAX) {
dst->x = INT_MAX;
}
if (src->y != -1) {
dst->y = -1;
if (src->y != INT_MAX) {
dst->y = INT_MAX;
}
if (src->scale != -1) {
dst->scale = -1;
@ -129,6 +130,13 @@ static void supersede_output_config(struct output_config *dst, struct output_con
if (src->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) {
dst->render_bit_depth = RENDER_BIT_DEPTH_DEFAULT;
}
if (src->set_color_transform) {
if (dst->color_transform) {
wlr_color_transform_unref(dst->color_transform);
dst->color_transform = NULL;
}
dst->set_color_transform = false;
}
if (src->background) {
free(dst->background);
dst->background = NULL;
@ -144,6 +152,12 @@ static void supersede_output_config(struct output_config *dst, struct output_con
if (src->power != -1) {
dst->power = -1;
}
if (src->allow_tearing != -1) {
dst->allow_tearing = -1;
}
if (src->hdr != -1) {
dst->hdr = -1;
}
}
// merge_output_config sets all fields in dst that were set in src
@ -157,10 +171,10 @@ static void merge_output_config(struct output_config *dst, struct output_config
if (src->height != -1) {
dst->height = src->height;
}
if (src->x != -1) {
if (src->x != INT_MAX) {
dst->x = src->x;
}
if (src->y != -1) {
if (src->y != INT_MAX) {
dst->y = src->y;
}
if (src->scale != -1) {
@ -219,6 +233,9 @@ static void merge_output_config(struct output_config *dst, struct output_config
if (src->allow_tearing != -1) {
dst->allow_tearing = src->allow_tearing;
}
if (src->hdr != -1) {
dst->hdr = src->hdr;
}
}
void store_output_config(struct output_config *oc) {
@ -261,11 +278,11 @@ void store_output_config(struct output_config *oc) {
sway_log(SWAY_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz "
"position %d,%d scale %f subpixel %s transform %d) (bg %s %s) (power %d) "
"(max render time: %d) (allow tearing: %d)",
"(max render time: %d) (allow tearing: %d) (hdr: %d)",
oc->name, oc->enabled, oc->width, oc->height, oc->refresh_rate,
oc->x, oc->y, oc->scale, sway_wl_output_subpixel_to_string(oc->subpixel),
oc->transform, oc->background, oc->background_option, oc->power,
oc->max_render_time, oc->allow_tearing);
oc->max_render_time, oc->allow_tearing, oc->hdr);
// If the configuration was not merged into an existing configuration, add
// it to the list. Otherwise we're done with it and can free it.
@ -331,6 +348,45 @@ static void set_modeline(struct wlr_output *output,
#endif
}
bool output_supports_hdr(struct wlr_output *output, const char **unsupported_reason_ptr) {
const char *unsupported_reason = NULL;
if (!(output->supported_primaries & WLR_COLOR_NAMED_PRIMARIES_BT2020)) {
unsupported_reason = "BT2020 primaries not supported by output";
} else if (!(output->supported_transfer_functions & WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ)) {
unsupported_reason = "PQ transfer function not supported by output";
} else if (!server.renderer->features.output_color_transform) {
unsupported_reason = "renderer doesn't support output color transforms";
}
if (unsupported_reason_ptr != NULL) {
*unsupported_reason_ptr = unsupported_reason;
}
return unsupported_reason == NULL;
}
static void set_hdr(struct wlr_output *output, struct wlr_output_state *pending, bool enabled) {
const char *unsupported_reason = NULL;
if (enabled && !output_supports_hdr(output, &unsupported_reason)) {
sway_log(SWAY_ERROR, "Cannot enable HDR on output %s: %s",
output->name, unsupported_reason);
enabled = false;
}
if (!enabled) {
if (output->supported_primaries != 0 || output->supported_transfer_functions != 0) {
sway_log(SWAY_DEBUG, "Disabling HDR on output %s", output->name);
wlr_output_state_set_image_description(pending, NULL);
}
return;
}
sway_log(SWAY_DEBUG, "Enabling HDR on output %s", output->name);
const struct wlr_output_image_description image_desc = {
.primaries = WLR_COLOR_NAMED_PRIMARIES_BT2020,
.transfer_function = WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ,
};
wlr_output_state_set_image_description(pending, &image_desc);
}
/* Some manufacturers hardcode the aspect-ratio of the output in the physical
* size field. */
static bool phys_size_is_aspect_ratio(struct wlr_output *output) {
@ -405,6 +461,16 @@ static enum render_bit_depth bit_depth_from_format(uint32_t render_format) {
return RENDER_BIT_DEPTH_DEFAULT;
}
static enum render_bit_depth get_config_render_bit_depth(const struct output_config *oc) {
if (oc && oc->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) {
return oc->render_bit_depth;
}
if (oc && oc->hdr == 1) {
return RENDER_BIT_DEPTH_10;
}
return RENDER_BIT_DEPTH_8;
}
static bool render_format_is_bgr(uint32_t fmt) {
return fmt == DRM_FORMAT_XBGR2101010 || fmt == DRM_FORMAT_XBGR8888;
}
@ -475,24 +541,29 @@ static void queue_output_config(struct output_config *oc,
}
}
if (oc && oc->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) {
if (oc->render_bit_depth == RENDER_BIT_DEPTH_10 &&
bit_depth_from_format(output->wlr_output->render_format) == oc->render_bit_depth) {
// 10-bit was set successfully before, try to save some tests by reusing the format
wlr_output_state_set_render_format(pending, output->wlr_output->render_format);
} else if (oc->render_bit_depth == RENDER_BIT_DEPTH_10) {
wlr_output_state_set_render_format(pending, DRM_FORMAT_XRGB2101010);
} else if (oc->render_bit_depth == RENDER_BIT_DEPTH_6){
wlr_output_state_set_render_format(pending, DRM_FORMAT_RGB565);
} else {
wlr_output_state_set_render_format(pending, DRM_FORMAT_XRGB8888);
}
enum render_bit_depth render_bit_depth = get_config_render_bit_depth(oc);
if (render_bit_depth == RENDER_BIT_DEPTH_10 &&
bit_depth_from_format(output->wlr_output->render_format) == render_bit_depth) {
// 10-bit was set successfully before, try to save some tests by reusing the format
wlr_output_state_set_render_format(pending, output->wlr_output->render_format);
} else if (render_bit_depth == RENDER_BIT_DEPTH_10) {
wlr_output_state_set_render_format(pending, DRM_FORMAT_XRGB2101010);
} else if (render_bit_depth == RENDER_BIT_DEPTH_6) {
wlr_output_state_set_render_format(pending, DRM_FORMAT_RGB565);
} else {
wlr_output_state_set_render_format(pending, DRM_FORMAT_XRGB8888);
}
bool hdr = oc && oc->hdr == 1;
if (hdr && oc->color_transform != NULL) {
sway_log(SWAY_ERROR, "Cannot HDR on output %s: output has an ICC profile set", wlr_output->name);
hdr = false;
}
set_hdr(wlr_output, pending, hdr);
}
static bool finalize_output_config(struct output_config *oc, struct sway_output *output) {
static bool finalize_output_config(struct output_config *oc, struct sway_output *output,
const struct wlr_output_state *applied) {
if (output == root->fallback_output) {
return false;
}
@ -527,7 +598,7 @@ static bool finalize_output_config(struct output_config *oc, struct sway_output
}
// Find position for it
if (oc && (oc->x != -1 || oc->y != -1)) {
if (oc && oc->x != INT_MAX && oc->y != INT_MAX) {
sway_log(SWAY_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y);
wlr_output_layout_add(root->output_layout, wlr_output, oc->x, oc->y);
} else {
@ -551,6 +622,7 @@ static bool finalize_output_config(struct output_config *oc, struct sway_output
output->max_render_time = oc && oc->max_render_time > 0 ? oc->max_render_time : 0;
output->allow_tearing = oc && oc->allow_tearing > 0;
output->hdr = applied->image_description != NULL;
return true;
}
@ -775,10 +847,7 @@ static bool search_render_format(struct search_context *ctx, size_t output_idx)
const struct wlr_drm_format_set *primary_formats =
wlr_output_get_primary_formats(wlr_output, server.allocator->buffer_caps);
enum render_bit_depth needed_bits = RENDER_BIT_DEPTH_8;
if (cfg->config && cfg->config->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) {
needed_bits = cfg->config->render_bit_depth;
}
enum render_bit_depth needed_bits = get_config_render_bit_depth(cfg->config);
for (size_t idx = 0; fmts[idx] != DRM_FORMAT_INVALID; idx++) {
enum render_bit_depth format_bits = bit_depth_from_format(fmts[idx]);
if (needed_bits < format_bits) {
@ -933,9 +1002,10 @@ static bool apply_resolved_output_configs(struct matched_output_config *configs,
for (size_t idx = 0; idx < configs_len; idx++) {
struct matched_output_config *cfg = &configs[idx];
struct wlr_backend_output_state *backend_state = &states[idx];
sway_log(SWAY_DEBUG, "Finalizing config for %s",
cfg->output->wlr_output->name);
finalize_output_config(cfg->config, cfg->output);
finalize_output_config(cfg->config, cfg->output, &backend_state->base);
}
// Output layout being applied in finalize_output_config can shift outputs

View file

@ -37,7 +37,8 @@ bool criteria_is_empty(struct criteria *criteria) {
&& !criteria->pid
&& !criteria->sandbox_engine
&& !criteria->sandbox_app_id
&& !criteria->sandbox_instance_id;
&& !criteria->sandbox_instance_id
&& !criteria->tag;
}
// The error pointer is used for parsing functions, and saves having to pass it
@ -104,6 +105,7 @@ void criteria_destroy(struct criteria *criteria) {
pattern_destroy(criteria->sandbox_engine);
pattern_destroy(criteria->sandbox_app_id);
pattern_destroy(criteria->sandbox_instance_id);
pattern_destroy(criteria->tag);
free(criteria->target);
free(criteria->cmdlist);
free(criteria->raw);
@ -314,6 +316,26 @@ static bool criteria_matches_view(struct criteria *criteria,
}
}
if (criteria->tag) {
const char *tag = view_get_tag(view);
if (!tag) {
return false;
}
switch (criteria->tag->match_type) {
case PATTERN_FOCUSED:
if (focused && lenient_strcmp(tag, view_get_tag(focused))) {
return false;
}
break;
case PATTERN_PCRE2:
if (regex_cmp(tag, criteria->tag->regex) < 0) {
return false;
}
break;
}
}
if (!criteria_matches_container(criteria, view->container)) {
return false;
}
@ -544,6 +566,7 @@ enum criteria_token {
T_SANDBOX_ENGINE,
T_SANDBOX_APP_ID,
T_SANDBOX_INSTANCE_ID,
T_TAG,
T_INVALID,
};
@ -589,6 +612,8 @@ static enum criteria_token token_from_name(char *name) {
return T_SANDBOX_APP_ID;
} else if (strcmp(name, "sandbox_instance_id") == 0) {
return T_SANDBOX_INSTANCE_ID;
} else if (strcmp(name, "tag") == 0) {
return T_TAG;
}
return T_INVALID;
}
@ -700,6 +725,9 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) {
case T_SANDBOX_INSTANCE_ID:
pattern_create(&criteria->sandbox_instance_id, value);
break;
case T_TAG:
pattern_create(&criteria->tag, value);
break;
case T_INVALID:
break;
}

View file

@ -216,14 +216,6 @@ static struct sway_layer_surface *find_mapped_layer_by_client(
return NULL;
}
static void handle_output_destroy(struct wl_listener *listener, void *data) {
struct sway_layer_surface *layer =
wl_container_of(listener, layer, output_destroy);
layer->output = NULL;
wlr_layer_surface_v1_destroy(layer->layer_surface);
}
static void handle_node_destroy(struct wl_listener *listener, void *data) {
struct sway_layer_surface *layer =
wl_container_of(listener, layer, node_destroy);
@ -257,10 +249,10 @@ static void handle_node_destroy(struct wl_listener *listener, void *data) {
wl_list_remove(&layer->surface_commit.link);
wl_list_remove(&layer->node_destroy.link);
wl_list_remove(&layer->new_popup.link);
wl_list_remove(&layer->output_destroy.link);
layer->layer_surface->data = NULL;
wl_list_remove(&layer->link);
free(layer);
}
@ -269,12 +261,8 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
wl_container_of(listener, surface, surface_commit);
struct wlr_layer_surface_v1 *layer_surface = surface->layer_surface;
if (!layer_surface->initialized) {
return;
}
uint32_t committed = layer_surface->current.committed;
if (committed & WLR_LAYER_SURFACE_V1_STATE_LAYER) {
if (layer_surface->initialized && committed & WLR_LAYER_SURFACE_V1_STATE_LAYER) {
enum zwlr_layer_shell_v1_layer layer_type = layer_surface->current.layer;
struct wlr_scene_tree *output_layer = sway_layer_get_scene(
surface->output, layer_type);
@ -479,6 +467,7 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
}
surface->output = output;
wl_list_insert(&output->layer_surfaces, &surface->link);
// now that the surface's output is known, we can advertise its scale
wlr_fractional_scale_v1_notify_scale(surface->layer_surface->surface,
@ -496,9 +485,14 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
surface->new_popup.notify = handle_new_popup;
wl_signal_add(&layer_surface->events.new_popup, &surface->new_popup);
surface->output_destroy.notify = handle_output_destroy;
wl_signal_add(&output->events.disable, &surface->output_destroy);
surface->node_destroy.notify = handle_node_destroy;
wl_signal_add(&scene_surface->tree->node.events.destroy, &surface->node_destroy);
}
void destroy_layers(struct sway_output *output) {
struct sway_layer_surface *layer, *layer_tmp;
wl_list_for_each_safe(layer, layer_tmp, &output->layer_surfaces, link) {
layer->output = NULL;
wlr_layer_surface_v1_destroy(layer->layer_surface);
}
}

View file

@ -97,11 +97,11 @@ struct buffer_timer {
};
static int handle_buffer_timer(void *data) {
struct wlr_scene_buffer *buffer = data;
struct wlr_scene_surface *scene_surface = data;
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
wlr_scene_buffer_send_frame_done(buffer, &now);
wlr_scene_surface_send_frame_done(scene_surface, &now);
return 0;
}
@ -114,7 +114,9 @@ static void handle_buffer_timer_destroy(struct wl_listener *listener,
free(timer);
}
static struct buffer_timer *buffer_timer_get_or_create(struct wlr_scene_buffer *buffer) {
static struct buffer_timer *buffer_timer_get_or_create(struct wlr_scene_surface *scene_surface) {
struct wlr_scene_buffer *buffer = scene_surface->buffer;
struct buffer_timer *timer =
scene_descriptor_try_get(&buffer->node, SWAY_SCENE_DESC_BUFFER_TIMER);
if (timer) {
@ -127,7 +129,7 @@ static struct buffer_timer *buffer_timer_get_or_create(struct wlr_scene_buffer *
}
timer->frame_done_timer = wl_event_loop_add_timer(server.wl_event_loop,
handle_buffer_timer, buffer);
handle_buffer_timer, scene_surface);
if (!timer->frame_done_timer) {
free(timer);
return NULL;
@ -151,6 +153,11 @@ static void send_frame_done_iterator(struct wlr_scene_buffer *buffer,
return;
}
struct wlr_scene_surface *scene_surface = wlr_scene_surface_try_from_buffer(buffer);
if (scene_surface == NULL) {
return;
}
struct wlr_scene_node *current = &buffer->node;
while (true) {
struct sway_view *view = scene_descriptor_try_get(current,
@ -173,13 +180,13 @@ static void send_frame_done_iterator(struct wlr_scene_buffer *buffer,
struct buffer_timer *timer = NULL;
if (output->max_render_time != 0 && view_max_render_time != 0 && delay > 0) {
timer = buffer_timer_get_or_create(buffer);
timer = buffer_timer_get_or_create(scene_surface);
}
if (timer) {
wl_event_source_timer_update(timer->frame_done_timer, delay);
} else {
wlr_scene_buffer_send_frame_done(buffer, &data->when);
wlr_scene_surface_send_frame_done(scene_surface, &data->when);
}
}
@ -422,13 +429,6 @@ void force_modeset(void) {
}
static void begin_destroy(struct sway_output *output) {
if (output->enabled) {
output_disable(output);
}
output_begin_destroy(output);
wl_list_remove(&output->link);
wl_list_remove(&output->layout_destroy.link);
wl_list_remove(&output->destroy.link);
@ -436,8 +436,17 @@ static void begin_destroy(struct sway_output *output) {
wl_list_remove(&output->frame.link);
wl_list_remove(&output->request_state.link);
// Remove the scene_output first to ensure that the scene does not emit
// events for this output.
wlr_scene_output_destroy(output->scene_output);
output->scene_output = NULL;
if (output->enabled) {
output_disable(output);
}
output_begin_destroy(output);
wl_list_remove(&output->link);
output->wlr_output->data = NULL;
output->wlr_output = NULL;

View file

@ -309,6 +309,7 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
arrange_title_bar(child, title_offset, -title_bar_height,
next_title_offset - title_offset, title_bar_height);
wlr_scene_node_set_enabled(&child->border.tree->node, activated);
wlr_scene_node_set_enabled(&child->scene_tree->node, true);
wlr_scene_node_set_position(&child->scene_tree->node, 0, title_bar_height);
wlr_scene_node_reparent(&child->scene_tree->node, content);
@ -338,10 +339,11 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
arrange_title_bar(child, 0, y - title_height, width, title_bar_height);
wlr_scene_node_set_enabled(&child->border.tree->node, activated);
wlr_scene_node_set_enabled(&child->scene_tree->node, true);
wlr_scene_node_set_position(&child->scene_tree->node, 0, title_height);
wlr_scene_node_reparent(&child->scene_tree->node, content);
int net_height = height - title_bar_height;
int net_height = height - title_height;
if (activated && width > 0 && net_height > 0) {
arrange_container(child, width, net_height, title_bar_height == 0, 0);
} else {
@ -532,6 +534,7 @@ static void arrange_workspace_floating(struct sway_workspace *ws) {
wlr_scene_node_set_position(&floater->scene_tree->node,
floater->current.x, floater->current.y);
wlr_scene_node_set_enabled(&floater->scene_tree->node, true);
wlr_scene_node_set_enabled(&floater->border.tree->node, true);
arrange_container(floater, floater->current.width, floater->current.height,
true, ws->gaps_inner);
@ -584,15 +587,16 @@ static void arrange_output(struct sway_output *output, int width, int height) {
wlr_scene_node_set_enabled(&child->layers.tiling->node, !fs);
wlr_scene_node_set_enabled(&child->layers.fullscreen->node, fs);
arrange_workspace_floating(child);
wlr_scene_node_set_enabled(&output->layers.shell_background->node, !fs);
wlr_scene_node_set_enabled(&output->layers.shell_bottom->node, !fs);
wlr_scene_node_set_enabled(&output->layers.fullscreen->node, fs);
if (fs) {
disable_workspace(child);
wlr_scene_rect_set_size(output->fullscreen_background, width, height);
arrange_workspace_floating(child);
arrange_fullscreen(child->layers.fullscreen, fs, child,
width, height);
} else {
@ -605,6 +609,7 @@ static void arrange_output(struct sway_output *output, int width, int height) {
arrange_workspace_tiling(child,
area->width - gaps->left - gaps->right,
area->height - gaps->top - gaps->bottom);
arrange_workspace_floating(child);
}
} else {
wlr_scene_node_set_enabled(&child->layers.tiling->node, false);
@ -662,6 +667,13 @@ static void arrange_root(struct sway_root *root) {
wlr_scene_output_set_position(output->scene_output, output->lx, output->ly);
// disable all workspaces to get to a known state
for (int j = 0; j < output->current.workspaces->length; j++) {
struct sway_workspace *workspace = output->current.workspaces->items[j];
disable_workspace(workspace);
}
// arrange the active workspace
if (ws) {
arrange_workspace_floating(ws);
}

View file

@ -3,6 +3,7 @@
#include <stdlib.h>
#include <wayland-server-core.h>
#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/types/wlr_xdg_toplevel_tag_v1.h>
#include <wlr/util/edges.h>
#include "log.h"
#include "sway/decoration.h"
@ -20,13 +21,13 @@
static struct sway_xdg_popup *popup_create(
struct wlr_xdg_popup *wlr_popup, struct sway_view *view,
struct wlr_scene_tree *parent);
struct wlr_scene_tree *parent, struct wlr_scene_tree *image_capture_parent);
static void popup_handle_new_popup(struct wl_listener *listener, void *data) {
struct sway_xdg_popup *popup =
wl_container_of(listener, popup, new_popup);
struct wlr_xdg_popup *wlr_popup = data;
popup_create(wlr_popup, popup->view, popup->xdg_surface_tree);
popup_create(wlr_popup, popup->view, popup->xdg_surface_tree, popup->image_capture_tree);
}
static void popup_handle_destroy(struct wl_listener *listener, void *data) {
@ -77,7 +78,8 @@ static void popup_handle_reposition(struct wl_listener *listener, void *data) {
}
static struct sway_xdg_popup *popup_create(struct wlr_xdg_popup *wlr_popup,
struct sway_view *view, struct wlr_scene_tree *parent) {
struct sway_view *view, struct wlr_scene_tree *parent,
struct wlr_scene_tree *image_capture_parent) {
struct wlr_xdg_surface *xdg_surface = wlr_popup->base;
struct sway_xdg_popup *popup = calloc(1, sizeof(struct sway_xdg_popup));
@ -113,6 +115,11 @@ static struct sway_xdg_popup *popup_create(struct wlr_xdg_popup *wlr_popup,
return NULL;
}
popup->image_capture_tree = wlr_scene_xdg_surface_create(image_capture_parent, xdg_surface);
if (popup->image_capture_tree == NULL) {
return NULL;
}
popup->wlr_xdg_popup = xdg_surface->popup;
struct sway_xdg_shell_view *shell_view =
wl_container_of(view, shell_view, view);
@ -151,7 +158,8 @@ static void get_constraints(struct sway_view *view, double *min_width,
static const char *get_string_prop(struct sway_view *view,
enum sway_view_prop prop) {
if (xdg_shell_view_from_view(view) == NULL) {
struct sway_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view);
if (xdg_shell_view == NULL) {
return NULL;
}
switch (prop) {
@ -159,6 +167,8 @@ static const char *get_string_prop(struct sway_view *view,
return view->wlr_xdg_toplevel->title;
case VIEW_PROP_APP_ID:
return view->wlr_xdg_toplevel->app_id;
case VIEW_PROP_TAG:
return xdg_shell_view->tag;
default:
return NULL;
}
@ -259,6 +269,7 @@ static void destroy(struct sway_view *view) {
if (xdg_shell_view == NULL) {
return;
}
free(xdg_shell_view->tag);
free(xdg_shell_view);
}
@ -290,7 +301,7 @@ static void handle_commit(struct wl_listener *listener, void *data) {
// XXX: https://github.com/swaywm/sway/issues/2176
wlr_xdg_surface_schedule_configure(xdg_surface);
wlr_xdg_toplevel_set_wm_capabilities(view->wlr_xdg_toplevel,
XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
// TODO: wlr_xdg_toplevel_set_bounds()
return;
}
@ -359,7 +370,7 @@ static void handle_new_popup(struct wl_listener *listener, void *data) {
struct wlr_xdg_popup *wlr_popup = data;
struct sway_xdg_popup *popup = popup_create(wlr_popup,
&xdg_shell_view->view, root->layers.popup);
&xdg_shell_view->view, root->layers.popup, xdg_shell_view->image_capture_tree);
if (!popup) {
return;
}
@ -570,6 +581,17 @@ void handle_xdg_shell_toplevel(struct wl_listener *listener, void *data) {
wl_signal_add(&xdg_toplevel->events.destroy, &xdg_shell_view->destroy);
wlr_scene_xdg_surface_create(xdg_shell_view->view.content_tree, xdg_toplevel->base);
xdg_shell_view->image_capture_tree =
wlr_scene_xdg_surface_create(&xdg_shell_view->view.image_capture_scene->tree, xdg_toplevel->base);
xdg_toplevel->base->data = xdg_shell_view;
}
void xdg_toplevel_tag_manager_v1_handle_set_tag(struct wl_listener *listener, void *data) {
const struct wlr_xdg_toplevel_tag_manager_v1_set_tag_event *event = data;
struct sway_view *view = view_from_wlr_xdg_surface(event->toplevel->base);
struct sway_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view);
free(xdg_shell_view->tag);
xdg_shell_view->tag = strdup(event->tag);
view_execute_criteria(view);
}

View file

@ -497,6 +497,9 @@ static void handle_unmap(struct wl_listener *listener, void *data) {
wl_list_remove(&xwayland_view->commit.link);
wl_list_remove(&xwayland_view->surface_tree_destroy.link);
wlr_scene_node_destroy(&xwayland_view->image_capture_scene_surface->buffer->node);
xwayland_view->image_capture_scene_surface = NULL;
if (xwayland_view->surface_tree) {
wlr_scene_node_destroy(&xwayland_view->surface_tree->node);
xwayland_view->surface_tree = NULL;
@ -537,6 +540,9 @@ static void handle_map(struct wl_listener *listener, void *data) {
&xwayland_view->surface_tree_destroy);
}
xwayland_view->image_capture_scene_surface =
wlr_scene_surface_create(&xwayland_view->view.image_capture_scene->tree, xsurface->surface);
transaction_commit_dirty();
}

View file

@ -32,12 +32,6 @@
#include "sway/tree/workspace.h"
#include "wlr-layer-shell-unstable-v1-protocol.h"
static uint32_t get_current_time_msec(void) {
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
return now.tv_sec * 1000 + now.tv_nsec / 1000000;
}
/**
* Returns the node at the cursor's position. If there is a surface at that
* location, it is stored in **surface (it may not be a view).
@ -144,7 +138,7 @@ struct sway_node *node_at_coords(
}
void cursor_rebase(struct sway_cursor *cursor) {
uint32_t time_msec = get_current_time_msec();
uint32_t time_msec = get_current_time_in_msec();
seatop_rebase(cursor->seat, time_msec);
}
@ -359,7 +353,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
struct wlr_input_device *device, uint32_t time_msec, uint32_t button,
enum wl_pointer_button_state state) {
if (time_msec == 0) {
time_msec = get_current_time_msec();
time_msec = get_current_time_in_msec();
}
seatop_button(cursor->seat, time_msec, device, button, state);
@ -584,6 +578,7 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor,
} else {
wlr_tablet_v2_tablet_tool_notify_proximity_out(tool->tablet_v2_tool);
pointer_motion(cursor, time_msec, input_device->wlr_device, dx, dy, dx, dy);
wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
}
}

View file

@ -980,10 +980,10 @@ static void sway_keyboard_group_add(struct sway_keyboard *keyboard) {
wl_signal_add(&sway_group->wlr_group->keyboard.events.modifiers,
&sway_group->keyboard_modifiers);
sway_group->keyboard_modifiers.notify = handle_keyboard_group_modifiers;
wl_signal_add(&sway_group->wlr_group->events.enter, &sway_group->enter);
sway_group->enter.notify = handle_keyboard_group_enter;
wl_signal_add(&sway_group->wlr_group->events.leave, &sway_group->leave);
sway_group->leave.notify = handle_keyboard_group_leave;
return;

View file

@ -272,10 +272,6 @@ bool sway_input_configure_libinput_device(struct sway_input_device *input_device
}
if (ic->drag_lock != INT_MIN) {
changed |= set_tap_drag_lock(device, ic->drag_lock);
} else {
#if HAVE_LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY
changed |= set_tap_drag_lock(device, LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY);
#endif
}
if (ic->pointer_accel != FLT_MIN) {
changed |= set_accel_speed(device, ic->pointer_accel);
@ -358,12 +354,8 @@ void sway_input_reset_libinput_device(struct sway_input_device *input_device) {
libinput_device_config_tap_get_default_button_map(device));
changed |= set_tap_drag(device,
libinput_device_config_tap_get_default_drag_enabled(device));
#if HAVE_LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY
changed |= set_tap_drag_lock(device, LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY);
#else
changed |= set_tap_drag_lock(device,
libinput_device_config_tap_get_default_drag_lock_enabled(device));
#endif
changed |= set_accel_speed(device,
libinput_device_config_accel_get_default_speed(device));
changed |= set_rotation_angle(device,
@ -399,6 +391,19 @@ void sway_input_reset_libinput_device(struct sway_input_device *input_device) {
}
}
static bool sway_udev_device_is_builtin(struct udev_device *udev_device) {
const char *id_path = udev_device_get_property_value(udev_device, "ID_PATH");
if (!id_path) {
return false;
}
if (has_prefix(id_path, "platform-")) {
return true;
}
return has_prefix(id_path, "pci-") && strstr(id_path, "-platform-");
}
bool sway_libinput_device_is_builtin(struct sway_input_device *sway_device) {
if (!wlr_input_device_is_libinput(sway_device->wlr_device)) {
return false;
@ -412,14 +417,7 @@ bool sway_libinput_device_is_builtin(struct sway_input_device *sway_device) {
return false;
}
const char *id_path = udev_device_get_property_value(udev_device, "ID_PATH");
if (!id_path) {
return false;
}
if (has_prefix(id_path, "platform-")) {
return true;
}
return has_prefix(id_path, "pci-") && strstr(id_path, "-platform-");
bool is_builtin = sway_udev_device_is_builtin(udev_device);
udev_device_unref(udev_device);
return is_builtin;
}

View file

@ -16,6 +16,7 @@
#include "sway/tree/view.h"
#include "sway/tree/workspace.h"
#include "log.h"
#include "util.h"
#if WLR_HAS_XWAYLAND
#include "sway/xwayland.h"
#endif
@ -793,7 +794,7 @@ static void handle_pointer_axis(struct sway_seat *seat,
if (!handled) {
wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec,
event->orientation, scroll_factor * event->delta,
event->orientation, scroll_factor * event->delta,
roundf(scroll_factor * event->delta_discrete), event->source,
event->relative_direction);
}
@ -1110,7 +1111,7 @@ static void handle_rebase(struct sway_seat *seat, uint32_t time_msec) {
cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
if (surface) {
if (seat_is_input_allowed(seat, surface)) {
if (seat_is_input_allowed(seat, surface) && !cursor->hidden) {
wlr_seat_pointer_notify_enter(seat->wlr_seat, surface, sx, sy);
wlr_seat_pointer_notify_motion(seat->wlr_seat, time_msec, sx, sy);
}
@ -1148,5 +1149,7 @@ void seatop_begin_default(struct sway_seat *seat) {
seat->seatop_impl = &seatop_impl;
seat->seatop_data = e;
seatop_rebase(seat, 0);
uint32_t time_msec = get_current_time_in_msec();
seatop_rebase(seat, time_msec);
}

View file

@ -100,6 +100,7 @@ static void handle_touch_down(struct sway_seat *seat,
if (focused_node) {
seat_set_focus(seat, focused_node);
transaction_commit_dirty();
}
}

View file

@ -42,23 +42,21 @@ static void handle_im_commit(struct wl_listener *listener, void *data) {
if (!text_input) {
return;
}
struct wlr_input_method_v2 *context = data;
assert(context == relay->input_method);
if (context->current.preedit.text) {
if (relay->input_method->current.preedit.text) {
wlr_text_input_v3_send_preedit_string(text_input->input,
context->current.preedit.text,
context->current.preedit.cursor_begin,
context->current.preedit.cursor_end);
relay->input_method->current.preedit.text,
relay->input_method->current.preedit.cursor_begin,
relay->input_method->current.preedit.cursor_end);
}
if (context->current.commit_text) {
if (relay->input_method->current.commit_text) {
wlr_text_input_v3_send_commit_string(text_input->input,
context->current.commit_text);
relay->input_method->current.commit_text);
}
if (context->current.delete.before_length
|| context->current.delete.after_length) {
if (relay->input_method->current.delete.before_length
|| relay->input_method->current.delete.after_length) {
wlr_text_input_v3_send_delete_surrounding_text(text_input->input,
context->current.delete.before_length,
context->current.delete.after_length);
relay->input_method->current.delete.before_length,
relay->input_method->current.delete.after_length);
}
wlr_text_input_v3_send_done(text_input->input);
}
@ -66,7 +64,7 @@ static void handle_im_commit(struct wl_listener *listener, void *data) {
static void handle_im_keyboard_grab_destroy(struct wl_listener *listener, void *data) {
struct sway_input_method_relay *relay = wl_container_of(listener, relay,
input_method_keyboard_grab_destroy);
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = relay->input_method->keyboard_grab;
struct wlr_seat *wlr_seat = keyboard_grab->input_method->seat;
wl_list_remove(&relay->input_method_keyboard_grab_destroy.link);
@ -110,8 +108,6 @@ static void text_input_set_pending_focused_surface(
static void handle_im_destroy(struct wl_listener *listener, void *data) {
struct sway_input_method_relay *relay = wl_container_of(listener, relay,
input_method_destroy);
struct wlr_input_method_v2 *context = data;
assert(context == relay->input_method);
wl_list_remove(&relay->input_method_commit.link);
wl_list_remove(&relay->input_method_grab_keyboard.link);
wl_list_remove(&relay->input_method_destroy.link);
@ -248,6 +244,10 @@ static void relay_send_im_state(struct sway_input_method_relay *relay,
static void handle_text_input_enable(struct wl_listener *listener, void *data) {
struct sway_text_input *text_input = wl_container_of(listener, text_input,
text_input_enable);
if (text_input->input->focused_surface == NULL) {
sway_log(SWAY_DEBUG, "Enabling text input, but no longer focused");
return;
}
if (text_input->relay->input_method == NULL) {
sway_log(SWAY_INFO, "Enabling text input when input method is gone");
return;
@ -260,6 +260,10 @@ static void handle_text_input_commit(struct wl_listener *listener,
void *data) {
struct sway_text_input *text_input = wl_container_of(listener, text_input,
text_input_commit);
if (text_input->input->focused_surface == NULL) {
sway_log(SWAY_DEBUG, "Unfocused text input tried to commit an update");
return;
}
if (!text_input->input->current_enabled) {
sway_log(SWAY_INFO, "Inactive text input tried to commit an update");
return;
@ -314,8 +318,6 @@ static void handle_pending_focused_surface_destroy(struct wl_listener *listener,
void *data) {
struct sway_text_input *text_input = wl_container_of(listener, text_input,
pending_focused_surface_destroy);
struct wlr_surface *surface = data;
assert(text_input->pending_focused_surface == surface);
text_input->pending_focused_surface = NULL;
wl_list_remove(&text_input->pending_focused_surface_destroy.link);
wl_list_init(&text_input->pending_focused_surface_destroy.link);
@ -632,7 +634,7 @@ void sway_input_method_relay_init(struct sway_seat *seat,
wl_list_init(&relay->input_popups);
relay->text_input_new.notify = relay_handle_text_input;
wl_signal_add(&server.text_input->events.text_input,
wl_signal_add(&server.text_input->events.new_text_input,
&relay->text_input_new);
relay->text_input_manager_destroy.notify = relay_handle_text_input_manager_destroy;
wl_signal_add(&server.text_input->events.destroy,
@ -640,7 +642,7 @@ void sway_input_method_relay_init(struct sway_seat *seat,
relay->input_method_new.notify = relay_handle_input_method;
wl_signal_add(
&server.input_method->events.input_method,
&server.input_method->events.new_input_method,
&relay->input_method_new);
relay->input_method_manager_destroy.notify = relay_handle_input_method_manager_destroy;
wl_signal_add(&server.input_method->events.destroy,

View file

@ -318,6 +318,14 @@ static void ipc_json_describe_wlr_output(struct wlr_output *wlr_output, json_obj
json_object_array_add(modes_array, mode_object);
}
json_object_object_add(object, "modes", modes_array);
json_object *features_object = json_object_new_object();
json_object_object_add(features_object, "adaptive_sync",
json_object_new_boolean(wlr_output->adaptive_sync_supported ||
wlr_output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED));
json_object_object_add(features_object, "hdr",
json_object_new_boolean(output_supports_hdr(wlr_output, NULL)));
json_object_object_add(object, "features", features_object);
}
static void ipc_json_describe_output(struct sway_output *output,
@ -400,8 +408,8 @@ static void ipc_json_describe_enabled_output(struct sway_output *output,
}
json_object_object_add(object, "max_render_time", json_object_new_int(output->max_render_time));
json_object_object_add(object, "allow_tearing", json_object_new_boolean(output->allow_tearing));
json_object_object_add(object, "hdr", json_object_new_boolean(output->hdr));
}
json_object *ipc_json_describe_disabled_output(struct sway_output *output) {
@ -619,6 +627,9 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object
json_object_object_add(object, "sandbox_instance_id",
sandbox_instance_id ? json_object_new_string(sandbox_instance_id) : NULL);
const char *tag = view_get_tag(c->view);
json_object_object_add(object, "tag", tag ? json_object_new_string(tag) : NULL);
json_object *idle_inhibitors = json_object_new_object();
struct sway_idle_inhibitor_v1 *user_inhibitor =

View file

@ -108,20 +108,6 @@ static void log_kernel(void) {
pclose(f);
}
static bool detect_suid(void) {
if (geteuid() != 0 && getegid() != 0) {
return false;
}
if (getuid() == geteuid() && getgid() == getegid()) {
return false;
}
sway_log(SWAY_ERROR, "SUID operation is no longer supported, refusing to start. "
"This check will be removed in a future release.");
return true;
}
static void restore_nofile_limit(void) {
if (original_nofile_rlimit.rlim_cur == 0) {
return;
@ -292,11 +278,6 @@ int main(int argc, char **argv) {
}
}
// SUID operation is deprecated, so block it for now.
if (detect_suid()) {
exit(EXIT_FAILURE);
}
// Since wayland requires XDG_RUNTIME_DIR to be set, abort with just the
// clear error message (when not running as an IPC client).
if (!getenv("XDG_RUNTIME_DIR") && optind == argc) {

View file

@ -195,6 +195,7 @@ sway_sources = files(
'commands/output/disable.c',
'commands/output/dpms.c',
'commands/output/enable.c',
'commands/output/hdr.c',
'commands/output/max_render_time.c',
'commands/output/mode.c',
'commands/output/position.c',

View file

@ -10,6 +10,7 @@
#include <wlr/render/allocator.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_alpha_modifier_v1.h>
#include <wlr/types/wlr_color_management_v1.h>
#include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_content_type_v1.h>
#include <wlr/types/wlr_cursor_shape_v1.h>
@ -18,6 +19,7 @@
#include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_export_dmabuf_v1.h>
#include <wlr/types/wlr_ext_foreign_toplevel_list_v1.h>
#include <wlr/types/wlr_fixes.h>
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
#include <wlr/types/wlr_ext_image_capture_source_v1.h>
#include <wlr/types/wlr_ext_image_copy_capture_v1.h>
@ -48,6 +50,7 @@
#include <wlr/types/wlr_xdg_foreign_v1.h>
#include <wlr/types/wlr_xdg_foreign_v2.h>
#include <wlr/types/wlr_xdg_output_v1.h>
#include <wlr/types/wlr_xdg_toplevel_tag_v1.h>
#include <xf86drm.h>
#include "config.h"
#include "list.h"
@ -232,6 +235,21 @@ static void handle_renderer_lost(struct wl_listener *listener, void *data) {
server->recreating_renderer = wl_event_loop_add_idle(server->wl_event_loop, do_renderer_recreate, server);
}
static void handle_new_foreign_toplevel_capture_request(struct wl_listener *listener, void *data) {
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request *request = data;
struct sway_view *view = request->toplevel_handle->data;
if (view->image_capture_source == NULL) {
view->image_capture_source = wlr_ext_image_capture_source_v1_create_with_scene_node(
&view->image_capture_scene->tree.node, server.wl_event_loop, server.allocator, server.renderer);
if (view->image_capture_source == NULL) {
return;
}
}
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_accept(request, view->image_capture_source);
}
bool server_init(struct sway_server *server) {
sway_log(SWAY_DEBUG, "Initializing Wayland server");
server->wl_display = wl_display_create();
@ -240,6 +258,7 @@ bool server_init(struct sway_server *server) {
wl_display_set_global_filter(server->wl_display, filter_global, NULL);
wl_display_set_default_max_buffer_size(server->wl_display, 1024 * 1024);
wlr_fixes_create(server->wl_display, 1);
root = root_create(server->wl_display);
server->backend = wlr_backend_autocreate(server->wl_event_loop, &server->session);
@ -395,6 +414,12 @@ bool server_init(struct sway_server *server) {
wlr_content_type_manager_v1_create(server->wl_display, 1);
wlr_fractional_scale_manager_v1_create(server->wl_display, 1);
server->ext_foreign_toplevel_image_capture_source_manager_v1 =
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_create(server->wl_display, 1);
server->new_foreign_toplevel_capture_request.notify = handle_new_foreign_toplevel_capture_request;
wl_signal_add(&server->ext_foreign_toplevel_image_capture_source_manager_v1->events.new_request,
&server->new_foreign_toplevel_capture_request);
server->tearing_control_v1 =
wlr_tearing_control_manager_v1_create(server->wl_display, 1);
server->tearing_control_new_object.notify = handle_new_tearing_hint;
@ -417,11 +442,49 @@ bool server_init(struct sway_server *server) {
wl_signal_add(&server->xdg_activation_v1->events.new_token,
&server->xdg_activation_v1_new_token);
struct wlr_xdg_toplevel_tag_manager_v1 *xdg_toplevel_tag_manager_v1 =
wlr_xdg_toplevel_tag_manager_v1_create(server->wl_display, 1);
server->xdg_toplevel_tag_manager_v1_set_tag.notify =
xdg_toplevel_tag_manager_v1_handle_set_tag;
wl_signal_add(&xdg_toplevel_tag_manager_v1->events.set_tag,
&server->xdg_toplevel_tag_manager_v1_set_tag);
struct wlr_cursor_shape_manager_v1 *cursor_shape_manager =
wlr_cursor_shape_manager_v1_create(server->wl_display, 1);
server->request_set_cursor_shape.notify = handle_request_set_cursor_shape;
wl_signal_add(&cursor_shape_manager->events.request_set_shape, &server->request_set_cursor_shape);
if (server->renderer->features.input_color_transform) {
const enum wp_color_manager_v1_render_intent render_intents[] = {
WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL,
};
const enum wp_color_manager_v1_transfer_function transfer_functions[] = {
WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB,
WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ,
WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR,
WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA22,
WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_BT1886,
};
const enum wp_color_manager_v1_primaries primaries[] = {
WP_COLOR_MANAGER_V1_PRIMARIES_SRGB,
WP_COLOR_MANAGER_V1_PRIMARIES_BT2020,
};
struct wlr_color_manager_v1 *cm = wlr_color_manager_v1_create(
server->wl_display, 1, &(struct wlr_color_manager_v1_options){
.features = {
.parametric = true,
.set_mastering_display_primaries = true,
},
.render_intents = render_intents,
.render_intents_len = sizeof(render_intents) / sizeof(render_intents[0]),
.transfer_functions = transfer_functions,
.transfer_functions_len = sizeof(transfer_functions) / sizeof(transfer_functions[0]),
.primaries = primaries,
.primaries_len = sizeof(primaries) / sizeof(primaries[0]),
});
wlr_scene_set_color_manager_v1(root->root_scene, cm);
}
wl_list_init(&server->pending_launcher_ctxs);
// Avoid using "wayland-0" as display socket
@ -487,7 +550,9 @@ void server_fini(struct sway_server *server) {
wl_list_remove(&server->tearing_control_new_object.link);
wl_list_remove(&server->xdg_activation_v1_request_activate.link);
wl_list_remove(&server->xdg_activation_v1_new_token.link);
wl_list_remove(&server->xdg_toplevel_tag_manager_v1_set_tag.link);
wl_list_remove(&server->request_set_cursor_shape.link);
wl_list_remove(&server->new_foreign_toplevel_capture_request.link);
input_manager_finish(server->input);
// TODO: free sway-specific resources
@ -502,6 +567,7 @@ void server_fini(struct sway_server *server) {
wlr_backend_destroy(server->backend);
wl_display_destroy(server->wl_display);
list_free(server->dirty_nodes);
free(server->socket);
}
bool server_start(struct sway_server *server) {

View file

@ -244,6 +244,9 @@ following properties:
|- rect
: object
: The bounds for the output consisting of _x_, _y_, _width_, and _height_
|- hdr
: boolean
: Whether HDR is enabled
*Example Reply:*
@ -416,6 +419,10 @@ node and will have the following properties:
: string
: (Only windows) The instance ID provided by the associated sandbox engine (or
_null_)
|- tag
: string
: (Only windows) For an xdg-shell window, tag of the toplevel, if set.
Otherwise, _null_
|- window
: integer
: (Only xwayland windows) The X11 window ID for the xwayland window

View file

@ -196,9 +196,9 @@ must be separated by one space. For example:
screen tearing is allowed.
With immediate page flips, frames from the client are presented as soon
as possible instead of synchronizing with the monitor's vblank interval
(VSync).
as possible instead of synchronizing with the monitor's vblank interval
(VSync).
It is recommended to set *max_render_time* to *off*. In that case a page flip
happens as soon as a client updates. Otherwise, tearing will only happen if
rendering takes longer than the configured milliseconds before the next
@ -210,6 +210,17 @@ must be separated by one space. For example:
This setting only has effect when a window is fullscreen on the output.
*output* <name> hdr on|off|toggle
Enables or disables HDR (High Dynamic Range). HDR enables a larger color
gamut and brightness range. HDR uses the BT2020 primaries and the PQ
transfer function.
When HDR is enabled, _render_bit_depth_ is implicitly set to 10 unless
explicitly configured. Using a lower render bit depth may result in color
banding artifacts.
HDR needs to be supported by the output and renderer to be enabled.
# SEE ALSO
*sway*(5) *sway-input*(5)

View file

@ -228,8 +228,8 @@ set|plus|minus|toggle <amount>
regardless of the tearing hints.
This setting only has an effect if tearing is allowed on the output through
the per-output *allow_tearing* setting. See *sway-output*(5)
for further details.
the per-output *allow_tearing* setting. See *sway-output*(5) for further
details.
*move* left|right|up|down [<px> px]
Moves the focused container in the direction specified. The optional _px_
@ -302,28 +302,34 @@ set|plus|minus|toggle <amount>
*rename* workspace [<old_name>] to <new_name>
Rename either <old_name> or the focused workspace to the <new_name>
*resize* shrink|grow width|height [<amount> [px|ppt]]
*resize* shrink|grow up|right|down|left|width|height [<amount> [px|ppt]]
Resizes the currently focused container by _amount_, specified in pixels or
percentage points. If the units are omitted, floating containers are resized
in px and tiled containers by ppt. _amount_ will default to 10 if omitted.
For tiling containers, space is taken/given from the container in the
specified direction. If _width_ or _height_ is specified, space will be
taken/given from all other containers.
*resize* set height <height> [px|ppt]
Sets the height of the container to _height_, specified in pixels or
percentage points. If the units are omitted, floating containers are
resized in px and tiled containers by ppt. If _height_ is 0, the container
will not be resized.
will not be resized. For tiling containers, space is taken/given from all
other containers.
*resize* set [width] <width> [px|ppt]
Sets the width of the container to _width_, specified in pixels or
percentage points. If the units are omitted, floating containers are
resized in px and tiled containers by ppt. If _width_ is 0, the container
will not be resized.
will not be resized. For tiling containers, space is taken/given from all
other containers.
*resize* set [width] <width> [px|ppt] [height] <height> [px|ppt]
Sets the width and height of the container to _width_ and _height_,
specified in pixels or percentage points. If the units are omitted,
floating containers are resized in px and tiled containers by ppt. If
_width_ or _height_ is 0, the container will not be resized on that axis.
For tiling containers, space is taken/given from all other containers.
*scratchpad* show
Shows a window from the scratchpad. Repeatedly using this command will
@ -1055,6 +1061,9 @@ The following attributes may be matched with:
Can be a regular expression. If value is \_\_focused\_\_, then the shell
must be the same as that of the currently focused window.
*tag*
Compare value against the tag. _tag_ is specific to Wayland applications.
*tiling*
Matches tiling windows.

View file

@ -7,7 +7,6 @@
#include <wlr/types/wlr_linux_dmabuf_v1.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_subcompositor.h>
#include "linux-dmabuf-unstable-v1-protocol.h"
#include "sway/config.h"
#include "sway/desktop/transaction.h"
#include "sway/input/input-manager.h"
@ -547,8 +546,8 @@ void container_begin_destroy(struct sway_container *con) {
container_end_mouse_operation(con);
con->node.destroying = true;
node_set_dirty(&con->node);
con->node.destroying = true;
if (con->scratchpad) {
root_scratchpad_remove_container(con);

View file

@ -29,7 +29,7 @@ const char *node_type_to_str(enum sway_node_type type) {
}
void node_set_dirty(struct sway_node *node) {
if (node->dirty) {
if (node->dirty || node->destroying) {
return;
}
node->dirty = true;

View file

@ -37,7 +37,7 @@ static void restore_workspaces(struct sway_output *output) {
for (int j = 0; j < other->workspaces->length; j++) {
struct sway_workspace *ws = other->workspaces->items[j];
struct sway_output *highest =
workspace_output_get_highest_available(ws, NULL);
workspace_output_get_highest_available(ws);
if (highest == output) {
workspace_detach(ws);
output_add_workspace(output, ws);
@ -136,12 +136,11 @@ 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.disable);
wl_list_insert(&root->all_outputs, &output->link);
output->workspaces = create_list();
output->current.workspaces = create_list();
wl_list_init(&output->layer_surfaces);
return output;
}
@ -205,11 +204,8 @@ static void output_evacuate(struct sway_output *output) {
return;
}
struct sway_output *fallback_output = NULL;
if (root->outputs->length > 1) {
if (root->outputs->length > 0) {
fallback_output = root->outputs->items[0];
if (fallback_output == output) {
fallback_output = root->outputs->items[1];
}
}
while (output->workspaces->length) {
@ -218,7 +214,7 @@ static void output_evacuate(struct sway_output *output) {
workspace_detach(workspace);
struct sway_output *new_output =
workspace_output_get_highest_available(workspace, output);
workspace_output_get_highest_available(workspace);
if (!new_output) {
new_output = fallback_output;
}
@ -287,13 +283,15 @@ void output_disable(struct sway_output *output) {
}
sway_log(SWAY_DEBUG, "Disabling output '%s'", output->wlr_output->name);
wl_signal_emit_mutable(&output->events.disable, output);
output_evacuate(output);
// Remove the output now to avoid interacting with it during e.g.,
// transactions, as the output might be physically removed with the scene
// output destroyed.
list_del(root->outputs, index);
output->enabled = false;
destroy_layers(output);
output_evacuate(output);
}
void output_begin_destroy(struct sway_output *output) {
@ -303,8 +301,8 @@ void output_begin_destroy(struct sway_output *output) {
sway_log(SWAY_DEBUG, "Destroying output '%s'", output->wlr_output->name);
wl_signal_emit_mutable(&output->node.events.destroy, &output->node);
output->node.destroying = true;
node_set_dirty(&output->node);
output->node.destroying = true;
}
struct sway_output *output_from_wlr_output(struct wlr_output *output) {

View file

@ -199,6 +199,8 @@ void root_scratchpad_show(struct sway_container *con) {
if (old_ws) {
workspace_consider_destroy(old_ws);
}
container_raise_floating(con);
}
static void disable_fullscreen(struct sway_container *con, void *data) {
@ -212,9 +214,7 @@ void root_scratchpad_hide(struct sway_container *con) {
struct sway_node *focus = seat_get_focus_inactive(seat, &root->node);
struct sway_workspace *ws = con->pending.workspace;
if (con->pending.fullscreen_mode == FULLSCREEN_GLOBAL && !con->pending.workspace) {
// If the container was made fullscreen global while in the scratchpad,
// it should be shown until fullscreen has been disabled
if (!con->pending.workspace) {
return;
}

View file

@ -49,6 +49,11 @@ bool view_init(struct sway_view *view, enum sway_view_type type,
failed = true;
}
view->image_capture_scene = wlr_scene_create();
if (view->image_capture_scene == NULL) {
failed = true;
}
if (failed) {
wlr_scene_node_destroy(&view->scene_tree->node);
return false;
@ -81,6 +86,7 @@ void view_destroy(struct sway_view *view) {
list_free(view->executed_criteria);
view_assign_ctx(view, NULL);
wlr_scene_node_destroy(&view->image_capture_scene->tree.node);
wlr_scene_node_destroy(&view->scene_tree->node);
if (view->impl->destroy) {
view->impl->destroy(view);
@ -184,6 +190,13 @@ const char *view_get_sandbox_instance_id(struct sway_view *view) {
return security_context ? security_context->instance_id : NULL;
}
const char *view_get_tag(struct sway_view *view) {
if (view->impl->get_string_prop) {
return view->impl->get_string_prop(view, VIEW_PROP_TAG);
}
return NULL;
}
const char *view_get_shell(struct sway_view *view) {
switch(view->type) {
case SWAY_VIEW_XDG_SHELL:
@ -517,10 +530,12 @@ void view_execute_criteria(struct sway_view *view) {
sway_log(SWAY_DEBUG, "for_window '%s' matches view %p, cmd: '%s'",
criteria->raw, view, criteria->cmdlist);
list_add(view->executed_criteria, criteria);
list_t *res_list = execute_command(
criteria->cmdlist, NULL, view->container);
list_t *res_list = execute_command(criteria->cmdlist, NULL, view->container);
while (res_list->length) {
struct cmd_results *res = res_list->items[0];
if (res->status != CMD_SUCCESS) {
sway_log(SWAY_ERROR, "for_window '%s' failed: %s", criteria->raw, res->error);
}
free_cmd_results(res);
list_del(res_list, 0);
}
@ -813,6 +828,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
};
view->ext_foreign_toplevel =
wlr_ext_foreign_toplevel_handle_v1_create(server.foreign_toplevel_list, &foreign_toplevel_state);
view->ext_foreign_toplevel->data = view;
view->foreign_toplevel =
wlr_foreign_toplevel_handle_v1_create(server.foreign_toplevel_manager);
@ -1190,6 +1206,10 @@ static void view_save_buffer_iterator(struct wlr_scene_buffer *buffer,
wlr_scene_buffer_set_dest_size(sbuf,
buffer->dst_width, buffer->dst_height);
wlr_scene_buffer_set_opaque_region(sbuf, &buffer->opaque_region);
wlr_scene_buffer_set_opacity(sbuf, buffer->opacity);
wlr_scene_buffer_set_filter_mode(sbuf, buffer->filter_mode);
wlr_scene_buffer_set_transfer_function(sbuf, buffer->transfer_function);
wlr_scene_buffer_set_primaries(sbuf, buffer->primaries);
wlr_scene_buffer_set_source_box(sbuf, &buffer->src_box);
wlr_scene_node_set_position(&sbuf->node, sx, sy);
wlr_scene_buffer_set_transform(sbuf, buffer->transform);
@ -1240,7 +1260,11 @@ bool view_can_tear(struct sway_view *view) {
static void send_frame_done_iterator(struct wlr_scene_buffer *scene_buffer,
int x, int y, void *data) {
struct timespec *when = data;
wl_signal_emit_mutable(&scene_buffer->events.frame_done, when);
struct wlr_scene_surface *scene_surface = wlr_scene_surface_try_from_buffer(scene_buffer);
if (scene_surface == NULL) {
return;
}
wlr_surface_send_frame_done(scene_surface->surface, when);
}
void view_send_frame_done(struct sway_view *view) {

View file

@ -166,8 +166,8 @@ void workspace_begin_destroy(struct sway_workspace *workspace) {
if (workspace->output) {
workspace_detach(workspace);
}
workspace->node.destroying = true;
node_set_dirty(&workspace->node);
workspace->node.destroying = true;
}
void workspace_consider_destroy(struct sway_workspace *ws) {
@ -659,13 +659,9 @@ void workspace_output_add_priority(struct sway_workspace *workspace,
}
struct sway_output *workspace_output_get_highest_available(
struct sway_workspace *ws, struct sway_output *exclude) {
struct sway_workspace *ws) {
for (int i = 0; i < ws->output_priority->length; i++) {
const char *name = ws->output_priority->items[i];
if (exclude && output_match_name_or_id(exclude, name)) {
continue;
}
struct sway_output *output = output_by_name_or_id(name);
if (output) {
return output;

View file

@ -13,7 +13,6 @@
#include "swaybar/ipc.h"
#include "swaybar/render.h"
#include "swaybar/status_line.h"
#include "log.h"
#if HAVE_TRAY
#include "swaybar/tray/tray.h"
#endif
@ -21,7 +20,7 @@
static const int WS_HORIZONTAL_PADDING = 5;
static const double WS_VERTICAL_PADDING = 1.5;
static const double BORDER_WIDTH = 1;
static const int BORDER_WIDTH = 1;
struct render_context {
cairo_t *cairo;
@ -541,6 +540,63 @@ static uint32_t render_status_line(struct render_context *ctx, double *x) {
return 0;
}
static struct box_size render_box(struct render_context *ctx, double x,
struct box_colors colors, const char *label, bool pango_markup) {
struct swaybar_output *output = ctx->output;
struct swaybar_config *config = output->bar->config;
cairo_t *cairo = ctx->cairo;
int text_width, text_height;
get_text_size(cairo, config->font_description, &text_width, &text_height, NULL,
1, pango_markup, "%s", label);
uint32_t width = text_width + WS_HORIZONTAL_PADDING * 2 + BORDER_WIDTH * 2;
if (width < config->workspace_min_width) {
width = config->workspace_min_width;
}
uint32_t ideal_height = text_height + WS_VERTICAL_PADDING * 2
+ BORDER_WIDTH * 2;
uint32_t ideal_surface_height = ideal_height;
if (!output->bar->config->height &&
output->height < ideal_surface_height) {
return (struct box_size) {
.width = width,
.height = ideal_surface_height,
};
}
uint32_t height = output->height;
cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
cairo_set_source_u32(cairo, colors.background);
ctx->background_color = colors.background;
ctx->has_transparency |= (colors.background & 0xFF) != 0xFF;
cairo_rectangle(cairo, x, 0, width, height);
cairo_fill(cairo);
cairo_set_source_u32(cairo, colors.border);
cairo_rectangle(cairo, x, 0, width, BORDER_WIDTH);
cairo_fill(cairo);
cairo_rectangle(cairo, x, 0, BORDER_WIDTH, height);
cairo_fill(cairo);
cairo_rectangle(cairo, x + width - BORDER_WIDTH, 0, BORDER_WIDTH, height);
cairo_fill(cairo);
cairo_rectangle(cairo, x, height - BORDER_WIDTH, width, BORDER_WIDTH);
cairo_fill(cairo);
double text_y = height / 2.0 - text_height / 2.0;
cairo_set_source_u32(cairo, colors.text);
cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y));
choose_text_aa_mode(ctx, colors.text);
render_text(cairo, config->font_description, 1, pango_markup,
"%s", label);
return (struct box_size) {
.width = width,
.height = output->height,
};
}
static uint32_t render_binding_mode_indicator(struct render_context *ctx,
double x) {
struct swaybar_output *output = ctx->output;
@ -549,54 +605,9 @@ static uint32_t render_binding_mode_indicator(struct render_context *ctx,
return 0;
}
cairo_t *cairo = ctx->cairo;
struct swaybar_config *config = output->bar->config;
int text_width, text_height;
get_text_size(cairo, config->font_description, &text_width, &text_height, NULL,
1, output->bar->mode_pango_markup,
"%s", mode);
int ws_vertical_padding = WS_VERTICAL_PADDING;
int ws_horizontal_padding = WS_HORIZONTAL_PADDING;
int border_width = BORDER_WIDTH;
uint32_t ideal_height = text_height + ws_vertical_padding * 2
+ border_width * 2;
uint32_t ideal_surface_height = ideal_height;
if (!output->bar->config->height &&
output->height < ideal_surface_height) {
return ideal_surface_height;
}
uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2;
if (width < config->workspace_min_width) {
width = config->workspace_min_width;
}
uint32_t height = output->height;
cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
cairo_set_source_u32(cairo, config->colors.binding_mode.background);
ctx->background_color = config->colors.binding_mode.background;
ctx->has_transparency |= (config->colors.binding_mode.background & 0xFF) != 0xFF;
cairo_rectangle(cairo, x, 0, width, height);
cairo_fill(cairo);
cairo_set_source_u32(cairo, config->colors.binding_mode.border);
cairo_rectangle(cairo, x, 0, width, border_width);
cairo_fill(cairo);
cairo_rectangle(cairo, x, 0, border_width, height);
cairo_fill(cairo);
cairo_rectangle(cairo, x + width - border_width, 0, border_width, height);
cairo_fill(cairo);
cairo_rectangle(cairo, x, height - border_width, width, border_width);
cairo_fill(cairo);
double text_y = height / 2.0 - text_height / 2.0;
cairo_set_source_u32(cairo, config->colors.binding_mode.text);
cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y));
choose_text_aa_mode(ctx, config->colors.binding_mode.text);
render_text(cairo, config->font_description, 1, output->bar->mode_pango_markup,
"%s", mode);
return output->height;
struct box_size size = render_box(ctx, x, output->bar->config->colors.binding_mode,
mode, output->bar->mode_pango_markup);
return size.height;
}
static enum hotspot_event_handling workspace_hotspot_callback(
@ -618,6 +629,7 @@ static uint32_t render_workspace_button(struct render_context *ctx,
struct swaybar_workspace *ws, double *x) {
struct swaybar_output *output = ctx->output;
struct swaybar_config *config = output->bar->config;
struct box_colors box_colors;
if (ws->urgent) {
box_colors = config->colors.urgent_workspace;
@ -629,66 +641,21 @@ static uint32_t render_workspace_button(struct render_context *ctx,
box_colors = config->colors.inactive_workspace;
}
uint32_t height = output->height;
cairo_t *cairo = ctx->cairo;
int text_width, text_height;
get_text_size(cairo, config->font_description, &text_width, &text_height, NULL,
1, config->pango_markup, "%s", ws->label);
int ws_vertical_padding = WS_VERTICAL_PADDING;
int ws_horizontal_padding = WS_HORIZONTAL_PADDING;
int border_width = BORDER_WIDTH;
uint32_t ideal_height = ws_vertical_padding * 2 + text_height
+ border_width * 2;
uint32_t ideal_surface_height = ideal_height;
if (!output->bar->config->height &&
output->height < ideal_surface_height) {
return ideal_surface_height;
}
uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2;
if (width < config->workspace_min_width) {
width = config->workspace_min_width;
}
cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
cairo_set_source_u32(cairo, box_colors.background);
ctx->background_color = box_colors.background;
ctx->has_transparency |= (box_colors.background & 0xFF) != 0xFF;
cairo_rectangle(cairo, *x, 0, width, height);
cairo_fill(cairo);
cairo_set_source_u32(cairo, box_colors.border);
cairo_rectangle(cairo, *x, 0, width, border_width);
cairo_fill(cairo);
cairo_rectangle(cairo, *x, 0, border_width, height);
cairo_fill(cairo);
cairo_rectangle(cairo, *x + width - border_width, 0, border_width, height);
cairo_fill(cairo);
cairo_rectangle(cairo, *x, height - border_width, width, border_width);
cairo_fill(cairo);
double text_y = height / 2.0 - text_height / 2.0;
cairo_set_source_u32(cairo, box_colors.text);
cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y));
choose_text_aa_mode(ctx, box_colors.text);
render_text(cairo, config->font_description, 1, config->pango_markup,
"%s", ws->label);
struct box_size size = render_box(ctx, *x, box_colors,
ws->label, config->pango_markup);
struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot));
hotspot->x = *x;
hotspot->y = 0;
hotspot->width = width;
hotspot->height = height;
hotspot->width = size.width;
hotspot->height = size.height;
hotspot->callback = workspace_hotspot_callback;
hotspot->destroy = free;
hotspot->data = strdup(ws->name);
wl_list_insert(&output->hotspots, &hotspot->link);
*x += width;
return output->height;
*x += size.width;
return size.height;
}
static uint32_t render_to_cairo(struct render_context *ctx) {

View file

@ -189,7 +189,8 @@ static void pretty_print_output(json_object *o) {
json_object_object_get_ex(o, "current_workspace", &ws);
json_object_object_get_ex(o, "non_desktop", &non_desktop);
json_object *make, *model, *serial, *scale, *scale_filter, *subpixel,
*transform, *max_render_time, *adaptive_sync_status, *allow_tearing;
*transform, *max_render_time, *adaptive_sync_status, *allow_tearing,
*hdr;
json_object_object_get_ex(o, "make", &make);
json_object_object_get_ex(o, "model", &model);
json_object_object_get_ex(o, "serial", &serial);
@ -200,6 +201,7 @@ static void pretty_print_output(json_object *o) {
json_object_object_get_ex(o, "max_render_time", &max_render_time);
json_object_object_get_ex(o, "adaptive_sync_status", &adaptive_sync_status);
json_object_object_get_ex(o, "allow_tearing", &allow_tearing);
json_object_object_get_ex(o, "hdr", &hdr);
json_object *x, *y;
json_object_object_get_ex(rect, "x", &x);
json_object_object_get_ex(rect, "y", &y);
@ -210,6 +212,10 @@ static void pretty_print_output(json_object *o) {
json_object_object_get_ex(current_mode, "width", &width);
json_object_object_get_ex(current_mode, "height", &height);
json_object_object_get_ex(current_mode, "refresh", &refresh);
json_object *features, *features_adaptive_sync, *features_hdr;
json_object_object_get_ex(o, "features", &features);
json_object_object_get_ex(features, "adaptive_sync", &features_adaptive_sync);
json_object_object_get_ex(features, "hdr", &features_hdr);
if (json_object_get_boolean(non_desktop)) {
printf(
@ -252,10 +258,18 @@ static void pretty_print_output(json_object *o) {
printf(max_render_time_int == 0 ? "off\n" : "%d ms\n", max_render_time_int);
printf(" Adaptive sync: %s\n",
json_object_get_string(adaptive_sync_status));
json_object_get_boolean(features_adaptive_sync) ?
json_object_get_string(adaptive_sync_status) :
"unsupported");
printf(" Allow tearing: %s\n",
json_object_get_boolean(allow_tearing) ? "yes" : "no");
const char *hdr_str = "unsupported";
if (json_object_get_boolean(features_hdr)) {
hdr_str = json_object_get_boolean(hdr) ? "on" : "off";
}
printf(" HDR: %s\n", hdr_str);
} else {
printf(
"Output %s '%s %s %s' (disabled)\n",