vnc: keyboard delay, colormap support

ui: misc bugfixes
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABAgAGBQJXUSuIAAoJEEy22O7T6HE4egUP/iVtfRVi95fqOMj4e7QDlO3K
 Xf7Yn36sHi9Ov4GF5EbCAfkJQQfYHJDFyN1XibuUfH5LSRR/Z1a4mFAiSTi1jbB/
 mMxFA/wbKJ1Qr+fbA3yDBdj+A0DM0YRkwvBmdtgmkhrc7nzH2AAKt5mcHaCJW7+u
 CkBiuBfSG2QvrNSYe3hhQ5TfuXnHfAVyxDRRkA12Vj28ismfGX+vvbIg3sKWvd98
 o01TrX1fBJOoGDWyA1mDei0HbZXqYMdU0ioBcxc+LwhNgr89TxTHgGnWZOYJiF43
 Y22uddpuxdXCET9GbyOGYl8Y28yJtihxhl2/rTyVMTHNL8WShxZv+KWL2riUc03Q
 hgC4D4PRhD0MdJ1ONNmYiN5ss0fxHCgymF2kQ6CZEo71qpn3wR6WTlsbaKbD/M8B
 1lEDlOYKm8e3ncCAJO75icyYnjUt2aCgPZY1XciW7RWVBm36TP+fAGEAktlGSvku
 hbBwlXa13DSLjyCmbif3eXPb+l4M5QP6+DG1tZPmRknTbsgWvzC74GwVqfQlKfvW
 zvIxZecXFGZO2burLcEYejq/+YRolpLxuWIyVtwmpSGtycNepFe0cmss/JiIrCbb
 KPCQl6dBZosRfbS8xlHhXBq4yVGqgnJ6QOBJ9HVxO3WNGSsS+miv2A/C6p/q/bSD
 g4L/YX5GD42jeSKrkXnM
 =qX3g
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/kraxel/tags/pull-ui-20160603-1' into staging

vnc: keyboard delay, colormap support
ui: misc bugfixes

# gpg: Signature made Fri 03 Jun 2016 08:02:32 BST using RSA key ID D3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>"
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>"
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>"

* remotes/kraxel/tags/pull-ui-20160603-1:
  vnc: add configurable keyboard delay
  sdl2: skip init without outputs
  vnc: Add support for color map
  SDL2: add bgrx pixel format
  gtk: fix unchecked vc dereference
  ui: spice: Exit if gl=on EGL init fails
  ui: egl: Replace fprintf with error_report

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2016-06-03 12:03:36 +01:00
commit 6b3532b20b
8 changed files with 77 additions and 20 deletions

View File

@ -1410,6 +1410,14 @@ everybody else. 'ignore' completely ignores the shared flag and
allows everybody connect unconditionally. Doesn't conform to the rfb
spec but is traditional QEMU behavior.
@item key-delay-ms
Set keyboard delay, for key down and key up events, in milliseconds.
Default is 1. Keyboards are low-bandwidth devices, so this slowdown
can help the device and guest to keep up and not lose events in case
events are arriving in bulk. Possible causes for the latter are flaky
network connections, or scripts for automated testing.
@end table
ETEXI

View File

