int depth; /* internal VNC frame buffer byte per pixel */
int has_resize;
int has_hextile;
+ int has_pointer_type_change;
+ int absolute;
+ int last_x;
+ int last_y;
+
+ const char *display;
+
Buffer output;
Buffer input;
kbd_layout_t *kbd_layout;
uint8_t modifiers_state[256];
};
+static VncState *vnc_state; /* needed for info vnc */
+
+void do_info_vnc(void)
+{
+ if (vnc_state == NULL)
+ term_printf("VNC server disabled\n");
+ else {
+ term_printf("VNC server active on: ");
+ term_print_filename(vnc_state->display);
+ term_printf("\n");
+
+ if (vnc_state->csock == -1)
+ term_printf("No client connected\n");
+ else
+ term_printf("Client connected\n");
+ }
+}
+
/* TODO
1) Get the queue working for IO.
2) there is some weirdness when using the -S option (the screen is grey
{
}
+static void check_pointer_type_change(VncState *vs, int absolute)
+{
+ if (vs->has_pointer_type_change && vs->absolute != absolute) {
+ vnc_write_u8(vs, 0);
+ vnc_write_u8(vs, 0);
+ vnc_write_u16(vs, 1);
+ vnc_framebuffer_update(vs, absolute, 0,
+ vs->ds->width, vs->ds->height, -257);
+ vnc_flush(vs);
+ }
+ vs->absolute = absolute;
+}
+
static void pointer_event(VncState *vs, int button_mask, int x, int y)
{
int buttons = 0;
dz = -1;
if (button_mask & 0x10)
dz = 1;
-
- if (kbd_mouse_is_absolute()) {
+
+ if (vs->absolute) {
kbd_mouse_event(x * 0x7FFF / vs->ds->width,
y * 0x7FFF / vs->ds->height,
dz, buttons);
- } else {
- static int last_x = -1;
- static int last_y = -1;
-
- if (last_x != -1)
- kbd_mouse_event(x - last_x, y - last_y, dz, buttons);
+ } else if (vs->has_pointer_type_change) {
+ x -= 0x7FFF;
+ y -= 0x7FFF;
- last_x = x;
- last_y = y;
+ kbd_mouse_event(x, y, dz, buttons);
+ } else {
+ if (vs->last_x != -1)
+ kbd_mouse_event(x - vs->last_x,
+ y - vs->last_y,
+ dz, buttons);
+ vs->last_x = x;
+ vs->last_y = y;
}
+
+ check_pointer_type_change(vs, kbd_mouse_is_absolute());
}
static void reset_keys(VncState *vs)
int x_position, int y_position,
int w, int h)
{
+ if (x_position > vs->ds->width)
+ x_position = vs->ds->width;
+ if (y_position > vs->ds->height)
+ y_position = vs->ds->height;
+ if (x_position + w >= vs->ds->width)
+ w = vs->ds->width - x_position;
+ if (y_position + h >= vs->ds->height)
+ h = vs->ds->height - y_position;
+
int i;
vs->need_update = 1;
if (!incremental) {
vs->has_hextile = 0;
vs->has_resize = 0;
+ vs->has_pointer_type_change = 0;
+ vs->absolute = -1;
vs->ds->dpy_copy = NULL;
for (i = n_encodings - 1; i >= 0; i--) {
case -223: /* DesktopResize */
vs->has_resize = 1;
break;
+ case -257:
+ vs->has_pointer_type_change = 1;
+ break;
default:
break;
}
}
+
+ check_pointer_type_change(vs, kbd_mouse_is_absolute());
}
static int compute_nbits(unsigned int val)
static int protocol_client_init(VncState *vs, char *data, size_t len)
{
char pad[3] = { 0, 0, 0 };
+ char buf[1024];
+ int size;
vs->width = vs->ds->width;
vs->height = vs->ds->height;
vnc_write(vs, pad, 3); /* padding */
- vnc_write_u32(vs, 4);
- vnc_write(vs, "QEMU", 4);
+ if (qemu_name)
+ size = snprintf(buf, sizeof(buf), "QEMU (%s)", qemu_name);
+ else
+ size = snprintf(buf, sizeof(buf), "QEMU");
+
+ vnc_write_u32(vs, size);
+ vnc_write(vs, buf, size);
vnc_flush(vs);
vnc_read_when(vs, protocol_client_msg, 1);
}
}
-void vnc_display_init(DisplayState *ds, int display)
+extern int parse_host_port(struct sockaddr_in *saddr, const char *str);
+
+void vnc_display_init(DisplayState *ds, const char *arg)
{
- struct sockaddr_in addr;
+ struct sockaddr *addr;
+ struct sockaddr_in iaddr;
+#ifndef _WIN32
+ struct sockaddr_un uaddr;
+#endif
int reuse_addr, ret;
+ socklen_t addrlen;
+ const char *p;
VncState *vs;
vs = qemu_mallocz(sizeof(VncState));
exit(1);
ds->opaque = vs;
+ vnc_state = vs;
+ vs->display = arg;
vs->lsock = -1;
vs->csock = -1;
vs->depth = 4;
+ vs->last_x = -1;
+ vs->last_y = -1;
vs->ds = ds;
if (!vs->kbd_layout)
exit(1);
- vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
- if (vs->lsock == -1) {
- fprintf(stderr, "Could not create socket\n");
- exit(1);
- }
+ vs->ds->data = NULL;
+ vs->ds->dpy_update = vnc_dpy_update;
+ vs->ds->dpy_resize = vnc_dpy_resize;
+ vs->ds->dpy_refresh = vnc_dpy_refresh;
- addr.sin_family = AF_INET;
- addr.sin_port = htons(5900 + display);
- memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
+ memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
- reuse_addr = 1;
- ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
- (const char *)&reuse_addr, sizeof(reuse_addr));
- if (ret == -1) {
- fprintf(stderr, "setsockopt() failed\n");
- exit(1);
+ vnc_dpy_resize(vs->ds, 640, 400);
+
+#ifndef _WIN32
+ if (strstart(arg, "unix:", &p)) {
+ addr = (struct sockaddr *)&uaddr;
+ addrlen = sizeof(uaddr);
+
+ vs->lsock = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (vs->lsock == -1) {
+ fprintf(stderr, "Could not create socket\n");
+ exit(1);
+ }
+
+ uaddr.sun_family = AF_UNIX;
+ memset(uaddr.sun_path, 0, 108);
+ snprintf(uaddr.sun_path, 108, "%s", p);
+
+ unlink(uaddr.sun_path);
+ } else
+#endif
+ {
+ addr = (struct sockaddr *)&iaddr;
+ addrlen = sizeof(iaddr);
+
+ vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
+ if (vs->lsock == -1) {
+ fprintf(stderr, "Could not create socket\n");
+ exit(1);
+ }
+
+ if (parse_host_port(&iaddr, arg) < 0) {
+ fprintf(stderr, "Could not parse VNC address\n");
+ exit(1);
+ }
+
+ iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900);
+
+ reuse_addr = 1;
+ ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
+ (const char *)&reuse_addr, sizeof(reuse_addr));
+ if (ret == -1) {
+ fprintf(stderr, "setsockopt() failed\n");
+ exit(1);
+ }
}
- if (bind(vs->lsock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+ if (bind(vs->lsock, addr, addrlen) == -1) {
fprintf(stderr, "bind() failed\n");
exit(1);
}
if (ret == -1) {
exit(1);
}
-
- vs->ds->data = NULL;
- vs->ds->dpy_update = vnc_dpy_update;
- vs->ds->dpy_resize = vnc_dpy_resize;
- vs->ds->dpy_refresh = vnc_dpy_refresh;
-
- memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
-
- vnc_dpy_resize(vs->ds, 640, 400);
}