qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v2] Machine menu patch for Mac OS X


From: Programmingkid
Subject: [Qemu-devel] [PATCH v2] Machine menu patch for Mac OS X
Date: Tue, 20 Jan 2015 12:22:44 -0500

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 <address@hidden>

---
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();
 }
-- 
1.7.5.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]