@ -2,6 +2,7 @@
#include <glob.h>
#include <dirent.h>
#include "qemu/error-report.h"
#include "ui/egl-helpers.h"
EGLDisplay *qemu_egl_display;
@ -74,13 +75,13 @@ int egl_rendernode_init(void)
qemu_egl_rn_fd = qemu_egl_rendernode_open();
if (qemu_egl_rn_fd == -1) {
fprintf(stderr, "egl: no drm render node available\n");
error_report("egl: no drm render node available");
goto err;
}
qemu_egl_rn_gbm_dev = gbm_create_device(qemu_egl_rn_fd);
if (!qemu_egl_rn_gbm_dev) {
fprintf(stderr, "egl: gbm_create_device failed\n");
error_report("egl: gbm_create_device failed");
goto err;
}
@ -88,18 +89,18 @@ int egl_rendernode_init(void)
if (!epoxy_has_egl_extension(qemu_egl_display,
"EGL_KHR_surfaceless_context")) {
fprintf(stderr, "egl: EGL_KHR_surfaceless_context not supported\n");
error_report("egl: EGL_KHR_surfaceless_context not supported");
goto err;
}
if (!epoxy_has_egl_extension(qemu_egl_display,
"EGL_MESA_image_dma_buf_export")) {
fprintf(stderr, "egl: EGL_MESA_image_dma_buf_export not supported\n");
error_report("egl: EGL_MESA_image_dma_buf_export not supported");
goto err;
}
qemu_egl_rn_ctx = qemu_egl_init_ctx();
if (!qemu_egl_rn_ctx) {
fprintf(stderr, "egl: egl_init_ctx failed\n");
error_report("egl: egl_init_ctx failed");
goto err;
}
@ -156,13 +157,13 @@ EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, Window win)
qemu_egl_config,
(EGLNativeWindowType)win, NULL);
if (esurface == EGL_NO_SURFACE) {
fprintf(stderr, "egl: eglCreateWindowSurface failed\n");
error_report("egl: eglCreateWindowSurface failed");
return NULL;
}
b = eglMakeCurrent(qemu_egl_display, esurface, esurface, ectx);
if (b == EGL_FALSE) {
fprintf(stderr, "egl: eglMakeCurrent failed\n");
error_report("egl: eglMakeCurrent failed");
return NULL;
}
@ -204,21 +205,21 @@ int qemu_egl_init_dpy(EGLNativeDisplayType dpy, bool gles, bool debug)
egl_dbg("eglGetDisplay (dpy %p) ...\n", dpy);
qemu_egl_display = eglGetDisplay(dpy);
if (qemu_egl_display == EGL_NO_DISPLAY) {
fprintf(stderr, "egl: eglGetDisplay failed\n");
error_report("egl: eglGetDisplay failed");
return -1;
}
egl_dbg("eglInitialize ...\n");
b = eglInitialize(qemu_egl_display, &major, &minor);
if (b == EGL_FALSE) {
fprintf(stderr, "egl: eglInitialize failed\n");
error_report("egl: eglInitialize failed");
return -1;
}
egl_dbg("eglBindAPI ...\n");
b = eglBindAPI(gles ? EGL_OPENGL_ES_API : EGL_OPENGL_API);
if (b == EGL_FALSE) {
fprintf(stderr, "egl: eglBindAPI failed\n");
error_report("egl: eglBindAPI failed");
return -1;
}
@ -227,7 +228,7 @@ int qemu_egl_init_dpy(EGLNativeDisplayType dpy, bool gles, bool debug)
gles ? conf_att_gles : conf_att_gl,
&qemu_egl_config, 1, &n);
if (b == EGL_FALSE || n != 1) {
fprintf(stderr, "egl: eglChooseConfig failed\n");
error_report("egl: eglChooseConfig failed");
return -1;
}
@ -252,13 +253,13 @@ EGLContext qemu_egl_init_ctx(void)
ectx = eglCreateContext(qemu_egl_display, qemu_egl_config, EGL_NO_CONTEXT,
egl_gles ? ctx_att_gles : ctx_att_gl);
if (ectx == EGL_NO_CONTEXT) {
fprintf(stderr, "egl: eglCreateContext failed\n");
error_report("egl: eglCreateContext failed");
return NULL;
}
b = eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, ectx);
if (b == EGL_FALSE) {
fprintf(stderr, "egl: eglMakeCurrent failed\n");
error_report("egl: eglMakeCurrent failed");
return NULL;
}

View File

@ -1477,13 +1477,14 @@ static void gd_grab_pointer(VirtualConsole *vc, const char *reason)
static void gd_ungrab_pointer(GtkDisplayState *s)
{
VirtualConsole *vc = s->ptr_owner;
GdkDisplay *display = gtk_widget_get_display(vc->gfx.drawing_area);
GdkDisplay *display;
if (vc == NULL) {
return;
}
s->ptr_owner = NULL;
display = gtk_widget_get_display(vc->gfx.drawing_area);
#if GTK_CHECK_VERSION(3, 20, 0)
gd_grab_update(vc, vc->s->kbd_owner == vc, false);
gdk_device_warp(gd_get_pointer(display),

View File

@ -116,6 +116,9 @@ void sdl2_2d_switch(DisplayChangeListener *dcl,
case PIXMAN_r8g8b8x8:
format = SDL_PIXELFORMAT_RGBA8888;
break;
case PIXMAN_b8g8r8x8:
format = SDL_PIXELFORMAT_BGRX8888;
break;
default:
g_assert_not_reached();
}

View File

@ -794,6 +794,9 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
}
}
sdl2_num_outputs = i;
if (sdl2_num_outputs == 0) {
return;
}
sdl2_console = g_new0(struct sdl2_console, sdl2_num_outputs);
for (i = 0; i < sdl2_num_outputs; i++) {
QemuConsole *con = qemu_console_lookup_by_index(i);

View File

@ -833,9 +833,11 @@ void qemu_spice_init(void)
"incompatible with -spice port/tls-port");
exit(1);
}
if (egl_rendernode_init() == 0) {
display_opengl = 1;
if (egl_rendernode_init() != 0) {
error_report("Failed to initialize EGL render node for SPICE GL");
exit(1);
}
display_opengl = 1;
}
#endif
}

