Compare commits

..

62 commits

Author SHA1 Message Date
Simon Ser
dc8f5338be build: bump version to 1.10-rc3 2024-10-13 18:00:12 +02:00
Furkan Sahin
d262a241cc input/mouse: bugfix button2 being interpreted as trying to move the container
Man sway(5) specifies that when tiling_drag is enable, the floating_mod
can be used to drag tiling, as well as floating containers. However the
current code indiscriminately assumes any button press to be intended
for moving the container, consequently causing an unintended call to
`seatop_move_tilting:handle_button` rather than
`seatop_default:handle_button` to pass
`state=WL_POINTER_BUTTON_STATE_RELEASED` to `get_active_mouse_binding`

My idea was to make 'Handle moving a tiling container' follow the same
path as 'Handle moving a floating container' because the initial call to
handle moving a floating correctly exits that branch and ends up passing
the RELEASED state to `get_active_mouse_binding`.

Fixes #8334

(cherry picked from commit 7f1cd0b73b)
2024-10-13 13:54:25 +02:00
ShootingStarDragons
91be6e8a09 fix: sway crashes if switch to another workspace with surface when IME popup is shown
in pr https://github.com/swaywm/sway/pull/8196, when im_popup_surface is unmapped, author set the popup->relative to NULL, butt popup is still in popup groups, where assert the relative is not NULL, this cause the panic

Take the suggestion of Nefsen402, remove the line where set relative to
NULL, and add NULL check in scene_descriptor_destory

(cherry picked from commit f855b0898b)
2024-10-13 13:54:25 +02:00
Simon Ser
63005491cf build: bump version to 1.10-rc2 2024-10-06 16:54:45 +02:00
Kenny Levinsen
67ecc7d2cd Re-init renderer for all outputs on lost context
sway_root.outputs only include enabled outputs. We also need to re-init
the renderer for any disabled outputs, so use sway_root.all_outputs
instead.

Resolves the following heap-use-after-free accessing the render formats
when a disabled output is modeset after a GPU reset has occurred.

(cherry picked from commit c90cb37b2a)
2024-10-06 16:54:34 +02:00
Alexander Orzechowski
0de35b3585 Fix alpha-modifier-v1
(cherry picked from commit 9a9be01ad4)
2024-10-06 16:54:31 +02:00
Simon Ser
703671a12d release: push tags before creating GitHub release
Otherwise the GitHub release isn't attached to the Git tag.

(cherry picked from commit a2757e5f16)
2024-10-06 16:54:27 +02:00
Simon Ser
ae75fea8ef build: bump version to 1.10-rc1 2024-09-29 17:32:08 +02:00
Simon Ser
872cf451a1 Add support for alpha-modifier-v1
(cherry picked from commit a0b3606f17)
2024-09-29 17:27:20 +02:00
Furkan Sahin
1311685d1c swaybar: Fix 100% cpu usage if dbus dies.
Currently, swaybar does not gracefully die if it detects
that the dbus connection was lost. Although it's not recommended
to restart dbus without restarting the compositor, it can very
easily happen. In the case it does, compositor's tray should
not consume 100% cpu until it has to be force killed.

apply suggestions

just setting the bar to not running will call teardown and unref the
dbus.

(cherry picked from commit 00e9a94152)
2024-09-29 17:27:18 +02:00
Kenny Levinsen
75cfed65bb desktop/output: Clear modeset timer on output manager apply
If a modeset timer exists at the time we apply an output manager config,
clear it to avoid a useless double commit.

(cherry picked from commit 63345977e2)
2024-09-29 17:27:14 +02:00
Kenny Levinsen
4ea5a9cee1 config: Batch input/output configuration on load
We batch modesets and input configuration performed during config reload
but commit for every command during the intial config load. There is no
need to perform commits during the initial config load as outputs have
not yet been created, but swaybg spawn should still be batched.

At the same time, replace direct calls to apply output configuration
with request_modeset to properly handle the modeset timer.

(cherry picked from commit cdff4f7c74)
2024-09-29 17:27:09 +02:00
Kenny Levinsen
4aa71ca661 desktop/output: Expose request_modeset
We remove the struct sway_server argument for consistency with the rest
of our internal APIs which rely on the global server instance.

(cherry picked from commit b73f54a966)
2024-09-29 17:27:06 +02:00
Olivia Taliesin
952c428482 Removed destination-is-ancestor check from container_move_to_container to match i3 behaviour
(cherry picked from commit b6da218974)
2024-09-29 17:27:01 +02:00
Kenny Levinsen
0299e0412a commands/gaps: Check config->reading instead
Checking if the config is not active or is reloading is just a
convoluted way of checking if the config is being read.

(cherry picked from commit 861dde100a)
2024-09-29 17:26:48 +02:00
Kenny Levinsen
7f9baa05fa ext-session-lock: Do not use commit listener to arrange
Arranging lock surfaces rely on the sway_output width and height being
updated, but these are only updated after the commit has been completed
and all commit listeners have executed. This means that the lock
surfaces will not be appropriately scaled to match a change in output
dimensions, and may reveal what is under the lock background.

Replace the implicit arrange through the output commit listener with an
explicit arrange after the output configuration is finalized.

This might have regressed by other transition away from output commit
listeners for other arrange tasks, but even then it would have
erroneously relied on signalling order.

(cherry-picked from 785a459a55)
2024-09-21 16:16:56 +02:00
Kenny Levinsen
5686be82c6 config/output: Rename to apply_stored_output_configs
(cherry-picked from d7a76d381b)
2024-09-21 16:16:56 +02:00
Kenny Levinsen
a9c295fd67 config/output: Accept a list of output_configs to use
Instead of using a single finalized output config per output, accept a
regular list of output configs like the one ultimately stored for
configuration purposes. This allows the output management code to test
an augmented configuration while still using the same output config
logic, without having to mutate the stored configuration.

This in turn allows us to make a few APIs private. A bug note about an
existing issue with derade to off is added as well.

(cherry picked from 29b3f00e6f)
2024-09-21 16:16:56 +02:00
Kenny Levinsen
3b27392a47 config/output: Always start with default in find_output_config
We always need to start out with the default configuration, regardless
of whether the config is reloading or not to ensure that config
decisions are stable given a specific configuration.

(cherry picked from 0496477f92)
2024-09-21 16:16:56 +02:00
Kenny Levinsen
5664103902 config/output: Support multiple matches in find_output_config
Simplify find_output_config and inline the search through the output
configs instead of using list_seq_find with a comparator function. The
new implementation will merge any amount of matched configs in order,
which will be relied upon in a future commit.

(cherry picked from a0c0349934)
2024-09-21 16:16:56 +02:00
Kenny Levinsen
af86879462 tree/arrange; Skip arranging disabled outputs
Disabled outputs might not have a geometry to arrange for, so skip the
arrange to avoid messing up the workspace geometry.

(cherry picked from f4a6b0395f)
2024-09-21 16:16:56 +02:00
Kenny Levinsen
2879260f79 tree/arrange: Remove redundant output geometry update
This is handled by apply_output_configs.

(cherry picked from 4f9ce4675c)
2024-09-21 16:16:56 +02:00
Kenny Levinsen
b7be9de2be tree/output: Avoid duplicate input mapping configure
(cherry picked from 4fe054c6db)
2024-09-21 16:16:56 +02:00
Kenny Levinsen
c580b54b5e desktop/output: Avoid duplicate output manager update
(cherry picked from 4fe054c6db)
2024-09-21 16:16:56 +02:00
Kenny Levinsen
6baee5cb68 (desktop|tree)/output: Do not use layout listener to arrange
Output layout changes originate from the centralized modeset
infrastructure and request_state which already takes care of arranging
and updating outputs as needed.

(cherry picked from af28ac04a4)
2024-09-21 16:16:56 +02:00
Kenny Levinsen
fa96c64e24 tree/output: Rely on modeset arranging root
output_enable/output_disable are only called from modeset, and from
output destroy which requests modeset. As such, they can rely on the
modeset handling arrange.

(cherry picked from 6045ad9a02)
2024-09-21 16:16:56 +02:00
Kenny Levinsen
2f1db190c6 desktop/output: Do not use commit listener to arrange
The reasoning for using a commit handler is to ensure that all paths for
output changes are correctly handled. With the centralized modeset
infrastructure in place, we can move the logic there. This allows us to
be smarter and avoid extraneous arranges, output manager updates and
transaction commits.

The side-effect is a minor duplication for the special-case
request_state, but the shared path will be relied upon further in future
commits to justify this duplication.

(cherry picked from commit b83e5aaa54)
2024-09-21 16:16:56 +02:00
Alexander Orzechowski
307ab531c0 text_input: Inline input_popup_update into input_popup_set_focus
This seems to be the intention of input_popup_update in the first place:
handle the scenario where the focus moves.

(cherry picked from commit e9dd218231)
2024-09-20 19:48:52 +02:00
Alexander Orzechowski
9d667383b4 text_input: Properly handle map/unmap events
The last implementation would ignore these and get it could get into
a bad state where it would start crashing sway.

(cherry picked from commit 74e507962e)
2024-09-20 19:48:52 +02:00
Alexander Orzechowski
bb666f2ac9 transaction: Allow no popup descriptor in popup list
Input method popups in the future will destroy the scene descriptor when
it isn't mapped and therefore shouldn't be tampered with here.

(cherry picked from commit 023f6b0a50)
2024-09-20 19:48:52 +02:00
Alexander Orzechowski
af782c17bb text_input: Move popup placement to own function
(cherry picked from commit 1537c9dae5)
2024-09-20 19:48:52 +02:00
Alexander Orzechowski
5a920c48d1 text_input: Check for allocation failure
(cherry picked from commit 48069097ea)
2024-09-20 19:48:52 +02:00
Scott Dubinsky
b4d550bff8 Remove unguarded double include
(cherry picked from commit 266cd4515a)
2024-09-20 19:48:38 +02:00
Emil Engberg
4cca004583 Add toggle for output adaptive_sync
(cherry picked from commit e940acd374)
2024-09-20 19:48:35 +02:00
Kenny Levinsen
a8b6d02868 config/output: Stringify render format when logging it
(cherry picked from commit 9765c29be1)
2024-09-20 19:48:33 +02:00
Kenny Levinsen
12796fb0b3 config/output: Add support for 6-bit render fmt
GUD devices uses RGB565 by default for performance reasons. Allow
specifying render_bit_depth 6 to pick this format. The definition works
out if you consider the maximum number of bits per channel instead of
the average.

(cherry picked from commit 034d02f8a5)
2024-09-20 19:48:30 +02:00
Steffen Dirkwinkel
3264696469 config/output: support DRM_FORMAT_ARGB8888
Some display output hardware [1] doesn't support any of the current
formats, but works with ARGB8888. Fall back to it if available.

[1] 196145c606/drivers/gpu/drm/xlnx/zynqmp_disp.c (L313)

Signed-off-by: Steffen Dirkwinkel <s.dirkwinkel@beckhoff.com>
(cherry picked from commit f957c7e658)
2024-09-20 19:47:52 +02:00
Adam Chovanec
6835cbd046 readme: update Czech translation
(cherry picked from commit fb5eadc363)
2024-09-20 19:47:11 +02:00
llyyr
24fafa9490 sway/input/keyboard: always set active keyboard if there is none
Previously, we incorrectly only set active keyboard for non-virtual
devices. 4c3c060211 incorrectly put
unrelated code in `sway_keyboard_set_layout`.

Fixes: 4c3c060211
(cherry picked from commit c5ba7f23a5)
2024-09-20 19:47:06 +02:00
Kenny Levinsen
559f9eba33 desktop/transaction: Deactivate workspace on inactive outputs
If the output is not active, it might not have a valid geometry to
arrange for. Outputs do not gain a geometry until modeset, so if an
output is connected with a configuration present to disable it, it will
not have a geometry. If the output has a past workspace restored, this
will be attemtped arranged to fit a 0x0 rectangle, which asserts when
trying to sort out borders.

Consider the workspace activated only if the output itself is active to
get the scene nodes disabled.

(cherry picked from commit 14bff7b451)
2024-09-20 19:46:40 +02:00
Alexander Orzechowski
31ce4ea53d container: Skip % char if it doesn't match a view property
The else condition was missed here and we would never skip the % char
if it didn't end up matching with any property. Since we fail to skip
we would re-evaluate the % in an infinite loop never achieving any
forward-progress.

Fixes: https://github.com/swaywm/sway/issues/8333
(cherry picked from commit fc6b8d6af2)
2024-09-20 19:46:27 +02:00
Norbert Bolanowski
7246bf909c move title_format to container
(cherry picked from commit be840f730e)
2024-09-20 19:44:34 +02:00
Jon Wallace
d2fceae379 use subheadings instead
(cherry picked from commit 980a4e0211)
2024-09-20 19:44:28 +02:00
Jon Wallace
401a84bf21 Use heading markdown to demarcate sections of commands
Its a little tought to notice that the COMMANDS section is actually 3 sections. Use markdown to make this easier to see for the user.

(cherry picked from commit f2b2a81149)
2024-09-20 19:44:23 +02:00
llyyr
9cdd57a032 sway/tree/container: don't trunc coords in floating_fix_coordinates
This can cause issues such as the window not being shown at the exact
same coordinates when the old and new wlr_box aren't the same
dimensions and the container is being moved back-and-forth between them.

For example, in the case where a floating window gets moved
from one output to another but the outputs aren't the same resolution.
For e.g. have two displays that aren't the same resolution then:

1. Open a floating window and set it to pos 0,0 on output 2
2. Send it to scratchpad then `scratchpad show` on output 1
3. `scratchpad show` on output 2 again

Observe that the window isn't at 0,0 on output 2 anymore.

(cherry picked from commit 77b9ddabe2)
2024-09-20 19:44:17 +02:00
Anna (navi) Figueiredo Gomes
a4927e4cb2 sway/commands/move.c: arrange new workspace
When moving a container to a new workspace, the workspace's dimension
are left unset. Usually this doesn't matter, but when moving a floating
container to a new workspace on a different output, this leads to the
position of the container being calculated with 0, so the container ends
up halfway offscreen on the leftmost topmost monitor.

Signed-off-by: Anna (navi) Figueiredo Gomes <navi@vlhl.dev>
(cherry picked from commit f00f964abf)
2024-09-20 19:44:09 +02:00
Kenny Levinsen
b1c2155a8e config/output: Skip search if config has a mode
When doing an output configuration search, the intent is to only look
for modes if the output's configuration does not contain a specific
mode. This was done by testing if config_has_auto_mode returned false.

config_has_auto_mode had its return values backwards, leading to other
modes being tested if the output configuration had specified modes or
modelines, leading to unwanted modes being selected.

Invert the function to config_has_manual_mode to give it a clearer name,
and fix the return values in the process.

(cherry picked from commit f9c0f043e5)
2024-09-20 19:44:03 +02:00
Kenny Levinsen
234f18d357 config/output: Do not set adaptive_sync if not supported
After 4e38f93f36 ("config/output: Skip VRR tests when not supported"),
the configuration search no longer touches VRR state for outputs that
are known to not support it. This also means that it will not remove VRR
if already set, which could cause output configuration to fail.

Ensure that VRR state is never set for outputs that do not support it by
adding the same test for support to queue_output_config.

Fixes: 4e38f93f36 ("config/output: Skip VRR tests when not supported")
Fixes: https://github.com/swaywm/sway/issues/8296
(cherry picked from commit ae7c1b139a)
2024-09-20 19:43:57 +02:00
Felix Pehla
d100835485 commands/output/color_profile: allows use of relative path for ICC profile
(cherry picked from commit 6576b99c24)
2024-09-20 19:43:08 +02:00
Simon Ser
fb0f2add19 Switch default config to wmenu-run
This removes the last dependency bit on dmenu. No need for
"swaymsg exec" anymore: wmenu-run handles the xdg-activation
shenanigans.

(cherry picked from commit b44015578a)
2024-09-20 19:43:01 +02:00
Simon Ser
3fba40da50 Bind a few utilities to special keys in default config
(cherry picked from commit 9ba1beee58)
2024-09-20 19:42:58 +02:00
JingMatrix
e6c3612b72 Add null-safety check for virtual keyboard keymaps
Note that in the `sway_keyboard_configure` function of sway/input/keyboard.c,
we have skipped the `sway_keyboard_set_layout` function for virtual
keyboards, which then have null keymaps.
Hence, a null-safety check is needed at runtime.

(cherry picked from commit f344e9d5a5)
2024-09-20 19:42:53 +02:00
Kirill Primak
04943bc6ac tearing: fix UAF on destroy
Fixes: 9a1c411abd
(cherry picked from commit 32e5e5232d)
2024-09-20 19:42:45 +02:00
Kirill Primak
fa4912b1f9 tearing: remove trailing whitespace
(cherry picked from commit 3e956b9229)
2024-09-20 19:42:41 +02:00
Ricardo Steijn
01f5c50438 Add support for tearing-control-v1
References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3871

Adds option to allow tearing per output, as well as an option to force
enable or disable tearing for a specific application using a window
rule. Only works with fullscreen applications.

(cherry picked from commit 9a1c411abd)
2024-09-20 19:42:33 +02:00
Alexander Orzechowski
b4ab8182b7 transaction: Reparent all container children when disabling for scratchpad
Fixes: #8205
(cherry picked from commit b881c2e84c)
2024-09-20 19:42:28 +02:00
James Knight
8b923a3623 build: avoid git repository discovery when determining version
When attempting to use Git to populate commit/branch information in a
version string, it is possible through repository discovery that it
uses Git information not relevant to project. For example, if
repository content is extract into an interim build location when using
an embedded build framework (e.g. Buildroot), the project will not have
its Git repository to refer to. When it cannot find its repository, it
will look into its parent folders and may find the Git repository of
another project and use its branch/commit information.

This commit provides an explicit path to the project's Git repository
when consider commit/branch information. This will prevent any
repository discovery from occurring.

