[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 3/3] vnc: rich cursor support.
From: |
Gerd Hoffmann |
Subject: |
[Qemu-devel] [PATCH 3/3] vnc: rich cursor support. |
Date: |
Wed, 5 May 2010 14:51:44 +0200 |
Uses VNC_ENCODING_RICH_CURSOR. Adding XCURSOR support should be
possible without much trouble. Shouldn't be needed though as
RICH_CURSOR is a superset of XCURSOR.
Signed-off-by: Gerd Hoffmann <address@hidden>
---
vnc.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++-------
vnc.h | 8 ++++++-
vnchextile.h | 7 +++--
3 files changed, 70 insertions(+), 12 deletions(-)
diff --git a/vnc.c b/vnc.c
index b1a3fdb..b97eae7 100644
--- a/vnc.c
+++ b/vnc.c
@@ -554,7 +554,8 @@ static void vnc_dpy_resize(DisplayState *ds)
}
/* fastest code */
-static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size)
+static void vnc_write_pixels_copy(VncState *vs, struct PixelFormat *pf,
+ void *pixels, int size)
{
vnc_write(vs, pixels, size);
}
@@ -604,12 +605,12 @@ void vnc_convert_pixel(VncState *vs, uint8_t *buf,
uint32_t v)
}
}
-static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
+static void vnc_write_pixels_generic(VncState *vs, struct PixelFormat *pf,
+ void *pixels1, int size)
{
uint8_t buf[4];
- VncDisplay *vd = vs->vd;
- if (vd->server->pf.bytes_per_pixel == 4) {
+ if (pf->bytes_per_pixel == 4) {
uint32_t *pixels = pixels1;
int n, i;
n = size >> 2;
@@ -617,7 +618,7 @@ static void vnc_write_pixels_generic(VncState *vs, void
*pixels1, int size)
vnc_convert_pixel(vs, buf, pixels[i]);
vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel);
}
- } else if (vd->server->pf.bytes_per_pixel == 2) {
+ } else if (pf->bytes_per_pixel == 2) {
uint16_t *pixels = pixels1;
int n, i;
n = size >> 1;
@@ -625,7 +626,7 @@ static void vnc_write_pixels_generic(VncState *vs, void
*pixels1, int size)
vnc_convert_pixel(vs, buf, pixels[i]);
vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel);
}
- } else if (vd->server->pf.bytes_per_pixel == 1) {
+ } else if (pf->bytes_per_pixel == 1) {
uint8_t *pixels = pixels1;
int n, i;
n = size;
@@ -646,7 +647,7 @@ void vnc_raw_send_framebuffer_update(VncState *vs, int x,
int y, int w, int h)
row = vd->server->data + y * ds_get_linesize(vs->ds) + x *
ds_get_bytes_per_pixel(vs->ds);
for (i = 0; i < h; i++) {
- vs->write_pixels(vs, row, w * ds_get_bytes_per_pixel(vs->ds));
+ vs->write_pixels(vs, &vd->server->pf, row, w *
ds_get_bytes_per_pixel(vs->ds));
row += ds_get_linesize(vs->ds);
}
}
@@ -752,6 +753,50 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int
src_y, int dst_x, int
}
}
+static void vnc_mouse_set(int x, int y, int visible)
+{
+ /* can we ask the client(s) to move the pointer ??? */
+}
+
+static int vnc_cursor_define(VncState *vs)
+{
+ QEMUCursor *c = vs->vd->cursor;
+ PixelFormat pf = qemu_default_pixelformat(32);
+ int isize;
+
+ if (vnc_has_feature(vs, VNC_FEATURE_RICH_CURSOR)) {
+ vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
+ vnc_write_u8(vs, 0); /* padding */
+ vnc_write_u16(vs, 1); /* # of rects */
+ vnc_framebuffer_update(vs, c->hot_x, c->hot_y, c->width, c->height,
+ VNC_ENCODING_RICH_CURSOR);
+ isize = c->width * c->height * vs->clientds.pf.bytes_per_pixel;
+ vnc_write_pixels_generic(vs, &pf, c->data, isize);
+ vnc_write(vs, vs->vd->cursor_mask, vs->vd->cursor_msize);
+ return 0;
+ }
+ return -1;
+}
+
+static void vnc_dpy_cursor_define(QEMUCursor *c)
+{
+ VncDisplay *vd = vnc_display;
+ VncState *vs;
+
+ cursor_put(vd->cursor);
+ qemu_free(vd->cursor_mask);
+
+ vd->cursor = c;
+ cursor_get(vd->cursor);
+ vd->cursor_msize = cursor_get_mono_bpl(c) * c->height;
+ vd->cursor_mask = qemu_mallocz(vd->cursor_msize);
+ cursor_get_mono_mask(c, 0, vd->cursor_mask);
+
+ QTAILQ_FOREACH(vs, &vd->clients, next) {
+ vnc_cursor_define(vs);
+ }
+}
+
static int find_and_clear_dirty_height(struct VncState *vs,
int y, int last_x, int x)
{
@@ -1622,6 +1667,9 @@ static void set_encodings(VncState *vs, int32_t
*encodings, size_t n_encodings)
case VNC_ENCODING_POINTER_TYPE_CHANGE:
vs->features |= VNC_FEATURE_POINTER_TYPE_CHANGE_MASK;
break;
+ case VNC_ENCODING_RICH_CURSOR:
+ vs->features |= VNC_FEATURE_RICH_CURSOR_MASK;
+ break;
case VNC_ENCODING_EXT_KEY_EVENT:
send_ext_key_event_ack(vs);
break;
@@ -1642,8 +1690,9 @@ static void set_encodings(VncState *vs, int32_t
*encodings, size_t n_encodings)
break;
}
}
-
check_pointer_type_change(&vs->mouse_mode_notifier);
+ if (vs->vd->cursor)
+ vnc_cursor_define(vs);
}
static void set_pixel_conversion(VncState *vs)
@@ -2288,6 +2337,8 @@ void vnc_display_init(DisplayState *ds)
dcl->dpy_resize = vnc_dpy_resize;
dcl->dpy_setdata = vnc_dpy_setdata;
register_displaychangelistener(ds, dcl);
+ ds->mouse_set = vnc_mouse_set;
+ ds->cursor_define = vnc_dpy_cursor_define;
}
diff --git a/vnc.h b/vnc.h
index 1aa71b0..0d39897 100644
--- a/vnc.h
+++ b/vnc.h
@@ -61,7 +61,7 @@ typedef struct VncState VncState;
typedef int VncReadEvent(VncState *vs, uint8_t *data, size_t len);
-typedef void VncWritePixels(VncState *vs, void *data, int size);
+typedef void VncWritePixels(VncState *vs, struct PixelFormat *pf, void *data,
int size);
typedef void VncSendHextileTile(VncState *vs,
int x, int y, int w, int h,
@@ -101,6 +101,10 @@ struct VncDisplay
kbd_layout_t *kbd_layout;
int lock_key_sync;
+ QEMUCursor *cursor;
+ int cursor_msize;
+ uint8_t *cursor_mask;
+
struct VncSurface guest; /* guest visible surface (aka ds->surface) */
DisplaySurface *server; /* vnc server surface */
@@ -273,6 +277,7 @@ enum {
#define VNC_FEATURE_TIGHT 4
#define VNC_FEATURE_ZLIB 5
#define VNC_FEATURE_COPYRECT 6
+#define VNC_FEATURE_RICH_CURSOR 7
#define VNC_FEATURE_RESIZE_MASK (1 << VNC_FEATURE_RESIZE)
#define VNC_FEATURE_HEXTILE_MASK (1 << VNC_FEATURE_HEXTILE)
@@ -281,6 +286,7 @@ enum {
#define VNC_FEATURE_TIGHT_MASK (1 << VNC_FEATURE_TIGHT)
#define VNC_FEATURE_ZLIB_MASK (1 << VNC_FEATURE_ZLIB)
#define VNC_FEATURE_COPYRECT_MASK (1 << VNC_FEATURE_COPYRECT)
+#define VNC_FEATURE_RICH_CURSOR_MASK (1 << VNC_FEATURE_RICH_CURSOR)
/* Client -> Server message IDs */
diff --git a/vnchextile.h b/vnchextile.h
index 78ed8c4..b9f9f5e 100644
--- a/vnchextile.h
+++ b/vnchextile.h
@@ -189,16 +189,17 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
vnc_write_u8(vs, flags);
if (n_colors < 4) {
if (flags & 0x02)
- vs->write_pixels(vs, last_bg, sizeof(pixel_t));
+ vs->write_pixels(vs, &vd->server->pf, last_bg, sizeof(pixel_t));
if (flags & 0x04)
- vs->write_pixels(vs, last_fg, sizeof(pixel_t));
+ vs->write_pixels(vs, &vd->server->pf, last_fg, sizeof(pixel_t));
if (n_subtiles) {
vnc_write_u8(vs, n_subtiles);
vnc_write(vs, data, n_data);
}
} else {
for (j = 0; j < h; j++) {
- vs->write_pixels(vs, row, w * ds_get_bytes_per_pixel(vs->ds));
+ vs->write_pixels(vs, &vd->server->pf, row,
+ w * ds_get_bytes_per_pixel(vs->ds));
row += ds_get_linesize(vs->ds);
}
}
--
1.6.6.1
- [Qemu-devel] [PATCH 0/3] local cursor patches., Gerd Hoffmann, 2010/05/05
- [Qemu-devel] [PATCH 2/3] use new cursor struct + functions for vmware vga and sdl., Gerd Hoffmann, 2010/05/05
- [Qemu-devel] [PATCH 3/3] vnc: rich cursor support.,
Gerd Hoffmann <=
- [Qemu-devel] [PATCH 1/3] cursor: add cursor functions., Gerd Hoffmann, 2010/05/05
- Re: [Qemu-devel] [PATCH 1/3] cursor: add cursor functions., Blue Swirl, 2010/05/06
- [Qemu-devel] Re: [PATCH 1/3] cursor: add cursor functions., Paolo Bonzini, 2010/05/07
- [Qemu-devel] Re: [PATCH 1/3] cursor: add cursor functions., Blue Swirl, 2010/05/07
- [Qemu-devel] Re: [PATCH 1/3] cursor: add cursor functions., Gerd Hoffmann, 2010/05/19
- [Qemu-devel] Re: [PATCH 1/3] cursor: add cursor functions., Blue Swirl, 2010/05/19
- Re: [Qemu-devel] Re: [PATCH 1/3] cursor: add cursor functions., Anthony Liguori, 2010/05/19
- Re: [Qemu-devel] Re: [PATCH 1/3] cursor: add cursor functions., Gerd Hoffmann, 2010/05/20