diff options
Diffstat (limited to 'ui')
-rw-r--r-- | ui/cocoa.m | 123 | ||||
-rw-r--r-- | ui/console.c | 23 | ||||
-rw-r--r-- | ui/curses.c | 20 | ||||
-rw-r--r-- | ui/spice-core.c | 2 | ||||
-rw-r--r-- | ui/spice-display.c | 92 | ||||
-rw-r--r-- | ui/vnc-enc-tight.c | 6 | ||||
-rw-r--r-- | ui/vnc.c | 4 |
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, @@ -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); |