|
@@ -54,6 +54,10 @@
|
|
#define MAC_OS_X_VERSION_10_13 101300
|
|
#define MAC_OS_X_VERSION_10_13 101300
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+#ifndef MAC_OS_VERSION_14_0
|
|
|
|
+#define MAC_OS_VERSION_14_0 140000
|
|
|
|
+#endif
|
|
|
|
+
|
|
/* 10.14 deprecates NSOnState and NSOffState in favor of
|
|
/* 10.14 deprecates NSOnState and NSOffState in favor of
|
|
* NSControlStateValueOn/Off, which were introduced in 10.13.
|
|
* NSControlStateValueOn/Off, which were introduced in 10.13.
|
|
* Define for older versions
|
|
* Define for older versions
|
|
@@ -89,7 +93,6 @@ static void cocoa_switch(DisplayChangeListener *dcl,
|
|
|
|
|
|
static void cocoa_refresh(DisplayChangeListener *dcl);
|
|
static void cocoa_refresh(DisplayChangeListener *dcl);
|
|
|
|
|
|
-static NSWindow *normalWindow;
|
|
|
|
static const DisplayChangeListenerOps dcl_ops = {
|
|
static const DisplayChangeListenerOps dcl_ops = {
|
|
.dpy_name = "cocoa",
|
|
.dpy_name = "cocoa",
|
|
.dpy_gfx_update = cocoa_update,
|
|
.dpy_gfx_update = cocoa_update,
|
|
@@ -99,12 +102,11 @@ static void cocoa_switch(DisplayChangeListener *dcl,
|
|
static DisplayChangeListener dcl = {
|
|
static DisplayChangeListener dcl = {
|
|
.ops = &dcl_ops,
|
|
.ops = &dcl_ops,
|
|
};
|
|
};
|
|
-static int last_buttons;
|
|
|
|
static int cursor_hide = 1;
|
|
static int cursor_hide = 1;
|
|
static int left_command_key_enabled = 1;
|
|
static int left_command_key_enabled = 1;
|
|
static bool swap_opt_cmd;
|
|
static bool swap_opt_cmd;
|
|
|
|
|
|
-static bool stretch_video;
|
|
|
|
|
|
+static CGInterpolationQuality zoom_interpolation = kCGInterpolationNone;
|
|
static NSTextField *pauseLabel;
|
|
static NSTextField *pauseLabel;
|
|
|
|
|
|
static bool allow_events;
|
|
static bool allow_events;
|
|
@@ -304,20 +306,17 @@ static void handleAnyDeviceErrors(Error * err)
|
|
*/
|
|
*/
|
|
@interface QemuCocoaView : NSView
|
|
@interface QemuCocoaView : NSView
|
|
{
|
|
{
|
|
|
|
+ NSTrackingArea *trackingArea;
|
|
QEMUScreen screen;
|
|
QEMUScreen screen;
|
|
- NSWindow *fullScreenWindow;
|
|
|
|
- float cx,cy,cw,ch,cdx,cdy;
|
|
|
|
pixman_image_t *pixman_image;
|
|
pixman_image_t *pixman_image;
|
|
QKbdState *kbd;
|
|
QKbdState *kbd;
|
|
BOOL isMouseGrabbed;
|
|
BOOL isMouseGrabbed;
|
|
- BOOL isFullscreen;
|
|
|
|
BOOL isAbsoluteEnabled;
|
|
BOOL isAbsoluteEnabled;
|
|
CFMachPortRef eventsTap;
|
|
CFMachPortRef eventsTap;
|
|
}
|
|
}
|
|
- (void) switchSurface:(pixman_image_t *)image;
|
|
- (void) switchSurface:(pixman_image_t *)image;
|
|
- (void) grabMouse;
|
|
- (void) grabMouse;
|
|
- (void) ungrabMouse;
|
|
- (void) ungrabMouse;
|
|
-- (void) toggleFullScreen:(id)sender;
|
|
|
|
- (void) setFullGrab:(id)sender;
|
|
- (void) setFullGrab:(id)sender;
|
|
- (void) handleMonitorInput:(NSEvent *)event;
|
|
- (void) handleMonitorInput:(NSEvent *)event;
|
|
- (bool) handleEvent:(NSEvent *)event;
|
|
- (bool) handleEvent:(NSEvent *)event;
|
|
@@ -333,8 +332,6 @@ - (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled;
|
|
*/
|
|
*/
|
|
- (BOOL) isMouseGrabbed;
|
|
- (BOOL) isMouseGrabbed;
|
|
- (BOOL) isAbsoluteEnabled;
|
|
- (BOOL) isAbsoluteEnabled;
|
|
-- (float) cdx;
|
|
|
|
-- (float) cdy;
|
|
|
|
- (QEMUScreen) gscreen;
|
|
- (QEMUScreen) gscreen;
|
|
- (void) raiseAllKeys;
|
|
- (void) raiseAllKeys;
|
|
@end
|
|
@end
|
|
@@ -365,6 +362,9 @@ - (id)initWithFrame:(NSRect)frameRect
|
|
screen.width = frameRect.size.width;
|
|
screen.width = frameRect.size.width;
|
|
screen.height = frameRect.size.height;
|
|
screen.height = frameRect.size.height;
|
|
kbd = qkbd_state_init(dcl.con);
|
|
kbd = qkbd_state_init(dcl.con);
|
|
|
|
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_14_0
|
|
|
|
+ [self setClipsToBounds:YES];
|
|
|
|
+#endif
|
|
|
|
|
|
}
|
|
}
|
|
return self;
|
|
return self;
|
|
@@ -392,46 +392,43 @@ - (BOOL) isOpaque
|
|
return YES;
|
|
return YES;
|
|
}
|
|
}
|
|
|
|
|
|
-- (BOOL) screenContainsPoint:(NSPoint) p
|
|
|
|
|
|
+- (void) removeTrackingRect
|
|
{
|
|
{
|
|
- return (p.x > -1 && p.x < screen.width && p.y > -1 && p.y < screen.height);
|
|
|
|
|
|
+ if (trackingArea) {
|
|
|
|
+ [self removeTrackingArea:trackingArea];
|
|
|
|
+ [trackingArea release];
|
|
|
|
+ trackingArea = nil;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
-/* Get location of event and convert to virtual screen coordinate */
|
|
|
|
-- (CGPoint) screenLocationOfEvent:(NSEvent *)ev
|
|
|
|
|
|
+- (void) frameUpdated
|
|
{
|
|
{
|
|
- NSWindow *eventWindow = [ev window];
|
|
|
|
- // XXX: Use CGRect and -convertRectFromScreen: to support macOS 10.10
|
|
|
|
- CGRect r = CGRectZero;
|
|
|
|
- r.origin = [ev locationInWindow];
|
|
|
|
- if (!eventWindow) {
|
|
|
|
- if (!isFullscreen) {
|
|
|
|
- return [[self window] convertRectFromScreen:r].origin;
|
|
|
|
- } else {
|
|
|
|
- CGPoint locationInSelfWindow = [[self window] convertRectFromScreen:r].origin;
|
|
|
|
- CGPoint loc = [self convertPoint:locationInSelfWindow fromView:nil];
|
|
|
|
- if (stretch_video) {
|
|
|
|
- loc.x /= cdx;
|
|
|
|
- loc.y /= cdy;
|
|
|
|
- }
|
|
|
|
- return loc;
|
|
|
|
- }
|
|
|
|
- } else if ([[self window] isEqual:eventWindow]) {
|
|
|
|
- if (!isFullscreen) {
|
|
|
|
- return r.origin;
|
|
|
|
- } else {
|
|
|
|
- CGPoint loc = [self convertPoint:r.origin fromView:nil];
|
|
|
|
- if (stretch_video) {
|
|
|
|
- loc.x /= cdx;
|
|
|
|
- loc.y /= cdy;
|
|
|
|
- }
|
|
|
|
- return loc;
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- return [[self window] convertRectFromScreen:[eventWindow convertRectToScreen:r]].origin;
|
|
|
|
|
|
+ [self removeTrackingRect];
|
|
|
|
+
|
|
|
|
+ if ([self window]) {
|
|
|
|
+ NSTrackingAreaOptions options = NSTrackingActiveInKeyWindow |
|
|
|
|
+ NSTrackingMouseEnteredAndExited |
|
|
|
|
+ NSTrackingMouseMoved;
|
|
|
|
+ trackingArea = [[NSTrackingArea alloc] initWithRect:[self frame]
|
|
|
|
+ options:options
|
|
|
|
+ owner:self
|
|
|
|
+ userInfo:nil];
|
|
|
|
+ [self addTrackingArea:trackingArea];
|
|
|
|
+ [self updateUIInfo];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+- (void) viewDidMoveToWindow
|
|
|
|
+{
|
|
|
|
+ [self resizeWindow];
|
|
|
|
+ [self frameUpdated];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (void) viewWillMoveToWindow:(NSWindow *)newWindow
|
|
|
|
+{
|
|
|
|
+ [self removeTrackingRect];
|
|
|
|
+}
|
|
|
|
+
|
|
- (void) hideCursor
|
|
- (void) hideCursor
|
|
{
|
|
{
|
|
if (!cursor_hide) {
|
|
if (!cursor_hide) {
|
|
@@ -455,7 +452,7 @@ - (void) drawRect:(NSRect) rect
|
|
// get CoreGraphic context
|
|
// get CoreGraphic context
|
|
CGContextRef viewContextRef = [[NSGraphicsContext currentContext] CGContext];
|
|
CGContextRef viewContextRef = [[NSGraphicsContext currentContext] CGContext];
|
|
|
|
|
|
- CGContextSetInterpolationQuality (viewContextRef, kCGInterpolationNone);
|
|
|
|
|
|
+ CGContextSetInterpolationQuality (viewContextRef, zoom_interpolation);
|
|
CGContextSetShouldAntialias (viewContextRef, NO);
|
|
CGContextSetShouldAntialias (viewContextRef, NO);
|
|
|
|
|
|
// draw screen bitmap directly to Core Graphics context
|
|
// draw screen bitmap directly to Core Graphics context
|
|
@@ -497,10 +494,8 @@ - (void) drawRect:(NSRect) rect
|
|
|
|
|
|
[self getRectsBeingDrawn:&rectList count:&rectCount];
|
|
[self getRectsBeingDrawn:&rectList count:&rectCount];
|
|
for (i = 0; i < rectCount; i++) {
|
|
for (i = 0; i < rectCount; i++) {
|
|
- clipRect.origin.x = rectList[i].origin.x / cdx;
|
|
|
|
- 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;
|
|
|
|
|
|
+ clipRect = rectList[i];
|
|
|
|
+ clipRect.origin.y = (float)h - (clipRect.origin.y + clipRect.size.height);
|
|
clipImageRef = CGImageCreateWithImageInRect(
|
|
clipImageRef = CGImageCreateWithImageInRect(
|
|
imageRef,
|
|
imageRef,
|
|
clipRect
|
|
clipRect
|
|
@@ -513,39 +508,33 @@ - (void) drawRect:(NSRect) rect
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-- (void) setContentDimensions
|
|
|
|
|
|
+- (NSSize) screenSafeAreaSize
|
|
{
|
|
{
|
|
- COCOA_DEBUG("QemuCocoaView: setContentDimensions\n");
|
|
|
|
|
|
+ NSSize size = [[[self window] screen] frame].size;
|
|
|
|
+ NSEdgeInsets insets = [[[self window] screen] safeAreaInsets];
|
|
|
|
+ size.width -= insets.left + insets.right;
|
|
|
|
+ size.height -= insets.top + insets.bottom;
|
|
|
|
+ return size;
|
|
|
|
+}
|
|
|
|
|
|
- if (isFullscreen) {
|
|
|
|
- cdx = [[NSScreen mainScreen] frame].size.width / (float)screen.width;
|
|
|
|
- cdy = [[NSScreen mainScreen] frame].size.height / (float)screen.height;
|
|
|
|
|
|
+- (void) resizeWindow
|
|
|
|
+{
|
|
|
|
+ [[self window] setContentAspectRatio:NSMakeSize(screen.width, screen.height)];
|
|
|
|
|
|
- /* stretches video, but keeps same aspect ratio */
|
|
|
|
- if (stretch_video == true) {
|
|
|
|
- /* use smallest stretch value - prevents clipping on sides */
|
|
|
|
- if (MIN(cdx, cdy) == cdx) {
|
|
|
|
- cdy = cdx;
|
|
|
|
- } else {
|
|
|
|
- cdx = cdy;
|
|
|
|
- }
|
|
|
|
- } else { /* No stretching */
|
|
|
|
- cdx = cdy = 1;
|
|
|
|
- }
|
|
|
|
- cw = screen.width * cdx;
|
|
|
|
- ch = screen.height * cdy;
|
|
|
|
- cx = ([[NSScreen mainScreen] frame].size.width - cw) / 2.0;
|
|
|
|
- cy = ([[NSScreen mainScreen] frame].size.height - ch) / 2.0;
|
|
|
|
- } else {
|
|
|
|
- cx = 0;
|
|
|
|
- cy = 0;
|
|
|
|
- cw = screen.width;
|
|
|
|
- ch = screen.height;
|
|
|
|
- cdx = 1.0;
|
|
|
|
- cdy = 1.0;
|
|
|
|
|
|
+ if (!([[self window] styleMask] & NSWindowStyleMaskResizable)) {
|
|
|
|
+ [[self window] setContentSize:NSMakeSize(screen.width, screen.height)];
|
|
|
|
+ [[self window] center];
|
|
|
|
+ } else if ([[self window] styleMask] & NSWindowStyleMaskFullScreen) {
|
|
|
|
+ [[self window] setContentSize:[self screenSafeAreaSize]];
|
|
|
|
+ [[self window] center];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+- (void) updateBounds
|
|
|
|
+{
|
|
|
|
+ [self setBoundsSize:NSMakeSize(screen.width, screen.height)];
|
|
|
|
+}
|
|
|
|
+
|
|
- (void) updateUIInfoLocked
|
|
- (void) updateUIInfoLocked
|
|
{
|
|
{
|
|
/* Must be called with the BQL, i.e. via updateUIInfo */
|
|
/* Must be called with the BQL, i.e. via updateUIInfo */
|
|
@@ -561,9 +550,10 @@ - (void) updateUIInfoLocked
|
|
CGDirectDisplayID display = [[description objectForKey:@"NSScreenNumber"] unsignedIntValue];
|
|
CGDirectDisplayID display = [[description objectForKey:@"NSScreenNumber"] unsignedIntValue];
|
|
NSSize screenSize = [[[self window] screen] frame].size;
|
|
NSSize screenSize = [[[self window] screen] frame].size;
|
|
CGSize screenPhysicalSize = CGDisplayScreenSize(display);
|
|
CGSize screenPhysicalSize = CGDisplayScreenSize(display);
|
|
|
|
+ bool isFullscreen = ([[self window] styleMask] & NSWindowStyleMaskFullScreen) != 0;
|
|
CVDisplayLinkRef displayLink;
|
|
CVDisplayLinkRef displayLink;
|
|
|
|
|
|
- frameSize = isFullscreen ? screenSize : [self frame].size;
|
|
|
|
|
|
+ frameSize = isFullscreen ? [self screenSafeAreaSize] : [self frame].size;
|
|
|
|
|
|
if (!CVDisplayLinkCreateWithCGDisplay(display, &displayLink)) {
|
|
if (!CVDisplayLinkCreateWithCGDisplay(display, &displayLink)) {
|
|
CVTime period = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(displayLink);
|
|
CVTime period = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(displayLink);
|
|
@@ -610,31 +600,20 @@ - (void) updateUIInfo
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
-- (void)viewDidMoveToWindow
|
|
|
|
-{
|
|
|
|
- [self updateUIInfo];
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
- (void) switchSurface:(pixman_image_t *)image
|
|
- (void) switchSurface:(pixman_image_t *)image
|
|
{
|
|
{
|
|
COCOA_DEBUG("QemuCocoaView: switchSurface\n");
|
|
COCOA_DEBUG("QemuCocoaView: switchSurface\n");
|
|
|
|
|
|
int w = pixman_image_get_width(image);
|
|
int w = pixman_image_get_width(image);
|
|
int h = pixman_image_get_height(image);
|
|
int h = pixman_image_get_height(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.
|
|
|
|
- */
|
|
|
|
- bool isResize = (w != screen.width || h != screen.height || cdx == 0.0);
|
|
|
|
|
|
|
|
- int oldh = screen.height;
|
|
|
|
- if (isResize) {
|
|
|
|
|
|
+ if (w != screen.width || h != screen.height) {
|
|
// Resize before we trigger the redraw, or we'll redraw at the wrong size
|
|
// Resize before we trigger the redraw, or we'll redraw at the wrong size
|
|
COCOA_DEBUG("switchSurface: new size %d x %d\n", w, h);
|
|
COCOA_DEBUG("switchSurface: new size %d x %d\n", w, h);
|
|
screen.width = w;
|
|
screen.width = w;
|
|
screen.height = h;
|
|
screen.height = h;
|
|
- [self setContentDimensions];
|
|
|
|
- [self setFrame:NSMakeRect(cx, cy, cw, ch)];
|
|
|
|
|
|
+ [self resizeWindow];
|
|
|
|
+ [self updateBounds];
|
|
}
|
|
}
|
|
|
|
|
|
// update screenBuffer
|
|
// update screenBuffer
|
|
@@ -643,51 +622,6 @@ - (void) switchSurface:(pixman_image_t *)image
|
|
}
|
|
}
|
|
|
|
|
|
pixman_image = image;
|
|
pixman_image = image;
|
|
-
|
|
|
|
- // update windows
|
|
|
|
- if (isFullscreen) {
|
|
|
|
- [[fullScreenWindow contentView] setFrame:[[NSScreen mainScreen] frame]];
|
|
|
|
- [normalWindow setFrame:NSMakeRect([normalWindow frame].origin.x, [normalWindow frame].origin.y - h + oldh, w, h + [normalWindow frame].size.height - oldh) display:NO animate:NO];
|
|
|
|
- } else {
|
|
|
|
- if (qemu_name)
|
|
|
|
- [normalWindow setTitle:[NSString stringWithFormat:@"QEMU %s", qemu_name]];
|
|
|
|
- [normalWindow setFrame:NSMakeRect([normalWindow frame].origin.x, [normalWindow frame].origin.y - h + oldh, w, h + [normalWindow frame].size.height - oldh) display:YES animate:NO];
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (isResize) {
|
|
|
|
- [normalWindow center];
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-- (void) toggleFullScreen:(id)sender
|
|
|
|
-{
|
|
|
|
- COCOA_DEBUG("QemuCocoaView: toggleFullScreen\n");
|
|
|
|
-
|
|
|
|
- if (isFullscreen) { // switch from fullscreen to desktop
|
|
|
|
- isFullscreen = FALSE;
|
|
|
|
- [self ungrabMouse];
|
|
|
|
- [self setContentDimensions];
|
|
|
|
- [fullScreenWindow close];
|
|
|
|
- [normalWindow setContentView: self];
|
|
|
|
- [normalWindow makeKeyAndOrderFront: self];
|
|
|
|
- [NSMenu setMenuBarVisible:YES];
|
|
|
|
- } else { // switch from desktop to fullscreen
|
|
|
|
- isFullscreen = TRUE;
|
|
|
|
- [normalWindow orderOut: nil]; /* Hide the window */
|
|
|
|
- [self grabMouse];
|
|
|
|
- [self setContentDimensions];
|
|
|
|
- [NSMenu setMenuBarVisible:NO];
|
|
|
|
- fullScreenWindow = [[NSWindow alloc] initWithContentRect:[[NSScreen mainScreen] frame]
|
|
|
|
- styleMask:NSWindowStyleMaskBorderless
|
|
|
|
- backing:NSBackingStoreBuffered
|
|
|
|
- defer:NO];
|
|
|
|
- [fullScreenWindow setAcceptsMouseMovedEvents: YES];
|
|
|
|
- [fullScreenWindow setHasShadow:NO];
|
|
|
|
- [fullScreenWindow setBackgroundColor: [NSColor blackColor]];
|
|
|
|
- [self setFrame:NSMakeRect(cx, cy, cw, ch)];
|
|
|
|
- [[fullScreenWindow contentView] addSubview: self];
|
|
|
|
- [fullScreenWindow makeKeyAndOrderFront:self];
|
|
|
|
- }
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- (void) setFullGrab:(id)sender
|
|
- (void) setFullGrab:(id)sender
|
|
@@ -799,11 +733,8 @@ - (bool) handleEventLocked:(NSEvent *)event
|
|
{
|
|
{
|
|
/* Return true if we handled the event, false if it should be given to OSX */
|
|
/* Return true if we handled the event, false if it should be given to OSX */
|
|
COCOA_DEBUG("QemuCocoaView: handleEvent\n");
|
|
COCOA_DEBUG("QemuCocoaView: handleEvent\n");
|
|
- int buttons = 0;
|
|
|
|
|
|
+ InputButton button;
|
|
int keycode = 0;
|
|
int keycode = 0;
|
|
- bool mouse_event = false;
|
|
|
|
- // Location of event in virtual screen coordinates
|
|
|
|
- NSPoint p = [self screenLocationOfEvent:event];
|
|
|
|
NSUInteger modifiers = [event modifierFlags];
|
|
NSUInteger modifiers = [event modifierFlags];
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -947,7 +878,7 @@ - (bool) handleEventLocked:(NSEvent *)event
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- break;
|
|
|
|
|
|
+ return true;
|
|
case NSEventTypeKeyDown:
|
|
case NSEventTypeKeyDown:
|
|
keycode = cocoa_keycode_to_qemu([event keyCode]);
|
|
keycode = cocoa_keycode_to_qemu([event keyCode]);
|
|
|
|
|
|
@@ -983,7 +914,7 @@ - (bool) handleEventLocked:(NSEvent *)event
|
|
} else {
|
|
} else {
|
|
[self handleMonitorInput: event];
|
|
[self handleMonitorInput: event];
|
|
}
|
|
}
|
|
- break;
|
|
|
|
|
|
+ return true;
|
|
case NSEventTypeKeyUp:
|
|
case NSEventTypeKeyUp:
|
|
keycode = cocoa_keycode_to_qemu([event keyCode]);
|
|
keycode = cocoa_keycode_to_qemu([event keyCode]);
|
|
|
|
|
|
@@ -996,153 +927,151 @@ - (bool) handleEventLocked:(NSEvent *)event
|
|
if (qemu_console_is_graphic(NULL)) {
|
|
if (qemu_console_is_graphic(NULL)) {
|
|
qkbd_state_key_event(kbd, keycode, false);
|
|
qkbd_state_key_event(kbd, keycode, false);
|
|
}
|
|
}
|
|
- break;
|
|
|
|
- case NSEventTypeMouseMoved:
|
|
|
|
- if (isAbsoluteEnabled) {
|
|
|
|
- // Cursor re-entered into a window might generate events bound to screen coordinates
|
|
|
|
- // and `nil` window property, and in full screen mode, current window might not be
|
|
|
|
- // key window, where event location alone should suffice.
|
|
|
|
- if (![self screenContainsPoint:p] || !([[self window] isKeyWindow] || isFullscreen)) {
|
|
|
|
- if (isMouseGrabbed) {
|
|
|
|
- [self ungrabMouse];
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- if (!isMouseGrabbed) {
|
|
|
|
- [self grabMouse];
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- mouse_event = true;
|
|
|
|
- break;
|
|
|
|
- case NSEventTypeLeftMouseDown:
|
|
|
|
- buttons |= MOUSE_EVENT_LBUTTON;
|
|
|
|
- mouse_event = true;
|
|
|
|
- break;
|
|
|
|
- case NSEventTypeRightMouseDown:
|
|
|
|
- buttons |= MOUSE_EVENT_RBUTTON;
|
|
|
|
- mouse_event = true;
|
|
|
|
- break;
|
|
|
|
- case NSEventTypeOtherMouseDown:
|
|
|
|
- buttons |= MOUSE_EVENT_MBUTTON;
|
|
|
|
- mouse_event = true;
|
|
|
|
- break;
|
|
|
|
- case NSEventTypeLeftMouseDragged:
|
|
|
|
- buttons |= MOUSE_EVENT_LBUTTON;
|
|
|
|
- mouse_event = true;
|
|
|
|
- break;
|
|
|
|
- case NSEventTypeRightMouseDragged:
|
|
|
|
- buttons |= MOUSE_EVENT_RBUTTON;
|
|
|
|
- mouse_event = true;
|
|
|
|
- break;
|
|
|
|
- case NSEventTypeOtherMouseDragged:
|
|
|
|
- buttons |= MOUSE_EVENT_MBUTTON;
|
|
|
|
- mouse_event = true;
|
|
|
|
- break;
|
|
|
|
- case NSEventTypeLeftMouseUp:
|
|
|
|
- mouse_event = true;
|
|
|
|
- if (!isMouseGrabbed && [self screenContainsPoint:p]) {
|
|
|
|
- /*
|
|
|
|
- * In fullscreen mode, the window of cocoaView may not be the
|
|
|
|
- * key window, therefore the position relative to the virtual
|
|
|
|
- * screen alone will be sufficient.
|
|
|
|
- */
|
|
|
|
- if(isFullscreen || [[self window] isKeyWindow]) {
|
|
|
|
- [self grabMouse];
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- break;
|
|
|
|
- case NSEventTypeRightMouseUp:
|
|
|
|
- mouse_event = true;
|
|
|
|
- break;
|
|
|
|
- case NSEventTypeOtherMouseUp:
|
|
|
|
- mouse_event = true;
|
|
|
|
- break;
|
|
|
|
|
|
+ return true;
|
|
case NSEventTypeScrollWheel:
|
|
case NSEventTypeScrollWheel:
|
|
/*
|
|
/*
|
|
* Send wheel events to the guest regardless of window focus.
|
|
* Send wheel events to the guest regardless of window focus.
|
|
* This is in-line with standard Mac OS X UI behaviour.
|
|
* This is in-line with standard Mac OS X UI behaviour.
|
|
*/
|
|
*/
|
|
|
|
|
|
- /*
|
|
|
|
- * We shouldn't have got a scroll event when deltaY and delta Y
|
|
|
|
- * are zero, hence no harm in dropping the event
|
|
|
|
- */
|
|
|
|
- if ([event deltaY] != 0 || [event deltaX] != 0) {
|
|
|
|
/* Determine if this is a scroll up or scroll down event */
|
|
/* Determine if this is a scroll up or scroll down event */
|
|
- if ([event deltaY] != 0) {
|
|
|
|
- buttons = ([event deltaY] > 0) ?
|
|
|
|
|
|
+ if ([event deltaY] != 0) {
|
|
|
|
+ button = ([event deltaY] > 0) ?
|
|
INPUT_BUTTON_WHEEL_UP : INPUT_BUTTON_WHEEL_DOWN;
|
|
INPUT_BUTTON_WHEEL_UP : INPUT_BUTTON_WHEEL_DOWN;
|
|
- } else if ([event deltaX] != 0) {
|
|
|
|
- buttons = ([event deltaX] > 0) ?
|
|
|
|
|
|
+ } else if ([event deltaX] != 0) {
|
|
|
|
+ button = ([event deltaX] > 0) ?
|
|
INPUT_BUTTON_WHEEL_LEFT : INPUT_BUTTON_WHEEL_RIGHT;
|
|
INPUT_BUTTON_WHEEL_LEFT : INPUT_BUTTON_WHEEL_RIGHT;
|
|
- }
|
|
|
|
-
|
|
|
|
- qemu_input_queue_btn(dcl.con, buttons, true);
|
|
|
|
- qemu_input_event_sync();
|
|
|
|
- qemu_input_queue_btn(dcl.con, buttons, false);
|
|
|
|
- qemu_input_event_sync();
|
|
|
|
|
|
+ } else {
|
|
|
|
+ /*
|
|
|
|
+ * We shouldn't have got a scroll event when deltaY and delta Y
|
|
|
|
+ * are zero, hence no harm in dropping the event
|
|
|
|
+ */
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
|
|
- /*
|
|
|
|
- * Since deltaX/deltaY also report scroll wheel events we prevent mouse
|
|
|
|
- * movement code from executing.
|
|
|
|
- */
|
|
|
|
- mouse_event = false;
|
|
|
|
- break;
|
|
|
|
|
|
+ qemu_input_queue_btn(dcl.con, button, true);
|
|
|
|
+ qemu_input_event_sync();
|
|
|
|
+ qemu_input_queue_btn(dcl.con, button, false);
|
|
|
|
+ qemu_input_event_sync();
|
|
|
|
+
|
|
|
|
+ return true;
|
|
default:
|
|
default:
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
+}
|
|
|
|
|
|
- if (mouse_event) {
|
|
|
|
- /* Don't send button events to the guest unless we've got a
|
|
|
|
- * mouse grab or window focus. If we have neither then this event
|
|
|
|
- * is the user clicking on the background window to activate and
|
|
|
|
- * bring us to the front, which will be done by the sendEvent
|
|
|
|
- * call below. We definitely don't want to pass that click through
|
|
|
|
- * to the guest.
|
|
|
|
- */
|
|
|
|
- if ((isMouseGrabbed || [[self window] isKeyWindow]) &&
|
|
|
|
- (last_buttons != buttons)) {
|
|
|
|
- static uint32_t bmap[INPUT_BUTTON__MAX] = {
|
|
|
|
- [INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON,
|
|
|
|
- [INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
|
|
|
|
- [INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON
|
|
|
|
- };
|
|
|
|
- qemu_input_update_buttons(dcl.con, bmap, last_buttons, buttons);
|
|
|
|
- last_buttons = buttons;
|
|
|
|
- }
|
|
|
|
- if (isMouseGrabbed) {
|
|
|
|
- if (isAbsoluteEnabled) {
|
|
|
|
- /* Note that the origin for Cocoa mouse coords is bottom left, not top left.
|
|
|
|
- * The check on screenContainsPoint is to avoid sending out of range values for
|
|
|
|
- * 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);
|
|
|
|
- }
|
|
|
|
- } 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]);
|
|
|
|
- }
|
|
|
|
|
|
+- (void) handleMouseEvent:(NSEvent *)event button:(InputButton)button down:(bool)down
|
|
|
|
+{
|
|
|
|
+ if (!isMouseGrabbed) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ with_bql(^{
|
|
|
|
+ qemu_input_queue_btn(dcl.con, button, down);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ [self handleMouseEvent:event];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (void) handleMouseEvent:(NSEvent *)event
|
|
|
|
+{
|
|
|
|
+ if (!isMouseGrabbed) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ with_bql(^{
|
|
|
|
+ if (isAbsoluteEnabled) {
|
|
|
|
+ CGFloat d = (CGFloat)screen.height / [self frame].size.height;
|
|
|
|
+ NSPoint p = [event locationInWindow];
|
|
|
|
+
|
|
|
|
+ /* Note that the origin for Cocoa mouse coords is bottom left, not top left. */
|
|
|
|
+ qemu_input_queue_abs(dcl.con, INPUT_AXIS_X, p.x * d, 0, screen.width);
|
|
|
|
+ qemu_input_queue_abs(dcl.con, INPUT_AXIS_Y, screen.height - p.y * d, 0, screen.height);
|
|
} else {
|
|
} else {
|
|
- return false;
|
|
|
|
|
|
+ qemu_input_queue_rel(dcl.con, INPUT_AXIS_X, [event deltaX]);
|
|
|
|
+ qemu_input_queue_rel(dcl.con, INPUT_AXIS_Y, [event deltaY]);
|
|
}
|
|
}
|
|
|
|
+
|
|
qemu_input_event_sync();
|
|
qemu_input_event_sync();
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (void) mouseExited:(NSEvent *)event
|
|
|
|
+{
|
|
|
|
+ if (isAbsoluteEnabled && isMouseGrabbed) {
|
|
|
|
+ [self ungrabMouse];
|
|
}
|
|
}
|
|
- return true;
|
|
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (void) mouseEntered:(NSEvent *)event
|
|
|
|
+{
|
|
|
|
+ if (isAbsoluteEnabled && !isMouseGrabbed) {
|
|
|
|
+ [self grabMouse];
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (void) mouseMoved:(NSEvent *)event
|
|
|
|
+{
|
|
|
|
+ [self handleMouseEvent:event];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (void) mouseDown:(NSEvent *)event
|
|
|
|
+{
|
|
|
|
+ [self handleMouseEvent:event button:INPUT_BUTTON_LEFT down:true];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (void) rightMouseDown:(NSEvent *)event
|
|
|
|
+{
|
|
|
|
+ [self handleMouseEvent:event button:INPUT_BUTTON_RIGHT down:true];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (void) otherMouseDown:(NSEvent *)event
|
|
|
|
+{
|
|
|
|
+ [self handleMouseEvent:event button:INPUT_BUTTON_MIDDLE down:true];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (void) mouseDragged:(NSEvent *)event
|
|
|
|
+{
|
|
|
|
+ [self handleMouseEvent:event];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (void) rightMouseDragged:(NSEvent *)event
|
|
|
|
+{
|
|
|
|
+ [self handleMouseEvent:event];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (void) otherMouseDragged:(NSEvent *)event
|
|
|
|
+{
|
|
|
|
+ [self handleMouseEvent:event];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (void) mouseUp:(NSEvent *)event
|
|
|
|
+{
|
|
|
|
+ if (!isMouseGrabbed) {
|
|
|
|
+ [self grabMouse];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ [self handleMouseEvent:event button:INPUT_BUTTON_LEFT down:false];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (void) rightMouseUp:(NSEvent *)event
|
|
|
|
+{
|
|
|
|
+ [self handleMouseEvent:event button:INPUT_BUTTON_RIGHT down:false];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (void) otherMouseUp:(NSEvent *)event
|
|
|
|
+{
|
|
|
|
+ [self handleMouseEvent:event button:INPUT_BUTTON_MIDDLE down:false];
|
|
}
|
|
}
|
|
|
|
|
|
- (void) grabMouse
|
|
- (void) grabMouse
|
|
{
|
|
{
|
|
COCOA_DEBUG("QemuCocoaView: grabMouse\n");
|
|
COCOA_DEBUG("QemuCocoaView: grabMouse\n");
|
|
|
|
|
|
- if (!isFullscreen) {
|
|
|
|
- if (qemu_name)
|
|
|
|
- [normalWindow setTitle:[NSString stringWithFormat:@"QEMU %s - (Press " UC_CTRL_KEY " " UC_ALT_KEY " G to release Mouse)", qemu_name]];
|
|
|
|
- else
|
|
|
|
- [normalWindow setTitle:@"QEMU - (Press " UC_CTRL_KEY " " UC_ALT_KEY " G to release Mouse)"];
|
|
|
|
- }
|
|
|
|
|
|
+ if (qemu_name)
|
|
|
|
+ [[self window] setTitle:[NSString stringWithFormat:@"QEMU %s - (Press " UC_CTRL_KEY " " UC_ALT_KEY " G to release Mouse)", qemu_name]];
|
|
|
|
+ else
|
|
|
|
+ [[self window] setTitle:@"QEMU - (Press " UC_CTRL_KEY " " UC_ALT_KEY " G to release Mouse)"];
|
|
[self hideCursor];
|
|
[self hideCursor];
|
|
CGAssociateMouseAndMouseCursorPosition(isAbsoluteEnabled);
|
|
CGAssociateMouseAndMouseCursorPosition(isAbsoluteEnabled);
|
|
isMouseGrabbed = TRUE; // while isMouseGrabbed = TRUE, QemuCocoaApp sends all events to [cocoaView handleEvent:]
|
|
isMouseGrabbed = TRUE; // while isMouseGrabbed = TRUE, QemuCocoaApp sends all events to [cocoaView handleEvent:]
|
|
@@ -1152,15 +1081,14 @@ - (void) ungrabMouse
|
|
{
|
|
{
|
|
COCOA_DEBUG("QemuCocoaView: ungrabMouse\n");
|
|
COCOA_DEBUG("QemuCocoaView: ungrabMouse\n");
|
|
|
|
|
|
- if (!isFullscreen) {
|
|
|
|
- if (qemu_name)
|
|
|
|
- [normalWindow setTitle:[NSString stringWithFormat:@"QEMU %s", qemu_name]];
|
|
|
|
- else
|
|
|
|
- [normalWindow setTitle:@"QEMU"];
|
|
|
|
- }
|
|
|
|
|
|
+ if (qemu_name)
|
|
|
|
+ [[self window] setTitle:[NSString stringWithFormat:@"QEMU %s", qemu_name]];
|
|
|
|
+ else
|
|
|
|
+ [[self window] setTitle:@"QEMU"];
|
|
[self unhideCursor];
|
|
[self unhideCursor];
|
|
CGAssociateMouseAndMouseCursorPosition(TRUE);
|
|
CGAssociateMouseAndMouseCursorPosition(TRUE);
|
|
isMouseGrabbed = FALSE;
|
|
isMouseGrabbed = FALSE;
|
|
|
|
+ [self raiseAllButtons];
|
|
}
|
|
}
|
|
|
|
|
|
- (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled {
|
|
- (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled {
|
|
@@ -1171,8 +1099,6 @@ - (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled {
|
|
}
|
|
}
|
|
- (BOOL) isMouseGrabbed {return isMouseGrabbed;}
|
|
- (BOOL) isMouseGrabbed {return isMouseGrabbed;}
|
|
- (BOOL) isAbsoluteEnabled {return isAbsoluteEnabled;}
|
|
- (BOOL) isAbsoluteEnabled {return isAbsoluteEnabled;}
|
|
-- (float) cdx {return cdx;}
|
|
|
|
-- (float) cdy {return cdy;}
|
|
|
|
- (QEMUScreen) gscreen {return screen;}
|
|
- (QEMUScreen) gscreen {return screen;}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1186,6 +1112,15 @@ - (void) raiseAllKeys
|
|
qkbd_state_lift_all_keys(kbd);
|
|
qkbd_state_lift_all_keys(kbd);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+- (void) raiseAllButtons
|
|
|
|
+{
|
|
|
|
+ with_bql(^{
|
|
|
|
+ qemu_input_queue_btn(dcl.con, INPUT_BUTTON_LEFT, false);
|
|
|
|
+ qemu_input_queue_btn(dcl.con, INPUT_BUTTON_RIGHT, false);
|
|
|
|
+ qemu_input_queue_btn(dcl.con, INPUT_BUTTON_MIDDLE, false);
|
|
|
|
+ });
|
|
|
|
+}
|
|
@end
|
|
@end
|
|
|
|
|
|
|
|
|
|
@@ -1200,7 +1135,6 @@ @interface QemuCocoaAppController : NSObject
|
|
{
|
|
{
|
|
}
|
|
}
|
|
- (void)doToggleFullScreen:(id)sender;
|
|
- (void)doToggleFullScreen:(id)sender;
|
|
-- (void)toggleFullScreen:(id)sender;
|
|
|
|
- (void)showQEMUDoc:(id)sender;
|
|
- (void)showQEMUDoc:(id)sender;
|
|
- (void)zoomToFit:(id) sender;
|
|
- (void)zoomToFit:(id) sender;
|
|
- (void)displayConsole:(id)sender;
|
|
- (void)displayConsole:(id)sender;
|
|
@@ -1221,6 +1155,8 @@ - (void)adjustSpeed:(id)sender;
|
|
@implementation QemuCocoaAppController
|
|
@implementation QemuCocoaAppController
|
|
- (id) init
|
|
- (id) init
|
|
{
|
|
{
|
|
|
|
+ NSWindow *window;
|
|
|
|
+
|
|
COCOA_DEBUG("QemuCocoaAppController: init\n");
|
|
COCOA_DEBUG("QemuCocoaAppController: init\n");
|
|
|
|
|
|
self = [super init];
|
|
self = [super init];
|
|
@@ -1234,19 +1170,20 @@ - (id) init
|
|
}
|
|
}
|
|
|
|
|
|
// create a window
|
|
// create a window
|
|
- normalWindow = [[NSWindow alloc] initWithContentRect:[cocoaView frame]
|
|
|
|
|
|
+ window = [[NSWindow alloc] initWithContentRect:[cocoaView frame]
|
|
styleMask:NSWindowStyleMaskTitled|NSWindowStyleMaskMiniaturizable|NSWindowStyleMaskClosable
|
|
styleMask:NSWindowStyleMaskTitled|NSWindowStyleMaskMiniaturizable|NSWindowStyleMaskClosable
|
|
backing:NSBackingStoreBuffered defer:NO];
|
|
backing:NSBackingStoreBuffered defer:NO];
|
|
- if(!normalWindow) {
|
|
|
|
|
|
+ if(!window) {
|
|
error_report("(cocoa) can't create window");
|
|
error_report("(cocoa) can't create window");
|
|
exit(1);
|
|
exit(1);
|
|
}
|
|
}
|
|
- [normalWindow setAcceptsMouseMovedEvents:YES];
|
|
|
|
- [normalWindow setTitle:@"QEMU"];
|
|
|
|
- [normalWindow setContentView:cocoaView];
|
|
|
|
- [normalWindow makeKeyAndOrderFront:self];
|
|
|
|
- [normalWindow center];
|
|
|
|
- [normalWindow setDelegate: self];
|
|
|
|
|
|
+ [window setAcceptsMouseMovedEvents:YES];
|
|
|
|
+ [window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
|
|
|
|
+ [window setTitle:qemu_name ? [NSString stringWithFormat:@"QEMU %s", qemu_name] : @"QEMU"];
|
|
|
|
+ [window setContentView:cocoaView];
|
|
|
|
+ [window makeKeyAndOrderFront:self];
|
|
|
|
+ [window center];
|
|
|
|
+ [window setDelegate: self];
|
|
|
|
|
|
/* Used for displaying pause on the screen */
|
|
/* Used for displaying pause on the screen */
|
|
pauseLabel = [NSTextField new];
|
|
pauseLabel = [NSTextField new];
|
|
@@ -1312,9 +1249,21 @@ - (void)windowDidChangeScreen:(NSNotification *)notification
|
|
[cocoaView updateUIInfo];
|
|
[cocoaView updateUIInfo];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+- (void)windowDidEnterFullScreen:(NSNotification *)notification
|
|
|
|
+{
|
|
|
|
+ [cocoaView grabMouse];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (void)windowDidExitFullScreen:(NSNotification *)notification
|
|
|
|
+{
|
|
|
|
+ [cocoaView resizeWindow];
|
|
|
|
+ [cocoaView ungrabMouse];
|
|
|
|
+}
|
|
|
|
+
|
|
- (void)windowDidResize:(NSNotification *)notification
|
|
- (void)windowDidResize:(NSNotification *)notification
|
|
{
|
|
{
|
|
- [cocoaView updateUIInfo];
|
|
|
|
|
|
+ [cocoaView updateBounds];
|
|
|
|
+ [cocoaView frameUpdated];
|
|
}
|
|
}
|
|
|
|
|
|
/* Called when the user clicks on a window's close button */
|
|
/* Called when the user clicks on a window's close button */
|
|
@@ -1330,6 +1279,14 @@ - (BOOL)windowShouldClose:(id)sender
|
|
return NO;
|
|
return NO;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+- (NSApplicationPresentationOptions) window:(NSWindow *)window
|
|
|
|
+ willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions;
|
|
|
|
+
|
|
|
|
+{
|
|
|
|
+ return (proposedOptions & ~(NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar)) |
|
|
|
|
+ NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Called when QEMU goes into the background. Note that
|
|
* Called when QEMU goes into the background. Note that
|
|
* [-NSWindowDelegate windowDidResignKey:] is used here instead of
|
|
* [-NSWindowDelegate windowDidResignKey:] is used here instead of
|
|
@@ -1349,14 +1306,7 @@ - (void) windowDidResignKey: (NSNotification *)aNotification
|
|
*/
|
|
*/
|
|
- (void) doToggleFullScreen:(id)sender
|
|
- (void) doToggleFullScreen:(id)sender
|
|
{
|
|
{
|
|
- [self toggleFullScreen:(id)sender];
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-- (void)toggleFullScreen:(id)sender
|
|
|
|
-{
|
|
|
|
- COCOA_DEBUG("QemuCocoaAppController: toggleFullScreen\n");
|
|
|
|
-
|
|
|
|
- [cocoaView toggleFullScreen:sender];
|
|
|
|
|
|
+ [[cocoaView window] toggleFullScreen:sender];
|
|
}
|
|
}
|
|
|
|
|
|
- (void) setFullGrab:(id)sender
|
|
- (void) setFullGrab:(id)sender
|
|
@@ -1403,10 +1353,19 @@ - (void)showQEMUDoc:(id)sender
|
|
/* Stretches video to fit host monitor size */
|
|
/* Stretches video to fit host monitor size */
|
|
- (void)zoomToFit:(id) sender
|
|
- (void)zoomToFit:(id) sender
|
|
{
|
|
{
|
|
- stretch_video = !stretch_video;
|
|
|
|
- if (stretch_video == true) {
|
|
|
|
|
|
+ NSWindowStyleMask styleMask = [[cocoaView window] styleMask] ^ NSWindowStyleMaskResizable;
|
|
|
|
+
|
|
|
|
+ [[cocoaView window] setStyleMask:styleMask];
|
|
|
|
+ [sender setState:styleMask & NSWindowStyleMaskResizable ? NSControlStateValueOn : NSControlStateValueOff];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (void)toggleZoomInterpolation:(id) sender
|
|
|
|
+{
|
|
|
|
+ if (zoom_interpolation == kCGInterpolationNone) {
|
|
|
|
+ zoom_interpolation = kCGInterpolationLow;
|
|
[sender setState: NSControlStateValueOn];
|
|
[sender setState: NSControlStateValueOn];
|
|
} else {
|
|
} else {
|
|
|
|
+ zoom_interpolation = kCGInterpolationNone;
|
|
[sender setState: NSControlStateValueOff];
|
|
[sender setState: NSControlStateValueOff];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1414,7 +1373,9 @@ - (void)zoomToFit:(id) sender
|
|
/* Displays the console on the screen */
|
|
/* Displays the console on the screen */
|
|
- (void)displayConsole:(id)sender
|
|
- (void)displayConsole:(id)sender
|
|
{
|
|
{
|
|
- console_select([sender tag]);
|
|
|
|
|
|
+ with_bql(^{
|
|
|
|
+ console_select([sender tag]);
|
|
|
|
+ });
|
|
}
|
|
}
|
|
|
|
|
|
/* Pause the guest */
|
|
/* Pause the guest */
|
|
@@ -1444,8 +1405,8 @@ - (void)displayPause
|
|
{
|
|
{
|
|
/* Coordinates have to be calculated each time because the window can change its size */
|
|
/* Coordinates have to be calculated each time because the window can change its size */
|
|
int xCoord, yCoord, width, height;
|
|
int xCoord, yCoord, width, height;
|
|
- xCoord = ([normalWindow frame].size.width - [pauseLabel frame].size.width)/2;
|
|
|
|
- yCoord = [normalWindow frame].size.height - [pauseLabel frame].size.height - ([pauseLabel frame].size.height * .5);
|
|
|
|
|
|
+ xCoord = ([cocoaView frame].size.width - [pauseLabel frame].size.width)/2;
|
|
|
|
+ yCoord = [cocoaView frame].size.height - [pauseLabel frame].size.height - ([pauseLabel frame].size.height * .5);
|
|
width = [pauseLabel frame].size.width;
|
|
width = [pauseLabel frame].size.width;
|
|
height = [pauseLabel frame].size.height;
|
|
height = [pauseLabel frame].size.height;
|
|
[pauseLabel setFrame: NSMakeRect(xCoord, yCoord, width, height)];
|
|
[pauseLabel setFrame: NSMakeRect(xCoord, yCoord, width, height)];
|
|
@@ -1671,7 +1632,10 @@ static void create_initial_menus(void)
|
|
menu = [[NSMenu alloc] initWithTitle:@"View"];
|
|
menu = [[NSMenu alloc] initWithTitle:@"View"];
|
|
[menu addItem: [[[NSMenuItem alloc] initWithTitle:@"Enter Fullscreen" action:@selector(doToggleFullScreen:) keyEquivalent:@"f"] autorelease]]; // Fullscreen
|
|
[menu addItem: [[[NSMenuItem alloc] initWithTitle:@"Enter Fullscreen" action:@selector(doToggleFullScreen:) keyEquivalent:@"f"] autorelease]]; // Fullscreen
|
|
menuItem = [[[NSMenuItem alloc] initWithTitle:@"Zoom To Fit" action:@selector(zoomToFit:) keyEquivalent:@""] autorelease];
|
|
menuItem = [[[NSMenuItem alloc] initWithTitle:@"Zoom To Fit" action:@selector(zoomToFit:) keyEquivalent:@""] autorelease];
|
|
- [menuItem setState: stretch_video ? NSControlStateValueOn : NSControlStateValueOff];
|
|
|
|
|
|
+ [menuItem setState: [[cocoaView window] styleMask] & NSWindowStyleMaskResizable ? NSControlStateValueOn : NSControlStateValueOff];
|
|
|
|
+ [menu addItem: menuItem];
|
|
|
|
+ menuItem = [[[NSMenuItem alloc] initWithTitle:@"Zoom Interpolation" action:@selector(toggleZoomInterpolation:) keyEquivalent:@""] autorelease];
|
|
|
|
+ [menuItem setState: zoom_interpolation == kCGInterpolationLow ? NSControlStateValueOn : NSControlStateValueOff];
|
|
[menu addItem: menuItem];
|
|
[menu addItem: menuItem];
|
|
menuItem = [[[NSMenuItem alloc] initWithTitle:@"View" action:nil keyEquivalent:@""] autorelease];
|
|
menuItem = [[[NSMenuItem alloc] initWithTitle:@"View" action:nil keyEquivalent:@""] autorelease];
|
|
[menuItem setSubmenu:menu];
|
|
[menuItem setSubmenu:menu];
|
|
@@ -1962,16 +1926,7 @@ static void cocoa_update(DisplayChangeListener *dcl,
|
|
COCOA_DEBUG("qemu_cocoa: cocoa_update\n");
|
|
COCOA_DEBUG("qemu_cocoa: cocoa_update\n");
|
|
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
- NSRect rect;
|
|
|
|
- if ([cocoaView cdx] == 1.0) {
|
|
|
|
- rect = NSMakeRect(x, [cocoaView gscreen].height - y - h, w, h);
|
|
|
|
- } else {
|
|
|
|
- rect = NSMakeRect(
|
|
|
|
- x * [cocoaView cdx],
|
|
|
|
- ([cocoaView gscreen].height - y - h) * [cocoaView cdy],
|
|
|
|
- w * [cocoaView cdx],
|
|
|
|
- h * [cocoaView cdy]);
|
|
|
|
- }
|
|
|
|
|
|
+ NSRect rect = NSMakeRect(x, [cocoaView gscreen].height - y - h, w, h);
|
|
[cocoaView setNeedsDisplayInRect:rect];
|
|
[cocoaView setNeedsDisplayInRect:rect];
|
|
});
|
|
});
|
|
}
|
|
}
|
|
@@ -2048,8 +2003,7 @@ static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts)
|
|
|
|
|
|
/* if fullscreen mode is to be used */
|
|
/* if fullscreen mode is to be used */
|
|
if (opts->has_full_screen && opts->full_screen) {
|
|
if (opts->has_full_screen && opts->full_screen) {
|
|
- [NSApp activateIgnoringOtherApps: YES];
|
|
|
|
- [controller toggleFullScreen: nil];
|
|
|
|
|
|
+ [[cocoaView window] toggleFullScreen: nil];
|
|
}
|
|
}
|
|
if (opts->u.cocoa.has_full_grab && opts->u.cocoa.full_grab) {
|
|
if (opts->u.cocoa.has_full_grab && opts->u.cocoa.full_grab) {
|
|
[controller setFullGrab: nil];
|
|
[controller setFullGrab: nil];
|
|
@@ -2067,7 +2021,11 @@ static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts)
|
|
}
|
|
}
|
|
|
|
|
|
if (opts->u.cocoa.has_zoom_to_fit && opts->u.cocoa.zoom_to_fit) {
|
|
if (opts->u.cocoa.has_zoom_to_fit && opts->u.cocoa.zoom_to_fit) {
|
|
- stretch_video = true;
|
|
|
|
|
|
+ [cocoaView window].styleMask |= NSWindowStyleMaskResizable;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (opts->u.cocoa.has_zoom_interpolation && opts->u.cocoa.zoom_interpolation) {
|
|
|
|
+ zoom_interpolation = kCGInterpolationLow;
|
|
}
|
|
}
|
|
|
|
|
|
create_initial_menus();
|
|
create_initial_menus();
|