Signed-off-by: James Knight <james.d.knight@live.com>
(cherry picked from commit 6e4ccb99c3)
2024-09-20 19:42:14 +02:00
Simon Ser
53ffc1119a desktop/xwayland: don't restack when marking window as inactive
daaec72ac0 ("desktop/xwayland: restack surface upon activation")
has updated Sway for wlroots commit bfc69decdd04 ("xwm: do not
restack surfaces on activation"). However, it unconditionally
restacks the window above all other windows even if marking the
window as inactive.

Closes: https://github.com/swaywm/sway/issues/7974
(cherry picked from commit 7e74a49142)
2024-09-20 19:41:52 +02:00
Joan Bruguera Micó
100f92a189 layer-shell: Restore interactive layer focus code
Commit 188811f808 ("scene_graph: Port layer_shell") accidentally
removed code in `arrange_layers` to handle focus on layer shell
surfaces with keyboard interactivity.

Due to this, layer shell surfaces requesting exclusive keyboard
interactivity may not get automatically focused, and layer shell
surfaces giving up exclusive keyboard interactivity can remain focused.

Add the previous code back to fix the problem.

Note the non-rename change included in b4d7e84d38 ("desktop: Rename
layers to shell_layers") is not included as it also seems accidental.

Fixes: #7936
(cherry picked from commit 4d4c88f0a7)
2024-09-20 19:41:52 +02:00
Kenny Levinsen
19ca790a9f desktop/output: Stop repaint loop when not needed
1e0031781f refactored repaint to accumulate all changes in a single
wlr_output_state and commit them at the end of the repaint loop,
replacing a call to wlr_scene_output_commit. wlr_scene_output_commit
contains an early bail-out when no frame has been requested and no
damage has accumulated, which was not replicated as part of this
refactor, causing the repaint loop to never pause.

Replicate the logic to stop the repaint loop as needed.

Fixes: 1e0031781f ("desktop/output: unify page-flip codepath")
(cherry picked from commit 3f327b3db0)
2024-07-17 08:44:16 +02:00
Bill Li
6320aef295 ci: use package x11-servers/xwayland instead of x11-servers/xwayland-devel
(cherry picked from commit 50073dc579)
2024-07-17 08:44:16 +02:00
Simon Ser
1c992d847d ci: pin wlroots to v0.18.x 2024-07-13 13:07:16 +02:00
121 changed files with 1192 additions and 2001 deletions

View file

@ -25,16 +25,16 @@ packages:
- hwdata-dev
sources:
- https://github.com/swaywm/sway
- https://gitlab.freedesktop.org/wlroots/wlroots.git
- https://gitlab.freedesktop.org/wlroots/wlroots.git#0.18
tasks:
- wlroots: |
cd wlroots
meson setup --prefix=/usr build -Dexamples=false
meson --prefix=/usr build -Dexamples=false
ninja -C build
sudo ninja -C build install
- setup: |
cd sway
meson setup build --fatal-meson-warnings -Dauto_features=enabled -Dtray=disabled
meson 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 setup build --fatal-meson-warnings --default-library=static --force-fallback-for=wlroots
meson build --fatal-meson-warnings --default-library=static --force-fallback-for=wlroots
ninja -C build

View file

@ -22,16 +22,16 @@ packages:
- hwdata
sources:
- https://github.com/swaywm/sway
- https://gitlab.freedesktop.org/wlroots/wlroots.git
- https://gitlab.freedesktop.org/wlroots/wlroots.git#0.18
tasks:
- wlroots: |
cd wlroots
meson setup --prefix=/usr build -Dexamples=false
meson --prefix=/usr build -Dexamples=false
ninja -C build
sudo ninja -C build install
- setup: |
cd sway
meson setup build --fatal-meson-warnings -Dauto_features=enabled -Dsd-bus-provider=libsystemd
meson build --fatal-meson-warnings -Dauto_features=enabled -Dsd-bus-provider=libsystemd
- build: |
cd sway
ninja -C build

View file

@ -31,7 +31,7 @@ packages:
- misc/hwdata
sources:
- https://github.com/swaywm/sway
- https://gitlab.freedesktop.org/wlroots/wlroots.git
- https://gitlab.freedesktop.org/wlroots/wlroots.git#0.18
tasks:
- setup: |
cd sway
@ -39,7 +39,7 @@ tasks:
cd subprojects
ln -s ../../wlroots wlroots
cd ..
meson setup build --fatal-meson-warnings -Dtray=enabled -Dsd-bus-provider=basu
meson 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 setup build/
meson build/
ninja -C build/
sudo ninja -C build/ install

View file

@ -1,66 +0,0 @@
# 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,24 +1,25 @@
# sway
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).
[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]
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).
## Podpisy vydání
Vydané verze jsou podepsány klíčem [E88F5E48] a publikovány
[na GitHubu][GitHub releases].
Vydání jsou podepsána [E88F5E48] a publikována [na GitHubu][GitHub releases].
## Instalace
### Z balíků
### Z balíč
Sway je dostupný v mnoha distribucích. Zkuste v té vaší nainstalovat balík "sway".
Sway je dostupný ve spoustě distribucí. Zkuste nainstalovat balíček "sway" ve vaší
distribuci.
### Kompilace ze zdrojových kódů
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].
Podívejte se na [tuto stránku wiki][Development setup], pokud chcete sestavit HEAD
sway a wlroots pro testování nebo vývoj.
Nainstalujte závislosti:
@ -30,16 +31,16 @@ Nainstalujte závislosti:
* json-c
* pango
* cairo
* gdk-pixbuf2 (volitelné: dodatečné formáty ikon pro oznamovací oblast)
* [swaybg] (volitelné: tapeta plochy)
* [scdoc] (volitelné: man stránky) \*
* gdk-pixbuf2 (volitelné: oznamovací oblast)
* [swaybg] (volitelné: tapeta)
* [scdoc] (volitelné: manuálové stránky) \*
* git (volitelné: informace o verzi) \*
_\* Závislost pouze pro kompilaci_
Spusťte tyto příkazy:
meson setup build/
meson build/
ninja -C build/
sudo ninja -C build/ install
@ -52,7 +53,8 @@ Pro více informací o konfiguraci spusťte `man 5 sway`.
## Spuštění
Spusťte `sway` z TTY nebo ze správce displeje.
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).
[en]: https://github.com/swaywm/sway#readme
[ar]: README.ar.md

View file

@ -1,21 +1,21 @@
# Sway
Sway ist ein [i3]-kompatibler [Wayland]-Compositor. Lies die [FAQ]. Tritt dem [IRC Channel] bei (#sway on irc.libera.chat; Englisch).
Sway ist ein [i3](https://i3wm.org/)-kompatibler [Wayland](http://wayland.freedesktop.org/)-Compositor. Lies die [FAQ](https://github.com/swaywm/sway/wiki). Tritt dem [IRC Channel](https://web.libera.chat/gamja/?channels=#sway) bei (#sway on irc.libera.chat; Englisch).
## Signaturen
Jeder Release wird mit dem PGP-Schlüssel [E88F5E48] signiert und [auf GitHub][GitHub releases] veröffentlicht.
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.
## Installation
### Über die Paketverwaltung
Sway kann in vielen Distributionen direkt durch die Paketverwaltung installiert werden. Versuche einfach das Paket "sway" zu installieren.
Sway kann in vielen Distributionen direkt durch die Paketverwaltung installiert werden. Versuche einfach das Packet "sway" zu installieren.
### Quellcode selbst kompilieren
sway benötigt die folgenden Pakete:
* meson \*
* [wlroots]
* meson\*
* [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots)
* wayland
* wayland-protocols\*
* pcre2
@ -23,34 +23,21 @@ sway benötigt die folgenden Pakete:
* pango
* cairo
* gdk-pixbuf2 (Optional, wird für das Benachrichtigungsfeld (System Tray) benötigt)
* [swaybg] (Optional, wird für das Setzen von Desktophintergrundbildern benötigt)
* [scdoc] (Optional, wird für die Dokumentation (Man Pages) benötigt)\*
* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (Optional, wird für die Dokumentation (Man Pages) benötigt)\*
* git (Optional: Versionsinfo)\*
_\*Werden nur für das Kompilieren benötigt_
_\*Werden nur während des Kompilierens benötigt_
Führe die folgenden Befehle aus:
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.
meson build
ninja -C build
sudo ninja -C build install
## 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 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
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).

View file

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

View file

@ -40,7 +40,7 @@ _\*Compile-time dep_
Desde su consola, ejecute las órdenes:
meson setup build
meson 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 setup build
meson build
ninja -C build
sudo ninja -C build install
@ -61,7 +61,9 @@ documentation pour la configuration de sway.
## Exécution
Exécutez `sway` à partir d'un TTY ou d'un gestionnaires d'affichage.
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).
[Wayland]: http://wayland.freedesktop.org/
[i3]: https://i3wm.org/

View file

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

View file

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

View file

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

View file

