Implement server-side resizing

pull/42/head
Andri Yngvason 2020-07-19 11:54:39 +00:00
parent eb4b9d71a4
commit a0801f04e4
2 changed files with 51 additions and 0 deletions

View File

@ -78,6 +78,8 @@ struct nvnc_client {
size_t buffer_index; size_t buffer_index;
size_t buffer_len; size_t buffer_len;
uint8_t msg_buffer[MSG_BUFFER_SIZE]; uint8_t msg_buffer[MSG_BUFFER_SIZE];
uint32_t known_width;
uint32_t known_height;
}; };
LIST_HEAD(nvnc_client_list, nvnc_client); LIST_HEAD(nvnc_client_list, nvnc_client);

View File

@ -384,6 +384,8 @@ static void send_server_init_message(struct nvnc_client* client)
struct rcbuf* payload = rcbuf_new(msg, size); struct rcbuf* payload = rcbuf_new(msg, size);
stream_send(client->net_stream, payload, NULL, NULL); stream_send(client->net_stream, payload, NULL, NULL);
client->known_width = width;
client->known_height = height;
return; return;
pixfmt_failure: pixfmt_failure:
@ -963,6 +965,16 @@ static enum tight_quality client_get_tight_quality(struct nvnc_client* client)
return TIGHT_QUALITY_LOSSLESS; return TIGHT_QUALITY_LOSSLESS;
} }
static bool client_has_encoding(const struct nvnc_client* client,
enum rfb_encodings encoding)
{
for (size_t i = 0; i < client->n_encodings; ++i)
if (client->encodings[i] == encoding)
return true;
return false;
}
static void do_client_update_fb(void* work) static void do_client_update_fb(void* work)
{ {
struct fb_update_work* update = aml_get_userdata(work); struct fb_update_work* update = aml_get_userdata(work);
@ -1028,6 +1040,37 @@ static void on_client_update_fb_done(void* work)
client_unref(client); client_unref(client);
} }
static int send_desktop_resize(struct nvnc_client* client, struct nvnc_fb* fb)
{
if (!client_has_encoding(client, RFB_ENCODING_DESKTOPSIZE)) {
log_error("Client does not support desktop resizing. Closing connection...\n");
stream_close(client->net_stream);
client_unref(client);
return -1;
}
client->known_width = fb->width;
client->known_height = fb->height;
pixman_region_union_rect(&client->damage, &client->damage, 0, 0,
fb->width, fb->height);
struct rfb_server_fb_update_msg head = {
.type = RFB_SERVER_TO_CLIENT_FRAMEBUFFER_UPDATE,
.n_rects = htons(1),
};
struct rfb_server_fb_rect rect = {
.encoding = htonl(RFB_ENCODING_DESKTOPSIZE),
.width = htons(fb->width),
.height = htons(fb->height),
};
stream_write(client->net_stream, &head, sizeof(head), NULL, NULL);
stream_write(client->net_stream, &rect, sizeof(rect), NULL, NULL);
return 0;
}
int schedule_client_update_fb(struct nvnc_client* client) int schedule_client_update_fb(struct nvnc_client* client)
{ {
struct nvnc_fb* fb = client->server->display->buffer; struct nvnc_fb* fb = client->server->display->buffer;
@ -1045,6 +1088,11 @@ int schedule_client_update_fb(struct nvnc_client* client)
work->client = client; work->client = client;
work->fb = fb; work->fb = fb;
if (fb->width != client->known_width
|| fb->height != client->known_height)
if (send_desktop_resize(client, fb) < 0)
goto resize_failure;
/* The client's damage is exchanged for an empty one */ /* The client's damage is exchanged for an empty one */
work->region = client->damage; work->region = client->damage;
pixman_region_init(&client->damage); pixman_region_init(&client->damage);
@ -1080,6 +1128,7 @@ oom_failure:
vec_destroy(&work->frame); vec_destroy(&work->frame);
vec_failure: vec_failure:
pixfmt_failure: pixfmt_failure:
resize_failure:
free(work); free(work);
return -1; return -1;
} }