ui: bugfixes and small improvements all over the place.

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABAgAGBQJYkLHEAAoJEEy22O7T6HE46sEQAJQbadd6JiSu0nt9X6+HTAUM
 +EeCumagX/Y92q88ZgBEk3GUtcBVrQAhF6NWJjQx6u/mNrXDno6hgIAS7APJlaOJ
 HolzXt+Up2LbmwF0stYHA1+4jlQZshmFc8ieg0HqiFO04WTvFT+N64I62MlZcsx6
 Eb26DntdeVcGkcJ3ZukN1w0jdBUV+Nifq+B2TLE1zBxTSioxgaHiG2ZXzc+Q+6wo
 iGERN9JLPPD3OaZx2ZoP0gi+Hl23+aUY2dwgD2pzHlgdkWKLq+ntr48C6HChETLK
 FDC4h2QnQ4Rayr4jeuUnEZq5GIsSVWfjLyJM14PG7L43CvvgN+J42sjR0T5EZSN4
 2lFaUcvkEnO+aFySdEfQB04T/Cl4C7U5PMrgIXs4kkrhNvBtBLsnNr7u6XbLZOI0
 d4wqZMQBIXKREKffhADdZcqlxn3PnjbljvntiXgsTSpqoLuEHh9YHsXp3/ggSVqu
 kzYIwnk2TQ3VU0hHjqCHZ6Va0aRq/tGYeXyb5Sq2HUqbDFiH08w0pVjUr70QZm6U
 xdYeqz/k+SEymk02QhaJLZrSJfkNajkYeCrp+GggOnwnP5h1xu3rBKRqrOa8eGwK
 FJME6EwHd2jyPucLj4hROxfMiRSHrIsA4sY0eLMVrz613+TxWx50wjG7dshcbMnR
 0Y39Ll9HysqcJHKkhqLq
 =gRLy
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/kraxel/tags/pull-ui-20170131-2' into staging

ui: bugfixes and small improvements all over the place.

# gpg: Signature made Tue 31 Jan 2017 15:48:20 GMT
# gpg:                using RSA key 0x4CB6D8EED3E87138
# 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>"
# Primary key fingerprint: A032 8CFF B93A 17A7 9901  FE7D 4CB6 D8EE D3E8 7138

* remotes/kraxel/tags/pull-ui-20170131-2:
  console: fix console resize
  gtk: Hardcode LC_CTYPE as C.utf-8
  vnc: fix overflow in vnc_update_stats
  spice: wakeup QXL worker to pick up mouse changes
  ui/gtk.c: add ctrl-alt-= support for zoom in acceleration
  ui: fix format specfier in vnc to avoid break in build.
  ui/gtk: Fix mouse wheel on 3.4.0 or later
  vnc: track LED state separately
  ui: add support for mice with extra/side buttons
  ps2: add support for mice with extra/side buttons
  qapi: add support for mice with extra/side buttons

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2017-01-31 18:41:33 +00:00
commit 6fe791b5e3
9 changed files with 80 additions and 53 deletions

View File

