Compare commits

..

No commits in common. "master" and "output-management" have entirely different histories.

20 changed files with 69 additions and 458 deletions

1
.gitignore vendored
View File

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

10
FAQ.md
View File

@ -19,16 +19,6 @@ 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,2 +1 @@
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/pulls/1.svg)](https://builds.sr.ht/~andri/wayvnc/pulls/1?)
[![builds.sr.ht status](https://builds.sr.ht/~andri/wayvnc/commits/master.svg)](https://builds.sr.ht/~andri/wayvnc/commits/master?)
[![Packaging status](https://repology.org/badge/tiny-repos/wayvnc.svg)](https://repology.org/project/wayvnc/versions)
## Introduction
@ -122,9 +122,8 @@ 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 ec -pkeyopt ec_paramgen_curve:secp384r1 -sha384 \
-days 3650 -nodes -keyout tls_key.pem -out tls_cert.pem \
-subj /CN=localhost \
openssl req -x509 -newkey rsa:4096 -sha256 -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 -
```

View File

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

@ -19,8 +19,6 @@
#include "output.h"
#include <sys/socket.h>
struct ctl;
struct cmd_response;
@ -28,12 +26,9 @@ struct ctl_server_client;
struct ctl_server_client_info {
int id;
union {
struct sockaddr_storage address_storage;
struct sockaddr address;
};
const char* username;
const char* seat;
const char *hostname;
const char *username;
const char *seat;
};
struct ctl_server_output {
@ -89,6 +84,3 @@ 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,13 +19,11 @@
#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;
@ -46,4 +44,3 @@ 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,7 +19,6 @@
#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.9-dev',
version: '0.8-dev',
license: 'ISC',
default_options: [
'c_std=gnu11',
@ -16,7 +16,6 @@ prefix = get_option('prefix')
c_args = [
'-D_GNU_SOURCE',
'-DAML_UNSTABLE_API=1',
'-DWLR_USE_UNSTABLE=true',
'-Wno-unused-parameter',
'-Wno-missing-field-initializers',
@ -25,8 +24,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'], check: false)
git_branch = run_command([git, 'rev-parse', '--abbrev-ref', 'HEAD'], check: false)
git_commit = run_command([git, 'rev-parse', '--short', 'HEAD'])
git_branch = run_command([git, 'rev-parse', '--abbrev-ref', 'HEAD'])
if git_commit.returncode() == 0 and git_branch.returncode() == 0
version = '"v@0@-@1@ (@2@)"'.format(
meson.project_version(),
@ -54,18 +53,11 @@ 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.9', '<0.10.0']
neatvnc_version = ['>=0.7.0', '<0.9.0']
neatvnc_project = subproject(
'neatvnc',
@ -86,7 +78,7 @@ else
neatvnc = dependency('neatvnc', version: neatvnc_version)
endif
inc = include_directories('include', '/usr/include/wlroots0.16')
inc = include_directories('include')
subdir('protocols')
@ -127,11 +119,6 @@ dependencies = [
xkbcommon,
client_protos,
jansson,
x11_dep,
x11_fixes_dep,
wayland_client_protocol,
wayland_cursor,
wayland_server
]
ctlsources = [
@ -157,10 +144,6 @@ 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,5 +1,5 @@
/*
* Copyright (c) 2020 - 2024 Andri Yngvason
* Copyright (c) 2020 - 2021 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,20 +31,10 @@
#include "buffer.h"
#include "pixels.h"
#include "config.h"
#include "util.h"
#ifdef ENABLE_SCREENCOPY_DMABUF
#include <gbm.h>
#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
#endif
extern struct wl_shm* wl_shm;
extern struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf;
@ -128,81 +118,6 @@ 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)
{
@ -218,17 +133,8 @@ static struct wv_buffer* wv_buffer_create_dmabuf(int width, int height,
self->height = height;
self->format = fourcc;
// 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);
self->bo = gbm_bo_create(gbm_device, width, height, fourcc,
GBM_BO_USE_RENDERING);
if (!self->bo)
goto bo_failure;

View File

@ -354,17 +354,17 @@ static void pretty_client_list(json_t* data)
json_t* value;
json_array_foreach(data, i, value) {
char* id = NULL;
char* address = NULL;
char* hostname = NULL;
char* username = NULL;
json_unpack(value, "{s:s, s?s, s?s}", "id", &id, "address",
&address, "username", &username);
json_unpack(value, "{s:s, s?s, s?s}", "id", &id, "hostname",
&hostname, "username", &username);
printf(" %s: ", id);
if (username)
printf("%s@", username);
printf("%s\n", address ? address : "<unknown>");
printf("%s\n", hostname ? hostname : "<unknown>");
}
}

View File

@ -98,8 +98,8 @@ struct cmd_info ctl_command_list[] = {
{ "connection_count", \
"The total number of connected VNC clients " including " this one.", \
"<integer>" }, \
{ "address", \
"The IP address of this client (may be null)", \
{ "hostname", \
"The hostname or IP address of this client (may be null)", \
"<name|ip>" }, \
{ "username", \
"The username used to authentice this client (may be null).", \
@ -128,20 +128,6 @@ 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

@ -27,8 +27,6 @@
#include <neatvnc.h>
#include <aml.h>
#include <jansson.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "output.h"
#include "ctl-commands.h"
@ -364,25 +362,6 @@ static struct ctl_server_client* ctl_server_client_next(struct ctl* self,
return self->actions.client_next(self, prev);
}
static int sockaddr_to_string(char* dst, size_t sz, const struct sockaddr* addr)
{
struct sockaddr_in* sa_in = (struct sockaddr_in*)addr;
struct sockaddr_in6* sa_in6 = (struct sockaddr_in6*)addr;
switch (addr->sa_family) {
case AF_INET:
inet_ntop(addr->sa_family, &sa_in->sin_addr, dst, sz);
return 0;
case AF_INET6:
inet_ntop(addr->sa_family, &sa_in6->sin6_addr, dst, sz);
return 0;
}
nvnc_log(NVNC_LOG_DEBUG,
"Don't know how to convert sa_family %d to string",
addr->sa_family);
return -1;
}
static void ctl_server_client_get_info(struct ctl* self,
const struct ctl_server_client* client,
struct ctl_server_client_info* info)
@ -405,12 +384,9 @@ static struct cmd_response* generate_vnc_client_list(struct ctl* self)
snprintf(id_str, sizeof(id_str), "%d", info.id);
json_t* packed = json_pack("{s:s}", "id", id_str);
char address_string[256];
if (sockaddr_to_string(address_string, sizeof(address_string),
&info.address) == 0) {
json_object_set_new(packed, "address",
json_string(address_string));
}
if (info.hostname)
json_object_set_new(packed, "hostname",
json_string(info.hostname));
if (info.username)
json_object_set_new(packed, "username",
@ -921,13 +897,9 @@ json_t* pack_connection_event_params(
char id_str[64];
snprintf(id_str, sizeof(id_str), "%d", info->id);
char address_string[256];
bool have_addr = sockaddr_to_string(address_string,
sizeof(address_string), &info->address) == 0;
return json_pack("{s:s, s:s?, s:s?, s:s?, s:i}",
"id", id_str,
"address", have_addr ? address_string : NULL,
"hostname", info->hostname,
"username", info->username,
"seat", info->seat,
"connection_count", new_connection_count);
@ -1006,15 +978,3 @@ 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,18 +436,3 @@ 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,10 +57,6 @@
#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
@ -91,7 +87,6 @@ struct wayvnc {
struct wl_display* display;
struct wl_registry* registry;
struct aml_handler* wl_handler;
struct wl_list outputs;
struct wl_list seats;
struct cfg cfg;
@ -244,10 +239,7 @@ 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;
}
@ -329,8 +321,6 @@ 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);
@ -402,10 +392,6 @@ static void wayland_detach(struct wayvnc* self)
if (!self->display)
return;
aml_stop(aml_get_default(), self->wl_handler);
aml_unref(self->wl_handler);
self->wl_handler = NULL;
// Screen blanking is required to release wl_shm of linux_dmabuf.
if (self->nvnc)
blank_screen(self);
@ -478,8 +464,7 @@ static void wayland_detach(struct wayvnc* self)
wl_display_disconnect(self->display);
self->display = NULL;
if (self->ctl)
ctl_server_event_detached(self->ctl);
ctl_server_event_detached(self->ctl);
}
void wayvnc_destroy(struct wayvnc* self)
@ -576,24 +561,21 @@ static int init_wayland(struct wayvnc* self, const char* display)
self->screencopy.on_done = on_capture_done;
self->screencopy.userdata = self;
self->wl_handler = aml_handler_new(wl_display_get_fd(self->display),
struct aml_handler* wl_handler;
wl_handler = aml_handler_new(wl_display_get_fd(self->display),
on_wayland_event, self, NULL);
if (!self->wl_handler)
if (!wl_handler)
goto failure;
int rc = aml_start(aml_get_default(), self->wl_handler);
int rc = aml_start(aml_get_default(), wl_handler);
aml_unref(wl_handler);
if (rc < 0)
goto handler_failure;
goto failure;
return 0;
failure:
wl_display_disconnect(self->display);
self->display = NULL;
handler_failure:
if (self->wl_handler)
aml_unref(self->wl_handler);
self->wl_handler = NULL;
return -1;
}
@ -645,24 +627,17 @@ static struct ctl_server_client *client_next(struct ctl* ctl,
(struct ctl_server_client*)nvnc_client_first(self->nvnc);
}
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_storage);
nvnc_client_get_address(client->nvnc_client,
(struct sockaddr*)&info->address_storage, &addrlen);
info->username = nvnc_client_get_auth_username(client->nvnc_client);
info->seat = client->seat ? client->seat->name : NULL;
}
static void client_info(const struct ctl_server_client* client_handle,
struct ctl_server_client_info* info)
{
const struct nvnc_client *vnc_client =
(const struct nvnc_client*)client_handle;
const struct wayvnc_client *client = nvnc_get_userdata(vnc_client);
compose_client_info(client, info);
info->id = client->id;
info->hostname = nvnc_client_get_hostname(vnc_client);
info->username = nvnc_client_get_auth_username(vnc_client);
info->seat = client->seat ? client->seat->name : NULL;
}
static int get_output_list(struct ctl* ctl,
@ -753,125 +728,6 @@ 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,
@ -883,9 +739,6 @@ 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,
@ -897,9 +750,6 @@ 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,
@ -1419,13 +1269,14 @@ static void client_destroy(void* obj)
nvnc_log(NVNC_LOG_DEBUG, "Client disconnected, new client count: %d",
wayvnc->nr_clients);
if (wayvnc->ctl) {
struct ctl_server_client_info info = {};
compose_client_info(self, &info);
struct ctl_server_client_info info = {
.id = self->id,
.hostname = nvnc_client_get_hostname(self->nvnc_client),
.username = nvnc_client_get_auth_username(self->nvnc_client),
.seat = self->seat ? self->seat->name : NULL,
};
ctl_server_event_disconnected(wayvnc->ctl, &info,
wayvnc->nr_clients);
}
ctl_server_event_disconnected(wayvnc->ctl, &info, wayvnc->nr_clients);
if (wayvnc->nr_clients == 0 && wayvnc->display) {
nvnc_log(NVNC_LOG_INFO, "Stopping screen capture");
@ -1471,8 +1322,12 @@ static void on_nvnc_client_new(struct nvnc_client* client)
nvnc_log(NVNC_LOG_DEBUG, "Client connected, new client count: %d",
self->nr_clients);
struct ctl_server_client_info info = {};
compose_client_info(wayvnc_client, &info);
struct ctl_server_client_info info = {
.id = wayvnc_client->id,
.hostname = nvnc_client_get_hostname(client),
.username = nvnc_client_get_auth_username(client),
.seat = wayvnc_client->seat ? wayvnc_client->seat->name : NULL,
};
ctl_server_event_connected(self->ctl, &info, self->nr_clients);
}
@ -1693,42 +1548,16 @@ void switch_to_prev_output(struct wayvnc* self)
switch_to_output(self, prev);
}
static char intercepted_error[256];
static void intercept_cmd_error(const struct nvnc_log_data* meta,
const char* message)
{
if (meta->level != NVNC_LOG_ERROR) {
nvnc_default_logger(meta, message);
return;
}
struct nvnc_log_data meta_override = *meta;
meta_override.level = NVNC_LOG_DEBUG;
nvnc_default_logger(&meta_override, message);
size_t len = strlen(intercepted_error);
if (len != 0 && len < sizeof(intercepted_error) - 2)
intercepted_error[len++] = '\n';
strlcpy(intercepted_error + len, message,
sizeof(intercepted_error) - len);
}
static struct cmd_response* on_attach(struct ctl* ctl, const char* display)
{
struct wayvnc* self = ctl_server_userdata(ctl);
assert(self);
memset(intercepted_error, 0, sizeof(intercepted_error));
nvnc_set_log_fn_thread_local(intercept_cmd_error);
// TODO: Add optional output argument
bool ok = wayland_attach(self, display, NULL);
if (!wayland_attach(self, display, NULL))
return cmd_failed("Failed to attach to %s", display);
nvnc_set_log_fn_thread_local(NULL);
return ok ? cmd_ok() : cmd_failed("%s", intercepted_error);
return cmd_ok();
}
static bool wayland_attach(struct wayvnc* self, const char* display,
@ -2052,6 +1881,9 @@ 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);
@ -2084,9 +1916,6 @@ 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);
@ -2104,7 +1933,6 @@ int main(int argc, char* argv[])
screencopy_stop(&self.screencopy);
ctl_server_destroy(self.ctl);
self.ctl = NULL;
nvnc_display_unref(self.nvnc_display);
nvnc_close(self.nvnc);
@ -2120,10 +1948,11 @@ 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

@ -211,18 +211,7 @@ void wlr_output_manager_destroy(void)
if (!wlr_output_manager)
return;
struct output_manager_head* head;
struct output_manager_head* tmp;
wl_list_for_each_safe(head, tmp, &heads, link) {
wl_list_remove(&head->link);
free(head->name);
free(head);
}
zwlr_output_manager_v1_destroy(wlr_output_manager);
wlr_output_manager = NULL;
last_config_serial = 0;
}
bool wlr_output_manager_resize_output(struct output* output,

View File

@ -30,7 +30,7 @@ static int pam_return_pwd(int num_msg, const struct pam_message** msgm,
struct pam_response** response, void* appdata_ptr)
{
struct credentials* cred = appdata_ptr;
struct pam_response* resp = calloc(num_msg, sizeof(*resp));
struct pam_response* resp = calloc(sizeof(*response), num_msg);
for (int i = 0; i < num_msg; i++) {
resp[i].resp_retcode = PAM_SUCCESS;
switch(msgm[i]->msg_style) {

View File

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

View File

@ -269,8 +269,8 @@ Parameters:
*connection_count=...*
The total number of connected VNC clients including this one.
*address=...*
The IP address of this client. May be null.
*hostname=...*
The hostname or IP of this client. May be null.
*username=...*
The username used to authenticate this client. May be null.
@ -288,8 +288,8 @@ Parameters:
*connection_count=...*
The total number of connected VNC clients not including this one.
*address=...*
The IP address of this client. May be null.
*hostname=...*
The hostname or IP of this client. May be null.
*username=...*
The username used to authenticate this client. May be null.

View File

@ -63,8 +63,8 @@ the end, for ease in scripting:
```
$ wayvncctl --json event-receive
{"method":"client-connected","params":{"id":"0x10ef670","address":null,"username":null,"connection_count":1}}
{"method":"client-disconnected","params":{"id":"0x10ef670","address":null,"username":null,"connection_count":0}}
{"method":"client-connected","params":{"id":"0x10ef670","hostname":null,"username":null,"connection_count":1}}
{"method":"client-disconnected","params":{"id":"0x10ef670","hostname":null,"username":null,"connection_count":0}}
```
The default human-readible output is a multi-line yaml-like format, with two
@ -75,12 +75,12 @@ $ wayvncctl event-receive
client-connected:
id: 0x10ef670
address: 192.168.1.18
hostname: 192.168.1.18
connection_count: 1
client-disconnected:
id: 0x10ef670
address: 192.168.1.18
hostname: 192.168.1.18
connection_count: 0
```