@ -1,10 +1,10 @@
# sway
A Sway egy [i3]-kompatibilis [Wayland]-kompozitor. Olvasd el a [Gyarkan Ismételt Kérdéseket][FAQ]. Csatlakozz az [IRC-csatornához][IRC channel] \(`#sway` az `irc.libera.chat`-en).
A Sway egy [i3]-kompatibilis [Wayland] kompozitor. Olvasd el a [Gyarkan Ismételt Kérdéseket][FAQ]. Csatlakozz az [IRC csatornához][IRC channel] \(`#sway` az `irc.libera.chat`-en).
## Csomagaláírások
## Csomag aláírások
A kiadott csomagok az [E88F5E48] kulccsal vannak aláírva, és [GitHubon][GitHub releases] publikálva.
A kiadott csomagok az [E88F5E48] kulccsal vannak aláírva és [GitHub-on][GitHub releases] publikálva.
## Telepítés
@ -13,12 +13,12 @@ A kiadott csomagok az [E88F5E48] kulccsal vannak aláírva, és [GitHubon][GitHu
A Sway sok disztribúció csomagkezelőjéből elérhető, próbáld meg a "sway"
csomagot telepíteni az általad használt eszközzel.
Ha szeretnél csomagot készíteni a saját disztribúciódhoz, ugorj be az IRC-
Ha szeretnél csomagot készíteni a saját disztribúciódhoz, ugorj be az IRC
csatornára, vagy küldj levelet a sir@cmpwn.com címre tanácsokért.
### Fordítás forráskódból
Olvasd el [ezt a wikioldalt][Development setup], ha szeretnéd tesztelési vagy
Olvasd el [ezt a wiki oldalt][Development setup], ha szeretnéd tesztelési vagy
fejlesztési célokból lefordítani az aktuális (HEAD) állapotát a `sway`-nek és a
`wlroots`-nak.
@ -40,13 +40,13 @@ _\*Fordításidejű függőség_
Futtasd ezeket a parancsokat:
meson setup build
meson build
ninja -C build
sudo ninja -C build install
## Konfiguráció
Ha előzőleg i3-at használtál, akkor átmásolhatod az i3-beállításaidat a
Ha előzőleg i3-mat használtál, akkor átmásolhatod az i3 beállításaidat a
`~/.config/sway/config` file-ba és ugyanúgy működni fognak. Egyéb esetben másold
le kiindulási alapnak a mintát, ami általában az `etc/sway/config` elérési
útvonalon található.
@ -55,7 +55,7 @@ kapcsolatban.
## Futtatás
Futtasd a `sway` parancsot egy TTY-felületről. Néhány bejelentkezéskezelő
Futtasd a `sway` parancsot egy TTY felületről. Néhány bejelentkezéskezelő
(display manager) működhet, de alapvetően nem támogatottak a sway által. (A
gdm-ről ismeretes, hogy egész jól működik.)

View file

@ -41,7 +41,7 @@ _\*نیازمندی‌های زمان کامپایل برنامه_
این فرمان‌ها را اجرا کنید:
meson setup build
meson 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 IRC] \(#sway su irc.libera.chat).
Unisciti al [canale di IRC] \(#sway su irc.libera.chat).
## Firma delle versioni
@ -38,7 +38,7 @@ _\* Dipendenza necessaria per la compilazione_
Esegui questi comandi:
meson setup build/
meson build/
ninja -C build/
sudo ninja -C build/ install
@ -52,12 +52,13 @@ configurazione.
## Esecuzione
Lancia `sway` da un TTY o da un display manager.
Lancia `sway` da un TTY. Alcuni gestori d'accesso potrebbero funzionare ma non
sono supportati da sway (gdm funziona abbastanza bene).
[i3]: https://i3wm.org/
[Wayland]: http://wayland.freedesktop.org/
[FAQ]: https://github.com/swaywm/sway/wiki
[canale IRC]: https://web.libera.chat/gamja/?channels=#sway
[canale di 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 setup build
meson build
ninja -C build
sudo ninja -C build install
@ -52,4 +52,5 @@ _\*コンパイル時の依存_
## 実行
`sway`をTTYまたはディスプレイマネージャから実行してください。
`sway`をTTYから実行してください。いくつかのディスプレイマネージャは動くかもしれませんが、Swayからサポートされていません(gdmは非常に良く動作することが知られています)。

View file

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

View file

@ -1,6 +1,6 @@
# sway
**[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]
**[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]
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 setup build/
meson 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 or from a display manager.
Run `sway` from a TTY. Some display managers may work but are not supported by
sway (gdm is known to work fairly well).
[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,7 +77,6 @@ Run `sway` from a TTY or from a display manager.
[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 setup build
meson build
ninja -C build
sudo ninja -C build install

View file

@ -1,25 +1,29 @@
# 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).
## Signaturer
## Utgivelses 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 systempakker
### Fra system pakker
Sway er tilgjengelig i mange distribusjoner. Prøv å installere pakken "sway"
Sway er tilgjengelig i mange distribusjoner. Prøv å installere "sway" pakken
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.
Installer avhengigheter:
Installasjonsavhengigheter:
* meson \*
* [wlroots]
@ -29,37 +33,36 @@ Installer avhengigheter:
* json-c
* pango
* cairo
* gdk-pixbuf2 (valgfritt: støtte for ekstra bildeformater i system tray)
* [swaybg] (valgfritt: bakgrunnsbilde)
* gdk-pixbuf2 (valgfritt: system tray)
* [scdoc] (valgfritt: man pages) \*
* git (valgfritt: versjonsinformasjon) \*
* git \*
_\* Kompileringsavhengigheter_
_\*Kompileringsavhengigheter_
Kjør følgende kommandoer:
meson setup build/
ninja -C build/
sudo ninja -C build/ install
meson 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 eksempelkonfigurasjonsfilen til
`~/.config/sway/config`. Eksempelfilen er normalt plasert i `/etc/sway/config`.
Kjør `man 5 sway` for å få opplysninger om konfigurasjonen.
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.
## Kjøring
## Utførelse
Kjør `sway` fra en TTY eller fra en display manager.
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).
[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 setup build
meson build
ninja -C build
sudo ninja -C build install
@ -53,4 +53,5 @@ Wykonaj polecenie `man 5 sway` aby uzyskać informacje dotyczące konfiguracji.
## Uruchamianie
Wykonaj polecenie `sway` z poziomu TTY lub menedżera wyświetlania.
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).

View file

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

View file

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

View file

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

View file

@ -1,65 +0,0 @@
# 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

@ -1,5 +1,7 @@
# sway
[English][en] - [Deutsch][de] - [Dansk][dk] - [Español][es] - [Français][fr] - **[Svenska][sv]** - [Ελληνικά][gr] - [Magyar][hu] - [فارسی][ir] - [Italiano][it] - [日本語][ja] - [한국어][ko] - [Nederlands][nl] - [Polski][pl] - [Português][pt] - [Română][ro] - [Русский][ru] - [Türkçe][tr] - [Українська][uk] - [中文-简体][zh-CN] - [中文-繁體][zh-TW]
sway är en [i3]-kompatibel [Wayland] compositor. Läs våran [FAQ]-sida. Gå med i vår
[IRC-kanal] \(#sway på irc.libera.chat).
@ -35,7 +37,7 @@ _\* Krav för kompilering_
Kör dessa kommandon:
meson setup build/
meson 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 setup build
meson build
ninja -C build
sudo ninja -C build install

View file

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

View file

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

View file

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

View file

@ -360,7 +360,3 @@ char *format_str(const char *fmt, ...) {
va_end(args);
return str;
}
bool has_prefix(const char *str, const char *prefix) {
return strncmp(str, prefix, strlen(prefix)) == 0;
}

View file

@ -141,9 +141,3 @@ 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,18 +46,14 @@ output * bg @datadir@/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png fill
#
# Example configuration:
#
# input type:touchpad {
# input "2:14:SynPS/2_Synaptics_TouchPad" {
# dwt enabled
# tap enabled
# natural_scroll enabled
# middle_emulation enabled
# }
#
# input type:keyboard {
# xkb_layout "eu"
# }
#
# You can also configure each device individually.
# You can get the names of your inputs by running: swaymsg -t get_inputs
# Read `man 5 sway-input` for more information about this section.
### Key bindings
@ -205,18 +201,9 @@ 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

@ -40,6 +40,4 @@ bool expand_path(char **path);
char *vformat_str(const char *fmt, va_list args) _SWAY_ATTRIB_PRINTF(1, 0);
char *format_str(const char *fmt, ...) _SWAY_ATTRIB_PRINTF(1, 2);
bool has_prefix(const char *str, const char *prefix);
#endif

View file

@ -290,7 +290,6 @@ 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 for SDR, 10 for HDR
RENDER_BIT_DEPTH_DEFAULT, // the default is currently 8
RENDER_BIT_DEPTH_6,
RENDER_BIT_DEPTH_8,
RENDER_BIT_DEPTH_10,
@ -291,7 +291,6 @@ struct output_config {
bool set_color_transform;
struct wlr_color_transform *color_transform;
int allow_tearing;
int hdr;
char *background;
char *background_option;
@ -706,8 +705,6 @@ struct output_config *find_output_config(struct sway_output *output);
void free_output_config(struct output_config *oc);
void request_modeset(void);
void force_modeset(void);
bool modeset_is_pending(void);
bool spawn_swaybg(void);

View file

@ -53,10 +53,6 @@ struct criteria {
char urgent; // 'l' for latest or 'o' for oldest
struct pattern *workspace;
pid_t pid;
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

@ -13,7 +13,6 @@ enum sway_idle_inhibit_mode {
struct sway_idle_inhibit_manager_v1 {
struct wlr_idle_inhibit_manager_v1 *wlr_manager;
struct wl_listener new_idle_inhibitor_v1;
struct wl_listener manager_destroy;
struct wl_list inhibitors;
};

View file

@ -39,8 +39,6 @@ struct sway_input_manager {
struct sway_input_manager *input_manager_create(struct sway_server *server);
void input_manager_finish(struct sway_input_manager *input);
bool input_manager_has_focus(struct sway_node *node);
void input_manager_set_focus(struct sway_node *node);

View file

@ -25,10 +25,8 @@ struct sway_input_method_relay {
struct wlr_input_method_v2 *input_method; // doesn't have to be present
struct wl_listener text_input_new;
struct wl_listener text_input_manager_destroy;
struct wl_listener input_method_new;
struct wl_listener input_method_manager_destroy;
struct wl_listener input_method_commit;
struct wl_listener input_method_new_popup_surface;
struct wl_listener input_method_grab_keyboard;

View file

@ -9,6 +9,7 @@ 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;
@ -18,8 +19,6 @@ 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;
@ -42,6 +41,4 @@ 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,25 +52,28 @@ struct sway_output {
bool enabled;
list_t *workspaces;
struct wl_list layer_surfaces; // sway_layer_surface.link
struct sway_output_state current;
struct wl_listener layout_destroy;
struct wl_listener destroy;
struct wl_listener commit;
struct wl_listener present;
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 gamma_lut_changed;
bool allow_tearing;
bool hdr;
};
struct sway_output_non_desktop {
@ -90,9 +93,6 @@ struct sway_output *output_from_wlr_output(struct wlr_output *output);
struct sway_output *output_get_in_direction(struct sway_output *reference,
enum wlr_direction direction);
void output_configure_scene(struct sway_output *output,
struct wlr_scene_node *node, float opacity);
void output_add_workspace(struct sway_output *output,
struct sway_workspace *workspace);
@ -131,13 +131,14 @@ 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);
enum wlr_direction opposite_direction(enum wlr_direction d);
void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data);
void handle_output_manager_apply(struct wl_listener *listener, void *data);
void handle_output_manager_test(struct wl_listener *listener, void *data);

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;
char *socket;
const char *socket;
struct wlr_backend *backend;
struct wlr_session *session;
@ -46,7 +46,6 @@ struct sway_server {
struct wl_listener new_output;
struct wl_listener renderer_lost;
struct wl_event_source *recreating_renderer;
struct wlr_idle_notifier_v1 *idle_notifier_v1;
struct sway_idle_inhibit_manager_v1 idle_inhibit_manager_v1;
@ -105,24 +104,17 @@ struct sway_server {
struct wlr_ext_foreign_toplevel_list_v1 *foreign_toplevel_list;
struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager;
struct wlr_content_type_manager_v1 *content_type_manager_v1;
struct wlr_data_control_manager_v1 *wlr_data_control_manager_v1;
struct wlr_ext_data_control_manager_v1 *ext_data_control_manager_v1;
struct wlr_data_control_manager_v1 *data_control_manager_v1;
struct wlr_screencopy_manager_v1 *screencopy_manager_v1;
struct wlr_ext_image_copy_capture_manager_v1 *ext_image_copy_capture_manager_v1;
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
@ -156,19 +148,20 @@ struct sway_debug {
bool noatomic; // Ignore atomic layout updates
bool txn_timings; // Log verbose messages about transactions
bool txn_wait; // Always wait for the timeout before applying
bool legacy_wl_drm; // Enable the legacy wl_drm interface
};
extern struct sway_debug debug;
extern bool allow_unsupported_gpu;
void sway_terminate(int exit_code);
bool server_init(struct sway_server *server);
void server_fini(struct sway_server *server);
bool server_start(struct sway_server *server);
void server_run(struct sway_server *server);
void restore_nofile_limit(void);
void handle_new_output(struct wl_listener *listener, void *data);
void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data);

View file

@ -95,7 +95,6 @@ struct sway_container {
struct wl_listener output_enter;
struct wl_listener output_leave;
struct wl_listener output_handler_destroy;
struct sway_container_state current;
struct sway_container_state pending;
@ -103,7 +102,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,7 +25,6 @@ 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,
@ -70,9 +69,6 @@ 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;
@ -128,9 +124,6 @@ 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;
@ -149,8 +142,6 @@ 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;
@ -201,12 +192,10 @@ 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_scene_tree *image_capture_tree;
struct wlr_xdg_popup *wlr_xdg_popup;
struct sway_popup_desc desc;
@ -232,14 +221,6 @@ const char *view_get_window_role(struct sway_view *view);
uint32_t view_get_window_type(struct sway_view *view);
const char *view_get_sandbox_engine(struct sway_view *view);
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,
@ -364,6 +345,4 @@ 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_workspace *ws, struct sway_output *exclude);
void workspace_detect_urgent(struct sway_workspace *workspace);

View file

@ -14,11 +14,6 @@ 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,6 +61,4 @@ 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,14 +1,13 @@
project(
'sway',
'c',
version: '1.12-dev',
version: '1.10-rc3',
license: 'MIT',
meson_version: '>=1.3',
meson_version: '>=0.60.0',
default_options: [
'c_std=c11',
'warning_level=2',
'werror=true',
'wrap_mode=nodownload',
],
)
@ -39,14 +38,14 @@ if is_freebsd
endif
# Execute the wlroots subproject, if any
wlroots_version = ['>=0.20.0', '<0.21.0']
wlroots_version = ['>=0.18.0', '<0.19.0']
subproject(
'wlroots',
default_options: ['examples=false'],
required: false,
version: wlroots_version,
)
wlroots = dependency('wlroots-0.20', version: wlroots_version, fallback: 'wlroots')
wlroots = dependency('wlroots-0.18', version: wlroots_version, fallback: 'wlroots')
wlroots_features = {
'xwayland': false,
'libinput_backend': false,
@ -65,7 +64,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.41', default_options: ['tests=false'])
wayland_protos = dependency('wayland-protocols', version: '>=1.24', default_options: ['tests=false'])
xkbcommon = dependency('xkbcommon', version: '>=1.5.0')
cairo = dependency('cairo')
pango = dependency('pango')
@ -80,7 +79,7 @@ libudev = wlroots_features['libinput_backend'] ? dependency('libudev') : null_de
math = cc.find_library('m')
rt = cc.find_library('rt')
xcb_icccm = wlroots_features['xwayland'] ? dependency('xcb-icccm') : null_dep
threads = dependency('threads') # for pthread_setschedparam and pthread_atfork
threads = dependency('threads') # for pthread_setschedparam
if get_option('sd-bus-provider') == 'auto'
if not get_option('tray').disabled()
@ -110,9 +109,11 @@ conf_data.set10('HAVE_LIBSYSTEMD', sdbus.found() and sdbus.name() == 'libsystemd
conf_data.set10('HAVE_LIBELOGIND', sdbus.found() and sdbus.name() == 'libelogind')
conf_data.set10('HAVE_BASU', sdbus.found() and sdbus.name() == 'basu')
conf_data.set10('HAVE_TRAY', have_tray)
foreach sym : ['LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM', 'LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY']
conf_data.set10('HAVE_' + sym, cc.has_header_symbol('libinput.h', sym, dependencies: libinput))
endforeach
conf_data.set10('HAVE_LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM', cc.has_header_symbol(
'libinput.h',
'LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM',
dependencies: libinput,
))
scdoc = dependency('scdoc', version: '>=1.9.2', native: true, required: get_option('man-pages'))
if scdoc.found()
@ -171,10 +172,31 @@ if git.found()
endif
add_project_arguments('-DSWAY_VERSION=@0@'.format(version), language: 'c')
fs = import('fs')
# Compute the relative path used by compiler invocations.
source_root = meson.current_source_dir().split('/')
build_root = meson.global_build_root().split('/')
relative_dir_parts = []
i = 0
in_prefix = true
foreach p : build_root
if i >= source_root.length() or not in_prefix or p != source_root[i]
in_prefix = false
relative_dir_parts += '..'
endif
i += 1
endforeach
i = 0
in_prefix = true
foreach p : source_root
if i >= build_root.length() or not in_prefix or build_root[i] != p
in_prefix = false
relative_dir_parts += p
endif
i += 1
endforeach
relative_dir = join_paths(relative_dir_parts) + '/'
# Strip relative path prefixes from the code if possible, otherwise hide them.
relative_dir = fs.relative_to(meson.current_source_dir(), meson.global_build_root()) + '/'
if cc.has_argument('-fmacro-prefix-map=/prefix/to/hide=')
add_project_arguments(
'-fmacro-prefix-map=@0@='.format(relative_dir),

View file

@ -9,8 +9,12 @@ 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/cursor-shape/cursor-shape-v1.xml',
wl_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
wl_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml',
wl_protocol_dir / 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.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/tearing-control/tearing-control-v1.xml',
'wlr-layer-shell-unstable-v1.xml',
'idle.xml',
'wlr-output-power-management-unstable-v1.xml',

View file

@ -1,7 +1,7 @@
#!/bin/sh -eu
prev=$(git describe --tags --abbrev=0)
next=$(meson rewrite kwargs info project / | jq -r '.kwargs["project#/"].version')
next=$(meson rewrite kwargs info project / 2>&1 >/dev/null | jq -r '.kwargs["project#/"].version')
case "$next" in
*-dev)

View file

@ -3,4 +3,3 @@ Name=Sway
Comment=An i3-compatible Wayland compositor
Exec=sway
Type=Application
DesktopNames=sway;wlroots

View file

@ -23,7 +23,7 @@ struct cmd_results *cmd_assign(int argc, char **argv) {
--argc; ++argv;
if (has_prefix(*argv, "")) {
if (strncmp(*argv, "", strlen("")) == 0) {
if (argc < 2) {
free(criteria);
return cmd_results_new(CMD_INVALID, "Missing workspace");

View file

@ -11,7 +11,7 @@ struct cmd_results *bar_cmd_font(int argc, char **argv) {
char *font = join_args(argv, argc);
free(config->current_bar->font);
if (has_prefix(font, "pango:")) {
if (strncmp(font, "pango:", 6) == 0) {
if (config->current_bar->pango_markup == PANGO_MARKUP_DEFAULT) {
config->current_bar->pango_markup = true;
}

View file

@ -367,7 +367,8 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
}
} else if (strcmp("--exclude-titlebar", argv[0]) == 0) {
exclude_titlebar = true;
} else if (has_prefix(argv[0], "--input-device=")) {
} else if (strncmp("--input-device=", argv[0],
strlen("--input-device=")) == 0) {
free(binding->input);
binding->input = strdup(argv[0] + strlen("--input-device="));
strip_quotes(binding->input);
@ -398,7 +399,7 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
list_t *split = split_string(argv[0], "+");
for (int i = 0; i < split->length; ++i) {
// Check for group
if (has_prefix(split->items[i], "Group")) {
if (strncmp(split->items[i], "Group", strlen("Group")) == 0) {
if (binding->group != XKB_LAYOUT_INVALID) {
free_sway_binding(binding);
list_free_items_and_destroy(split);

View file

@ -25,6 +25,16 @@ struct cmd_results *cmd_exec_validate(int argc, char **argv) {
return error;
}
static void export_xdga_token(struct launcher_ctx *ctx) {
const char *token = launcher_ctx_get_token_name(ctx);
setenv("XDG_ACTIVATION_TOKEN", token, 1);
}
static void export_startup_id(struct launcher_ctx *ctx) {
const char *token = launcher_ctx_get_token_name(ctx);
setenv("DESKTOP_STARTUP_ID", token, 1);
}
struct cmd_results *cmd_exec_process(int argc, char **argv) {
struct cmd_results *error = NULL;
char *cmd = NULL;
@ -46,37 +56,67 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) {
sway_log(SWAY_DEBUG, "Executing %s", cmd);
int fd[2];
if (pipe(fd) != 0) {
sway_log(SWAY_ERROR, "Unable to create pipe for fork");
}
pid_t pid, child;
struct launcher_ctx *ctx = launcher_ctx_create_internal();
// Fork process
pid_t child = fork();
if (child == 0) {
if ((pid = fork()) == 0) {
// Fork child process again
restore_nofile_limit();
setsid();
if (ctx) {
const char *token = launcher_ctx_get_token_name(ctx);
setenv("XDG_ACTIVATION_TOKEN", token, 1);
if (!no_startup_id) {
setenv("DESKTOP_STARTUP_ID", token, 1);
sigset_t set;
sigemptyset(&set);
sigprocmask(SIG_SETMASK, &set, NULL);
signal(SIGPIPE, SIG_DFL);
close(fd[0]);
if ((child = fork()) == 0) {
close(fd[1]);
if (ctx) {
export_xdga_token(ctx);
}
if (ctx && !no_startup_id) {
export_startup_id(ctx);
}
execlp("sh", "sh", "-c", cmd, (void *)NULL);
sway_log_errno(SWAY_ERROR, "execlp failed");
_exit(1);
}
execlp("sh", "sh", "-c", cmd, (void*)NULL);
sway_log_errno(SWAY_ERROR, "execve failed");
ssize_t s = 0;
while ((size_t)s < sizeof(pid_t)) {
s += write(fd[1], ((uint8_t *)&child) + s, sizeof(pid_t) - s);
}
close(fd[1]);
_exit(0); // Close child process
} else if (child < 0) {
launcher_ctx_destroy(ctx);
} else if (pid < 0) {
free(cmd);
close(fd[0]);
close(fd[1]);
return cmd_results_new(CMD_FAILURE, "fork() failed");
}
sway_log(SWAY_DEBUG, "Child process created with pid %d", child);
if (ctx != NULL) {
sway_log(SWAY_DEBUG, "Recording workspace for process %d", child);
ctx->pid = child;
free(cmd);
close(fd[1]); // close write
ssize_t s = 0;
while ((size_t)s < sizeof(pid_t)) {
s += read(fd[0], ((uint8_t *)&child) + s, sizeof(pid_t) - s);
}
close(fd[0]);
// cleanup child process
waitpid(pid, NULL, 0);
if (child > 0) {
sway_log(SWAY_DEBUG, "Child process created with pid %d", child);
if (ctx != NULL) {
sway_log(SWAY_DEBUG, "Recording workspace for process %d", child);
ctx->pid = child;
}
} else {
launcher_ctx_destroy(ctx);
return cmd_results_new(CMD_FAILURE, "Second fork() failed");
}
free(cmd);
return cmd_results_new(CMD_SUCCESS, NULL);
}

View file

@ -1,7 +1,8 @@
#include <stddef.h>
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/server.h"
void sway_terminate(int exit_code);
struct cmd_results *cmd_exit(int argc, char **argv) {
struct cmd_results *error = NULL;

View file

@ -13,9 +13,9 @@ struct cmd_results *cmd_font(int argc, char **argv) {
char *font = join_args(argv, argc);
free(config->font);
if (has_prefix(font, "pango:")) {
if (strncmp(font, "pango:", 6) == 0) {
config->pango_markup = true;
config->font = strdup(font + strlen("pango:"));
config->font = strdup(font + 6);
free(font);
} else {
config->pango_markup = false;

View file

@ -121,7 +121,8 @@ static struct cmd_results *cmd_bind_or_unbind_gesture(int argc, char **argv, boo
binding->flags |= BINDING_EXACT;
} else if (strcmp("--no-warn", argv[0]) == 0) {
warn = false;
} else if (has_prefix(argv[0], "--input-device=")) {
} else if (strncmp("--input-device=", argv[0],
strlen("--input-device=")) == 0) {
free(binding->input);
binding->input = strdup(argv[0] + strlen("--input-device="));
} else {

View file

@ -3,12 +3,12 @@
struct cmd_results *cmd_include(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "include", EXPECTED_AT_LEAST, 1))) {
if ((error = checkarg(argc, "include", EXPECTED_EQUAL_TO, 1))) {
return error;
}
char *files = join_args(argv, argc);
// We don't care if the included config(s) fails to load.
load_include_configs(files, config, &config->swaynag_config_errors);
load_include_configs(argv[0], config, &config->swaynag_config_errors);
return cmd_results_new(CMD_SUCCESS, NULL);
}

View file

@ -15,11 +15,6 @@ struct cmd_results *input_cmd_drag_lock(int argc, char **argv) {
return cmd_results_new(CMD_FAILURE, "No input device defined.");
}
#if HAVE_LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY
if (strcmp(argv[0], "enabled_sticky") == 0) {
ic->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY;
} else
#endif
if (parse_boolean(argv[0], true)) {
ic->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED;
} else {

View file

@ -86,7 +86,7 @@ static void toggle_select_send_events_for_device(struct input_config *ic,
static void toggle_send_events(int argc, char **argv) {
struct input_config *ic = config->handler_context.input_config;
bool wildcard = strcmp(ic->identifier, "*") == 0;
const char *type = has_prefix(ic->identifier, "type:")
const char *type = strncmp(ic->identifier, "type:", strlen("type:")) == 0
? ic->identifier + strlen("type:") : NULL;
struct sway_input_device *device = NULL;
wl_list_for_each(device, &server.input->devices, link) {
@ -146,7 +146,8 @@ struct cmd_results *input_cmd_events(int argc, char **argv) {
toggle_send_events(argc - 1, argv + 1);
if (strcmp(ic->identifier, "*") == 0 || has_prefix(ic->identifier, "type:")) {
if (strcmp(ic->identifier, "*") == 0 ||
strncmp(ic->identifier, "type:", strlen("type:")) == 0) {
// Update the device input configs and then reset the type/wildcard
// config send events mode so that is does not override the device
// ones. The device ones will be applied when attempting to apply

View file

@ -134,19 +134,6 @@ 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

@ -23,7 +23,7 @@ struct cmd_results *cmd_mark(int argc, char **argv) {
}
bool add = false, toggle = false;
while (argc > 0 && has_prefix(*argv, "--")) {
while (argc > 0 && strncmp(*argv, "--", 2) == 0) {
if (strcmp(*argv, "--add") == 0) {
add = true;
} else if (strcmp(*argv, "--replace") == 0) {

View file

@ -222,7 +222,6 @@ 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

@ -2,8 +2,7 @@
#include <stdlib.h>
#include <strings.h>
#include "sway/commands.h"
#include "sway/tree/container.h"
#include "sway/output.h"
#include "sway/tree/view.h"
#include "log.h"
struct cmd_results *cmd_opacity(int argc, char **argv) {
@ -38,7 +37,6 @@ struct cmd_results *cmd_opacity(int argc, char **argv) {
}
con->alpha = val;
output_configure_scene(NULL, &con->scene_tree->node, 1);
container_update(con);
return cmd_results_new(CMD_SUCCESS, NULL);

View file

@ -15,7 +15,6 @@ 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

@ -3,8 +3,10 @@
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/swaynag.h"
#include "log.h"
#include "stringop.h"
@ -40,14 +42,14 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
}
struct output_config *output = config->handler_context.output_config;
char *src = NULL;
if (strcasecmp(argv[1], "solid_color") == 0) {
if (!validate_color(argv[0])) {
return cmd_results_new(CMD_INVALID,
"Colors should be of the form #RRGGBB");
}
if (!(output->background = strdup(argv[0]))) goto cleanup;
if (!(output->background_option = strdup("solid_color"))) goto cleanup;
output->background = strdup(argv[0]);
output->background_option = strdup("solid_color");
output->background_fallback = NULL;
argc -= 2; argv += 2;
} else {
@ -75,25 +77,37 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
return cmd_results_new(CMD_INVALID, "Missing background file");
}
if (!(src = join_args(argv, j))) goto cleanup;
char *src = join_args(argv, j);
if (!expand_path(&src)) {
struct cmd_results *cmd_res = cmd_results_new(CMD_INVALID,
"Invalid syntax (%s)", src);
free(src);
return cmd_res;
}
if (!src) {
sway_log(SWAY_ERROR, "Failed to allocate expanded path");
return cmd_results_new(CMD_FAILURE, "Unable to allocate resource");
}
if (config->reading && *src != '/') {
// src file is inside configuration dir
char *conf = strdup(config->current_config_path);
if (!conf) goto cleanup;
if (!conf) {
sway_log(SWAY_ERROR, "Failed to duplicate string");
free(src);
return cmd_results_new(CMD_FAILURE,
"Unable to allocate resources");
}
char *conf_path = dirname(conf);
char *real_src = malloc(strlen(conf_path) + strlen(src) + 2);
if (!real_src) {
free(src);
free(conf);
goto cleanup;
sway_log(SWAY_ERROR, "Unable to allocate memory");
return cmd_results_new(CMD_FAILURE,
"Unable to allocate resources");
}
snprintf(real_src, strlen(conf_path) + strlen(src) + 2, "%s/%s", conf_path, src);
@ -103,48 +117,40 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
}
bool can_access = access(src, F_OK) != -1;
argc -= j + 1; argv += j + 1;
free(output->background_option);
free(output->background_fallback);
free(output->background);
output->background = output->background_option = output->background_fallback = NULL;
char *fallback = NULL;
if (argc && *argv[0] == '#') {
if (validate_color(argv[0])) {
if (!(fallback = strdup(argv[0]))) goto cleanup;
output->background_fallback = fallback;
} else {
sway_log(SWAY_ERROR, "fallback '%s' should be of the form #RRGGBB", argv[0]);
config_add_swaynag_warning("fallback '%s' should be of the form #RRGGBB\n", argv[0]);
}
argc--; argv++;
}
if (!can_access) {
if (!fallback) {
sway_log(SWAY_ERROR, "Unable to access background file '%s' "
"and no valid fallback provided", src);
struct cmd_results *res = cmd_results_new(CMD_FAILURE, "Unable to access "
"background file '%s' and no valid fallback provided", src);
free(src);
return res;
}
sway_log(SWAY_DEBUG, "Cannot access file '%s', using fallback '%s'", src, fallback);
output->background = fallback;
if (!(output->background_option = strdup("solid_color"))) goto cleanup;
output->background_fallback = NULL;
sway_log_errno(SWAY_ERROR, "Unable to access background file '%s'",
src);
config_add_swaynag_warning("Unable to access background file '%s'",
src);
struct cmd_results *result = cmd_results_new(CMD_FAILURE,
"unable to access background file '%s'", src);
free(src);
return result;
} else {
output->background = src;
if (!(output->background_option = strdup(mode))) goto cleanup;
output->background_option = strdup(mode);
}
argc -= j + 1; argv += j + 1;
output->background_fallback = NULL;
if (argc && *argv[0] == '#') {
if (!validate_color(argv[0])) {
return cmd_results_new(CMD_INVALID,
"fallback color should be of the form #RRGGBB");
}
output->background_fallback = strdup(argv[0]);
argc--; argv++;
if (!can_access) {
output->background = output->background_fallback;
output->background_option = strdup("solid_color");
output->background_fallback = NULL;
}
}
}
config->handler_context.leftovers.argc = argc;
config->handler_context.leftovers.argv = argv;
return NULL;
cleanup:
free(src);
sway_log(SWAY_ERROR, "Failed to allocate resources");
return cmd_results_new(CMD_FAILURE, "Unable to allocate resources");
}

View file

@ -1,37 +0,0 @@
#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,46 +80,61 @@ void container_resize_tiled(struct sway_container *con,
}
// For HORIZONTAL or VERTICAL, we are growing in two directions so select
// all adjacent siblings. For RIGHT or DOWN or LEFT or UP select just the
// previous or next sibling.
list_t *resize = create_list();
// 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;
list_t *siblings = container_get_siblings(con);
int index = container_sibling_index(con);
if (axis == AXIS_HORIZONTAL || axis == AXIS_VERTICAL) {
list_cat(resize, siblings);
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];
}
} else if (axis == WLR_EDGE_TOP || axis == WLR_EDGE_LEFT) {
if (!sway_assert(index > 0, "Didn't expect first child")) {
goto cleanup;
return;
}
list_add(resize, siblings->items[index - 1]);
list_add(resize, con);
next = con;
con = siblings->items[index - 1];
amount = -amount;
} else {
if (!sway_assert(index < siblings->length - 1,
"Didn't expect last child")) {
goto cleanup;
return;
}
list_add(resize, con);
list_add(resize, siblings->items[index + 1]);
next = siblings->items[index + 1];
}
// Apply new dimensions
int sibling_amount = ceil((double)amount / (double)(resize->length - 1));
int sibling_amount = prev ? ceil((double)amount / 2.0) : amount;
if (is_horizontal(axis)) {
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->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;
}
if (con->child_total_width <= 0) {
goto cleanup;
return;
}
// 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;
@ -127,27 +142,30 @@ void container_resize_tiled(struct sway_container *con,
double amount_fraction = (double)amount / con->child_total_width;
double sibling_amount_fraction =
amount_fraction / (double)(resize->length - 1);
prev ? amount_fraction / 2.0 : 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;
con->width_fraction += amount_fraction;
next->width_fraction -= sibling_amount_fraction;
if (prev) {
prev->width_fraction -= sibling_amount_fraction;
}
} else {
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->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;
}
if (con->child_total_height <= 0) {
goto cleanup;
return;
}
// 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;
@ -155,12 +173,12 @@ void container_resize_tiled(struct sway_container *con,
double amount_fraction = (double)amount / con->child_total_height;
double sibling_amount_fraction =
amount_fraction / (double)(resize->length - 1);
prev ? amount_fraction / 2.0 : 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;
con->height_fraction += amount_fraction;
next->height_fraction -= sibling_amount_fraction;
if (prev) {
prev->height_fraction -= sibling_amount_fraction;
}
}
@ -169,9 +187,6 @@ void container_resize_tiled(struct sway_container *con,
} else {
arrange_workspace(con->pending.workspace);
}
cleanup:
list_free(resize);
}
/**
@ -442,7 +457,7 @@ static struct cmd_results *cmd_resize_set(int argc, char **argv) {
if (argc > num_consumed_args) {
return cmd_results_new(CMD_INVALID, "%s", usage);
}
if (height.unit == MOVEMENT_UNIT_INVALID) {
if (width.unit == MOVEMENT_UNIT_INVALID) {
return cmd_results_new(CMD_INVALID, "%s", usage);
}
}

View file

@ -118,10 +118,10 @@ struct cmd_results *cmd_scratchpad(int argc, char **argv) {
// If using criteria, this command is executed for every container which
// matches the criteria. If this container isn't in the scratchpad,
// we'll return an error. The same is true if the
// we'll just silently return a success. The same is true if the
// overridden node is not a container.
if (!con || !con->scratchpad) {
return cmd_results_new(CMD_INVALID, "Container is not in scratchpad.");
return cmd_results_new(CMD_SUCCESS, NULL);
}
scratchpad_toggle_container(con);
} else {

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,12 +552,28 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
return success;
}
static bool load_include_config(const char *path, struct sway_config *config,
struct swaynag_instance *swaynag) {
static bool load_include_config(const char *path, const char *parent_dir,
struct sway_config *config, struct swaynag_instance *swaynag) {
// save parent config
const char *parent_config = config->current_config_path;
char *real_path = realpath(path, NULL);
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);
if (real_path == NULL) {
sway_log(SWAY_DEBUG, "%s not found.", path);
@ -609,7 +625,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], config, swaynag);
load_include_config(w[i], parent_dir, config, swaynag);
}
wordfree(&p);
}
@ -909,8 +925,8 @@ char *do_var_replacement(char *str) {
// Find matching variable
for (i = 0; i < config->symbols->length; ++i) {
struct sway_variable *var = config->symbols->items[i];
if (has_prefix(find, var->name)) {
int vnlen = strlen(var->name);
int vnlen = strlen(var->name);
if (strncmp(find, var->name, vnlen) == 0) {
int vvlen = strlen(var->value);
char *newstr = malloc(strlen(str) - vnlen + vvlen + 1);
if (!newstr) {

View file

@ -213,21 +213,36 @@ static void invoke_swaybar(struct bar_config *bar) {
sway_log(SWAY_ERROR, "Failed to create fork for swaybar");
return;
} else if (pid == 0) {
if (!sway_set_cloexec(sockets[1], false)) {
// Remove the SIGUSR1 handler that wlroots adds for xwayland
sigset_t set;
sigemptyset(&set);
sigprocmask(SIG_SETMASK, &set, NULL);
signal(SIGPIPE, SIG_DFL);
restore_nofile_limit();
pid = fork();
if (pid < 0) {
sway_log_errno(SWAY_ERROR, "fork failed");
_exit(EXIT_FAILURE);
} else if (pid == 0) {
if (!sway_set_cloexec(sockets[1], false)) {
_exit(EXIT_FAILURE);
}
char wayland_socket_str[16];
snprintf(wayland_socket_str, sizeof(wayland_socket_str),
"%d", sockets[1]);
setenv("WAYLAND_SOCKET", wayland_socket_str, true);
// run custom swaybar
char *const cmd[] = {
bar->swaybar_command ? bar->swaybar_command : "swaybar",
"-b", bar->id, NULL};
execvp(cmd[0], cmd);
_exit(EXIT_FAILURE);
}
char wayland_socket_str[16];
snprintf(wayland_socket_str, sizeof(wayland_socket_str),
"%d", sockets[1]);
setenv("WAYLAND_SOCKET", wayland_socket_str, true);
// run custom swaybar
char *const cmd[] = {
bar->swaybar_command ? bar->swaybar_command : "swaybar",
"-b", bar->id, NULL};
execvp(cmd[0], cmd);
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
if (close(sockets[1]) != 0) {
@ -235,6 +250,11 @@ static void invoke_swaybar(struct bar_config *bar) {
return;
}
if (waitpid(pid, NULL, 0) < 0) {
sway_log_errno(SWAY_ERROR, "waitpid failed");
return;
}
sway_log(SWAY_DEBUG, "Spawned swaybar %s", bar->id);
}

View file

@ -300,7 +300,7 @@ struct input_config *store_input_config(struct input_config *ic,
return NULL;
}
bool type = has_prefix(ic->identifier, "type:");
bool type = strncmp(ic->identifier, "type:", strlen("type:")) == 0;
if (type && error && !validate_type_on_existing(ic, error)) {
return NULL;
}

View file

@ -6,7 +6,6 @@
#include <sys/wait.h>
#include <unistd.h>
#include <wlr/config.h>
#include <wlr/render/allocator.h>
#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_output.h>
@ -67,7 +66,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 = INT_MAX;
oc->x = oc->y = -1;
oc->scale = -1;
oc->scale_filter = SCALE_FILTER_DEFAULT;
oc->transform = -1;
@ -79,7 +78,6 @@ 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;
}
@ -94,11 +92,11 @@ static void supersede_output_config(struct output_config *dst, struct output_con
if (src->height != -1) {
dst->height = -1;
}
if (src->x != INT_MAX) {
dst->x = INT_MAX;
if (src->x != -1) {
dst->x = -1;
}
if (src->y != INT_MAX) {
dst->y = INT_MAX;
if (src->y != -1) {
dst->y = -1;
}
if (src->scale != -1) {
dst->scale = -1;
@ -130,13 +128,6 @@ 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;
@ -152,12 +143,6 @@ 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
@ -171,10 +156,10 @@ static void merge_output_config(struct output_config *dst, struct output_config
if (src->height != -1) {
dst->height = src->height;
}
if (src->x != INT_MAX) {
if (src->x != -1) {
dst->x = src->x;
}
if (src->y != INT_MAX) {
if (src->y != -1) {
dst->y = src->y;
}
if (src->scale != -1) {
@ -233,9 +218,6 @@ 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) {
@ -278,11 +260,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) (hdr: %d)",
"(max render time: %d) (allow tearing: %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->hdr);
oc->max_render_time, oc->allow_tearing);
// 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.
@ -303,6 +285,7 @@ static void set_mode(struct wlr_output *output, struct wlr_output_state *pending
mhz = mhz <= 0 ? INT_MAX : mhz;
if (wl_list_empty(&output->modes) || custom) {
sway_log(SWAY_DEBUG, "Assigning custom mode to %s", output->name);
wlr_output_state_set_custom_mode(pending, width, height,
refresh_rate > 0 ? mhz : 0);
return;
@ -322,7 +305,10 @@ static void set_mode(struct wlr_output *output, struct wlr_output_state *pending
}
}
}
if (!best) {
if (best) {
sway_log(SWAY_INFO, "Assigning configured mode (%dx%d@%.3fHz) to %s",
best->width, best->height, best->refresh / 1000.f, output->name);
} else {
best = wlr_output_preferred_mode(output);
sway_log(SWAY_INFO, "Configured mode (%dx%d@%.3fHz) not available, "
"applying preferred mode (%dx%d@%.3fHz)",
@ -339,6 +325,7 @@ static void set_modeline(struct wlr_output *output,
sway_log(SWAY_ERROR, "Modeline can only be set to DRM output");
return;
}
sway_log(SWAY_DEBUG, "Assigning custom modeline to %s", output->name);
struct wlr_output_mode *mode = wlr_drm_connector_add_mode(output, drm_mode);
if (mode) {
wlr_output_state_set_mode(pending, mode);
@ -348,45 +335,6 @@ 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) {
@ -443,6 +391,7 @@ static int compute_default_scale(struct wlr_output *output,
double dpi_x = (double) width / (output->phys_width / MM_PER_INCH);
double dpi_y = (double) height / (output->phys_height / MM_PER_INCH);
sway_log(SWAY_DEBUG, "Output DPI: %fx%f", dpi_x, dpi_y);
if (dpi_x <= HIDPI_DPI_LIMIT || dpi_y <= HIDPI_DPI_LIMIT) {
return 1;
}
@ -461,16 +410,6 @@ 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;
}
@ -488,82 +427,96 @@ static void queue_output_config(struct output_config *oc,
struct wlr_output *wlr_output = output->wlr_output;
if (output_config_is_disabling(oc)) {
sway_log(SWAY_DEBUG, "Turning off output %s", wlr_output->name);
wlr_output_state_set_enabled(pending, false);
return;
}
sway_log(SWAY_DEBUG, "Turning on output %s", wlr_output->name);
wlr_output_state_set_enabled(pending, true);
if (oc && oc->drm_mode.type != 0 && oc->drm_mode.type != (uint32_t) -1) {
sway_log(SWAY_DEBUG, "Set %s modeline",
wlr_output->name);
set_modeline(wlr_output, pending, &oc->drm_mode);
} else if (oc && oc->width > 0 && oc->height > 0) {
sway_log(SWAY_DEBUG, "Set %s mode to %dx%d (%f Hz)",
wlr_output->name, oc->width, oc->height, oc->refresh_rate);
set_mode(wlr_output, pending, oc->width, oc->height,
oc->refresh_rate, oc->custom_mode == 1);
} else if (!wl_list_empty(&wlr_output->modes)) {
sway_log(SWAY_DEBUG, "Set preferred mode");
struct wlr_output_mode *preferred_mode =
wlr_output_preferred_mode(wlr_output);
wlr_output_state_set_mode(pending, preferred_mode);
}
if (oc && oc->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN) {
if (oc && (oc->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN || config->reloading)) {
sway_log(SWAY_DEBUG, "Set %s subpixel to %s", oc->name,
sway_wl_output_subpixel_to_string(oc->subpixel));
wlr_output_state_set_subpixel(pending, oc->subpixel);
} else {
wlr_output_state_set_subpixel(pending, output->detected_subpixel);
}
enum wl_output_transform tr = WL_OUTPUT_TRANSFORM_NORMAL;
if (oc && oc->transform >= 0) {
wlr_output_state_set_transform(pending, oc->transform);
tr = oc->transform;
#if WLR_HAS_DRM_BACKEND
} else if (wlr_output_is_drm(wlr_output)) {
wlr_output_state_set_transform(pending,
wlr_drm_connector_get_panel_orientation(wlr_output));
tr = wlr_drm_connector_get_panel_orientation(wlr_output);
sway_log(SWAY_DEBUG, "Auto-detected output transform: %d", tr);
#endif
} else {
wlr_output_state_set_transform(pending, WL_OUTPUT_TRANSFORM_NORMAL);
}
if (wlr_output->transform != tr) {
sway_log(SWAY_DEBUG, "Set %s transform to %d", wlr_output->name, tr);
wlr_output_state_set_transform(pending, tr);
}
// Apply the scale after sorting out the mode, because the scale
// auto-detection reads the pending output size
// Apply the scale last before the commit, because the scale auto-detection
// reads the pending output size
float scale;
if (oc && oc->scale > 0) {
scale = oc->scale;
// The factional-scale-v1 protocol uses increments of 120ths to send
// the scale factor to the client. Adjust the scale so that we use the
// same value as the clients'.
wlr_output_state_set_scale(pending, round(oc->scale * 120) / 120);
float adjusted_scale = round(scale * 120) / 120;
if (scale != adjusted_scale) {
sway_log(SWAY_INFO, "Adjusting output scale from %f to %f",
scale, adjusted_scale);
scale = adjusted_scale;
}
} else {
wlr_output_state_set_scale(pending,
compute_default_scale(wlr_output, pending));
scale = compute_default_scale(wlr_output, pending);
sway_log(SWAY_DEBUG, "Auto-detected output scale: %f", scale);
}
if (scale != wlr_output->scale) {
sway_log(SWAY_DEBUG, "Set %s scale to %f", wlr_output->name, scale);
wlr_output_state_set_scale(pending, scale);
}
if (wlr_output->adaptive_sync_supported) {
if (oc && oc->adaptive_sync != -1) {
wlr_output_state_set_adaptive_sync_enabled(pending, oc->adaptive_sync == 1);
if (oc && oc->adaptive_sync != -1 && wlr_output->adaptive_sync_supported) {
sway_log(SWAY_DEBUG, "Set %s adaptive sync to %d", wlr_output->name,
oc->adaptive_sync);
wlr_output_state_set_adaptive_sync_enabled(pending, oc->adaptive_sync == 1);
}
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_adaptive_sync_enabled(pending, false);
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,
const struct wlr_output_state *applied) {
static bool finalize_output_config(struct output_config *oc, struct sway_output *output) {
if (output == root->fallback_output) {
return false;
}
@ -578,64 +531,69 @@ static bool finalize_output_config(struct output_config *oc, struct sway_output
return true;
}
enum scale_filter_mode scale_filter_old = output->scale_filter;
enum scale_filter_mode scale_filter_new = oc ? oc->scale_filter : SCALE_FILTER_DEFAULT;
switch (scale_filter_new) {
case SCALE_FILTER_DEFAULT:
case SCALE_FILTER_SMART:
output->scale_filter = ceilf(wlr_output->scale) == wlr_output->scale ?
SCALE_FILTER_NEAREST : SCALE_FILTER_LINEAR;
break;
case SCALE_FILTER_LINEAR:
case SCALE_FILTER_NEAREST:
output->scale_filter = scale_filter_new;
break;
}
if (scale_filter_old != output->scale_filter) {
sway_log(SWAY_DEBUG, "Set %s scale_filter to %s", oc->name,
sway_output_scale_filter_to_string(output->scale_filter));
wlr_damage_ring_add_whole(&output->scene_output->damage_ring);
if (oc) {
enum scale_filter_mode scale_filter_old = output->scale_filter;
switch (oc->scale_filter) {
case SCALE_FILTER_DEFAULT:
case SCALE_FILTER_SMART:
output->scale_filter = ceilf(wlr_output->scale) == wlr_output->scale ?
SCALE_FILTER_NEAREST : SCALE_FILTER_LINEAR;
break;
case SCALE_FILTER_LINEAR:
case SCALE_FILTER_NEAREST:
output->scale_filter = oc->scale_filter;
break;
}
if (scale_filter_old != output->scale_filter) {
sway_log(SWAY_DEBUG, "Set %s scale_filter to %s", oc->name,
sway_output_scale_filter_to_string(output->scale_filter));
wlr_damage_ring_add_whole(&output->scene_output->damage_ring);
}
}
// Find position for it
if (oc && oc->x != INT_MAX && oc->y != INT_MAX) {
if (oc && (oc->x != -1 || oc->y != -1)) {
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 {
wlr_output_layout_add_auto(root->output_layout, wlr_output);
}
// Update output->{lx, ly, width, height}
struct wlr_box output_box;
wlr_output_layout_get_box(root->output_layout, wlr_output, &output_box);
output->lx = output_box.x;
output->ly = output_box.y;
output->width = output_box.width;
output->height = output_box.height;
if (!output->enabled) {
output_enable(output);
}
if (oc && oc->max_render_time >= 0) {
sway_log(SWAY_DEBUG, "Set %s max render time to %d",
oc->name, oc->max_render_time);
output->max_render_time = oc->max_render_time;
}
if (oc && oc->set_color_transform) {
if (oc->color_transform) {
wlr_color_transform_ref(oc->color_transform);
}
wlr_color_transform_unref(output->color_transform);
output->color_transform = oc->color_transform;
} else {
wlr_color_transform_unref(output->color_transform);
output->color_transform = NULL;
}
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;
if (oc && oc->allow_tearing >= 0) {
sway_log(SWAY_DEBUG, "Set %s allow tearing to %d",
oc->name, oc->allow_tearing);
output->allow_tearing = oc->allow_tearing;
}
return true;
}
static void output_update_position(struct sway_output *output) {
struct wlr_box output_box;
wlr_output_layout_get_box(root->output_layout, output->wlr_output, &output_box);
output->lx = output_box.x;
output->ly = output_box.y;
output->width = output_box.width;
output->height = output_box.height;
}
// find_output_config_from_list returns a merged output_config containing all
// stored configuration that applies to the specified output.
static struct output_config *find_output_config_from_list(
@ -647,6 +605,15 @@ static struct output_config *find_output_config_from_list(
return NULL;
}
// Set output defaults for the "base" configuration
result->enabled = 1;
result->power = 1;
result->scale = 0; // auto
result->subpixel = sway_output->detected_subpixel;
result->transform = WL_OUTPUT_TRANSFORM_NORMAL;
result->max_render_time = 0;
result->allow_tearing = 0;
char id[128];
output_get_identifier(id, sizeof(id), sway_output);
@ -725,13 +692,6 @@ static void dump_output_state(struct wlr_output *wlr_output, struct wlr_output_s
sway_log(SWAY_DEBUG, " adaptive_sync: %s",
state->adaptive_sync_enabled ? "enabled": "disabled");
}
if (state->committed & WLR_OUTPUT_STATE_SCALE) {
sway_log(SWAY_DEBUG, " scale: %f", state->scale);
}
if (state->committed & WLR_OUTPUT_STATE_SUBPIXEL) {
sway_log(SWAY_DEBUG, " subpixel: %s",
sway_wl_output_subpixel_to_string(state->subpixel));
}
}
static bool search_valid_config(struct search_context *ctx, size_t output_idx);
@ -846,15 +806,17 @@ 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 = get_config_render_bit_depth(cfg->config);
wlr_output_get_primary_formats(wlr_output, WLR_BUFFER_CAP_DMABUF);
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;
}
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) {
continue;
}
// If primary_formats is NULL, all formats are supported
if (primary_formats && !wlr_drm_format_set_get(primary_formats, fmts[idx])) {
if (!wlr_drm_format_set_get(primary_formats, fmts[idx])) {
// This is not a supported format for this output
continue;
}
@ -944,8 +906,9 @@ static bool apply_resolved_output_configs(struct matched_output_config *configs,
backend_state->output = cfg->output->wlr_output;
wlr_output_state_init(&backend_state->base);
sway_log(SWAY_DEBUG, "Preparing config for %s",
cfg->output->wlr_output->name);
queue_output_config(cfg->config, cfg->output, &backend_state->base);
dump_output_state(cfg->output->wlr_output, &backend_state->base);
}
struct wlr_output_swapchain_manager swapchain_mgr;
@ -1002,17 +965,9 @@ 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, &backend_state->base);
}
// Output layout being applied in finalize_output_config can shift outputs
// around, so we do a second pass to update positions and arrange.
for (size_t idx = 0; idx < configs_len; idx++) {
struct matched_output_config *cfg = &configs[idx];
output_update_position(cfg->output);
finalize_output_config(cfg->config, cfg->output);
arrange_layers(cfg->output);
}
@ -1088,7 +1043,6 @@ void free_output_config(struct output_config *oc) {
free(oc->name);
free(oc->background);
free(oc->background_option);
free(oc->background_fallback);
wlr_color_transform_unref(oc->color_transform);
free(oc);
}
@ -1130,27 +1084,42 @@ static bool _spawn_swaybg(char **command) {
sway_log_errno(SWAY_ERROR, "fork failed");
return false;
} else if (pid == 0) {
if (!sway_set_cloexec(sockets[1], false)) {
restore_nofile_limit();
pid = fork();
if (pid < 0) {
sway_log_errno(SWAY_ERROR, "fork failed");
_exit(EXIT_FAILURE);
} else if (pid == 0) {
if (!sway_set_cloexec(sockets[1], false)) {
_exit(EXIT_FAILURE);
}
char wayland_socket_str[16];
snprintf(wayland_socket_str, sizeof(wayland_socket_str),
"%d", sockets[1]);
setenv("WAYLAND_SOCKET", wayland_socket_str, true);
execvp(command[0], command);
sway_log_errno(SWAY_ERROR, "failed to execute '%s' "
"(background configuration probably not applied)",
command[0]);
_exit(EXIT_FAILURE);
}
char wayland_socket_str[16];
snprintf(wayland_socket_str, sizeof(wayland_socket_str),
"%d", sockets[1]);
setenv("WAYLAND_SOCKET", wayland_socket_str, true);
execvp(command[0], command);
sway_log_errno(SWAY_ERROR, "failed to execute '%s' "
"(background configuration probably not applied)",
command[0]);
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
if (close(sockets[1]) != 0) {
sway_log_errno(SWAY_ERROR, "close failed");
return false;
}
return true;
int fork_status = 0;
if (waitpid(pid, &fork_status, 0) < 0) {
sway_log_errno(SWAY_ERROR, "waitpid failed");
return false;
}
return WIFEXITED(fork_status) && WEXITSTATUS(fork_status) == EXIT_SUCCESS;
}
bool spawn_swaybg(void) {

View file

@ -34,11 +34,7 @@ bool criteria_is_empty(struct criteria *criteria) {
&& !criteria->tiling
&& !criteria->urgent
&& !criteria->workspace
&& !criteria->pid
&& !criteria->sandbox_engine
&& !criteria->sandbox_app_id
&& !criteria->sandbox_instance_id
&& !criteria->tag;
&& !criteria->pid;
}
// The error pointer is used for parsing functions, and saves having to pass it
@ -102,10 +98,6 @@ void criteria_destroy(struct criteria *criteria) {
#endif
pattern_destroy(criteria->con_mark);
pattern_destroy(criteria->workspace);
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);
@ -256,86 +248,6 @@ static bool criteria_matches_view(struct criteria *criteria,
}
}
if (criteria->sandbox_engine) {
const char *sandbox_engine = view_get_sandbox_engine(view);
if (!sandbox_engine) {
return false;
}
switch (criteria->sandbox_engine->match_type) {
case PATTERN_FOCUSED:
if (focused && lenient_strcmp(sandbox_engine, view_get_sandbox_engine(focused))) {
return false;
}
break;
case PATTERN_PCRE2:
if (regex_cmp(sandbox_engine, criteria->sandbox_engine->regex) < 0) {
return false;
}
break;
}
}
if (criteria->sandbox_app_id) {
const char *sandbox_app_id = view_get_sandbox_app_id(view);
if (!sandbox_app_id) {
return false;
}
switch (criteria->sandbox_app_id->match_type) {
case PATTERN_FOCUSED:
if (focused && lenient_strcmp(sandbox_app_id, view_get_sandbox_app_id(focused))) {
return false;
}
break;
case PATTERN_PCRE2:
if (regex_cmp(sandbox_app_id, criteria->sandbox_app_id->regex) < 0) {
return false;
}
break;
}
}
if (criteria->sandbox_instance_id) {
const char *sandbox_instance_id = view_get_sandbox_instance_id(view);
if (!sandbox_instance_id) {
return false;
}
switch (criteria->sandbox_instance_id->match_type) {
case PATTERN_FOCUSED:
if (focused && lenient_strcmp(sandbox_instance_id, view_get_sandbox_instance_id(focused))) {
return false;
}
break;
case PATTERN_PCRE2:
if (regex_cmp(sandbox_instance_id, criteria->sandbox_instance_id->regex) < 0) {
return false;
}
break;
}
}
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;
}
@ -563,10 +475,6 @@ enum criteria_token {
T_URGENT,
T_WORKSPACE,
T_PID,
T_SANDBOX_ENGINE,
T_SANDBOX_APP_ID,
T_SANDBOX_INSTANCE_ID,
T_TAG,
T_INVALID,
};
@ -606,14 +514,6 @@ static enum criteria_token token_from_name(char *name) {
return T_FLOATING;
} else if (strcmp(name, "pid") == 0) {
return T_PID;
} else if (strcmp(name, "sandbox_engine") == 0) {
return T_SANDBOX_ENGINE;
} else if (strcmp(name, "sandbox_app_id") == 0) {
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;
}
@ -655,7 +555,8 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) {
if (strcmp(value, "__focused__") == 0) {
struct sway_seat *seat = input_manager_current_seat();
struct sway_container *focus = seat_get_focused_container(seat);
criteria->con_id = focus ? focus->node.id : 0;
struct sway_view *view = focus ? focus->view : NULL;
criteria->con_id = view ? view->container->node.id : 0;
} else {
criteria->con_id = strtoul(value, &endptr, 10);
if (*endptr != 0) {
@ -716,18 +617,6 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) {
error = strdup("The value for 'pid' should be numeric");
}
break;
case T_SANDBOX_ENGINE:
pattern_create(&criteria->sandbox_engine, value);
break;
case T_SANDBOX_APP_ID:
pattern_create(&criteria->sandbox_app_id, value);
break;
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

@ -1,6 +1,5 @@
#include <stdlib.h>
#include <wlr/types/wlr_idle_notify_v1.h>
#include <wlr/types/wlr_session_lock_v1.h>
#include "log.h"
#include "sway/desktop/idle_inhibit_v1.h"
#include "sway/input/seat.h"
@ -45,14 +44,6 @@ void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) {
sway_idle_inhibit_v1_check_active();
}
void handle_manager_destroy(struct wl_listener *listener, void *data) {
struct sway_idle_inhibit_manager_v1 *manager =
wl_container_of(listener, manager, manager_destroy);
wl_list_remove(&manager->manager_destroy.link);
wl_list_remove(&manager->new_idle_inhibitor_v1.link);
}
void sway_idle_inhibit_v1_user_inhibitor_register(struct sway_view *view,
enum sway_idle_inhibit_mode mode) {
struct sway_idle_inhibit_manager_v1 *manager = &server.idle_inhibit_manager_v1;
@ -112,34 +103,11 @@ void sway_idle_inhibit_v1_user_inhibitor_destroy(
}
bool sway_idle_inhibit_v1_is_active(struct sway_idle_inhibitor_v1 *inhibitor) {
if (server.session_lock.lock) {
// A session lock is active. In this case, only application inhibitors
// on the session lock surface can have any effect.
if (inhibitor->mode != INHIBIT_IDLE_APPLICATION) {
return false;
}
struct wlr_surface *wlr_surface = inhibitor->wlr_inhibitor->surface;
if (!wlr_session_lock_surface_v1_try_from_wlr_surface(wlr_surface)) {
return false;
}
return wlr_surface->mapped;
}
switch (inhibitor->mode) {
case INHIBIT_IDLE_APPLICATION:;
struct wlr_surface *wlr_surface = inhibitor->wlr_inhibitor->surface;
struct wlr_layer_surface_v1 *layer_surface =
wlr_layer_surface_v1_try_from_wlr_surface(wlr_surface);
if (layer_surface) {
// Layer surfaces can be occluded but are always on screen after
// they have been mapped.
return layer_surface->output && layer_surface->output->enabled &&
wlr_surface->mapped;
}
// If there is no view associated with the inhibitor, assume invisible
struct sway_view *view = view_from_wlr_surface(wlr_surface);
return view && view->container && view_is_visible(view);
// If there is no view associated with the inhibitor, assume visible
struct sway_view *view = view_from_wlr_surface(inhibitor->wlr_inhibitor->surface);
return !view || !view->container || view_is_visible(view);
case INHIBIT_IDLE_FOCUS:;
struct sway_seat *seat = NULL;
wl_list_for_each(seat, &server.input->seats, link) {
@ -185,9 +153,6 @@ bool sway_idle_inhibit_manager_v1_init(void) {
wl_signal_add(&manager->wlr_manager->events.new_inhibitor,
&manager->new_idle_inhibitor_v1);
manager->new_idle_inhibitor_v1.notify = handle_idle_inhibitor_v1;
wl_signal_add(&manager->wlr_manager->events.destroy,
&manager->manager_destroy);
manager->manager_destroy.notify = handle_manager_destroy;
wl_list_init(&manager->inhibitors);
return true;

View file

@ -54,7 +54,7 @@ struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface(
}
static void arrange_surface(struct sway_output *output, const struct wlr_box *full_area,
struct wlr_box *usable_area, struct wlr_scene_tree *tree, bool exclusive) {
struct wlr_box *usable_area, struct wlr_scene_tree *tree) {
struct wlr_scene_node *node;
wl_list_for_each(node, &tree->children, link) {
struct sway_layer_surface *surface = scene_descriptor_try_get(node,
@ -68,10 +68,6 @@ static void arrange_surface(struct sway_output *output, const struct wlr_box *fu
continue;
}
if ((surface->scene->layer_surface->current.exclusive_zone > 0) != exclusive) {
continue;
}
wlr_scene_layer_surface_v1_configure(surface->scene, full_area, usable_area);
}
}
@ -82,15 +78,10 @@ void arrange_layers(struct sway_output *output) {
&usable_area.width, &usable_area.height);
const struct wlr_box full_area = usable_area;
arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay, true);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_top, true);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom, true);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_background, true);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay, false);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_top, false);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom, false);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_background, false);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_background);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_bottom);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_top);
arrange_surface(output, &full_area, &usable_area, output->layers.shell_overlay);
if (!wlr_box_equal(&usable_area, &output->usable_area)) {
sway_log(SWAY_DEBUG, "Usable area changed, rearranging output");
@ -216,6 +207,14 @@ 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_scene_node_destroy(&layer->scene->tree->node);
}
static void handle_node_destroy(struct wl_listener *listener, void *data) {
struct sway_layer_surface *layer =
wl_container_of(listener, layer, node_destroy);
@ -248,11 +247,10 @@ static void handle_node_destroy(struct wl_listener *listener, void *data) {
wl_list_remove(&layer->unmap.link);
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);
}
@ -261,8 +259,12 @@ 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 (layer_surface->initialized && committed & WLR_LAYER_SURFACE_V1_STATE_LAYER) {
if (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);
@ -467,7 +469,6 @@ 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,
@ -485,14 +486,9 @@ 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

@ -10,6 +10,7 @@
#include <wlr/types/wlr_buffer.h>
#include <wlr/types/wlr_alpha_modifier_v1.h>
#include <wlr/types/wlr_gamma_control_v1.h>
#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_output_management_v1.h>
#include <wlr/types/wlr_output_power_management_v1.h>
@ -97,11 +98,11 @@ struct buffer_timer {
};
static int handle_buffer_timer(void *data) {
struct wlr_scene_surface *scene_surface = data;
struct wlr_scene_buffer *buffer = data;
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
wlr_scene_surface_send_frame_done(scene_surface, &now);
wlr_scene_buffer_send_frame_done(buffer, &now);
return 0;
}
@ -114,9 +115,7 @@ static void handle_buffer_timer_destroy(struct wl_listener *listener,
free(timer);
}
static struct buffer_timer *buffer_timer_get_or_create(struct wlr_scene_surface *scene_surface) {
struct wlr_scene_buffer *buffer = scene_surface->buffer;
static struct buffer_timer *buffer_timer_get_or_create(struct wlr_scene_buffer *buffer) {
struct buffer_timer *timer =
scene_descriptor_try_get(&buffer->node, SWAY_SCENE_DESC_BUFFER_TIMER);
if (timer) {
@ -129,7 +128,7 @@ static struct buffer_timer *buffer_timer_get_or_create(struct wlr_scene_surface
}
timer->frame_done_timer = wl_event_loop_add_timer(server.wl_event_loop,
handle_buffer_timer, scene_surface);
handle_buffer_timer, buffer);
if (!timer->frame_done_timer) {
free(timer);
return NULL;
@ -153,11 +152,6 @@ 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,
@ -180,13 +174,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(scene_surface);
timer = buffer_timer_get_or_create(buffer);
}
if (timer) {
wl_event_source_timer_update(timer->frame_done_timer, delay);
} else {
wlr_scene_surface_send_frame_done(scene_surface, &data->when);
wlr_scene_buffer_send_frame_done(buffer, &data->when);
}
}
@ -194,8 +188,8 @@ static enum wlr_scale_filter_mode get_scale_filter(struct sway_output *output,
struct wlr_scene_buffer *buffer) {
// if we are scaling down, we should always choose linear
if (buffer->dst_width > 0 && buffer->dst_height > 0 && (
buffer->dst_width < buffer->WLR_PRIVATE.buffer_width ||
buffer->dst_height < buffer->WLR_PRIVATE.buffer_height)) {
buffer->dst_width < buffer->buffer_width ||
buffer->dst_height < buffer->buffer_height)) {
return WLR_SCALE_FILTER_BILINEAR;
}
@ -209,7 +203,7 @@ static enum wlr_scale_filter_mode get_scale_filter(struct sway_output *output,
}
}
void output_configure_scene(struct sway_output *output,
static void output_configure_scene(struct sway_output *output,
struct wlr_scene_node *node, float opacity) {
if (!node->enabled) {
return;
@ -236,9 +230,7 @@ void output_configure_scene(struct sway_output *output,
// hack: don't call the scene setter because that will damage all outputs
// We don't want to damage outputs that aren't our current output that
// we're configuring
if (output) {
buffer->filter_mode = get_scale_filter(output, buffer);
}
buffer->filter_mode = get_scale_filter(output, buffer);
wlr_scene_buffer_set_opacity(buffer, opacity);
} else if (node->type == WLR_SCENE_NODE_TREE) {
@ -270,29 +262,47 @@ static bool output_can_tear(struct sway_output *output) {
static int output_repaint_timer_handler(void *data) {
struct sway_output *output = data;
output->wlr_output->frame_pending = false;
if (!output->wlr_output->enabled) {
if (!output->enabled) {
return 0;
}
output->wlr_output->frame_pending = false;
output_configure_scene(output, &root->root_scene->tree.node, 1.0f);
struct wlr_scene_output_state_options opts = {
.color_transform = output->color_transform,
};
struct wlr_output *wlr_output = output->wlr_output;
struct wlr_scene_output *scene_output = output->scene_output;
if (!wlr_scene_output_needs_frame(scene_output)) {
if (!wlr_output->needs_frame && !output->gamma_lut_changed &&
!pixman_region32_not_empty(&scene_output->pending_commit_damage)) {
return 0;
}
struct wlr_output_state pending;
wlr_output_state_init(&pending);
if (!wlr_scene_output_build_state(output->scene_output, &pending, &opts)) {
wlr_output_state_finish(&pending);
return 0;
}
if (output->gamma_lut_changed) {
output->gamma_lut_changed = false;
struct wlr_gamma_control_v1 *gamma_control =
wlr_gamma_control_manager_v1_get_control(
server.gamma_control_manager_v1, output->wlr_output);
if (!wlr_gamma_control_v1_apply(gamma_control, &pending)) {
wlr_output_state_finish(&pending);
return 0;
}
if (!wlr_output_test_state(output->wlr_output, &pending)) {
wlr_gamma_control_v1_send_failed_and_destroy(gamma_control);
wlr_output_state_set_gamma_lut(&pending, 0, NULL, NULL, NULL);
}
}
if (output_can_tear(output)) {
pending.tearing_page_flip = true;
@ -416,43 +426,27 @@ void request_modeset(void) {
}
}
bool modeset_is_pending(void) {
return server.delayed_modeset != NULL;
}
void force_modeset(void) {
if (server.delayed_modeset != NULL) {
wl_event_source_remove(server.delayed_modeset);
server.delayed_modeset = NULL;
}
apply_stored_output_configs();
}
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);
wl_list_remove(&output->commit.link);
wl_list_remove(&output->present.link);
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;
wl_event_source_remove(output->repaint_timer);
output->repaint_timer = NULL;
request_modeset();
}
@ -466,6 +460,20 @@ static void handle_layout_destroy(struct wl_listener *listener, void *data) {
begin_destroy(output);
}
static void handle_commit(struct wl_listener *listener, void *data) {
struct sway_output *output = wl_container_of(listener, output, commit);
struct wlr_output_event_commit *event = data;
if (!output->enabled) {
return;
}
// Next time the output is enabled, try to re-apply the gamma LUT
if ((event->state->committed & WLR_OUTPUT_STATE_ENABLED) && !output->wlr_output->enabled) {
output->gamma_lut_changed = true;
}
}
static void handle_present(struct wl_listener *listener, void *data) {
struct sway_output *output = wl_container_of(listener, output, present);
struct wlr_output_event_present *output_event = data;
@ -474,7 +482,7 @@ static void handle_present(struct wl_listener *listener, void *data) {
return;
}
output->last_presentation = output_event->when;
output->last_presentation = *output_event->when;
output->refresh_nsec = output_event->refresh;
}
@ -482,44 +490,20 @@ static void handle_request_state(struct wl_listener *listener, void *data) {
struct sway_output *output =
wl_container_of(listener, output, request_state);
const struct wlr_output_event_request_state *event = data;
const struct wlr_output_state *state = event->state;
// Store the requested changes so that the active configuration is
// consistent with the current state, and to avoid duplicate logic to apply
// the changes.
struct output_config *oc = new_output_config(output->wlr_output->name);
if (!oc) {
sway_log(SWAY_ERROR, "Allocation failed");
return;
}
uint32_t committed = event->state->committed;
wlr_output_commit_state(output->wlr_output, event->state);
int committed = state->committed;
if (committed & WLR_OUTPUT_STATE_MODE) {
if (state->mode != NULL) {
oc->width = state->mode->width;
oc->height = state->mode->height;
oc->refresh_rate = state->mode->refresh / 1000.f;
} else {
oc->width = state->custom_mode.width;
oc->height = state->custom_mode.height;
oc->refresh_rate = state->custom_mode.refresh / 1000.f;
}
committed &= ~WLR_OUTPUT_STATE_MODE;
}
if (committed & WLR_OUTPUT_STATE_SCALE) {
oc->scale = state->scale;
committed &= ~WLR_OUTPUT_STATE_SCALE;
}
if (committed & WLR_OUTPUT_STATE_TRANSFORM) {
oc->transform = state->transform;
committed &= ~WLR_OUTPUT_STATE_TRANSFORM;
}
if (committed & (
WLR_OUTPUT_STATE_MODE |
WLR_OUTPUT_STATE_TRANSFORM |
WLR_OUTPUT_STATE_SCALE)) {
arrange_layers(output);
arrange_output(output);
transaction_commit_dirty();
// We do not expect or support any other changes here
assert(committed == 0);
store_output_config(oc);
force_modeset();
update_output_manager_config(output->server);
}
}
static unsigned int last_headless_num = 0;
@ -583,6 +567,8 @@ void handle_new_output(struct wl_listener *listener, void *data) {
output->layout_destroy.notify = handle_layout_destroy;
wl_signal_add(&wlr_output->events.destroy, &output->destroy);
output->destroy.notify = handle_destroy;
wl_signal_add(&wlr_output->events.commit, &output->commit);
output->commit.notify = handle_commit;
wl_signal_add(&wlr_output->events.present, &output->present);
output->present.notify = handle_present;
wl_signal_add(&wlr_output->events.frame, &output->frame);
@ -600,13 +586,24 @@ void handle_new_output(struct wl_listener *listener, void *data) {
request_modeset();
}
void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data) {
struct sway_server *server =
wl_container_of(listener, server, gamma_control_set_gamma);
const struct wlr_gamma_control_manager_v1_set_gamma_event *event = data;
struct sway_output *output = event->output->data;
if(!output) {
return;
}
output->gamma_lut_changed = true;
wlr_output_schedule_frame(output->wlr_output);
}
static struct output_config *output_config_for_config_head(
struct wlr_output_configuration_head_v1 *config_head) {
struct output_config *oc = new_output_config(config_head->state.output->name);
if (!oc) {
return NULL;
}
oc->enabled = config_head->state.enabled;
if (!oc->enabled) {
return oc;
@ -637,8 +634,7 @@ static void output_manager_apply(struct sway_server *server,
size_t configs_len = config->output_configs->length + wl_list_length(&cfg->heads);
struct output_config **configs = calloc(configs_len, sizeof(*configs));
if (!configs) {
sway_log(SWAY_ERROR, "Allocation failed");
goto error;
goto done;
}
size_t start_new_configs = config->output_configs->length;
for (size_t idx = 0; idx < start_new_configs; idx++) {
@ -651,10 +647,6 @@ static void output_manager_apply(struct sway_server *server,
// Generate the configuration and store it as a temporary
// config. We keep a record of it so we can remove it later.
struct output_config *oc = output_config_for_config_head(config_head);
if (!oc) {
sway_log(SWAY_ERROR, "Allocation failed");
goto error_config;
}
configs[config_idx++] = oc;
}
@ -662,8 +654,6 @@ static void output_manager_apply(struct sway_server *server,
// if any output configured for enablement fails to be enabled, even if it
// was not part of the config heads we were asked to configure.
ok = apply_output_configs(configs, configs_len, test_only, false);
error_config:
for (size_t idx = start_new_configs; idx < configs_len; idx++) {
struct output_config *cfg = configs[idx];
if (!test_only && ok) {
@ -674,7 +664,7 @@ error_config:
}
free(configs);
error:
done:
if (ok) {
wlr_output_configuration_v1_send_succeeded(cfg);
if (server->delayed_modeset != NULL) {
@ -709,11 +699,6 @@ void handle_output_power_manager_set_mode(struct wl_listener *listener,
struct sway_output *output = event->output->data;
struct output_config *oc = new_output_config(output->wlr_output->name);
if (!oc) {
sway_log(SWAY_ERROR, "Allocation failed");
return;
}
switch (event->mode) {
case ZWLR_OUTPUT_POWER_V1_MODE_OFF:
oc->power = 0;

View file

@ -309,13 +309,12 @@ 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);
int net_height = height - title_bar_height;
if (activated && width > 0 && net_height > 0) {
arrange_container(child, width, net_height, title_bar_height == 0, 0);
if (activated) {
arrange_container(child, width, height - title_bar_height,
title_bar_height == 0, 0);
} else {
disable_container(child);
}
@ -339,13 +338,12 @@ 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_height;
if (activated && width > 0 && net_height > 0) {
arrange_container(child, width, net_height, title_bar_height == 0, 0);
if (activated) {
arrange_container(child, width, height - title_height,
title_bar_height == 0, 0);
} else {
disable_container(child);
}
@ -361,12 +359,8 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
wlr_scene_node_set_enabled(&child->border.tree->node, true);
wlr_scene_node_set_position(&child->scene_tree->node, 0, off);
wlr_scene_node_reparent(&child->scene_tree->node, content);
if (width > 0 && cheight > 0) {
arrange_container(child, width, cheight, true, gaps);
off += cheight + gaps;
} else {
disable_container(child);
}
arrange_container(child, width, cheight, true, gaps);
off += cheight + gaps;
}
} else if (layout == L_HORIZ) {
int off = 0;
@ -377,12 +371,8 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
wlr_scene_node_set_enabled(&child->border.tree->node, true);
wlr_scene_node_set_position(&child->scene_tree->node, off, 0);
wlr_scene_node_reparent(&child->scene_tree->node, content);
if (cwidth > 0 && height > 0) {
arrange_container(child, cwidth, height, true, gaps);
off += cwidth + gaps;
} else {
disable_container(child);
}
arrange_container(child, cwidth, height, true, gaps);
off += cwidth + gaps;
}
} else {
sway_assert(false, "unreachable");
@ -434,14 +424,13 @@ static void arrange_container(struct sway_container *con,
int border_bottom = con->current.border_bottom ? border_width : 0;
int border_left = con->current.border_left ? border_width : 0;
int border_right = con->current.border_right ? border_width : 0;
int vert_border_height = MAX(0, height - border_top - border_bottom);
wlr_scene_rect_set_size(con->border.top, width, border_top);
wlr_scene_rect_set_size(con->border.bottom, width, border_bottom);
wlr_scene_rect_set_size(con->border.left,
border_left, vert_border_height);
border_left, height - border_top - border_bottom);
wlr_scene_rect_set_size(con->border.right,
border_right, vert_border_height);
border_right, height - border_top - border_bottom);
wlr_scene_node_set_position(&con->border.top->node, 0, 0);
wlr_scene_node_set_position(&con->border.bottom->node,
@ -534,7 +523,6 @@ 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);
@ -587,16 +575,15 @@ 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 {
@ -609,7 +596,6 @@ 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);
@ -665,15 +651,6 @@ static void arrange_root(struct sway_root *root) {
struct sway_output *output = root->outputs->items[i];
struct sway_workspace *ws = output->current.active_workspace;
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,7 +3,6 @@
#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"
@ -21,13 +20,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 *image_capture_parent);
struct wlr_scene_tree *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->image_capture_tree);
popup_create(wlr_popup, popup->view, popup->xdg_surface_tree);
}
static void popup_handle_destroy(struct wl_listener *listener, void *data) {
@ -78,8 +77,7 @@ 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 wlr_scene_tree *image_capture_parent) {
struct sway_view *view, struct wlr_scene_tree *parent) {
struct wlr_xdg_surface *xdg_surface = wlr_popup->base;
struct sway_xdg_popup *popup = calloc(1, sizeof(struct sway_xdg_popup));
@ -115,11 +113,6 @@ 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);
@ -158,8 +151,7 @@ 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) {
struct sway_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view);
if (xdg_shell_view == NULL) {
if (xdg_shell_view_from_view(view) == NULL) {
return NULL;
}
switch (prop) {
@ -167,8 +159,6 @@ 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;
}
@ -269,7 +259,6 @@ static void destroy(struct sway_view *view) {
if (xdg_shell_view == NULL) {
return;
}
free(xdg_shell_view->tag);
free(xdg_shell_view);
}
@ -301,7 +290,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,
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
// TODO: wlr_xdg_toplevel_set_bounds()
return;
}
@ -310,17 +299,18 @@ static void handle_commit(struct wl_listener *listener, void *data) {
return;
}
struct wlr_box *new_geo = &xdg_surface->geometry;
bool new_size = new_geo->width != view->geometry.width ||
new_geo->height != view->geometry.height ||
new_geo->x != view->geometry.x ||
new_geo->y != view->geometry.y;
struct wlr_box new_geo;
wlr_xdg_surface_get_geometry(xdg_surface, &new_geo);
bool new_size = new_geo.width != view->geometry.width ||
new_geo.height != view->geometry.height ||
new_geo.x != view->geometry.x ||
new_geo.y != view->geometry.y;
if (new_size) {
// The client changed its surface size in this commit. For floating
// containers, we resize the container to match. For tiling containers,
// we only recenter the surface.
memcpy(&view->geometry, new_geo, sizeof(struct wlr_box));
memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box));
if (container_is_floating(view->container)) {
view_update_size(view);
// Only set the toplevel size the current container actually has a size.
@ -370,7 +360,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->image_capture_tree);
&xdg_shell_view->view, root->layers.popup);
if (!popup) {
return;
}
@ -473,8 +463,12 @@ static void handle_map(struct wl_listener *listener, void *data) {
struct sway_view *view = &xdg_shell_view->view;
struct wlr_xdg_toplevel *toplevel = view->wlr_xdg_toplevel;
view->natural_width = toplevel->base->geometry.width;
view->natural_height = toplevel->base->geometry.height;
view->natural_width = toplevel->base->current.geometry.width;
view->natural_height = toplevel->base->current.geometry.height;
if (!view->natural_width && !view->natural_height) {
view->natural_width = toplevel->base->surface->current.width;
view->natural_height = toplevel->base->surface->current.height;
}
bool csd = false;
@ -581,17 +575,6 @@ 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

@ -71,7 +71,7 @@ static void unmanaged_handle_map(struct wl_listener *listener, void *data) {
surface->set_geometry.notify = unmanaged_handle_set_geometry;
}
if (wlr_xwayland_surface_override_redirect_wants_focus(xsurface)) {
if (wlr_xwayland_or_surface_wants_focus(xsurface)) {
struct sway_seat *seat = input_manager_current_seat();
struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland;
wlr_xwayland_set_seat(xwayland, seat->wlr_seat);
@ -96,7 +96,7 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) {
// This simply returns focus to the parent surface if there's one available.
// This seems to handle JetBrains issues.
if (xsurface->parent && xsurface->parent->surface
&& wlr_xwayland_surface_override_redirect_wants_focus(xsurface->parent)) {
&& wlr_xwayland_or_surface_wants_focus(xsurface->parent)) {
seat_set_focus_surface(seat, xsurface->parent->surface, false);
return;
}
@ -289,6 +289,9 @@ static void set_activated(struct sway_view *view, bool activated) {
}
wlr_xwayland_surface_activate(surface, activated);
if (activated) {
wlr_xwayland_surface_restack(surface, NULL, XCB_STACK_MODE_ABOVE);
}
}
static void set_tiled(struct sway_view *view, bool tiled) {
@ -296,7 +299,7 @@ static void set_tiled(struct sway_view *view, bool tiled) {
return;
}
struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface;
wlr_xwayland_surface_set_maximized(surface, tiled, tiled);
wlr_xwayland_surface_set_maximized(surface, tiled);
}
static void set_fullscreen(struct sway_view *view, bool fullscreen) {
@ -497,9 +500,6 @@ 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;
@ -540,9 +540,6 @@ 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,6 +32,12 @@
#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).
@ -138,7 +144,7 @@ struct sway_node *node_at_coords(
}
void cursor_rebase(struct sway_cursor *cursor) {
uint32_t time_msec = get_current_time_in_msec();
uint32_t time_msec = get_current_time_msec();
seatop_rebase(cursor->seat, time_msec);
}
@ -353,7 +359,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_in_msec();
time_msec = get_current_time_msec();
}
seatop_button(cursor->seat, time_msec, device, button, state);
@ -572,13 +578,12 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor,
// tablet events until the drag is released, even if we are now over a
// non-tablet surface.
if (!cursor->simulating_pointer_from_tool_tip &&
((surface && wlr_surface_accepts_tablet_v2(surface, tablet->tablet_v2)) ||
((surface && wlr_surface_accepts_tablet_v2(tablet->tablet_v2, surface)) ||
wlr_tablet_tool_v2_has_implicit_grab(tool->tablet_v2_tool))) {
seatop_tablet_tool_motion(seat, tool, time_msec);
} 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);
}
}
@ -659,7 +664,7 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) {
dispatch_cursor_button(cursor, &event->tablet->base, event->time_msec,
BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
} else if (!surface || !wlr_surface_accepts_tablet_v2(surface, tablet_v2)) {
} else if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) {
// If we started holding the tool tip down on a surface that accepts
// tablet v2, we should notify that surface if it gets released over a
// surface that doesn't support v2.
@ -744,7 +749,7 @@ static void handle_tool_button(struct wl_listener *listener, void *data) {
bool mod_pressed = modifiers & config->floating_mod;
bool surface_supports_tablet_events =
surface && wlr_surface_accepts_tablet_v2(surface, tablet_v2);
surface && wlr_surface_accepts_tablet_v2(tablet_v2, surface);
// Simulate pointer when:
// 1. The modifier key is pressed, OR
@ -1042,7 +1047,6 @@ void sway_cursor_destroy(struct sway_cursor *cursor) {
wl_list_remove(&cursor->touch_frame.link);
wl_list_remove(&cursor->tool_axis.link);
wl_list_remove(&cursor->tool_tip.link);
wl_list_remove(&cursor->tool_proximity.link);
wl_list_remove(&cursor->tool_button.link);
wl_list_remove(&cursor->request_set_cursor.link);
@ -1208,7 +1212,7 @@ uint32_t get_mouse_bindsym(const char *name, char **error) {
SWAY_SCROLL_UP, SWAY_SCROLL_DOWN, SWAY_SCROLL_LEFT,
SWAY_SCROLL_RIGHT, BTN_SIDE, BTN_EXTRA};
return buttons[number - 1];
} else if (has_prefix(name, "BTN_")) {
} else if (strncmp(name, "BTN_", strlen("BTN_")) == 0) {
// Get event code from name
int code = libevdev_event_code_from_name(EV_KEY, name);
if (code == -1) {
@ -1233,7 +1237,7 @@ uint32_t get_mouse_bindcode(const char *name, char **error) {
return 0;
}
const char *event = libevdev_event_code_get_name(EV_KEY, code);
if (!event || !has_prefix(event, "BTN_")) {
if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) {
*error = format_str("Event code %d (%s) is not a button",
code, event ? event : "(null)");
return 0;

View file

@ -493,14 +493,6 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) {
return input;
}
void input_manager_finish(struct sway_input_manager *input) {
wl_list_remove(&input->new_input.link);
wl_list_remove(&input->virtual_keyboard_new.link);
wl_list_remove(&input->virtual_pointer_new.link);
wl_list_remove(&input->keyboard_shortcuts_inhibit_new_inhibitor.link);
wl_list_remove(&input->transient_seat_create.link);
}
bool input_manager_has_focus(struct sway_node *node) {
struct sway_seat *seat = NULL;
wl_list_for_each(seat, &server.input->seats, link) {
@ -585,7 +577,7 @@ void input_manager_configure_all_input_mappings(void) {
void input_manager_apply_input_config(struct input_config *input_config) {
struct sway_input_device *input_device = NULL;
bool wildcard = strcmp(input_config->identifier, "*") == 0;
bool type_wildcard = has_prefix(input_config->identifier, "type:");
bool type_wildcard = strncmp(input_config->identifier, "type:", 5) == 0;
wl_list_for_each(input_device, &server.input->devices, link) {
bool type_matches = type_wildcard &&
strcmp(input_device_get_type(input_device), input_config->identifier + 5) == 0;

View file

@ -4,7 +4,6 @@
#include <wlr/config.h>
#include <wlr/backend/multi.h>
#include <wlr/interfaces/wlr_keyboard.h>
#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_keyboard.h>
#include <wlr/types/wlr_keyboard_group.h>
#include <xkbcommon/xkbcommon-names.h>
@ -268,7 +267,6 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard,
const xkb_keysym_t *pressed_keysyms, uint32_t modifiers, size_t keysyms_len) {
for (size_t i = 0; i < keysyms_len; ++i) {
xkb_keysym_t keysym = pressed_keysyms[i];
if (keysym >= XKB_KEY_XF86Switch_VT_1 &&
keysym <= XKB_KEY_XF86Switch_VT_12) {
#if WLR_HAS_SESSION
@ -284,36 +282,6 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard,
return false;
}
static bool keyboard_execute_pointer_keysyms(struct sway_keyboard *keyboard,
uint32_t time, const xkb_keysym_t *pressed_keysyms, size_t keysyms_len,
enum wl_keyboard_key_state state) {
struct sway_cursor *cursor = keyboard->seat_device->sway_seat->cursor;
for (size_t i = 0; i < keysyms_len; ++i) {
xkb_keysym_t keysym = pressed_keysyms[i];
uint32_t button = wlr_keyboard_keysym_to_pointer_button(keysym);
if (button != 0) {
dispatch_cursor_button(cursor, &keyboard->wlr->base, time, button,
(enum wl_pointer_button_state)state);
wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
return true;
}
int dx, dy;
wlr_keyboard_keysym_to_pointer_motion(keysym, &dx, &dy);
if (state == WL_KEYBOARD_KEY_STATE_PRESSED && (dx != 0 || dy != 0)) {
dx *= 10;
dy *= 10;
pointer_motion(cursor, time, &keyboard->wlr->base, dx, dy, dx, dy);
wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
return true;
}
}
return false;
}
/**
* Get keysyms and modifiers from the keyboard as xkb sees them.
*
@ -539,11 +507,6 @@ static void handle_key_event(struct sway_keyboard *keyboard,
keyboard, keyinfo.raw_keysyms, keyinfo.raw_modifiers,
keyinfo.raw_keysyms_len);
}
if (!handled) {
handled = keyboard_execute_pointer_keysyms(keyboard, event->time_msec,
keyinfo.translated_keysyms, keyinfo.translated_keysyms_len,
event->state);
}
if (event->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
// If the pressed event was sent to a client and we have a focused
@ -980,10 +943,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

@ -391,19 +391,6 @@ 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;
@ -417,7 +404,18 @@ bool sway_libinput_device_is_builtin(struct sway_input_device *sway_device) {
return false;
}
bool is_builtin = sway_udev_device_is_builtin(udev_device);
udev_device_unref(udev_device);
return is_builtin;
const char *id_path = udev_device_get_property_value(udev_device, "ID_PATH");
if (!id_path) {
return false;
}
const char prefix_platform[] = "platform-";
if (strncmp(id_path, prefix_platform, strlen(prefix_platform)) != 0) {
return false;
}
const char prefix_pci[] = "pci-";
const char infix_platform[] = "-platform-";
return (strncmp(id_path, prefix_pci, strlen(prefix_pci)) == 0) &&
strstr(id_path, infix_platform);
}

View file

@ -647,6 +647,10 @@ static void seat_reset_input_config(struct sway_seat *seat,
sway_device->input_device->wlr_device, NULL);
}
static bool has_prefix(const char *str, const char *prefix) {
return strncmp(str, prefix, strlen(prefix)) == 0;
}
/**
* Get the name of the built-in output, if any. Returns NULL if there isn't
* exactly one built-in output.
@ -1090,7 +1094,6 @@ static void seat_send_unfocus(struct sway_node *node, struct sway_seat *seat) {
static int handle_urgent_timeout(void *data) {
struct sway_view *view = data;
view_set_urgent(view, false);
container_update_itself_and_parents(view->container);
return 0;
}

View file

@ -16,7 +16,6 @@
#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
@ -274,7 +273,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat,
// Handle tapping on an xwayland unmanaged view
else if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(surface)) &&
xsurface->override_redirect &&
wlr_xwayland_surface_override_redirect_wants_focus(xsurface)) {
wlr_xwayland_or_surface_wants_focus(xsurface)) {
struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland;
wlr_xwayland_set_seat(xwayland, seat->wlr_seat);
seat_set_focus_surface(seat, xsurface->surface, false);
@ -356,13 +355,6 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat);
uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
bool mod_pressed = modifiers & config->floating_mod;
uint32_t mod_move_btn = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT;
uint32_t mod_resize_btn = config->floating_mod_inverse ? BTN_LEFT : BTN_RIGHT;
bool mod_move_btn_pressed = mod_pressed && button == mod_move_btn;
bool mod_resize_btn_pressed = mod_pressed && button == mod_resize_btn;
bool titlebar_left_btn_pressed = on_titlebar && button == BTN_LEFT;
// Handle mouse bindings
if (trigger_pointer_button_binding(seat, device, button, state, modifiers,
on_titlebar, on_border, on_contents, on_workspace)) {
@ -411,28 +403,33 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
}
// Handle tiling resize via mod
if (cont && !is_floating_or_child && mod_pressed && mod_resize_btn_pressed &&
bool mod_pressed = modifiers & config->floating_mod;
if (cont && !is_floating_or_child && mod_pressed &&
state == WL_POINTER_BUTTON_STATE_PRESSED) {
edge = 0;
edge |= cursor->cursor->x > cont->pending.x + cont->pending.width / 2 ?
WLR_EDGE_RIGHT : WLR_EDGE_LEFT;
edge |= cursor->cursor->y > cont->pending.y + cont->pending.height / 2 ?
WLR_EDGE_BOTTOM : WLR_EDGE_TOP;
uint32_t btn_resize = config->floating_mod_inverse ?
BTN_LEFT : BTN_RIGHT;
if (button == btn_resize) {
edge = 0;
edge |= cursor->cursor->x > cont->pending.x + cont->pending.width / 2 ?
WLR_EDGE_RIGHT : WLR_EDGE_LEFT;
edge |= cursor->cursor->y > cont->pending.y + cont->pending.height / 2 ?
WLR_EDGE_BOTTOM : WLR_EDGE_TOP;
const char *image = NULL;
if (edge == (WLR_EDGE_LEFT | WLR_EDGE_TOP)) {
image = "nw-resize";
} else if (edge == (WLR_EDGE_TOP | WLR_EDGE_RIGHT)) {
image = "ne-resize";
} else if (edge == (WLR_EDGE_RIGHT | WLR_EDGE_BOTTOM)) {
image = "se-resize";
} else if (edge == (WLR_EDGE_BOTTOM | WLR_EDGE_LEFT)) {
image = "sw-resize";
const char *image = NULL;
if (edge == (WLR_EDGE_LEFT | WLR_EDGE_TOP)) {
image = "nw-resize";
} else if (edge == (WLR_EDGE_TOP | WLR_EDGE_RIGHT)) {
image = "ne-resize";
} else if (edge == (WLR_EDGE_RIGHT | WLR_EDGE_BOTTOM)) {
image = "se-resize";
} else if (edge == (WLR_EDGE_BOTTOM | WLR_EDGE_LEFT)) {
image = "sw-resize";
}
cursor_set_image(seat->cursor, image, NULL);
seat_set_focus_container(seat, cont);
seatop_begin_resize_tiling(seat, cont, edge);
return;
}
cursor_set_image(seat->cursor, image, NULL);
seat_set_focus_container(seat, cont);
seatop_begin_resize_tiling(seat, cont, edge);
return;
}
// Handle changing focus when clicking on a container
@ -457,10 +454,12 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
// Handle beginning floating move
if (cont && is_floating_or_child && !is_fullscreen_or_child &&
state == WL_POINTER_BUTTON_STATE_PRESSED &&
(mod_move_btn_pressed || titlebar_left_btn_pressed)) {
seatop_begin_move_floating(seat, container_toplevel_ancestor(cont));
return;
state == WL_POINTER_BUTTON_STATE_PRESSED) {
uint32_t btn_move = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT;
if (button == btn_move && (mod_pressed || on_titlebar)) {
seatop_begin_move_floating(seat, container_toplevel_ancestor(cont));
return;
}
}
// Handle beginning floating resize
@ -474,7 +473,9 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
}
// Via mod+click
if (mod_resize_btn_pressed) {
uint32_t btn_resize = config->floating_mod_inverse ?
BTN_LEFT : BTN_RIGHT;
if (mod_pressed && button == btn_resize) {
struct sway_container *floater = container_toplevel_ancestor(cont);
edge = 0;
edge |= cursor->cursor->x > floater->pending.x + floater->pending.width / 2 ?
@ -488,15 +489,18 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
}
// Handle moving a tiling container
if (config->tiling_drag && (mod_move_btn_pressed || titlebar_left_btn_pressed) &&
if (config->tiling_drag && (mod_pressed || on_titlebar) &&
state == WL_POINTER_BUTTON_STATE_PRESSED && !is_floating_or_child &&
cont && cont->pending.fullscreen_mode == FULLSCREEN_NONE) {
cont && cont->pending.fullscreen_mode == FULLSCREEN_NONE &&
button == (config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT)) {
// If moving a container by its title bar, use a threshold for the drag
if (!mod_pressed && config->tiling_drag_threshold > 0) {
seatop_begin_move_tiling_threshold(seat, cont);
} else {
seatop_begin_move_tiling(seat, cont);
}
return;
}
@ -519,7 +523,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
if (surface &&
(xsurface = wlr_xwayland_surface_try_from_wlr_surface(surface)) &&
xsurface->override_redirect &&
wlr_xwayland_surface_override_redirect_wants_focus(xsurface)) {
wlr_xwayland_or_surface_wants_focus(xsurface)) {
struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland;
wlr_xwayland_set_seat(xwayland, seat->wlr_seat);
seat_set_focus_surface(seat, xsurface->surface, false);
@ -665,7 +669,7 @@ static void handle_touch_down(struct sway_seat *seat,
double sx, sy;
node_at_coords(seat, seat->touch_x, seat->touch_y, &surface, &sx, &sy);
if (surface && wlr_surface_accepts_touch(surface, wlr_seat)) {
if (surface && wlr_surface_accepts_touch(wlr_seat, surface)) {
if (seat_is_input_allowed(seat, surface)) {
cursor->simulating_pointer_from_touch = false;
seatop_begin_touch_down(seat, surface, event, sx, sy, lx, ly);
@ -794,7 +798,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);
}
@ -1111,7 +1115,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) && !cursor->hidden) {
if (seat_is_input_allowed(seat, surface)) {
wlr_seat_pointer_notify_enter(seat->wlr_seat, surface, sx, sy);
wlr_seat_pointer_notify_motion(seat->wlr_seat, time_msec, sx, sy);
}
@ -1149,7 +1153,5 @@ void seatop_begin_default(struct sway_seat *seat) {
seat->seatop_impl = &seatop_impl;
seat->seatop_data = e;
uint32_t time_msec = get_current_time_in_msec();
seatop_rebase(seat, time_msec);
seatop_rebase(seat, 0);
}

View file

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

View file

@ -363,7 +363,7 @@ void sway_tablet_pad_set_focus(struct sway_tablet_pad *tablet_pad,
}
if (surface == NULL ||
!wlr_surface_accepts_tablet_v2(surface, tablet_pad->tablet->tablet_v2)) {
!wlr_surface_accepts_tablet_v2(tablet_pad->tablet->tablet_v2, surface)) {
return;
}

View file

@ -10,7 +10,6 @@
#include "sway/input/text_input_popup.h"
#include "sway/layers.h"
#include "sway/server.h"
#include <wlr/types/wlr_session_lock_v1.h>
static struct sway_text_input *relay_get_focusable_text_input(
struct sway_input_method_relay *relay) {
@ -42,21 +41,23 @@ static void handle_im_commit(struct wl_listener *listener, void *data) {
if (!text_input) {
return;
}
if (relay->input_method->current.preedit.text) {
struct wlr_input_method_v2 *context = data;
assert(context == relay->input_method);
if (context->current.preedit.text) {
wlr_text_input_v3_send_preedit_string(text_input->input,
relay->input_method->current.preedit.text,
relay->input_method->current.preedit.cursor_begin,
relay->input_method->current.preedit.cursor_end);
context->current.preedit.text,
context->current.preedit.cursor_begin,
context->current.preedit.cursor_end);
}
if (relay->input_method->current.commit_text) {
if (context->current.commit_text) {
wlr_text_input_v3_send_commit_string(text_input->input,
relay->input_method->current.commit_text);
context->current.commit_text);
}
if (relay->input_method->current.delete.before_length
|| relay->input_method->current.delete.after_length) {
if (context->current.delete.before_length
|| context->current.delete.after_length) {
wlr_text_input_v3_send_delete_surrounding_text(text_input->input,
relay->input_method->current.delete.before_length,
relay->input_method->current.delete.after_length);
context->current.delete.before_length,
context->current.delete.after_length);
}
wlr_text_input_v3_send_done(text_input->input);
}
@ -64,7 +65,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 = relay->input_method->keyboard_grab;
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
struct wlr_seat *wlr_seat = keyboard_grab->input_method->seat;
wl_list_remove(&relay->input_method_keyboard_grab_destroy.link);
@ -108,6 +109,8 @@ 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);
@ -244,10 +247,6 @@ 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,10 +259,6 @@ 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;
@ -318,6 +313,8 @@ 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);
@ -388,8 +385,6 @@ static void input_popup_set_focus(struct sway_input_popup *popup,
struct wlr_layer_surface_v1 *layer_surface =
wlr_layer_surface_v1_try_from_wlr_surface(surface);
struct wlr_session_lock_surface_v1 *lock_surface =
wlr_session_lock_surface_v1_try_from_wlr_surface(surface);
struct wlr_scene_tree *relative_parent;
if (layer_surface) {
@ -409,30 +404,8 @@ static void input_popup_set_focus(struct sway_input_popup *popup,
// surface. Layer surfaces get destroyed as part of the output being
// destroyed, thus also trickling down to popups.
popup->fixed_output = layer->layer_surface->output;
} else if (lock_surface) {
wl_signal_add(&lock_surface->surface->events.unmap,
&popup->focused_surface_unmap);
struct sway_layer_surface *lock = lock_surface->data;
if (lock == NULL) {
return;
}
relative_parent = lock->scene->tree;
popup->desc.view = NULL;
// we don't need to add an event here to NULL out this field because
// this field will only be initialized if the popup is part of a layer
// surface. Layer surfaces get destroyed as part of the output being
// destroyed, thus also trickling down to popups.
popup->fixed_output = lock->layer_surface->output;
} else {
struct sway_view *view = view_from_wlr_surface(surface);
// In the future there may be other shells been added, so we also need to check here.
if (view == NULL) {
sway_log(SWAY_DEBUG, "Unsupported IME focus surface");
return;
}
wl_signal_add(&view->events.unmap, &popup->focused_surface_unmap);
relative_parent = view->scene_tree;
popup->desc.view = view;
@ -599,34 +572,6 @@ static void relay_handle_input_method(struct wl_listener *listener,
}
}
static void sway_input_method_relay_finish_text_input(struct sway_input_method_relay *relay) {
wl_list_remove(&relay->text_input_new.link);
wl_list_remove(&relay->text_input_manager_destroy.link);
wl_list_init(&relay->text_input_new.link);
wl_list_init(&relay->text_input_manager_destroy.link);
}
static void relay_handle_text_input_manager_destroy(struct wl_listener *listener, void *data) {
struct sway_input_method_relay *relay = wl_container_of(listener, relay,
text_input_manager_destroy);
sway_input_method_relay_finish_text_input(relay);
}
static void sway_input_method_relay_finish_input_method(struct sway_input_method_relay *relay) {
wl_list_remove(&relay->input_method_new.link);
wl_list_remove(&relay->input_method_manager_destroy.link);
wl_list_init(&relay->input_method_new.link);
wl_list_init(&relay->input_method_manager_destroy.link);
}
static void relay_handle_input_method_manager_destroy(struct wl_listener *listener, void *data) {
struct sway_input_method_relay *relay = wl_container_of(listener, relay,
input_method_manager_destroy);
sway_input_method_relay_finish_input_method(relay);
}
void sway_input_method_relay_init(struct sway_seat *seat,
struct sway_input_method_relay *relay) {
relay->seat = seat;
@ -634,24 +579,18 @@ 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.new_text_input,
wl_signal_add(&server.text_input->events.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,
&relay->text_input_manager_destroy);
relay->input_method_new.notify = relay_handle_input_method;
wl_signal_add(
&server.input_method->events.new_input_method,
&server.input_method->events.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,
&relay->input_method_manager_destroy);
}
void sway_input_method_relay_finish(struct sway_input_method_relay *relay) {
sway_input_method_relay_finish_text_input(relay);
sway_input_method_relay_finish_input_method(relay);
wl_list_remove(&relay->input_method_new.link);
wl_list_remove(&relay->text_input_new.link);
}
void sway_input_method_relay_set_focus(struct sway_input_method_relay *relay,

View file

@ -6,7 +6,6 @@
#include <wlr/config.h>
#include <wlr/types/wlr_content_type_v1.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_ext_foreign_toplevel_list_v1.h>
#include <xkbcommon/xkbcommon.h>
#include "config.h"
#include "log.h"
@ -318,14 +317,6 @@ 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,
@ -408,8 +399,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) {
@ -586,10 +577,6 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object
json_object_object_add(object, "app_id",
app_id ? json_object_new_string(app_id) : NULL);
json_object_object_add(object, "foreign_toplevel_identifier",
c->view->ext_foreign_toplevel ?
json_object_new_string(c->view->ext_foreign_toplevel->identifier) : NULL);
bool visible = view_is_visible(c->view);
json_object_object_add(object, "visible", json_object_new_boolean(visible));
@ -615,21 +602,6 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object
json_object_object_add(object, "inhibit_idle",
json_object_new_boolean(view_inhibit_idle(c->view)));
const char *sandbox_engine = view_get_sandbox_engine(c->view);
json_object_object_add(object, "sandbox_engine",
sandbox_engine ? json_object_new_string(sandbox_engine) : NULL);
const char *sandbox_app_id = view_get_sandbox_app_id(c->view);
json_object_object_add(object, "sandbox_app_id",
sandbox_app_id ? json_object_new_string(sandbox_app_id) : NULL);
const char *sandbox_instance_id = view_get_sandbox_instance_id(c->view);
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 =
@ -959,11 +931,6 @@ static json_object *describe_libinput_device(struct libinput_device *device) {
case LIBINPUT_CONFIG_DRAG_LOCK_DISABLED:
drag_lock = "disabled";
break;
#if HAVE_LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY
case LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY:
drag_lock = "enabled_sticky";
break;
#endif
}
json_object_object_add(object, "tap_drag_lock",
json_object_new_string(drag_lock));

View file

@ -648,12 +648,6 @@ void ipc_client_handle_command(struct ipc_client *client, uint32_t payload_lengt
}
list_t *res_list = execute_command(buf, NULL, NULL);
if (modeset_is_pending()) {
// IPC expects commands to have taken immediate effect, so we need
// to force a modeset after output commands. We do a single modeset
// here to avoid modesetting for every output command in sequence.
force_modeset();
}
transaction_commit_dirty();
char *json = cmd_results_to_json(res_list);
int length = strlen(json);

View file

@ -234,9 +234,6 @@ static void handle_unlock(struct wl_listener *listener, void *data) {
struct sway_output *output = root->outputs->items[i];
arrange_layers(output);
}
// Views are now visible, so check if we need to activate inhibition again.
sway_idle_inhibit_v1_check_active();
}
static void handle_abandon(struct wl_listener *listener, void *data) {
@ -300,10 +297,6 @@ static void handle_session_lock(struct wl_listener *listener, void *data) {
wlr_session_lock_v1_send_locked(lock);
server.session_lock.lock = sway_lock;
// The lock screen covers everything, so check if any active inhibition got
// deactivated due to lost visibility.
sway_idle_inhibit_v1_check_active();
}
static void handle_session_lock_destroy(struct wl_listener *listener, void *data) {

View file

@ -1,6 +1,5 @@
#include <getopt.h>
#include <pango/pangocairo.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
@ -45,6 +44,10 @@ void sway_terminate(int exit_code) {
}
}
void sig_handler(int signal) {
sway_terminate(EXIT_SUCCESS);
}
void run_as_ipc_client(char *command, char *socket_path) {
int socketfd = ipc_open_socket(socket_path);
uint32_t len = strlen(command);
@ -108,14 +111,18 @@ static void log_kernel(void) {
pclose(f);
}
static void restore_nofile_limit(void) {
if (original_nofile_rlimit.rlim_cur == 0) {
return;
static bool detect_suid(void) {
if (geteuid() != 0 && getegid() != 0) {
return false;
}
if (setrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) {
sway_log_errno(SWAY_ERROR, "Failed to restore max open files limit: "
"setrlimit(NOFILE) failed");
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 increase_nofile_limit(void) {
@ -132,38 +139,17 @@ static void increase_nofile_limit(void) {
"setrlimit(NOFILE) failed");
sway_log(SWAY_INFO, "Running with %d max open files",
(int)original_nofile_rlimit.rlim_cur);
}
}
void restore_nofile_limit(void) {
if (original_nofile_rlimit.rlim_cur == 0) {
return;
}
pthread_atfork(NULL, NULL, restore_nofile_limit);
}
static int term_signal(int signal, void *data) {
sway_terminate(EXIT_SUCCESS);
return 0;
}
static void restore_signals(void) {
sigset_t set;
sigemptyset(&set);
sigprocmask(SIG_SETMASK, &set, NULL);
struct sigaction sa_dfl = { .sa_handler = SIG_DFL };
sigaction(SIGCHLD, &sa_dfl, NULL);
sigaction(SIGPIPE, &sa_dfl, NULL);
}
static void init_signals(void) {
wl_event_loop_add_signal(server.wl_event_loop, SIGTERM, term_signal, NULL);
wl_event_loop_add_signal(server.wl_event_loop, SIGINT, term_signal, NULL);
struct sigaction sa_ign = { .sa_handler = SIG_IGN };
// avoid need to reap children
sigaction(SIGCHLD, &sa_ign, NULL);
// prevent ipc write errors from crashing sway
sigaction(SIGPIPE, &sa_ign, NULL);
pthread_atfork(NULL, NULL, restore_signals);
if (setrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) {
sway_log_errno(SWAY_ERROR, "Failed to restore max open files limit: "
"setrlimit(NOFILE) failed");
}
}
void enable_debug_flag(const char *flag) {
@ -173,8 +159,10 @@ void enable_debug_flag(const char *flag) {
debug.txn_wait = true;
} else if (strcmp(flag, "txn-timings") == 0) {
debug.txn_timings = true;
} else if (has_prefix(flag, "txn-timeout=")) {
server.txn_timeout_ms = atoi(&flag[strlen("txn-timeout=")]);
} else if (strncmp(flag, "txn-timeout=", 12) == 0) {
server.txn_timeout_ms = atoi(&flag[12]);
} else if (strcmp(flag, "legacy-wl-drm") == 0) {
debug.legacy_wl_drm = true;
} else {
sway_log(SWAY_ERROR, "Unknown debug flag: %s", flag);
}
@ -278,6 +266,11 @@ 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) {
@ -329,14 +322,19 @@ int main(int argc, char **argv) {
increase_nofile_limit();
// handle SIGTERM signals
signal(SIGTERM, sig_handler);
signal(SIGINT, sig_handler);
// prevent ipc from crashing sway
signal(SIGPIPE, SIG_IGN);
sway_log(SWAY_INFO, "Starting sway version " SWAY_VERSION);
if (!server_init(&server)) {
return 1;
}
init_signals();
if (server.linux_dmabuf_v1) {
wlr_scene_set_linux_dmabuf_v1(root->root_scene, server.linux_dmabuf_v1);
}
@ -363,7 +361,6 @@ int main(int argc, char **argv) {
}
config->active = true;
force_modeset();
load_swaybars();
run_deferred_commands();
run_deferred_bindings();

View file

@ -195,7 +195,6 @@ 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,25 +10,20 @@
#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>
#include <wlr/types/wlr_data_control_v1.h>
#include <wlr/types/wlr_ext_data_control_v1.h>
#include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_drm.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>
#include <wlr/types/wlr_fractional_scale_v1.h>
#include <wlr/types/wlr_gamma_control_v1.h>
#include <wlr/types/wlr_idle_notify_v1.h>
#include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/types/wlr_linux_dmabuf_v1.h>
#include <wlr/types/wlr_linux_drm_syncobj_v1.h>
#include <wlr/types/wlr_output_management_v1.h>
#include <wlr/types/wlr_output_power_management_v1.h>
#include <wlr/types/wlr_pointer_constraints_v1.h>
@ -50,7 +45,6 @@
#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"
@ -75,7 +69,6 @@
#define SWAY_XDG_SHELL_VERSION 5
#define SWAY_LAYER_SHELL_VERSION 4
#define SWAY_FOREIGN_TOPLEVEL_LIST_VERSION 1
#define SWAY_PRESENTATION_VERSION 2
bool allow_unsupported_gpu = false;
@ -111,10 +104,8 @@ static bool is_privileged(const struct wl_global *global) {
global == server.input_method->global ||
global == server.foreign_toplevel_list->global ||
global == server.foreign_toplevel_manager->global ||
global == server.wlr_data_control_manager_v1->global ||
global == server.ext_data_control_manager_v1->global ||
global == server.data_control_manager_v1->global ||
global == server.screencopy_manager_v1->global ||
global == server.ext_image_copy_capture_manager_v1->global ||
global == server.export_dmabuf_manager_v1->global ||
global == server.security_context_manager_v1->global ||
global == server.gamma_control_manager_v1->global ||
@ -184,11 +175,11 @@ static void detect_proprietary(struct wlr_backend *backend, void *data) {
drmFreeVersion(version);
}
static void do_renderer_recreate(void *data) {
struct sway_server *server = data;
server->recreating_renderer = NULL;
static void handle_renderer_lost(struct wl_listener *listener, void *data) {
struct sway_server *server = wl_container_of(listener, server, renderer_lost);
sway_log(SWAY_INFO, "Re-creating renderer after GPU reset");
struct wlr_renderer *renderer = wlr_renderer_autocreate(server->backend);
if (renderer == NULL) {
sway_log(SWAY_ERROR, "Unable to create renderer");
@ -223,42 +214,13 @@ static void do_renderer_recreate(void *data) {
wlr_renderer_destroy(old_renderer);
}
static void handle_renderer_lost(struct wl_listener *listener, void *data) {
struct sway_server *server = wl_container_of(listener, server, renderer_lost);
if (server->recreating_renderer != NULL) {
sway_log(SWAY_DEBUG, "Re-creation of renderer already scheduled");
return;
}
sway_log(SWAY_INFO, "Scheduling re-creation of renderer after GPU reset");
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();
server->wl_event_loop = wl_display_get_event_loop(server->wl_display);
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);
@ -283,12 +245,9 @@ bool server_init(struct sway_server *server) {
if (wlr_renderer_get_texture_formats(server->renderer, WLR_BUFFER_CAP_DMABUF) != NULL) {
server->linux_dmabuf_v1 = wlr_linux_dmabuf_v1_create_with_renderer(
server->wl_display, 4, server->renderer);
}
if (wlr_renderer_get_drm_fd(server->renderer) >= 0 &&
server->renderer->features.timeline &&
server->backend->features.timeline) {
wlr_linux_drm_syncobj_manager_v1_create(server->wl_display, 1,
wlr_renderer_get_drm_fd(server->renderer));
if (debug.legacy_wl_drm) {
wlr_drm_create(server->wl_display, server->renderer);
}
}
server->allocator = wlr_allocator_autocreate(server->backend,
@ -308,8 +267,9 @@ bool server_init(struct sway_server *server) {
server->gamma_control_manager_v1 =
wlr_gamma_control_manager_v1_create(server->wl_display);
wlr_scene_set_gamma_control_manager_v1(root->root_scene,
server->gamma_control_manager_v1);
server->gamma_control_set_gamma.notify = handle_gamma_control_set_gamma;
wl_signal_add(&server->gamma_control_manager_v1->events.set_gamma,
&server->gamma_control_set_gamma);
server->new_output.notify = handle_new_output;
wl_signal_add(&server->backend->events.new_output, &server->new_output);
@ -361,7 +321,7 @@ bool server_init(struct sway_server *server) {
wl_signal_add(&server->pointer_constraints->events.new_constraint,
&server->pointer_constraint);
wlr_presentation_create(server->wl_display, server->backend, SWAY_PRESENTATION_VERSION);
wlr_presentation_create(server->wl_display, server->backend);
wlr_alpha_modifier_v1_create(server->wl_display);
server->output_manager_v1 =
@ -403,10 +363,7 @@ bool server_init(struct sway_server *server) {
server->export_dmabuf_manager_v1 = wlr_export_dmabuf_manager_v1_create(server->wl_display);
server->screencopy_manager_v1 = wlr_screencopy_manager_v1_create(server->wl_display);
server->ext_image_copy_capture_manager_v1 = wlr_ext_image_copy_capture_manager_v1_create(server->wl_display, 1);
wlr_ext_output_image_capture_source_manager_v1_create(server->wl_display, 1);
server->wlr_data_control_manager_v1 = wlr_data_control_manager_v1_create(server->wl_display);
server->ext_data_control_manager_v1 = wlr_ext_data_control_manager_v1_create(server->wl_display, 1);
server->data_control_manager_v1 = wlr_data_control_manager_v1_create(server->wl_display);
server->security_context_manager_v1 = wlr_security_context_manager_v1_create(server->wl_display);
wlr_viewporter_create(server->wl_display);
wlr_single_pixel_buffer_manager_v1_create(server->wl_display);
@ -414,12 +371,6 @@ 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;
@ -442,49 +393,11 @@ 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
@ -531,43 +444,14 @@ bool server_init(struct sway_server *server) {
}
void server_fini(struct sway_server *server) {
// remove listeners
wl_list_remove(&server->renderer_lost.link);
wl_list_remove(&server->new_output.link);
wl_list_remove(&server->layer_shell_surface.link);
wl_list_remove(&server->xdg_shell_toplevel.link);
wl_list_remove(&server->server_decoration.link);
wl_list_remove(&server->xdg_decoration.link);
wl_list_remove(&server->pointer_constraint.link);
wl_list_remove(&server->output_manager_apply.link);
wl_list_remove(&server->output_manager_test.link);
wl_list_remove(&server->output_power_manager_set_mode.link);
#if WLR_HAS_DRM_BACKEND
if (server->drm_lease_manager) {
wl_list_remove(&server->drm_lease_request.link);
}
#endif
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
#if WLR_HAS_XWAYLAND
if (server->xwayland.wlr_xwayland != NULL) {
wl_list_remove(&server->xwayland_surface.link);
wl_list_remove(&server->xwayland_ready.link);
wlr_xwayland_destroy(server->xwayland.wlr_xwayland);
}
wlr_xwayland_destroy(server->xwayland.wlr_xwayland);
#endif
wl_display_destroy_clients(server->wl_display);
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

@ -143,12 +143,6 @@ runtime.
This setting also applies to the current binding mode indicator.
The following commands may only be used at runtime.
*mode* toggle [<bar_id>]
Toggles the current mode between _hide_ and _dock_. Any other mode
is treated as _hide_.
## TRAY
Swaybar provides a system tray where third-party applications may place icons.

Some files were not shown because too many files have changed in this diff Show more