ui: add kbd stats tracker.

ui: gtk scroll fixes.
 ui: egl cursor scale fix.
 ui: more sdl1 cleanup.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABAgAGBQJcWWwmAAoJEEy22O7T6HE473kQAIlRHR4xHWTgsVD4sxj7qRqv
 vN+OHCz/Z+bRPUaP2xR583Bhw67J1Z6KjBoZj67WDHBXG8gjV5HwQvM0ahGrH4iB
 70InTLe2EQkS34lFGwjChDd3uVV3jgPXItILYr8UeAJSMpKF95mx/WL9UZT41Q0n
 BiOEwy33EpqV6vZXRrWLjzeqZEiIKF66/flmVjcJDPk09gN5dUP80+0bXyfZe4qs
 7ChvAk/t8ycgw1P60MsdYadzG7Vqp7tezbMSba+Cfm/SSeAbZJQVcsV4og6K0ppv
 fidLAzH51BEHSDXRKdzCg5L8jNusgnXhBZ5eh0RrpEEodOom7XdbypDTJn2uipG1
 11911D5+8Z5iLplgMqLtNtktA8UoSZxIVuzG7wrCV4dvRx45BHwyV+aw4Y0LYrOi
 +jB9pLMfNp0FcqYWk2VcXQKSkC6wGBz0E0iqcNKu1oZBpTWs400hw+cN+ACyxWg9
 HklPxST/wZSrlTg7WrQmSaqC+rAtUkPYKwTnWEOjncxUu+C5t2kLFNyxbvrg+z4i
 6c+tAiJicjMVhTjvGg905l/0g8FNNVUDWGpJ1DGuD+03l6mZgyWzc8IToClAHzdl
 RpZwZ6tdshV9P+l3eLzVvk2BIYcs6/MA4z/Adk/YbrXYty9FGk0WUKgfJqkyfzFx
 7yn56KpBGHKm2Pvca+qO
 =Q86o
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/kraxel/tags/ui-20190205-pull-request' into staging

ui: add kbd stats tracker.
ui: gtk scroll fixes.
ui: egl cursor scale fix.
ui: more sdl1 cleanup.

# gpg: Signature made Tue 05 Feb 2019 10:57:42 GMT
# gpg:                using RSA key 4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full]
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>" [full]
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full]
# Primary key fingerprint: A032 8CFF B93A 17A7 9901  FE7D 4CB6 D8EE D3E8 7138

* remotes/kraxel/tags/ui-20190205-pull-request:
  keymap: fix keyup mappings
  keymap: pass full keyboard state to keysym2scancode
  kbd-state: use state tracker for vnc
  kbd-state: use state tracker for gtk
  sdl2: use only QKeyCode in sdl2_process_key()
  kbd-state: use state tracker for sdl2
  sdl2: remove sdl2_reset_keys() function
  kbd-state: add keyboard state tracker
  ui/egl-helpers: Augment parameter list of egl_texture_blend() to convey scales of viewport
  ui/cocoa.m: Fix macOS 10.14 deprecation warnings
  ui/sdl_keysym: Remove obsolete SDL1.2 related code
  ui: listen for GDK_SMOOTH_SCROLL events
  ui: don't send any event if delta_y == 0
  Remove deprecated -no-frame option

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2019-02-05 14:01:29 +00:00
commit 01a9a51ffa
24 changed files with 360 additions and 533 deletions

View File

@ -102,7 +102,6 @@ extern const char *keyboard_layout;
extern int win2k_install_hack;
extern int alt_grab;
extern int ctrl_grab;
extern int no_frame;
extern int smp_cpus;
extern unsigned int max_cpus;
extern int cursor_hide;

View File

@ -27,7 +27,7 @@ void egl_fb_read(void *dst, egl_fb *src);
void egl_texture_blit(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip);
void egl_texture_blend(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip,
int x, int y);
int x, int y, double scale_x, double scale_y);
#ifdef CONFIG_OPENGL_DMABUF

View File

