summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
Diffstat (limited to 'ui')
-rw-r--r--ui/cocoa.m123
-rw-r--r--ui/console.c23
-rw-r--r--ui/curses.c20
-rw-r--r--ui/spice-core.c2
-rw-r--r--ui/spice-display.c92
-rw-r--r--ui/vnc-enc-tight.c6
-rw-r--r--ui/vnc.c4
7 files changed, 227 insertions, 43 deletions
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 36c6bf0cb0..26d4a1c07f 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -33,6 +33,7 @@
#include "sysemu/sysemu.h"
#include "qmp-commands.h"
#include "sysemu/blockdev.h"
+#include "qemu-version.h"
#include <Carbon/Carbon.h>
#ifndef MAC_OS_X_VERSION_10_5
@@ -63,7 +64,7 @@ typedef struct {
int bitsPerPixel;
} QEMUScreen;
-NSWindow *normalWindow;
+NSWindow *normalWindow, *about_window;
static DisplayChangeListener *dcl;
static int last_buttons;
@@ -670,7 +671,9 @@ QemuCocoaView *cocoaView;
case NSLeftMouseUp:
mouse_event = true;
if (!isMouseGrabbed && [self screenContainsPoint:p]) {
- [self grabMouse];
+ if([[self window] isKeyWindow]) {
+ [self grabMouse];
+ }
}
break;
case NSRightMouseUp:
@@ -811,7 +814,6 @@ QemuCocoaView *cocoaView;
- (void)doToggleFullScreen:(id)sender;
- (void)toggleFullScreen:(id)sender;
- (void)showQEMUDoc:(id)sender;
-- (void)showQEMUTec:(id)sender;
- (void)zoomToFit:(id) sender;
- (void)displayConsole:(id)sender;
- (void)pauseQEMU:(id)sender;
@@ -824,6 +826,8 @@ QemuCocoaView *cocoaView;
- (void)changeDeviceMedia:(id)sender;
- (BOOL)verifyQuit;
- (void)openDocumentation:(NSString *)filename;
+- (IBAction) do_about_menu_item: (id) sender;
+- (void)make_about_window;
@end
@implementation QemuCocoaAppController
@@ -876,6 +880,7 @@ QemuCocoaView *cocoaView;
supportedImageFileTypes = [NSArray arrayWithObjects: @"img", @"iso", @"dmg",
@"qcow", @"qcow2", @"cloop", @"vmdk", @"cdr",
nil];
+ [self make_about_window];
}
return self;
}
@@ -992,13 +997,6 @@ QemuCocoaView *cocoaView;
[self openDocumentation: @"qemu-doc.html"];
}
-- (void)showQEMUTec:(id)sender
-{
- COCOA_DEBUG("QemuCocoaAppController: showQEMUTec\n");
-
- [self openDocumentation: @"qemu-tech.html"];
-}
-
/* Stretches video to fit host monitor size */
- (void)zoomToFit:(id) sender
{
@@ -1079,7 +1077,8 @@ QemuCocoaView *cocoaView;
}
Error *err = NULL;
- qmp_eject([drive cStringUsingEncoding: NSASCIIStringEncoding], false, false, &err);
+ qmp_eject(true, [drive cStringUsingEncoding: NSASCIIStringEncoding],
+ false, NULL, false, false, &err);
handleAnyDeviceErrors(err);
}
@@ -1112,8 +1111,10 @@ QemuCocoaView *cocoaView;
}
Error *err = NULL;
- qmp_blockdev_change_medium([drive cStringUsingEncoding:
+ qmp_blockdev_change_medium(true,
+ [drive cStringUsingEncoding:
NSASCIIStringEncoding],
+ false, NULL,
[file cStringUsingEncoding:
NSASCIIStringEncoding],
true, "raw",
@@ -1138,6 +1139,101 @@ QemuCocoaView *cocoaView;
}
}
+/* The action method for the About menu item */
+- (IBAction) do_about_menu_item: (id) sender
+{
+ [about_window makeKeyAndOrderFront: nil];
+}
+
+/* Create and display the about dialog */
+- (void)make_about_window
+{
+ /* Make the window */
+ int x = 0, y = 0, about_width = 400, about_height = 200;
+ NSRect window_rect = NSMakeRect(x, y, about_width, about_height);
+ about_window = [[NSWindow alloc] initWithContentRect:window_rect
+ styleMask:NSTitledWindowMask | NSClosableWindowMask |
+ NSMiniaturizableWindowMask
+ backing:NSBackingStoreBuffered
+ defer:NO];
+ [about_window setTitle: @"About"];
+ [about_window setReleasedWhenClosed: NO];
+ [about_window center];
+ NSView *superView = [about_window contentView];
+
+ /* Create the dimensions of the picture */
+ int picture_width = 80, picture_height = 80;
+ x = (about_width - picture_width)/2;
+ y = about_height - picture_height - 10;
+ NSRect picture_rect = NSMakeRect(x, y, picture_width, picture_height);
+
+ /* Get the path to the QEMU binary */
+ NSString *binary_name = [NSString stringWithCString: gArgv[0]
+ encoding: NSASCIIStringEncoding];
+ binary_name = [binary_name lastPathComponent];
+ NSString *program_path = [[NSString alloc] initWithFormat: @"%@/%@",
+ [[NSBundle mainBundle] bundlePath], binary_name];
+
+ /* Make the picture of QEMU */
+ NSImageView *picture_view = [[NSImageView alloc] initWithFrame:
+ picture_rect];
+ NSImage *qemu_image = [[NSWorkspace sharedWorkspace] iconForFile:
+ program_path];
+ [picture_view setImage: qemu_image];
+ [picture_view setImageScaling: NSImageScaleProportionallyUpOrDown];
+ [superView addSubview: picture_view];
+
+ /* Make the name label */
+ x = 0;
+ y = y - 25;
+ int name_width = about_width, name_height = 20;
+ NSRect name_rect = NSMakeRect(x, y, name_width, name_height);
+ NSTextField *name_label = [[NSTextField alloc] initWithFrame: name_rect];
+ [name_label setEditable: NO];
+ [name_label setBezeled: NO];
+ [name_label setDrawsBackground: NO];
+ [name_label setAlignment: NSCenterTextAlignment];
+ NSString *qemu_name = [[NSString alloc] initWithCString: gArgv[0]
+ encoding: NSASCIIStringEncoding];
+ qemu_name = [qemu_name lastPathComponent];
+ [name_label setStringValue: qemu_name];
+ [superView addSubview: name_label];
+
+ /* Set the version label's attributes */
+ x = 0;
+ y = 50;
+ int version_width = about_width, version_height = 20;
+ NSRect version_rect = NSMakeRect(x, y, version_width, version_height);
+ NSTextField *version_label = [[NSTextField alloc] initWithFrame:
+ version_rect];
+ [version_label setEditable: NO];
+ [version_label setBezeled: NO];
+ [version_label setAlignment: NSCenterTextAlignment];
+ [version_label setDrawsBackground: NO];
+
+ /* Create the version string*/
+ NSString *version_string;
+ version_string = [[NSString alloc] initWithFormat:
+ @"QEMU emulator version %s%s", QEMU_VERSION, QEMU_PKGVERSION];
+ [version_label setStringValue: version_string];
+ [superView addSubview: version_label];
+
+ /* Make copyright label */
+ x = 0;
+ y = 35;
+ int copyright_width = about_width, copyright_height = 20;
+ NSRect copyright_rect = NSMakeRect(x, y, copyright_width, copyright_height);
+ NSTextField *copyright_label = [[NSTextField alloc] initWithFrame:
+ copyright_rect];
+ [copyright_label setEditable: NO];
+ [copyright_label setBezeled: NO];
+ [copyright_label setDrawsBackground: NO];
+ [copyright_label setAlignment: NSCenterTextAlignment];
+ [copyright_label setStringValue: [NSString stringWithFormat: @"%s",
+ QEMU_COPYRIGHT]];
+ [superView addSubview: copyright_label];
+}
+
@end
@@ -1185,7 +1281,7 @@ int main (int argc, const char * argv[]) {
// Application menu
menu = [[NSMenu alloc] initWithTitle:@""];
- [menu addItemWithTitle:@"About QEMU" action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; // About QEMU
+ [menu addItemWithTitle:@"About QEMU" action:@selector(do_about_menu_item:) keyEquivalent:@""]; // About QEMU
[menu addItem:[NSMenuItem separatorItem]]; //Separator
[menu addItemWithTitle:@"Hide QEMU" action:@selector(hide:) keyEquivalent:@"h"]; //Hide QEMU
menuItem = (NSMenuItem *)[menu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; // Hide Others
@@ -1231,7 +1327,6 @@ int main (int argc, const char * argv[]) {
// Help menu
menu = [[NSMenu alloc] initWithTitle:@"Help"];
[menu addItem: [[[NSMenuItem alloc] initWithTitle:@"QEMU Documentation" action:@selector(showQEMUDoc:) keyEquivalent:@"?"] autorelease]]; // QEMU Help
- [menu addItem: [[[NSMenuItem alloc] initWithTitle:@"QEMU Technology" action:@selector(showQEMUTec:) keyEquivalent:@""] autorelease]]; // QEMU Help
menuItem = [[[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""] autorelease];
[menuItem setSubmenu:menu];
[[NSApp mainMenu] addItem:menuItem];
diff --git a/ui/console.c b/ui/console.c
index c24bfe422d..fa3e658edd 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -123,6 +123,7 @@ struct QemuConsole {
DisplaySurface *surface;
int dcls;
DisplayChangeListener *gl;
+ bool gl_block;
/* Graphic console state. */
Object *device;
@@ -264,10 +265,10 @@ void graphic_hw_update(QemuConsole *con)
void graphic_hw_gl_block(QemuConsole *con, bool block)
{
- if (!con) {
- con = active_console;
- }
- if (con && con->hw_ops->gl_block) {
+ assert(con != NULL);
+
+ con->gl_block = block;
+ if (con->hw_ops->gl_block) {
con->hw_ops->gl_block(con->hw, block);
}
}
@@ -1142,6 +1143,7 @@ static const int qcode_to_keysym[Q_KEY_CODE__MAX] = {
[Q_KEY_CODE_PGUP] = QEMU_KEY_PAGEUP,
[Q_KEY_CODE_PGDN] = QEMU_KEY_PAGEDOWN,
[Q_KEY_CODE_DELETE] = QEMU_KEY_DELETE,
+ [Q_KEY_CODE_BACKSPACE] = QEMU_KEY_BACKSPACE,
};
bool kbd_put_qcode_console(QemuConsole *s, int qcode)
@@ -1878,6 +1880,12 @@ bool qemu_console_is_fixedsize(QemuConsole *con)
return con && (con->console_type != TEXT_CONSOLE);
}
+bool qemu_console_is_gl_blocked(QemuConsole *con)
+{
+ assert(con != NULL);
+ return con->gl_block;
+}
+
char *qemu_console_get_label(QemuConsole *con)
{
if (con->console_type == GRAPHIC_CONSOLE) {
@@ -2100,6 +2108,13 @@ void qemu_console_resize(QemuConsole *s, int width, int height)
DisplaySurface *surface;
assert(s->console_type == GRAPHIC_CONSOLE);
+
+ if (s->surface &&
+ pixman_image_get_width(s->surface->image) == width &&
+ pixman_image_get_height(s->surface->image) == height) {
+ return;
+ }
+
surface = qemu_create_displaysurface(width, height);
dpy_gfx_replace_surface(s, surface);
}
diff --git a/ui/curses.c b/ui/curses.c
index b47558956c..d06f724879 100644
--- a/ui/curses.c
+++ b/ui/curses.c
@@ -181,7 +181,7 @@ static kbd_layout_t *kbd_layout = NULL;
static void curses_refresh(DisplayChangeListener *dcl)
{
- int chr, nextchr, keysym, keycode, keycode_alt;
+ int chr, keysym, keycode, keycode_alt;
curses_winch_check();
@@ -195,15 +195,9 @@ static void curses_refresh(DisplayChangeListener *dcl)
graphic_hw_text_update(NULL, screen);
- nextchr = ERR;
while (1) {
/* while there are any pending key strokes to process */
- if (nextchr == ERR)
- chr = getch();
- else {
- chr = nextchr;
- nextchr = ERR;
- }
+ chr = getch();
if (chr == ERR)
break;
@@ -224,13 +218,12 @@ static void curses_refresh(DisplayChangeListener *dcl)
/* alt key */
if (keycode == 1) {
- nextchr = getch();
+ int nextchr = getch();
if (nextchr != ERR) {
chr = nextchr;
keycode_alt = ALT;
- keycode = curses2keycode[nextchr];
- nextchr = ERR;
+ keycode = curses2keycode[chr];
if (keycode != -1) {
keycode |= ALT;
@@ -317,7 +310,10 @@ static void curses_refresh(DisplayChangeListener *dcl)
qemu_input_event_send_key_delay(0);
}
} else {
- keysym = curses2qemu[chr];
+ keysym = -1;
+ if (chr < CURSES_KEYS) {
+ keysym = curses2qemu[chr];
+ }
if (keysym == -1)
keysym = chr;
diff --git a/ui/spice-core.c b/ui/spice-core.c
index da0505434a..1452e77fd1 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -796,7 +796,7 @@ void qemu_spice_init(void)
qemu_opt_foreach(opts, add_channel, &tls_port, NULL);
spice_server_set_name(spice_server, qemu_name);
- spice_server_set_uuid(spice_server, qemu_uuid);
+ spice_server_set_uuid(spice_server, (unsigned char *)&qemu_uuid);
seamless_migration = qemu_opt_get_bool(opts, "seamless-migration", 0);
spice_server_set_seamless_migration(spice_server, seamless_migration);
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 99132b69b6..5e6f78a219 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -850,6 +850,74 @@ static void qemu_spice_gl_block_timer(void *opaque)
fprintf(stderr, "WARNING: spice: no gl-draw-done within one second\n");
}
+static void spice_gl_refresh(DisplayChangeListener *dcl)
+{
+ SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
+ uint64_t cookie;
+
+ if (!ssd->ds || qemu_console_is_gl_blocked(ssd->dcl.con)) {
+ return;
+ }
+
+ graphic_hw_update(dcl->con);
+ if (ssd->gl_updates && ssd->have_surface) {
+ qemu_spice_gl_block(ssd, true);
+ 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),
+ surface_height(ssd->ds),
+ cookie);
+ ssd->gl_updates = 0;
+ }
+}
+
+static void spice_gl_update(DisplayChangeListener *dcl,
+ int x, int y, int w, int h)
+{
+ SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
+
+ surface_gl_update_texture(ssd->gls, ssd->ds, x, y, w, h);
+ ssd->gl_updates++;
+}
+
+static void spice_gl_switch(DisplayChangeListener *dcl,
+ struct DisplaySurface *new_surface)
+{
+ SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
+ EGLint stride, fourcc;
+ int fd;
+
+ if (ssd->ds) {
+ surface_gl_destroy_texture(ssd->gls, ssd->ds);
+ }
+ ssd->ds = new_surface;
+ if (ssd->ds) {
+ surface_gl_create_texture(ssd->gls, ssd->ds);
+ fd = egl_get_fd_for_texture(ssd->ds->texture,
+ &stride, &fourcc);
+ if (fd < 0) {
+ surface_gl_destroy_texture(ssd->gls, ssd->ds);
+ return;
+ }
+
+ dprint(1, "%s: %dx%d (stride %d/%d, fourcc 0x%x)\n", __func__,
+ surface_width(ssd->ds), surface_height(ssd->ds),
+ surface_stride(ssd->ds), stride, fourcc);
+
+ /* note: spice server will close the fd */
+ spice_qxl_gl_scanout(&ssd->qxl, fd,
+ surface_width(ssd->ds),
+ surface_height(ssd->ds),
+ stride, fourcc, false);
+ ssd->have_surface = true;
+ ssd->have_scanout = false;
+
+ qemu_spice_gl_monitor_config(ssd, 0, 0,
+ surface_width(ssd->ds),
+ surface_height(ssd->ds));
+ }
+}
+
static QEMUGLContext qemu_spice_gl_create_context(DisplayChangeListener *dcl,
QEMUGLParams *params)
{
@@ -887,6 +955,8 @@ static void qemu_spice_gl_scanout(DisplayChangeListener *dcl,
/* note: spice server will close the fd */
spice_qxl_gl_scanout(&ssd->qxl, fd, backing_width, backing_height,
stride, fourcc, y_0_top);
+ ssd->have_surface = false;
+ ssd->have_scanout = (tex_id != 0);
qemu_spice_gl_monitor_config(ssd, x, y, w, h);
}
@@ -897,6 +967,10 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl,
SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
uint64_t cookie;
+ if (!ssd->have_scanout) {
+ return;
+ }
+
dprint(2, "%s: %dx%d+%d+%d\n", __func__, w, h, x, y);
qemu_spice_gl_block(ssd, true);
cookie = (uintptr_t)qxl_cookie_new(QXL_COOKIE_TYPE_GL_DRAW_DONE, 0);
@@ -904,13 +978,13 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl,
}
static const DisplayChangeListenerOps display_listener_gl_ops = {
- .dpy_name = "spice-egl",
- .dpy_gfx_update = display_update,
- .dpy_gfx_switch = display_switch,
- .dpy_gfx_check_format = qemu_pixman_check_format,
- .dpy_refresh = display_refresh,
- .dpy_mouse_set = display_mouse_set,
- .dpy_cursor_define = display_mouse_define,
+ .dpy_name = "spice-egl",
+ .dpy_gfx_update = spice_gl_update,
+ .dpy_gfx_switch = spice_gl_switch,
+ .dpy_gfx_check_format = console_gl_check_format,
+ .dpy_refresh = spice_gl_refresh,
+ .dpy_mouse_set = display_mouse_set,
+ .dpy_cursor_define = display_mouse_define,
.dpy_gl_ctx_create = qemu_spice_gl_create_context,
.dpy_gl_ctx_destroy = qemu_egl_destroy_context,
@@ -933,10 +1007,12 @@ static void qemu_spice_display_init_one(QemuConsole *con)
#ifdef HAVE_SPICE_GL
if (display_opengl) {
ssd->dcl.ops = &display_listener_gl_ops;
- ssd->dmabuf_fd = -1;
ssd->gl_unblock_bh = qemu_bh_new(qemu_spice_gl_unblock_bh, ssd);
ssd->gl_unblock_timer = timer_new_ms(QEMU_CLOCK_REALTIME,
qemu_spice_gl_block_timer, ssd);
+ ssd->gls = console_gl_init_context();
+ ssd->have_surface = false;
+ ssd->have_scanout = false;
}
#endif
ssd->dcl.con = con;
diff --git a/ui/vnc-enc-tight.c b/ui/vnc-enc-tight.c
index 49df85e763..1e53b1cf84 100644
--- a/ui/vnc-enc-tight.c
+++ b/ui/vnc-enc-tight.c
@@ -707,10 +707,8 @@ check_solid_tile32(VncState *vs, int x, int y, int w, int h,
static bool check_solid_tile(VncState *vs, int x, int y, int w, int h,
uint32_t* color, bool samecolor)
{
- switch (VNC_SERVER_FB_BYTES) {
- case 4:
- return check_solid_tile32(vs, x, y, w, h, color, samecolor);
- }
+ QEMU_BUILD_BUG_ON(VNC_SERVER_FB_BYTES != 4);
+ return check_solid_tile32(vs, x, y, w, h, color, samecolor);
}
static void find_best_solid_area(VncState *vs, int x, int y, int w, int h,
diff --git a/ui/vnc.c b/ui/vnc.c
index d1087c93a5..76a3273e0b 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -911,6 +911,10 @@ static void vnc_dpy_copy(DisplayChangeListener *dcl,
}
}
+ if (!vd->server) {
+ /* no client connected */
+ return;
+ }
/* do bitblit op on the local surface too */
pitch = vnc_server_fb_stride(vd);
src_row = vnc_server_fb_ptr(vd, src_x, src_y);