Compare commits

..

18 Commits
pios ... master

Author SHA1 Message Date
Jonas Letzbor 6dca473059
Fix open-h264 encoding for AMD GPU 2024-06-12 00:03:21 +02:00
Jonas Letzbor ffa0a56335
Add (uncommented) workaround for locale cursor rendering in xwayland 2024-06-11 22:22:27 +02:00
Andri Yngvason 50f095d6e8 Initialise VNC last
This fixes deinitialisation ordering and makes it so that we don't start
listening until everything else is initialised.
2024-06-04 21:09:05 +00:00
Attila Fidan b7de0d9fa6 main: Use info.address_storage to compose client addr strings
Otherwise, getpeername() will truncate IPv6 client addresses and any
IPv6 clients the control client receives information about in the JSON
response will have the second half of their addresses zeroed out.
2024-06-02 10:14:27 +00:00
Attila Fidan f970c5ceb7 FAQ: Add example disabling floating_modifier in passthrough mode 2024-06-02 10:13:52 +00:00
Simon Ser 3c596455e8 meson: Specify check arg in run_command()
Fixes the following warning:

    WARNING: You should add the boolean check kwarg to the run_command call.
             It currently defaults to false,
             but it will default to true in future releases of meson.
             See also: https://github.com/mesonbuild/meson/issues/9300
2024-04-19 22:24:59 +00:00
Andri Yngvason 15660cd4a7 keyboard: Pass keyboard LED state to client 2024-04-07 12:31:34 +00:00
Andri Yngvason fbd98edae9 README: Update builds.sr.ht badge path
It changed...
2024-03-30 17:14:15 +00:00
Andri Yngvason 56c38af25f buffer: Only include linux/dma-heap.h where available
This unbreaks the build on FreeBSD.
2024-03-30 17:04:53 +00:00
Andri Yngvason 333381326d test: integration: Disable multi-output test
It seems rather fragile and I don't have the time to make it more robust.
2024-03-30 16:39:33 +00:00
Andri Yngvason 17841f9ece FUNDING.yml: Add github sponsors 2024-03-26 10:35:30 +00:00
Andri Yngvason b292c086fe buffer: Align CMA buffers up to nearest multiple of 16 2024-03-16 22:33:09 +00:00
Andri Yngvason 54fb881aab util: Add ALIGN_UP macro 2024-03-16 16:46:14 +00:00
Andri Yngvason bd9daa85c3 buffer: Allocate DMA-BUFs via CMA where available 2024-03-10 17:57:34 +00:00
Jan Beich 5b01551673 ctl: Add missing header after 42494fbbe4
src/ctl-server.c:373:36: error: incomplete definition of type 'struct sockaddr_in'
                inet_ntop(addr->sa_family, &sa_in->sin_addr, dst, sz);
                                            ~~~~~^
src/ctl-server.c:368:9: note: forward declaration of 'struct sockaddr_in'
        struct sockaddr_in* sa_in = (struct sockaddr_in*)addr;
               ^
src/ctl-server.c:376:37: error: incomplete definition of type 'struct sockaddr_in6'
                inet_ntop(addr->sa_family, &sa_in6->sin6_addr, dst, sz);
                                            ~~~~~~^
src/ctl-server.c:369:9: note: forward declaration of 'struct sockaddr_in6'
        struct sockaddr_in6* sa_in6 = (struct sockaddr_in6*)addr;
               ^
2024-02-26 12:37:19 +00:00
Andri Yngvason d71bca5270 meson: Bump version to 0.9 2024-02-25 12:11:31 +00:00
Andri Yngvason 5d55944dab ctl: Emit event when output is added/removed 2024-02-11 22:17:50 +00:00
Andri Yngvason d819ca477c README: Use ECDSA instead of RSA 2024-01-10 22:43:05 +00:00
34 changed files with 329 additions and 491 deletions

1
.gitignore vendored
View File

@ -7,3 +7,4 @@ perf.*
*.pem
.vimrc
.cache
.vscode

10
FAQ.md
View File

@ -19,6 +19,16 @@ bindsym $mod+Pause mode passthrough
This makes it so that when you press $mod+Pause, all keybindings, except the one
to switch back, are disabled.
Disable `floating_modifier` during the mode if it's set up in your config file
and you wish to be able to use the same functionality in the nested desktop:
```
mode passthrough {
bindsym $mod+Pause mode default; floating_modifier $mod normal
}
bindsym $mod+Pause mode passthrough; floating_modifier none
```
Replace `$mod normal` with different arguments if applicable.
**Q: Not all symbols show up when I'm typing. What can I do to fix this?**
A: Try setting the keyboard layout in wayvnc to the one that most closely

View File

@ -1 +1,2 @@
github: any1
patreon: andriyngvason

View File

