#include "sysemu/cpu-throttle.h"
#include "qapi/error.h"
#include "qapi/qapi-commands-block.h"
+#include "qapi/qapi-commands-machine.h"
#include "qapi/qapi-commands-misc.h"
#include "sysemu/blockdev.h"
#include "qemu-version.h"
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;
[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.
QEMUScreen screen;
NSWindow *fullScreenWindow;
float cx,cy,cw,ch,cdx,cdy;
- CGDataProviderRef dataProviderRef;
pixman_image_t *pixman_image;
BOOL modifiers_state[256];
BOOL isMouseGrabbed;
self = [super initWithFrame:frameRect];
if (self) {
- screen.bitsPerComponent = 8;
- screen.bitsPerPixel = 32;
screen.width = frameRect.size.width;
screen.height = frameRect.size.height;
{
COCOA_DEBUG("QemuCocoaView: dealloc\n");
- if (dataProviderRef) {
- CGDataProviderRelease(dataProviderRef);
+ if (pixman_image) {
pixman_image_unref(pixman_image);
}
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,
[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(
CGImageRelease (clipImageRef);
}
CGImageRelease (imageRef);
+ CGDataProviderRelease(dataProviderRef);
}
}
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.
}
// 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) {
// 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
}
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];
}
}
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:
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:
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:
/* 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();
}
/*
[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) {
* 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;
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);
}
}
});
- (void) openDocumentation: (NSString *) filename
{
/* Where to look for local files */
- NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"../docs/"};
+ NSString *path_array[] = {@"../share/doc/qemu/", @"../doc/qemu/", @"docs/"};
NSString *full_file_path;
+ NSURL *full_file_url;
/* iterate thru the possible paths until the file is found */
int index;
full_file_path = [full_file_path stringByDeletingLastPathComponent];
full_file_path = [NSString stringWithFormat: @"%@/%@%@", full_file_path,
path_array[index], filename];
- if ([[NSWorkspace sharedWorkspace] openFile: full_file_path] == YES) {
+ full_file_url = [NSURL fileURLWithPath: full_file_path
+ isDirectory: false];
+ if ([[NSWorkspace sharedWorkspace] openURL: full_file_url] == YES) {
return;
}
}
[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");
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 = {