Implement client side cursor rendering
parent
258dccd768
commit
48baf74560
|
@ -89,6 +89,7 @@ struct nvnc_client {
|
||||||
struct cut_text cut_text;
|
struct cut_text cut_text;
|
||||||
bool is_qemu_key_ext_notified;
|
bool is_qemu_key_ext_notified;
|
||||||
struct encoder* encoder;
|
struct encoder* encoder;
|
||||||
|
uint32_t cursor_seq;
|
||||||
};
|
};
|
||||||
|
|
||||||
LIST_HEAD(nvnc_client_list, nvnc_client);
|
LIST_HEAD(nvnc_client_list, nvnc_client);
|
||||||
|
@ -107,6 +108,11 @@ struct nvnc {
|
||||||
nvnc_client_fn new_client_fn;
|
nvnc_client_fn new_client_fn;
|
||||||
nvnc_cut_text_fn cut_text_fn;
|
nvnc_cut_text_fn cut_text_fn;
|
||||||
struct nvnc_display* display;
|
struct nvnc_display* display;
|
||||||
|
struct {
|
||||||
|
struct nvnc_fb* buffer;
|
||||||
|
uint32_t x_hotspot, y_hotspot;
|
||||||
|
} cursor;
|
||||||
|
uint32_t cursor_seq;
|
||||||
|
|
||||||
#ifdef ENABLE_TLS
|
#ifdef ENABLE_TLS
|
||||||
gnutls_certificate_credentials_t tls_creds;
|
gnutls_certificate_credentials_t tls_creds;
|
||||||
|
|
|
@ -141,3 +141,6 @@ void nvnc_display_feed_buffer(struct nvnc_display*, struct nvnc_fb*,
|
||||||
struct pixman_region16* damage);
|
struct pixman_region16* damage);
|
||||||
|
|
||||||
void nvnc_send_cut_text(struct nvnc*, const char* text, uint32_t len);
|
void nvnc_send_cut_text(struct nvnc*, const char* text, uint32_t len);
|
||||||
|
|
||||||
|
void nvnc_set_cursor(struct nvnc*, struct nvnc_fb*, uint16_t x_hotspot,
|
||||||
|
uint16_t y_hotspot, struct pixman_region16* damage);
|
||||||
|
|
|
@ -83,6 +83,7 @@ sources = [
|
||||||
'src/damage-refinery.c',
|
'src/damage-refinery.c',
|
||||||
'src/murmurhash.c',
|
'src/murmurhash.c',
|
||||||
'src/encoder.c',
|
'src/encoder.c',
|
||||||
|
'src/cursor.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|
81
src/server.c
81
src/server.c
|
@ -29,6 +29,7 @@
|
||||||
#include "encoder.h"
|
#include "encoder.h"
|
||||||
#include "tight.h"
|
#include "tight.h"
|
||||||
#include "enc-util.h"
|
#include "enc-util.h"
|
||||||
|
#include "cursor.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -518,6 +519,39 @@ static void on_encoder_push_done(struct encoder* encoder, struct rcbuf* payload)
|
||||||
process_fb_update_requests(client);
|
process_fb_update_requests(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void send_cursor_update(struct nvnc_client* client)
|
||||||
|
{
|
||||||
|
struct nvnc* server = client->server;
|
||||||
|
|
||||||
|
if (!server->cursor.buffer) {
|
||||||
|
// TODO: Empty buffer means that no cursor should be visible
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct vec payload;
|
||||||
|
vec_init(&payload, 4096);
|
||||||
|
|
||||||
|
struct rfb_server_fb_update_msg head = {
|
||||||
|
.type = RFB_SERVER_TO_CLIENT_FRAMEBUFFER_UPDATE,
|
||||||
|
.n_rects = htons(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
vec_append(&payload, &head, sizeof(head));
|
||||||
|
|
||||||
|
int rc = cursor_encode(&payload, &client->pixfmt, server->cursor.buffer,
|
||||||
|
server->cursor.x_hotspot, server->cursor.y_hotspot);
|
||||||
|
if (rc < 0) {
|
||||||
|
log_error("Failed to send cursor to client\n");
|
||||||
|
vec_destroy(&payload);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
client->cursor_seq = server->cursor_seq;
|
||||||
|
|
||||||
|
stream_send(client->net_stream, rcbuf_new(payload.data, payload.len),
|
||||||
|
NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void process_fb_update_requests(struct nvnc_client* client)
|
static void process_fb_update_requests(struct nvnc_client* client)
|
||||||
{
|
{
|
||||||
struct nvnc* server = client->server;
|
struct nvnc* server = client->server;
|
||||||
|
@ -528,9 +562,6 @@ static void process_fb_update_requests(struct nvnc_client* client)
|
||||||
if (client->net_stream->state == STREAM_STATE_CLOSED)
|
if (client->net_stream->state == STREAM_STATE_CLOSED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!pixman_region_not_empty(&client->damage))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (client->is_updating || client->n_pending_requests == 0)
|
if (client->is_updating || client->n_pending_requests == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -559,6 +590,17 @@ static void process_fb_update_requests(struct nvnc_client* client)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (server->cursor_seq != client->cursor_seq
|
||||||
|
&& client_has_encoding(client, RFB_ENCODING_CURSOR)) {
|
||||||
|
send_cursor_update(client);
|
||||||
|
|
||||||
|
if (--client->n_pending_requests <= 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pixman_region_not_empty(&client->damage))
|
||||||
|
return;
|
||||||
|
|
||||||
DTRACE_PROBE1(neatvnc, update_fb_start, client);
|
DTRACE_PROBE1(neatvnc, update_fb_start, client);
|
||||||
|
|
||||||
enum rfb_encodings encoding = choose_frame_encoding(client, fb);
|
enum rfb_encodings encoding = choose_frame_encoding(client, fb);
|
||||||
|
@ -1533,3 +1575,36 @@ cert_alloc_failure:
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPORT
|
||||||
|
void nvnc_set_cursor(struct nvnc* self, struct nvnc_fb* fb, uint16_t x_hotspot,
|
||||||
|
uint16_t y_hotspot, struct pixman_region16* damage)
|
||||||
|
{
|
||||||
|
if (self->cursor.buffer) {
|
||||||
|
nvnc_fb_release(self->cursor.buffer);
|
||||||
|
nvnc_fb_unref(self->cursor.buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
self->cursor.buffer = fb;
|
||||||
|
if (!fb) {
|
||||||
|
self->cursor.x_hotspot = 0;
|
||||||
|
self->cursor.y_hotspot = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nvnc_fb_ref(fb);
|
||||||
|
nvnc_fb_hold(fb);
|
||||||
|
|
||||||
|
self->cursor.x_hotspot = x_hotspot;
|
||||||
|
self->cursor.y_hotspot = y_hotspot;
|
||||||
|
|
||||||
|
if (!damage || pixman_region_not_empty(damage)) {
|
||||||
|
// TODO: Hash cursors to check if they actually changed
|
||||||
|
|
||||||
|
self->cursor_seq++;
|
||||||
|
|
||||||
|
struct nvnc_client* client;
|
||||||
|
LIST_FOREACH(client, &self->clients, link)
|
||||||
|
process_fb_update_requests(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue