Compare commits

...

18 Commits
v0.8 ... 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
15 changed files with 329 additions and 21 deletions

1
.gitignore vendored
View File

@ -7,3 +7,4 @@ perf.*
*.pem *.pem
.vimrc .vimrc
.cache .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 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

View File

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

View File

@ -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 -
``` ```

View File

@ -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

View File

@ -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);

View File

@ -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*);

View File

@ -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;

View File

@ -1,7 +1,7 @@
project( project(
'wayvnc', 'wayvnc',
'c', 'c',
version: '0.8-dev', 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)

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 * 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;

View File

@ -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)

View File

@ -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));
}

View File

@ -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;
}

View File

@ -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:

View File

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