@ -22,6 +22,7 @@
#include <gdk/gdkwayland.h>
#endif
#include "ui/kbd-state.h"
#if defined(CONFIG_OPENGL)
#include "ui/egl-helpers.h"
#include "ui/egl-context.h"
@ -32,6 +33,7 @@ typedef struct GtkDisplayState GtkDisplayState;
typedef struct VirtualGfxConsole {
GtkWidget *drawing_area;
DisplayChangeListener dcl;
QKbdState *kbd;
DisplaySurface *ds;
pixman_image_t *convert;
cairo_surface_t *surface;

101
include/ui/kbd-state.h Normal file
View File

@ -0,0 +1,101 @@
/*
* This work is licensed under the terms of the GNU GPL, version 2 or
* (at your option) any later version. See the COPYING file in the
* top-level directory.
*/
#ifndef QEMU_UI_KBD_STATE_H
#define QEMU_UI_KBD_STATE_H 1
#include "qapi/qapi-types-ui.h"
typedef enum QKbdModifier QKbdModifier;
enum QKbdModifier {
QKBD_MOD_NONE = 0,
QKBD_MOD_SHIFT,
QKBD_MOD_CTRL,
QKBD_MOD_ALT,
QKBD_MOD_ALTGR,
QKBD_MOD_NUMLOCK,
QKBD_MOD_CAPSLOCK,
QKBD_MOD__MAX
};
typedef struct QKbdState QKbdState;
/**
* qkbd_state_init: init keyboard state tracker.
*
* Allocates and initializes keyboard state struct.
*
* @con: QemuConsole for this state tracker. Gets passed down to
* qemu_input_*() functions when sending key events to the guest.
*/
QKbdState *qkbd_state_init(QemuConsole *con);
/**
* qkbd_state_free: free keyboard tracker state.
*
* @kbd: state tracker state.
*/
void qkbd_state_free(QKbdState *kbd);
/**
* qkbd_state_key_event: process key event.
*
* Update keyboard state, send event to the guest.
*
* This function takes care to not send suspious events (keyup event
* for a key not pressed for example).
*
* @kbd: state tracker state.
* @qcode: the key pressed or released.
* @down: true for key down events, false otherwise.
*/
void qkbd_state_key_event(QKbdState *kbd, QKeyCode qcode, bool down);
/**
* qkbd_state_set_delay: set key press delay.
*
* When set the specified delay will be added after each key event,
* using qemu_input_event_send_key_delay().
*
* @kbd: state tracker state.
* @delay_ms: the delay in miliseconds.
*/
void qkbd_state_set_delay(QKbdState *kbd, int delay_ms);
/**
* qkbd_state_key_get: get key state.
*
* Returns true when the key is down.
*
* @kbd: state tracker state.
* @qcode: the key to query.
*/
bool qkbd_state_key_get(QKbdState *kbd, QKeyCode qcode);
/**
* qkbd_state_modifier_get: get modifier state.
*
* Returns true when the modifier is active.
*
* @kbd: state tracker state.
* @mod: the modifier to query.
*/
bool qkbd_state_modifier_get(QKbdState *kbd, QKbdModifier mod);
/**
* qkbd_state_lift_all_keys: lift all pressed keys.
*
* This sends key up events to the guest for all keys which are in
* down state.
*
* @kbd: state tracker state.
*/
void qkbd_state_lift_all_keys(QKbdState *kbd);
#endif /* QEMU_UI_KBD_STATE_H */

View File

@ -10,6 +10,7 @@
# include <SDL_image.h>
#endif
#include "ui/kbd-state.h"
#ifdef CONFIG_OPENGL
# include "ui/egl-helpers.h"
#endif
@ -30,6 +31,7 @@ struct sdl2_console {
int idle_counter;
int ignore_hotkeys;
SDL_GLContext winctx;
QKbdState *kbd;
#ifdef CONFIG_OPENGL
QemuGLShader *gls;
egl_fb guest_fb;
@ -44,7 +46,6 @@ void sdl2_window_destroy(struct sdl2_console *scon);
void sdl2_window_resize(struct sdl2_console *scon);
void sdl2_poll_events(struct sdl2_console *scon);
void sdl2_reset_keys(struct sdl2_console *scon);
void sdl2_process_key(struct sdl2_console *scon,
SDL_KeyboardEvent *ev);

View File

@ -37,12 +37,6 @@ would automatically enable USB support on the machine type.
If using the new syntax, USB support must be explicitly
enabled via the ``-machine usb=on'' argument.
@subsection -no-frame (since 2.12.0)
The @code{--no-frame} argument works with SDL 1.2 only. The other user
interfaces never implemented this in the first place. So this will be
removed together with SDL 1.2 support.
@subsection -virtioconsole (since 3.0.0)
Option @option{-virtioconsole} has been replaced by

View File

@ -1294,17 +1294,6 @@ mode using a curses/ncurses interface. Nothing is displayed in graphical
mode.
ETEXI
DEF("no-frame", 0, QEMU_OPTION_no_frame,
"-no-frame open SDL window without a frame and window decorations\n",
QEMU_ARCH_ALL)
STEXI
@item -no-frame
@findex -no-frame
Do not use decorations for SDL windows and start them using the whole
available screen space. This makes the using QEMU in a dedicated desktop
workspace more convenient.
ETEXI
DEF("alt-grab", 0, QEMU_OPTION_alt_grab,
"-alt-grab use Ctrl-Alt-Shift to grab mouse (instead of Ctrl-Alt)\n",
QEMU_ARCH_ALL)

View File

@ -8,7 +8,7 @@ vnc-obj-y += vnc-ws.o
vnc-obj-y += vnc-jobs.o
common-obj-y += keymaps.o console.o cursor.o qemu-pixman.o
common-obj-y += input.o input-keymap.o input-legacy.o
common-obj-y += input.o input-keymap.o input-legacy.o kbd-state.o
common-obj-$(CONFIG_LINUX) += input-linux.o
common-obj-$(CONFIG_SPICE) += spice-core.o spice-input.o spice-display.o
common-obj-$(CONFIG_COCOA) += cocoa.o

View File

@ -54,6 +54,9 @@
#ifndef MAC_OS_X_VERSION_10_12
#define MAC_OS_X_VERSION_10_12 101200
#endif
#ifndef MAC_OS_X_VERSION_10_13
#define MAC_OS_X_VERSION_10_13 101300
#endif
/* macOS 10.12 deprecated many constants, #define the new names for older SDKs */
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
@ -90,6 +93,14 @@
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_9
#define NSModalResponseOK NSFileHandlingPanelOKButton
#endif
/* 10.14 deprecates NSOnState and NSOffState in favor of
* NSControlStateValueOn/Off, which were introduced in 10.13.
* Define for older versions
*/
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_13
#define NSControlStateValueOn NSOnState
#define NSControlStateValueOff NSOffState
#endif
//#define DEBUG
@ -377,7 +388,12 @@ QemuCocoaView *cocoaView;
COCOA_DEBUG("QemuCocoaView: drawRect\n");
// get CoreGraphic context
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10
CGContextRef viewContextRef = [[NSGraphicsContext currentContext] graphicsPort];
#else
CGContextRef viewContextRef = [[NSGraphicsContext currentContext] CGContext];
#endif
CGContextSetInterpolationQuality (viewContextRef, kCGInterpolationNone);
CGContextSetShouldAntialias (viewContextRef, NO);
@ -1147,9 +1163,9 @@ QemuCocoaView *cocoaView;
{
stretch_video = !stretch_video;
if (stretch_video == true) {
[sender setState: NSOnState];
[sender setState: NSControlStateValueOn];
} else {
[sender setState: NSOffState];
[sender setState: NSControlStateValueOff];
}
}
@ -1390,15 +1406,15 @@ QemuCocoaView *cocoaView;
{
/* Unselect the currently selected item */
for (NSMenuItem *item in [menu itemArray]) {
if (item.state == NSOnState) {
[item setState: NSOffState];
if (item.state == NSControlStateValueOn) {
[item setState: NSControlStateValueOff];
break;
}
}
}
// check the menu item
[sender setState: NSOnState];
[sender setState: NSControlStateValueOn];
// get the throttle percentage
throttle_pct = [sender tag];
@ -1502,7 +1518,7 @@ int main (int argc, const char * argv[]) {
initWithTitle: [NSString stringWithFormat: @"%d%%", percentage] action:@selector(adjustSpeed:) keyEquivalent:@""] autorelease];
if (percentage == 100) {
[menuItem setState: NSOnState];
[menuItem setState: NSControlStateValueOn];
}
/* Calculate the throttle percentage */

View File

@ -273,7 +273,7 @@ static void curses_refresh(DisplayChangeListener *dcl)
}
keycode = keysym2scancode(kbd_layout, keysym & KEYSYM_MASK,
false, false, false);
NULL, false);
if (keycode == 0)
continue;

