ui: spice bugfixes.

ui: first batch of cocoa updates.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEoDKM/7k6F6eZAf59TLbY7tPocTgFAmAwNO4ACgkQTLbY7tPo
 cTh1bg/9HFDW5uJCWgZUX4xFiTYspJAR9OmMKmV/8oPSZEgBpB6Pk8KMHUW/FAIc
 C7h0x7MQPccDk44zBO7CR4rJgPN1V3n4ws6xXtsnjLh+EoDxmC3mUYv7AQIRQL+7
 cF4wBABB2uKJeBNG3yHzLE9KWnHj7jCmSOqC6HQs/erm30fxxLYgWlSpLcLTrga+
 DPbCoZbmh1GE4NNBf6HdoBjwwTSAACgrs1nUsie9PsHsTO4EZu2DdVqC+bL63n7G
 hVDxiMYhNUZEWn8uRZY0S6O1qXkXTXmMruUqGb4uiwcBIHo+EyuWfHDU4hPcz+UE
 awbbt4kkv4MhNQi154271X4z0rwK64ox7R3ut+kZaCquuTI7bzKN+zPqU0ZkfpJm
 rhT83NcrKh523xHBOimxjMSBmnhyIC9vFmI6kpnRxNCF4o6bKmZwHRTovgAYtG1O
 YJjDlV075ZbGZZD8DEZkWjinNu8w/zcme+Ppu7XXNggf3dSWwYWbWRtRNCmhDadS
 zn6PrFrO8nl0y0GYT8mwtacFgkyX593hllmhSYQK075ISvgfORUhZ5C0eMPY2w3H
 RXCWkkbHTaY4N6Fm+OfVBRTFS1rPkWyVOUraydHwi8XdLfCCC3YytYqxslCVa9hu
 SkIQkGOUzTIRiGekCDo4wZwCmUboHxQeJrpLnBHRArnTsNc6Pow=
 =ZdZ1
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Peter Maydell 2021-02-19 22:20:17 +00:00
commit d6798cc01d
5 changed files with 69 additions and 73 deletions

View File

@ -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);

View File

@ -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 = {

View File

@ -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)
{

View File

@ -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);

View File

@ -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);
}