summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGard Spreemann <gspr@nonempty.org>2023-06-08 11:28:27 +0200
committerGard Spreemann <gspr@nonempty.org>2023-06-08 11:28:27 +0200
commit1a5ead938488d53c075330194f2a7d437729677e (patch)
treee00767f7db381490947dd9f94cab1a72341c0e6a
parent0f97580c12dba210e1cf9e538c072a13c12bdd77 (diff)
parent033d0e7eb613f1ddfe104d07079a81b8d4e02dac (diff)
Merge tag 'v0.8.6' into gspr/post-bookworm
-rw-r--r--.gitlab-ci.yml75
-rw-r--r--.gitlab-ci/debian-install.sh15
-rw-r--r--.gitlab-ci/debian32-install.sh17
-rw-r--r--.gitlab-ci/debian32.yml141
-rw-r--r--README.md52
-rw-r--r--meson.build2
-rwxr-xr-xminimal_build.sh2
-rw-r--r--protocols/wayland.xml223
-rw-r--r--src/dmabuf.c2
-rw-r--r--src/handlers.c74
-rw-r--r--src/mainloop.c158
-rw-r--r--src/server.c5
-rw-r--r--src/shadow.c10
-rw-r--r--src/video.c13
-rw-r--r--src/waypipe.c4
-rw-r--r--test/common.c2
-rw-r--r--test/fuzz_hook_det.c3
-rw-r--r--test/fuzz_hook_ext.c3
-rw-r--r--test/fuzz_hook_int.c3
19 files changed, 391 insertions, 413 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
deleted file mode 100644
index 631e69d..0000000
--- a/.gitlab-ci.yml
+++ /dev/null
@@ -1,75 +0,0 @@
-
-variables:
- UPSTREAM_REPO: mstoeckl/waypipe
-
- DEBIAN_TAG: '2019-06-25.1'
- DEBIAN_VERSION: buster
- DEBIAN_EXEC: 'bash .gitlab-ci/debian-install.sh'
- DEBIAN_CONTAINER_IMAGE: $CI_REGISTRY_IMAGE/debian/$DEBIAN_VERSION:$DEBIAN_TAG
-
- DEBIAN32_TAG: 'deb32-2019-07-04.2'
- DEBIAN32_VERSION: buster
- DEBIAN32_EXEC: 'bash .gitlab-ci/debian32-install.sh'
- DEBIAN32_CONTAINER_IMAGE: $CI_REGISTRY_IMAGE/debian/$DEBIAN32_VERSION:$DEBIAN32_TAG
-
-include:
- - project: 'wayland/ci-templates'
- ref: 96912c7331cbc6da41fbf22c4217aa541176f063
- file: '/templates/debian.yml'
- - project: 'mstoeckl/waypipe'
- file: '/.gitlab-ci/debian32.yml'
- ref: master
-
-stages:
- - container_prep
- - build
-
-debian_container_prep:
- extends: .debian@container-ifnot-exists
- stage: container_prep
-
-debian32_container_prep:
- extends: .debian32@container-ifnot-exists
- stage: container_prep
-
-.build-debian-all:
- stage: build
- script:
- - export PATH=~/.local/bin:$PATH
- - cd "$BUILDDIR"
- - meson --prefix="$PREFIX" -Dwerror=true ..
- - ninja -k0
- - ninja install
- - ninja test
- - ninja clean
- artifacts:
- name: waypipe-$CI_COMMIT_SHA-$CI_JOB_ID
- when: always
- paths:
- - b-*/meson-logs
- - b-*/run
- - p-*
-
-debian-build:
- before_script:
- - export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
- - export BUILD_ID="$CI_COMMIT_SHA-$CI_JOB_ID"
- - export PREFIX="$(pwd)/p-$BUILD_ID"
- - export BUILDDIR="$(pwd)/b-$BUILD_ID"
- - mkdir "$BUILDDIR" "$PREFIX"
- - export CC=gcc
- extends: .build-debian-all
- image: $DEBIAN_CONTAINER_IMAGE
-
-debian32-build:
- before_script:
- - export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
- - export BUILD_ID="$CI_COMMIT_SHA-$CI_JOB_ID"
- - export PREFIX="$(pwd)/p-$BUILD_ID"
- - export BUILDDIR="$(pwd)/b-$BUILD_ID"
- - mkdir "$BUILDDIR" "$PREFIX"
- - export CC=/usr/bin/gcc-8
- - export PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig/
- extends: .build-debian-all
- image: $DEBIAN32_CONTAINER_IMAGE
-
diff --git a/.gitlab-ci/debian-install.sh b/.gitlab-ci/debian-install.sh
deleted file mode 100644
index 03287d3..0000000
--- a/.gitlab-ci/debian-install.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-set -e -o xtrace
-
-apt-get update
-apt-get -y --no-install-recommends install \
- build-essential git automake autoconf libtool pkg-config libexpat1-dev \
- libffi-dev libxml2-dev mesa-common-dev libglu1-mesa-dev libegl1-mesa-dev \
- libgles2-mesa-dev libwayland-dev libudev-dev libgbm-dev libxkbcommon-dev \
- libvpx-dev libva-dev curl python3-pip python3-setuptools ninja-build weston \
- liblz4-dev libzstd-dev wayland-protocols libavcodec-dev libavutil-dev \
- libswscale-dev
-
-pip3 install --user git+https://github.com/mesonbuild/meson.git@0.47
-
diff --git a/.gitlab-ci/debian32-install.sh b/.gitlab-ci/debian32-install.sh
deleted file mode 100644
index 00fc7ea..0000000
--- a/.gitlab-ci/debian32-install.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-
-set -e -o xtrace
-
-dpkg --print-foreign-architectures
-dpkg --add-architecture i386
-
-apt-get update
-
-# Actual package dependencies
-apt-get -y --no-install-recommends install wayland-protocols:i386 pkg-config:i386 libwayland-dev:i386 libgbm-dev:i386 liblz4-dev:i386 libzstd-dev:i386 libavcodec-dev:i386 libavutil-dev:i386 libswscale-dev:i386 weston:i386 libdrm-dev:i386
-apt-get -y --no-install-recommends install gcc-8-multilib:i386 gcc-8:i386 make:i386
-
-# Build scripts, architecture doesn't matter
-apt-get -y --no-install-recommends install git python3-pip python3-wheel python3-setuptools ninja-build scdoc
-pip3 install --user git+https://github.com/mesonbuild/meson.git@0.47
-
diff --git a/.gitlab-ci/debian32.yml b/.gitlab-ci/debian32.yml
deleted file mode 100644
index 6e250b9..0000000
--- a/.gitlab-ci/debian32.yml
+++ /dev/null
@@ -1,141 +0,0 @@
-# vim: set expandtab shiftwidth=2 tabstop=8 textwidth=0:
-
-# This template will create a debian image based on the following variables:
-#
-# - DEBIAN_VERSION: the debian version (stretch, sid, etc...)
-# - DEBIAN_DEBS: if set, list of packages that needs to be installed
-# - DEBIAN_EXEC: if set, this command will be run once the packages have
-# been installed
-# - UPSTREAM_REPO: the upstream project on this gitlab instance where we might
-# find the given tag (for example: `wayland/weston`)
-# - DEBIAN_TAG: tag to copy the image from the upstream registry. If the
-# tag does not exist, create a new build and tag it
-#
-# The resulting image will be pushed in the local registry, under:
-# $CI_REGISTRY_IMAGE/debian/$DEBIAN_VERSION:$DEBIAN_TAG
-#
-# Two flavors of templates are available:
-# - `.debian32@container-build`: this will force rebuild a new container
-# and tag it with $DEBIAN_TAG without checks
-# - `.debian32@container-ifnot-exists`: this will rebuild a new container
-# only if $DEBIAN_TAG is not available in the local registry or
-# in the $UPSTREAM_REPO registry
-
-# we can not reuse exported variables in after_script,
-# so have a common definition
-.debian32_vars: &distro_vars |
- # exporting templates variables
- # https://gitlab.com/gitlab-com/support-forum/issues/4349
- export BUILDAH_FORMAT=docker
- # The '32' version should run multilib
- export DISTRO=debian
- export DISTRO_TAG=$DEBIAN32_TAG
- export DISTRO_VERSION=$DEBIAN32_VERSION
- export DISTRO_EXEC=$DEBIAN32_EXEC
-
-
-# Do not use this template directly, you can not reuse the produced image
-# as it is tagged with $CI_JOB_ID
-..debian32@container-template:
- image: $CI_REGISTRY/wayland/ci-templates/buildah:latest
- stage: build
- before_script:
- # log in to the registry
- - podman login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
-
- - *distro_vars
-
- script:
- - *distro_vars
- - echo Building $DISTRO/$DISTRO_VERSION:$DISTRO_TAG from $DISTRO:$DISTRO_VERSION
- # initial set up: take the base image, update it and install the packages
- - buildcntr=$(buildah from $DISTRO:$DISTRO_VERSION)
- - buildmnt=$(buildah mount $buildcntr)
- - buildah run $buildcntr cat /etc/apt/sources.list
- - echo 'path-exclude=/usr/share/doc/*' > $buildmnt/etc/dpkg/dpkg.cfg.d/99-exclude-cruft
- - echo 'path-exclude=/usr/share/locale/*' >> $buildmnt/etc/dpkg/dpkg.cfg.d/99-exclude-cruft
- - echo 'path-exclude=/usr/share/man/*' >> $buildmnt/etc/dpkg/dpkg.cfg.d/99-exclude-cruft
- - echo 'APT::Install-Recommends "false";' > $buildmnt/etc/apt/apt.conf
- - echo '#!/bin/sh' > $buildmnt/usr/sbin/policy-rc.d
- - echo 'exit 101' >> $buildmnt/usr/sbin/policy-rc.d
- - chmod +x $buildmnt/usr/sbin/policy-rc.d
-
- - buildah run $buildcntr env DEBIAN_FRONTEND=noninteractive apt-get update
- - buildah run $buildcntr env DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade
- - if [[ x"$DEBIAN_DEBS" != x"" ]] ;
- then
- buildah run $buildcntr env DEBIAN_FRONTEND=noninteractive apt-get -y install $DEBIAN_DEBS ;
- fi
-
- # check if there is an optional post install script and run it
- - if [[ x"$DISTRO_EXEC" != x"" ]] ;
- then
- echo Running $DISTRO_EXEC ;
- set -x ;
- mkdir $buildmnt/tmp/clone ;
- pushd $buildmnt/tmp/clone ;
- git init ;
- git remote add origin $CI_REPOSITORY_URL ;
- git fetch --depth 1 origin $CI_COMMIT_SHA ;
- git checkout FETCH_HEAD > /dev/null;
- buildah config --workingdir /tmp/clone $buildcntr ;
- buildah run $buildcntr bash -c "set -x ; $DISTRO_EXEC" ;
- popd ;
- rm -rf $buildmnt/tmp/clone ;
- set +x ;
- fi
-
- # do not store the packages database, it's pointless
- - buildah run $buildcntr env DEBIAN_FRONTEND=noninteractive apt-get clean
- - rm -f $buildmnt/var/lib/apt/lists/*.lz4
-
- # set up the working directory
- - buildah config --workingdir /app $buildcntr
- # umount the container, not required, but, heh
- - buildah unmount $buildcntr
- # tag the current container
- - buildah commit $buildcntr $CI_REGISTRY_IMAGE/$DISTRO/$DISTRO_VERSION:$CI_JOB_ID
- # clean up the working container
- - buildah rm $buildcntr
-
- # push the container image to the registry
- # There is a bug when pushing 2 tags in the same repo with the same base:
- # this may fail. Just retry it after.
- - podman push $CI_REGISTRY_IMAGE/$DISTRO/$DISTRO_VERSION:$CI_JOB_ID || true
- - sleep 2
- - podman push $CI_REGISTRY_IMAGE/$DISTRO/$DISTRO_VERSION:$CI_JOB_ID
-
- # mark the current stage as successed, to get the result in after_script
- - touch .success
-
-
-.debian32@container-build:
- extends: ..debian32@container-template
- after_script:
- # if we did not build, or if there was a failure, exit
- # (the exit status does not matter here)
- - if [[ ! -e .success ]] ;
- then
- exit 0;
- fi
-
- - *distro_vars
-
- - skopeo copy docker://$CI_REGISTRY_IMAGE/$DISTRO/$DISTRO_VERSION:$CI_JOB_ID
- docker://$CI_REGISTRY_IMAGE/$DISTRO/$DISTRO_VERSION:$DISTRO_TAG
-
-
-.debian32@container-ifnot-exists:
- extends: .debian32@container-build
- before_script:
- # log in to the registry
- - podman login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
-
- - *distro_vars
-
- # check if our image is already in the current registry
- - skopeo inspect docker://$CI_REGISTRY_IMAGE/$DISTRO/$DISTRO_VERSION:$DISTRO_TAG > /dev/null && exit 0 || true
-
- # copy the original image into the current project registry namespace
- - skopeo copy docker://$CI_REGISTRY/$UPSTREAM_REPO/$DISTRO/$DISTRO_VERSION:$DISTRO_TAG
- docker://$CI_REGISTRY_IMAGE/$DISTRO/$DISTRO_VERSION:$DISTRO_TAG && exit 0 || true
diff --git a/README.md b/README.md
index 5ec7c00..5cda76d 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ serializes changes to shared memory buffers over a single socket. This makes
application forwarding similar to `ssh -X` [1] feasible.
[0] [https://wayland.freedesktop.org/](https://wayland.freedesktop.org/)
-[1] [https://unix.stackexchange.com/questions/12755/how-to-forward-x-over-ssh-to-run-graphics-applications-remotely](https://unix.stackexchange.com/questions/12755/how-to-forward-x-over-ssh-to-run-graphics-applications-remotely)
+[1] [https://wiki.archlinux.org/title/OpenSSH#X11_forwarding](https://wiki.archlinux.org/title/OpenSSH#X11_forwarding)
## Usage
@@ -65,35 +65,36 @@ Optional dependencies:
[0] [https://mesonbuild.com/](https://mesonbuild.com/)
[1] [https://git.sr.ht/~sircmpwn/scdoc](https://git.sr.ht/~sircmpwn/scdoc)
-## Status
+## Reporting issues
-This program is now relatively stable, with no large changes to the
-command line interface or wire format expected. Features like video
-encoding, multiplanar and tiled DMABUFs, and support for newer Wayland
-protocols are less well tested and more likely to break between minor
-versions.
+Waypipe is developed at [0]; file bug reports or submit patches here.
-Waypipe is developed at [1]; file bug reports or submit patches here.
+In general, if a program does not work properly under Waypipe, it is a bug
+worth reporting. If possible, before doing so ensure both computers are using
+the most recently released version of Waypipe (or are built from git master).
-The wire format most recently changed with version 0.7.0, and is not
-compatible with earlier versions of Waypipe. Both the client and
-server sides of a connection must have a feature in order for it to work;
-for example, if the local copy of Waypipe was built without LZ4 support,
-and the remote copy has the `--compress lz4` option set, the connection
-may fail at some point.
+A workaround that may help for some programs using OpenGL or Vulkan is to
+run Waypipe with the `--no-gpu` flag, which may force them to use software
+rendering and shared memory buffers. (Please still file a bug.)
-Any of the following may make waypipe crash with an error message. If
-it segfaults, file a bug report!
+Some programs may require specific environment variable settings or command
+line flags to run remotely; a few examples are given in the man page[1].
-* Different local/client and remote/server versions or capabilities
-* Differing byte orders
-* Applications using unexpected protocols that pass file descriptors; file
- bug reports for these
+Useful information for bug reports includes:
-[0] [https://mstoeckl.com/notes/gsoc/blog.html](https://mstoeckl.com/notes/gsoc/blog.html)
-[1] [https://gitlab.freedesktop.org/mstoeckl/waypipe/](https://gitlab.freedesktop.org/mstoeckl/waypipe/)
+* If a Waypipe process has crashed on either end of the connection,
+ a full stack trace, with debug symbols. (In gdb, `bt full`).
+* If the program uses OpenGL or Vulkan, the graphics cards and drivers on
+ both computers.
+* The output of `waypipe --version` on both ends of the connection
+* Logs when Waypipe is run with the `--debug` flag, or when the program
+ is run with the environment variable setting `WAYLAND_DEBUG=1`.
+* Screenshots of any visual glitches.
-## Limitations
+[0] [https://gitlab.freedesktop.org/mstoeckl/waypipe/](https://gitlab.freedesktop.org/mstoeckl/waypipe/)
+[1] [https://gitlab.freedesktop.org/mstoeckl/waypipe/-/blob/master/waypipe.scd](https://gitlab.freedesktop.org/mstoeckl/waypipe/-/blob/master/waypipe.scd)
+
+## Technical Limitations
Waypipe does not have a full view of the Wayland protocol. It includes a
compiled form of the base protocol and several extension protocols, but is not
@@ -127,3 +128,8 @@ each buffer that is used by a window surface. Since surfaces typically rotate
between a small number of buffers, a video encoded window will appear to
flicker as it switches rapidly between the underlying buffers, each of whose
video streams has different encoding artifacts.
+
+The `zwp_linux_explicit_synchronization_v1` Wayland protocol is currently not
+supported.
+
+Waypipe does not work between computers that use different byte orders.
diff --git a/meson.build b/meson.build
index d53e7d8..64cee09 100644
--- a/meson.build
+++ b/meson.build
@@ -8,7 +8,7 @@ project(
'warning_level=3',
'werror=true',
],
- version: '0.8.4',
+ version: '0.8.6',
)
# DEFAULT_SOURCE implies POSIX_C_SOURCE 200809L + extras like CMSG_LEN
diff --git a/minimal_build.sh b/minimal_build.sh
index a1ea2eb..0cab19e 100755
--- a/minimal_build.sh
+++ b/minimal_build.sh
@@ -18,7 +18,7 @@ python3 ../protocols/symgen.py header ../protocols/function_list.txt protocols.h
echo '#define WAYPIPE_VERSION "minimal"' > config-waypipe.h
echo "Compiling..."
-gcc -D_DEFAULT_SOURCE -I. -I../protocols/ -lpthread -o waypipe protocols.c \
+gcc -D_DEFAULT_SOURCE -Os -I. -I../protocols/ -lpthread -o waypipe protocols.c \
../src/bench.c ../src/client.c ../src/dmabuf.c ../src/handlers.c \
../src/interval.c ../src/kernel.c ../src/mainloop.c ../src/parsing.c \
../src/platform.c ../src/server.c ../src/shadow.c ../src/util.c \
diff --git a/protocols/wayland.xml b/protocols/wayland.xml
index 784d971..a7def4d 100644
--- a/protocols/wayland.xml
+++ b/protocols/wayland.xml
@@ -177,6 +177,9 @@
<description summary="callback object">
Clients can handle the 'done' event to get notified when
the related request is done.
+
+ Note, because wl_callback objects are created from multiple independent
+ factory interfaces, the wl_callback interface is frozen at version 1.
</description>
<event name="done" type="destructor">
@@ -187,7 +190,7 @@
</event>
</interface>
- <interface name="wl_compositor" version="5">
+ <interface name="wl_compositor" version="6">
<description summary="the compositor singleton">
A compositor. This object is a singleton global. The
compositor is in charge of combining the contents of multiple
@@ -258,6 +261,12 @@
for the pool from the file descriptor passed when the pool was
created, but using the new size. This request can only be
used to make the pool bigger.
+
+ This request only changes the amount of bytes that are mmapped
+ by the server and does not touch the file corresponding to the
+ file descriptor passed at creation time. It is the client's
+ responsibility to ensure that the file is at least as big as
+ the new pool size.
</description>
<arg name="size" type="int" summary="new size of the pool, in bytes"/>
</request>
@@ -271,8 +280,8 @@
Clients can create wl_shm_pool objects using the create_pool
request.
- At connection setup time, the wl_shm object emits one or more
- format events to inform clients about the valid pixel formats
+ On binding the wl_shm object one or more format events
+ are emitted to inform clients about the valid pixel formats
that can be used for buffers.
</description>
@@ -410,6 +419,21 @@
<entry name="xbgr16161616" value="0x38344258" summary="[63:0] x:B:G:R 16:16:16:16 little endian"/>
<entry name="argb16161616" value="0x38345241" summary="[63:0] A:R:G:B 16:16:16:16 little endian"/>
<entry name="abgr16161616" value="0x38344241" summary="[63:0] A:B:G:R 16:16:16:16 little endian"/>
+ <entry name="c1" value="0x20203143" summary="[7:0] C0:C1:C2:C3:C4:C5:C6:C7 1:1:1:1:1:1:1:1 eight pixels/byte"/>
+ <entry name="c2" value="0x20203243" summary="[7:0] C0:C1:C2:C3 2:2:2:2 four pixels/byte"/>
+ <entry name="c4" value="0x20203443" summary="[7:0] C0:C1 4:4 two pixels/byte"/>
+ <entry name="d1" value="0x20203144" summary="[7:0] D0:D1:D2:D3:D4:D5:D6:D7 1:1:1:1:1:1:1:1 eight pixels/byte"/>
+ <entry name="d2" value="0x20203244" summary="[7:0] D0:D1:D2:D3 2:2:2:2 four pixels/byte"/>
+ <entry name="d4" value="0x20203444" summary="[7:0] D0:D1 4:4 two pixels/byte"/>
+ <entry name="d8" value="0x20203844" summary="[7:0] D"/>
+ <entry name="r1" value="0x20203152" summary="[7:0] R0:R1:R2:R3:R4:R5:R6:R7 1:1:1:1:1:1:1:1 eight pixels/byte"/>
+ <entry name="r2" value="0x20203252" summary="[7:0] R0:R1:R2:R3 2:2:2:2 four pixels/byte"/>
+ <entry name="r4" value="0x20203452" summary="[7:0] R0:R1 4:4 two pixels/byte"/>
+ <entry name="r10" value="0x20303152" summary="[15:0] x:R 6:10 little endian"/>
+ <entry name="r12" value="0x20323152" summary="[15:0] x:R 4:12 little endian"/>
+ <entry name="avuy8888" value="0x59555641" summary="[31:0] A:Cr:Cb:Y 8:8:8:8 little endian"/>
+ <entry name="xvuy8888" value="0x59555658" summary="[31:0] X:Cr:Cb:Y 8:8:8:8 little endian"/>
+ <entry name="p030" value="0x30333050" summary="2x2 subsampled Cr:Cb plane 10 bits per channel packed"/>
</enum>
<request name="create_pool">
@@ -447,6 +471,9 @@
If the buffer uses a format that has an alpha channel, the alpha channel
is assumed to be premultiplied in the color channels unless otherwise
specified.
+
+ Note, because wl_buffer objects are created from multiple independent
+ factory interfaces, the wl_buffer interface is frozen at version 1.
</description>
<request name="destroy" type="destructor">
@@ -618,8 +645,9 @@
<event name="source_actions" since="3">
<description summary="notify the source-side available actions">
This event indicates the actions offered by the data source. It
- will be sent right after wl_data_device.enter, or anytime the source
- side changes its offered actions through wl_data_source.set_actions.
+ will be sent immediately after creating the wl_data_offer object,
+ or anytime the source side changes its offered actions through
+ wl_data_source.set_actions.
</description>
<arg name="source_actions" type="uint" summary="actions offered by the data source"
enum="wl_data_device_manager.dnd_action"/>
@@ -861,11 +889,8 @@
a drag-and-drop icon. If the icon surface already has another role,
it raises a protocol error.
- The current and pending input regions of the icon wl_surface are
- cleared, and wl_surface.set_input_region is ignored until the
- wl_surface is no longer used as the icon surface. When the use
- as an icon ends, the current and pending input regions become
- undefined, and the wl_surface is unmapped.
+ The input region is ignored for wl_surfaces with the role of a
+ drag-and-drop icon.
</description>
<arg name="source" type="object" interface="wl_data_source" allow-null="true" summary="data source for the eventual transfer"/>
<arg name="origin" type="object" interface="wl_surface" summary="surface where the drag originates"/>
@@ -890,7 +915,7 @@
which will subsequently be used in either the
data_device.enter event (for drag-and-drop) or the
data_device.selection event (for selections). Immediately
- following the data_device_data_offer event, the new data_offer
+ following the data_device.data_offer event, the new data_offer
object will send out data_offer.offer events to describe the
mime types it offers.
</description>
@@ -1051,7 +1076,8 @@
a basic surface.
Note! This protocol is deprecated and not intended for production use.
- For desktop-style user interfaces, use xdg_shell.
+ For desktop-style user interfaces, use xdg_shell. Compositors and clients
+ should not implement this interface.
</description>
<enum name="error">
@@ -1345,7 +1371,7 @@
</event>
</interface>
- <interface name="wl_surface" version="5">
+ <interface name="wl_surface" version="6">
<description summary="an onscreen surface">
A surface is a rectangular area that may be displayed on zero
or more outputs, and shown any number of times at the compositor's
@@ -1377,8 +1403,9 @@
that this request gives a role to a wl_surface. Often, this
request also creates a new protocol object that represents the
role and adds additional functionality to wl_surface. When a
- client wants to destroy a wl_surface, they must destroy this 'role
- object' before the wl_surface.
+ client wants to destroy a wl_surface, they must destroy this role
+ object before the wl_surface, otherwise a defunct_role_object error is
+ sent.
Destroying the role object does not remove the role from the
wl_surface, but it may stop the wl_surface from "playing the role".
@@ -1398,6 +1425,8 @@
<entry name="invalid_transform" value="1" summary="buffer transform value is invalid"/>
<entry name="invalid_size" value="2" summary="buffer size is invalid"/>
<entry name="invalid_offset" value="3" summary="buffer offset is invalid"/>
+ <entry name="defunct_role_object" value="4"
+ summary="surface was destroyed before its role object"/>
</enum>
<request name="destroy" type="destructor">
@@ -1426,8 +1455,9 @@
When the bound wl_surface version is 5 or higher, passing any
non-zero x or y is a protocol violation, and will result in an
- 'invalid_offset' error being raised. To achieve equivalent semantics,
- use wl_surface.offset.
+ 'invalid_offset' error being raised. The x and y arguments are ignored
+ and do not change the pending state. To achieve equivalent semantics,
+ use wl_surface.offset.
Surface contents are double-buffered state, see wl_surface.commit.
@@ -1779,9 +1809,37 @@
<arg name="x" type="int" summary="surface-local x coordinate"/>
<arg name="y" type="int" summary="surface-local y coordinate"/>
</request>
+
+ <!-- Version 6 additions -->
+
+ <event name="preferred_buffer_scale" since="6">
+ <description summary="preferred buffer scale for the surface">
+ This event indicates the preferred buffer scale for this surface. It is
+ sent whenever the compositor's preference changes.
+
+ It is intended that scaling aware clients use this event to scale their
+ content and use wl_surface.set_buffer_scale to indicate the scale they
+ have rendered with. This allows clients to supply a higher detail
+ buffer.
+ </description>
+ <arg name="factor" type="int" summary="preferred scaling factor"/>
+ </event>
+
+ <event name="preferred_buffer_transform" since="6">
+ <description summary="preferred buffer transform for the surface">
+ This event indicates the preferred buffer transform for this surface.
+ It is sent whenever the compositor's preference changes.
+
+ It is intended that transform aware clients use this event to apply the
+ transform to their content and use wl_surface.set_buffer_transform to
+ indicate the transform they have rendered with.
+ </description>
+ <arg name="transform" type="uint" enum="wl_output.transform"
+ summary="preferred transform"/>
+ </event>
</interface>
- <interface name="wl_seat" version="7">
+ <interface name="wl_seat" version="9">
<description summary="group of input devices">
A seat is a group of keyboards, pointer and touch devices. This
object is published as a global during start up, or when such a
@@ -1914,7 +1972,7 @@
</interface>
- <interface name="wl_pointer" version="7">
+ <interface name="wl_pointer" version="9">
<description summary="pointer input device">
The wl_pointer interface represents one or more input devices,
such as mice, which control the pointer location and pointer_focus
@@ -1958,11 +2016,9 @@
pointer surface to this request with new values for hotspot_x
and hotspot_y.
- The current and pending input regions of the wl_surface are
- cleared, and wl_surface.set_input_region is ignored until the
- wl_surface is no longer used as the cursor. When the use as a
- cursor ends, the current and pending input regions become
- undefined, and the wl_surface is unmapped.
+ The input region is ignored for wl_surfaces with the role of
+ a cursor. When the use as a cursor ends, the wl_surface is
+ unmapped.
The serial parameter must match the latest wl_pointer.enter
serial number sent to the client. Otherwise the request will be
@@ -2214,6 +2270,9 @@
This event carries the axis value of the wl_pointer.axis event in
discrete steps (e.g. mouse wheel clicks).
+ This event is deprecated with wl_pointer version 8 - this event is not
+ sent to clients supporting version 8 or later.
+
This event does not occur on its own, it is coupled with a
wl_pointer.axis event that represents this axis value on a
continuous scale. The protocol guarantees that each axis_discrete
@@ -2221,7 +2280,8 @@
axis number within the same wl_pointer.frame. Note that the protocol
allows for other events to occur between the axis_discrete and
its coupled axis event, including other axis_discrete or axis
- events.
+ events. A wl_pointer.frame must not contain more than one axis_discrete
+ event per axis type.
This event is optional; continuous scrolling devices
like two-finger scrolling on touchpads do not have discrete
@@ -2239,9 +2299,93 @@
<arg name="axis" type="uint" enum="axis" summary="axis type"/>
<arg name="discrete" type="int" summary="number of steps"/>
</event>
+
+ <event name="axis_value120" since="8">
+ <description summary="axis high-resolution scroll event">
+ Discrete high-resolution scroll information.
+
+ This event carries high-resolution wheel scroll information,
+ with each multiple of 120 representing one logical scroll step
+ (a wheel detent). For example, an axis_value120 of 30 is one quarter of
+ a logical scroll step in the positive direction, a value120 of
+ -240 are two logical scroll steps in the negative direction within the
+ same hardware event.
+ Clients that rely on discrete scrolling should accumulate the
+ value120 to multiples of 120 before processing the event.
+
+ The value120 must not be zero.
+
+ This event replaces the wl_pointer.axis_discrete event in clients
+ supporting wl_pointer version 8 or later.
+
+ Where a wl_pointer.axis_source event occurs in the same
+ wl_pointer.frame, the axis source applies to this event.
+
+ The order of wl_pointer.axis_value120 and wl_pointer.axis_source is
+ not guaranteed.
+ </description>
+ <arg name="axis" type="uint" enum="axis" summary="axis type"/>
+ <arg name="value120" type="int" summary="scroll distance as fraction of 120"/>
+ </event>
+
+ <!-- Version 9 additions -->
+
+ <enum name="axis_relative_direction">
+ <description summary="axis relative direction">
+ This specifies the direction of the physical motion that caused a
+ wl_pointer.axis event, relative to the wl_pointer.axis direction.
+ </description>
+ <entry name="identical" value="0"
+ summary="physical motion matches axis direction"/>
+ <entry name="inverted" value="1"
+ summary="physical motion is the inverse of the axis direction"/>
+ </enum>
+
+ <event name="axis_relative_direction" since="9">
+ <description summary="axis relative physical direction event">
+ Relative directional information of the entity causing the axis
+ motion.
+
+ For a wl_pointer.axis event, the wl_pointer.axis_relative_direction
+ event specifies the movement direction of the entity causing the
+ wl_pointer.axis event. For example:
+ - if a user's fingers on a touchpad move down and this
+ causes a wl_pointer.axis vertical_scroll down event, the physical
+ direction is 'identical'
+ - if a user's fingers on a touchpad move down and this causes a
+ wl_pointer.axis vertical_scroll up scroll up event ('natural
+ scrolling'), the physical direction is 'inverted'.
+
+ A client may use this information to adjust scroll motion of
+ components. Specifically, enabling natural scrolling causes the
+ content to change direction compared to traditional scrolling.
+ Some widgets like volume control sliders should usually match the
+ physical direction regardless of whether natural scrolling is
+ active. This event enables clients to match the scroll direction of
+ a widget to the physical direction.
+
+ This event does not occur on its own, it is coupled with a
+ wl_pointer.axis event that represents this axis value.
+ The protocol guarantees that each axis_relative_direction event is
+ always followed by exactly one axis event with the same
+ axis number within the same wl_pointer.frame. Note that the protocol
+ allows for other events to occur between the axis_relative_direction
+ and its coupled axis event.
+
+ The axis number is identical to the axis number in the associated
+ axis event.
+
+ The order of wl_pointer.axis_relative_direction,
+ wl_pointer.axis_discrete and wl_pointer.axis_source is not
+ guaranteed.
+ </description>
+ <arg name="axis" type="uint" enum="axis" summary="axis type"/>
+ <arg name="direction" type="uint" enum="axis_relative_direction"
+ summary="physical direction relative to axis motion"/>
+ </event>
</interface>
- <interface name="wl_keyboard" version="7">
+ <interface name="wl_keyboard" version="9">
<description summary="keyboard input device">
The wl_keyboard interface represents one or more keyboards
associated with a seat.
@@ -2255,7 +2399,7 @@
<entry name="no_keymap" value="0"
summary="no keymap; client must understand how to interpret the raw keycode"/>
<entry name="xkb_v1" value="1"
- summary="libxkbcommon compatible; to determine the xkb keycode, clients must add 8 to the key event keycode"/>
+ summary="libxkbcommon compatible, null-terminated string; to determine the xkb keycode, clients must add 8 to the key event keycode"/>
</enum>
<event name="keymap">
@@ -2368,7 +2512,7 @@
</event>
</interface>
- <interface name="wl_touch" version="7">
+ <interface name="wl_touch" version="9">
<description summary="touchscreen input device">
The wl_touch interface represents a touchscreen
associated with a seat.
@@ -2822,6 +2966,8 @@
<enum name="error">
<entry name="bad_surface" value="0"
summary="the to-be sub-surface is invalid"/>
+ <entry name="bad_parent" value="1"
+ summary="the to-be sub-surface parent is invalid"/>
</enum>
<request name="get_subsurface">
@@ -2831,14 +2977,18 @@
plain wl_surface into a sub-surface.
The to-be sub-surface must not already have another role, and it
- must not have an existing wl_subsurface object. Otherwise a protocol
- error is raised.
+ must not have an existing wl_subsurface object. Otherwise the
+ bad_surface protocol error is raised.
Adding sub-surfaces to a parent is a double-buffered operation on the
parent (see wl_surface.commit). The effect of adding a sub-surface
becomes visible on the next time the state of the parent surface is
applied.
+ The parent surface must not be one of the child surface's descendants,
+ and the parent must be different from the child surface, otherwise the
+ bad_parent protocol error is raised.
+
This request modifies the behaviour of wl_surface.commit request on
the sub-surface, see the documentation on wl_subsurface interface.
</description>
@@ -2893,12 +3043,10 @@
synchronized mode, and then assume that all its child and grand-child
sub-surfaces are synchronized, too, without explicitly setting them.
- If the wl_surface associated with the wl_subsurface is destroyed, the
- wl_subsurface object becomes inert. Note, that destroying either object
- takes effect immediately. If you need to synchronize the removal
- of a sub-surface to the parent surface update, unmap the sub-surface
- first by attaching a NULL wl_buffer, update parent, and then destroy
- the sub-surface.
+ Destroying a sub-surface takes effect immediately. If you need to
+ synchronize the removal of a sub-surface to the parent surface update,
+ unmap the sub-surface first by attaching a NULL wl_buffer, update parent,
+ and then destroy the sub-surface.
If the parent wl_surface object is destroyed, the sub-surface is
unmapped.
@@ -2909,8 +3057,7 @@
The sub-surface interface is removed from the wl_surface object
that was turned into a sub-surface with a
wl_subcompositor.get_subsurface request. The wl_surface's association
- to the parent is deleted, and the wl_surface loses its role as
- a sub-surface. The wl_surface is unmapped immediately.
+ to the parent is deleted. The wl_surface is unmapped immediately.
</description>
</request>
diff --git a/src/dmabuf.c b/src/dmabuf.c
index 7b8126e..b3718be 100644
--- a/src/dmabuf.c
+++ b/src/dmabuf.c
@@ -120,7 +120,7 @@ int init_render_data(struct render_data *data)
const char *card = data->drm_node_path ? data->drm_node_path
: "/dev/dri/renderD128";
- int drm_fd = open(card, O_RDWR | O_CLOEXEC);
+ int drm_fd = open(card, O_RDWR | O_CLOEXEC | O_NOCTTY);
if (drm_fd == -1) {
wp_error("Failed to open drm fd for %s: %s", card,
strerror(errno));
diff --git a/src/handlers.c b/src/handlers.c
index e7ea460..9c32a92 100644
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -30,6 +30,7 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
@@ -617,6 +618,28 @@ int get_shm_bytes_per_pixel(uint32_t format)
case WL_SHM_FORMAT_ARGB16161616:
case WL_SHM_FORMAT_ABGR16161616:
return 8;
+ // todo: adjust API to handle bit packed formats
+ case WL_SHM_FORMAT_C1:
+ case WL_SHM_FORMAT_C2:
+ case WL_SHM_FORMAT_C4:
+ case WL_SHM_FORMAT_D1:
+ case WL_SHM_FORMAT_D2:
+ case WL_SHM_FORMAT_D4:
+ goto planar;
+ case WL_SHM_FORMAT_D8:
+ return 1;
+ case WL_SHM_FORMAT_R1:
+ case WL_SHM_FORMAT_R2:
+ case WL_SHM_FORMAT_R4:
+ goto planar;
+ case WL_SHM_FORMAT_R10:
+ case WL_SHM_FORMAT_R12:
+ return 2;
+ case WL_SHM_FORMAT_AVUY8888:
+ case WL_SHM_FORMAT_XVUY8888:
+ return 4;
+ case WL_SHM_FORMAT_P030:
+ goto planar;
default:
wp_error("Unidentified WL_SHM format %x", format);
return -1;
@@ -1560,27 +1583,22 @@ void do_zwp_linux_dmabuf_feedback_v1_evt_done(struct context *ctx)
/* Inject messages for filtered tranche parameters here */
size_t m = 0;
for (size_t i = 0; i < obj->tranche_count; i++) {
- ctx->message[m] = obj->base.obj_id;
-
- size_t w = 0;
- uint16_t *fmts = (uint16_t *)&ctx->message[m + 3];
+ bool empty = true;
for (size_t j = 0; j < obj->tranches[i].tranche_size; j++) {
uint16_t idx = obj->tranches[i].tranche[j];
if (dmabuf_format_permitted(ctx, obj->table[idx].format,
obj->table[idx].modifier)) {
- fmts[w++] = idx;
+ empty = false;
+ break;
}
}
- if (w == 0) {
+
+ if (empty) {
/* discard tranche, has no entries */
continue;
}
- size_t s = 3 + ((w + 1) / 2);
- ctx->message[m + 1] = message_header_2(
- 4 * (uint32_t)s, 5); // tranche_formats
- ctx->message[m + 2] = (uint32_t)(2 * w);
- m += s;
+ size_t s;
s = 3 + ((sizeof(dev_t) + 3) / 4);
ctx->message[m] = obj->base.obj_id;
@@ -1597,6 +1615,22 @@ void do_zwp_linux_dmabuf_feedback_v1_evt_done(struct context *ctx)
ctx->message[m + 2] = obj->tranches[i].flags;
m += s;
+ size_t w = 0;
+ uint16_t *fmts = (uint16_t *)&ctx->message[m + 3];
+ for (size_t j = 0; j < obj->tranches[i].tranche_size; j++) {
+ uint16_t idx = obj->tranches[i].tranche[j];
+ if (dmabuf_format_permitted(ctx, obj->table[idx].format,
+ obj->table[idx].modifier)) {
+ fmts[w++] = idx;
+ }
+ }
+ s = 3 + ((w + 1) / 2);
+ ctx->message[m] = obj->base.obj_id;
+ ctx->message[m + 1] = message_header_2(
+ 4 * (uint32_t)s, 5); // tranche_formats
+ ctx->message[m + 2] = (uint32_t)(2 * w);
+ m += s;
+
s = 2;
ctx->message[m] = obj->base.obj_id;
ctx->message[m + 1] = message_header_2(
@@ -1655,6 +1689,7 @@ void do_zwp_linux_dmabuf_feedback_v1_evt_format_table(
void do_zwp_linux_dmabuf_feedback_v1_evt_main_device(struct context *ctx,
uint32_t device_count, const uint8_t *device_val)
{
+
struct obj_zwp_linux_dmabuf_feedback *obj =
(struct obj_zwp_linux_dmabuf_feedback *)ctx->obj;
if ((size_t)device_count != sizeof(dev_t)) {
@@ -1662,7 +1697,20 @@ void do_zwp_linux_dmabuf_feedback_v1_evt_main_device(struct context *ctx,
(size_t)device_count, sizeof(dev_t));
return;
}
- memcpy(&obj->main_device, device_val, sizeof(dev_t));
+
+ if (ctx->on_display_side) {
+ memcpy(&obj->main_device, device_val, sizeof(dev_t));
+ } else {
+ // adopt the main device from the render fd being used
+ struct stat fsdata;
+ memset(&fsdata, 0, sizeof(fsdata));
+ int ret = fstat(ctx->g->render.drm_fd, &fsdata);
+ if (ret == -1) {
+ wp_error("Failed to get render device info");
+ return;
+ }
+ obj->main_device = fsdata.st_rdev;
+ }
/* todo: add support for changing render devices in waypipe */
}
@@ -1670,7 +1718,7 @@ void do_zwp_linux_dmabuf_feedback_v1_evt_tranche_done(struct context *ctx)
{
struct obj_zwp_linux_dmabuf_feedback *obj =
(struct obj_zwp_linux_dmabuf_feedback *)ctx->obj;
- if (obj->main_device != obj->current_device) {
+ if (obj->main_device != obj->current_device && ctx->on_display_side) {
/* Filter out/ignore all tranches for anything but the main
* device. */
return;
diff --git a/src/mainloop.c b/src/mainloop.c
index 181319c..a91a197 100644
--- a/src/mainloop.c
+++ b/src/mainloop.c
@@ -271,7 +271,7 @@ static int interpret_chanmsg(struct chan_msg_state *cmsg,
}
} else if (type == WMSG_RESTART) {
struct wmsg_restart *ackm = (struct wmsg_restart *)packet;
- wp_debug("Received restart message: remote last saw ack %d (we last recvd %d, acked %d)",
+ wp_debug("Received WMSG_RESTART: remote last saw ack %d (we last recvd %d, acked %d)",
ackm->last_ack_received,
cxs->last_received_msgno,
cxs->last_acked_msgno);
@@ -279,8 +279,10 @@ static int interpret_chanmsg(struct chan_msg_state *cmsg,
return 0;
} else if (type == WMSG_ACK_NBLOCKS) {
struct wmsg_ack *ackm = (struct wmsg_ack *)packet;
+ wp_debug("Received WMSG_ACK_NBLOCKS: remote recvd %u",
+ ackm->messages_received);
if (msgno_gt(ackm->messages_received,
- cxs->last_received_msgno)) {
+ cxs->last_confirmed_msgno)) {
cxs->last_confirmed_msgno = ackm->messages_received;
}
return 0;
@@ -301,6 +303,7 @@ static int interpret_chanmsg(struct chan_msg_state *cmsg,
const int32_t *fds = &((const int32_t *)packet)[1];
int nfds = (int)((unpadded_size - sizeof(uint32_t)) /
sizeof(int32_t));
+ wp_debug("Received WMSG_INJECT_RIDS with %d fds", nfds);
if (buf_ensure_size(nfds, sizeof(int), &cmsg->transf_fds.size,
(void **)&cmsg->transf_fds.data) == -1) {
@@ -333,6 +336,8 @@ static int interpret_chanmsg(struct chan_msg_state *cmsg,
* guaranteed that all file descriptors provided will be used by
* the messages. This makes fd handling more complicated. */
int protosize = (int)(unpadded_size - sizeof(uint32_t));
+ wp_debug("Received WMSG_PROTOCOL with %d bytes of messages",
+ protosize);
// TODO: have message editing routines ensure size, so
// that this limit can be tighter
if (buf_ensure_size(protosize + 1024, 1,
@@ -687,6 +692,80 @@ static int partial_write_transfer(int chanfd, struct transfer_queue *td,
return 0;
}
+static int inject_acknowledge(
+ struct way_msg_state *wmsg, struct cross_state *cxs)
+{
+ if (transfer_ensure_size(&wmsg->transfers, wmsg->transfers.end + 1) ==
+ -1) {
+ wp_error("Failed to allocate space for ack message transfer");
+ return -1;
+ }
+ /* To avoid infinite regress, receive acknowledgement
+ * messages do not themselves increase the message counters. */
+ uint32_t ack_msgno;
+ if (wmsg->transfers.start == wmsg->transfers.end) {
+ ack_msgno = wmsg->transfers.last_msgno;
+ } else {
+ ack_msgno = wmsg->transfers.meta[wmsg->transfers.start].msgno;
+ }
+
+ /* This is the next point where messages can be changed */
+ int next_slot = (wmsg->transfers.partial_write_amt > 0)
+ ? wmsg->transfers.start + 1
+ : wmsg->transfers.start;
+ struct wmsg_ack *not_in_prog_msg = NULL;
+ struct wmsg_ack *queued_msg = NULL;
+ for (size_t i = 0; i < 2; i++) {
+ if (wmsg->transfers.partial_write_amt > 0 &&
+ wmsg->transfers.vecs[wmsg->transfers.start]
+ .iov_base ==
+ &wmsg->ack_msgs[i]) {
+ not_in_prog_msg = &wmsg->ack_msgs[1 - i];
+ }
+ if (next_slot < wmsg->transfers.end &&
+ wmsg->transfers.vecs[next_slot].iov_base ==
+ &wmsg->ack_msgs[i]) {
+ queued_msg = &wmsg->ack_msgs[i];
+ }
+ }
+
+ if (!queued_msg) {
+ /* Insert a message--which is not partially written--
+ * in the next available slot, pushing forward other
+ * messages */
+ if (!not_in_prog_msg) {
+ queued_msg = &wmsg->ack_msgs[0];
+ } else {
+ queued_msg = not_in_prog_msg;
+ }
+
+ if (next_slot < wmsg->transfers.end) {
+ size_t nmoved = (size_t)(wmsg->transfers.end -
+ next_slot);
+ memmove(wmsg->transfers.vecs + next_slot + 1,
+ wmsg->transfers.vecs + next_slot,
+ sizeof(*wmsg->transfers.vecs) * nmoved);
+ memmove(wmsg->transfers.meta + next_slot + 1,
+ wmsg->transfers.meta + next_slot,
+ sizeof(*wmsg->transfers.meta) * nmoved);
+ }
+ wmsg->transfers.vecs[next_slot].iov_len =
+ sizeof(struct wmsg_ack);
+ wmsg->transfers.vecs[next_slot].iov_base = queued_msg;
+ wmsg->transfers.meta[next_slot].msgno = ack_msgno;
+ wmsg->transfers.meta[next_slot].static_alloc = true;
+ wmsg->transfers.end++;
+ }
+
+ /* Modify the message which is now next up in the transfer
+ * queue */
+ queued_msg->size_and_type = transfer_header(
+ sizeof(struct wmsg_ack), WMSG_ACK_NBLOCKS);
+ queued_msg->messages_received = cxs->last_received_msgno;
+ cxs->last_acked_msgno = cxs->last_received_msgno;
+ return 0;
+}
+
static int advance_waymsg_chanwrite(struct way_msg_state *wmsg,
struct cross_state *cxs, struct globals *g, int chanfd,
bool display_side)
@@ -701,80 +780,7 @@ static int advance_waymsg_chanwrite(struct way_msg_state *wmsg,
/* Acknowledge the other side's transfers as soon as possible */
if (cxs->last_acked_msgno != cxs->last_received_msgno) {
- if (transfer_ensure_size(&wmsg->transfers,
- wmsg->transfers.end + 1) == -1) {
- wp_error("Failed to allocate space for ack message transfer");
- goto ackmsg_fail;
- }
- /* To avoid infinite regress, receive acknowledgement
- * messages do not themselves increase the message counters. */
- uint32_t ack_msgno;
- if (wmsg->transfers.start == wmsg->transfers.end) {
- ack_msgno = wmsg->transfers.last_msgno;
- } else {
- ack_msgno = wmsg->transfers.meta[wmsg->transfers.start]
- .msgno;
- }
-
- /* This is the next point where messages can be changed */
- int next_slot = (wmsg->transfers.partial_write_amt > 0)
- ? wmsg->transfers.start + 1
- : wmsg->transfers.start;
- struct wmsg_ack *not_in_prog_msg = NULL;
- struct wmsg_ack *queued_msg = NULL;
- for (size_t i = 0; i < 2; i++) {
- if (wmsg->transfers.partial_write_amt > 0 &&
- wmsg->transfers.vecs[wmsg->transfers.start]
- .iov_base ==
- &wmsg->ack_msgs[i]) {
- not_in_prog_msg = &wmsg->ack_msgs[1 - i];
- }
- if (next_slot < wmsg->transfers.end &&
- wmsg->transfers.vecs[next_slot].iov_base ==
- &wmsg->ack_msgs[i]) {
- queued_msg = &wmsg->ack_msgs[i];
- }
- }
-
- if (!queued_msg) {
- /* Insert a message--which is not partially written--
- * in the next available slot, pushing forward other
- * messages */
- if (!not_in_prog_msg) {
- queued_msg = &wmsg->ack_msgs[0];
- } else {
- queued_msg = not_in_prog_msg;
- }
-
- if (next_slot < wmsg->transfers.end) {
- size_t nmoved = (size_t)(wmsg->transfers.end -
- next_slot);
- memmove(wmsg->transfers.vecs + next_slot + 1,
- wmsg->transfers.vecs +
- next_slot,
- sizeof(*wmsg->transfers.vecs) *
- nmoved);
- memmove(wmsg->transfers.meta + next_slot + 1,
- wmsg->transfers.meta +
- next_slot,
- sizeof(*wmsg->transfers.meta) *
- nmoved);
- }
- wmsg->transfers.vecs[next_slot].iov_len =
- sizeof(struct wmsg_ack);
- wmsg->transfers.vecs[next_slot].iov_base = queued_msg;
- wmsg->transfers.meta[next_slot].msgno = ack_msgno;
- wmsg->transfers.meta[next_slot].static_alloc = true;
- wmsg->transfers.end++;
- }
-
- /* Modify the message which is now next up in the transfer
- * queue */
- queued_msg->size_and_type = transfer_header(
- sizeof(struct wmsg_ack), WMSG_ACK_NBLOCKS);
- queued_msg->messages_received = cxs->last_received_msgno;
- cxs->last_acked_msgno = cxs->last_received_msgno;
- ackmsg_fail:;
+ (void)inject_acknowledge(wmsg, cxs);
}
int ret = partial_write_transfer(chanfd, &wmsg->transfers,
diff --git a/src/server.c b/src/server.c
index 1deef89..8723d7e 100644
--- a/src/server.c
+++ b/src/server.c
@@ -87,7 +87,7 @@ static void fill_random_key(struct connection_token *token)
token->key[1] += 1 + (uint32_t)tp.tv_sec;
token->key[2] += 2 + (uint32_t)tp.tv_nsec;
- int devrand = open("/dev/urandom", O_RDONLY);
+ int devrand = open("/dev/urandom", O_RDONLY | O_NOCTTY);
if (devrand != -1) {
uint32_t tmp[3];
errno = 0;
@@ -737,7 +737,8 @@ int run_server(int cwd_fd, struct socket_path socket_path,
/* To prevent getting POLLHUP spam after the first user
* closes this pipe, open both read and write ends of
* the named pipe */
- control_pipe = open(control_path, O_RDWR | O_NONBLOCK);
+ control_pipe = open(control_path,
+ O_RDWR | O_NONBLOCK | O_NOCTTY);
if (control_pipe == -1) {
wp_error("Failed to open created FIFO for reading: %s",
control_path, strerror(errno));
diff --git a/src/shadow.c b/src/shadow.c
index df60c4a..a1e67f9 100644
--- a/src/shadow.c
+++ b/src/shadow.c
@@ -2311,6 +2311,16 @@ void mark_pipe_object_statuses(
if (pfds[i].revents & POLLOUT) {
sfd->pipe.writable = true;
}
+ if (pfds[i].revents & POLLERR) {
+ wp_debug("Pipe poll returned POLLERR for .pipe_fd=%d, closing",
+ lfd);
+ if (sfd->pipe.can_read) {
+ pipe_close_read(sfd);
+ }
+ if (sfd->pipe.can_write) {
+ pipe_close_write(sfd);
+ }
+ }
}
}
diff --git a/src/video.c b/src/video.c
index 2fe019a..ff77fcb 100644
--- a/src/video.c
+++ b/src/video.c
@@ -375,12 +375,11 @@ static int setup_vaapi_pipeline(struct shadow_fd *sfd, struct render_data *rd,
static void cleanup_vaapi_pipeline(struct shadow_fd *sfd)
{
- if (!sfd->video_context) {
- return;
- }
- if (!sfd->video_context->hw_device_ctx) {
+ if (!sfd->video_va_surface && !sfd->video_va_context &&
+ !sfd->video_va_pipeline) {
return;
}
+
AVHWDeviceContext *vwdc =
(AVHWDeviceContext *)
sfd->video_context->hw_device_ctx->data;
@@ -853,6 +852,12 @@ fail_alignment:
int setup_video_encode(struct shadow_fd *sfd, struct render_data *rd)
{
+ if (sfd->video_context) {
+ wp_error("Video context already set up for sfd RID=%d",
+ sfd->remote_id);
+ return -1;
+ }
+
bool has_hw = init_hwcontext(rd) == 0;
/* Attempt hardware encoding, and if it doesn't succeed, fall back
* to software encoding */
diff --git a/src/waypipe.c b/src/waypipe.c
index adbe048..9e30f92 100644
--- a/src/waypipe.c
+++ b/src/waypipe.c
@@ -292,7 +292,7 @@ static int run_recon(const char *control_path, const char *recon_path)
control_path, (int)len, 108);
return EXIT_FAILURE;
}
- int cfd = open(control_path, O_WRONLY);
+ int cfd = open(control_path, O_WRONLY | O_NOCTTY);
if (cfd == -1) {
fprintf(stderr, "Failed to open control pipe at \"%s\"\n",
control_path);
@@ -430,7 +430,7 @@ static const struct arg_permissions arg_permissions[] = {
{ARG_VERSION, MODE_FAIL},
{ARG_ALLOW_TILED, MODE_SSH | MODE_CLIENT | MODE_SERVER},
{ARG_UNLINK, MODE_SERVER},
- {ARG_DRMNODE, MODE_SERVER},
+ {ARG_DRMNODE, MODE_SSH | MODE_CLIENT | MODE_SERVER},
{ARG_REMOTENODE, MODE_SSH},
{ARG_WAYPIPE_BINARY, MODE_SSH},
{ARG_LOGIN_SHELL, MODE_SERVER},
diff --git a/test/common.c b/test/common.c
index 44924e7..ec1c8d3 100644
--- a/test/common.c
+++ b/test/common.c
@@ -39,7 +39,7 @@ uint64_t local_time_offset = 0;
void *read_file_into_mem(const char *path, size_t *len)
{
- int fd = open(path, O_RDONLY);
+ int fd = open(path, O_RDONLY | O_NOCTTY);
if (fd == -1) {
fprintf(stderr, "Failed to open '%s'", path);
return NULL;
diff --git a/test/fuzz_hook_det.c b/test/fuzz_hook_det.c
index a9443d2..b3d47b6 100644
--- a/test/fuzz_hook_det.c
+++ b/test/fuzz_hook_det.c
@@ -89,7 +89,8 @@ int main(int argc, char **argv)
uint32_t fsize = data[cursor++];
if (fsize == 0) {
/* 'copy' sink */
- new_fileno = open("/dev/null", O_WRONLY);
+ new_fileno = open("/dev/null",
+ O_WRONLY | O_NOCTTY);
if (new_fileno == -1) {
wp_error("Failed to open /dev/null");
}
diff --git a/test/fuzz_hook_ext.c b/test/fuzz_hook_ext.c
index a53f08f..aea177b 100644
--- a/test/fuzz_hook_ext.c
+++ b/test/fuzz_hook_ext.c
@@ -133,7 +133,8 @@ int main(int argc, char **argv)
uint32_t fsize = data[cursor++];
if (fsize == 0) {
/* 'copy' sink */
- new_fileno = open("/dev/null", O_WRONLY);
+ new_fileno = open("/dev/null",
+ O_WRONLY | O_NOCTTY);
if (new_fileno == -1) {
wp_error("Failed to open /dev/null");
}
diff --git a/test/fuzz_hook_int.c b/test/fuzz_hook_int.c
index 53ac711..f3058b3 100644
--- a/test/fuzz_hook_int.c
+++ b/test/fuzz_hook_int.c
@@ -131,7 +131,8 @@ int main(int argc, char **argv)
uint32_t fsize = data[cursor++];
if (fsize == 0) {
/* 'copy' sink */
- new_fileno = open("/dev/null", O_WRONLY);
+ new_fileno = open("/dev/null",
+ O_WRONLY | O_NOCTTY);
if (new_fileno == -1) {
wp_error("Failed to open /dev/null");
}