View File

@ -142,7 +142,8 @@ static void egl_scanout_flush(DisplayChangeListener *dcl,
egl_texture_blit(edpy->gls, &edpy->blit_fb, &edpy->guest_fb,
!edpy->y_0_top);
egl_texture_blend(edpy->gls, &edpy->blit_fb, &edpy->cursor_fb,
!edpy->y_0_top, edpy->pos_x, edpy->pos_y);
!edpy->y_0_top, edpy->pos_x, edpy->pos_y,
1.0, 1.0);
} else {
/* no cursor -> use simple framebuffer blit */
egl_fb_blit(&edpy->blit_fb, &edpy->guest_fb, edpy->y_0_top);

View File

@ -120,14 +120,15 @@ void egl_texture_blit(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip)
}
void egl_texture_blend(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip,
int x, int y)
int x, int y, double scale_x, double scale_y)
{
glBindFramebuffer(GL_FRAMEBUFFER_EXT, dst->framebuffer);
int w = scale_x * src->width;
int h = scale_y * src->height;
if (flip) {
glViewport(x, y, src->width, src->height);
glViewport(x, y, w, h);
} else {
glViewport(x, dst->height - src->height - y,
src->width, src->height);
glViewport(x, dst->height - h - y, w, h);
}
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, src->texture);

View File

@ -278,7 +278,8 @@ void gd_egl_scanout_flush(DisplayChangeListener *dcl,
vc->gfx.y0_top);
egl_texture_blend(vc->gfx.gls, &vc->gfx.win_fb, &vc->gfx.cursor_fb,
vc->gfx.y0_top,
vc->gfx.cursor_x, vc->gfx.cursor_y);
vc->gfx.cursor_x, vc->gfx.cursor_y,
vc->gfx.scale_x, vc->gfx.scale_y);
} else {
egl_fb_blit(&vc->gfx.win_fb, &vc->gfx.guest_fb, !vc->gfx.y0_top);
}

View File