@ -881,9 +881,11 @@ static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
InputEvent *evt) InputEvent *evt)
{ {
static const int bmap[INPUT_BUTTON__MAX] = { static const int bmap[INPUT_BUTTON__MAX] = {
[INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON, [INPUT_BUTTON_LEFT] = PS2_MOUSE_BUTTON_LEFT,
[INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON, [INPUT_BUTTON_MIDDLE] = PS2_MOUSE_BUTTON_MIDDLE,
[INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON, [INPUT_BUTTON_RIGHT] = PS2_MOUSE_BUTTON_RIGHT,
[INPUT_BUTTON_SIDE] = PS2_MOUSE_BUTTON_SIDE,
[INPUT_BUTTON_EXTRA] = PS2_MOUSE_BUTTON_EXTRA,
}; };
PS2MouseState *s = (PS2MouseState *)dev; PS2MouseState *s = (PS2MouseState *)dev;
InputMoveEvent *move; InputMoveEvent *move;

View File

@ -25,6 +25,12 @@
#ifndef HW_PS2_H #ifndef HW_PS2_H
#define HW_PS2_H #define HW_PS2_H
#define PS2_MOUSE_BUTTON_LEFT 0x01
#define PS2_MOUSE_BUTTON_MIDDLE 0x02
#define PS2_MOUSE_BUTTON_RIGHT 0x04
#define PS2_MOUSE_BUTTON_SIDE 0x08
#define PS2_MOUSE_BUTTON_EXTRA 0x10
/* ps2.c */ /* ps2.c */
void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg); void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg);
void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg); void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg);

View File

@ -5390,10 +5390,15 @@
# #
# Button of a pointer input device (mouse, tablet). # Button of a pointer input device (mouse, tablet).
# #
# @side: front side button of a 5-button mouse (since 2.9)
#
# @extra: rear side button of a 5-button mouse (since 2.9)
#
# Since: 2.0 # Since: 2.0
## ##
{ 'enum' : 'InputButton', { 'enum' : 'InputButton',
'data' : [ 'left', 'middle', 'right', 'wheel-up', 'wheel-down' ] } 'data' : [ 'left', 'middle', 'right', 'wheel-up', 'wheel-down', 'side',
'extra' ] }
## ##
# @InputAxis: # @InputAxis:

View File

@ -2116,7 +2116,7 @@ void qemu_console_resize(QemuConsole *s, int width, int height)
assert(s->console_type == GRAPHIC_CONSOLE); assert(s->console_type == GRAPHIC_CONSOLE);
if (s->surface && if (s->surface && (s->surface->flags & QEMU_ALLOCATED_FLAG) &&
pixman_image_get_width(s->surface->image) == width && pixman_image_get_width(s->surface->image) == width &&
pixman_image_get_height(s->surface->image) == height) { pixman_image_get_height(s->surface->image) == height) {
return; return;

View File

@ -105,6 +105,7 @@
#define GDK_KEY_g GDK_g #define GDK_KEY_g GDK_g
#define GDK_KEY_q GDK_q #define GDK_KEY_q GDK_q
#define GDK_KEY_plus GDK_plus #define GDK_KEY_plus GDK_plus
#define GDK_KEY_equal GDK_equal
#define GDK_KEY_minus GDK_minus #define GDK_KEY_minus GDK_minus
#define GDK_KEY_Pause GDK_Pause #define GDK_KEY_Pause GDK_Pause
#define GDK_KEY_Delete GDK_Delete #define GDK_KEY_Delete GDK_Delete
@ -1007,6 +1008,10 @@ static gboolean gd_button_event(GtkWidget *widget, GdkEventButton *button,
btn = INPUT_BUTTON_MIDDLE; btn = INPUT_BUTTON_MIDDLE;
} else if (button->button == 3) { } else if (button->button == 3) {
btn = INPUT_BUTTON_RIGHT; btn = INPUT_BUTTON_RIGHT;
} else if (button->button == 8) {
btn = INPUT_BUTTON_SIDE;
} else if (button->button == 9) {
btn = INPUT_BUTTON_EXTRA;
} else { } else {
return TRUE; return TRUE;
} }
@ -1027,6 +1032,19 @@ static gboolean gd_scroll_event(GtkWidget *widget, GdkEventScroll *scroll,
btn = INPUT_BUTTON_WHEEL_UP; btn = INPUT_BUTTON_WHEEL_UP;
} else if (scroll->direction == GDK_SCROLL_DOWN) { } else if (scroll->direction == GDK_SCROLL_DOWN) {
btn = INPUT_BUTTON_WHEEL_DOWN; btn = INPUT_BUTTON_WHEEL_DOWN;
#if GTK_CHECK_VERSION(3, 4, 0)
} else if (scroll->direction == GDK_SCROLL_SMOOTH) {
gdouble delta_x, delta_y;
if (!gdk_event_get_scroll_deltas((GdkEvent *)scroll,
&delta_x, &delta_y)) {
return TRUE;
}
if (delta_y > 0) {
btn = INPUT_BUTTON_WHEEL_DOWN;
} else {
btn = INPUT_BUTTON_WHEEL_UP;
}
#endif
} else { } else {
return TRUE; return TRUE;
} }
@ -1325,6 +1343,12 @@ static void gd_menu_zoom_in(GtkMenuItem *item, void *opaque)
gd_update_windowsize(vc); gd_update_windowsize(vc);
} }
static void gd_accel_zoom_in(void *opaque)
{
GtkDisplayState *s = opaque;
gtk_menu_item_activate(GTK_MENU_ITEM(s->zoom_in_item));
}
static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque) static void gd_menu_zoom_out(GtkMenuItem *item, void *opaque)
{ {
GtkDisplayState *s = opaque; GtkDisplayState *s = opaque;
@ -2092,6 +2116,8 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s)
"<QEMU>/View/Zoom In"); "<QEMU>/View/Zoom In");
gtk_accel_map_add_entry("<QEMU>/View/Zoom In", GDK_KEY_plus, gtk_accel_map_add_entry("<QEMU>/View/Zoom In", GDK_KEY_plus,
HOTKEY_MODIFIERS); HOTKEY_MODIFIERS);
gtk_accel_group_connect(s->accel_group, GDK_KEY_equal, HOTKEY_MODIFIERS, 0,
g_cclosure_new_swap(G_CALLBACK(gd_accel_zoom_in), s, NULL));
gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->zoom_in_item); gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->zoom_in_item);
s->zoom_out_item = gtk_menu_item_new_with_mnemonic(_("Zoom _Out")); s->zoom_out_item = gtk_menu_item_new_with_mnemonic(_("Zoom _Out"));
@ -2232,8 +2258,12 @@ void gtk_display_init(DisplayState *ds, bool full_screen, bool grab_on_hover)
s->free_scale = FALSE; s->free_scale = FALSE;
/* LC_MESSAGES only. See early_gtk_display_init() for details */ /* Mostly LC_MESSAGES only. See early_gtk_display_init() for details. For
* LC_CTYPE, we need to make sure that non-ASCII characters are considered
* printable, but without changing any of the character classes to make
* sure that we don't accidentally break implicit assumptions. */
setlocale(LC_MESSAGES, ""); setlocale(LC_MESSAGES, "");
setlocale(LC_CTYPE, "C.UTF-8");
bindtextdomain("qemu", CONFIG_QEMU_LOCALEDIR); bindtextdomain("qemu", CONFIG_QEMU_LOCALEDIR);
textdomain("qemu"); textdomain("qemu");

