Create a nicer API around libvncclient
This hides some implementation details of libvncclient from the rest of the system and reduces coupling.qemu-extended-key-event
parent
da1ad20dcd
commit
0a68dbb720
|
@ -9,6 +9,7 @@ Expect bugs and missing features.
|
||||||
* libvncclient
|
* libvncclient
|
||||||
* libwayland
|
* libwayland
|
||||||
* libxkbcommon
|
* libxkbcommon
|
||||||
|
* pixman
|
||||||
|
|
||||||
## Build Dependencies
|
## Build Dependencies
|
||||||
* GCC/clang
|
* GCC/clang
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <pixman.h>
|
||||||
|
#include <wayland-client.h>
|
||||||
|
#include <rfb/rfbclient.h>
|
||||||
|
|
||||||
|
struct vnc_client {
|
||||||
|
rfbClient* client;
|
||||||
|
|
||||||
|
int (*alloc_fb)(struct vnc_client*);
|
||||||
|
void (*update_fb)(struct vnc_client*);
|
||||||
|
|
||||||
|
void* userdata;
|
||||||
|
struct pixman_region16 damage;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vnc_client* vnc_client_create(void);
|
||||||
|
void vnc_client_destroy(struct vnc_client* self);
|
||||||
|
|
||||||
|
int vnc_client_connect(struct vnc_client* self, const char* address, int port);
|
||||||
|
|
||||||
|
int vnc_client_set_pixel_format(struct vnc_client* self,
|
||||||
|
enum wl_shm_format format);
|
||||||
|
|
||||||
|
int vnc_client_get_fd(const struct vnc_client* self);
|
||||||
|
int vnc_client_get_width(const struct vnc_client* self);
|
||||||
|
int vnc_client_get_height(const struct vnc_client* self);
|
||||||
|
int vnc_client_get_stride(const struct vnc_client* self);
|
||||||
|
void* vnc_client_get_fb(const struct vnc_client* self);
|
||||||
|
void vnc_client_set_fb(struct vnc_client* self, void* fb);
|
||||||
|
const char* vnc_client_get_desktop_name(const struct vnc_client* self);
|
||||||
|
int vnc_client_process(struct vnc_client* self);
|
||||||
|
void vnc_client_send_pointer_event(struct vnc_client* self, int x, int y,
|
||||||
|
uint32_t button_mask);
|
||||||
|
void vnc_client_send_keyboard_event(struct vnc_client* self, uint32_t symbol,
|
||||||
|
bool is_pressed);
|
|
@ -28,6 +28,7 @@ libm = cc.find_library('m', required: false)
|
||||||
librt = cc.find_library('rt', required: false)
|
librt = cc.find_library('rt', required: false)
|
||||||
|
|
||||||
xkbcommon = dependency('xkbcommon')
|
xkbcommon = dependency('xkbcommon')
|
||||||
|
pixman = dependency('pixman-1')
|
||||||
wayland_client = dependency('wayland-client')
|
wayland_client = dependency('wayland-client')
|
||||||
libvncclient = dependency('libvncclient')
|
libvncclient = dependency('libvncclient')
|
||||||
|
|
||||||
|
@ -48,6 +49,7 @@ sources = [
|
||||||
'src/seat.c',
|
'src/seat.c',
|
||||||
'src/pointer.c',
|
'src/pointer.c',
|
||||||
'src/keyboard.c',
|
'src/keyboard.c',
|
||||||
|
'src/vnc.c',
|
||||||
'src/strlcpy.c',
|
'src/strlcpy.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -55,6 +57,7 @@ dependencies = [
|
||||||
libm,
|
libm,
|
||||||
librt,
|
librt,
|
||||||
xkbcommon,
|
xkbcommon,
|
||||||
|
pixman,
|
||||||
aml,
|
aml,
|
||||||
wayland_client,
|
wayland_client,
|
||||||
libvncclient,
|
libvncclient,
|
||||||
|
|
141
src/main.c
141
src/main.c
|
@ -26,14 +26,15 @@
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <aml.h>
|
#include <aml.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include <rfb/rfbclient.h>
|
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
|
#include "pixman.h"
|
||||||
#include "xdg-shell.h"
|
#include "xdg-shell.h"
|
||||||
#include "shm.h"
|
#include "shm.h"
|
||||||
#include "seat.h"
|
#include "seat.h"
|
||||||
#include "pointer.h"
|
#include "pointer.h"
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
|
#include "vnc.h"
|
||||||
|
|
||||||
struct buffer {
|
struct buffer {
|
||||||
int width, height, stride;
|
int width, height, stride;
|
||||||
|
@ -49,7 +50,6 @@ struct window {
|
||||||
struct xdg_toplevel* xdg_toplevel;
|
struct xdg_toplevel* xdg_toplevel;
|
||||||
|
|
||||||
struct buffer* buffer;
|
struct buffer* buffer;
|
||||||
bool is_attached;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct wl_display* wl_display;
|
static struct wl_display* wl_display;
|
||||||
|
@ -357,18 +357,18 @@ static void window_destroy(struct window* w)
|
||||||
void on_pointer_event(struct pointer_collection* collection,
|
void on_pointer_event(struct pointer_collection* collection,
|
||||||
struct pointer* pointer)
|
struct pointer* pointer)
|
||||||
{
|
{
|
||||||
rfbClient* client = collection->userdata;
|
struct vnc_client* client = collection->userdata;
|
||||||
|
|
||||||
int x = wl_fixed_to_int(pointer->x);
|
int x = wl_fixed_to_int(pointer->x);
|
||||||
int y = wl_fixed_to_int(pointer->y);
|
int y = wl_fixed_to_int(pointer->y);
|
||||||
|
|
||||||
SendPointerEvent(client, x, y, pointer->pressed);
|
vnc_client_send_pointer_event(client, x, y, pointer->pressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_keyboard_event(struct keyboard_collection* collection,
|
void on_keyboard_event(struct keyboard_collection* collection,
|
||||||
struct keyboard* keyboard, uint32_t key, bool is_pressed)
|
struct keyboard* keyboard, uint32_t key, bool is_pressed)
|
||||||
{
|
{
|
||||||
rfbClient* client = collection->userdata;
|
struct vnc_client* client = collection->userdata;
|
||||||
|
|
||||||
// TODO handle multiple symbols
|
// TODO handle multiple symbols
|
||||||
xkb_keysym_t symbol = xkb_state_key_get_one_sym(keyboard->state, key);
|
xkb_keysym_t symbol = xkb_state_key_get_one_sym(keyboard->state, key);
|
||||||
|
@ -376,109 +376,81 @@ void on_keyboard_event(struct keyboard_collection* collection,
|
||||||
char name[256];
|
char name[256];
|
||||||
xkb_keysym_get_name(symbol, name, sizeof(name));
|
xkb_keysym_get_name(symbol, name, sizeof(name));
|
||||||
|
|
||||||
SendKeyEvent(client, symbol, is_pressed);
|
vnc_client_send_keyboard_event(client, symbol, is_pressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
rfbBool rfb_client_alloc_fb(rfbClient* cl)
|
int on_vnc_client_alloc_fb(struct vnc_client* client)
|
||||||
{
|
{
|
||||||
int stride = cl->width * 4; // TODO?
|
|
||||||
|
|
||||||
assert(!window); // TODO: Support resizing
|
assert(!window); // TODO: Support resizing
|
||||||
|
|
||||||
window = window_create(cl->desktopName);
|
int width = vnc_client_get_width(client);
|
||||||
|
int height = vnc_client_get_height(client);
|
||||||
|
int stride = vnc_client_get_stride(client);
|
||||||
|
|
||||||
|
window = window_create(vnc_client_get_desktop_name(client));
|
||||||
if (!window)
|
if (!window)
|
||||||
return FALSE;
|
return -1;
|
||||||
|
|
||||||
window->buffer = buffer_create(cl->width, cl->height, stride,
|
window->buffer = buffer_create(width, height, stride, wl_shm_format);
|
||||||
wl_shm_format);
|
vnc_client_set_fb(client, window->buffer->pixels);
|
||||||
|
return 0;
|
||||||
cl->frameBuffer = window->buffer->pixels;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rfb_client_update_box(rfbClient* cl, int x, int y, int width, int height)
|
void on_vnc_client_update_fb(struct vnc_client* client)
|
||||||
{
|
{
|
||||||
|
if (!pixman_region_not_empty(&client->damage))
|
||||||
|
return;
|
||||||
|
|
||||||
// TODO: Make sure that the buffer is released at this point, or make
|
// TODO: Make sure that the buffer is released at this point, or make
|
||||||
// this a side-buffer and copy damaged regions into double buffers.
|
// this a side-buffer and copy damaged regions into double buffers.
|
||||||
|
|
||||||
if (!window->is_attached)
|
|
||||||
window_attach(window, 0, 0);
|
window_attach(window, 0, 0);
|
||||||
|
|
||||||
|
int n_rects = 0;
|
||||||
|
struct pixman_box16* box = pixman_region_rectangles(&client->damage,
|
||||||
|
&n_rects);
|
||||||
|
|
||||||
|
for (int i = 0; i < n_rects; ++i) {
|
||||||
|
int x = box[i].x1;
|
||||||
|
int y = box[i].y1;
|
||||||
|
int width = box[i].x2 - x;
|
||||||
|
int height = box[i].y2 - y;
|
||||||
|
|
||||||
window_damage(window, x, y, width, height);
|
window_damage(window, x, y, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rfb_client_finish_update(rfbClient* cl)
|
|
||||||
{
|
|
||||||
window_commit(window);
|
window_commit(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_rfb_client_server_event(void* obj)
|
void on_vnc_client_event(void* obj)
|
||||||
{
|
{
|
||||||
rfbClient* cl = aml_get_userdata(obj);
|
struct vnc_client* client = aml_get_userdata(obj);
|
||||||
if (!HandleRFBServerMessage(cl))
|
if (vnc_client_process(client) < 0)
|
||||||
do_run = false;
|
do_run = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rfb_format_from_wl_shm_format(rfbPixelFormat* dst,
|
static struct vnc_client* connect_to_server(const char* address, int port)
|
||||||
enum wl_shm_format src)
|
|
||||||
{
|
{
|
||||||
int bpp = -1;
|
struct vnc_client* client = vnc_client_create();
|
||||||
|
if (!client)
|
||||||
switch (src) {
|
|
||||||
case WL_SHM_FORMAT_ARGB8888:
|
|
||||||
case WL_SHM_FORMAT_XRGB8888:
|
|
||||||
dst->redShift = 16;
|
|
||||||
dst->greenShift = 8;
|
|
||||||
dst->blueShift = 0;
|
|
||||||
bpp = 32;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (bpp) {
|
|
||||||
case 32:
|
|
||||||
dst->bitsPerPixel = 32;
|
|
||||||
dst->depth = 24;
|
|
||||||
dst->redMax = 0xff;
|
|
||||||
dst->greenMax = 0xff;
|
|
||||||
dst->blueMax = 0xff;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static rfbClient* rfb_client_create(int* argc, char* argv[])
|
|
||||||
{
|
|
||||||
int bits_per_sample = 8;
|
|
||||||
int samples_per_pixel = 3;
|
|
||||||
int bytes_per_pixel = 4;
|
|
||||||
|
|
||||||
rfbClient* cl = rfbGetClient(bits_per_sample, samples_per_pixel,
|
|
||||||
bytes_per_pixel);
|
|
||||||
if (!cl)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
cl->MallocFrameBuffer = rfb_client_alloc_fb;
|
client->alloc_fb = on_vnc_client_alloc_fb;
|
||||||
cl->GotFrameBufferUpdate = rfb_client_update_box;
|
client->update_fb = on_vnc_client_update_fb;
|
||||||
cl->FinishedFrameBufferUpdate = rfb_client_finish_update;
|
|
||||||
|
|
||||||
if (rfb_format_from_wl_shm_format(&cl->format, wl_shm_format) < 0) {
|
if (vnc_client_set_pixel_format(client, wl_shm_format) < 0) {
|
||||||
fprintf(stderr, "Unsupported pixel format\n");
|
fprintf(stderr, "Unsupported pixel format\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rfbInitClient(cl, argc, argv))
|
if (vnc_client_connect(client, address, port) < 0) {
|
||||||
return NULL;
|
fprintf(stderr, "Failed to connect to server\n");
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
|
||||||
int fd = cl->sock;
|
int fd = vnc_client_get_fd(client);
|
||||||
|
|
||||||
struct aml_handler* handler;
|
struct aml_handler* handler;
|
||||||
handler = aml_handler_new(fd, on_rfb_client_server_event, cl, NULL);
|
handler = aml_handler_new(fd, on_vnc_client_event, client, NULL);
|
||||||
if (!handler)
|
if (!handler)
|
||||||
goto failure;
|
goto failure;
|
||||||
|
|
||||||
|
@ -488,22 +460,33 @@ static rfbClient* rfb_client_create(int* argc, char* argv[])
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
goto failure;
|
goto failure;
|
||||||
|
|
||||||
return cl;
|
return client;
|
||||||
|
|
||||||
failure:
|
failure:
|
||||||
rfbClientCleanup(cl);
|
vnc_client_destroy(client);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rfb_client_destroy(rfbClient* cl)
|
static int usage(int r)
|
||||||
{
|
{
|
||||||
rfbClientCleanup(cl);
|
fprintf(r ? stderr : stdout, "\
|
||||||
|
Usage: wlvncc <address> [port]\n\
|
||||||
|
");
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
return usage(1);
|
||||||
|
|
||||||
|
const char* address = argv[1];
|
||||||
|
int port = 5900;
|
||||||
|
if (argc > 2)
|
||||||
|
port = atoi(argv[2]);
|
||||||
|
|
||||||
struct aml* aml = aml_new();
|
struct aml* aml = aml_new();
|
||||||
if (!aml)
|
if (!aml)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -550,7 +533,7 @@ int main(int argc, char* argv[])
|
||||||
wl_display_roundtrip(wl_display);
|
wl_display_roundtrip(wl_display);
|
||||||
wl_display_roundtrip(wl_display);
|
wl_display_roundtrip(wl_display);
|
||||||
|
|
||||||
rfbClient* vnc = rfb_client_create(&argc, argv);
|
struct vnc_client* vnc = connect_to_server(address, port);
|
||||||
if (!vnc)
|
if (!vnc)
|
||||||
goto vnc_failure;
|
goto vnc_failure;
|
||||||
|
|
||||||
|
@ -568,7 +551,7 @@ int main(int argc, char* argv[])
|
||||||
rc = 0;
|
rc = 0;
|
||||||
if (window)
|
if (window)
|
||||||
window_destroy(window);
|
window_destroy(window);
|
||||||
rfb_client_destroy(vnc);
|
vnc_client_destroy(vnc);
|
||||||
vnc_failure:
|
vnc_failure:
|
||||||
seat_list_destroy(&seats);
|
seat_list_destroy(&seats);
|
||||||
wl_compositor_destroy(wl_compositor);
|
wl_compositor_destroy(wl_compositor);
|
||||||
|
|
|
@ -0,0 +1,200 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <pixman.h>
|
||||||
|
#include <rfb/rfbclient.h>
|
||||||
|
#include <wayland-client.h>
|
||||||
|
|
||||||
|
#include "vnc.h"
|
||||||
|
|
||||||
|
static rfbBool vnc_client_alloc_fb(rfbClient* client)
|
||||||
|
{
|
||||||
|
struct vnc_client* self = rfbClientGetClientData(client, NULL);
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
return self->alloc_fb(self) < 0 ? FALSE : TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vnc_client_update_box(rfbClient* client, int x, int y, int width,
|
||||||
|
int height)
|
||||||
|
{
|
||||||
|
struct vnc_client* self = rfbClientGetClientData(client, NULL);
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
pixman_region_union_rect(&self->damage, &self->damage, x, y, width,
|
||||||
|
height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vnc_client_finish_update(rfbClient* client)
|
||||||
|
{
|
||||||
|
struct vnc_client* self = rfbClientGetClientData(client, NULL);
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
self->update_fb(self);
|
||||||
|
|
||||||
|
pixman_region_clear(&self->damage);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct vnc_client* vnc_client_create(void)
|
||||||
|
{
|
||||||
|
struct vnc_client* self = calloc(1, sizeof(*self));
|
||||||
|
if (!self)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* These are defaults that can be changed with
|
||||||
|
* vnc_client_set_pixel_format().
|
||||||
|
*/
|
||||||
|
int bits_per_sample = 8;
|
||||||
|
int samples_per_pixel = 3;
|
||||||
|
int bytes_per_pixel = 4;
|
||||||
|
|
||||||
|
rfbClient* client = rfbGetClient(bits_per_sample, samples_per_pixel,
|
||||||
|
bytes_per_pixel);
|
||||||
|
if (!client)
|
||||||
|
goto failure;
|
||||||
|
|
||||||
|
self->client = client;
|
||||||
|
rfbClientSetClientData(client, NULL, self);
|
||||||
|
|
||||||
|
client->MallocFrameBuffer = vnc_client_alloc_fb;
|
||||||
|
client->GotFrameBufferUpdate = vnc_client_update_box;
|
||||||
|
client->FinishedFrameBufferUpdate = vnc_client_finish_update;
|
||||||
|
|
||||||
|
return self;
|
||||||
|
|
||||||
|
failure:
|
||||||
|
free(self);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vnc_client_destroy(struct vnc_client* self)
|
||||||
|
{
|
||||||
|
rfbClientCleanup(self->client);
|
||||||
|
free(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vnc_client_connect(struct vnc_client* self, const char* address, int port)
|
||||||
|
{
|
||||||
|
rfbClient* client = self->client;
|
||||||
|
|
||||||
|
if (!ConnectToRFBServer(client, address, port))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!InitialiseRFBConnection(client))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
client->width = client->si.framebufferWidth;
|
||||||
|
client->height = client->si.framebufferHeight;
|
||||||
|
|
||||||
|
if (!client->MallocFrameBuffer(client))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!SetFormatAndEncodings(client))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (client->updateRect.x < 0) {
|
||||||
|
client->updateRect.x = client->updateRect.y = 0;
|
||||||
|
client->updateRect.w = client->width;
|
||||||
|
client->updateRect.h = client->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SendFramebufferUpdateRequest(client,
|
||||||
|
client->updateRect.x, client->updateRect.y,
|
||||||
|
client->updateRect.w, client->updateRect.h,
|
||||||
|
FALSE))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vnc_client_set_pixel_format(struct vnc_client* self,
|
||||||
|
enum wl_shm_format format)
|
||||||
|
{
|
||||||
|
rfbPixelFormat* dst = &self->client->format;
|
||||||
|
int bpp = -1;
|
||||||
|
|
||||||
|
switch (format) {
|
||||||
|
case WL_SHM_FORMAT_ARGB8888:
|
||||||
|
case WL_SHM_FORMAT_XRGB8888:
|
||||||
|
dst->redShift = 16;
|
||||||
|
dst->greenShift = 8;
|
||||||
|
dst->blueShift = 0;
|
||||||
|
bpp = 32;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (bpp) {
|
||||||
|
case 32:
|
||||||
|
dst->bitsPerPixel = 32;
|
||||||
|
dst->depth = 24;
|
||||||
|
dst->redMax = 0xff;
|
||||||
|
dst->greenMax = 0xff;
|
||||||
|
dst->blueMax = 0xff;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
dst->trueColour = 1;
|
||||||
|
dst->bigEndian = FALSE;
|
||||||
|
self->client->appData.requestedDepth = dst->depth;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vnc_client_get_width(const struct vnc_client* self)
|
||||||
|
{
|
||||||
|
return self->client->width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vnc_client_get_height(const struct vnc_client* self)
|
||||||
|
{
|
||||||
|
return self->client->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vnc_client_get_stride(const struct vnc_client* self)
|
||||||
|
{
|
||||||
|
// TODO: What happens if bitsPerPixel == 24?
|
||||||
|
return self->client->width * self->client->format.bitsPerPixel / 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* vnc_client_get_fb(const struct vnc_client* self)
|
||||||
|
{
|
||||||
|
return self->client->frameBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vnc_client_set_fb(struct vnc_client* self, void* fb)
|
||||||
|
{
|
||||||
|
self->client->frameBuffer = fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vnc_client_get_fd(const struct vnc_client* self)
|
||||||
|
{
|
||||||
|
return self->client->sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* vnc_client_get_desktop_name(const struct vnc_client* self)
|
||||||
|
{
|
||||||
|
return self->client->desktopName;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vnc_client_process(struct vnc_client* self)
|
||||||
|
{
|
||||||
|
return HandleRFBServerMessage(self->client) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vnc_client_send_pointer_event(struct vnc_client* self, int x, int y,
|
||||||
|
uint32_t button_mask)
|
||||||
|
{
|
||||||
|
SendPointerEvent(self->client, x, y, button_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vnc_client_send_keyboard_event(struct vnc_client* self, uint32_t symbol,
|
||||||
|
bool is_pressed)
|
||||||
|
{
|
||||||
|
SendKeyEvent(self->client, symbol, is_pressed);
|
||||||
|
}
|
Loading…
Reference in New Issue