aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2021-02-19 22:20:17 +0000
committerPeter Maydell <peter.maydell@linaro.org>2021-02-19 22:20:17 +0000
commitd6798cc01d6edabaa4e326359b69f08d022bf4c7 (patch)
tree3b8e38b434a5cdf4a668f2a2ac7f72100b1041b2
parente90ef02389dc8b57eaea22b290244609d720a8bf (diff)
parent075e7a5b7f3c640823fce76c8dab503c42f0d7f6 (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.h1
-rw-r--r--ui/cocoa.m126
-rw-r--r--ui/gtk-gl-area.c5
-rw-r--r--ui/spice-app.c8
-rw-r--r--ui/spice-display.c2
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);
}