From patchwork Tue Jan 20 17:22:44 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Programmingkid X-Patchwork-Id: 431203 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 082771402D9 for ; Wed, 21 Jan 2015 04:23:41 +1100 (AEDT) Received: from localhost ([::1]:44852 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YDcWf-00005k-Iy for incoming@patchwork.ozlabs.org; Tue, 20 Jan 2015 12:23:37 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41296) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YDcW7-0007ym-48 for qemu-devel@nongnu.org; Tue, 20 Jan 2015 12:23:18 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YDcVs-0007kN-K7 for qemu-devel@nongnu.org; Tue, 20 Jan 2015 12:23:02 -0500 Received: from mail-qc0-x22a.google.com ([2607:f8b0:400d:c01::22a]:65424) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YDcVs-0007j1-EW for qemu-devel@nongnu.org; Tue, 20 Jan 2015 12:22:48 -0500 Received: by mail-qc0-f170.google.com with SMTP id p6so6819176qcv.1 for ; Tue, 20 Jan 2015 09:22:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:content-type:content-transfer-encoding:subject:date:message-id :cc:to:mime-version; bh=98rKku3mPQs0UF4xoPK7GYBBqFxZQA59cwwy1O8Twao=; b=o8JWvcrCz+Sv/pSYxQiDmUCvLjn2xZ2LMtW6JGwtgZyBmLA4tiW9H8SMdm5fQTJZZh kM/8ZtTnb3vJBiH9DP2fBrooe/3Dr2g9W7wFFsAgjuhjg+exug1F9S3o+9Nbs6HZQbEO VRMIG9kdQDgXc+lZys/k9Udqqutoo1zFl0nytXeiG79ZRnjxUbcZ7j9eLxzZzfyj9lwv Jugu0fGisuRj8di1Bp3Mh4smXcDEtpj+u7sNtZ/a06PzBYPNYFi6yw81EV4cvp49vDwI yW8qtYpHbT3BXI7ICaoG+dB481wObaOnfC0zhMtwo97KPmZOcZbyqKrShr16Y6z0vURQ hThQ== X-Received: by 10.140.38.114 with SMTP id s105mr56871146qgs.106.1421774567365; Tue, 20 Jan 2015 09:22:47 -0800 (PST) Received: from [192.168.0.2] (d199-74-164-53.col.wideopenwest.com. [74.199.53.164]) by mx.google.com with ESMTPSA id k91sm8664628qgf.48.2015.01.20.09.22.45 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 20 Jan 2015 09:22:46 -0800 (PST) From: Programmingkid Date: Tue, 20 Jan 2015 12:22:44 -0500 Message-Id: To: Peter Maydell Mime-Version: 1.0 (Apple Message framework v1084) X-Mailer: Apple Mail (2.1084) X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2607:f8b0:400d:c01::22a Cc: qemu-devel qemu-devel Subject: [Qemu-devel] [PATCH v2] Machine menu patch for Mac OS X X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Features: Menu items to switch floppy and CD image files. Menu items to eject floppy and CD image files. Menu item to use /dev/cdrom. Verifies with the user before quitting QEMU by displaying a dialog box. Signed-off-by: John Arbuckle --- Changed setting the window title to pause to displaying the word pause on the window in big red colors. Added "Power Down" menu item. Dynamically adds cdrom and floppy related menu items. Displays verify quit dialog when user pushes close button. ui/cocoa.m | 237 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 236 insertions(+), 1 deletions(-) diff --git a/ui/cocoa.m b/ui/cocoa.m index d37c29b..31a2043 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -29,6 +29,8 @@ #include "ui/console.h" #include "ui/input.h" #include "sysemu/sysemu.h" +#include "qmp-commands.h" +#include "sysemu/blockdev.h" #ifndef MAC_OS_X_VERSION_10_4 #define MAC_OS_X_VERSION_10_4 1040 @@ -64,6 +66,9 @@ static int last_buttons; int gArgc; char **gArgv; +#define MAX_DEVICE_NAME_SIZE 10 +char floppy_drive_name[MAX_DEVICE_NAME_SIZE], cdrom_drive_name[MAX_DEVICE_NAME_SIZE]; +NSTextField * pause_label; // keymap conversion int keymap[] = @@ -239,7 +244,95 @@ static int cocoa_keycode_to_qemu(int keycode) return keymap[keycode]; } +/* Handles any errors that happen with a device transaction */ +static void handleAnyDeviceErrors(Error * err) +{ + if (err) { + NSRunAlertPanel(@"Alert", [NSString stringWithCString: error_get_pretty(err)], @"OK", nil, nil); + error_free(err); + } +} + +/* +Determine if the current emulator has the specified device. +device_name: the name of the device you want: floppy, cd +official_name: QEMU's name for the device: floppy0, ide-cd0 +*/ +static bool emulatorHasDevice(char * device_name, char * official_name) +{ + BlockInfoList * block_device_data; + block_device_data = qmp_query_block(false); + if(block_device_data == NULL) { + return false; + } + while(block_device_data->next != NULL) { + /* If we found the device */ + if (strstr(block_device_data->value->device, device_name)) { + strcpy(official_name, block_device_data->value->device); + qapi_free_BlockInfoList(block_device_data); + return true; + } + block_device_data = block_device_data->next; + } + return false; +} + +/* Determine if the current emulator has a floppy drive */ +static bool emulatorHasFloppy() +{ + if (emulatorHasDevice("floppy", floppy_drive_name)) { + return true; + } else { + return false; + } +} + +/* Determine if the current emulator has a CDROM drive */ +static bool emulatorHasCDROM() +{ + if (emulatorHasDevice("cd", cdrom_drive_name)) { + return true; + } else { + return false; + } +} +/* Adds the Machine menu to the menu bar. */ +/* Has to be added separately because QEMU needs + to be running to determine used devices. +*/ +static void createMachineMenu() +{ + NSMenu * menu; + NSMenuItem * menuItem; + + // Machine menu + menu = [[NSMenu alloc] initWithTitle: @"Machine"]; + [menu setAutoenablesItems: NO]; + [menu addItem: [[[NSMenuItem alloc] initWithTitle: @"Pause" action: @selector(pauseQemu:) keyEquivalent: @""] autorelease]]; + [menu addItem: [[[NSMenuItem alloc] initWithTitle: @"Resume" action: @selector(resumeQemu:) keyEquivalent: @""] autorelease]]; + + if(emulatorHasFloppy() || emulatorHasCDROM()) { + [menu addItem: [NSMenuItem separatorItem]]; + } + + if (emulatorHasFloppy()) { + [menu addItem: [[[NSMenuItem alloc] initWithTitle: @"Eject Floppy" action: @selector(ejectFloppy:) keyEquivalent: @""] autorelease]]; + [menu addItem: [[[NSMenuItem alloc] initWithTitle: @"Change Floppy..." action: @selector(changeFloppy:) keyEquivalent: @""] autorelease]]; + } + if (emulatorHasCDROM()) { + [menu addItem: [[[NSMenuItem alloc] initWithTitle: @"Eject cdrom" action: @selector(ejectCdrom:) keyEquivalent: @""] autorelease]]; + [menu addItem: [[[NSMenuItem alloc] initWithTitle: @"Use cdrom image..." action: @selector(changeCdrom:) keyEquivalent: @""] autorelease]]; + [menu addItem: [[[NSMenuItem alloc] initWithTitle: @"Use real cdrom drive" action: @selector(useRealCdrom:) keyEquivalent: @""] autorelease]]; + } + [menu addItem: [NSMenuItem separatorItem]]; + [menu addItem: [[[NSMenuItem alloc] initWithTitle: @"Reset" action: @selector(restartQemu:) keyEquivalent: @""] autorelease]]; + [menu addItem: [[[NSMenuItem alloc] initWithTitle: @"Power Down" action: @selector(powerDown:) keyEquivalent: @""] autorelease]]; + menuItem = [[[NSMenuItem alloc] initWithTitle: @"Machine" action:nil keyEquivalent:@""] autorelease]; + [menuItem setSubmenu:menu]; + [[NSApp mainMenu] insertItem: menuItem atIndex: 2]; /* Insert after View menu */ + [[menu itemWithTitle: @"Resume"] setEnabled: NO]; +} /* ------------------------------------------------------ @@ -801,6 +894,17 @@ QemuCocoaView *cocoaView; - (void)toggleFullScreen:(id)sender; - (void)showQEMUDoc:(id)sender; - (void)showQEMUTec:(id)sender; +- (void)pauseQemu:(id)sender; +- (void)ejectFloppy:(id)sender; +- (void)ejectCdrom:(id)sender; +- (void)changeCdrom:(id)sender; +- (void)changeFloppy:(id)sender; +- (void)restartQemu:(id)sender; +- (void)useRealCdrom:(id)sender; +- (void)verifyQuit:(id)sender; +- (void)powerDown:(id)sender; +- (void)displayPause; +- (void)removePause; @end @implementation QemuCocoaAppController @@ -833,6 +937,21 @@ QemuCocoaView *cocoaView; [normalWindow makeKeyAndOrderFront:self]; [normalWindow center]; + /* Used for displaying pause on the screen */ + pause_label = [NSTextField new]; + [pause_label setBezeled:NO]; + [pause_label setDrawsBackground:NO]; + [pause_label setEditable:NO]; + [pause_label setSelectable:NO]; + [pause_label setStringValue: @"Paused"]; + [pause_label setFont: [NSFont fontWithName: @"Helvetica" size: 90]]; + [pause_label setTextColor: [NSColor redColor]]; + [pause_label sizeToFit]; + + /* Verify with the user before quitting QEMU */ + NSButton *closeButton = [normalWindow standardWindowButton:NSWindowCloseButton]; + [closeButton setTarget: self]; + [closeButton setAction: @selector(verifyQuit:)]; } return self; } @@ -943,6 +1062,119 @@ QemuCocoaView *cocoaView; [[NSWorkspace sharedWorkspace] openFile:[NSString stringWithFormat:@"%@/../doc/qemu/qemu-tech.html", [[NSBundle mainBundle] resourcePath]] withApplication:@"Help Viewer"]; } + +/* Pause the guest */ +- (void)pauseQemu:(id)sender +{ + qmp_stop(NULL); + [sender setEnabled: NO]; + [[[sender menu] itemWithTitle: @"Resume"] setEnabled: YES]; + [self displayPause]; +} + +/* Resume running the guest operating system */ +- (void)resumeQemu: (id) sender +{ + qmp_cont(NULL); + [sender setEnabled: NO]; + [[[sender menu] itemWithTitle: @"Pause"] setEnabled: YES]; + [self removePause]; +} + +/* Eject the floppy0 disk */ +- (void)ejectFloppy:(id)sender +{ + Error *err = NULL; + qmp_eject(floppy_drive_name, false, false, &err); + handleAnyDeviceErrors(err); +} + +/* Displays a dialog box asking the user to select a floppy image to load */ +- (void)changeFloppy:(id)sender +{ + NSOpenPanel * open_panel; + open_panel = [NSOpenPanel openPanel]; + [open_panel setCanChooseFiles: YES]; + [open_panel setAllowsMultipleSelection: NO]; + if([open_panel runModalForDirectory: nil file: nil] == NSOKButton) { + Error *err = NULL; + NSString * file = [[open_panel filenames] objectAtIndex: 0]; + qmp_change_blockdev(floppy_drive_name, [file cString], "raw", &err); + handleAnyDeviceErrors(err); + } +} + +// Ejects the cdrom +- (void)ejectCdrom:(id)sender +{ + Error *err = NULL; + qmp_eject(cdrom_drive_name, false, false, &err); + handleAnyDeviceErrors(err); +} + +/* Displays a dialog box asking the user to select a CD image to load */ +- (void)changeCdrom:(id)sender +{ + NSOpenPanel * open_panel; + open_panel = [NSOpenPanel openPanel]; + [open_panel setCanChooseFiles: YES]; + [open_panel setAllowsMultipleSelection: NO]; + if([open_panel runModalForDirectory: nil file: nil] == NSOKButton) { + NSString * file = [[open_panel filenames] objectAtIndex: 0]; + Error *err = NULL; + qmp_change_blockdev(cdrom_drive_name, [file cString], "raw", &err); + handleAnyDeviceErrors(err); + } +} + +/* Restarts QEMU */ +- (void)restartQemu:(id)sender +{ + qemu_system_reset_request(); +} + +/* Switches QEMU to use the real cdrom drive */ +- (void)useRealCdrom:(id)sender +{ + Error *err = NULL; + qmp_change_blockdev(cdrom_drive_name, "/dev/cdrom", "raw", &err); + handleAnyDeviceErrors(err); +} + +/* Verifies if the user really wants to quit */ +- (void)verifyQuit:(id)sender +{ + NSInteger response; + response = NSRunAlertPanel(@"Quit?", @"Are you sure you want to quit?", @"Cancel", @"Quit", nil); + if(response == NSAlertAlternateReturn) + qmp_quit(NULL); +} + +/* Powers down the emulator */ +- (void)powerDown:(id)sender +{ + qmp_system_powerdown(NULL); +} + +/* Displays the word pause on the screen */ +- (void)displayPause +{ + /* Coordinates have to be calculated each time because the window can change its size */ + int xCoord, yCoord, width, height; + xCoord = ([normalWindow frame].size.width - [pause_label frame].size.width)/2; + yCoord = [normalWindow frame].size.height - [pause_label frame].size.height - ([pause_label frame].size.height * .5); + width = [pause_label frame].size.width; + height = [pause_label frame].size.height; + [pause_label setFrame: NSMakeRect(xCoord, yCoord, width, height)]; + [cocoaView addSubview: pause_label]; +} + +/* Removes the word pause from the screen */ +- (void)removePause +{ + [pause_label removeFromSuperview]; +} + @end @@ -997,7 +1229,7 @@ int main (int argc, const char * argv[]) { [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; [menu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; // Show All [menu addItem:[NSMenuItem separatorItem]]; //Separator - [menu addItemWithTitle:@"Quit QEMU" action:@selector(terminate:) keyEquivalent:@"q"]; + [menu addItemWithTitle:@"Quit QEMU" action:@selector(verifyQuit:) keyEquivalent:@"q"]; menuItem = [[NSMenuItem alloc] initWithTitle:@"Apple" action:nil keyEquivalent:@""]; [menuItem setSubmenu:menu]; [[NSApp mainMenu] addItem:menuItem]; @@ -1128,4 +1360,7 @@ void cocoa_display_init(DisplayState *ds, int full_screen) // register cleanup function atexit(cocoa_cleanup); + + /* Creates and adds the Machine menu to the menubar */ + createMachineMenu(); }