diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2021-02-19 22:20:17 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-02-19 22:20:17 +0000 |
commit | d6798cc01d6edabaa4e326359b69f08d022bf4c7 (patch) | |
tree | 3b8e38b434a5cdf4a668f2a2ac7f72100b1041b2 | |
parent | e90ef02389dc8b57eaea22b290244609d720a8bf (diff) | |
parent | 075e7a5b7f3c640823fce76c8dab503c42f0d7f6 (diff) |
Merge remote-tracking branch 'remotes/kraxel/tags/ui-20210219-pull-request' into staging
ui: spice bugfixes.
ui: first batch of cocoa updates.
# gpg: Signature made Fri 19 Feb 2021 22:00:14 GMT
# gpg: using RSA key A0328CFFB93A17A79901FE7D4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full]
# gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" [full]
# gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full]
# Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138
* remotes/kraxel/tags/ui-20210219-pull-request:
ui/console: Remove dpy_gl_ctx_get_current
ui/cocoa: Statically allocate dcl
ui/cocoa: Interpret left button down as is when command is pressed
spice-app: avoid crash when core spice module doesn't loaded
ui/cocoa: Do not copy members of pixman image
ui/cocoa: Support unique keys of JIS keyboards
spice: flush drawing before notifying client
spice: flush on GL update before notifying client
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | include/ui/gtk.h | 1 | ||||
-rw-r--r-- | ui/cocoa.m | 126 | ||||
-rw-r--r-- | ui/gtk-gl-area.c | 5 | ||||
-rw-r--r-- | ui/spice-app.c | 8 | ||||
-rw-r--r-- | ui/spice-display.c | 2 |
5 files changed, 69 insertions, 73 deletions
diff --git a/include/ui/gtk.h b/include/ui/gtk.h index 3c1cd98db8..5ae0ad60a6 100644 --- a/include/ui/gtk.h +++ b/include/ui/gtk.h @@ -147,7 +147,6 @@ void gd_gl_area_scanout_disable(DisplayChangeListener *dcl); void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, uint32_t x, uint32_t y, uint32_t w, uint32_t h); void gtk_gl_area_init(void); -QEMUGLContext gd_gl_area_get_current_context(DisplayChangeListener *dcl); int gd_gl_area_make_current(DisplayChangeListener *dcl, QEMUGLContext ctx); diff --git a/ui/cocoa.m b/ui/cocoa.m index 13fba8103e..0ef5fdf3b7 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -70,12 +70,26 @@ typedef struct { int width; int height; - int bitsPerComponent; - int bitsPerPixel; } QEMUScreen; +static void cocoa_update(DisplayChangeListener *dcl, + int x, int y, int w, int h); + +static void cocoa_switch(DisplayChangeListener *dcl, + DisplaySurface *surface); + +static void cocoa_refresh(DisplayChangeListener *dcl); + NSWindow *normalWindow, *about_window; -static DisplayChangeListener *dcl; +static const DisplayChangeListenerOps dcl_ops = { + .dpy_name = "cocoa", + .dpy_gfx_update = cocoa_update, + .dpy_gfx_switch = cocoa_switch, + .dpy_refresh = cocoa_refresh, +}; +static DisplayChangeListener dcl = { + .ops = &dcl_ops, +}; static int last_buttons; static int cursor_hide = 1; @@ -240,6 +254,13 @@ const int mac_to_qkeycode_map[] = { [kVK_F14] = Q_KEY_CODE_SCROLL_LOCK, [kVK_F15] = Q_KEY_CODE_PAUSE, + // JIS keyboards only + [kVK_JIS_Yen] = Q_KEY_CODE_YEN, + [kVK_JIS_Underscore] = Q_KEY_CODE_RO, + [kVK_JIS_KeypadComma] = Q_KEY_CODE_KP_COMMA, + [kVK_JIS_Eisu] = Q_KEY_CODE_MUHENKAN, + [kVK_JIS_Kana] = Q_KEY_CODE_HENKAN, + /* * The eject and volume keys can't be used here because they are handled at * a lower level than what an Application can see. @@ -284,7 +305,6 @@ static void handleAnyDeviceErrors(Error * err) QEMUScreen screen; NSWindow *fullScreenWindow; float cx,cy,cw,ch,cdx,cdy; - CGDataProviderRef dataProviderRef; pixman_image_t *pixman_image; BOOL modifiers_state[256]; BOOL isMouseGrabbed; @@ -331,8 +351,6 @@ QemuCocoaView *cocoaView; self = [super initWithFrame:frameRect]; if (self) { - screen.bitsPerComponent = 8; - screen.bitsPerPixel = 32; screen.width = frameRect.size.width; screen.height = frameRect.size.height; @@ -344,8 +362,7 @@ QemuCocoaView *cocoaView; { COCOA_DEBUG("QemuCocoaView: dealloc\n"); - if (dataProviderRef) { - CGDataProviderRelease(dataProviderRef); + if (pixman_image) { pixman_image_unref(pixman_image); } @@ -424,18 +441,28 @@ QemuCocoaView *cocoaView; CGContextSetShouldAntialias (viewContextRef, NO); // draw screen bitmap directly to Core Graphics context - if (!dataProviderRef) { + if (!pixman_image) { // Draw request before any guest device has set up a framebuffer: // just draw an opaque black rectangle CGContextSetRGBFillColor(viewContextRef, 0, 0, 0, 1.0); CGContextFillRect(viewContextRef, NSRectToCGRect(rect)); } else { + int w = pixman_image_get_width(pixman_image); + int h = pixman_image_get_height(pixman_image); + int bitsPerPixel = PIXMAN_FORMAT_BPP(pixman_image_get_format(pixman_image)); + int bitsPerComponent = DIV_ROUND_UP(bitsPerPixel, 8) * 2; + CGDataProviderRef dataProviderRef = CGDataProviderCreateWithData( + NULL, + pixman_image_get_data(pixman_image), + w * 4 * h, + NULL + ); CGImageRef imageRef = CGImageCreate( - screen.width, //width - screen.height, //height - screen.bitsPerComponent, //bitsPerComponent - screen.bitsPerPixel, //bitsPerPixel - (screen.width * (screen.bitsPerComponent/2)), //bytesPerRow + w, //width + h, //height + bitsPerComponent, //bitsPerComponent + bitsPerPixel, //bitsPerPixel + (w * (bitsPerComponent/2)), //bytesPerRow #ifdef __LITTLE_ENDIAN__ CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB), //colorspace for OS X >= 10.4 kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst, @@ -458,7 +485,7 @@ QemuCocoaView *cocoaView; [self getRectsBeingDrawn:&rectList count:&rectCount]; for (i = 0; i < rectCount; i++) { clipRect.origin.x = rectList[i].origin.x / cdx; - clipRect.origin.y = (float)screen.height - (rectList[i].origin.y + rectList[i].size.height) / cdy; + clipRect.origin.y = (float)h - (rectList[i].origin.y + rectList[i].size.height) / cdy; clipRect.size.width = rectList[i].size.width / cdx; clipRect.size.height = rectList[i].size.height / cdy; clipImageRef = CGImageCreateWithImageInRect( @@ -469,6 +496,7 @@ QemuCocoaView *cocoaView; CGImageRelease (clipImageRef); } CGImageRelease (imageRef); + CGDataProviderRelease(dataProviderRef); } } @@ -511,7 +539,6 @@ QemuCocoaView *cocoaView; int w = pixman_image_get_width(image); int h = pixman_image_get_height(image); - pixman_format_code_t image_format = pixman_image_get_format(image); /* cdx == 0 means this is our very first surface, in which case we need * to recalculate the content dimensions even if it happens to be the size * of the initial empty window. @@ -529,17 +556,11 @@ QemuCocoaView *cocoaView; } // update screenBuffer - if (dataProviderRef) { - CGDataProviderRelease(dataProviderRef); + if (pixman_image) { pixman_image_unref(pixman_image); } - //sync host window color space with guests - screen.bitsPerPixel = PIXMAN_FORMAT_BPP(image_format); - screen.bitsPerComponent = DIV_ROUND_UP(screen.bitsPerPixel, 8) * 2; - pixman_image = image; - dataProviderRef = CGDataProviderCreateWithData(NULL, pixman_image_get_data(image), w * 4 * h, NULL); // update windows if (isFullscreen) { @@ -602,15 +623,15 @@ QemuCocoaView *cocoaView; // Toggle the stored state. modifiers_state[keycode] = !modifiers_state[keycode]; // Send a keyup or keydown depending on the state. - qemu_input_event_send_key_qcode(dcl->con, keycode, modifiers_state[keycode]); + qemu_input_event_send_key_qcode(dcl.con, keycode, modifiers_state[keycode]); } - (void) toggleStatefulModifier: (int)keycode { // Toggle the stored state. modifiers_state[keycode] = !modifiers_state[keycode]; // Generate keydown and keyup. - qemu_input_event_send_key_qcode(dcl->con, keycode, true); - qemu_input_event_send_key_qcode(dcl->con, keycode, false); + qemu_input_event_send_key_qcode(dcl.con, keycode, true); + qemu_input_event_send_key_qcode(dcl.con, keycode, false); } // Does the work of sending input to the monitor @@ -794,7 +815,7 @@ QemuCocoaView *cocoaView; } if (qemu_console_is_graphic(NULL)) { - qemu_input_event_send_key_qcode(dcl->con, keycode, true); + qemu_input_event_send_key_qcode(dcl.con, keycode, true); } else { [self handleMonitorInput: event]; } @@ -809,7 +830,7 @@ QemuCocoaView *cocoaView; } if (qemu_console_is_graphic(NULL)) { - qemu_input_event_send_key_qcode(dcl->con, keycode, false); + qemu_input_event_send_key_qcode(dcl.con, keycode, false); } break; case NSEventTypeMouseMoved: @@ -830,11 +851,7 @@ QemuCocoaView *cocoaView; mouse_event = true; break; case NSEventTypeLeftMouseDown: - if ([event modifierFlags] & NSEventModifierFlagCommand) { - buttons |= MOUSE_EVENT_RBUTTON; - } else { - buttons |= MOUSE_EVENT_LBUTTON; - } + buttons |= MOUSE_EVENT_LBUTTON; mouse_event = true; break; case NSEventTypeRightMouseDown: @@ -846,11 +863,7 @@ QemuCocoaView *cocoaView; mouse_event = true; break; case NSEventTypeLeftMouseDragged: - if ([event modifierFlags] & NSEventModifierFlagCommand) { - buttons |= MOUSE_EVENT_RBUTTON; - } else { - buttons |= MOUSE_EVENT_LBUTTON; - } + buttons |= MOUSE_EVENT_LBUTTON; mouse_event = true; break; case NSEventTypeRightMouseDragged: @@ -895,9 +908,9 @@ QemuCocoaView *cocoaView; /* Determine if this is a scroll up or scroll down event */ buttons = ([event deltaY] > 0) ? INPUT_BUTTON_WHEEL_UP : INPUT_BUTTON_WHEEL_DOWN; - qemu_input_queue_btn(dcl->con, buttons, true); + qemu_input_queue_btn(dcl.con, buttons, true); qemu_input_event_sync(); - qemu_input_queue_btn(dcl->con, buttons, false); + qemu_input_queue_btn(dcl.con, buttons, false); qemu_input_event_sync(); } /* @@ -925,7 +938,7 @@ QemuCocoaView *cocoaView; [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON, [INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON }; - qemu_input_update_buttons(dcl->con, bmap, last_buttons, buttons); + qemu_input_update_buttons(dcl.con, bmap, last_buttons, buttons); last_buttons = buttons; } if (isMouseGrabbed) { @@ -935,12 +948,12 @@ QemuCocoaView *cocoaView; * clicks in the titlebar. */ if ([self screenContainsPoint:p]) { - qemu_input_queue_abs(dcl->con, INPUT_AXIS_X, p.x, 0, screen.width); - qemu_input_queue_abs(dcl->con, INPUT_AXIS_Y, screen.height - p.y, 0, screen.height); + qemu_input_queue_abs(dcl.con, INPUT_AXIS_X, p.x, 0, screen.width); + qemu_input_queue_abs(dcl.con, INPUT_AXIS_Y, screen.height - p.y, 0, screen.height); } } else { - qemu_input_queue_rel(dcl->con, INPUT_AXIS_X, (int)[event deltaX]); - qemu_input_queue_rel(dcl->con, INPUT_AXIS_Y, (int)[event deltaY]); + qemu_input_queue_rel(dcl.con, INPUT_AXIS_X, (int)[event deltaX]); + qemu_input_queue_rel(dcl.con, INPUT_AXIS_Y, (int)[event deltaY]); } } else { return false; @@ -1009,7 +1022,7 @@ QemuCocoaView *cocoaView; for (index = 0; index < max_index; index++) { if (modifiers_state[index]) { modifiers_state[index] = 0; - qemu_input_event_send_key_qcode(dcl->con, index, false); + qemu_input_event_send_key_qcode(dcl.con, index, false); } } }); @@ -1836,19 +1849,6 @@ static void cocoa_refresh(DisplayChangeListener *dcl) [pool release]; } -static void cocoa_cleanup(void) -{ - COCOA_DEBUG("qemu_cocoa: cocoa_cleanup\n"); - g_free(dcl); -} - -static const DisplayChangeListenerOps dcl_ops = { - .dpy_name = "cocoa", - .dpy_gfx_update = cocoa_update, - .dpy_gfx_switch = cocoa_switch, - .dpy_refresh = cocoa_refresh, -}; - static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts) { COCOA_DEBUG("qemu_cocoa: cocoa_display_init\n"); @@ -1869,14 +1869,8 @@ static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts) cursor_hide = 0; } - dcl = g_malloc0(sizeof(DisplayChangeListener)); - // register vga output callbacks - dcl->ops = &dcl_ops; - register_displaychangelistener(dcl); - - // register cleanup function - atexit(cocoa_cleanup); + register_displaychangelistener(&dcl); } static QemuDisplay qemu_display_cocoa = { diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index e7ca73c7b1..4e8ee88b9b 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -239,11 +239,6 @@ void gtk_gl_area_init(void) display_opengl = 1; } -QEMUGLContext gd_gl_area_get_current_context(DisplayChangeListener *dcl) -{ - return gdk_gl_context_get_current(); -} - int gd_gl_area_make_current(DisplayChangeListener *dcl, QEMUGLContext ctx) { diff --git a/ui/spice-app.c b/ui/spice-app.c index 026124ef56..4325ac2d9c 100644 --- a/ui/spice-app.c +++ b/ui/spice-app.c @@ -129,6 +129,7 @@ static void spice_app_atexit(void) static void spice_app_display_early_init(DisplayOptions *opts) { QemuOpts *qopts; + QemuOptsList *list; GError *err = NULL; if (opts->has_full_screen) { @@ -159,11 +160,16 @@ static void spice_app_display_early_init(DisplayOptions *opts) exit(1); } } + list = qemu_find_opts("spice"); + if (list == NULL) { + error_report("spice-app missing spice support"); + exit(1); + } type_register(&char_vc_type_info); sock_path = g_strjoin("", app_dir, "/", "spice.sock", NULL); - qopts = qemu_opts_create(qemu_find_opts("spice"), NULL, 0, &error_abort); + qopts = qemu_opts_create(list, NULL, 0, &error_abort); qemu_opt_set(qopts, "disable-ticketing", "on", &error_abort); qemu_opt_set(qopts, "unix", "on", &error_abort); qemu_opt_set(qopts, "addr", sock_path, &error_abort); diff --git a/ui/spice-display.c b/ui/spice-display.c index 6f32b66a6e..ad93b953a9 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -846,6 +846,7 @@ static void spice_gl_refresh(DisplayChangeListener *dcl) graphic_hw_update(dcl->con); if (ssd->gl_updates && ssd->have_surface) { qemu_spice_gl_block(ssd, true); + glFlush(); cookie = (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_GL_DRAW_DONE, 0); spice_qxl_gl_draw_async(&ssd->qxl, 0, 0, surface_width(ssd->ds), @@ -1087,6 +1088,7 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl, trace_qemu_spice_gl_update(ssd->qxl.id, w, h, x, y); qemu_spice_gl_block(ssd, true); + glFlush(); cookie = (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_GL_DRAW_DONE, 0); spice_qxl_gl_draw_async(&ssd->qxl, x, y, w, h, cookie); } |