UI patch queue
- vhost-user-gpu: support dmabuf modifiers - fix VNC crash when there are no active_console - cleanups and refactoring in ui/vc code -----BEGIN PGP SIGNATURE----- iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmUAQX4cHG1hcmNhbmRy ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5Y4jD/4/whR7a1KZqHytl6sc cCQ0Xn0gpcPM8rn3tWItp2vAOlGmx8ACfAyXYa5QzO7pBOU/xoMJt8a99geNRXFu nN33UJ0NRAWW6V0/cF5AVe9clckzs1Vq4VX2ITP+VAG+c+kt4E3fgFn9o8nwnBrd zuiqYz4pO9yBVO/av/FZQcBY8s9/M8jrdraDNNhsY2O2k2zLTxt1xxNG5qeVvPUw 2RZyc/EOG7RzW8eUA55BW/NU8Olg5u7dxsB0jfYnWBQxknOy5c+wF9MTGJSKmdGk HmgfMns6intUdfHmmJuDpP1Tiy1sVK1lkrsMeeQ67M84lYZsrSI+kIG5+YbWN8vx mMB/qwDmNMVMnGiBN5/ktvAJwcilYBUqen0KFrEHBghTpGhqAVoBNCC1MT/9w/bO c3/E1viuCi8OamPixVu9LeqQsxuP2jK5qxjfyDYH87HdnljSY6wFbVzD/2zz5YNv 43JtEbP9bv1yyRRd+JTpD54vCK0IZK7MBR8MbJqfknpbEw1FSPofRQxCSe9BlSJ/ nYamatH9I9i92kGg5eD573X+UcLX9eOPBw8gVNKxuttwSIW1cwjGKi12B9MiFMg7 Z6jP3gvpe9DrYef+4Wojo1PAioyweZVG5IFtWIqXRZjPwAoIzzVgBcEtcq4qeZwX BAliXWeUcRGsbLorT3COx2DjBw== =Xsr0 -----END PGP SIGNATURE----- Merge tag 'ui-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging UI patch queue - vhost-user-gpu: support dmabuf modifiers - fix VNC crash when there are no active_console - cleanups and refactoring in ui/vc code # -----BEGIN PGP SIGNATURE----- # # iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmUAQX4cHG1hcmNhbmRy # ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5Y4jD/4/whR7a1KZqHytl6sc # cCQ0Xn0gpcPM8rn3tWItp2vAOlGmx8ACfAyXYa5QzO7pBOU/xoMJt8a99geNRXFu # nN33UJ0NRAWW6V0/cF5AVe9clckzs1Vq4VX2ITP+VAG+c+kt4E3fgFn9o8nwnBrd # zuiqYz4pO9yBVO/av/FZQcBY8s9/M8jrdraDNNhsY2O2k2zLTxt1xxNG5qeVvPUw # 2RZyc/EOG7RzW8eUA55BW/NU8Olg5u7dxsB0jfYnWBQxknOy5c+wF9MTGJSKmdGk # HmgfMns6intUdfHmmJuDpP1Tiy1sVK1lkrsMeeQ67M84lYZsrSI+kIG5+YbWN8vx # mMB/qwDmNMVMnGiBN5/ktvAJwcilYBUqen0KFrEHBghTpGhqAVoBNCC1MT/9w/bO # c3/E1viuCi8OamPixVu9LeqQsxuP2jK5qxjfyDYH87HdnljSY6wFbVzD/2zz5YNv # 43JtEbP9bv1yyRRd+JTpD54vCK0IZK7MBR8MbJqfknpbEw1FSPofRQxCSe9BlSJ/ # nYamatH9I9i92kGg5eD573X+UcLX9eOPBw8gVNKxuttwSIW1cwjGKi12B9MiFMg7 # Z6jP3gvpe9DrYef+4Wojo1PAioyweZVG5IFtWIqXRZjPwAoIzzVgBcEtcq4qeZwX # BAliXWeUcRGsbLorT3COx2DjBw== # =Xsr0 # -----END PGP SIGNATURE----- # gpg: Signature made Tue 12 Sep 2023 06:46:22 EDT # gpg: using RSA key 87A9BD933F87C606D276F62DDAE8E10975969CE5 # gpg: issuer "marcandre.lureau@redhat.com" # gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" [full] # gpg: aka "Marc-André Lureau <marcandre.lureau@gmail.com>" [full] # Primary key fingerprint: 87A9 BD93 3F87 C606 D276 F62D DAE8 E109 7596 9CE5 * tag 'ui-pull-request' of https://gitlab.com/marcandre.lureau/qemu: ui: add precondition for dpy_get_ui_info() ui: fix crash when there are no active_console virtio-gpu/win32: set the destroy function on load ui/console: move DisplaySurface to its own header ui/vc: split off the VC part from console.c ui/vc: preliminary QemuTextConsole changes before split ui/console: remove redundant format field ui/vc: rename kbd_put to qemu_text_console functions ui/vc: remove kbd_put_keysym() and update function calls vmmouse: use explicit code vmmouse: replace DPRINTF with tracing vhost-user-gpu: support dmabuf modifiers contrib/vhost-user-gpu: add support for sending dmabuf modifiers docs: vhost-user-gpu: add protocol changes for dmabuf modifiers Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
7754c97179
@ -1071,6 +1071,7 @@ static gboolean
|
||||
protocol_features_cb(gint fd, GIOCondition condition, gpointer user_data)
|
||||
{
|
||||
const uint64_t protocol_edid = (1 << VHOST_USER_GPU_PROTOCOL_F_EDID);
|
||||
const uint64_t protocol_dmabuf2 = (1 << VHOST_USER_GPU_PROTOCOL_F_DMABUF2);
|
||||
VuGpu *g = user_data;
|
||||
uint64_t protocol_features;
|
||||
VhostUserGpuMsg msg = {
|
||||
@ -1082,7 +1083,7 @@ protocol_features_cb(gint fd, GIOCondition condition, gpointer user_data)
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
protocol_features &= protocol_edid;
|
||||
protocol_features &= (protocol_edid | protocol_dmabuf2);
|
||||
|
||||
msg = (VhostUserGpuMsg) {
|
||||
.request = VHOST_USER_GPU_SET_PROTOCOL_FEATURES,
|
||||
@ -1100,6 +1101,8 @@ protocol_features_cb(gint fd, GIOCondition condition, gpointer user_data)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
g->use_modifiers = !!(protocol_features & protocol_dmabuf2);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
|
@ -318,6 +318,37 @@ virgl_resource_detach_backing(VuGpu *g,
|
||||
vg_cleanup_mapping_iov(g, res_iovs, num_iovs);
|
||||
}
|
||||
|
||||
static int
|
||||
virgl_get_resource_info_modifiers(uint32_t resource_id,
|
||||
struct virgl_renderer_resource_info *info,
|
||||
uint64_t *modifiers)
|
||||
{
|
||||
int ret;
|
||||
#ifdef VIRGL_RENDERER_RESOURCE_INFO_EXT_VERSION
|
||||
struct virgl_renderer_resource_info_ext info_ext;
|
||||
ret = virgl_renderer_resource_get_info_ext(resource_id, &info_ext);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
*info = info_ext.base;
|
||||
*modifiers = info_ext.modifiers;
|
||||
#else
|
||||
ret = virgl_renderer_resource_get_info(resource_id, info);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Before virgl_renderer_resource_get_info_ext,
|
||||
* getting the modifiers was not possible.
|
||||
*/
|
||||
*modifiers = 0;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
virgl_cmd_set_scanout(VuGpu *g,
|
||||
struct virtio_gpu_ctrl_command *cmd)
|
||||
@ -338,7 +369,9 @@ virgl_cmd_set_scanout(VuGpu *g,
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
if (ss.resource_id && ss.r.width && ss.r.height) {
|
||||
ret = virgl_renderer_resource_get_info(ss.resource_id, &info);
|
||||
uint64_t modifiers = 0;
|
||||
ret = virgl_get_resource_info_modifiers(ss.resource_id, &info,
|
||||
&modifiers);
|
||||
if (ret == -1) {
|
||||
g_critical("%s: illegal resource specified %d\n",
|
||||
__func__, ss.resource_id);
|
||||
@ -354,8 +387,6 @@ virgl_cmd_set_scanout(VuGpu *g,
|
||||
}
|
||||
assert(fd >= 0);
|
||||
VhostUserGpuMsg msg = {
|
||||
.request = VHOST_USER_GPU_DMABUF_SCANOUT,
|
||||
.size = sizeof(VhostUserGpuDMABUFScanout),
|
||||
.payload.dmabuf_scanout.scanout_id = ss.scanout_id,
|
||||
.payload.dmabuf_scanout.x = ss.r.x,
|
||||
.payload.dmabuf_scanout.y = ss.r.y,
|
||||
@ -367,6 +398,20 @@ virgl_cmd_set_scanout(VuGpu *g,
|
||||
.payload.dmabuf_scanout.fd_flags = info.flags,
|
||||
.payload.dmabuf_scanout.fd_drm_fourcc = info.drm_fourcc
|
||||
};
|
||||
|
||||
if (g->use_modifiers) {
|
||||
/*
|
||||
* The mesage uses all the fields set in dmabuf_scanout plus
|
||||
* modifiers which is appended after VhostUserGpuDMABUFScanout.
|
||||
*/
|
||||
msg.request = VHOST_USER_GPU_DMABUF_SCANOUT2;
|
||||
msg.size = sizeof(VhostUserGpuDMABUFScanout2);
|
||||
msg.payload.dmabuf_scanout2.modifier = modifiers;
|
||||
} else {
|
||||
msg.request = VHOST_USER_GPU_DMABUF_SCANOUT;
|
||||
msg.size = sizeof(VhostUserGpuDMABUFScanout);
|
||||
}
|
||||
|
||||
vg_send_msg(g, &msg, fd);
|
||||
close(fd);
|
||||
} else {
|
||||
|
@ -37,6 +37,7 @@ typedef enum VhostUserGpuRequest {
|
||||
VHOST_USER_GPU_DMABUF_SCANOUT,
|
||||
VHOST_USER_GPU_DMABUF_UPDATE,
|
||||
VHOST_USER_GPU_GET_EDID,
|
||||
VHOST_USER_GPU_DMABUF_SCANOUT2,
|
||||
} VhostUserGpuRequest;
|
||||
|
||||
typedef struct VhostUserGpuDisplayInfoReply {
|
||||
@ -84,6 +85,11 @@ typedef struct VhostUserGpuDMABUFScanout {
|
||||
int fd_drm_fourcc;
|
||||
} QEMU_PACKED VhostUserGpuDMABUFScanout;
|
||||
|
||||
typedef struct VhostUserGpuDMABUFScanout2 {
|
||||
struct VhostUserGpuDMABUFScanout dmabuf_scanout;
|
||||
uint64_t modifier;
|
||||
} QEMU_PACKED VhostUserGpuDMABUFScanout2;
|
||||
|
||||
typedef struct VhostUserGpuEdidRequest {
|
||||
uint32_t scanout_id;
|
||||
} QEMU_PACKED VhostUserGpuEdidRequest;
|
||||
@ -98,6 +104,7 @@ typedef struct VhostUserGpuMsg {
|
||||
VhostUserGpuScanout scanout;
|
||||
VhostUserGpuUpdate update;
|
||||
VhostUserGpuDMABUFScanout dmabuf_scanout;
|
||||
VhostUserGpuDMABUFScanout2 dmabuf_scanout2;
|
||||
VhostUserGpuEdidRequest edid_req;
|
||||
struct virtio_gpu_resp_edid resp_edid;
|
||||
struct virtio_gpu_resp_display_info display_info;
|
||||
@ -112,6 +119,7 @@ static VhostUserGpuMsg m __attribute__ ((unused));
|
||||
#define VHOST_USER_GPU_MSG_FLAG_REPLY 0x4
|
||||
|
||||
#define VHOST_USER_GPU_PROTOCOL_F_EDID 0
|
||||
#define VHOST_USER_GPU_PROTOCOL_F_DMABUF2 1
|
||||
|
||||
struct virtio_gpu_scanout {
|
||||
uint32_t width, height;
|
||||
@ -132,6 +140,7 @@ typedef struct VuGpu {
|
||||
bool virgl;
|
||||
bool virgl_inited;
|
||||
bool edid_inited;
|
||||
bool use_modifiers;
|
||||
uint32_t inflight;
|
||||
|
||||
struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUTS];
|
||||
|
@ -134,6 +134,19 @@ VhostUserGpuEdidRequest
|
||||
:scanout-id: ``u32``, the scanout to get edid from
|
||||
|
||||
|
||||
VhostUserGpuDMABUFScanout2
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
+----------------+----------+
|
||||
| dmabuf_scanout | modifier |
|
||||
+----------------+----------+
|
||||
|
||||
:dmabuf_scanout: ``VhostUserGpuDMABUFScanout``, filled as described in the
|
||||
VhostUserGpuDMABUFScanout structure.
|
||||
|
||||
:modifier: ``u64``, the DMABUF modifiers
|
||||
|
||||
|
||||
C structure
|
||||
-----------
|
||||
|
||||
@ -163,7 +176,8 @@ Protocol features
|
||||
|
||||
.. code:: c
|
||||
|
||||
#define VHOST_USER_GPU_PROTOCOL_F_EDID 0
|
||||
#define VHOST_USER_GPU_PROTOCOL_F_EDID 0
|
||||
#define VHOST_USER_GPU_PROTOCOL_F_DMABUF2 1
|
||||
|
||||
New messages and communication changes are negotiated thanks to the
|
||||
``VHOST_USER_GPU_GET_PROTOCOL_FEATURES`` and
|
||||
@ -263,3 +277,13 @@ Message types
|
||||
Retrieve the EDID data for a given scanout.
|
||||
This message requires the ``VHOST_USER_GPU_PROTOCOL_F_EDID`` protocol
|
||||
feature to be supported.
|
||||
|
||||
``VHOST_USER_GPU_DMABUF_SCANOUT2``
|
||||
:id: 12
|
||||
:request payload: ``VhostUserGpuDMABUFScanout2``
|
||||
:reply payload: N/A
|
||||
|
||||
Same as VHOST_USER_GPU_DMABUF_SCANOUT, but also sends the dmabuf modifiers
|
||||
appended to the message, which were not provided in the other message.
|
||||
This message requires the ``VHOST_USER_GPU_PROTOCOL_F_DMABUF2`` protocol
|
||||
feature to be supported.
|
||||
|
@ -32,6 +32,7 @@ typedef enum VhostUserGpuRequest {
|
||||
VHOST_USER_GPU_DMABUF_SCANOUT,
|
||||
VHOST_USER_GPU_DMABUF_UPDATE,
|
||||
VHOST_USER_GPU_GET_EDID,
|
||||
VHOST_USER_GPU_DMABUF_SCANOUT2,
|
||||
} VhostUserGpuRequest;
|
||||
|
||||
typedef struct VhostUserGpuDisplayInfoReply {
|
||||
@ -79,6 +80,11 @@ typedef struct VhostUserGpuDMABUFScanout {
|
||||
int fd_drm_fourcc;
|
||||
} QEMU_PACKED VhostUserGpuDMABUFScanout;
|
||||
|
||||
typedef struct VhostUserGpuDMABUFScanout2 {
|
||||
struct VhostUserGpuDMABUFScanout dmabuf_scanout;
|
||||
uint64_t modifier;
|
||||
} QEMU_PACKED VhostUserGpuDMABUFScanout2;
|
||||
|
||||
typedef struct VhostUserGpuEdidRequest {
|
||||
uint32_t scanout_id;
|
||||
} QEMU_PACKED VhostUserGpuEdidRequest;
|
||||
@ -93,6 +99,7 @@ typedef struct VhostUserGpuMsg {
|
||||
VhostUserGpuScanout scanout;
|
||||
VhostUserGpuUpdate update;
|
||||
VhostUserGpuDMABUFScanout dmabuf_scanout;
|
||||
VhostUserGpuDMABUFScanout2 dmabuf_scanout2;
|
||||
VhostUserGpuEdidRequest edid_req;
|
||||
struct virtio_gpu_resp_edid resp_edid;
|
||||
struct virtio_gpu_resp_display_info display_info;
|
||||
@ -107,6 +114,7 @@ static VhostUserGpuMsg m __attribute__ ((unused));
|
||||
#define VHOST_USER_GPU_MSG_FLAG_REPLY 0x4
|
||||
|
||||
#define VHOST_USER_GPU_PROTOCOL_F_EDID 0
|
||||
#define VHOST_USER_GPU_PROTOCOL_F_DMABUF2 1
|
||||
|
||||
static void vhost_user_gpu_update_blocked(VhostUserGPU *g, bool blocked);
|
||||
|
||||
@ -171,7 +179,8 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg)
|
||||
.flags = VHOST_USER_GPU_MSG_FLAG_REPLY,
|
||||
.size = sizeof(uint64_t),
|
||||
.payload = {
|
||||
.u64 = (1 << VHOST_USER_GPU_PROTOCOL_F_EDID)
|
||||
.u64 = (1 << VHOST_USER_GPU_PROTOCOL_F_EDID) |
|
||||
(1 << VHOST_USER_GPU_PROTOCOL_F_DMABUF2)
|
||||
}
|
||||
};
|
||||
|
||||
@ -236,6 +245,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg)
|
||||
|
||||
break;
|
||||
}
|
||||
case VHOST_USER_GPU_DMABUF_SCANOUT2:
|
||||
case VHOST_USER_GPU_DMABUF_SCANOUT: {
|
||||
VhostUserGpuDMABUFScanout *m = &msg->payload.dmabuf_scanout;
|
||||
int fd = qemu_chr_fe_get_msgfd(&g->vhost_chr);
|
||||
@ -269,6 +279,11 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg)
|
||||
.fourcc = m->fd_drm_fourcc,
|
||||
.y0_top = m->fd_flags & VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP,
|
||||
};
|
||||
if (msg->request == VHOST_USER_GPU_DMABUF_SCANOUT2) {
|
||||
VhostUserGpuDMABUFScanout2 *m2 = &msg->payload.dmabuf_scanout2;
|
||||
dmabuf->modifier = m2->modifier;
|
||||
}
|
||||
|
||||
dpy_gl_scanout_dmabuf(con, dmabuf);
|
||||
break;
|
||||
}
|
||||
|
@ -1283,7 +1283,9 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size,
|
||||
g_free(res);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
pixman_image_set_destroy_function(res->image, win32_pixman_image_destroy, res->handle);
|
||||
#endif
|
||||
|
||||
res->addrs = g_new(uint64_t, res->iov_cnt);
|
||||
res->iov = g_new(struct iovec, res->iov_cnt);
|
||||
|
@ -121,3 +121,13 @@ x86_pic_interrupt(int irqn, int level) "PIC interrupt #%d level:%d"
|
||||
# port92.c
|
||||
port92_read(uint8_t val) "port92: read 0x%02x"
|
||||
port92_write(uint8_t val) "port92: write 0x%02x"
|
||||
|
||||
# vmmouse.c
|
||||
vmmouse_get_status(void) ""
|
||||
vmmouse_mouse_event(int x, int y, int dz, int buttons_state) "event: x=%d y=%d dz=%d state=%d"
|
||||
vmmouse_init(void) ""
|
||||
vmmouse_read_id(void) ""
|
||||
vmmouse_request_relative(void) ""
|
||||
vmmouse_request_absolute(void) ""
|
||||
vmmouse_disable(void) ""
|
||||
vmmouse_data(uint32_t size) "data: size=%" PRIu32
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include "cpu.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#include "trace.h"
|
||||
|
||||
/* debug only vmmouse */
|
||||
//#define DEBUG_VMMOUSE
|
||||
|
||||
@ -50,11 +52,10 @@
|
||||
#define VMMOUSE_RIGHT_BUTTON 0x10
|
||||
#define VMMOUSE_MIDDLE_BUTTON 0x08
|
||||
|
||||
#ifdef DEBUG_VMMOUSE
|
||||
#define DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
|
||||
#else
|
||||
#define DPRINTF(fmt, ...) do { } while (0)
|
||||
#endif
|
||||
#define VMMOUSE_MIN_X 0
|
||||
#define VMMOUSE_MIN_Y 0
|
||||
#define VMMOUSE_MAX_X 0xFFFF
|
||||
#define VMMOUSE_MAX_Y 0xFFFF
|
||||
|
||||
#define TYPE_VMMOUSE "vmmouse"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(VMMouseState, VMMOUSE)
|
||||
@ -93,7 +94,8 @@ static void vmmouse_set_data(const uint32_t *data)
|
||||
|
||||
static uint32_t vmmouse_get_status(VMMouseState *s)
|
||||
{
|
||||
DPRINTF("vmmouse_get_status()\n");
|
||||
trace_vmmouse_get_status();
|
||||
|
||||
return (s->status << 16) | s->nb_queue;
|
||||
}
|
||||
|
||||
@ -105,8 +107,7 @@ static void vmmouse_mouse_event(void *opaque, int x, int y, int dz, int buttons_
|
||||
if (s->nb_queue > (VMMOUSE_QUEUE_SIZE - 4))
|
||||
return;
|
||||
|
||||
DPRINTF("vmmouse_mouse_event(%d, %d, %d, %d)\n",
|
||||
x, y, dz, buttons_state);
|
||||
trace_vmmouse_mouse_event(x, y, dz, buttons_state);
|
||||
|
||||
if ((buttons_state & MOUSE_EVENT_LBUTTON))
|
||||
buttons |= VMMOUSE_LEFT_BUTTON;
|
||||
@ -116,8 +117,12 @@ static void vmmouse_mouse_event(void *opaque, int x, int y, int dz, int buttons_
|
||||
buttons |= VMMOUSE_MIDDLE_BUTTON;
|
||||
|
||||
if (s->absolute) {
|
||||
x <<= 1;
|
||||
y <<= 1;
|
||||
x = qemu_input_scale_axis(x,
|
||||
INPUT_EVENT_ABS_MIN, INPUT_EVENT_ABS_MAX,
|
||||
VMMOUSE_MIN_X, VMMOUSE_MAX_X);
|
||||
y = qemu_input_scale_axis(y,
|
||||
INPUT_EVENT_ABS_MIN, INPUT_EVENT_ABS_MAX,
|
||||
VMMOUSE_MIN_Y, VMMOUSE_MAX_Y);
|
||||
} else{
|
||||
/* add for guest vmmouse driver to judge this is a relative packet. */
|
||||
buttons |= VMMOUSE_RELATIVE_PACKET;
|
||||
@ -160,7 +165,7 @@ static void vmmouse_update_handler(VMMouseState *s, int absolute)
|
||||
|
||||
static void vmmouse_read_id(VMMouseState *s)
|
||||
{
|
||||
DPRINTF("vmmouse_read_id()\n");
|
||||
trace_vmmouse_read_id();
|
||||
|
||||
if (s->nb_queue == VMMOUSE_QUEUE_SIZE)
|
||||
return;
|
||||
@ -172,19 +177,22 @@ static void vmmouse_read_id(VMMouseState *s)
|
||||
|
||||
static void vmmouse_request_relative(VMMouseState *s)
|
||||
{
|
||||
DPRINTF("vmmouse_request_relative()\n");
|
||||
trace_vmmouse_request_relative();
|
||||
|
||||
vmmouse_update_handler(s, 0);
|
||||
}
|
||||
|
||||
static void vmmouse_request_absolute(VMMouseState *s)
|
||||
{
|
||||
DPRINTF("vmmouse_request_absolute()\n");
|
||||
trace_vmmouse_request_absolute();
|
||||
|
||||
vmmouse_update_handler(s, 1);
|
||||
}
|
||||
|
||||
static void vmmouse_disable(VMMouseState *s)
|
||||
{
|
||||
DPRINTF("vmmouse_disable()\n");
|
||||
trace_vmmouse_disable();
|
||||
|
||||
s->status = 0xffff;
|
||||
vmmouse_remove_handler(s);
|
||||
}
|
||||
@ -193,7 +201,7 @@ static void vmmouse_data(VMMouseState *s, uint32_t *data, uint32_t size)
|
||||
{
|
||||
int i;
|
||||
|
||||
DPRINTF("vmmouse_data(%d)\n", size);
|
||||
trace_vmmouse_data(size);
|
||||
|
||||
if (size == 0 || size > 6 || size > s->nb_queue) {
|
||||
printf("vmmouse: driver requested too much data %d\n", size);
|
||||
@ -293,7 +301,7 @@ static void vmmouse_realizefn(DeviceState *dev, Error **errp)
|
||||
{
|
||||
VMMouseState *s = VMMOUSE(dev);
|
||||
|
||||
DPRINTF("vmmouse_init\n");
|
||||
trace_vmmouse_init();
|
||||
|
||||
if (!s->i8042) {
|
||||
error_setg(errp, "'i8042' link is not set");
|
||||
|
@ -6,11 +6,7 @@
|
||||
#include "qemu/notify.h"
|
||||
#include "qapi/qapi-types-ui.h"
|
||||
#include "ui/input.h"
|
||||
|
||||
#ifdef CONFIG_OPENGL
|
||||
# include <epoxy/gl.h>
|
||||
# include "ui/shader.h"
|
||||
#endif
|
||||
#include "ui/surface.h"
|
||||
|
||||
#define TYPE_QEMU_CONSOLE "qemu-console"
|
||||
OBJECT_DECLARE_TYPE(QemuConsole, QemuConsoleClass, QEMU_CONSOLE)
|
||||
@ -112,10 +108,9 @@ bool qemu_mouse_set(int index, Error **errp);
|
||||
#define QEMU_KEY_CTRL_PAGEUP 0xe406
|
||||
#define QEMU_KEY_CTRL_PAGEDOWN 0xe407
|
||||
|
||||
void kbd_put_keysym_console(QemuTextConsole *s, int keysym);
|
||||
bool kbd_put_qcode_console(QemuTextConsole *s, int qcode, bool ctrl);
|
||||
void kbd_put_string_console(QemuTextConsole *s, const char *str, int len);
|
||||
void kbd_put_keysym(int keysym);
|
||||
void qemu_text_console_put_keysym(QemuTextConsole *s, int keysym);
|
||||
bool qemu_text_console_put_qcode(QemuTextConsole *s, int qcode, bool ctrl);
|
||||
void qemu_text_console_put_string(QemuTextConsole *s, const char *str, int len);
|
||||
|
||||
/* Touch devices */
|
||||
typedef struct touch_slot {
|
||||
@ -137,9 +132,6 @@ struct QemuConsoleClass {
|
||||
ObjectClass parent_class;
|
||||
};
|
||||
|
||||
#define QEMU_ALLOCATED_FLAG 0x01
|
||||
#define QEMU_PLACEHOLDER_FLAG 0x02
|
||||
|
||||
typedef struct ScanoutTexture {
|
||||
uint32_t backing_id;
|
||||
bool backing_y_0_top;
|
||||
@ -152,21 +144,6 @@ typedef struct ScanoutTexture {
|
||||
void *d3d_tex2d;
|
||||
} ScanoutTexture;
|
||||
|
||||
typedef struct DisplaySurface {
|
||||
pixman_format_code_t format;
|
||||
pixman_image_t *image;
|
||||
uint8_t flags;
|
||||
#ifdef CONFIG_OPENGL
|
||||
GLenum glformat;
|
||||
GLenum gltype;
|
||||
GLuint texture;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
HANDLE handle;
|
||||
uint32_t handle_offset;
|
||||
#endif
|
||||
} DisplaySurface;
|
||||
|
||||
typedef struct QemuUIInfo {
|
||||
/* physical dimension */
|
||||
uint16_t width_mm;
|
||||
@ -346,37 +323,13 @@ struct DisplayGLCtx {
|
||||
};
|
||||
|
||||
DisplayState *init_displaystate(void);
|
||||
DisplaySurface *qemu_create_displaysurface_from(int width, int height,
|
||||
pixman_format_code_t format,
|
||||
int linesize, uint8_t *data);
|
||||
DisplaySurface *qemu_create_displaysurface_pixman(pixman_image_t *image);
|
||||
DisplaySurface *qemu_create_placeholder_surface(int w, int h,
|
||||
const char *msg);
|
||||
#ifdef WIN32
|
||||
void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
|
||||
HANDLE h, uint32_t offset);
|
||||
#endif
|
||||
PixelFormat qemu_default_pixelformat(int bpp);
|
||||
|
||||
DisplaySurface *qemu_create_displaysurface(int width, int height);
|
||||
void qemu_free_displaysurface(DisplaySurface *surface);
|
||||
|
||||
static inline int is_buffer_shared(DisplaySurface *surface)
|
||||
{
|
||||
return !(surface->flags & QEMU_ALLOCATED_FLAG);
|
||||
}
|
||||
|
||||
static inline int is_placeholder(DisplaySurface *surface)
|
||||
{
|
||||
return surface->flags & QEMU_PLACEHOLDER_FLAG;
|
||||
}
|
||||
|
||||
void register_displaychangelistener(DisplayChangeListener *dcl);
|
||||
void update_displaychangelistener(DisplayChangeListener *dcl,
|
||||
uint64_t interval);
|
||||
void unregister_displaychangelistener(DisplayChangeListener *dcl);
|
||||
|
||||
bool dpy_ui_info_supported(QemuConsole *con);
|
||||
bool dpy_ui_info_supported(const QemuConsole *con);
|
||||
const QemuUIInfo *dpy_get_ui_info(const QemuConsole *con);
|
||||
int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info, bool delay);
|
||||
|
||||
@ -417,43 +370,6 @@ int dpy_gl_ctx_make_current(QemuConsole *con, QEMUGLContext ctx);
|
||||
|
||||
bool console_has_gl(QemuConsole *con);
|
||||
|
||||
static inline int surface_stride(DisplaySurface *s)
|
||||
{
|
||||
return pixman_image_get_stride(s->image);
|
||||
}
|
||||
|
||||
static inline void *surface_data(DisplaySurface *s)
|
||||
{
|
||||
return pixman_image_get_data(s->image);
|
||||
}
|
||||
|
||||
static inline int surface_width(DisplaySurface *s)
|
||||
{
|
||||
return pixman_image_get_width(s->image);
|
||||
}
|
||||
|
||||
static inline int surface_height(DisplaySurface *s)
|
||||
{
|
||||
return pixman_image_get_height(s->image);
|
||||
}
|
||||
|
||||
static inline int surface_bits_per_pixel(DisplaySurface *s)
|
||||
{
|
||||
int bits = PIXMAN_FORMAT_BPP(s->format);
|
||||
return bits;
|
||||
}
|
||||
|
||||
static inline int surface_bytes_per_pixel(DisplaySurface *s)
|
||||
{
|
||||
int bits = PIXMAN_FORMAT_BPP(s->format);
|
||||
return DIV_ROUND_UP(bits, 8);
|
||||
}
|
||||
|
||||
static inline pixman_format_code_t surface_format(DisplaySurface *s)
|
||||
{
|
||||
return s->format;
|
||||
}
|
||||
|
||||
typedef uint32_t console_ch_t;
|
||||
|
||||
static inline void console_write_ch(console_ch_t *dest, uint32_t ch)
|
||||
|
95
include/ui/surface.h
Normal file
95
include/ui/surface.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* QEMU UI Console
|
||||
*/
|
||||
#ifndef SURFACE_H
|
||||
#define SURFACE_H
|
||||
|
||||
#include "ui/qemu-pixman.h"
|
||||
|
||||
#ifdef CONFIG_OPENGL
|
||||
# include <epoxy/gl.h>
|
||||
# include "ui/shader.h"
|
||||
#endif
|
||||
|
||||
#define QEMU_ALLOCATED_FLAG 0x01
|
||||
#define QEMU_PLACEHOLDER_FLAG 0x02
|
||||
|
||||
typedef struct DisplaySurface {
|
||||
pixman_image_t *image;
|
||||
uint8_t flags;
|
||||
#ifdef CONFIG_OPENGL
|
||||
GLenum glformat;
|
||||
GLenum gltype;
|
||||
GLuint texture;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
HANDLE handle;
|
||||
uint32_t handle_offset;
|
||||
#endif
|
||||
} DisplaySurface;
|
||||
|
||||
PixelFormat qemu_default_pixelformat(int bpp);
|
||||
|
||||
DisplaySurface *qemu_create_displaysurface_from(int width, int height,
|
||||
pixman_format_code_t format,
|
||||
int linesize, uint8_t *data);
|
||||
DisplaySurface *qemu_create_displaysurface_pixman(pixman_image_t *image);
|
||||
DisplaySurface *qemu_create_placeholder_surface(int w, int h,
|
||||
const char *msg);
|
||||
#ifdef WIN32
|
||||
void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
|
||||
HANDLE h, uint32_t offset);
|
||||
#endif
|
||||
|
||||
DisplaySurface *qemu_create_displaysurface(int width, int height);
|
||||
void qemu_free_displaysurface(DisplaySurface *surface);
|
||||
|
||||
static inline int is_buffer_shared(DisplaySurface *surface)
|
||||
{
|
||||
return !(surface->flags & QEMU_ALLOCATED_FLAG);
|
||||
}
|
||||
|
||||
static inline int is_placeholder(DisplaySurface *surface)
|
||||
{
|
||||
return surface->flags & QEMU_PLACEHOLDER_FLAG;
|
||||
}
|
||||
|
||||
static inline int surface_stride(DisplaySurface *s)
|
||||
{
|
||||
return pixman_image_get_stride(s->image);
|
||||
}
|
||||
|
||||
static inline void *surface_data(DisplaySurface *s)
|
||||
{
|
||||
return pixman_image_get_data(s->image);
|
||||
}
|
||||
|
||||
static inline int surface_width(DisplaySurface *s)
|
||||
{
|
||||
return pixman_image_get_width(s->image);
|
||||
}
|
||||
|
||||
static inline int surface_height(DisplaySurface *s)
|
||||
{
|
||||
return pixman_image_get_height(s->image);
|
||||
}
|
||||
|
||||
static inline pixman_format_code_t surface_format(DisplaySurface *s)
|
||||
{
|
||||
return pixman_image_get_format(s->image);
|
||||
}
|
||||
|
||||
static inline int surface_bits_per_pixel(DisplaySurface *s)
|
||||
{
|
||||
int bits = PIXMAN_FORMAT_BPP(surface_format(s));
|
||||
return bits;
|
||||
}
|
||||
|
||||
static inline int surface_bytes_per_pixel(DisplaySurface *s)
|
||||
{
|
||||
int bits = PIXMAN_FORMAT_BPP(surface_format(s));
|
||||
return DIV_ROUND_UP(bits, 8);
|
||||
}
|
||||
|
||||
#endif
|
@ -784,7 +784,7 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven
|
||||
}
|
||||
|
||||
if (keysym) {
|
||||
kbd_put_keysym(keysym);
|
||||
qemu_text_console_put_keysym(NULL, keysym);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ void surface_gl_create_texture(QemuGLShader *gls,
|
||||
return;
|
||||
}
|
||||
|
||||
switch (surface->format) {
|
||||
switch (surface_format(surface)) {
|
||||
case PIXMAN_BE_b8g8r8x8:
|
||||
case PIXMAN_BE_b8g8r8a8:
|
||||
surface->glformat = GL_BGRA_EXT;
|
||||
|
43
ui/console-priv.h
Normal file
43
ui/console-priv.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* QEMU UI Console
|
||||
*/
|
||||
#ifndef CONSOLE_PRIV_H
|
||||
#define CONSOLE_PRIV_H
|
||||
|
||||
#include "ui/console.h"
|
||||
#include "qemu/coroutine.h"
|
||||
#include "qemu/timer.h"
|
||||
|
||||
#include "vgafont.h"
|
||||
|
||||
#define FONT_HEIGHT 16
|
||||
#define FONT_WIDTH 8
|
||||
|
||||
struct QemuConsole {
|
||||
Object parent;
|
||||
|
||||
int index;
|
||||
DisplayState *ds;
|
||||
DisplaySurface *surface;
|
||||
DisplayScanout scanout;
|
||||
int dcls;
|
||||
DisplayGLCtx *gl;
|
||||
int gl_block;
|
||||
QEMUTimer *gl_unblock_timer;
|
||||
int window_id;
|
||||
QemuUIInfo ui_info;
|
||||
QEMUTimer *ui_timer;
|
||||
const GraphicHwOps *hw_ops;
|
||||
void *hw;
|
||||
CoQueue dump_queue;
|
||||
|
||||
QTAILQ_ENTRY(QemuConsole) next;
|
||||
};
|
||||
|
||||
void qemu_text_console_select(QemuTextConsole *c);
|
||||
const char * qemu_text_console_get_label(QemuTextConsole *c);
|
||||
void qemu_text_console_update_cursor(void);
|
||||
void qemu_text_console_handle_keysym(QemuTextConsole *s, int keysym);
|
||||
|
||||
#endif
|
1079
ui/console-vc.c
Normal file
1079
ui/console-vc.c
Normal file
File diff suppressed because it is too large
Load Diff
1119
ui/console.c
1119
ui/console.c
File diff suppressed because it is too large
Load Diff
@ -400,7 +400,7 @@ static void curses_refresh(DisplayChangeListener *dcl)
|
||||
if (keysym == -1)
|
||||
keysym = chr;
|
||||
|
||||
kbd_put_keysym(keysym);
|
||||
qemu_text_console_put_keysym(NULL, keysym);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
8
ui/gtk.c
8
ui/gtk.c
@ -514,7 +514,7 @@ static void gd_switch(DisplayChangeListener *dcl,
|
||||
}
|
||||
vc->gfx.ds = surface;
|
||||
|
||||
if (surface->format == PIXMAN_x8r8g8b8) {
|
||||
if (surface_format(surface) == PIXMAN_x8r8g8b8) {
|
||||
/*
|
||||
* PIXMAN_x8r8g8b8 == CAIRO_FORMAT_RGB24
|
||||
*
|
||||
@ -1190,12 +1190,12 @@ static gboolean gd_text_key_down(GtkWidget *widget,
|
||||
QemuTextConsole *con = QEMU_TEXT_CONSOLE(vc->gfx.dcl.con);
|
||||
|
||||
if (key->keyval == GDK_KEY_Delete) {
|
||||
kbd_put_qcode_console(con, Q_KEY_CODE_DELETE, false);
|
||||
qemu_text_console_put_qcode(con, Q_KEY_CODE_DELETE, false);
|
||||
} else if (key->length) {
|
||||
kbd_put_string_console(con, key->string, key->length);
|
||||
qemu_text_console_put_string(con, key->string, key->length);
|
||||
} else {
|
||||
int qcode = gd_map_keycode(gd_get_keycode(key));
|
||||
kbd_put_qcode_console(con, qcode, false);
|
||||
qemu_text_console_put_qcode(con, qcode, false);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ system_ss.add(png)
|
||||
system_ss.add(files(
|
||||
'clipboard.c',
|
||||
'console.c',
|
||||
'console-vc.c',
|
||||
'cursor.c',
|
||||
'input-keymap.c',
|
||||
'input-legacy.c',
|
||||
|
@ -49,10 +49,10 @@ void sdl2_process_key(struct sdl2_console *scon,
|
||||
if (ev->type == SDL_KEYDOWN) {
|
||||
switch (qcode) {
|
||||
case Q_KEY_CODE_RET:
|
||||
kbd_put_keysym_console(s, '\n');
|
||||
qemu_text_console_put_keysym(s, '\n');
|
||||
break;
|
||||
default:
|
||||
kbd_put_qcode_console(s, qcode, ctrl);
|
||||
qemu_text_console_put_qcode(s, qcode, ctrl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -484,7 +484,7 @@ static void handle_textinput(SDL_Event *ev)
|
||||
}
|
||||
|
||||
if (QEMU_IS_TEXT_CONSOLE(con)) {
|
||||
kbd_put_string_console(QEMU_TEXT_CONSOLE(con), ev->text.text, strlen(ev->text.text));
|
||||
qemu_text_console_put_string(QEMU_TEXT_CONSOLE(con), ev->text.text, strlen(ev->text.text));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -437,7 +437,7 @@ void qemu_spice_display_switch(SimpleSpiceDisplay *ssd,
|
||||
}
|
||||
if (ssd->ds) {
|
||||
ssd->surface = pixman_image_ref(ssd->ds->image);
|
||||
ssd->mirror = qemu_pixman_mirror_create(ssd->ds->format,
|
||||
ssd->mirror = qemu_pixman_mirror_create(surface_format(ssd->ds),
|
||||
ssd->ds->image);
|
||||
qemu_spice_create_host_primary(ssd);
|
||||
}
|
||||
|
56
ui/vnc.c
56
ui/vnc.c
@ -833,7 +833,7 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl,
|
||||
/* guest surface */
|
||||
qemu_pixman_image_unref(vd->guest.fb);
|
||||
vd->guest.fb = pixman_image_ref(surface->image);
|
||||
vd->guest.format = surface->format;
|
||||
vd->guest.format = surface_format(surface);
|
||||
|
||||
|
||||
if (pageflip) {
|
||||
@ -1945,88 +1945,88 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
|
||||
case 0xb8: /* Right ALT */
|
||||
break;
|
||||
case 0xc8:
|
||||
kbd_put_keysym(QEMU_KEY_UP);
|
||||
qemu_text_console_put_keysym(NULL, QEMU_KEY_UP);
|
||||
break;
|
||||
case 0xd0:
|
||||
kbd_put_keysym(QEMU_KEY_DOWN);
|
||||
qemu_text_console_put_keysym(NULL, QEMU_KEY_DOWN);
|
||||
break;
|
||||
case 0xcb:
|
||||
kbd_put_keysym(QEMU_KEY_LEFT);
|
||||
qemu_text_console_put_keysym(NULL, QEMU_KEY_LEFT);
|
||||
break;
|
||||
case 0xcd:
|
||||
kbd_put_keysym(QEMU_KEY_RIGHT);
|
||||
qemu_text_console_put_keysym(NULL, QEMU_KEY_RIGHT);
|
||||
break;
|
||||
case 0xd3:
|
||||
kbd_put_keysym(QEMU_KEY_DELETE);
|
||||
qemu_text_console_put_keysym(NULL, QEMU_KEY_DELETE);
|
||||
break;
|
||||
case 0xc7:
|
||||
kbd_put_keysym(QEMU_KEY_HOME);
|
||||
qemu_text_console_put_keysym(NULL, QEMU_KEY_HOME);
|
||||
break;
|
||||
case 0xcf:
|
||||
kbd_put_keysym(QEMU_KEY_END);
|
||||
qemu_text_console_put_keysym(NULL, QEMU_KEY_END);
|
||||
break;
|
||||
case 0xc9:
|
||||
kbd_put_keysym(QEMU_KEY_PAGEUP);
|
||||
qemu_text_console_put_keysym(NULL, QEMU_KEY_PAGEUP);
|
||||
break;
|
||||
case 0xd1:
|
||||
kbd_put_keysym(QEMU_KEY_PAGEDOWN);
|
||||
qemu_text_console_put_keysym(NULL, QEMU_KEY_PAGEDOWN);
|
||||
break;
|
||||
|
||||
case 0x47:
|
||||
kbd_put_keysym(numlock ? '7' : QEMU_KEY_HOME);
|
||||
qemu_text_console_put_keysym(NULL, numlock ? '7' : QEMU_KEY_HOME);
|
||||
break;
|
||||
case 0x48:
|
||||
kbd_put_keysym(numlock ? '8' : QEMU_KEY_UP);
|
||||
qemu_text_console_put_keysym(NULL, numlock ? '8' : QEMU_KEY_UP);
|
||||
break;
|
||||
case 0x49:
|
||||
kbd_put_keysym(numlock ? '9' : QEMU_KEY_PAGEUP);
|
||||
qemu_text_console_put_keysym(NULL, numlock ? '9' : QEMU_KEY_PAGEUP);
|
||||
break;
|
||||
case 0x4b:
|
||||
kbd_put_keysym(numlock ? '4' : QEMU_KEY_LEFT);
|
||||
qemu_text_console_put_keysym(NULL, numlock ? '4' : QEMU_KEY_LEFT);
|
||||
break;
|
||||
case 0x4c:
|
||||
kbd_put_keysym('5');
|
||||
qemu_text_console_put_keysym(NULL, '5');
|
||||
break;
|
||||
case 0x4d:
|
||||
kbd_put_keysym(numlock ? '6' : QEMU_KEY_RIGHT);
|
||||
qemu_text_console_put_keysym(NULL, numlock ? '6' : QEMU_KEY_RIGHT);
|
||||
break;
|
||||
case 0x4f:
|
||||
kbd_put_keysym(numlock ? '1' : QEMU_KEY_END);
|
||||
qemu_text_console_put_keysym(NULL, numlock ? '1' : QEMU_KEY_END);
|
||||
break;
|
||||
case 0x50:
|
||||
kbd_put_keysym(numlock ? '2' : QEMU_KEY_DOWN);
|
||||
qemu_text_console_put_keysym(NULL, numlock ? '2' : QEMU_KEY_DOWN);
|
||||
break;
|
||||
case 0x51:
|
||||
kbd_put_keysym(numlock ? '3' : QEMU_KEY_PAGEDOWN);
|
||||
qemu_text_console_put_keysym(NULL, numlock ? '3' : QEMU_KEY_PAGEDOWN);
|
||||
break;
|
||||
case 0x52:
|
||||
kbd_put_keysym('0');
|
||||
qemu_text_console_put_keysym(NULL, '0');
|
||||
break;
|
||||
case 0x53:
|
||||
kbd_put_keysym(numlock ? '.' : QEMU_KEY_DELETE);
|
||||
qemu_text_console_put_keysym(NULL, numlock ? '.' : QEMU_KEY_DELETE);
|
||||
break;
|
||||
|
||||
case 0xb5:
|
||||
kbd_put_keysym('/');
|
||||
qemu_text_console_put_keysym(NULL, '/');
|
||||
break;
|
||||
case 0x37:
|
||||
kbd_put_keysym('*');
|
||||
qemu_text_console_put_keysym(NULL, '*');
|
||||
break;
|
||||
case 0x4a:
|
||||
kbd_put_keysym('-');
|
||||
qemu_text_console_put_keysym(NULL, '-');
|
||||
break;
|
||||
case 0x4e:
|
||||
kbd_put_keysym('+');
|
||||
qemu_text_console_put_keysym(NULL, '+');
|
||||
break;
|
||||
case 0x9c:
|
||||
kbd_put_keysym('\n');
|
||||
qemu_text_console_put_keysym(NULL, '\n');
|
||||
break;
|
||||
|
||||
default:
|
||||
if (control) {
|
||||
kbd_put_keysym(sym & 0x1f);
|
||||
qemu_text_console_put_keysym(NULL, sym & 0x1f);
|
||||
} else {
|
||||
kbd_put_keysym(sym);
|
||||
qemu_text_console_put_keysym(NULL, sym);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user