View File

@ -291,6 +291,12 @@ static void input_linux_handle_mouse(InputLinux *il, struct input_event *event)
qemu_input_queue_btn(NULL, INPUT_BUTTON_WHEEL_DOWN, qemu_input_queue_btn(NULL, INPUT_BUTTON_WHEEL_DOWN,
event->value); event->value);
break; break;
case BTN_SIDE:
qemu_input_queue_btn(NULL, INPUT_BUTTON_SIDE, event->value);
break;
case BTN_EXTRA:
qemu_input_queue_btn(NULL, INPUT_BUTTON_EXTRA, event->value);
break;
}; };
break; break;
case EV_REL: case EV_REL:

View File

@ -769,6 +769,7 @@ static void display_mouse_set(DisplayChangeListener *dcl,
g_free(ssd->ptr_move); g_free(ssd->ptr_move);
ssd->ptr_move = qemu_spice_create_cursor_update(ssd, NULL, on); ssd->ptr_move = qemu_spice_create_cursor_update(ssd, NULL, on);
qemu_mutex_unlock(&ssd->lock); qemu_mutex_unlock(&ssd->lock);
qemu_spice_wakeup(ssd);
} }
static void display_mouse_define(DisplayChangeListener *dcl, static void display_mouse_define(DisplayChangeListener *dcl,
@ -787,6 +788,7 @@ static void display_mouse_define(DisplayChangeListener *dcl,
g_free(ssd->ptr_define); g_free(ssd->ptr_define);
ssd->ptr_define = qemu_spice_create_cursor_update(ssd, c, 0); ssd->ptr_define = qemu_spice_create_cursor_update(ssd, c, 0);
qemu_mutex_unlock(&ssd->lock); qemu_mutex_unlock(&ssd->lock);
qemu_spice_wakeup(ssd);
} }
static const DisplayChangeListenerOps display_listener_ops = { static const DisplayChangeListenerOps display_listener_ops = {

View File

@ -1231,8 +1231,6 @@ void vnc_disconnect_finish(VncState *vs)
vnc_update_server_surface(vs->vd); vnc_update_server_surface(vs->vd);
} }
if (vs->vd->lock_key_sync)
qemu_remove_led_event_handler(vs->led);
vnc_unlock_output(vs); vnc_unlock_output(vs);
qemu_mutex_destroy(&vs->output_mutex); qemu_mutex_destroy(&vs->output_mutex);
@ -1259,7 +1257,7 @@ ssize_t vnc_client_io_error(VncState *vs, ssize_t ret, Error **errp)
if (ret == 0) { if (ret == 0) {
VNC_DEBUG("Closing down client sock: EOF\n"); VNC_DEBUG("Closing down client sock: EOF\n");
} else if (ret != QIO_CHANNEL_ERR_BLOCK) { } else if (ret != QIO_CHANNEL_ERR_BLOCK) {
VNC_DEBUG("Closing down client sock: ret %d (%s)\n", VNC_DEBUG("Closing down client sock: ret %zd (%s)\n",
ret, errp ? error_get_pretty(*errp) : "Unknown"); ret, errp ? error_get_pretty(*errp) : "Unknown");
} }
@ -1665,69 +1663,39 @@ static void press_key(VncState *vs, int keysym)
qemu_input_event_send_key_delay(vs->vd->key_delay_ms); qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
} }
static int current_led_state(VncState *vs)
{
int ledstate = 0;
if (vs->modifiers_state[0x46]) {
ledstate |= QEMU_SCROLL_LOCK_LED;
}
if (vs->modifiers_state[0x45]) {
ledstate |= QEMU_NUM_LOCK_LED;
}
if (vs->modifiers_state[0x3a]) {
ledstate |= QEMU_CAPS_LOCK_LED;
}
return ledstate;
}
static void vnc_led_state_change(VncState *vs) static void vnc_led_state_change(VncState *vs)
{ {
int ledstate = 0;
if (!vnc_has_feature(vs, VNC_FEATURE_LED_STATE)) { if (!vnc_has_feature(vs, VNC_FEATURE_LED_STATE)) {
return; return;
} }
ledstate = current_led_state(vs);
vnc_lock_output(vs); vnc_lock_output(vs);
vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
vnc_write_u8(vs, 0); vnc_write_u8(vs, 0);
vnc_write_u16(vs, 1); vnc_write_u16(vs, 1);
vnc_framebuffer_update(vs, 0, 0, 1, 1, VNC_ENCODING_LED_STATE); vnc_framebuffer_update(vs, 0, 0, 1, 1, VNC_ENCODING_LED_STATE);
vnc_write_u8(vs, ledstate); vnc_write_u8(vs, vs->vd->ledstate);
vnc_unlock_output(vs); vnc_unlock_output(vs);
vnc_flush(vs); vnc_flush(vs);
} }
static void kbd_leds(void *opaque, int ledstate) static void kbd_leds(void *opaque, int ledstate)
{ {
VncState *vs = opaque; VncDisplay *vd = opaque;
int caps, num, scr; VncState *client;
bool has_changed = (ledstate != current_led_state(vs));
trace_vnc_key_guest_leds((ledstate & QEMU_CAPS_LOCK_LED), trace_vnc_key_guest_leds((ledstate & QEMU_CAPS_LOCK_LED),
(ledstate & QEMU_NUM_LOCK_LED), (ledstate & QEMU_NUM_LOCK_LED),
(ledstate & QEMU_SCROLL_LOCK_LED)); (ledstate & QEMU_SCROLL_LOCK_LED));
caps = ledstate & QEMU_CAPS_LOCK_LED ? 1 : 0; if (ledstate == vd->ledstate) {
num = ledstate & QEMU_NUM_LOCK_LED ? 1 : 0; return;
scr = ledstate & QEMU_SCROLL_LOCK_LED ? 1 : 0;
if (vs->modifiers_state[0x3a] != caps) {
vs->modifiers_state[0x3a] = caps;
}
if (vs->modifiers_state[0x45] != num) {
vs->modifiers_state[0x45] = num;
}
if (vs->modifiers_state[0x46] != scr) {
vs->modifiers_state[0x46] = scr;
} }
/* Sending the current led state message to the client */ vd->ledstate = ledstate;
if (has_changed) {
vnc_led_state_change(vs); QTAILQ_FOREACH(client, &vd->clients, next) {
vnc_led_state_change(client);
} }
} }
@ -2756,8 +2724,10 @@ static int vnc_refresh_lossy_rect(VncDisplay *vd, int x, int y)
static int vnc_update_stats(VncDisplay *vd, struct timeval * tv) static int vnc_update_stats(VncDisplay *vd, struct timeval * tv)
{ {
int width = pixman_image_get_width(vd->guest.fb); int width = MIN(pixman_image_get_width(vd->guest.fb),
int height = pixman_image_get_height(vd->guest.fb); pixman_image_get_width(vd->server));
int height = MIN(pixman_image_get_height(vd->guest.fb),
pixman_image_get_height(vd->server));
int x, y; int x, y;
struct timeval res; struct timeval res;
int has_dirty = 0; int has_dirty = 0;
@ -3087,8 +3057,6 @@ void vnc_start_protocol(VncState *vs)
vnc_write(vs, "RFB 003.008\n", 12); vnc_write(vs, "RFB 003.008\n", 12);
vnc_flush(vs); vnc_flush(vs);
vnc_read_when(vs, protocol_version, 12); vnc_read_when(vs, protocol_version, 12);
if (vs->vd->lock_key_sync)
vs->led = qemu_add_led_event_handler(kbd_leds, vs);
vs->mouse_mode_notifier.notify = check_pointer_type_change; vs->mouse_mode_notifier.notify = check_pointer_type_change;
qemu_add_mouse_mode_change_notifier(&vs->mouse_mode_notifier); qemu_add_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
@ -3195,6 +3163,9 @@ static void vnc_display_close(VncDisplay *vd)
} }
g_free(vd->tlsaclname); g_free(vd->tlsaclname);
vd->tlsaclname = NULL; vd->tlsaclname = NULL;
if (vd->lock_key_sync) {
qemu_remove_led_event_handler(vd->led);
}
} }
int vnc_display_password(const char *id, const char *password) int vnc_display_password(const char *id, const char *password)
@ -3762,6 +3733,10 @@ void vnc_display_open(const char *id, Error **errp)
} }
#endif #endif
vd->lock_key_sync = lock_key_sync; vd->lock_key_sync = lock_key_sync;
if (lock_key_sync) {
vd->led = qemu_add_led_event_handler(kbd_leds, vd);
}
vd->ledstate = 0;
vd->key_delay_ms = key_delay_ms; vd->key_delay_ms = key_delay_ms;
device_id = qemu_opt_get(opts, "display"); device_id = qemu_opt_get(opts, "display");

View File

@ -154,6 +154,8 @@ struct VncDisplay
DisplayChangeListener dcl; DisplayChangeListener dcl;
kbd_layout_t *kbd_layout; kbd_layout_t *kbd_layout;
int lock_key_sync; int lock_key_sync;
QEMUPutLEDEntry *led;
int ledstate;
int key_delay_ms; int key_delay_ms;
QemuMutex mutex; QemuMutex mutex;
@ -304,7 +306,6 @@ struct VncState
size_t read_handler_expect; size_t read_handler_expect;
/* input */ /* input */
uint8_t modifiers_state[256]; uint8_t modifiers_state[256];
QEMUPutLEDEntry *led;
bool abort; bool abort;
QemuMutex output_mutex; QemuMutex output_mutex;