diff --git a/include/common.h b/include/common.h index c7ed237..91b0ee7 100644 --- a/include/common.h +++ b/include/common.h @@ -101,6 +101,7 @@ struct nvnc { char name[256]; void* userdata; nvnc_key_fn key_fn; + nvnc_key_fn key_code_fn; nvnc_pointer_fn pointer_fn; nvnc_fb_req_fn fb_req_fn; nvnc_client_fn new_client_fn; diff --git a/include/neatvnc.h b/include/neatvnc.h index 763de0e..7a414b9 100644 --- a/include/neatvnc.h +++ b/include/neatvnc.h @@ -37,7 +37,7 @@ enum nvnc_fb_flags { NVNC_FB_PARTIAL = 1 << 0, // The buffer contains only the damaged region }; -typedef void (*nvnc_key_fn)(struct nvnc_client*, uint32_t keysym, +typedef void (*nvnc_key_fn)(struct nvnc_client*, uint32_t key, bool is_pressed); typedef void (*nvnc_pointer_fn)(struct nvnc_client*, uint16_t x, uint16_t y, enum nvnc_button_mask); @@ -67,6 +67,7 @@ struct nvnc* nvnc_client_get_server(const struct nvnc_client* client); void nvnc_set_name(struct nvnc* self, const char* name); void nvnc_set_key_fn(struct nvnc* self, nvnc_key_fn); +void nvnc_set_key_code_fn(struct nvnc* self, nvnc_key_fn); void nvnc_set_pointer_fn(struct nvnc* self, nvnc_pointer_fn); void nvnc_set_fb_req_fn(struct nvnc* self, nvnc_fb_req_fn); void nvnc_set_new_client_fn(struct nvnc* self, nvnc_client_fn); diff --git a/src/server.c b/src/server.c index 1072461..b1a599c 100644 --- a/src/server.c +++ b/src/server.c @@ -484,6 +484,7 @@ static int on_client_set_encodings(struct nvnc_client* client) case RFB_ENCODING_DESKTOPSIZE: case RFB_ENCODING_JPEG_HIGHQ: case RFB_ENCODING_JPEG_LOWQ: + case RFB_ENCODING_QEMU_EXT_KEY_EVENT: client->encodings[n++] = encoding; } } @@ -619,6 +620,47 @@ static int on_client_key_event(struct nvnc_client* client) return sizeof(*msg); } +static int on_client_qemu_key_event(struct nvnc_client* client) +{ + struct nvnc* server = client->server; + + struct rfb_client_qemu_key_event_msg* msg = + (struct rfb_client_qemu_key_event_msg*)(client->msg_buffer + + client->buffer_index); + + if (client->buffer_len - client->buffer_index < sizeof(*msg)) + return 0; + + int down_flag = msg->down_flag; + uint32_t keycode = ntohl(msg->keycode); + + nvnc_key_fn fn = server->key_code_fn; + if (fn) + fn(client, keycode, !!down_flag); + + return sizeof(*msg); +} + +static int on_client_qemu_event(struct nvnc_client* client) +{ + if (client->buffer_len - client->buffer_index < 2) + return 0; + + enum rfb_client_to_server_qemu_msg_type subtype = + client->msg_buffer[client->buffer_index + 1]; + + switch (subtype) { + case RFB_CLIENT_TO_SERVER_QEMU_KEY_EVENT: + return on_client_qemu_key_event(client); + } + + log_debug("Got uninterpretable qemu message from client: %p (ref %d)\n", + client, client->ref); + stream_close(client->net_stream); + client_unref(client); + return 0; +} + static int on_client_pointer_event(struct nvnc_client* client) { struct nvnc* server = client->server; @@ -771,6 +813,8 @@ static int on_client_message(struct nvnc_client* client) return on_client_pointer_event(client); case RFB_CLIENT_TO_SERVER_CLIENT_CUT_TEXT: return on_client_cut_text(client); + case RFB_CLIENT_TO_SERVER_QEMU: + return on_client_qemu_event(client); } log_debug("Got uninterpretable message from client: %p (ref %d)\n", @@ -1322,6 +1366,12 @@ void nvnc_set_key_fn(struct nvnc* self, nvnc_key_fn fn) self->key_fn = fn; } +EXPORT +void nvnc_set_key_code_fn(struct nvnc* self, nvnc_key_fn fn) +{ + self->key_code_fn = fn; +} + EXPORT void nvnc_set_pointer_fn(struct nvnc* self, nvnc_pointer_fn fn) {