From patchwork Wed May 5 12:51:44 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 51724 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 0B908B7D4F for ; Thu, 6 May 2010 04:51:24 +1000 (EST) Received: from localhost ([127.0.0.1]:48210 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O9jgm-0000cp-V2 for incoming@patchwork.ozlabs.org; Wed, 05 May 2010 14:51:20 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O9e51-0001ye-Ba for qemu-devel@nongnu.org; Wed, 05 May 2010 08:51:59 -0400 Received: from [140.186.70.92] (port=41370 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O9e4z-0001vB-AK for qemu-devel@nongnu.org; Wed, 05 May 2010 08:51:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O9e4t-0004Iq-9Y for qemu-devel@nongnu.org; Wed, 05 May 2010 08:51:56 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53122) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O9e4s-0004Ia-Uw for qemu-devel@nongnu.org; Wed, 05 May 2010 08:51:51 -0400 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o45CpnXL001699 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 5 May 2010 08:51:50 -0400 Received: from zweiblum.home.kraxel.org (vpn2-10-127.ams2.redhat.com [10.36.10.127]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o45Cpj2a023438; Wed, 5 May 2010 08:51:46 -0400 Received: by zweiblum.home.kraxel.org (Postfix, from userid 500) id 124547011F; Wed, 5 May 2010 14:51:44 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Wed, 5 May 2010 14:51:44 +0200 Message-Id: <1273063904-6028-4-git-send-email-kraxel@redhat.com> In-Reply-To: <1273063904-6028-1-git-send-email-kraxel@redhat.com> References: <1273063904-6028-1-git-send-email-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. Cc: Gerd Hoffmann Subject: [Qemu-devel] [PATCH 3/3] vnc: rich cursor support. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- 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); } }