@ -1,7 +1,7 @@
# wayvnc
[![Build and Unit Test](https://github.com/any1/wayvnc/actions/workflows/build.yml/badge.svg)](https://github.com/any1/wayvnc/actions/workflows/build.yml)
[![builds.sr.ht status](https://builds.sr.ht/~andri/wayvnc/commits/master.svg)](https://builds.sr.ht/~andri/wayvnc/commits/master?)
[![builds.sr.ht status](https://builds.sr.ht/~andri/wayvnc/pulls/1.svg)](https://builds.sr.ht/~andri/wayvnc/pulls/1?)
[![Packaging status](https://repology.org/badge/tiny-repos/wayvnc.svg)](https://repology.org/project/wayvnc/versions)
## Introduction
@ -122,8 +122,9 @@ For TLS, you'll need a private X509 key and a certificate. A self-signed key
with a certificate can be generated like so:
```
cd ~/.config/wayvnc
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
-keyout tls_key.pem -out tls_cert.pem -subj /CN=localhost \
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:secp384r1 -sha384 \
-days 3650 -nodes -keyout tls_key.pem -out tls_cert.pem \
-subj /CN=localhost \
-addext subjectAltName=DNS:localhost,DNS:localhost,IP:127.0.0.1
cd -
```

74
debian/changelog vendored
View File

@ -1,74 +0,0 @@
wayvnc (0.8.0-rel-1) bookworm; urgency=medium
* Upgrade to v0.8.0
* The rel bit is there for sake of the new version being greater than the
previous one. Remove later.
-- Andri Yngvason <andri@yngvason.is> Sun, 25 Feb 2024 13:00:00 +0000
wayvnc (0.8.0-rc0-2) bookworm; urgency=medium
* Removed IP and added local domain to TLS
* Using ECDSA instead of RSA for TLS
-- Andri Yngvason <andri@yngvason.is> Tue, 23 Jan 2024 23:00:00 +0000
wayvnc (0.8.0-rc0-1) bookworm; urgency=medium
* Upgrade to v0.8-rc0
-- Andri Yngvason <andri@yngvason.is> Sun, 10 Dec 2023 20:00:00 +0000
wayvnc (0.7.1-1~bpo12+rpt2) bookworm; urgency=medium
* Add unreleased 0.7.2 changes
-- Simon Long <simon@raspberrypi.com> Mon, 06 Nov 2023 09:44:26 +0000
wayvnc (0.7.1-1~bpo12+rpt1) bookworm; urgency=medium
* Backport from Trixie
-- Simon Long <simon@raspberrypi.com> Tue, 31 Oct 2023 07:10:38 +0000
wayvnc (0.7.1-1) unstable; urgency=medium
* Upload to unstable.
-- Boyuan Yang <byang@debian.org> Tue, 24 Oct 2023 12:54:24 -0400
wayvnc (0.7.1-1~exp1) experimental; urgency=medium
* New upstream release.
* debian/copyright: Update Unlicense license.
-- Boyuan Yang <byang@debian.org> Sun, 15 Oct 2023 16:10:45 -0400
wayvnc (0.6.2-1) unstable; urgency=medium
* New upstream version. (Closes: #1041895)
* debian/wayvnc.examples: Install example files.
* debian/copyright: Update information.
* debian/control:
+ Add new build-dep libjansson-dev.
+ Further limit version requirement for libaml-dev, libneatvnc-dev.
+ Add myself into Uploaders list.
+ Bump Standards-Version to 4.6.2.
-- Boyuan Yang <byang@debian.org> Tue, 25 Jul 2023 14:01:01 -0400
wayvnc (0.5.0-1) unstable; urgency=medium
* New upstream version
- Use new NeatVNC buffer submission API (closes: #1015099)
* debian/control: add minimum version for libneatvnc-dev (>= 0.5.1)
* debian/copyright: murmurhash was moved to neatvnc
* debian/copyright: bump year
-- Johannes Schauer Marin Rodrigues <josch@debian.org> Sat, 16 Jul 2022 22:50:17 +0200
wayvnc (0.4.1-1) unstable; urgency=medium
* Initial release. (Closes: #1002590)
-- Johannes Schauer Marin Rodrigues <josch@debian.org> Tue, 28 Dec 2021 11:34:53 +0100

38
debian/control vendored
View File

@ -1,38 +0,0 @@
Source: wayvnc
Priority: optional
Section: admin
Maintainer: Andri Yngvason <andri@yngvason.is>
Uploaders:
Boyuan Yang <byang@debian.org>,
Johannes Schauer Marin Rodrigues <josch@debian.org>,
Simon Long <simon@raspberrypi.com>,
Standards-Version: 4.6.2
Build-Depends:
debhelper-compat (= 13),
meson,
pkg-config,
scdoc,
libpam0g-dev,
libpixman-1-dev,
libdrm-dev,
libxkbcommon-dev,
libwayland-dev,
libaml-dev (>= 0.3.0),
libjansson-dev,
libneatvnc-dev (>= 0.8.0),
zlib1g-dev,
libturbojpeg0-dev,
gnutls-dev,
Rules-Requires-Root: no
Homepage: https://github.com/any1/wayvnc
Vcs-Git: https://github.com/any1/wayvnc.git
Vcs-Browser: https://github.com/any1/wayvnc
Package: wayvnc
Architecture: any
Depends: ${misc:Depends}, ${shlibs:Depends}, python3
Description: VNC server for wlroots-based Wayland compositors
It attaches to a running Wayland session, creates virtual input devices, and
exposes a single display via the RFB protocol. The Wayland session may be a
headless one, so it is also possible to run wayvnc without a physical display
attached.

97
debian/copyright vendored
View File

@ -1,97 +0,0 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: wayvnc
Upstream-Contact: Andri Yngvason <andri@yngvason.is>
Source: https://github.com/any1/wayvnc
Files: *
Copyright: 2019-2020, 2023 Andri Yngvason
2020 Scott Moreau
2020 Nicholas Sica
1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
2022-2023 Jim Ramsay
License: ISC
Files: debian/*
Copyright: 2021-2022 Johannes Schauer Marin Rodrigues <josch@debian.org>
License: CC0-1.0
Files: test/integration/integration.sh
Copyright: (None)
License: Unlicense
Files: protocols/*
Copyright: 2019 Josef Gajdusek
2017 Red Hat Inc.
2018 Simon Ser
2019 Andri Yngvason
2018 Rostislav Pehlivanov
2019 Ivan Molodetskikh
2011 Kristian Høgsberg
2010-2013 Intel Corporation
2012-2013 Collabora, Ltd.
2018, 2019 Purism SPC
2014, 2015 Collabora, Ltd.
License: Expat
License: Unlicense
This is free and unencumbered software released into the public domain.
.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
.
For more information, please refer to <http://unlicense.org/>
License: Expat
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
.
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
License: CC0-1.0
On Debian systems, the full text of the CC0 1.0 Universal License
can be found in the file `/usr/share/common-licenses/CC0-1.0'.
License: ISC
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.
.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.

6
debian/rules vendored
View File

@ -1,6 +0,0 @@
#!/usr/bin/make -f
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
%:
dh $@

3
debian/salsa-ci.yml vendored
View File

@ -1,3 +0,0 @@
---
include:
- https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/recipes/debian.yml

View File

@ -1,5 +0,0 @@
---
Repository: https://github.com/any1/wayvnc
Repository-Browse: https://github.com/any1/wayvnc
Bug-Submit: https://github.com/any1/wayvnc/issues/new
Bug-Database: https://github.com/any1/wayvnc/issues

3
debian/watch vendored
View File

@ -1,3 +0,0 @@
version=4
opts="dversionmangle=auto,filenamemangle=s/.+\/v?(\d\S+)\.tar\.gz/wayvnc-$1\.tar\.gz/" \
https://github.com/any1/wayvnc/tags .*/v?(\d\S+)\.tar\.gz

View File

@ -1 +0,0 @@
examples/*

View File

@ -1 +0,0 @@
pios-control/* /

View File

@ -1,31 +0,0 @@
#!/bin/sh
set -e
configure_wayvnc()
{
systemd-sysusers ${DPKG_ROOT:+--root="$DPKG_ROOT"} vnc.conf
systemctl --system daemon-reload >/dev/null || true
deb-systemd-invoke enable 'wayvnc-control.service' >/dev/null || true
# If wayvnc was previously configured using xdg-autostart, we want to
# enable it; otherwise, leave it disabled.
if [ -e /etc/xdg/autostart/wayvnc.desktop ]; then
rm -f /etc/xdg/autostart/wayvnc.desktop
deb-systemd-invoke enable 'wayvnc.service' >/dev/null || true
fi
deb-systemd-invoke try-restart 'wayvnc.service' >/dev/null || true
}
case "$1" in
configure)
configure_wayvnc
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinstall called with unknown argument \`$1'" >&2
exit 1
;;
esac

14
debian/wayvnc.postrm vendored
View File

@ -1,14 +0,0 @@
#!/bin/sh
set -e
case "$1" in
remove)
systemctl --system daemon-reload >/dev/null || true
;;
purge)
rm -rf /etc/wayvnc
;;
*)
;;
esac

View File

@ -40,6 +40,8 @@ enum event_type {
EVT_CLIENT_CONNECTED,
EVT_CLIENT_DISCONNECTED,
EVT_DETACHED,
EVT_OUTPUT_ADDED,
EVT_OUTPUT_REMOVED,
EVT_UNKNOWN,
};
#define EVT_LIST_LEN EVT_UNKNOWN

View File

@ -89,3 +89,6 @@ void ctl_server_event_capture_changed(struct ctl*,
const char* captured_output);
void ctl_server_event_detached(struct ctl*);
void ctl_server_event_output_added(struct ctl*, const char* name);
void ctl_server_event_output_removed(struct ctl*, const char* name);

View File

@ -19,11 +19,13 @@
#include <stdlib.h>
#include <xkbcommon/xkbcommon.h>
#include <stdbool.h>
#include <neatvnc.h>
#include "intset.h"
struct zwp_virtual_keyboard_v1;
struct table_entry;
struct nvnc;
struct keyboard {
struct zwp_virtual_keyboard_v1* virtual_keyboard;
@ -44,3 +46,4 @@ void keyboard_destroy(struct keyboard* self);
void keyboard_feed(struct keyboard* self, xkb_keysym_t symbol, bool is_pressed);
void keyboard_feed_code(struct keyboard* self, xkb_keycode_t code,
bool is_pressed);
enum nvnc_keyboard_led_state keyboard_get_led_state(const struct keyboard*);

View File

@ -19,6 +19,7 @@
#include <sys/types.h>
#define UDIV_UP(a, b) (((a) + (b) - 1) / (b))
#define ALIGN_UP(a, b) ((b) * UDIV_UP((a), (b)))
extern const char* wayvnc_version;

View File

@ -1,7 +1,7 @@
project(
'wayvnc',
'c',
version: '0.8.0',
version: '0.9-dev',
license: 'ISC',
default_options: [
'c_std=gnu11',
@ -16,6 +16,7 @@ prefix = get_option('prefix')
c_args = [
'-D_GNU_SOURCE',
'-DAML_UNSTABLE_API=1',
'-DWLR_USE_UNSTABLE=true',
'-Wno-unused-parameter',
'-Wno-missing-field-initializers',
@ -24,8 +25,8 @@ c_args = [
version = '"@0@"'.format(meson.project_version())
git = find_program('git', native: true, required: false)
if git.found()
git_commit = run_command([git, 'rev-parse', '--short', 'HEAD'])
git_branch = run_command([git, 'rev-parse', '--abbrev-ref', 'HEAD'])
git_commit = run_command([git, 'rev-parse', '--short', 'HEAD'], check: false)
git_branch = run_command([git, 'rev-parse', '--abbrev-ref', 'HEAD'], check: false)
if git_commit.returncode() == 0 and git_branch.returncode() == 0
version = '"v@0@-@1@ (@2@)"'.format(
meson.project_version(),
@ -53,11 +54,18 @@ pixman = dependency('pixman-1')
gbm = dependency('gbm', required: get_option('screencopy-dmabuf'))
drm = dependency('libdrm')
xkbcommon = dependency('xkbcommon', version: '>=1.0.0')
wayland_server = dependency('wayland-server')
wayland_client = dependency('wayland-client')
wayland_client_protocol = dependency('wayland-protocols')
wayland_cursor = dependency('wayland-cursor')
jansson = dependency('jansson')
# Cursor image
x11_dep = dependency('x11')
x11_fixes_dep = dependency('xfixes')
aml_version = ['>=0.3.0', '<0.4.0']
neatvnc_version = ['>=0.8', '<0.9.0']
neatvnc_version = ['>=0.9', '<0.10.0']
neatvnc_project = subproject(
'neatvnc',
@ -78,7 +86,7 @@ else
neatvnc = dependency('neatvnc', version: neatvnc_version)
endif
inc = include_directories('include')
inc = include_directories('include', '/usr/include/wlroots0.16')
subdir('protocols')
@ -119,6 +127,11 @@ dependencies = [
xkbcommon,
client_protos,
jansson,
x11_dep,
x11_fixes_dep,
wayland_client_protocol,
wayland_cursor,
wayland_server
]
ctlsources = [
@ -144,6 +157,10 @@ if host_system == 'linux' and get_option('systemtap') and cc.has_header('sys/sdt
config.set('HAVE_USDT', true)
endif
if cc.has_header('linux/dma-heap.h') and cc.has_header('linux/dma-buf.h')
config.set('HAVE_LINUX_DMA_HEAP', true)
endif
if cc.has_function('memfd_create')
config.set('HAVE_MEMFD', true)
config.set('HAVE_MEMFD_CREATE', true)

View File

@ -1,7 +0,0 @@
use_relative_paths=true
address=::
enable_auth=true
enable_pam=true
private_key_file=tls_key.pem
certificate_file=tls_cert.pem
rsa_private_key_file=rsa_key.pem

View File

@ -1,13 +0,0 @@
[Unit]
Description=VNC Control Service
After=wayvnc.service
BindsTo=wayvnc.service
ConditionPathExists=/etc/wayvnc/config
[Service]
Type=simple
ExecStart=/usr/sbin/wayvnc-control.py
Restart=always
[Install]
WantedBy=wayvnc.service

View File

@ -1,9 +0,0 @@
[Unit]
Description=WayVNC Key Generation
ConditionPathExists=|!/etc/wayvnc/rsa_key.pem
ConditionPathExists=|!/etc/wayvnc/tls_key.pem
ConditionPathExists=|!/etc/wayvnc/tls_cert.pem
[Service]
ExecStart=/usr/sbin/wayvnc-generate-keys.sh
Type=oneshot

View File

@ -1,17 +0,0 @@
[Unit]
Description=VNC Server
Documentation=man:wayvnc
After=network.target wayvnc-generate-keys.service
Requires=wayvnc-generate-keys.service
ConditionPathExists=/etc/wayvnc/config
[Service]
ExecStart=/bin/sh /usr/sbin/wayvnc-run.sh
Type=notify
NotifyAccess=all
Restart=always
User=vnc
KillSignal=INT
[Install]
WantedBy=multi-user.target

View File

@ -1,2 +0,0 @@
u vnc - "vnc" /nonexistent
m vnc shadow

View File

@ -1,92 +0,0 @@
#!/usr/bin/env python
import asyncio
import json
import re
import os
import glob
from pathlib import Path
class Program:
command_seq = 0
reader = None
writer = None
read_buffer = ""
message_queue = asyncio.Queue()
reply_queue = asyncio.Queue()
decoder = json.JSONDecoder()
tasks = []
async def read_message(self):
while True:
try:
result, index = self.decoder.raw_decode(self.read_buffer)
self.read_buffer = self.read_buffer[index:].lstrip()
return result
except json.JSONDecodeError:
data = await self.reader.read(4096)
self.read_buffer += data.decode('utf-8')
async def send_command(self, method, params = None):
cmd = {
"method": method,
"id": self.command_seq,
}
if not params is None:
cmd['params'] = params
self.command_seq += 1
self.writer.write(json.dumps(cmd).encode())
await self.writer.drain()
reply = await self.reply_queue.get()
self.reply_queue.task_done()
return reply['code'] == 0
async def attach(self, display):
# TODO: It would be better to pass the socket on to wayvnc as a file descriptor
proc = await asyncio.create_subprocess_shell('setfacl -m "u:vnc:rwx" {} {}'.format(Path(display).parent, display))
await proc.wait()
return await self.send_command('attach', {'display': display})
async def attach_any(self):
for path in glob.iglob('/run/user/*/wayland-*'):
if path.endswith('.lock'):
continue
if await self.attach(path):
return True
return False
async def attach_any_with_retry(self):
while not await self.attach_any():
await asyncio.sleep(1.0)
async def process_message(self, message):
method = message['method']
if (method == 'detached'):
await self.attach_any_with_retry()
async def message_processor(self):
while True:
message = await self.read_message()
if 'method' in message:
await self.message_queue.put(message)
elif 'code' in message:
await self.reply_queue.put(message)
async def main(self):
self.reader, self.writer = await asyncio.open_unix_connection("/tmp/wayvnc/wayvncctl.sock")
self.tasks.append(asyncio.create_task(self.message_processor()))
await self.attach_any_with_retry()
await self.send_command("event-receive")
while True:
message = await self.message_queue.get()
await self.process_message(message)
prog = Program()
asyncio.run(prog.main())

View File

@ -1,34 +0,0 @@
#!/bin/sh
WAYVNC_CONFIG_PATH=/etc/wayvnc
generate_rsa_key()
{
echo "Generating RSA key..."
KEY_FILE="$WAYVNC_CONFIG_PATH/rsa_key.pem"
ssh-keygen -m pem -f "$KEY_FILE" -t rsa -N "" >/dev/null
rm -f "$KEY_FILE.pub"
chown root:vnc "$KEY_FILE"
chmod 640 "$KEY_FILE"
echo "Done"
}
generate_tls_creds()
{
echo "Generating TLS Credentials..."
KEY_FILE="$WAYVNC_CONFIG_PATH/tls_key.pem"
CERT_FILE="$WAYVNC_CONFIG_PATH/tls_cert.pem"
HOSTNAME=$(cat /etc/hostname)
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:secp384r1 \
-sha384 -days 3650 -nodes -keyout "$KEY_FILE" \
-out "$CERT_FILE" -subj /CN=$HOSTNAME \
-addext subjectAltName=DNS:localhost,DNS:$HOSTNAME,DNS:$HOSTNAME.local 2>/dev/null
chown root:vnc "$KEY_FILE" "$CERT_FILE"
chmod 640 "$KEY_FILE" "$CERT_FILE"
echo "Done"
}
test -e "$WAYVNC_CONFIG_PATH" || mkdir -p "$WAYVNC_CONFIG_PATH"
test -e "$WAYVNC_CONFIG_PATH/rsa_key.pem" || generate_rsa_key
test -e "$WAYVNC_CONFIG_PATH/tls_key.pem" -a \
-e "$WAYVNC_CONFIG_PATH/tls_cert.pem" || generate_tls_creds

View File

@ -1,23 +0,0 @@
#!/bin/sh
. /etc/default/keyboard
export XDG_RUNTIME_DIR=/tmp/wayvnc
mkdir -p "$XDG_RUNTIME_DIR"
export XKB_DEFAULT_MODEL="$XKBMODEL"
export XKB_DEFAULT_LAYOUT="$XKBLAYOUT"
SELF_PID=$$
{
while ! wayvncctl --socket=/tmp/wayvnc/wayvncctl.sock version >/dev/null 2>&1; do
sleep 0.1
done
systemd-notify --ready --pid=$SELF_PID
} &
wayvnc --render-cursor \
--detached \
--config /etc/wayvnc/config \
--socket /tmp/wayvnc/wayvncctl.sock

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020 - 2021 Andri Yngvason
* Copyright (c) 2020 - 2024 Andri Yngvason
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -31,10 +31,20 @@
#include "buffer.h"
#include "pixels.h"
#include "config.h"
#include "util.h"
#ifdef ENABLE_SCREENCOPY_DMABUF
#include <gbm.h>
#endif
#include <sys/ioctl.h>
#include <fcntl.h>
// #ifdef HAVE_LINUX_DMA_HEAP
#include <linux/dma-buf.h>
#include <linux/dma-heap.h>
#define LINUX_CMA_PATH "/dev/dma_heap/linux,cma"
//#endif // HAVE_LINUX_DMA_HEAP
#endif // ENABLE_SCREENCOPY_DMABUF
extern struct wl_shm* wl_shm;
extern struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf;
@ -118,6 +128,81 @@ failure:
}
#ifdef ENABLE_SCREENCOPY_DMABUF
#ifdef HAVE_LINUX_DMA_HEAP
static bool have_linux_cma(void)
{
return access(LINUX_CMA_PATH, R_OK | W_OK) == 0;
}
static int linux_cma_alloc(size_t size)
{
int fd = open(LINUX_CMA_PATH, O_RDWR | O_CLOEXEC, 0);
if (fd < 0) {
nvnc_log(NVNC_LOG_ERROR, "Failed to open CMA device: %m");
return -1;
}
struct dma_heap_allocation_data data = {
.len = size,
.fd_flags = O_CLOEXEC | O_RDWR,
};
int r = ioctl(fd, DMA_HEAP_IOCTL_ALLOC, &data);
if (r < 0) {
nvnc_log(NVNC_LOG_ERROR, "Failed to allocate CMA buffer: %m");
return -1;
}
close(fd);
return data.fd;
}
// Some devices (mostly ARM SBCs) need CMA for hardware encoders.
static struct gbm_bo* create_cma_gbm_bo(int width, int height, uint32_t fourcc)
{
assert(gbm_device);
int bpp = pixel_size_from_fourcc(fourcc);
if (!bpp) {
nvnc_log(NVNC_LOG_PANIC, "Unsupported pixel format: %" PRIu32,
fourcc);
}
/* TODO: Get alignment through feedback mechanism.
* Buffer sizes are aligned on both axes by 16 and we'll do the same
* in the encoder, but this requirement should come from the encoder.
*/
int stride = bpp * ALIGN_UP(width, 16);
int fd = linux_cma_alloc(stride * ALIGN_UP(height, 16));
if (fd < 0) {
return NULL;
}
struct gbm_import_fd_modifier_data d = {
.format = fourcc,
.width = width,
.height = height,
// v4l2m2m doesn't support modifiers, so we use linear
.modifier = DRM_FORMAT_MOD_LINEAR,
.num_fds = 1,
.fds[0] = fd,
.offsets[0] = 0,
.strides[0] = stride,
};
struct gbm_bo* bo = gbm_bo_import(gbm_device, GBM_BO_IMPORT_FD_MODIFIER,
&d, 0);
if (!bo) {
nvnc_log(NVNC_LOG_DEBUG, "Failed to import dmabuf: %m");
close(fd);
return NULL;
}
return bo;
}
#endif // HAVE_LINUX_DMA_HEAP
static struct wv_buffer* wv_buffer_create_dmabuf(int width, int height,
uint32_t fourcc)
{
@ -133,8 +218,17 @@ static struct wv_buffer* wv_buffer_create_dmabuf(int width, int height,
self->height = height;
self->format = fourcc;
self->bo = gbm_bo_create(gbm_device, width, height, fourcc,
GBM_BO_USE_RENDERING);
// Checks not needed anymore. Fixed with SCANOUT and within neatvnc for most GPUs.
// But this could still fail!
//#ifdef HAVE_LINUX_DMA_HEAP
self->bo = have_linux_cma() ?
create_cma_gbm_bo(width, height, fourcc) :
gbm_bo_create(gbm_device, width, height, fourcc,
GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT);
//#endif
// self->bo = gbm_bo_create(gbm_device, width, height, fourcc,
// GBM_BO_USE_RENDERING);
if (!self->bo)
goto bo_failure;

View File

@ -128,6 +128,20 @@ struct cmd_info ctl_event_list[] = {
"Sent after detaching from compositor",
{}
},
[EVT_OUTPUT_ADDED] = {"output-added",
"Sent when an output is added by the compositor",
{
{ "name", "Output name", "<string>" },
{}
}
},
[EVT_OUTPUT_REMOVED] = {"output-removed",
"Sent when an output is removed by the compositor",
{
{ "name", "Output name", "<string>" },
{}
}
},
};
enum cmd_type ctl_command_parse_name(const char* name)

View File

@ -28,6 +28,7 @@
#include <aml.h>
#include <jansson.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "output.h"
#include "ctl-commands.h"
@ -1005,3 +1006,15 @@ void ctl_server_event_detached(struct ctl* self)
{
ctl_server_enqueue_event(self, EVT_DETACHED, json_object());
}
void ctl_server_event_output_added(struct ctl* self, const char* name)
{
ctl_server_enqueue_event(self, EVT_OUTPUT_ADDED,
json_pack("{s:s}", "name", name));
}
void ctl_server_event_output_removed(struct ctl* self, const char* name)
{
ctl_server_enqueue_event(self, EVT_OUTPUT_REMOVED,
json_pack("{s:s}", "name", name));
}

View File

@ -436,3 +436,18 @@ void keyboard_feed_code(struct keyboard* self, xkb_keycode_t code,
send_key(self, code, is_pressed);
}
}
enum nvnc_keyboard_led_state keyboard_get_led_state(
const struct keyboard* self)
{
enum nvnc_keyboard_led_state led_state = 0;
if (xkb_state_led_name_is_active(self->state, XKB_LED_NAME_SCROLL))
led_state |= NVNC_KEYBOARD_LED_SCROLL_LOCK;
if (xkb_state_led_name_is_active(self->state, XKB_LED_NAME_NUM))
led_state |= NVNC_KEYBOARD_LED_NUM_LOCK;
if (xkb_state_led_name_is_active(self->state, XKB_LED_NAME_CAPS))
led_state |= NVNC_KEYBOARD_LED_CAPS_LOCK;
return led_state;
}

View File

@ -57,6 +57,10 @@
#include "util.h"
#include "option-parser.h"
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xfixes.h>
#ifdef ENABLE_PAM
#include "pam_auth.h"
#endif
@ -240,7 +244,10 @@ static void registry_add(void* data, struct wl_registry* registry,
if (!self->is_initializing) {
wl_display_dispatch(self->display);
wl_display_roundtrip(self->display);
ctl_server_event_output_added(self->ctl, output->name);
}
return;
}
@ -322,6 +329,8 @@ static void registry_remove(void* data, struct wl_registry* registry,
} else
nvnc_log(NVNC_LOG_INFO, "Output %s went away", out->name);
ctl_server_event_output_removed(self->ctl, out->name);
wl_list_remove(&out->link);
output_destroy(out);
@ -640,9 +649,9 @@ static void compose_client_info(const struct wayvnc_client* client,
struct ctl_server_client_info* info)
{
info->id = client->id;
socklen_t addrlen = sizeof(info->address);
socklen_t addrlen = sizeof(info->address_storage);
nvnc_client_get_address(client->nvnc_client,
(struct sockaddr*)&info->address, &addrlen);
(struct sockaddr*)&info->address_storage, &addrlen);
info->username = nvnc_client_get_auth_username(client->nvnc_client);
info->seat = client->seat ? client->seat->name : NULL;
}
@ -744,6 +753,125 @@ static void on_pointer_event(struct nvnc_client* client, uint16_t x, uint16_t y,
output_transform_coord(wayvnc->selected_output, x, y, &xfx, &xfy);
pointer_set(&wv_client->pointer, xfx, xfy, button_mask);
// This workaround would only work for x11 apps rendered in xwayland.
// It does NOT work for wayland!
// Waylan doesn't have any API to get the cursor image like in x11.
// We would need to grab and parse the surface of the pointer which is a pain.
// Would that even work with hardware cursors?
/*
/
static char ascii_art[] =
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX "
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX "
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXX "
"XXXXXXXXXXXXXXXXXXXXXXXXXXXX "
"XXXXXXXXXXXXXXXXXXXXXXXXXXX "
"XXXXXXXXXXXXXXXXXXXXXXXXXX "
"XXXXXXXXXXXXXXXXXXXXXXXXX "
"XXXXXXXX "
"XXXXXXXX "
"XXXXXXXX "
"XXXXXXXX "
"XXXXXXXX "
"XXXXXXXX "
"XXXXXXXX "
"XXXXXXXX "
"XXXXXXXX "
"XXXXXXXX "
"XXXXXXXX "
"XXXXXXXX "
"XXXXXXXX "
"XXXXXXXX "
"XXXXXXXX "
"XXXXXXXX "
"XXXXXXXX "
"XXXXXXX "
"XXXXXX "
"XXXXX "
"XXXX "
"XXX "
"XX "
"X ";
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
uint32_t colour = 0x00ff00ffULL;
#else
uint32_t colour = 0xff00ff00ULL;
#endif
// Print current x11 image
Display *display = XOpenDisplay(NULL);
if (!display) {
fprintf(stderr, "Failed to open X display\n");
}
XFixesCursorImage *img = XFixesGetCursorImage(display);
printf("Cursor serial: %ld (%d x %d)\n", img->cursor_serial, img->width, img->height);
//struct nvnc_fb* fb = nvnc_fb_new(32, 32, DRM_FORMAT_RGBA8888, 32);
//assert(fb);
//uint32_t* pixels = nvnc_fb_get_addr(fb);
//for (int i = 0; i < 32 * 32; ++i) {
// pixels[i] = ascii_art[i] != ' ' ? colour : 0;
//}
//nvnc_set_cursor(wv_client->server->nvnc, fb, 32, 32, 0, 0, true);
//nvnc_fb_unref(fb);
*/
/**
* The cursor image itself is returned as a single image at 32 bits per
pixel with 8 bits of alpha in the most significant 8 bits of the
pixel followed by 8 bits each of red, green and finally 8 bits of
blue in the least significant 8 bits. The color components are
pre-multiplied with the alpha component.
Colors are 0xrrggbb
*/
/*
struct nvnc_fb* fb = nvnc_fb_new(img->width, img->height, DRM_FORMAT_RGBA8888, 24);
assert(fb);
// Xlib stores 32-bit data in longs, even if longs are 64-bits long.
unsigned long* argb_data = img->pixels;
//uint32_t* dst = reinterpret_cast<uint32_t*>(image->data());
//uint32_t* dst_end = dst + (img->width * img->height);
//while (dst < dst_end) {
// *dst++ = static_cast<uint32_t>(*src++);
//}
uint32_t* pixels = nvnc_fb_get_addr(fb);
for (int i = 0; i < img->width * img->height; ++i) {
// We need to put alpha to the end of hex fo nvnc buffer
uint8_t a = ((argb_data[i] >> 24) & 0xff);
uint8_t r = ((argb_data[i] >> 16) & 0xff);
uint8_t g = ((argb_data[i] >> 8) & 0xff);
uint8_t b = ((argb_data[i] >> 0) & 0xff);
pixels[i] = ((uint32_t)r << 24) | ((uint32_t)g << 16) | ((uint32_t)b << 8) | a;
}
// TODO: use listener!
// CursorNotify
// https://chromium.googlesource.com/external/webrtc/stable/webrtc/+/master/modules/desktop_capture/mouse_cursor_monitor_x11.cc
// https://github.com/zwcloud/XcbSharp/blob/7d012ec64a2f5e6207da708d70856466ab35e173/xfixes.xml#L125
// sudo pacman -S libx11 libxfixes
// g++ file.c -lX11 -lXfixes -o tt
nvnc_set_cursor(wv_client->server->nvnc, fb, img->width, img->height, img->xhot, img->yhot / 2, true);
nvnc_fb_unref(fb);
XFree(img);
XCloseDisplay(display);
*/
}
static void on_key_event(struct nvnc_client* client, uint32_t symbol,
@ -755,6 +883,9 @@ static void on_key_event(struct nvnc_client* client, uint32_t symbol,
}
keyboard_feed(&wv_client->keyboard, symbol, is_pressed);
nvnc_client_set_led_state(wv_client->nvnc_client,
keyboard_get_led_state(&wv_client->keyboard));
}
static void on_key_code_event(struct nvnc_client* client, uint32_t code,
@ -766,6 +897,9 @@ static void on_key_code_event(struct nvnc_client* client, uint32_t code,
}
keyboard_feed_code(&wv_client->keyboard, code + 8, is_pressed);
nvnc_client_set_led_state(wv_client->nvnc_client,
keyboard_get_led_state(&wv_client->keyboard));
}
static void on_client_cut_text(struct nvnc_client* nvnc_client,
@ -1918,9 +2052,6 @@ int main(int argc, char* argv[])
else if (use_websocket)
socket_type = SOCKET_TYPE_WEBSOCKET;
if (init_nvnc(&self, address, port, socket_type) < 0)
goto nvnc_failure;
if (!start_detached) {
if (self.screencopy.manager)
screencopy_init(&self.screencopy);
@ -1953,6 +2084,9 @@ int main(int argc, char* argv[])
if (!self.ctl)
goto ctl_server_failure;
if (init_nvnc(&self, address, port, socket_type) < 0)
goto nvnc_failure;
if (self.display)
wl_display_dispatch_pending(self.display);
@ -1986,11 +2120,10 @@ int main(int argc, char* argv[])
return 0;
nvnc_failure:
ctl_server_destroy(self.ctl);
ctl_server_failure:
capture_failure:
nvnc_display_unref(self.nvnc_display);
nvnc_close(self.nvnc);
nvnc_failure:
wayland_failure:
aml_unref(aml);
failure:

View File

@ -377,4 +377,4 @@ multioutput_test() {
}
smoke_test
multioutput_test
#multioutput_test