Compare commits
18 Commits
Author | SHA1 | Date |
---|---|---|
Jonas Letzbor | 6dca473059 | |
Jonas Letzbor | ffa0a56335 | |
Andri Yngvason | 50f095d6e8 | |
Attila Fidan | b7de0d9fa6 | |
Attila Fidan | f970c5ceb7 | |
Simon Ser | 3c596455e8 | |
Andri Yngvason | 15660cd4a7 | |
Andri Yngvason | fbd98edae9 | |
Andri Yngvason | 56c38af25f | |
Andri Yngvason | 333381326d | |
Andri Yngvason | 17841f9ece | |
Andri Yngvason | b292c086fe | |
Andri Yngvason | 54fb881aab | |
Andri Yngvason | bd9daa85c3 | |
Jan Beich | 5b01551673 | |
Andri Yngvason | d71bca5270 | |
Andri Yngvason | 5d55944dab | |
Andri Yngvason | d819ca477c |
|
@ -7,3 +7,4 @@ perf.*
|
||||||
*.pem
|
*.pem
|
||||||
.vimrc
|
.vimrc
|
||||||
.cache
|
.cache
|
||||||
|
.vscode
|
10
FAQ.md
10
FAQ.md
|
@ -19,6 +19,16 @@ bindsym $mod+Pause mode passthrough
|
||||||
This makes it so that when you press $mod+Pause, all keybindings, except the one
|
This makes it so that when you press $mod+Pause, all keybindings, except the one
|
||||||
to switch back, are disabled.
|
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?**
|
**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
|
A: Try setting the keyboard layout in wayvnc to the one that most closely
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
|
github: any1
|
||||||
patreon: andriyngvason
|
patreon: andriyngvason
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# wayvnc
|
# 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)
|
[![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)
|
[![Packaging status](https://repology.org/badge/tiny-repos/wayvnc.svg)](https://repology.org/project/wayvnc/versions)
|
||||||
|
|
||||||
## Introduction
|
## 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:
|
with a certificate can be generated like so:
|
||||||
```
|
```
|
||||||
cd ~/.config/wayvnc
|
cd ~/.config/wayvnc
|
||||||
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
|
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:secp384r1 -sha384 \
|
||||||
-keyout tls_key.pem -out tls_cert.pem -subj /CN=localhost \
|
-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
|
-addext subjectAltName=DNS:localhost,DNS:localhost,IP:127.0.0.1
|
||||||
cd -
|
cd -
|
||||||
```
|
```
|
||||||
|
|
|
@ -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
|
|
|
@ -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.
|
|
|
@ -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.
|
|
|
@ -1,6 +0,0 @@
|
||||||
#!/usr/bin/make -f
|
|
||||||
|
|
||||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
|
||||||
|
|
||||||
%:
|
|
||||||
dh $@
|
|
|
@ -1,3 +0,0 @@
|
||||||
---
|
|
||||||
include:
|
|
||||||
- https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/recipes/debian.yml
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -1 +0,0 @@
|
||||||
examples/*
|
|
|
@ -1 +0,0 @@
|
||||||
pios-control/* /
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -40,6 +40,8 @@ enum event_type {
|
||||||
EVT_CLIENT_CONNECTED,
|
EVT_CLIENT_CONNECTED,
|
||||||
EVT_CLIENT_DISCONNECTED,
|
EVT_CLIENT_DISCONNECTED,
|
||||||
EVT_DETACHED,
|
EVT_DETACHED,
|
||||||
|
EVT_OUTPUT_ADDED,
|
||||||
|
EVT_OUTPUT_REMOVED,
|
||||||
EVT_UNKNOWN,
|
EVT_UNKNOWN,
|
||||||
};
|
};
|
||||||
#define EVT_LIST_LEN EVT_UNKNOWN
|
#define EVT_LIST_LEN EVT_UNKNOWN
|
||||||
|
|
|
@ -89,3 +89,6 @@ void ctl_server_event_capture_changed(struct ctl*,
|
||||||
const char* captured_output);
|
const char* captured_output);
|
||||||
|
|
||||||
void ctl_server_event_detached(struct ctl*);
|
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);
|
||||||
|
|
|
@ -19,11 +19,13 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <neatvnc.h>
|
||||||
|
|
||||||
#include "intset.h"
|
#include "intset.h"
|
||||||
|
|
||||||
struct zwp_virtual_keyboard_v1;
|
struct zwp_virtual_keyboard_v1;
|
||||||
struct table_entry;
|
struct table_entry;
|
||||||
|
struct nvnc;
|
||||||
|
|
||||||
struct keyboard {
|
struct keyboard {
|
||||||
struct zwp_virtual_keyboard_v1* virtual_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(struct keyboard* self, xkb_keysym_t symbol, bool is_pressed);
|
||||||
void keyboard_feed_code(struct keyboard* self, xkb_keycode_t code,
|
void keyboard_feed_code(struct keyboard* self, xkb_keycode_t code,
|
||||||
bool is_pressed);
|
bool is_pressed);
|
||||||
|
enum nvnc_keyboard_led_state keyboard_get_led_state(const struct keyboard*);
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#define UDIV_UP(a, b) (((a) + (b) - 1) / (b))
|
#define UDIV_UP(a, b) (((a) + (b) - 1) / (b))
|
||||||
|
#define ALIGN_UP(a, b) ((b) * UDIV_UP((a), (b)))
|
||||||
|
|
||||||
extern const char* wayvnc_version;
|
extern const char* wayvnc_version;
|
||||||
|
|
||||||
|
|
27
meson.build
27
meson.build
|
@ -1,7 +1,7 @@
|
||||||
project(
|
project(
|
||||||
'wayvnc',
|
'wayvnc',
|
||||||
'c',
|
'c',
|
||||||
version: '0.8.0',
|
version: '0.9-dev',
|
||||||
license: 'ISC',
|
license: 'ISC',
|
||||||
default_options: [
|
default_options: [
|
||||||
'c_std=gnu11',
|
'c_std=gnu11',
|
||||||
|
@ -16,6 +16,7 @@ prefix = get_option('prefix')
|
||||||
c_args = [
|
c_args = [
|
||||||
'-D_GNU_SOURCE',
|
'-D_GNU_SOURCE',
|
||||||
'-DAML_UNSTABLE_API=1',
|
'-DAML_UNSTABLE_API=1',
|
||||||
|
'-DWLR_USE_UNSTABLE=true',
|
||||||
|
|
||||||
'-Wno-unused-parameter',
|
'-Wno-unused-parameter',
|
||||||
'-Wno-missing-field-initializers',
|
'-Wno-missing-field-initializers',
|
||||||
|
@ -24,8 +25,8 @@ c_args = [
|
||||||
version = '"@0@"'.format(meson.project_version())
|
version = '"@0@"'.format(meson.project_version())
|
||||||
git = find_program('git', native: true, required: false)
|
git = find_program('git', native: true, required: false)
|
||||||
if git.found()
|
if git.found()
|
||||||
git_commit = run_command([git, 'rev-parse', '--short', 'HEAD'])
|
git_commit = run_command([git, 'rev-parse', '--short', 'HEAD'], check: false)
|
||||||
git_branch = run_command([git, 'rev-parse', '--abbrev-ref', 'HEAD'])
|
git_branch = run_command([git, 'rev-parse', '--abbrev-ref', 'HEAD'], check: false)
|
||||||
if git_commit.returncode() == 0 and git_branch.returncode() == 0
|
if git_commit.returncode() == 0 and git_branch.returncode() == 0
|
||||||
version = '"v@0@-@1@ (@2@)"'.format(
|
version = '"v@0@-@1@ (@2@)"'.format(
|
||||||
meson.project_version(),
|
meson.project_version(),
|
||||||
|
@ -53,11 +54,18 @@ pixman = dependency('pixman-1')
|
||||||
gbm = dependency('gbm', required: get_option('screencopy-dmabuf'))
|
gbm = dependency('gbm', required: get_option('screencopy-dmabuf'))
|
||||||
drm = dependency('libdrm')
|
drm = dependency('libdrm')
|
||||||
xkbcommon = dependency('xkbcommon', version: '>=1.0.0')
|
xkbcommon = dependency('xkbcommon', version: '>=1.0.0')
|
||||||
|
wayland_server = dependency('wayland-server')
|
||||||
wayland_client = dependency('wayland-client')
|
wayland_client = dependency('wayland-client')
|
||||||
|
wayland_client_protocol = dependency('wayland-protocols')
|
||||||
|
wayland_cursor = dependency('wayland-cursor')
|
||||||
jansson = dependency('jansson')
|
jansson = dependency('jansson')
|
||||||
|
|
||||||
|
# Cursor image
|
||||||
|
x11_dep = dependency('x11')
|
||||||
|
x11_fixes_dep = dependency('xfixes')
|
||||||
|
|
||||||
aml_version = ['>=0.3.0', '<0.4.0']
|
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_project = subproject(
|
||||||
'neatvnc',
|
'neatvnc',
|
||||||
|
@ -78,7 +86,7 @@ else
|
||||||
neatvnc = dependency('neatvnc', version: neatvnc_version)
|
neatvnc = dependency('neatvnc', version: neatvnc_version)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
inc = include_directories('include')
|
inc = include_directories('include', '/usr/include/wlroots0.16')
|
||||||
|
|
||||||
subdir('protocols')
|
subdir('protocols')
|
||||||
|
|
||||||
|
@ -119,6 +127,11 @@ dependencies = [
|
||||||
xkbcommon,
|
xkbcommon,
|
||||||
client_protos,
|
client_protos,
|
||||||
jansson,
|
jansson,
|
||||||
|
x11_dep,
|
||||||
|
x11_fixes_dep,
|
||||||
|
wayland_client_protocol,
|
||||||
|
wayland_cursor,
|
||||||
|
wayland_server
|
||||||
]
|
]
|
||||||
|
|
||||||
ctlsources = [
|
ctlsources = [
|
||||||
|
@ -144,6 +157,10 @@ if host_system == 'linux' and get_option('systemtap') and cc.has_header('sys/sdt
|
||||||
config.set('HAVE_USDT', true)
|
config.set('HAVE_USDT', true)
|
||||||
endif
|
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')
|
if cc.has_function('memfd_create')
|
||||||
config.set('HAVE_MEMFD', true)
|
config.set('HAVE_MEMFD', true)
|
||||||
config.set('HAVE_MEMFD_CREATE', true)
|
config.set('HAVE_MEMFD_CREATE', true)
|
||||||
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -1,2 +0,0 @@
|
||||||
u vnc - "vnc" /nonexistent
|
|
||||||
m vnc shadow
|
|
|
@ -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())
|
|
|
@ -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
|
|
|
@ -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
|
|
102
src/buffer.c
102
src/buffer.c
|
@ -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
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -31,10 +31,20 @@
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "pixels.h"
|
#include "pixels.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#ifdef ENABLE_SCREENCOPY_DMABUF
|
#ifdef ENABLE_SCREENCOPY_DMABUF
|
||||||
#include <gbm.h>
|
#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 wl_shm* wl_shm;
|
||||||
extern struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf;
|
extern struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf;
|
||||||
|
@ -118,6 +128,81 @@ failure:
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_SCREENCOPY_DMABUF
|
#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,
|
static struct wv_buffer* wv_buffer_create_dmabuf(int width, int height,
|
||||||
uint32_t fourcc)
|
uint32_t fourcc)
|
||||||
{
|
{
|
||||||
|
@ -133,8 +218,17 @@ static struct wv_buffer* wv_buffer_create_dmabuf(int width, int height,
|
||||||
self->height = height;
|
self->height = height;
|
||||||
self->format = fourcc;
|
self->format = fourcc;
|
||||||
|
|
||||||
self->bo = gbm_bo_create(gbm_device, width, height, fourcc,
|
// Checks not needed anymore. Fixed with SCANOUT and within neatvnc for most GPUs.
|
||||||
GBM_BO_USE_RENDERING);
|
// 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)
|
if (!self->bo)
|
||||||
goto bo_failure;
|
goto bo_failure;
|
||||||
|
|
||||||
|
|
|
@ -128,6 +128,20 @@ struct cmd_info ctl_event_list[] = {
|
||||||
"Sent after detaching from compositor",
|
"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)
|
enum cmd_type ctl_command_parse_name(const char* name)
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <aml.h>
|
#include <aml.h>
|
||||||
#include <jansson.h>
|
#include <jansson.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "ctl-commands.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());
|
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));
|
||||||
|
}
|
||||||
|
|
|
@ -436,3 +436,18 @@ void keyboard_feed_code(struct keyboard* self, xkb_keycode_t code,
|
||||||
send_key(self, code, is_pressed);
|
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;
|
||||||
|
}
|
||||||
|
|
149
src/main.c
149
src/main.c
|
@ -57,6 +57,10 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "option-parser.h"
|
#include "option-parser.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/extensions/Xfixes.h>
|
||||||
|
|
||||||
#ifdef ENABLE_PAM
|
#ifdef ENABLE_PAM
|
||||||
#include "pam_auth.h"
|
#include "pam_auth.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -240,7 +244,10 @@ static void registry_add(void* data, struct wl_registry* registry,
|
||||||
if (!self->is_initializing) {
|
if (!self->is_initializing) {
|
||||||
wl_display_dispatch(self->display);
|
wl_display_dispatch(self->display);
|
||||||
wl_display_roundtrip(self->display);
|
wl_display_roundtrip(self->display);
|
||||||
|
|
||||||
|
ctl_server_event_output_added(self->ctl, output->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,6 +329,8 @@ static void registry_remove(void* data, struct wl_registry* registry,
|
||||||
} else
|
} else
|
||||||
nvnc_log(NVNC_LOG_INFO, "Output %s went away", out->name);
|
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);
|
wl_list_remove(&out->link);
|
||||||
output_destroy(out);
|
output_destroy(out);
|
||||||
|
|
||||||
|
@ -640,9 +649,9 @@ static void compose_client_info(const struct wayvnc_client* client,
|
||||||
struct ctl_server_client_info* info)
|
struct ctl_server_client_info* info)
|
||||||
{
|
{
|
||||||
info->id = client->id;
|
info->id = client->id;
|
||||||
socklen_t addrlen = sizeof(info->address);
|
socklen_t addrlen = sizeof(info->address_storage);
|
||||||
nvnc_client_get_address(client->nvnc_client,
|
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->username = nvnc_client_get_auth_username(client->nvnc_client);
|
||||||
info->seat = client->seat ? client->seat->name : NULL;
|
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);
|
output_transform_coord(wayvnc->selected_output, x, y, &xfx, &xfy);
|
||||||
|
|
||||||
pointer_set(&wv_client->pointer, xfx, xfy, button_mask);
|
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,
|
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);
|
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,
|
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);
|
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,
|
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)
|
else if (use_websocket)
|
||||||
socket_type = SOCKET_TYPE_WEBSOCKET;
|
socket_type = SOCKET_TYPE_WEBSOCKET;
|
||||||
|
|
||||||
if (init_nvnc(&self, address, port, socket_type) < 0)
|
|
||||||
goto nvnc_failure;
|
|
||||||
|
|
||||||
if (!start_detached) {
|
if (!start_detached) {
|
||||||
if (self.screencopy.manager)
|
if (self.screencopy.manager)
|
||||||
screencopy_init(&self.screencopy);
|
screencopy_init(&self.screencopy);
|
||||||
|
@ -1953,6 +2084,9 @@ int main(int argc, char* argv[])
|
||||||
if (!self.ctl)
|
if (!self.ctl)
|
||||||
goto ctl_server_failure;
|
goto ctl_server_failure;
|
||||||
|
|
||||||
|
if (init_nvnc(&self, address, port, socket_type) < 0)
|
||||||
|
goto nvnc_failure;
|
||||||
|
|
||||||
if (self.display)
|
if (self.display)
|
||||||
wl_display_dispatch_pending(self.display);
|
wl_display_dispatch_pending(self.display);
|
||||||
|
|
||||||
|
@ -1986,11 +2120,10 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
nvnc_failure:
|
||||||
|
ctl_server_destroy(self.ctl);
|
||||||
ctl_server_failure:
|
ctl_server_failure:
|
||||||
capture_failure:
|
capture_failure:
|
||||||
nvnc_display_unref(self.nvnc_display);
|
|
||||||
nvnc_close(self.nvnc);
|
|
||||||
nvnc_failure:
|
|
||||||
wayland_failure:
|
wayland_failure:
|
||||||
aml_unref(aml);
|
aml_unref(aml);
|
||||||
failure:
|
failure:
|
||||||
|
|
|
@ -377,4 +377,4 @@ multioutput_test() {
|
||||||
}
|
}
|
||||||
|
|
||||||
smoke_test
|
smoke_test
|
||||||
multioutput_test
|
#multioutput_test
|
||||||
|
|
Loading…
Reference in New Issue