This commit introduces logic for using a new X11 window for each
incoming transfer, rather than having a global window for each selection
source.
This eliminates a whole class of bugs involving multiple concurrent
incoming transfers.
For now, we retain the outgoing transfer queue, and the selection
source-specific windows to support it. Source-specific windows are no
longer used in the incoming path, and will be removed in a future PR.
Refs #1497.
Previously, Xwayland could restart, and we'd get events for transfers
pointing to the previous (now freed) xwm instance. This led to
use-after-free segfaults.
Closes#2565.
This will hopefully be fixed in the future by having separate windows
for each X11-to-Wayland transfer, but until then, let's avoid a
compositor crash.
Previously, `transfer->incr` was being cleared on the next selection.
However, if the next selection was *also* incremental, it's possible
that `xwm_handle_selection_property_notify` would route us to
`xwm_get_incr_chunk` instead of `xwm_selection_get_data`.
Apart from reducing duplication, this has the positive side-effect of
allowing all deallocs to use
`xwm_selection_transfer_destroy_property_reply`, as opposed to the
latter and a mix of ad-hoc `free`s.
Previously, if the Wayland client died before an incremental transfer
was complete, the logs would be spammed by "write error to target fd" as
wlroots entered some control flow wherein it'd continually try
scheduling further writes to the already-dead pipe.
This commit contains no behavioral changes, but introduces explicit
handling for draining the X11 selection in case of Wayland client death.
If `xwm_data_source_write` failed, it's failed permanently. In fact, a
failing `xwm_data_source_write` sets `transfer->property_reply` to
null as part of its error handling.
Instead of relying on an indirect check (whether
`transfer->property_reply` is still non-null), explicitly use the return
value from `xwm_data_source_write`.
The `fd` is marked `O_NONBLOCK`, so `write` will never spuriously return
`EINTR`. Therefore, `write` failing is permanent, and we can return 0 to
make the return value meaningful.
wlroots would log "Unhandled NET_WM_STATE property change" log
messages for atoms we know about. Simplify the code structure
and remove these extra messages.
Previously, wlr_xwm_selection_transfer.source_fd meant:
- the source of data in a Wayland -> X11 copy (good)
- the destination of data in a X11 -> Wayland copy (confusing)
This made reading through xwayland/selection/incoming.c difficult: in
many places, "source" actually means "destination".
Previously, any error would be masked by an internal isatty call:
24:31:48.174 [DEBUG] [wlr] [xwayland/selection/incoming.c:386] XCB_SELECTION_NOTIFY (selection=277, property=278, target=256)
24:31:48.174 [ERROR] [wlr] [xwayland/selection/incoming.c:30] write error to target fd: Inappropriate ioctl for device
In certain situations windows can have their input field set to false
but still expect to receive input focus by passively listening to key
presses via a parent window. The ICCCM specification outlines how focus
should be given to clients.
Further reading: https://tronche.com/gui/x/icccm/sec-4.html#s-4.1.7
Relates to #2604
Xwayland has its own special handling for signals like SIGSEGV/SIGABRT.
Instead of leaving the job to the OS, it tries to walk up the call stack
(badly, because a lot of information is missing), print the stack trace
to stdout, then exit(1). This is very annoying because it prevents
Xwayland crashes from being easily debugged.
Xwayland has a flag "-core" that aborts instead of exiting. This allows
the OS to generate a coredump. It's far from perfect but better than
nothing, I guess.
We already mostly did this, but there were a couple of branches
(`calloc` failures) where we'd bail without letting the other side know.
Refs swaywm/sway#4007. Likely not going to be a real improvement there
(if `calloc` fails you're already pretty screwed), but it does address a
theoretical possibility.
It seems that if we ever try to reply to a selection request after
another has been sent by the same requestor (we reply in FIFO order),
the requestor never reads from it, and we end up stalling forever on a
transfer that will never complete.
It appears that `XCB_SELECTION_REQUEST` has some sort of singleton
semantics, and new requests for the same selection are meant to replace
outstanding older ones. I couldn't find a reference for this, but
empirically this does seem to be the case.
Real (contrived) case where we don't currently do this, and things break:
* run fcitx
* run Slack
* wl-copy < <(base64 /opt/firefox/libxul.so) # or some other large file
* focus Slack (no need to paste)
fcitx will send in an `XCB_SELECTION_REQUEST`, and we'll start
processing it. Immediately after, Slack sends its own. fcitx hangs for a
long, long time. In the meantime, Slack retries and sends another
selection request. We now have two pending requests from Slack.
Eventually fcitx gives up (or it can be `pkill`'d), and we start
processing the first request Slack gave us (FIFO). Slack (Electron?)
isn't listening on the other end anymore, and this transfer never
completes. The X11 clipboard becomes unusable until Slack is killed.
After this patch, the clipboard is immediately usable again after fcitx
bails. Also added a bunch of debug-level logging that makes diagnosing
this sort of issue easier.
Refs swaywm/sway#4007.
When debugging Xwayland-related issues, a common first step in debugging
has been to ask the reporter to move their real Xwayland to
/usr/bin/Xwayland.bin, and create a shell script starting Xwayland with
extra arguments under the original /usr/bin/Xwayland location.
Introducing a `WLR_XWAYLAND` environment variable makes this less
invasive, by allowing the user to swap out Xwayland without resorting to
global system changes (or source patches).
Fixes#2425.
wlroots can only handle one outgoing transfer at a time, so it keeps a
list of pending selections. The head of the list is the currently-active
selection, and when that transfer completes and is destroyed, the next
one is started.
The trouble is when you have a transfer to some app that is misbehaving.
fcitx is one such application. With really large transfers, fcitx will
hang and never wake up again. So, you can end up with a transfer list
that looks like this:
| T1: started | T2: pending | T3: pending | T4: pending |
The file descriptor for transfer T1 is registered in libwayland's epoll
loop. The rest are waiting in wlroots' list.
As a user, you want your clipboard back, so you `pkill fcitx`. Now
Xwayland sends `XCB_DESTROY_NOTIFY` to let us know to give up. We clean
up T4 first.
Due to a bug in wlroots code, we register the (fd, transfer data
pointer) pair for T1 with libwayland *again*, despite it already being
registered. We do this 2 more times as we remove T3 and T2.
Finally, we remove T1 and `free` all the memory associated with it,
before `close`-ing its transfer file descriptor.
However, we still have 3 copies of T1's file descriptor left in the
epoll loop, since we erroneously added them as part of removing T2/3/4.
When we `close` the file descriptor as part of T1's teardown, we
actually cause the epoll loop to wake up the next time around, saying
"this file descriptor has activity!" (it was closed, so `read`-ing would
normally return 0 to let us know of EOF).
But instead of returning 0, it returns -1 with `EBADF`, because the file
descriptor has already been closed. And finally, as part of error-handling
this, we access the transfer pointer, which was `free`'d. And we crash.
This one was awful to track down, but calls to `wlr_log` with %m have
the errno masked by the `isatty` call in `log_stderr`. Switch them to
`wlr_log_errno` instead.
Cue quality "how can read(2) POSSIBLY be returning ENOTTY?" moments.
Certain clients require this property to be set for expected behavior.
Most notably, steam client CSD maximize button no longer worked
after unmaximizing once, unless the state was changed by another
method. The state is unset whenever another surface gains focus.
If Xwayland is restarted, the ready handler assumes there is no xwm instance.
This means all of xwm was leaked on Xwayland restart. This caused compositors
to consume all cpu resources, where time is spent dispatching. Now we destroy
xwm if we get an event mask containing WL_EVENT_HANGUP or WL_EVENT_ERROR.
The xwayland ready signals are used to do initial setup like starting xwm.
Discarding the signals means that the handler functions will not be called
in the case that Xwayland is restarted and thus, xwm managed clients fail.
Fixes #2174."
This fixes issues with (at least) dialogs in Jetbrains IDEs becoming
unclickable if they ever lost focus (ref. swaywm/sway#5373). Prior to
this change, since `xwm->focus_surface` would be set prior to
`xwm_surface_activate` being called, the latter would short-circuit
immediately and not notify the application of the focus change.
Previously, some atoms had a leading underscore, others didn't. Be more
consistent and never use a leading underscore (symbols with a leading
underscore followed by an upper-case letter are reserved).
When running wlroots compositors with Xwayland executable bits
unset, if DISPLAY is set to the display number wlroots has set
up, then X and gtk clients (at least) hang when they are ran.
X clients should fail with an error and exit while gtk clients
should fall back to wayland backend and run correctly. This is
because wlroots opened sockets for Xwayland but wasn't closing
them if Xwayland failed to start.
Bumps minimum version to 0.51.0
- Remove all intermediate static libraries.
They serve no purpose and are just add a bunch of boilerplate for
managing dependencies and options. It's now managed as a list of
files which are compiled into libwlroots directly.
- Use install_subdir instead of installing headers individually.
I've changed my mind since I did that. Listing them out is annoying as
hell, and it's easy to forget to do it.
- Add not_found_message for all of our optional dependencies that have a
meson option. It gives some hints about what option to pass and what
the optional dependency is for.
- Move all backend subdirectories into their own meson.build. This
keeps some of the backend-specific build logic (especially rdp and
session) more neatly separated off.
- Don't overlink example clients with code they're not using.
This was done by merging the protocol dictionaries and setting some
variables containing the code and client header file.
Example clients now explicitly mention what extension protocols they
want to link to.
- Split compositor example logic from client example logic.
- Minor formatting changes
Without this information, compositors have no way to tell whether
or not to consider the position information valid. Most notably,
a compositor needs to know if it should pick a position for the
surface or use the position sent in the configure request.
The documentation for wayland-server.h says:
> Use of this header file is discouraged. Prefer including
> wayland-server-core.h instead, which does not include the server protocol
> header and as such only defines the library PI, excluding the deprecated API
> below.
Replacing wayland-server.h with wayland-server-core.h allows us to drop the
WL_HIDE_DEPRECATED declaration.
This change tracks, for each wlr_seat_client, the most recent serial
numbers which were sent to the client. When the client makes a
selection request, wlroots now verifies that the serial number
associated with the selection request was actually provided to that
specific client. This ensures that the client that was most
recently interacted with always has priority for its copy selection
requests, and that no other clients can incorrectly use a larger serial
value and "steal" the role of having the copy selection.
Also, the code used to determine when a given selection is superseded
by a newer request uses < instead of <= to allow clients to make
multiple selection requests with the same serial number and have the
last one hold.
To limit memory use, a ring buffer is used to store runs of sequential
serial numbers, and all serial numbers earlier than the start of the
ring buffer are assumed to be valid. Faking very old serials is
unlikely to be disruptive.
Assuming all clients are correctly written, the only additional
constraint which this patch should impose is that serial numbers
are now bound to seats: clients may not receive a serial number
from an input event on one seat and then use that to request
copy-selection on another seat.
This commit makes sure surface->mapped is true when the unmapped event is
emitted. This is necessary because listeners can only damage surfaces that are
mapped. This is similar to the fact that the destroy event is emitted before
any destruction is actually made.
Fixes https://github.com/swaywm/sway/issues/3568
Since xwm only manipulates the stack when focusing a window, newly
mapped windows should be stacked below the focused window. This prevents
the newly mapped window from stealing focus due to being on the top of
the stack.
This supersedes f24e17259e and
04c9ca4198. These commits were manually removing
wlr_data_source destroy handlers when starting a new drag. This is error-prone.
Instead, this commit destroys the previous source whenever we start a new drag.
This makes compositors able to block and/or customize set_selection requests
coming from clients. For instance, it's possible for a compositor to disable
rich selection content (by removing all MIME types except text/plain). This
commit implements the design proposed in [1].
Two new events are added to wlr_seat: request_set_selection and
request_set_primary_selection. Compositors need to listen to these events and
either destroy the source or effectively set the selection.
Fixes https://github.com/swaywm/wlroots/issues/1138
[1]: https://github.com/swaywm/wlroots/issues/1367#issuecomment-442403454
This has been causing troubles for some of our users and only been there
for legacy reasons, we trust Xwayland just as much as your next program
and weston doesn't take any such care when starting it.
This is a common interface that can be used for all primary selection
protocols, as discussed in [1]. A new function wlr_seat_set_primary_selection
is added to set the primary selection for all protocols.
The seat now owns again the source, and resets the selection to NULL when
destroyed.
[1]: https://github.com/swaywm/wlroots/issues/1367#issuecomment-442403454
This commits completely refactors wlr_gtk_primary_selection. The goal is to
remove gtk-primary-selection state from the seat and better handle inert
resources where it makes sense.
wlr_seat_client.primary_selection_devices has been removed and replaced by
wlr_gtk_primary_selection_device. This allows us to make offers inert when the
current selection is replaced.
wlr_seat_set_primary_selection has been removed because it relied on wlr_seat
instead of wlr_gtk_primary_selection_device_manager. A new function,
wlr_gtk_primary_selection_device_manager_set_selection (candidate for the
longest function name in wlroots) has been added. It doesn't take a serial
anymore as serial checking only makes sense for set_selection requests coming
from Wayland clients (serial checking is now done in the Wayland interface
implementation).
Since wlr_gtk_primary_selection_device_manager is now required to set the
selection, a new function wlr_xwayland_set_gtk_primary_selection_device_manager
(candidate number two for longest function name) has been added.
Devices are now made inert when the seat goes away.
Future work includes removing the last primary selection bits from the seat,
mainly wlr_seat.primary_selection_source and wlr_seat.events.primary_selection,
replacing those with new fields in wlr_gtk_primary_selection_device. Or maybe
we could keep those in the seat and replace them with a re-usable interface
(for future zwp_primary_selection_v1 support). We need to think how we'll sync
these three protocols (GTK, X11 and wayland-protocols).
See https://github.com/swaywm/wlroots/issues/1388
An X11 client can leave the hints->input WM hint unspecified,
by not setting the XCB_ICCCM_WM_HINT_INPUT flag in hints->flags.
In that case, we should assume a sane default.
Make the hint default to true, so that clients which do not specify
the hint, like mupdf, still get keyboard focus.
This should fixswaywm/sway#2231
It's not used (XCB_IMAGE_FORMAT_Z_PIXMAP comes from xproto.h) and we
don't even have a pkg-config dependency on xcb-image, making the build
to fail on that inclusion on systems without the package.
153f37bdf5 (#1145) removed the
wlr_xwayland_is_unamanged function while fixing OR, because it was
belieived that it's supposed to work around the broken OR handling.
This was a misunderstanding. is_unmanaged is (while sort of a hack)
intended to work around inherent differences between "real" X sessions
and our Xwayland/wayland situation.
The main reason it exists is to support applications like rofi and dzen,
while not handing focus to other OR windows (which should *not* be
required).
Traditionally, these applications just grabbed input from X and didn't
need to be focused by any logic in the WM. Which of course doesn't work
in wayland compositors. So we have to give them focus in some way.
Giving *every* OR window focus, breaks other applications that don't
expect focus to change.
A testcase that was pointed out to me where wlr_xwayland_is_unamanged was
breaking things is https://github.com/swaywm/sway/issues/2128 (syncplay,
gitk, gitgui)
Supposedly it broke using keyboard to navigate the menus.
I can't reproduce this with this patch. The popups can be navigated as
long as the parent has focus.
The override_redirect flag can change on configure notify and
on map notify. This adds an event to know when it changes.
This removes wlr_xwayland_surface_is_unmanaged which was wrongly
using the window type to decide whether the view should be
unmanaged.
A similar patch was proposed to Weston, but has never been
merged upstream [1].
[1]: https://patchwork.freedesktop.org/patch/211161/
Happens when e.g. closing gimp.
==24039==ERROR: AddressSanitizer: heap-use-after-free on address 0x6150001a7a78 at pc 0x7f09b09f1bb2 bp 0x7ffcf0237bf0 sp 0x7ffcf0237be0
WRITE of size 8 at 0x6150001a7a78 thread T0
#0 0x7f09b09f1bb1 in wl_list_remove ../util/signal.c:55
#1 0x7f09b094cf03 in xwayland_surface_destroy ../xwayland/xwm.c:295
#2 0x7f09b0950245 in xwm_handle_destroy_notify ../xwayland/xwm.c:717
#3 0x7f09b095304a in x11_event_handler ../xwayland/xwm.c:1149
#4 0x7f09b0c68f01 in wl_event_loop_dispatch src/event-loop.c:641
#5 0x7f09b0c67601 in wl_display_run src/wayland-server.c:1260
#6 0x40a2f4 in main ../sway/main.c:433
#7 0x7f09b011018a in __libc_start_main (/lib64/libc.so.6+0x2318a)
#8 0x40b749 in _start (/opt/wayland/bin/sway+0x40b749)
0x6150001a7a78 is located 120 bytes inside of 496-byte region [0x6150001a7a00,0x6150001a7bf0)
freed by thread T0 here:
#0 0x7f09b2b58880 in __interceptor_free (/lib64/libasan.so.5+0xee880)
#1 0x7f09b094d1a1 in xwayland_surface_destroy ../xwayland/xwm.c:315
#2 0x7f09b0950245 in xwm_handle_destroy_notify ../xwayland/xwm.c:717
#3 0x7f09b095304a in x11_event_handler ../xwayland/xwm.c:1149
#4 0x7f09b0c68f01 in wl_event_loop_dispatch src/event-loop.c:641
#5 0x7f09b0c67601 in wl_display_run src/wayland-server.c:1260
#6 0x40a2f4 in main ../sway/main.c:433
#7 0x7f09b011018a in __libc_start_main (/lib64/libc.so.6+0x2318a)
#8 0x40b749 in _start (/opt/wayland/bin/sway+0x40b749)
previously allocated by thread T0 here:
#0 0x7f09b2b58e50 in calloc (/lib64/libasan.so.5+0xeee50)
#1 0x7f09b094b585 in xwayland_surface_create ../xwayland/xwm.c:119
#2 0x7f09b0950151 in xwm_handle_create_notify ../xwayland/xwm.c:706
#3 0x7f09b0953032 in x11_event_handler ../xwayland/xwm.c:1146
#4 0x7f09b0c68f01 in wl_event_loop_dispatch src/event-loop.c:641
#5 0x7f09b0c67601 in wl_display_run src/wayland-server.c:1260
#6 0x40a2f4 in main ../sway/main.c:433
#7 0x7f09b011018a in __libc_start_main (/lib64/libc.so.6+0x2318a)
#8 0x40b749 in _start (/opt/wayland/bin/sway+0x40b749)
Makes the xwayland startup process two phased.
The first phase just initialises the X11 sockets.
The second phase starts the Xwayland server itself.
When starting xwayland lazily the second phase will be postponed until
a client has connected to the X11 socket.
Changes in behaviour:
The DISPLAY environment is now set immediately after the X11 sockets
are created.
When the Xwayland server is killed or crashes, the sockets will not be
recreated, but reused.
Fixes#849: Start up Xwayland lazily
Some comboboxes (e.g. in chrome://flags) are advertized as…
Notifications of course! Yeah, notifications, the thing that
tells you you have mail, your battery is low, or the dog has
eaten your carpet. This isn't the first time we notice Chromium's
X11 backend is pretty shit.
Anyway, added notifications and splash screens to the list of
unmanaged windows. Also removed utility windows because those
should be managed, but maybe I'm wrong and I'll revert this.
This unbreaks the build on armhf that otherwise fails like
../xwayland/selection/incoming.c: In function 'xwm_data_source_write':
../include/wlr/util/log.h:34:17: error: format '%ld' expects argument of type 'long int', but argument 6 has type 'ssize_t {aka int}' [-Werror=format=]
_wlr_log(verb, "[%s:%d] " fmt, wlr_strip_path(__FILE__), __LINE__, ##__VA_ARGS__)
^
../xwayland/selection/incoming.c:34:2: note: in expansion of macro 'wlr_log'
wlr_log(L_DEBUG, "wrote %zd (chunk size %ld) of %d bytes",
^~~~~~~
../xwayland/selection/incoming.c:34:44: note: format string is defined here
wlr_log(L_DEBUG, "wrote %zd (chunk size %ld) of %d bytes",
~~^
%d