UI patches
Subsystems (5)
From: Marc-André Lureau <[email protected]>
The following changes since commit 759c456b1d22fe4083c8b384da27d3f56fd53f82:
Merge tag 'linux-user-next-pull-request' of https://github.com/hdeller/qemu-hppa into staging (2026-04-27 12:57:33 -0400)
are available in the Git repository at:
https://gitlab.com/marcandre.lureau/qemu.git tags/ui-pull-request
for you to fetch changes up to 335e32cbd0a24f13e326d96dd30318cd78740c60:
ui/gtk: Turn clipboard flag into runtime option (2026-04-28 18:53:59 +0400)
----------------------------------------------------------------
UI-related fixes and cleanups
----------------------------------------------------------------
Akihiko Odaki (3):
audio: Avoid unsigned sample wraparound
audio: Clamp unsigned sample conversion
audio: Use unsigned PCM bias
Jindřich Makovička (2):
ui/gtk: Use non-blocking clipboard retrieval
ui/gtk: Turn clipboard flag into runtime option
Marc-André Lureau (10):
ui: move FONT_WIDTH/HEIGHT to vgafont.h
ui: move DisplaySurface functions to display-surface.c
ui: make qemu_default_pixelformat() static inline
ui: make unregister_displaychangelistener() skip unregistered
ui: minor code simplification
ui: rename init_keyboard_layout->kbd_layout_new() ui/console: remove qemu_console_is_visible() ui/console: return completion status from gfx_update callback ui/console: move console_handle_touch_event() to input ui/dbus: fix warning for clients without "Interfaces" property
meson.build | 4 - qapi/ui.json | 6 +- audio/mixeng_template.h | 14 +-- hw/display/qxl.h | 2 +- include/ui/console.h | 26 ++--- include/ui/input.h | 15 +++ include/ui/qemu-pixman.h | 8 ++ include/ui/surface.h | 2 - ui/console-priv.h | 6 - ui/keymaps.h | 4 +- ui/vgafont.h | 6 +- hw/arm/musicpal.c | 3 +- hw/display/artist.c | 4 +- hw/display/bcm2835_fb.c | 7 +- hw/display/bochs-display.c | 6 +- hw/display/cg3.c | 5 +- hw/display/dm163.c | 4 +- hw/display/exynos4210_fimd.c | 6 +- hw/display/g364fb.c | 9 +- hw/display/imx6ul_lcdif.c | 7 +- hw/display/jazz_led.c | 6 +- hw/display/macfb.c | 6 +- hw/display/next-fb.c | 4 +- hw/display/omap_lcdc.c | 14 ++- hw/display/pl110.c | 5 +- hw/display/qxl-render.c | 6 +- hw/display/qxl.c | 7 +- hw/display/ramfb-standalone.c | 4 +- hw/display/sm501.c | 8 +- hw/display/ssd0303.c | 10 +- hw/display/ssd0323.c | 11 +- hw/display/tcx.c | 6 +- hw/display/vga.c | 4 +- hw/display/virtio-gpu-base.c | 3 +- hw/display/virtio-vga.c | 6 +- hw/display/vmware_vga.c | 7 +- hw/display/xenfb.c | 6 +- hw/display/xlnx_dp.c | 10 +- hw/vfio/display.c | 17 +-- ui/console-vc.c | 1 + ui/console.c | 206 +--------------------------------- ui/curses.c | 4 +- ui/dbus-console.c | 6 +- ui/dbus-listener.c | 4 +- ui/display-surface.c | 107 ++++++++++++++++++ ui/gtk-clipboard.c | 53 ++++++--- ui/gtk.c | 16 +-- ui/input-barrier.c | 4 +- ui/input.c | 65 +++++++++++ ui/keymaps.c | 4 +- ui/sdl2.c | 8 +- ui/vnc.c | 12 +- hw/display/apple-gfx.m | 10 +- meson_options.txt | 7 -- qemu-options.hx | 9 +- scripts/meson-buildoptions.sh | 3 - ui/meson.build | 5 +- 57 files changed, 428 insertions(+), 380 deletions(-) create mode 100644 ui/display-surface.c
Signature · 1 line
2.54.0
[PULL v2 02/15] ui: move DisplaySurface functions to display-surface.c
From: Marc-André Lureau <[email protected]>
Extract DisplaySurface creation and destruction functions from console.c into their own file to reduce the size of console.c and improve code organization.
--- ui/console.c | 96 -------------------------------------- ui/display-surface.c | 107 +++++++++++++++++++++++++++++++++++++++++++ ui/meson.build | 1 + 3 files changed, 108 insertions(+), 96 deletions(-) create mode 100644 ui/display-surface.c
ui/console.c +0 -96
@@ -505,102 +505,6 @@ qemu_graphic_console_init(Object *obj) { } -void qemu_displaysurface_set_share_handle (DisplaySurface *surface, -qemu_pixman_shareable handle, -uint32_t offset) -{ -assert (surface->share_handle ==SHAREABLE_NONE ); - - surface->share_handle = handle; - surface->share_handle_offset = offset; - -} - -DisplaySurface *qemu_create_displaysurface (int width,int height) -{ -trace_displaysurface_create (width, height); - -return qemu_create_displaysurface_from ( - width, height, - PIXMAN_x8r8g8b8, - width *4 ,NULL - ); -} - -DisplaySurface *qemu_create_displaysurface_from (int width,int height, -pixman_format_code_t format, -int linesize,uint8_t *data) -{ -DisplaySurface *surface =g_new0 (DisplaySurface,1 ); - -trace_displaysurface_create_from (surface, width, height, format); - surface->share_handle =SHAREABLE_NONE ; - -if (data) { - surface->image =pixman_image_create_bits (format, - width, height, - (void *)data, linesize); - }else { -qemu_pixman_image_new_shareable (&surface->image, - &surface->share_handle, -"displaysurface" , - format, - width, - height, - linesize, - &error_abort); - surface->flags =QEMU_ALLOCATED_FLAG ; - } - -assert (surface->image !=NULL ); -return surface; -} - -DisplaySurface *qemu_create_displaysurface_pixman (pixman_image_t *image) -{ -DisplaySurface *surface =g_new0 (DisplaySurface,1 ); - -trace_displaysurface_create_pixman (surface); - surface->share_handle =SHAREABLE_NONE ; - surface->image =pixman_image_ref (image); - -return surface; -} - -DisplaySurface *qemu_create_placeholder_surface (int w,int h, -const char *msg) -{ -DisplaySurface *surface =qemu_create_displaysurface (w, h); -#ifdef CONFIG_PIXMAN -pixman_color_t bg =QEMU_PIXMAN_COLOR_BLACK ; -pixman_color_t fg =QEMU_PIXMAN_COLOR_GRAY ; -pixman_image_t *glyph; -int len, x, y, i; - - len =strlen (msg); - x = (w /FONT_WIDTH - len) /2 ; - y = (h /FONT_HEIGHT -1 ) /2 ; -for (i =0 ; i < len; i++) { - glyph =qemu_pixman_glyph_from_vgafont (FONT_HEIGHT , vgafont16, msg[i]); -qemu_pixman_glyph_render (glyph, surface->image, &fg, &bg, - x+i, y,FONT_WIDTH ,FONT_HEIGHT ); -qemu_pixman_image_unref (glyph); - } -#endif - surface->flags |=QEMU_PLACEHOLDER_FLAG ; -return surface; -} - -void qemu_free_displaysurface (DisplaySurface *surface) -{ -if (surface ==NULL ) { -return ; - } -trace_displaysurface_free (surface); -qemu_pixman_image_unref (surface->image); -g_free (surface); -} -bool console_has_gl (QemuConsole *con) {return con->gl !=NULL ;
ui/display-surface.c new file +107 -0
107 lines not on this page · raw message
ui/meson.build +1 -0
@@ -4,6 +4,7 @@ system_ss.add(files( 'clipboard.c', 'console.c', 'cursor.c', + 'display-surface.c', 'dmabuf.c', 'input-keymap.c', 'input-legacy.c',
Signature · 1 line
2.54.0
[PULL v2 01/15] ui: move FONT_WIDTH/HEIGHT to vgafont.h
In reply to [email protected]From: Marc-André Lureau <[email protected]>
Since those values are related to the VGA font, it make sense to move them here.
--- ui/console-priv.h | 5 ----- ui/vgafont.h | 6 +++++- ui/console-vc.c | 1 + ui/console.c | 1 + 4 files changed, 7 insertions(+), 6 deletions(-)
ui/console-priv.h +0 -5
@@ -9,11 +9,6 @@#include "qemu/coroutine.h" #include "qemu/timer.h" -#include "vgafont.h" - -#define FONT_HEIGHT 16 -#define FONT_WIDTH 8 -struct QemuConsole {Object parent;
ui/vgafont.h +5 -1
@@ -6,6 +6,10 @@#include <stdint.h> -extern const uint8_t vgafont16[256 *16 ]; +/* supports only vga 8x16 */ +#define FONT_WIDTH 8 +#define FONT_HEIGHT 16 + +extern const uint8_t vgafont16[256 *FONT_HEIGHT ];#endif
ui/console-vc.c +1 -0
@@ -10,6 +10,7 @@#include "qemu/option.h" #include "qemu/queue.h" #include "ui/console.h" +#include "ui/vgafont.h" #include "pixman.h" #include "trace.h"
ui/console.c +1 -0
@@ -24,6 +24,7 @@#include "qemu/osdep.h" #include "ui/console.h" +#include "ui/vgafont.h" #include "hw/core/qdev.h" #include "qapi/error.h" #include "qapi/qapi-commands-ui.h"
Signature · 1 line
2.54.0
[PULL v2 04/15] ui: make unregister_displaychangelistener() skip unregistered
In reply to [email protected]From: Marc-André Lureau <[email protected]>
If the listener doesn't have associate ds / display state, it is already unregistered.
--- ui/console.c | 3 +++ 1 file changed, 3 insertions(+)
ui/console.c +3 -0
@@ -675,6 +675,9 @@ void unregister_displaychangelistener(DisplayChangeListener *dcl) {DisplayState *ds = dcl->ds;trace_displaychangelistener_unregister (dcl, dcl->ops->dpy_name); +if (!ds) { +return ; + }if (dcl->con) { dcl->con->dcls--; }
Signature · 1 line
2.54.0
[PULL v2 05/15] ui: minor code simplification
In reply to [email protected]From: Marc-André Lureau <[email protected]>
Drop memset() usage.
--- ui/sdl2.c | 8 ++++---- ui/vnc.c | 6 ++---- 2 files changed, 6 insertions(+), 8 deletions(-)
ui/sdl2.c +4 -4
@@ -600,10 +600,10 @@ static void handle_windowevent(SDL_Event *ev)switch (ev->window.event) {case SDL_WINDOWEVENT_RESIZED : { -QemuUIInfo info; -memset (&info,0 ,sizeof (info)); - info.width = ev->window.data1; - info.height = ev->window.data2; +QemuUIInfo info = { + .width = ev->window.data1, + .height = ev->window.data2, + };dpy_set_ui_info (scon->dcl.con, &info, true); }sdl2_redraw (scon);
ui/vnc.c +2 -4
@@ -43,6 +43,7 @@#include "qapi/qapi-events-ui.h" #include "qapi/error.h" #include "qapi/qapi-commands-ui.h" +#include "ui/console.h" #include "ui/input.h" #include "crypto/hash.h" #include "crypto/tlscreds.h"
@@ -2639,10 +2640,7 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)trace_vnc_msg_client_set_desktop_size (vs, vs->ioc, w, h, screens);if (dpy_ui_info_supported (vs->vd->dcl.con)) { -QemuUIInfo info; -memset (&info,0 ,sizeof (info)); - info.width = w; - info.height = h; +QemuUIInfo info = { .width = w, .height = h };dpy_set_ui_info (vs->vd->dcl.con, &info, false);vnc_desktop_resize_ext (vs,4 /* Request forwarded */ ); }else {
Signature · 1 line
2.54.0
[PULL v2 08/15] ui/console: return completion status from gfx_update callback
In reply to [email protected]From: Marc-André Lureau <[email protected]>
Replace the two-field design (gfx_update void callback + gfx_update_async flag) with a single bool return value from gfx_update. Returning true means the update completed synchronously and graphic_hw_update_done() should be called by the console layer. Returning false means the update is deferred and the device will call graphic_hw_update_done() itself later (as done by QXL/SPICE and Apple GFX).
This simplifies the interface and makes the async contract explicit at each call site rather than relying on a separate struct field.
--- hw/display/qxl.h | 2 +- include/ui/console.h | 11 ++++++++--- hw/arm/musicpal.c | 3 ++- hw/display/artist.c | 4 +++- hw/display/bcm2835_fb.c | 7 ++++--- hw/display/bochs-display.c | 6 ++++-- hw/display/cg3.c | 5 +++-- hw/display/dm163.c | 4 +++- hw/display/exynos4210_fimd.c | 6 ++++-- hw/display/g364fb.c | 9 ++++++--- hw/display/imx6ul_lcdif.c | 7 ++++--- hw/display/jazz_led.c | 6 ++++-- hw/display/macfb.c | 6 ++++-- hw/display/next-fb.c | 4 +++- hw/display/omap_lcdc.c | 14 ++++++++------ hw/display/pl110.c | 5 +++-- hw/display/qxl-render.c | 6 +++--- hw/display/qxl.c | 7 +++---- hw/display/ramfb-standalone.c | 4 +++- hw/display/sm501.c | 8 +++++--- hw/display/ssd0303.c | 10 ++++++---- hw/display/ssd0323.c | 11 ++++++----- hw/display/tcx.c | 6 ++++-- hw/display/vga.c | 4 +++- hw/display/virtio-gpu-base.c | 3 ++- hw/display/virtio-vga.c | 6 +++--- hw/display/vmware_vga.c | 7 ++++--- hw/display/xenfb.c | 6 ++++-- hw/display/xlnx_dp.c | 10 ++++++---- hw/vfio/display.c | 17 ++++++++++------- ui/console.c | 7 +------ hw/display/apple-gfx.m | 10 +++++----- 32 files changed, 132 insertions(+), 89 deletions(-)
hw/display/qxl.h +1 -1
@@ -187,7 +187,7 @@ int qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext);/* qxl-render.c */ void qxl_render_resize (PCIQXLDevice *qxl); -void qxl_render_update (PCIQXLDevice *qxl); +bool qxl_render_update (PCIQXLDevice *qxl);int qxl_render_cursor (PCIQXLDevice *qxl,QXLCommandExt *ext);void qxl_render_update_area_done (PCIQXLDevice *qxl,QXLCookie *cookie);void qxl_render_update_area_bh (void *opaque);
include/ui/console.h +8 -3
@@ -368,9 +368,14 @@ enum {typedef struct GraphicHwOps {int (*get_flags)(void *opaque);/* optional, default 0 */ void (*invalidate)(void *opaque); -void (*gfx_update)(void *opaque); -bool gfx_update_async;/* if true, calls graphic_hw_update_done() */ -void (*text_update)(void *opaque,console_ch_t *text); +/* +* Returns true if the update is handled synchronously, false if deferred +* and graphic_hw_update_done() will be called when ready (to resume waiting +* tasks/coroutines). +* Optional. +*/ +bool (*gfx_update)(void *opaque); +void (*text_update)(void *opaque,uint32_t *text);void (*ui_info)(void *opaque,uint32_t head,QemuUIInfo *info);void (*gl_block)(void *opaque,bool block); }GraphicHwOps ;
hw/arm/musicpal.c +2 -1
@@ -152,7 +152,7 @@ static inline void set_lcd_pixel32(musicpal_lcd_state *s, } } -static void lcd_refresh (void *opaque) +static bool lcd_refresh (void *opaque) {musicpal_lcd_state *s = opaque;int x, y, col;
@@ -171,6 +171,7 @@ static void lcd_refresh(void *opaque) }dpy_gfx_update (s->con,0 ,0 ,128 *3 ,64 *3 ); +return true; }static void lcd_invalidate (void *opaque)
hw/display/artist.c +3 -1
@@ -1311,7 +1311,7 @@ static void artist_draw_line(void *opaque, uint8_t *d, const uint8_t *src, } } -static void artist_update_display (void *opaque) +static bool artist_update_display (void *opaque) {ARTISTState *s = opaque;DisplaySurface *surface =qemu_console_surface (s->con);
@@ -1326,6 +1326,8 @@ static void artist_update_display(void *opaque)if (first >=0 ) {dpy_gfx_update (s->con,0 , first, s->width, last - first +1 ); } + +return true; }static void artist_invalidate (void *opaque)
hw/display/bcm2835_fb.c +4 -3
@@ -150,7 +150,7 @@ static bool fb_use_offsets(BCM2835FBConfig *config) config->yres_virtual > config->yres; } -static void fb_update_display (void *opaque) +static bool fb_update_display (void *opaque) {BCM2835FBState *s = opaque;DisplaySurface *surface =qemu_console_surface (s->con);
@@ -161,7 +161,7 @@ static void fb_update_display(void *opaque)uint32_t xoff =0 , yoff =0 ;if (s->lock || !s->config.xres) { -return ; +return true; } src_width =bcm2835_fb_get_pitch (&s->config);
@@ -174,7 +174,7 @@ static void fb_update_display(void *opaque)switch (surface_bits_per_pixel (surface)) {case 0 : -return ; +return true;case 8 :break ;case 15 :
@@ -212,6 +212,7 @@ static void fb_update_display(void *opaque) } s->invalidate = false; +return true; }void bcm2835_fb_validate_config (BCM2835FBConfig *config)
hw/display/bochs-display.c +4 -2
@@ -198,7 +198,7 @@ static int bochs_display_get_mode(BochsDisplayState *s,return 0 ; } -static void bochs_display_update (void *opaque) +static bool bochs_display_update (void *opaque) {BochsDisplayState *s = opaque;DirtyBitmapSnapshot *snap =NULL ;
@@ -212,7 +212,7 @@ static void bochs_display_update(void *opaque) ret =bochs_display_get_mode (s, &mode);if (ret <0 ) {/* no (valid) video mode */ -return ; +return true; }if (memcmp (&s->mode, &mode,sizeof (mode)) !=0 ) {
@@ -255,6 +255,8 @@ static void bochs_display_update(void *opaque)g_free (snap); } + +return true; }static const GraphicHwOps bochs_display_gfx_ops = {
hw/display/cg3.c +3 -2
@@ -85,7 +85,7 @@ struct CG3State {uint8_t dac_index, dac_state; }; -static void cg3_update_display (void *opaque) +static bool cg3_update_display (void *opaque) {CG3State *s = opaque;DisplaySurface *surface =qemu_console_surface (s->con);
@@ -98,7 +98,7 @@ static void cg3_update_display(void *opaque)DirtyBitmapSnapshot *snap =NULL ;if (surface_bits_per_pixel (surface) !=32 ) { -return ; +return true; } width = s->width; height = s->height;
@@ -154,6 +154,7 @@ static void cg3_update_display(void *opaque)qemu_irq_raise (s->irq); }g_free (snap); +return true; }static void cg3_invalidate_display (void *opaque)
hw/display/dm163.c +3 -1
@@ -285,7 +285,7 @@ static uint32_t *update_display_of_row(DM163State *s, uint32_t *dest,return dest; } -static void dm163_update_display (void *opaque) +static bool dm163_update_display (void *opaque) {DM163State *s = (DM163State *)opaque;DisplaySurface *surface =qemu_console_surface (s->console);
@@ -300,6 +300,8 @@ static void dm163_update_display(void *opaque) } dest =update_display_of_row (s, dest, row); } + +return true; }static const GraphicHwOps dm163_ops = {
hw/display/exynos4210_fimd.c +4 -2
@@ -1270,7 +1270,7 @@ static void exynos4210_update_resolution(Exynos4210fimdState *s) } } -static void exynos4210_fimd_update (void *opaque) +static bool exynos4210_fimd_update (void *opaque) {Exynos4210fimdState *s = (Exynos4210fimdState *)opaque;DisplaySurface *surface;
@@ -1287,7 +1287,7 @@ static void exynos4210_fimd_update(void *opaque)if (!s || !s->console || !s->enabled ||surface_bits_per_pixel (qemu_console_surface (s->console)) ==0 ) { -return ; +return true; } global_width = (s->vidtcon[2 ] &FIMD_VIDTCON2_SIZE_MASK ) +1 ;
@@ -1348,6 +1348,8 @@ static void exynos4210_fimd_update(void *opaque)exynos4210_fimd_enable (s, false); }exynos4210_fimd_update_irq (s); + +return true; }static void exynos4210_fimd_reset (DeviceState *d)
hw/display/g364fb.c +6 -3
@@ -238,15 +238,16 @@ static void g364fb_draw_blank(G364State *s) s->blanked =1 ; } -static void g364fb_update_display (void *opaque) +static bool g364fb_update_display (void *opaque) {G364State *s = opaque;DisplaySurface *surface =qemu_console_surface (s->con);qemu_flush_coalesced_mmio_buffer (); -if (s->width ==0 || s->height ==0 ) -return ; +if (s->width ==0 || s->height ==0 ) { +return true; + }if (s->width !=surface_width (surface) || s->height !=surface_height (surface)) {
@@ -262,6 +263,8 @@ static void g364fb_update_display(void *opaque) }qemu_irq_raise (s->irq); + +return true; }static inline void g364fb_invalidate_display (void *opaque)
hw/display/imx6ul_lcdif.c +4 -3
@@ -152,7 +152,7 @@ static void imx6ul_lcdif_draw_line_xrgb8888(void *opaque, uint8_t *dst, } } -static void imx6ul_lcdif_update_display (void *opaque) +static bool imx6ul_lcdif_update_display (void *opaque) {IMX6ULLCDIFState *s = opaque;DisplaySurface *surface =qemu_console_surface (s->con);
@@ -167,7 +167,7 @@ static void imx6ul_lcdif_update_display(void *opaque)int src_width;if (!imx6ul_lcdif_is_running (s) || width ==0 || height ==0 ) { -return ; +return true; }switch (FIELD_EX32 (ctrl,CTRL ,WORD_LENGTH )) {
@@ -180,7 +180,7 @@ static void imx6ul_lcdif_update_display(void *opaque) fn = imx6ul_lcdif_draw_line_xrgb8888;break ;default : -return ; +return true; }if (surface_width (surface) != width ||surface_height (surface) != height) {
@@ -207,6 +207,7 @@ static void imx6ul_lcdif_update_display(void *opaque) } s->invalidate = false; +return true; }static void imx6ul_lcdif_invalidate_display (void *opaque)
hw/display/jazz_led.c +4 -2
@@ -144,7 +144,7 @@ static void draw_vertical_line(DisplaySurface *ds, } } -static void jazz_led_update_display (void *opaque) +static bool jazz_led_update_display (void *opaque) {LedState *s = opaque;DisplaySurface *surface =qemu_console_surface (s->con);
@@ -186,7 +186,7 @@ static void jazz_led_update_display(void *opaque) color_led =rgb_to_pixel32 (0x00 ,0xff ,0x00 );break ;default : -return ; +return true; }/* display segments */
@@ -218,6 +218,8 @@ static void jazz_led_update_display(void *opaque) s->state =REDRAW_NONE ;dpy_gfx_update_full (s->con); + +return true; }static void jazz_led_invalidate_display (void *opaque)
hw/display/macfb.c +4 -2
@@ -454,7 +454,7 @@ static gchar *macfb_mode_list(void) } -static void macfb_update_display (void *opaque) +static bool macfb_update_display (void *opaque) {MacfbState *s = opaque;DisplaySurface *surface =qemu_console_surface (s->con);
@@ -462,7 +462,7 @@ static void macfb_update_display(void *opaque)qemu_flush_coalesced_mmio_buffer ();if (s->width ==0 || s->height ==0 ) { -return ; +return true; } if (s->width != surface_width(surface) ||
@@ -471,6 +471,8 @@ static void macfb_update_display(void *opaque) }macfb_draw_graphic (s); + +return true; }static void macfb_update_irq (MacfbState *s)
hw/display/next-fb.c +3 -1
@@ -67,7 +67,7 @@ static void nextfb_draw_line(void *opaque, uint8_t *d, const uint8_t *s, } } -static void nextfb_update (void *opaque) +static bool nextfb_update (void *opaque) {NeXTFbState *s =NEXTFB (opaque);int dest_width =4 ;
@@ -90,6 +90,8 @@ static void nextfb_update(void *opaque) s, &first, &last);dpy_gfx_update (s->con,0 ,0 , s->cols, s->rows); + +return true; }static void nextfb_invalidate (void *opaque)
hw/display/omap_lcdc.c +8 -6
@@ -197,7 +197,7 @@ static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s, }while (-- width !=0 ); } -static void omap_update_display (void *opaque) +static bool omap_update_display (void *opaque) {struct omap_lcd_panel_s *omap_lcd = opaque;DisplaySurface *surface;
@@ -207,12 +207,12 @@ static void omap_update_display(void *opaque)hwaddr frame_base;if (!omap_lcd || omap_lcd->plm ==1 || !omap_lcd->enable) { -return ; +return true; } surface =qemu_console_surface (omap_lcd->con);if (!surface_bits_per_pixel (surface)) { -return ; +return true; } frame_offset =0 ;
@@ -256,7 +256,7 @@ static void omap_update_display(void *opaque)default :/* Unsupported at the moment. */ -return ; +return true; }/* Resolution */
@@ -278,7 +278,7 @@ static void omap_update_display(void *opaque) omap_lcd->sync_error =1 ;omap_lcd_interrupts (omap_lcd); omap_lcd->enable =0 ; -return ; +return true; }/* Content */
@@ -291,7 +291,7 @@ static void omap_update_display(void *opaque) omap_lcd->dma->current_frame ^=1 ;if (!surface_bits_per_pixel (surface)) { -return ; +return true; } first =0 ;
@@ -323,6 +323,8 @@ static void omap_update_display(void *opaque)dpy_gfx_update (omap_lcd->con,0 , first, width, last - first +1 ); } omap_lcd->invalidate =0 ; + +return true; }static void omap_invalidate_display (void *opaque) {
hw/display/pl110.c +3 -2
@@ -210,7 +210,7 @@ static int pl110_enabled(PL110State *s)return (s->cr &PL110_CR_EN ) && (s->cr &PL110_CR_PWR ); } -static void pl110_update_display (void *opaque) +static bool pl110_update_display (void *opaque) {PL110State *s = (PL110State *)opaque;DisplaySurface *surface =qemu_console_surface (s->con);
@@ -221,7 +221,7 @@ static void pl110_update_display(void *opaque)int last;if (!pl110_enabled (s)) { -return ; +return true; }if (s->cr &PL110_CR_BGR )
@@ -306,6 +306,7 @@ static void pl110_update_display(void *opaque)dpy_gfx_update (s->con,0 , first, s->cols, last - first +1 ); } s->invalidate =0 ; +return true; }static void pl110_invalidate_display (void * opaque)
hw/display/qxl-render.c +3 -3
@@ -173,7 +173,7 @@ end:* callbacks are called by spice_server thread, deferring to bh called from the * io thread. */ -void qxl_render_update (PCIQXLDevice *qxl) +bool qxl_render_update (PCIQXLDevice *qxl) {QXLCookie *cookie;
@@ -183,8 +183,7 @@ void qxl_render_update(PCIQXLDevice *qxl) qxl->mode == QXL_MODE_UNDEFINED) {qxl_render_update_area_unlocked (qxl);qemu_mutex_unlock (&qxl->ssd.lock); -graphic_hw_update_done (qxl->ssd.dcl.con); -return ; +return true; } qxl->guest_primary.commands =0 ;
@@ -195,6 +194,7 @@ void qxl_render_update(PCIQXLDevice *qxl)qxl_set_rect_to_surface (qxl, &cookie->u.render.area);qxl_spice_update_area (qxl,0 , &cookie->u.render.area,NULL ,0 ,1 /* clear_dirty_region */ ,QXL_ASYNC , cookie); +return false; }void qxl_render_update_area_bh (void *opaque)
hw/display/qxl.c +3 -4
@@ -122,7 +122,7 @@ static void qxl_reset_memslots(PCIQXLDevice *d);static void qxl_reset_surfaces (PCIQXLDevice *d);static void qxl_ring_set_dirty (PCIQXLDevice *qxl); -static void qxl_hw_update (void *opaque); +static bool qxl_hw_update (void *opaque);void qxl_set_guest_bug (PCIQXLDevice *qxl,const char *msg, ...) {
@@ -1144,7 +1144,6 @@ static const QXLInterface qxl_interface = {static const GraphicHwOps qxl_ops = { .gfx_update = qxl_hw_update, - .gfx_update_async = true, };static void qxl_enter_vga_mode (PCIQXLDevice *d)
@@ -1928,11 +1927,11 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)/* graphics console */ -static void qxl_hw_update (void *opaque) +static bool qxl_hw_update (void *opaque) {PCIQXLDevice *qxl = opaque; -qxl_render_update (qxl); +return qxl_render_update (qxl); } static void qxl_dirty_one_surface(PCIQXLDevice *qxl, QXLPHYSICAL pqxl,
hw/display/ramfb-standalone.c +3 -1
@@ -20,7 +20,7 @@ struct RAMFBStandaloneState {bool use_legacy_x86_rom; }; -static void display_update_wrapper (void *dev) +static bool display_update_wrapper (void *dev) {RAMFBStandaloneState *ramfb =RAMFB (dev);
@@ -29,6 +29,8 @@ static void display_update_wrapper(void *dev) }else {ramfb_display_update (ramfb->con, ramfb->state); } + +return true; }static const GraphicHwOps wrapper_ops = {
hw/display/sm501.c +5 -3
@@ -1716,7 +1716,7 @@ static void draw_hwc_line_32(uint8_t *d, const uint8_t *s, int width, } } -static void sm501_update_display (void *opaque) +static bool sm501_update_display (void *opaque) {SM501State *s = opaque;DisplaySurface *surface =qemu_console_surface (s->con);
@@ -1740,7 +1740,7 @@ static void sm501_update_display(void *opaque)if (!((crt ? s->dc_crt_control : s->dc_panel_control) &SM501_DC_CRT_CONTROL_ENABLE )) { -return ; +return true; } palette = (uint32_t *)(crt ? &s->dc_palette[SM501_DC_CRT_PALETTE -
@@ -1761,7 +1761,7 @@ static void sm501_update_display(void *opaque)default :qemu_log_mask (LOG_GUEST_ERROR ,"sm501: update display" "invalid control register value.\n" ); -return ; +return true; }/* set up to draw hardware cursor */
@@ -1833,6 +1833,8 @@ static void sm501_update_display(void *opaque)if (y_start >=0 ) {dpy_gfx_update (s->con,0 , y_start, width, y - y_start); } + +return true; }static const GraphicHwOps sm501_ops = {
hw/display/ssd0303.c +6 -4
@@ -203,7 +203,7 @@ static int ssd0303_event(I2CSlave *i2c, enum i2c_event event)return 0 ; } -static void ssd0303_update_display (void *opaque) +static bool ssd0303_update_display (void *opaque) {ssd0303_state *s = (ssd0303_state *)opaque;DisplaySurface *surface =qemu_console_surface (s->con);
@@ -218,11 +218,11 @@ static void ssd0303_update_display(void *opaque)uint8_t mask;if (!s->redraw) -return ; +return true;switch (surface_bits_per_pixel (surface)) {case 0 : -return ; +return true;case 15 : dest_width =2 ;break ;
@@ -237,7 +237,7 @@ static void ssd0303_update_display(void *opaque)break ;default :BADF ("Bad color depth\n" ); -return ; +return true; } dest_width *=MAGNIFY ;memset (colortab,0xff , dest_width);
@@ -269,6 +269,8 @@ static void ssd0303_update_display(void *opaque) } s->redraw =0 ;dpy_gfx_update (s->con,0 ,0 ,96 *MAGNIFY ,16 *MAGNIFY ); + +return true; }static void ssd0303_invalidate_display (void * opaque)
hw/display/ssd0323.c +6 -5
@@ -181,7 +181,7 @@ static uint32_t ssd0323_transfer(SSIPeripheral *dev, uint32_t data)return 0 ; } -static void ssd0323_update_display (void *opaque) +static bool ssd0323_update_display (void *opaque) {ssd0323_state *s = (ssd0323_state *)opaque;DisplaySurface *surface =qemu_console_surface (s->con);
@@ -197,11 +197,11 @@ static void ssd0323_update_display(void *opaque)int dest_width;if (!s->redraw) -return ; +return true;switch (surface_bits_per_pixel (surface)) {case 0 : -return ; +return true;case 15 : dest_width =2 ;break ;
@@ -216,7 +216,7 @@ static void ssd0323_update_display(void *opaque)break ;default :BADF ("Bad color depth\n" ); -return ; +return true; } p = colortab;for (i =0 ; i <16 ; i++) {
@@ -240,7 +240,7 @@ static void ssd0323_update_display(void *opaque)break ;default :BADF ("Bad color depth\n" ); -return ; +return true; } p += dest_width; }
@@ -271,6 +271,7 @@ static void ssd0323_update_display(void *opaque) } s->redraw =0 ;dpy_gfx_update (s->con,0 ,0 ,128 *MAGNIFY ,64 *MAGNIFY ); +return true; }static void ssd0323_invalidate_display (void * opaque)
hw/display/tcx.c +4 -2
@@ -209,7 +209,7 @@ static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,/* Fixed line length 1024 allows us to do nice tricks not possible on VGA... */ -static void tcx_update_display (void *opaque) +static bool tcx_update_display (void *opaque) {TCXState *ts = opaque;DisplaySurface *surface =qemu_console_surface (ts->con);
@@ -257,9 +257,10 @@ static void tcx_update_display(void *opaque) ts->width, y - y_start); }g_free (snap); +return true; } -static void tcx24_update_display (void *opaque) +static bool tcx24_update_display (void *opaque) {TCXState *ts = opaque;DisplaySurface *surface =qemu_console_surface (ts->con);
@@ -312,6 +313,7 @@ static void tcx24_update_display(void *opaque) ts->width, y - y_start); }g_free (snap); +return true; }static void tcx_invalidate_display (void *opaque)
hw/display/vga.c +3 -1
@@ -1783,7 +1783,7 @@ static void vga_draw_blank(VGACommonState *s, int full_update)#define GMODE_GRAPH 1#define GMODE_BLANK 2 -static void vga_update_display (void *opaque) +static bool vga_update_display (void *opaque) {VGACommonState *s = opaque;DisplaySurface *surface =qemu_console_surface (s->con);
@@ -1818,6 +1818,8 @@ static void vga_update_display(void *opaque)break ; } } + +return true; }/* force a full display refresh */
hw/display/virtio-gpu-base.c +2 -1
@@ -83,8 +83,9 @@ static void virtio_gpu_invalidate_display(void *opaque) { } -static void virtio_gpu_update_display (void *opaque) +static bool virtio_gpu_update_display (void *opaque) { +return true; }static void virtio_gpu_text_update (void *opaque,console_ch_t *chardata)
hw/display/virtio-vga.c +3 -3
@@ -19,15 +19,15 @@ static void virtio_vga_base_invalidate_display(void *opaque) } } -static void virtio_vga_base_update_display (void *opaque) +static bool virtio_vga_base_update_display (void *opaque) {VirtIOVGABase *vvga = opaque;VirtIOGPUBase *g = vvga->vgpu;if (g->enable) { - g->hw_ops->gfx_update (g); +return g->hw_ops->gfx_update (g); }else { - vvga->vga.hw_ops->gfx_update (&vvga->vga); +return vvga->vga.hw_ops->gfx_update (&vvga->vga); } }
hw/display/vmware_vga.c +4 -3
@@ -1135,14 +1135,13 @@ static inline void vmsvga_check_size(struct vmsvga_state_s *s) } } -static void vmsvga_update_display (void *opaque) +static bool vmsvga_update_display (void *opaque) {struct vmsvga_state_s *s = opaque;if (!s->enable || !s->config) {/* in standard vga mode */ - s->vga.hw_ops->gfx_update (&s->vga); -return ; +return s->vga.hw_ops->gfx_update (&s->vga); }vmsvga_check_size (s);
@@ -1154,6 +1153,8 @@ static void vmsvga_update_display(void *opaque) s->invalidated =0 ;dpy_gfx_update_full (s->vga.con); } + +return true; }static void vmsvga_reset (DeviceState *dev)
hw/display/xenfb.c +4 -2
@@ -709,14 +709,14 @@ static void xenfb_send_refresh_period(struct XenFB *xenfb, int period)* Our screen might be inactive. When asked for * an update we know it is active. */ -static void xenfb_update (void *opaque) +static bool xenfb_update (void *opaque) {struct XenFB *xenfb = opaque;DisplaySurface *surface;int i;if (xenfb->c.xendev.be_state != XenbusStateConnected) -return ; +return true;if (!xenfb->feature_update) {/* we don't get update notifications, thus use the
@@ -770,6 +770,8 @@ static void xenfb_update(void *opaque) } xenfb->up_count =0 ; xenfb->up_fullscreen =0 ; + +return true; }static void xenfb_ui_info (void *opaque,uint32_t idx,QemuUIInfo *info)
hw/display/xlnx_dp.c +6 -4
@@ -1252,12 +1252,12 @@ static inline void xlnx_dp_blend_surface(XlnxDPState *s) surface_height(s->g_plane.surface)); } -static void xlnx_dp_update_display (void *opaque) +static bool xlnx_dp_update_display (void *opaque) {XlnxDPState *s =XLNX_DP (opaque);if ((s->core_registers[DP_TRANSMITTER_ENABLE ] &0x01 ) ==0 ) { -return ; +return true; }xlnx_dpdma_trigger_vsync_irq (s->dpdma);
@@ -1272,14 +1272,14 @@ static void xlnx_dp_update_display(void *opaque)*/ s->core_registers[DP_INT_STATUS ] |= (1 <<21 );xlnx_dp_update_irq (s); -return ; +return true; }if (xlnx_dp_global_alpha_enabled (s)) {if (!xlnx_dpdma_start_operation (s->dpdma,0 , false)) { s->core_registers[DP_INT_STATUS ] |= (1 <<21 );xlnx_dp_update_irq (s); -return ; +return true; }xlnx_dp_blend_surface (s); }
@@ -1288,6 +1288,8 @@ static void xlnx_dp_update_display(void *opaque)* XXX: We might want to update only what changed. */ dpy_gfx_update_full (s->console); + +return true; }static const GraphicHwOps xlnx_dp_gfx_ops = {
hw/vfio/display.c +10 -7
@@ -285,7 +285,7 @@ static void vfio_display_free_dmabufs(VFIOPCIDevice *vdev) } } -static void vfio_display_dmabuf_update (void *opaque) +static bool vfio_display_dmabuf_update (void *opaque) {VFIOPCIDevice *vdev = opaque;VFIODisplay *dpy = vdev->dpy;
@@ -298,7 +298,7 @@ static void vfio_display_dmabuf_update(void *opaque)if (dpy->ramfb) {ramfb_display_update (dpy->con, dpy->ramfb); } -return ; +return true; } width =qemu_dmabuf_get_width (primary->buf);
@@ -340,6 +340,8 @@ static void vfio_display_dmabuf_update(void *opaque)if (free_bufs) {vfio_display_free_dmabufs (vdev); } + +return true; }static int vfio_display_get_flags (void *opaque)
@@ -399,7 +401,7 @@ void vfio_display_reset(VFIOPCIDevice *vdev)dpy_gfx_update_full (vdev->dpy->con); } -static void vfio_display_region_update (void *opaque) +static bool vfio_display_region_update (void *opaque) {VFIOPCIDevice *vdev = opaque;VFIODisplay *dpy = vdev->dpy;
@@ -414,18 +416,18 @@ static void vfio_display_region_update(void *opaque)if (ret <0 ) {error_report ("ioctl VFIO_DEVICE_QUERY_GFX_PLANE: %s" ,strerror (errno)); -return ; +return true; }if (!plane.drm_format || !plane.size) {if (dpy->ramfb) {ramfb_display_update (dpy->con, dpy->ramfb); dpy->region.surface =NULL ; } -return ; +return true; } format =qemu_drm_format_to_pixman (plane.drm_format);if (!format) { -return ; +return true; } if (dpy->region.buffer.size &&
@@ -476,11 +478,12 @@ static void vfio_display_region_update(void *opaque)dpy_gfx_update (dpy->con,0 ,0 ,surface_width (dpy->region.surface),surface_height (dpy->region.surface)); -return ; +return true; err:vfio_region_exit (&dpy->region.buffer);vfio_region_finalize (&dpy->region.buffer); +return true; }static const GraphicHwOps vfio_display_region_ops = {
ui/console.c +1 -6
@@ -136,15 +136,10 @@ void graphic_hw_update_done(QemuConsole *con)void graphic_hw_update (QemuConsole *con) { -bool async = false;if (!con) {return ; } -if (con->hw_ops->gfx_update) { - con->hw_ops->gfx_update (con->hw); - async = con->hw_ops->gfx_update_async; - } -if (!async) { +if (!con->hw_ops->gfx_update || con->hw_ops->gfx_update (con->hw)) {graphic_hw_update_done (con); } }
hw/display/apple-gfx.m +5 -5
@@ -330,25 +330,25 @@ static void apple_gfx_render_frame_completed_bh(void *opaque) } } -static void apple_gfx_fb_update_display(void *opaque) +static bool apple_gfx_fb_update_display(void *opaque) { AppleGFXState *s = opaque; + bool done = true; assert(bql_locked()); if (s->new_frame_ready) { dpy_gfx_update_full(s->con); s->new_frame_ready = false; - graphic_hw_update_done(s->con); } else if (s->pending_frames > 0) { s->gfx_update_requested = true; - } else { - graphic_hw_update_done(s->con); + done = false; } + + return done; } static const GraphicHwOps apple_gfx_fb_ops = { .gfx_update = apple_gfx_fb_update_display, - .gfx_update_async = true, }; /* ------ Mouse cursor and display mode setting ------ */
Signature · 1 line
2.54.0
[PULL v2 03/15] ui: make qemu_default_pixelformat() static inline
In reply to [email protected]From: Marc-André Lureau <[email protected]>
The function is a trivial wrapper around qemu_default_pixman_format() and qemu_pixelformat_from_pixman(), so make it static inline in qemu-pixman.h instead of a standalone function in console.c, allowing to be easily reused.
--- include/ui/qemu-pixman.h | 8 ++++++++ include/ui/surface.h | 2 -- ui/console.c | 7 ------- 3 files changed, 8 insertions(+), 9 deletions(-)
include/ui/qemu-pixman.h +8 -0
@@ -73,6 +73,14 @@ typedef struct PixelFormat {PixelFormat qemu_pixelformat_from_pixman (pixman_format_code_t format);pixman_format_code_t qemu_default_pixman_format (int bpp,bool native_endian); + +static inline PixelFormat qemu_default_pixelformat (int bpp) +{ +pixman_format_code_t fmt =qemu_default_pixman_format (bpp, true); +PixelFormat pf =qemu_pixelformat_from_pixman (fmt); +return pf; +} +pixman_format_code_t qemu_drm_format_to_pixman (uint32_t drm_format);uint32_t qemu_pixman_to_drm_format (pixman_format_code_t pixman);int qemu_pixman_get_type (int rshift,int gshift,int bshift,int endian);
include/ui/surface.h +0 -2
@@ -24,8 +24,6 @@ typedef struct DisplaySurface {uint32_t share_handle_offset; } 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);
ui/console.c +0 -7
@@ -1390,13 +1390,6 @@ DisplaySurface *qemu_console_surface(QemuConsole *console) } } -PixelFormat qemu_default_pixelformat (int bpp) -{ -pixman_format_code_t fmt =qemu_default_pixman_format (bpp, true); -PixelFormat pf =qemu_pixelformat_from_pixman (fmt); -return pf; -} -static QemuDisplay *dpys[DISPLAY_TYPE__MAX ];void qemu_display_register (QemuDisplay *ui)
Signature · 1 line
2.54.0
[PULL v2 09/15] ui/console: move console_handle_touch_event() to input
In reply to [email protected]From: Marc-André Lureau <[email protected]>
The function uses input.c functions to provide a simpler abstraction for touch events. Let's move it from the already overloaded console.c, and to avoid some unnecessary dependency from console.c on input.c.
--- include/ui/console.h | 14 ---------- include/ui/input.h | 15 ++++++++++ ui/console.c | 65 -------------------------------------------- ui/dbus-console.c | 6 ++-- ui/gtk.c | 8 +++--- ui/input.c | 65 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 87 insertions(+), 86 deletions(-)
include/ui/console.h +0 -14
@@ -111,20 +111,6 @@ 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 { -int x; -int y; -int tracking_id; -}touch_slot ; - -void console_handle_touch_event (QemuConsole *con, -struct touch_slot touch_slots[INPUT_EVENT_SLOTS_MAX ], -uint64_t num_slot, -int width,int height, -double x,double y, -InputMultiTouchType type, -Error **errp);/* consoles */ struct QemuConsoleClass {
include/ui/input.h +15 -0
@@ -70,6 +70,21 @@ void qemu_input_queue_mtt_abs(QemuConsole *src, InputAxis axis, int value, int min_in, int max_in, int slot, int tracking_id); +/* Touch devices */ +typedef struct touch_slot { +int x; +int y; +int tracking_id; +}touch_slot ; + +void qemu_input_touch_event (QemuConsole *con, +struct touch_slot touch_slots[INPUT_EVENT_SLOTS_MAX ], +uint64_t num_slot, +int width,int height, +double x,double y, +InputMultiTouchType type, +Error **errp); +void qemu_input_check_mode_change (void );void qemu_add_mouse_mode_change_notifier (Notifier *notify);void qemu_remove_mouse_mode_change_notifier (Notifier *notify);
ui/console.c +0 -65
71 lines not on this page · raw message
ui/dbus-console.c +3 -3
@@ -424,9 +424,9 @@ dbus_touch_send_event(DBusDisplayConsole *ddc, width =qemu_console_get_width (ddc->dcl.con,0 ); height =qemu_console_get_height (ddc->dcl.con,0 ); -console_handle_touch_event (ddc->dcl.con, touch_slots, - num_slot, width, height, - x, y, kind, &error); +qemu_input_touch_event (ddc->dcl.con, touch_slots, + num_slot, width, height, + x, y, kind, &error);if (error !=NULL ) { g_dbus_method_invocation_return_error( invocation, DBUS_DISPLAY_ERROR,
ui/gtk.c +4 -4
@@ -1201,10 +1201,10 @@ static gboolean gd_touch_event(GtkWidget *widget, GdkEventTouch *touch,return FALSE; } -console_handle_touch_event (vc->gfx.dcl.con, touch_slots, - num_slot,surface_width (vc->gfx.ds), -surface_height (vc->gfx.ds), touch->x, - touch->y, type, &err); +qemu_input_touch_event (vc->gfx.dcl.con, touch_slots, + num_slot,surface_width (vc->gfx.ds), +surface_height (vc->gfx.ds), touch->x, + touch->y, type, &err);if (err) {warn_report_err (err); }
ui/input.c +65 -0
68 lines not on this page · raw message
Signature · 1 line
2.54.0
[PULL v2 06/15] ui: rename init_keyboard_layout->kbd_layout_new()
In reply to [email protected]From: Marc-André Lureau <[email protected]>
Use a more convential name.
--- ui/keymaps.h | 4 ++-- ui/curses.c | 4 ++-- ui/input-barrier.c | 4 ++-- ui/keymaps.c | 4 ++-- ui/vnc.c | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-)
ui/keymaps.h +2 -2
@@ -52,8 +52,8 @@ typedef struct {typedef struct kbd_layout_t kbd_layout_t ; -kbd_layout_t *init_keyboard_layout (const name2keysym_t *table, -const char *language,Error **errp); +kbd_layout_t *kbd_layout_new (const name2keysym_t *table, +const char *language,Error **errp);void kbd_layout_free (kbd_layout_t *k);int keysym2scancode (kbd_layout_t *k,int keysym,QKbdState *kbd,bool down);
ui/curses.c +2 -2
@@ -770,8 +770,8 @@ static void curses_keyboard_setup(void) keyboard_layout ="en-us" ;#endif if (keyboard_layout) { - kbd_layout =init_keyboard_layout (name2keysym, keyboard_layout, - &error_fatal); + kbd_layout =kbd_layout_new (name2keysym, keyboard_layout, + &error_fatal); } }
ui/input-barrier.c +2 -2
@@ -679,8 +679,8 @@ static void input_barrier_instance_init(Object *obj)/* always use generic keymaps */ if (keyboard_layout && !kbd_layout) {/* We use X11 key id, so use VNC name2keysym */ - kbd_layout =init_keyboard_layout (name2keysym, keyboard_layout, - &error_fatal); + kbd_layout =kbd_layout_new (name2keysym, keyboard_layout, + &error_fatal); } ib->saddr.type =SOCKET_ADDRESS_TYPE_INET ;
ui/keymaps.c +2 -2
@@ -187,8 +187,8 @@ void kbd_layout_free(kbd_layout_t *k)g_free (k); } -kbd_layout_t *init_keyboard_layout (const name2keysym_t *table, -const char *language,Error **errp) +kbd_layout_t *kbd_layout_new (const name2keysym_t *table, +const char *language,Error **errp) {kbd_layout_t *k;
ui/vnc.c +3 -3
@@ -3443,10 +3443,10 @@ void vnc_display_init(const char *id, Error **errp)if (keyboard_layout) {trace_vnc_key_map_init (keyboard_layout); - vd->kbd_layout =init_keyboard_layout (name2keysym, - keyboard_layout, errp); + vd->kbd_layout =kbd_layout_new (name2keysym, + keyboard_layout, errp); }else { - vd->kbd_layout =init_keyboard_layout (name2keysym,"en-us" , errp); + vd->kbd_layout =kbd_layout_new (name2keysym,"en-us" , errp); }if (!vd->kbd_layout) {
Signature · 1 line
2.54.0
[PULL v2 11/15] audio: Avoid unsigned sample wraparound
In reply to [email protected]From: Akihiko Odaki <[email protected]>
When !defined(SIGNED), nv - HALF will wrap around if nv < HALF because nv and HALF are unsigned. Fix it by casting nv to mixeng_real, which is signed.
Message-Id: <[email protected]>
--- audio/mixeng_template.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
audio/mixeng_template.h +2 -2
@@ -43,13 +43,13 @@ static inline mixeng_real glue (conv_, ET) (IN_T v)#ifdef SIGNED return nv * (2.f / ((mixeng_real )IN_MAX -IN_MIN ));#else -return (nv -HALF ) * (2.f / (mixeng_real )IN_MAX ); +return ((mixeng_real )nv -HALF ) * (2.f / (mixeng_real )IN_MAX );#endif #else /* !RECIPROCAL */ #ifdef SIGNED return nv / (((mixeng_real )IN_MAX -IN_MIN ) /2.f );#else -return (nv -HALF ) / ((mixeng_real )IN_MAX /2.f ); +return ((mixeng_real )nv -HALF ) / ((mixeng_real )IN_MAX /2.f );#endif #endif }
Signature · 1 line
2.54.0
[PULL v2 14/15] ui/gtk: Use non-blocking clipboard retrieval
In reply to [email protected]From: Jindřich Makovička <[email protected]>
Message-ID: <[email protected]>
--- ui/gtk-clipboard.c | 53 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 13 deletions(-)
ui/gtk-clipboard.c +40 -13
@@ -136,26 +136,55 @@ static void gd_clipboard_notify(Notifier *notifier, void *data) } } +static void +gd_clipboard_request_text_received_callback (GtkClipboard *clipboard, +const gchar *text, +gpointer data) +{ +QemuClipboardInfo *info = (QemuClipboardInfo *)data; + +if (text) { +qemu_clipboard_set_data (info->owner, info,QEMU_CLIPBOARD_TYPE_TEXT , +strlen (text), text, true); + } +qemu_clipboard_info_unref (info); +} +static void gd_clipboard_request (QemuClipboardInfo *info,QemuClipboardType type) {GtkDisplayState *gd =container_of (info->owner, GtkDisplayState, cbpeer); -char *text;switch (type) {case QEMU_CLIPBOARD_TYPE_TEXT : - text =gtk_clipboard_wait_for_text (gd->gtkcb[info->selection]); -if (text) { -qemu_clipboard_set_data (&gd->cbpeer, info, type, -strlen (text), text, true); -g_free (text); - } +qemu_clipboard_info_ref (info); +gtk_clipboard_request_text (gd->gtkcb[info->selection], + gd_clipboard_request_text_received_callback, + info);break ;default :break ; } } +static void gd_clipboard_owner_change_targets_received_callback ( +GtkClipboard *clipboard, +GdkAtom *targets, +gint n_targets, +gpointer data) +{ +QemuClipboardInfo *info = (QemuClipboardInfo *)data; + +if (n_targets) { +if (gtk_targets_include_text (targets, n_targets)) { + info->types[QEMU_CLIPBOARD_TYPE_TEXT ].available = true; + } + } + +qemu_clipboard_update (info); +qemu_clipboard_info_unref (info); +} +static void gd_owner_change (GtkClipboard *clipboard,GdkEvent *event,gpointer data)
@@ -173,12 +202,10 @@ static void gd_owner_change(GtkClipboard *clipboard,switch (event->owner_change.reason) {case GDK_OWNER_CHANGE_NEW_OWNER : info =qemu_clipboard_info_new (&gd->cbpeer, s); -if (gtk_clipboard_wait_is_text_available (clipboard)) { - info->types[QEMU_CLIPBOARD_TYPE_TEXT ].available = true; - } - -qemu_clipboard_update (info); -qemu_clipboard_info_unref (info); +gtk_clipboard_request_targets ( + clipboard, + gd_clipboard_owner_change_targets_received_callback, + info);break ;default :qemu_clipboard_peer_release (&gd->cbpeer, s);
Signature · 1 line
2.54.0
[PULL v2 10/15] ui/dbus: fix warning for clients without "Interfaces" property
In reply to [email protected]From: Marc-André Lureau <[email protected]>
The "Interfaces" property is not strictly required. We can just assume the peer doesn't implement the given interface. Fix warning:
GLib: g_strv_contains: assertion 'strv != NULL' failed
--- ui/dbus-listener.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
ui/dbus-listener.c +3 -1
@@ -1026,9 +1026,11 @@ static bool dbus_display_listener_implements(DBusDisplayListener *ddl, const char *iface) {QemuDBusDisplay1Listener *l =QEMU_DBUS_DISPLAY1_LISTENER (ddl->proxy); +const char *const *interfaces;bool implements; - implements =g_strv_contains (qemu_dbus_display1_listener_get_interfaces (l), iface); + interfaces =qemu_dbus_display1_listener_get_interfaces (l); + implements = interfaces &&g_strv_contains (interfaces, iface);if (!implements) {g_debug ("Display listener does not implement: `%s`" , iface); }
Signature · 1 line
2.54.0
[PULL v2 12/15] audio: Clamp unsigned sample conversion
In reply to [email protected]From: Akihiko Odaki <[email protected]>
clip_*_uint32_t() returns 0 when v == 1.f because it computes the result as (IN_T)((v * ((mixeng_real)IN_MAX / 2.f)) + HALF):
- (v * ((mixeng_real)IN_MAX / 2.f)) + HALF == 0x100000000.f, which does not fit in uint32_t.
- (v * ((mixeng_real)IN_MAX / 2.f)) == 0x80000000.f
- ((mixeng_real)IN_MAX / 2.f) == 0x80000000.f
- (mixeng_real)IN_MAX == 0x100000000.f because 0xffffffff cannot be represented exactly in float.
- HALF == 0x7fffffff, which is implicitly converted to 0x80000000.f.
Clamp the result to avoid the overflow.
Message-Id: <[email protected]>
--- audio/mixeng_template.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
audio/mixeng_template.h +3 -1
@@ -65,7 +65,9 @@ static inline IN_T glue (clip_, ET) (mixeng_real v)#ifdef SIGNED return ENDIAN_CONVERT ((IN_T )(v * (((mixeng_real )IN_MAX -IN_MIN ) /2.f )));#else -return ENDIAN_CONVERT ((IN_T )((v * ((mixeng_real )IN_MAX /2.f )) +HALF )); +return ENDIAN_CONVERT (MIN ((int64_t )((v * ((mixeng_real )IN_MAX /2.f )) + +HALF ), +IN_MAX ));#endif }
Signature · 1 line
2.54.0
[PULL v2 15/15] ui/gtk: Turn clipboard flag into runtime option
In reply to [email protected]From: Jindřich Makovička <[email protected]>
- Compile the GTK clipboard support unconditionally
- Introduce GTK clipboard option, defaulting to off
Message-ID: <[email protected]>
--- meson.build | 4 ---- qapi/ui.json | 6 +++++- ui/gtk.c | 8 +++++--- meson_options.txt | 7 ------- qemu-options.hx | 9 ++++++--- scripts/meson-buildoptions.sh | 3 --- ui/meson.build | 4 +--- 7 files changed, 17 insertions(+), 24 deletions(-)
meson.build +0 -4
@@ -1932,7 +1932,6 @@ endif gtk = not_found gtkx11 = not_found vte = not_found -have_gtk_clipboard = get_option('gtk_clipboard').enabled() if get_option('gtk') \ .disable_auto_if(not have_system) \
@@ -1954,8 +1953,6 @@ if get_option('gtk') \ method: 'pkg-config', required: get_option('vte')) endif - elif have_gtk_clipboard - error('GTK clipboard requested, but GTK not found') endif endif
@@ -2475,7 +2472,6 @@ if glusterfs.found() endif config_host_data.set('CONFIG_GTK', gtk.found()) config_host_data.set('CONFIG_VTE', vte.found()) -config_host_data.set('CONFIG_GTK_CLIPBOARD', have_gtk_clipboard) config_host_data.set('CONFIG_HEXAGON_IDEF_PARSER', get_option('hexagon_idef_parser')) config_host_data.set('CONFIG_LIBATTR', have_old_libattr) config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
qapi/ui.json +5 -1
@@ -1319,6 +1319,9 @@ # # GTK display options. # +# @clipboard: Enable host-guest clipboard sharing. Defaults to "off". +# (Since 11.1) +# # @grab-on-hover: Grab keyboard input on mouse hover. # # @zoom-to-fit: Zoom guest display to fit into the host window. When
@@ -1344,7 +1347,8 @@ # Since: 2.12 ## { 'struct' : 'DisplayGTK', - 'data' : { '*grab-on-hover' : 'bool', + 'data' : { '*clipboard' : 'bool', + '*grab-on-hover' : 'bool', '*zoom-to-fit' : 'bool', '*show-tabs' : 'bool', '*show-menubar' : 'bool',
ui/gtk.c +5 -3
@@ -2601,9 +2601,11 @@ static void gtk_display_init(DisplayState *ds, DisplayOptions *opts) opts->u.gtk.show_tabs) {gtk_menu_item_activate (GTK_MENU_ITEM (s->show_tabs_item)); } -#ifdef CONFIG_GTK_CLIPBOARD -gd_clipboard_init (s); -#endif /* CONFIG_GTK_CLIPBOARD */ + +if (opts->u.gtk.has_clipboard && + opts->u.gtk.clipboard) { +gd_clipboard_init (s); + }/* GTK's event polling must happen on the main thread. */ qemu_main =NULL ;
meson_options.txt +0 -7
@@ -262,13 +262,6 @@ option('vnc_sasl', type : 'feature', value : 'auto', description: 'SASL authentication for VNC server') option('vte', type : 'feature', value : 'auto', description: 'vte support for the gtk UI') - -# GTK Clipboard implementation is disabled by default, since it may cause hangs -# of the guest VCPUs. See gitlab issue 1150: -# https://gitlab.com/qemu-project/qemu/-/issues/1150 - -option('gtk_clipboard', type: 'feature', value : 'disabled', - description: 'clipboard support for the gtk UI (EXPERIMENTAL, MAY HANG)') option('xkbcommon', type : 'feature', value : 'auto', description: 'xkbcommon support') option('zstd', type : 'feature', value : 'auto',
qemu-options.hx +6 -3
@@ -2209,9 +2209,9 @@ DEF("display", HAS_ARG, QEMU_OPTION_display, " [,window-close=on|off]\n" #endif #if defined(CONFIG_GTK) - "-display gtk[,full-screen=on|off][,gl=on|off][,grab-on-hover=on|off]\n" - " [,show-tabs=on|off][,show-cursor=on|off][,window-close=on|off]\n" - " [,show-menubar=on|off][,zoom-to-fit=on|off]\n" + "-display gtk[,clipboard=on|off][,full-screen=on|off][,gl=on|off]\n" + " [,grab-on-hover=on|off][,show-tabs=on|off][,show-cursor=on|off]\n" + " [,window-close=on|off][,show-menubar=on|off][,zoom-to-fit=on|off]\n" #endif #if defined(CONFIG_VNC) "-display vnc=<display>[,<optargs>]\n"
@@ -2295,6 +2295,9 @@ SRST drop-down menus and other UI elements to configure and control the VM during runtime. Valid parameters are: + ``clipboard=on|off`` : Enable host-guest clipboard sharing, + defaults to "off" + ``full-screen=on|off`` : Start in fullscreen mode ``gl=on|off`` : Use OpenGL for displaying
scripts/meson-buildoptions.sh +0 -3
@@ -124,7 +124,6 @@ meson_options_help() { printf "%s\n" ' glusterfs Glusterfs block device driver' printf "%s\n" ' gnutls GNUTLS cryptography support' printf "%s\n" ' gtk GTK+ user interface' - printf "%s\n" ' gtk-clipboard clipboard support for the gtk UI (EXPERIMENTAL, MAY HANG)' printf "%s\n" ' guest-agent Build QEMU Guest Agent' printf "%s\n" ' guest-agent-msi Build MSI package for the QEMU Guest Agent' printf "%s\n" ' hv-balloon hv-balloon driver (requires Glib 2.68+ GTree API)'
@@ -336,8 +335,6 @@ _meson_option_parse() { --disable-gnutls) printf "%s" -Dgnutls=disabled ;; --enable-gtk) printf "%s" -Dgtk=enabled ;; --disable-gtk) printf "%s" -Dgtk=disabled ;; - --enable-gtk-clipboard) printf "%s" -Dgtk_clipboard=enabled ;; - --disable-gtk-clipboard) printf "%s" -Dgtk_clipboard=disabled ;; --enable-guest-agent) printf "%s" -Dguest_agent=enabled ;; --disable-guest-agent) printf "%s" -Dguest_agent=disabled ;; --enable-guest-agent-msi) printf "%s" -Dguest_agent_msi=enabled ;;
ui/meson.build +1 -3
@@ -112,9 +112,7 @@ if gtk.found() gtk_ss = ss.source_set() gtk_ss.add(gtk, vte, pixman, files('gtk.c')) - if have_gtk_clipboard - gtk_ss.add(files('gtk-clipboard.c')) - endif + gtk_ss.add(files('gtk-clipboard.c')) gtk_ss.add(when: x11, if_true: files('x_keymap.c')) gtk_ss.add(when: opengl, if_true: files('gtk-gl-area.c')) gtk_ss.add(when: [x11, opengl], if_true: files('gtk-egl.c'))
Signature · 1 line
2.54.0
[PULL v2 13/15] audio: Use unsigned PCM bias
In reply to [email protected]From: Akihiko Odaki <[email protected]>
Clang warns for the uint32_t clip_ instantiations because HALF cannot be represented with mixeng_real:
[1115/2559] Compiling C object libqemuaudio.a.p/audio_mixeng.c.o
In file included from ../../qemu/audio/mixeng.c:147:../../qemu/audio/mixeng_template.h:68:70: warning: implicit conversion from 'unsigned int' to 'float' changes value from 2147483647 to 2147483648 [-Wimplicit-const-int-float-conversion]
68 | return ENDIAN_CONVERT((IN_T)((v * ((mixeng_real)IN_MAX / 2.f)) + HALF));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~../../qemu/audio/mixeng_template.h:31:22: note: expanded from macro 'HALF'
31 | #define HALF (IN_MAX >> 1)
| ^../../qemu/audio/mixeng.c:146:28: note: expanded from macro 'ENDIAN_CONVERT'
146 | #define ENDIAN_CONVERT(v) (v)
| ^
In file included from ../../qemu/audio/mixeng.c:152:../../qemu/audio/mixeng_template.h:68:70: warning: implicit conversion from 'unsigned int' to 'float' changes value from 2147483647 to 2147483648 [-Wimplicit-const-int-float-conversion]
68 | return ENDIAN_CONVERT((IN_T)((v * ((mixeng_real)IN_MAX / 2.f)) + HALF));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~../../qemu/audio/mixeng_template.h:31:22: note: expanded from macro 'HALF'
31 | #define HALF (IN_MAX >> 1)
| ^../../qemu/audio/mixeng.c:151:36: note: expanded from macro 'ENDIAN_CONVERT'
151 | #define ENDIAN_CONVERT(v) bswap32 (v)
| ~~~~~~~~~^~
/Users/person/v/qemu/include/qemu/bswap.h:10:39: note: expanded from macro 'bswap32'
10 | #define bswap32(_x) __builtin_bswap32(_x)
| ^~
2 warnings generated.
HALF is not the right value here anyway. IN_MAX is odd, so the integer sample range has two middle codes. Unsigned PCM normally uses the upper middle code as the "bias": 0x80, 0x8000, or 0x80000000. HALF is instead defined as the lower middle code: 0x7f, 0x7fff, or 0x7fffffff.
Replace HALF with BIAS, defined as the upper middle code. This fixes the warnings, since the value can be exactly represented with mixeng_real.
Message-Id: <[email protected]>
--- audio/mixeng_template.h | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
audio/mixeng_template.h +7 -9
@@ -28,7 +28,7 @@*/ #ifndef SIGNED -#define HALF (IN_MAX >> 1) +#define BIAS ((IN_T)1 << (SHIFT - 1))#endif #define ET glue (ENDIAN_CONVERSION, glue (glue (glue (_, ITYPE), BSIZE), _t))
@@ -43,13 +43,13 @@ static inline mixeng_real glue (conv_, ET) (IN_T v)#ifdef SIGNED return nv * (2.f / ((mixeng_real )IN_MAX -IN_MIN ));#else -return ((mixeng_real )nv -HALF ) * (2.f / (mixeng_real )IN_MAX ); +return ((mixeng_real )nv -BIAS ) * (1.f /BIAS );#endif #else /* !RECIPROCAL */ #ifdef SIGNED return nv / (((mixeng_real )IN_MAX -IN_MIN ) /2.f );#else -return ((mixeng_real )nv -HALF ) / ((mixeng_real )IN_MAX /2.f ); +return ((mixeng_real )nv -BIAS ) /BIAS ;#endif #endif }
@@ -65,9 +65,7 @@ static inline IN_T glue (clip_, ET) (mixeng_real v)#ifdef SIGNED return ENDIAN_CONVERT ((IN_T )(v * (((mixeng_real )IN_MAX -IN_MIN ) /2.f )));#else -return ENDIAN_CONVERT (MIN ((int64_t )((v * ((mixeng_real )IN_MAX /2.f )) + -HALF ), -IN_MAX )); +return ENDIAN_CONVERT (MIN ((int64_t )(v *BIAS ) +BIAS ,IN_MAX ));#endif }
@@ -79,7 +77,7 @@ static inline int64_t glue (conv_, ET) (IN_T v)#ifdef SIGNED return ((int64_t ) nv) << (32 -SHIFT );#else -return ((int64_t ) nv -HALF ) << (32 -SHIFT ); +return ((int64_t ) nv -BIAS ) << (32 -SHIFT );#endif }
@@ -94,7 +92,7 @@ static inline IN_T glue (clip_, ET) (int64_t v)#ifdef SIGNED return ENDIAN_CONVERT ((IN_T ) (v >> (32 -SHIFT )));#else -return ENDIAN_CONVERT ((IN_T ) ((v >> (32 -SHIFT )) +HALF )); +return ENDIAN_CONVERT ((IN_T )((v >> (32 -SHIFT )) +BIAS )); #endif }#endif
@@ -150,5 +148,5 @@ static void glue (glue (clip_, ET), _from_mono) }#undef ET -#undef HALF +#undef BIAS#undef IN_T
Signature · 1 line
2.54.0
[PULL v2 07/15] ui/console: remove qemu_console_is_visible()
In reply to [email protected]From: Marc-André Lureau <[email protected]>
Drop the bookkeeping, we can simply afford an empty "foreach".
Notice that dpy_gfx_update_texture() is now called even when there are no listeners. This is more correct, as the texture is not fully refreshed when a listener connects, so it may be outdated/garbaged.
--- include/ui/console.h | 1 - ui/console-priv.h | 1 - ui/console.c | 29 ----------------------------- 3 files changed, 31 deletions(-)
include/ui/console.h +0 -1
@@ -399,7 +399,6 @@ QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head);QemuConsole *qemu_console_lookup_by_device_name (const char *device_id,uint32_t head,Error **errp);QEMUCursor *qemu_console_get_cursor (QemuConsole *con); -bool qemu_console_is_visible (QemuConsole *con);bool qemu_console_is_graphic (QemuConsole *con);bool qemu_console_is_fixedsize (QemuConsole *con);bool qemu_console_is_gl_blocked (QemuConsole *con);
ui/console-priv.h +0 -1
@@ -16,7 +16,6 @@ struct QemuConsole {DisplayState *ds;DisplaySurface *surface;DisplayScanout scanout; -int dcls;DisplayGLCtx *gl;int gl_block;QEMUTimer *gl_unblock_timer;
ui/console.c +0 -29
@@ -648,9 +648,6 @@ void register_displaychangelistener(DisplayChangeListener *dcl) dcl->ds =get_alloc_displaystate ();QLIST_INSERT_HEAD (&dcl->ds->listeners, dcl, next);gui_setup_refresh (dcl->ds); -if (dcl->con) { - dcl->con->dcls++; - }displaychangelistener_display_console (dcl, &error_fatal);if (QEMU_IS_GRAPHIC_CONSOLE (dcl->con)) {dcl_set_graphic_cursor (dcl,QEMU_GRAPHIC_CONSOLE (dcl->con));
@@ -678,9 +675,6 @@ void unregister_displaychangelistener(DisplayChangeListener *dcl)if (!ds) {return ; } -if (dcl->con) { - dcl->con->dcls--; - }QLIST_REMOVE (dcl, next); dcl->ds =NULL ;gui_setup_refresh (ds);
@@ -745,9 +739,6 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h) w =MIN (w, width - x); h =MIN (h, height - y); -if (!qemu_console_is_visible (con)) { -return ; - }dpy_gfx_update_texture (con, con->surface, x, y, w, h); QLIST_FOREACH(dcl, &s->listeners, next) {if (con != dcl->con) {
@@ -846,9 +837,6 @@ void dpy_text_cursor(QemuConsole *con, int x, int y)DisplayState *s = con->ds;DisplayChangeListener *dcl; -if (!qemu_console_is_visible (con)) { -return ; - } QLIST_FOREACH(dcl, &s->listeners, next) {if (con != dcl->con) {continue ;
@@ -864,9 +852,6 @@ void dpy_text_update(QemuConsole *con, int x, int y, int w, int h)DisplayState *s = con->ds;DisplayChangeListener *dcl; -if (!qemu_console_is_visible (con)) { -return ; - } QLIST_FOREACH(dcl, &s->listeners, next) {if (con != dcl->con) {continue ;
@@ -882,9 +867,6 @@ void dpy_text_resize(QemuConsole *con, int w, int h)DisplayState *s = con->ds;DisplayChangeListener *dcl; -if (!qemu_console_is_visible (con)) { -return ; - } QLIST_FOREACH(dcl, &s->listeners, next) {if (con != dcl->con) {continue ;
@@ -904,9 +886,6 @@ void dpy_mouse_set(QemuConsole *c, int x, int y, bool on) con->cursor_x = x; con->cursor_y = y; con->cursor_on = on; -if (!qemu_console_is_visible (c)) { -return ; - } QLIST_FOREACH(dcl, &s->listeners, next) {if (c != dcl->con) {continue ;
@@ -925,9 +904,6 @@ void dpy_cursor_define(QemuConsole *c, QEMUCursor *cursor)cursor_unref (con->cursor); con->cursor =cursor_ref (cursor); -if (!qemu_console_is_visible (c)) { -return ; - } QLIST_FOREACH(dcl, &s->listeners, next) {if (c != dcl->con) {continue ;
@@ -1285,11 +1261,6 @@ QEMUCursor *qemu_console_get_cursor(QemuConsole *con)return QEMU_IS_GRAPHIC_CONSOLE (con) ?QEMU_GRAPHIC_CONSOLE (con)->cursor :NULL ; } -bool qemu_console_is_visible (QemuConsole *con) -{ -return con->dcls >0 ; -} -bool qemu_console_is_graphic (QemuConsole *con) {return con &&QEMU_IS_GRAPHIC_CONSOLE (con);
Signature · 1 line
2.54.0
Stefan Hajnoczi
AppliedApplied, thanks.
Please update the changelog at https://wiki.qemu.org/ChangeLog/11.1 for any user-visible changes.