View File

@ -1629,6 +1629,7 @@ static void reset_keys(VncState *vs)
for(i = 0; i < 256; i++) {
if (vs->modifiers_state[i]) {
qemu_input_event_send_key_number(vs->vd->dcl.con, i, false);
qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
vs->modifiers_state[i] = 0;
}
}
@ -1638,9 +1639,9 @@ static void press_key(VncState *vs, int keysym)
{
int keycode = keysym2scancode(vs->vd->kbd_layout, keysym) & SCANCODE_KEYMASK;
qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, true);
qemu_input_event_send_key_delay(0);
qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, false);
qemu_input_event_send_key_delay(0);
qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
}
static int current_led_state(VncState *vs)
@ -1792,6 +1793,7 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
if (qemu_console_is_graphic(NULL)) {
qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, down);
qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
} else {
bool numlock = vs->modifiers_state[0x45];
bool control = (vs->modifiers_state[0x1d] ||
@ -1913,6 +1915,7 @@ static void vnc_release_modifiers(VncState *vs)
continue;
}
qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, false);
qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
}
}
@ -2094,6 +2097,24 @@ static void set_pixel_conversion(VncState *vs)
}
}
static void send_color_map(VncState *vs)
{
int i;
vnc_write_u8(vs, VNC_MSG_SERVER_SET_COLOUR_MAP_ENTRIES);
vnc_write_u8(vs, 0); /* padding */
vnc_write_u16(vs, 0); /* first color */
vnc_write_u16(vs, 256); /* # of colors */
for (i = 0; i < 256; i++) {
PixelFormat *pf = &vs->client_pf;
vnc_write_u16(vs, (((i >> pf->rshift) & pf->rmax) << (16 - pf->rbits)));
vnc_write_u16(vs, (((i >> pf->gshift) & pf->gmax) << (16 - pf->gbits)));
vnc_write_u16(vs, (((i >> pf->bshift) & pf->bmax) << (16 - pf->bbits)));
}
}
static void set_pixel_format(VncState *vs,
int bits_per_pixel, int depth,
int big_endian_flag, int true_color_flag,
@ -2101,8 +2122,15 @@ static void set_pixel_format(VncState *vs,
int red_shift, int green_shift, int blue_shift)
{
if (!true_color_flag) {
vnc_client_error(vs);
return;
/* Expose a reasonable default 256 color map */
bits_per_pixel = 8;
depth = 8;
red_max = 7;
green_max = 7;
blue_max = 3;
red_shift = 0;
green_shift = 3;
blue_shift = 6;
}
switch (bits_per_pixel) {
@ -2132,6 +2160,10 @@ static void set_pixel_format(VncState *vs,
vs->client_pf.depth = bits_per_pixel == 32 ? 24 : bits_per_pixel;
vs->client_be = big_endian_flag;
if (!true_color_flag) {
send_color_map(vs);
}
set_pixel_conversion(vs);
graphic_hw_invalidate(vs->vd->dcl.con);
@ -3248,6 +3280,9 @@ static QemuOptsList qemu_vnc_opts = {
},{
.name = "lock-key-sync",
.type = QEMU_OPT_BOOL,
},{
.name = "key-delay-ms",
.type = QEMU_OPT_NUMBER,
},{
.name = "sasl",
.type = QEMU_OPT_BOOL,
@ -3486,6 +3521,7 @@ void vnc_display_open(const char *id, Error **errp)
#endif
int acl = 0;
int lock_key_sync = 1;
int key_delay_ms;
if (!vs) {
error_setg(errp, "VNC display not active");
@ -3604,6 +3640,7 @@ void vnc_display_open(const char *id, Error **errp)
reverse = qemu_opt_get_bool(opts, "reverse", false);
lock_key_sync = qemu_opt_get_bool(opts, "lock-key-sync", true);
key_delay_ms = qemu_opt_get_number(opts, "key-delay-ms", 1);
sasl = qemu_opt_get_bool(opts, "sasl", false);
#ifndef CONFIG_VNC_SASL
if (sasl) {
@ -3735,6 +3772,7 @@ void vnc_display_open(const char *id, Error **errp)
}
#endif
vs->lock_key_sync = lock_key_sync;
vs->key_delay_ms = key_delay_ms;
device_id = qemu_opt_get(opts, "display");
if (device_id) {

View File

@ -155,6 +155,7 @@ struct VncDisplay
DisplayChangeListener dcl;
kbd_layout_t *kbd_layout;
int lock_key_sync;
int key_delay_ms;
QemuMutex mutex;
QEMUCursor *cursor;