@ -122,17 +122,6 @@
#define HOTKEY_MODIFIERS (GDK_CONTROL_MASK | GDK_MOD1_MASK)
static const int modifier_keycode[] = {
Q_KEY_CODE_SHIFT,
Q_KEY_CODE_SHIFT_R,
Q_KEY_CODE_CTRL,
Q_KEY_CODE_CTRL_R,
Q_KEY_CODE_ALT,
Q_KEY_CODE_ALT_R,
Q_KEY_CODE_META_L,
Q_KEY_CODE_META_R,
};
static const guint16 *keycode_map;
static size_t keycode_maplen;
@ -187,7 +176,6 @@ struct GtkDisplayState {
bool external_pause_update;
bool modifier_pressed[ARRAY_SIZE(modifier_keycode)];
bool ignore_keys;
DisplayOptions *opts;
@ -426,20 +414,12 @@ static void gd_update_full_redraw(VirtualConsole *vc)
static void gtk_release_modifiers(GtkDisplayState *s)
{
VirtualConsole *vc = gd_vc_find_current(s);
int i, qcode;
if (vc->type != GD_VC_GFX ||
!qemu_console_is_graphic(vc->gfx.dcl.con)) {
return;
}
for (i = 0; i < ARRAY_SIZE(modifier_keycode); i++) {
qcode = modifier_keycode[i];
if (!s->modifier_pressed[i]) {
continue;
}
qemu_input_event_send_key_qcode(vc->gfx.dcl.con, qcode, false);
s->modifier_pressed[i] = false;
}
qkbd_state_lift_all_keys(vc->gfx.kbd);
}
static void gd_widget_reparent(GtkWidget *from, GtkWidget *to,
@ -1004,7 +984,9 @@ static gboolean gd_scroll_event(GtkWidget *widget, GdkEventScroll *scroll,
&delta_x, &delta_y)) {
return TRUE;
}
if (delta_y > 0) {
if (delta_y == 0) {
return TRUE;
} else if (delta_y > 0) {
btn = INPUT_BUTTON_WHEEL_DOWN;
} else {
btn = INPUT_BUTTON_WHEEL_UP;
@ -1113,7 +1095,6 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
VirtualConsole *vc = opaque;
GtkDisplayState *s = vc->s;
int qcode;
int i;
if (s->ignore_keys) {
s->ignore_keys = (key->type == GDK_KEY_PRESS);
@ -1134,8 +1115,8 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
|| key->hardware_keycode == VK_PAUSE
#endif
) {
qemu_input_event_send_key_qcode(vc->gfx.dcl.con, Q_KEY_CODE_PAUSE,
key->type == GDK_KEY_PRESS);
qkbd_state_key_event(vc->gfx.kbd, Q_KEY_CODE_PAUSE,
key->type == GDK_KEY_PRESS);
return TRUE;
}
@ -1144,14 +1125,8 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
trace_gd_key_event(vc->label, key->hardware_keycode, qcode,
(key->type == GDK_KEY_PRESS) ? "down" : "up");
for (i = 0; i < ARRAY_SIZE(modifier_keycode); i++) {
if (qcode == modifier_keycode[i]) {
s->modifier_pressed[i] = (key->type == GDK_KEY_PRESS);
}
}
qemu_input_event_send_key_qcode(vc->gfx.dcl.con, qcode,
key->type == GDK_KEY_PRESS);
qkbd_state_key_event(vc->gfx.kbd, qcode,
key->type == GDK_KEY_PRESS);
return TRUE;
}
@ -2043,6 +2018,7 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
GDK_ENTER_NOTIFY_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_SCROLL_MASK |
GDK_SMOOTH_SCROLL_MASK |
GDK_KEY_PRESS_MASK);
gtk_widget_set_can_focus(vc->gfx.drawing_area, TRUE);
@ -2052,6 +2028,7 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc,
gtk_notebook_append_page(GTK_NOTEBOOK(s->notebook),
vc->tab_item, gtk_label_new(vc->label));
vc->gfx.kbd = qkbd_state_init(con);
vc->gfx.dcl.con = con;
register_displaychangelistener(&vc->gfx.dcl);

130
ui/kbd-state.c Normal file
View File

@ -0,0 +1,130 @@
/*
* This work is licensed under the terms of the GNU GPL, version 2 or
* (at your option) any later version. See the COPYING file in the
* top-level directory.
*/
#include "qemu/osdep.h"
#include "qemu/bitmap.h"
#include "qemu/queue.h"
#include "ui/console.h"
#include "ui/input.h"
#include "ui/kbd-state.h"
struct QKbdState {
QemuConsole *con;
int key_delay_ms;
DECLARE_BITMAP(keys, Q_KEY_CODE__MAX);
DECLARE_BITMAP(mods, QKBD_MOD__MAX);
};
static void qkbd_state_modifier_update(QKbdState *kbd,
QKeyCode qcode1, QKeyCode qcode2,
QKbdModifier mod)
{
if (test_bit(qcode1, kbd->keys) || test_bit(qcode2, kbd->keys)) {
set_bit(mod, kbd->mods);
} else {
clear_bit(mod, kbd->mods);
}
}
bool qkbd_state_modifier_get(QKbdState *kbd, QKbdModifier mod)
{
return test_bit(mod, kbd->mods);
}
bool qkbd_state_key_get(QKbdState *kbd, QKeyCode qcode)
{
return test_bit(qcode, kbd->keys);
}
void qkbd_state_key_event(QKbdState *kbd, QKeyCode qcode, bool down)
{
bool state = test_bit(qcode, kbd->keys);
if (state == down) {
/*
* Filter out events which don't change the keyboard state.
*
* Most notably this allows to simply send along all key-up
* events, and this function will filter out everything where
* the corresponding key-down event wasn't send to the guest,
* for example due to being a host hotkey.
*/
return;
}
/* update key and modifier state */
change_bit(qcode, kbd->keys);
switch (qcode) {
case Q_KEY_CODE_SHIFT:
case Q_KEY_CODE_SHIFT_R:
qkbd_state_modifier_update(kbd, Q_KEY_CODE_SHIFT, Q_KEY_CODE_SHIFT_R,
QKBD_MOD_SHIFT);
break;
case Q_KEY_CODE_CTRL:
case Q_KEY_CODE_CTRL_R:
qkbd_state_modifier_update(kbd, Q_KEY_CODE_CTRL, Q_KEY_CODE_CTRL_R,
QKBD_MOD_CTRL);
break;
case Q_KEY_CODE_ALT:
qkbd_state_modifier_update(kbd, Q_KEY_CODE_ALT, Q_KEY_CODE_ALT,
QKBD_MOD_ALT);
break;
case Q_KEY_CODE_ALT_R:
qkbd_state_modifier_update(kbd, Q_KEY_CODE_ALT_R, Q_KEY_CODE_ALT_R,
QKBD_MOD_ALTGR);
break;
case Q_KEY_CODE_CAPS_LOCK:
if (down) {
change_bit(QKBD_MOD_CAPSLOCK, kbd->mods);
}
break;
case Q_KEY_CODE_NUM_LOCK:
if (down) {
change_bit(QKBD_MOD_NUMLOCK, kbd->mods);
}
break;
default:
/* keep gcc happy */
break;
}
/* send to guest */
if (qemu_console_is_graphic(kbd->con)) {
qemu_input_event_send_key_qcode(kbd->con, qcode, down);
if (kbd->key_delay_ms) {
qemu_input_event_send_key_delay(kbd->key_delay_ms);
}
}
}
void qkbd_state_lift_all_keys(QKbdState *kbd)
{
int qcode;
for (qcode = 0; qcode < Q_KEY_CODE__MAX; qcode++) {
if (test_bit(qcode, kbd->keys)) {
qkbd_state_key_event(kbd, qcode, false);
}
}
}
void qkbd_state_set_delay(QKbdState *kbd, int delay_ms)
{
kbd->key_delay_ms = delay_ms;
}
void qkbd_state_free(QKbdState *kbd)
{
g_free(kbd);
}
QKbdState *qkbd_state_init(QemuConsole *con)
{
QKbdState *kbd = g_new0(QKbdState, 1);
kbd->con = con;
return kbd;
}

View File

@ -28,6 +28,7 @@
#include "trace.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
#include "ui/input.h"
struct keysym2code {
uint32_t count;
@ -188,7 +189,7 @@ kbd_layout_t *init_keyboard_layout(const name2keysym_t *table,
int keysym2scancode(kbd_layout_t *k, int keysym,
bool shift, bool altgr, bool ctrl)
QKbdState *kbd, bool down)
{
static const uint32_t mask =
SCANCODE_SHIFT | SCANCODE_ALTGR | SCANCODE_CTRL;
@ -212,27 +213,39 @@ int keysym2scancode(kbd_layout_t *k, int keysym,
return keysym2code->keycodes[0];
}
/*
* We have multiple keysym -> keycode mappings.
*
* Check whenever we find one mapping where the modifier state of
* the mapping matches the current user interface modifier state.
* If so, prefer that one.
*/
mods = 0;
if (shift) {
mods |= SCANCODE_SHIFT;
}
if (altgr) {
mods |= SCANCODE_ALTGR;
}
if (ctrl) {
mods |= SCANCODE_CTRL;
}
/* We have multiple keysym -> keycode mappings. */
if (down) {
/*
* On keydown: Check whenever we find one mapping where the
* modifier state of the mapping matches the current user
* interface modifier state. If so, prefer that one.
*/
mods = 0;
if (kbd && qkbd_state_modifier_get(kbd, QKBD_MOD_SHIFT)) {
mods |= SCANCODE_SHIFT;
}
if (kbd && qkbd_state_modifier_get(kbd, QKBD_MOD_ALTGR)) {
mods |= SCANCODE_ALTGR;
}
if (kbd && qkbd_state_modifier_get(kbd, QKBD_MOD_CTRL)) {
mods |= SCANCODE_CTRL;
}
for (i = 0; i < keysym2code->count; i++) {
if ((keysym2code->keycodes[i] & mask) == mods) {
return keysym2code->keycodes[i];
for (i = 0; i < keysym2code->count; i++) {
if ((keysym2code->keycodes[i] & mask) == mods) {
return keysym2code->keycodes[i];
}
}
} else {
/*
* On keyup: Try find a key which is actually down.
*/
for (i = 0; i < keysym2code->count; i++) {
QKeyCode qcode = qemu_input_key_number_to_qcode
(keysym2code->keycodes[i]);
if (kbd && qkbd_state_key_get(kbd, qcode)) {
return keysym2code->keycodes[i];
}
}
}
return keysym2code->keycodes[0];

View File

@ -26,6 +26,7 @@
#define QEMU_KEYMAPS_H
#include "qemu-common.h"
#include "ui/kbd-state.h"
typedef struct {
const char* name;
@ -55,7 +56,7 @@ typedef struct kbd_layout_t kbd_layout_t;
kbd_layout_t *init_keyboard_layout(const name2keysym_t *table,
const char *language, Error **errp);
int keysym2scancode(kbd_layout_t *k, int keysym,
bool shift, bool altgr, bool ctrl);
QKbdState *kbd, bool down);
int keycode_is_keypad(kbd_layout_t *k, int keycode);
int keysym_is_numlock(kbd_layout_t *k, int keysym);

View File

@ -30,63 +30,23 @@
#include "ui/sdl2.h"
#include "sysemu/sysemu.h"
static uint8_t modifiers_state[SDL_NUM_SCANCODES];
void sdl2_reset_keys(struct sdl2_console *scon)
{
QemuConsole *con = scon ? scon->dcl.con : NULL;
int i;
for (i = 0 ;
i < SDL_NUM_SCANCODES && i < qemu_input_map_usb_to_qcode_len ;
i++) {
if (modifiers_state[i]) {
int qcode = qemu_input_map_usb_to_qcode[i];
qemu_input_event_send_key_qcode(con, qcode, false);
modifiers_state[i] = 0;
}
}
}
void sdl2_process_key(struct sdl2_console *scon,
SDL_KeyboardEvent *ev)
{
int qcode;
QemuConsole *con = scon ? scon->dcl.con : NULL;
QemuConsole *con = scon->dcl.con;
if (ev->keysym.scancode >= qemu_input_map_usb_to_qcode_len) {
return;
}
qcode = qemu_input_map_usb_to_qcode[ev->keysym.scancode];
/* modifier state tracking */
switch (ev->keysym.scancode) {
case SDL_SCANCODE_LCTRL:
case SDL_SCANCODE_LSHIFT:
case SDL_SCANCODE_LALT:
case SDL_SCANCODE_LGUI:
case SDL_SCANCODE_RCTRL:
case SDL_SCANCODE_RSHIFT:
case SDL_SCANCODE_RALT:
case SDL_SCANCODE_RGUI:
if (ev->type == SDL_KEYUP) {
modifiers_state[ev->keysym.scancode] = 0;
} else {
modifiers_state[ev->keysym.scancode] = 1;
}
break;
default:
/* nothing */
break;
}
qkbd_state_key_event(scon->kbd, qcode, ev->type == SDL_KEYDOWN);
if (!qemu_console_is_graphic(con)) {
bool ctrl = (modifiers_state[SDL_SCANCODE_LCTRL] ||
modifiers_state[SDL_SCANCODE_RCTRL]);
bool ctrl = qkbd_state_modifier_get(scon->kbd, QKBD_MOD_CTRL);
if (ev->type == SDL_KEYDOWN) {
switch (ev->keysym.scancode) {
case SDL_SCANCODE_RETURN:
switch (qcode) {
case Q_KEY_CODE_RET:
kbd_put_keysym_console(con, '\n');
break;
default:

View File

@ -38,7 +38,6 @@ static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
static int gui_saved_grab;
static int gui_fullscreen;
static int gui_keysym;
static int gui_grab_code = KMOD_LALT | KMOD_LCTRL;
static SDL_Cursor *sdl_cursor_normal;
static SDL_Cursor *sdl_cursor_hidden;
@ -330,6 +329,7 @@ static void handle_keydown(SDL_Event *ev)
int win;
struct sdl2_console *scon = get_scon_from_window(ev->key.windowID);
int gui_key_modifier_pressed = get_mod_state();
int gui_keysym = 0;
if (!scon->ignore_hotkeys && gui_key_modifier_pressed && !ev->key.repeat) {
switch (ev->key.keysym.scancode) {
@ -410,16 +410,9 @@ static void handle_keydown(SDL_Event *ev)
static void handle_keyup(SDL_Event *ev)
{
struct sdl2_console *scon = get_scon_from_window(ev->key.windowID);
int gui_key_modifier_pressed = get_mod_state();
scon->ignore_hotkeys = false;
if (!gui_key_modifier_pressed) {
gui_keysym = 0;
}
if (!gui_keysym) {
sdl2_process_key(scon, &ev->key);
}
sdl2_process_key(scon, &ev->key);
}
static void handle_textinput(SDL_Event *ev)
@ -823,6 +816,7 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
sdl2_console[i].dcl.ops = &dcl_2d_ops;
#endif
sdl2_console[i].dcl.con = con;
sdl2_console[i].kbd = qkbd_state_init(con);
register_displaychangelistener(&sdl2_console[i].dcl);
#if defined(SDL_VIDEO_DRIVER_WINDOWS) || defined(SDL_VIDEO_DRIVER_X11)

View File

@ -1,278 +0,0 @@
#include "keymaps.h"
static const name2keysym_t name2keysym[]={
/* ascii */
{ "space", 0x020},
{ "exclam", 0x021},
{ "quotedbl", 0x022},
{ "numbersign", 0x023},
{ "dollar", 0x024},
{ "percent", 0x025},
{ "ampersand", 0x026},
{ "apostrophe", 0x027},
{ "parenleft", 0x028},
{ "parenright", 0x029},
{ "asterisk", 0x02a},
{ "plus", 0x02b},
{ "comma", 0x02c},
{ "minus", 0x02d},
{ "period", 0x02e},
{ "slash", 0x02f},
{ "0", 0x030},
{ "1", 0x031},
{ "2", 0x032},
{ "3", 0x033},
{ "4", 0x034},
{ "5", 0x035},
{ "6", 0x036},
{ "7", 0x037},
{ "8", 0x038},
{ "9", 0x039},
{ "colon", 0x03a},
{ "semicolon", 0x03b},
{ "less", 0x03c},
{ "equal", 0x03d},
{ "greater", 0x03e},
{ "question", 0x03f},
{ "at", 0x040},
{ "A", 0x041},
{ "B", 0x042},
{ "C", 0x043},
{ "D", 0x044},
{ "E", 0x045},
{ "F", 0x046},
{ "G", 0x047},
{ "H", 0x048},
{ "I", 0x049},
{ "J", 0x04a},
{ "K", 0x04b},
{ "L", 0x04c},
{ "M", 0x04d},
{ "N", 0x04e},
{ "O", 0x04f},
{ "P", 0x050},
{ "Q", 0x051},
{ "R", 0x052},
{ "S", 0x053},
{ "T", 0x054},
{ "U", 0x055},
{ "V", 0x056},
{ "W", 0x057},
{ "X", 0x058},
{ "Y", 0x059},
{ "Z", 0x05a},
{ "bracketleft", 0x05b},
{ "backslash", 0x05c},
{ "bracketright", 0x05d},
{ "asciicircum", 0x05e},
{ "underscore", 0x05f},
{ "grave", 0x060},
{ "a", 0x061},
{ "b", 0x062},
{ "c", 0x063},
{ "d", 0x064},
{ "e", 0x065},
{ "f", 0x066},
{ "g", 0x067},
{ "h", 0x068},
{ "i", 0x069},
{ "j", 0x06a},
{ "k", 0x06b},
{ "l", 0x06c},
{ "m", 0x06d},
{ "n", 0x06e},
{ "o", 0x06f},
{ "p", 0x070},
{ "q", 0x071},
{ "r", 0x072},
{ "s", 0x073},
{ "t", 0x074},
{ "u", 0x075},
{ "v", 0x076},
{ "w", 0x077},
{ "x", 0x078},
{ "y", 0x079},
{ "z", 0x07a},
{ "braceleft", 0x07b},
{ "bar", 0x07c},
{ "braceright", 0x07d},
{ "asciitilde", 0x07e},
/* latin 1 extensions */
{ "nobreakspace", 0x0a0},
{ "exclamdown", 0x0a1},
{ "cent", 0x0a2},
{ "sterling", 0x0a3},
{ "currency", 0x0a4},
{ "yen", 0x0a5},
{ "brokenbar", 0x0a6},
{ "section", 0x0a7},
{ "diaeresis", 0x0a8},
{ "copyright", 0x0a9},
{ "ordfeminine", 0x0aa},
{ "guillemotleft", 0x0ab},
{ "notsign", 0x0ac},
{ "hyphen", 0x0ad},
{ "registered", 0x0ae},
{ "macron", 0x0af},
{ "degree", 0x0b0},
{ "plusminus", 0x0b1},
{ "twosuperior", 0x0b2},
{ "threesuperior", 0x0b3},
{ "acute", 0x0b4},
{ "mu", 0x0b5},
{ "paragraph", 0x0b6},
{ "periodcentered", 0x0b7},
{ "cedilla", 0x0b8},
{ "onesuperior", 0x0b9},
{ "masculine", 0x0ba},
{ "guillemotright", 0x0bb},
{ "onequarter", 0x0bc},
{ "onehalf", 0x0bd},
{ "threequarters", 0x0be},
{ "questiondown", 0x0bf},
{ "Agrave", 0x0c0},
{ "Aacute", 0x0c1},
{ "Acircumflex", 0x0c2},
{ "Atilde", 0x0c3},
{ "Adiaeresis", 0x0c4},
{ "Aring", 0x0c5},
{ "AE", 0x0c6},
{ "Ccedilla", 0x0c7},
{ "Egrave", 0x0c8},
{ "Eacute", 0x0c9},
{ "Ecircumflex", 0x0ca},
{ "Ediaeresis", 0x0cb},
{ "Igrave", 0x0cc},
{ "Iacute", 0x0cd},
{ "Icircumflex", 0x0ce},
{ "Idiaeresis", 0x0cf},
{ "ETH", 0x0d0},
{ "Eth", 0x0d0},
{ "Ntilde", 0x0d1},
{ "Ograve", 0x0d2},
{ "Oacute", 0x0d3},
{ "Ocircumflex", 0x0d4},
{ "Otilde", 0x0d5},
{ "Odiaeresis", 0x0d6},
{ "multiply", 0x0d7},
{ "Ooblique", 0x0d8},
{ "Oslash", 0x0d8},
{ "Ugrave", 0x0d9},
{ "Uacute", 0x0da},
{ "Ucircumflex", 0x0db},
{ "Udiaeresis", 0x0dc},
{ "Yacute", 0x0dd},
{ "THORN", 0x0de},
{ "Thorn", 0x0de},
{ "ssharp", 0x0df},
{ "agrave", 0x0e0},
{ "aacute", 0x0e1},
{ "acircumflex", 0x0e2},
{ "atilde", 0x0e3},
{ "adiaeresis", 0x0e4},
{ "aring", 0x0e5},
{ "ae", 0x0e6},
{ "ccedilla", 0x0e7},
{ "egrave", 0x0e8},
{ "eacute", 0x0e9},
{ "ecircumflex", 0x0ea},
{ "ediaeresis", 0x0eb},
{ "igrave", 0x0ec},
{ "iacute", 0x0ed},
{ "icircumflex", 0x0ee},
{ "idiaeresis", 0x0ef},
{ "eth", 0x0f0},
{ "ntilde", 0x0f1},
{ "ograve", 0x0f2},
{ "oacute", 0x0f3},
{ "ocircumflex", 0x0f4},
{ "otilde", 0x0f5},
{ "odiaeresis", 0x0f6},
{ "division", 0x0f7},
{ "oslash", 0x0f8},
{ "ooblique", 0x0f8},
{ "ugrave", 0x0f9},
{ "uacute", 0x0fa},
{ "ucircumflex", 0x0fb},
{ "udiaeresis", 0x0fc},
{ "yacute", 0x0fd},
{ "thorn", 0x0fe},
{ "ydiaeresis", 0x0ff},
#if SDL_MAJOR_VERSION == 1
{"EuroSign", SDLK_EURO},
/* modifiers */
{"Control_L", SDLK_LCTRL},
{"Control_R", SDLK_RCTRL},
{"Alt_L", SDLK_LALT},
{"Alt_R", SDLK_RALT},
{"Caps_Lock", SDLK_CAPSLOCK},
{"Meta_L", SDLK_LMETA},
{"Meta_R", SDLK_RMETA},
{"Shift_L", SDLK_LSHIFT},
{"Shift_R", SDLK_RSHIFT},
{"Super_L", SDLK_LSUPER},
{"Super_R", SDLK_RSUPER},
/* special keys */
{"BackSpace", SDLK_BACKSPACE},
{"Tab", SDLK_TAB},
{"Return", SDLK_RETURN},
{"Right", SDLK_RIGHT},
{"Left", SDLK_LEFT},
{"Up", SDLK_UP},
{"Down", SDLK_DOWN},
{"Page_Down", SDLK_PAGEDOWN},
{"Page_Up", SDLK_PAGEUP},
{"Insert", SDLK_INSERT},
{"Delete", SDLK_DELETE},
{"Home", SDLK_HOME},
{"End", SDLK_END},
{"Scroll_Lock", SDLK_SCROLLOCK},
{"F1", SDLK_F1},
{"F2", SDLK_F2},
{"F3", SDLK_F3},
{"F4", SDLK_F4},
{"F5", SDLK_F5},
{"F6", SDLK_F6},
{"F7", SDLK_F7},
{"F8", SDLK_F8},
{"F9", SDLK_F9},
{"F10", SDLK_F10},
{"F11", SDLK_F11},
{"F12", SDLK_F12},
{"F13", SDLK_F13},
{"F14", SDLK_F14},
{"F15", SDLK_F15},
{"Sys_Req", SDLK_SYSREQ},
{"KP_0", SDLK_KP0},
{"KP_1", SDLK_KP1},
{"KP_2", SDLK_KP2},
{"KP_3", SDLK_KP3},
{"KP_4", SDLK_KP4},
{"KP_5", SDLK_KP5},
{"KP_6", SDLK_KP6},
{"KP_7", SDLK_KP7},
{"KP_8", SDLK_KP8},
{"KP_9", SDLK_KP9},
{"KP_Add", SDLK_KP_PLUS},
{"KP_Decimal", SDLK_KP_PERIOD},
{"KP_Divide", SDLK_KP_DIVIDE},
{"KP_Enter", SDLK_KP_ENTER},
{"KP_Equal", SDLK_KP_EQUALS},
{"KP_Multiply", SDLK_KP_MULTIPLY},
{"KP_Subtract", SDLK_KP_MINUS},
{"help", SDLK_HELP},
{"Menu", SDLK_MENU},
{"Power", SDLK_POWER},
{"Print", SDLK_PRINT},
{"Mode_switch", SDLK_MODE},
{"Multi_Key", SDLK_COMPOSE},
{"Num_Lock", SDLK_NUMLOCK},
{"Pause", SDLK_PAUSE},
{"Escape", SDLK_ESCAPE},
#endif
{NULL, 0},
};

View File

@ -1090,7 +1090,7 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl,
egl_texture_blit(ssd->gls, &ssd->blit_fb, &ssd->guest_fb,
!y_0_top);
egl_texture_blend(ssd->gls, &ssd->blit_fb, &ssd->cursor_fb,
!y_0_top, x, y);
!y_0_top, x, y, 1.0, 1.0);
glFlush();
}

119
ui/vnc.c
View File

@ -59,7 +59,6 @@ static QTAILQ_HEAD(, VncDisplay) vnc_displays =
QTAILQ_HEAD_INITIALIZER(vnc_displays);
static int vnc_cursor_define(VncState *vs);
static void vnc_release_modifiers(VncState *vs);
static void vnc_update_throttle_offset(VncState *vs);
static void vnc_set_share_mode(VncState *vs, VncShareMode mode)
@ -1267,7 +1266,7 @@ void vnc_disconnect_finish(VncState *vs)
vnc_sasl_client_cleanup(vs);
#endif /* CONFIG_VNC_SASL */
audio_del(vs);
vnc_release_modifiers(vs);
qkbd_state_lift_all_keys(vs->vd->kbd);
if (vs->mouse_mode_notifier.notify != NULL) {
qemu_remove_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
@ -1756,26 +1755,10 @@ static void pointer_event(VncState *vs, int button_mask, int x, int y)
qemu_input_event_sync();
}
static void reset_keys(VncState *vs)
static void press_key(VncState *vs, QKeyCode qcode)
{
int i;
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;
}
}
}
static void press_key(VncState *vs, int keysym)
{
int keycode = keysym2scancode(vs->vd->kbd_layout, keysym,
false, false, false) & SCANCODE_KEYMASK;
qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, true);
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(vs->vd->key_delay_ms);
qkbd_state_key_event(vs->vd->kbd, qcode, true);
qkbd_state_key_event(vs->vd->kbd, qcode, false);
}
static void vnc_led_state_change(VncState *vs)
@ -1816,32 +1799,20 @@ static void kbd_leds(void *opaque, int ledstate)
static void do_key_event(VncState *vs, int down, int keycode, int sym)
{
QKeyCode qcode = qemu_input_key_number_to_qcode(keycode);
/* QEMU console switch */
switch(keycode) {
case 0x2a: /* Left Shift */
case 0x36: /* Right Shift */
case 0x1d: /* Left CTRL */
case 0x9d: /* Right CTRL */
case 0x38: /* Left ALT */
case 0xb8: /* Right ALT */
if (down)
vs->modifiers_state[keycode] = 1;
else
vs->modifiers_state[keycode] = 0;
break;
case 0x02 ... 0x0a: /* '1' to '9' keys */
if (vs->vd->dcl.con == NULL &&
down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
switch (qcode) {
case Q_KEY_CODE_1 ... Q_KEY_CODE_9: /* '1' to '9' keys */
if (vs->vd->dcl.con == NULL && down &&
qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_CTRL) &&
qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_ALT)) {
/* Reset the modifiers sent to the current console */
reset_keys(vs);
console_select(keycode - 0x02);
qkbd_state_lift_all_keys(vs->vd->kbd);
console_select(qcode - Q_KEY_CODE_1);
return;
}
break;
case 0x3a: /* CapsLock */
case 0x45: /* NumLock */
if (down)
vs->modifiers_state[keycode] ^= 1;
default:
break;
}
@ -1856,16 +1827,14 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
toggles numlock away from the VNC window.
*/
if (keysym_is_numlock(vs->vd->kbd_layout, sym & 0xFFFF)) {
if (!vs->modifiers_state[0x45]) {
if (!qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_NUMLOCK)) {
trace_vnc_key_sync_numlock(true);
vs->modifiers_state[0x45] = 1;
press_key(vs, 0xff7f);
press_key(vs, Q_KEY_CODE_NUM_LOCK);
}
} else {
if (vs->modifiers_state[0x45]) {
if (qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_NUMLOCK)) {
trace_vnc_key_sync_numlock(false);
vs->modifiers_state[0x45] = 0;
press_key(vs, 0xff7f);
press_key(vs, Q_KEY_CODE_NUM_LOCK);
}
}
}
@ -1878,30 +1847,25 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
toggles capslock away from the VNC window.
*/
int uppercase = !!(sym >= 'A' && sym <= 'Z');
int shift = !!(vs->modifiers_state[0x2a] | vs->modifiers_state[0x36]);
int capslock = !!(vs->modifiers_state[0x3a]);
bool shift = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_SHIFT);
bool capslock = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_CAPSLOCK);
if (capslock) {
if (uppercase == shift) {
trace_vnc_key_sync_capslock(false);
vs->modifiers_state[0x3a] = 0;
press_key(vs, 0xffe5);
press_key(vs, Q_KEY_CODE_CAPS_LOCK);
}
} else {
if (uppercase != shift) {
trace_vnc_key_sync_capslock(true);
vs->modifiers_state[0x3a] = 1;
press_key(vs, 0xffe5);
press_key(vs, Q_KEY_CODE_CAPS_LOCK);
}
}
}
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] ||
vs->modifiers_state[0x9d]);
qkbd_state_key_event(vs->vd->kbd, qcode, down);
if (!qemu_console_is_graphic(NULL)) {
bool numlock = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_NUMLOCK);
bool control = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_CTRL);
/* QEMU console emulation */
if (down) {
switch (keycode) {
@ -2002,27 +1966,6 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
}
}
static void vnc_release_modifiers(VncState *vs)
{
static const int keycodes[] = {
/* shift, control, alt keys, both left & right */
0x2a, 0x36, 0x1d, 0x9d, 0x38, 0xb8,
};
int i, keycode;
if (!qemu_console_is_graphic(NULL)) {
return;
}
for (i = 0; i < ARRAY_SIZE(keycodes); i++) {
keycode = keycodes[i];
if (!vs->modifiers_state[keycode]) {
continue;
}
qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, false);
qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
}
}
static const char *code2name(int keycode)
{
return QKeyCode_str(qemu_input_key_number_to_qcode(keycode));
@ -2030,9 +1973,6 @@ static const char *code2name(int keycode)
static void key_event(VncState *vs, int down, uint32_t sym)
{
bool shift = vs->modifiers_state[0x2a] || vs->modifiers_state[0x36];
bool altgr = vs->modifiers_state[0xb8];
bool ctrl = vs->modifiers_state[0x1d] || vs->modifiers_state[0x9d];
int keycode;
int lsym = sym;
@ -2041,7 +1981,7 @@ static void key_event(VncState *vs, int down, uint32_t sym)
}
keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF,
shift, altgr, ctrl) & SCANCODE_KEYMASK;
vs->vd->kbd, down) & SCANCODE_KEYMASK;
trace_vnc_key_event_map(down, sym, keycode, code2name(keycode));
do_key_event(vs, down, keycode, sym);
}
@ -3259,6 +3199,7 @@ void vnc_display_init(const char *id, Error **errp)
vd->dcl.ops = &dcl_ops;
register_displaychangelistener(&vd->dcl);
vd->kbd = qkbd_state_init(vd->dcl.con);
}
@ -3995,7 +3936,6 @@ void vnc_display_open(const char *id, Error **errp)
vd->led = qemu_add_led_event_handler(kbd_leds, vd);
}
vd->ledstate = 0;
vd->key_delay_ms = key_delay_ms;
device_id = qemu_opt_get(opts, "display");
if (device_id) {
@ -4012,10 +3952,13 @@ void vnc_display_open(const char *id, Error **errp)
}
if (con != vd->dcl.con) {
qkbd_state_free(vd->kbd);
unregister_displaychangelistener(&vd->dcl);
vd->dcl.con = con;
register_displaychangelistener(&vd->dcl);
vd->kbd = qkbd_state_init(vd->dcl.con);
}
qkbd_state_set_delay(vd->kbd, key_delay_ms);
if (saddr == NULL) {
goto cleanup;

View File

@ -44,6 +44,7 @@
#include "keymaps.h"
#include "vnc-palette.h"
#include "vnc-enc-zrle.h"
#include "ui/kbd-state.h"
// #define _VNC_DEBUG 1
@ -155,7 +156,7 @@ struct VncDisplay
int lock_key_sync;
QEMUPutLEDEntry *led;
int ledstate;
int key_delay_ms;
QKbdState *kbd;
QemuMutex mutex;
QEMUCursor *cursor;
@ -326,8 +327,6 @@ struct VncState
VncReadEvent *read_handler;
size_t read_handler_expect;
/* input */
uint8_t modifiers_state[256];
bool abort;
QemuMutex output_mutex;

23
vl.c
View File

@ -160,7 +160,6 @@ static int rtc_host_datetime_offset = -1; /* valid & used only with
QEMUClockType rtc_clock;
int vga_interface_type = VGA_NONE;
static DisplayOptions dpy;
int no_frame;
static int num_serial_hds;
static Chardev **serial_hds;
Chardev *parallel_hds[MAX_PARALLEL_PORTS];
@ -2113,18 +2112,7 @@ static void parse_display(const char *p)
while (*opts) {
const char *nextopt;
if (strstart(opts, ",frame=", &nextopt)) {
g_printerr("The frame= sdl option is deprecated, and will be\n"
"removed in a future release.\n");
opts = nextopt;
if (strstart(opts, "on", &nextopt)) {
no_frame = 0;
} else if (strstart(opts, "off", &nextopt)) {
no_frame = 1;
} else {
goto invalid_sdl_args;
}
} else if (strstart(opts, ",alt_grab=", &nextopt)) {
if (strstart(opts, ",alt_grab=", &nextopt)) {
opts = nextopt;
if (strstart(opts, "on", &nextopt)) {
alt_grab = 1;
@ -3596,11 +3584,6 @@ int main(int argc, char **argv, char **envp)
dpy.has_full_screen = true;
dpy.full_screen = true;
break;
case QEMU_OPTION_no_frame:
g_printerr("The -no-frame switch is deprecated, and will be\n"
"removed in a future release.\n");
no_frame = 1;
break;
case QEMU_OPTION_alt_grab:
alt_grab = 1;
break;
@ -4279,8 +4262,8 @@ int main(int argc, char **argv, char **envp)
dpy.type = DISPLAY_TYPE_NONE;
}
if ((no_frame || alt_grab || ctrl_grab) && dpy.type != DISPLAY_TYPE_SDL) {
error_report("-no-frame, -alt-grab and -ctrl-grab are only valid "
if ((alt_grab || ctrl_grab) && dpy.type != DISPLAY_TYPE_SDL) {
error_report("-alt-grab and -ctrl-grab are only valid "
"for SDL, ignoring option");
}
if (dpy.has_window_close &&