diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst index bc2d33fa83..a98b9f1e64 100644 --- a/DOCS/interface-changes.rst +++ b/DOCS/interface-changes.rst @@ -117,6 +117,7 @@ Interface changes - add `--target-gamut` - change the way display names are retrieved on macOS, usage of options and properties `--fs-screen-name`, `--screen-name` and `display-names` needs to be adjusted + - remove OpenGL cocoa backend that was deprecated in 0.29 --- mpv 0.36.0 --- - add `--target-contrast` - Target luminance value is now also applied when ICC profile is used. diff --git a/meson.build b/meson.build index bbd6b78b28..3b2dc2dd79 100644 --- a/meson.build +++ b/meson.build @@ -388,11 +388,7 @@ if features['cocoa'] 'osdep/macosx_events.m', 'osdep/macosx_menubar.m', 'osdep/main-fn-cocoa.c', - 'osdep/path-macosx.m', - 'video/out/cocoa_common.m', - 'video/out/cocoa/events_view.m', - 'video/out/cocoa/video_view.m', - 'video/out/cocoa/window.m') + 'osdep/path-macosx.m') endif if posix @@ -1079,7 +1075,6 @@ features += {'gl-cocoa': gl_cocoa.allowed()} if features['gl-cocoa'] dependencies += GL features += {'gl': true} - sources += files('video/out/opengl/context_cocoa.c') endif gl_win32 = get_option('gl-win32').require( @@ -1517,8 +1512,8 @@ if features['cocoa'] and features['swift'] endif macos_cocoa_cb = get_option('macos-cocoa-cb').require( - features['cocoa'] and features['swift'], - error_message: 'Either cocoa or swift could not be found!', + features['cocoa'] and features['gl-cocoa'] and features['swift'], + error_message: 'Either cocoa, gl-cocoa or swift could not be found!', ) features += {'macos-cocoa-cb': macos_cocoa_cb.allowed()} if features['macos-cocoa-cb'] diff --git a/video/out/cocoa/events_view.h b/video/out/cocoa/events_view.h deleted file mode 100644 index 27e750accc..0000000000 --- a/video/out/cocoa/events_view.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see . - */ - -#import -#import "video/out/cocoa/mpvadapter.h" - -@interface MpvEventsView : NSView -@property(nonatomic, retain) MpvCocoaAdapter *adapter; -- (BOOL)canHideCursor; -@end diff --git a/video/out/cocoa/events_view.m b/video/out/cocoa/events_view.m deleted file mode 100644 index d297a2ea74..0000000000 --- a/video/out/cocoa/events_view.m +++ /dev/null @@ -1,342 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see . - */ - -#include "input/input.h" -#include "input/keycodes.h" - -#include "video/out/cocoa_common.h" -#include "events_view.h" - -@interface MpvEventsView() -@property(nonatomic, assign) BOOL hasMouseDown; -@property(nonatomic, retain) NSTrackingArea *tracker; -- (int)mpvButtonNumber:(NSEvent*)event; -- (void)mouseDownEvent:(NSEvent *)event; -- (void)mouseUpEvent:(NSEvent *)event; -@end - -@implementation MpvEventsView -@synthesize adapter = _adapter; -@synthesize tracker = _tracker; -@synthesize hasMouseDown = _mouse_down; - -- (id)initWithFrame:(NSRect)frame -{ - self = [super initWithFrame:frame]; - if (self) { - [self registerForDraggedTypes:@[NSFilenamesPboardType, - NSURLPboardType]]; - [self setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; - } - return self; -} - -- (void)drawRect:(NSRect)rect -{ - [[NSColor blackColor] setFill]; - NSRectFill(rect); -} - -// mpv uses flipped coordinates, because X11 uses those. So let's just use them -// as well without having to do any coordinate conversion of mouse positions. -- (BOOL)isFlipped { return YES; } - -- (void)updateTrackingAreas -{ - if (self.tracker) - [self removeTrackingArea:self.tracker]; - - if (![self.adapter mouseEnabled]) - return; - - NSTrackingAreaOptions trackingOptions = - NSTrackingEnabledDuringMouseDrag | - NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | - NSTrackingActiveAlways; - - self.tracker = - [[[NSTrackingArea alloc] initWithRect:[self bounds] - options:trackingOptions - owner:self - userInfo:nil] autorelease]; - - [self addTrackingArea:self.tracker]; - - if (![self containsMouseLocation]) - [self.adapter putKey:MP_KEY_MOUSE_LEAVE withModifiers:0]; -} - -- (NSPoint)mouseLocation -{ - return [self.window mouseLocationOutsideOfEventStream]; -} - -- (BOOL)containsMouseLocation -{ - CGFloat topMargin = 0.0; - CGFloat menuBarHeight = [[NSApp mainMenu] menuBarHeight]; - - // menuBarHeight is 0 when menu bar is hidden in fullscreen - // 1pt to compensate of the black line beneath the menu bar - if ([self.adapter isInFullScreenMode] && menuBarHeight > 0) { - NSRect tr = [NSWindow frameRectForContentRect:CGRectZero - styleMask:NSWindowStyleMaskTitled]; - topMargin = tr.size.height + 1 + menuBarHeight; - } - - NSRect vF = [[self.window screen] frame]; - vF.size.height -= topMargin; - NSRect vFW = [self.window convertRectFromScreen:vF]; - NSRect vFV = [self convertRect:vFW fromView:nil]; - NSPoint pt = [self convertPoint:[self mouseLocation] fromView:nil]; - - // clip bounds to current visibleFrame - NSRect clippedBounds = CGRectIntersection([self bounds], vFV); - return CGRectContainsPoint(clippedBounds, pt); -} - -- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent -{ - return [self.adapter mouseEnabled]; -} - -- (BOOL)acceptsFirstResponder -{ - return [self.adapter keyboardEnabled] || [self.adapter mouseEnabled]; -} - -- (BOOL)becomeFirstResponder -{ - return [self.adapter keyboardEnabled] || [self.adapter mouseEnabled]; -} - -- (BOOL)resignFirstResponder { return YES; } - -- (BOOL)canHideCursor -{ - return !self.hasMouseDown && [self containsMouseLocation] - && [[self window] isKeyWindow]; -} - -- (void)mouseEntered:(NSEvent *)event -{ - [super mouseEntered:event]; - if ([self.adapter mouseEnabled]) { - [self.adapter putKey:MP_KEY_MOUSE_ENTER withModifiers:0]; - } -} - -- (void)mouseExited:(NSEvent *)event -{ - if ([self.adapter mouseEnabled]) { - [self.adapter putKey:MP_KEY_MOUSE_LEAVE withModifiers:0]; - } else { - [super mouseExited:event]; - } -} - -- (NSPoint)convertPointToPixels:(NSPoint)point -{ - point = [self convertPoint:point fromView:nil]; - point = [self convertPointToBacking:point]; - // flip y since isFlipped returning YES doesn't affect the backing - // coordinate system - point.y = -point.y; - return point; -} - -- (void)signalMouseMovement:(NSEvent *)event -{ - NSPoint p = [self convertPointToPixels:[event locationInWindow]]; - [self.adapter signalMouseMovement:p]; -} - -- (void)mouseMoved:(NSEvent *)event -{ - if ([self.adapter mouseEnabled]) { - [self signalMouseMovement:event]; - } else { - [super mouseMoved:event]; - } -} - -- (void)mouseDragged:(NSEvent *)event -{ - if ([self.adapter mouseEnabled]) { - [self signalMouseMovement:event]; - } else { - [super mouseDragged:event]; - } -} - -- (void)mouseDown:(NSEvent *)event -{ - if ([self.adapter mouseEnabled]) { - [self mouseDownEvent:event]; - } else { - [super mouseDown:event]; - } -} - -- (void)mouseUp:(NSEvent *)event -{ - if ([self.adapter mouseEnabled]) { - [self mouseUpEvent:event]; - } else { - [super mouseUp:event]; - } -} - -- (void)rightMouseDown:(NSEvent *)event -{ - if ([self.adapter mouseEnabled]) { - [self mouseDownEvent:event]; - } else { - [super rightMouseUp:event]; - } -} - -- (void)rightMouseUp:(NSEvent *)event -{ - if ([self.adapter mouseEnabled]) { - [self mouseUpEvent:event]; - } else { - [super rightMouseUp:event]; - } -} - -- (void)otherMouseDown:(NSEvent *)event -{ - if ([self.adapter mouseEnabled]) { - [self mouseDownEvent:event]; - } else { - [super otherMouseDown:event]; - } -} - -- (void)otherMouseUp:(NSEvent *)event -{ - if ([self.adapter mouseEnabled]) { - [self mouseUpEvent:event]; - } else { - [super otherMouseUp:event]; - } -} - -- (void)preciseScroll:(NSEvent *)event -{ - CGFloat delta; - int cmd; - - if (fabs([event deltaY]) >= fabs([event deltaX])) { - delta = [event deltaY] * 0.1; - cmd = delta > 0 ? MP_WHEEL_UP : MP_WHEEL_DOWN; - } else { - delta = [event deltaX] * 0.1; - cmd = delta > 0 ? MP_WHEEL_RIGHT : MP_WHEEL_LEFT; - } - - [self.adapter putWheel:cmd delta:fabs(delta)]; -} - -- (void)scrollWheel:(NSEvent *)event -{ - if (![self.adapter mouseEnabled]) { - [super scrollWheel:event]; - return; - } - - if ([event hasPreciseScrollingDeltas]) { - [self preciseScroll:event]; - } else { - const int modifiers = [event modifierFlags]; - const float deltaX = (modifiers & NSEventModifierFlagShift) ? - [event scrollingDeltaY] : [event scrollingDeltaX]; - const float deltaY = (modifiers & NSEventModifierFlagShift) ? - [event scrollingDeltaX] : [event scrollingDeltaY]; - int mpkey; - - if (fabs(deltaY) >= fabs(deltaX)) { - mpkey = deltaY > 0 ? MP_WHEEL_UP : MP_WHEEL_DOWN; - } else { - mpkey = deltaX > 0 ? MP_WHEEL_LEFT : MP_WHEEL_RIGHT; - } - - [self.adapter putKey:mpkey withModifiers:modifiers]; - } -} - -- (void)mouseDownEvent:(NSEvent *)event -{ - [self putMouseEvent:event withState:MP_KEY_STATE_DOWN]; - - if ([event clickCount] > 1) - [self putMouseEvent:event withState:MP_KEY_STATE_UP]; -} - -- (void)mouseUpEvent:(NSEvent *)event -{ - [self putMouseEvent:event withState:MP_KEY_STATE_UP]; -} - -- (void)putMouseEvent:(NSEvent *)event withState:(int)state -{ - self.hasMouseDown = (state == MP_KEY_STATE_DOWN); - int mpkey = [self mpvButtonNumber:event]; - [self.adapter putKey:(mpkey | state) withModifiers:[event modifierFlags]]; -} - -- (NSDragOperation)draggingEntered:(id )sender -{ - NSPasteboard *pboard = [sender draggingPasteboard]; - NSArray *types = [pboard types]; - if ([types containsObject:NSFilenamesPboardType] || - [types containsObject:NSURLPboardType]) { - return NSDragOperationCopy; - } else { - return NSDragOperationNone; - } -} - -- (BOOL)performDragOperation:(id )sender -{ - NSPasteboard *pboard = [sender draggingPasteboard]; - if ([[pboard types] containsObject:NSFilenamesPboardType]) { - NSArray *pbitems = [pboard propertyListForType:NSFilenamesPboardType]; - [self.adapter handleFilesArray:pbitems]; - return YES; - } else if ([[pboard types] containsObject:NSURLPboardType]) { - NSURL *url = [NSURL URLFromPasteboard:pboard]; - [self.adapter handleFilesArray:@[[url absoluteString]]]; - return YES; - } - return NO; -} - -- (int)mpvButtonNumber:(NSEvent*)event -{ - int buttonNumber = [event buttonNumber]; - switch (buttonNumber) { - case 0: return MP_MBTN_LEFT; - case 1: return MP_MBTN_RIGHT; - case 2: return MP_MBTN_MID; - case 3: return MP_MBTN_BACK; - case 4: return MP_MBTN_FORWARD; - default: return MP_MBTN9 - 5 + buttonNumber; - } -} -@end diff --git a/video/out/cocoa/mpvadapter.h b/video/out/cocoa/mpvadapter.h deleted file mode 100644 index 69b3b1ad66..0000000000 --- a/video/out/cocoa/mpvadapter.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see . - */ - -#import -#include "video/out/vo.h" - -@interface MpvCocoaAdapter : NSObject -- (void)setNeedsResize; -- (void)signalMouseMovement:(NSPoint)point; -- (void)putKey:(int)mpkey withModifiers:(int)modifiers; -- (void)putWheel:(int)mpkey delta:(float)delta; -- (void)putCommand:(char*)cmd; -- (void)handleFilesArray:(NSArray *)files; -- (void)didChangeWindowedScreenProfile:(NSNotification *)notification; -- (void)performAsyncResize:(NSSize)size; -- (void)windowDidChangePhysicalScreen; -- (void)windowDidEnterFullScreen; -- (void)windowDidExitFullScreen; - -- (BOOL)isInFullScreenMode; -- (BOOL)wantsNativeFullscreen; -- (BOOL)keyboardEnabled; -- (BOOL)mouseEnabled; - -- (NSScreen *)getTargetScreen; -@property(nonatomic, assign) struct vo *vout; -@end diff --git a/video/out/cocoa/video_view.h b/video/out/cocoa/video_view.h deleted file mode 100644 index 995d9bfd6a..0000000000 --- a/video/out/cocoa/video_view.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see . - */ - -#import -#import "video/out/cocoa/mpvadapter.h" - -@interface MpvVideoView : NSView -@property(nonatomic, retain) MpvCocoaAdapter *adapter; -- (NSRect)frameInPixels; -@end diff --git a/video/out/cocoa/video_view.m b/video/out/cocoa/video_view.m deleted file mode 100644 index 18ad69fcb4..0000000000 --- a/video/out/cocoa/video_view.m +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see . - */ - -#include "video/out/cocoa_common.h" -#include "video_view.h" - -@implementation MpvVideoView -@synthesize adapter = _adapter; - -- (id)initWithFrame:(NSRect)frame -{ - self = [super initWithFrame:frame]; - if (self) { - [self setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; - } - return self; -} - -- (void)setFrameSize:(NSSize)size -{ - [super setFrameSize:size]; - [self.adapter setNeedsResize]; -} - -- (NSRect)frameInPixels -{ - return [self convertRectToBacking:[self frame]]; -} - - -- (void)drawRect:(NSRect)rect -{ - [[NSColor blackColor] setFill]; - NSRectFill(rect); - [self.adapter performAsyncResize:[self frameInPixels].size]; -} -@end diff --git a/video/out/cocoa/window.h b/video/out/cocoa/window.h deleted file mode 100644 index 069e82ad5e..0000000000 --- a/video/out/cocoa/window.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see . - */ - -#import -#import "video/out/cocoa/mpvadapter.h" - -@protocol MpvWindowUpdate -- (void)queueNewVideoSize:(NSSize)newSize; -- (void)updateBorder:(int)border; -@end - -@interface MpvVideoWindow : NSWindow -@property(nonatomic, retain) MpvCocoaAdapter *adapter; -- (BOOL)canBecomeKeyWindow; -- (BOOL)canBecomeMainWindow; -- (void)mulSize:(float)multiplier; -@end diff --git a/video/out/cocoa/window.m b/video/out/cocoa/window.m deleted file mode 100644 index e95578975f..0000000000 --- a/video/out/cocoa/window.m +++ /dev/null @@ -1,454 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see . - */ - -#include - -#include "input/keycodes.h" - -#include "osdep/macosx_events.h" -#include "video/out/cocoa_common.h" - -#include "window.h" - -@interface MpvVideoWindow() -@property(nonatomic, retain) NSScreen *targetScreen; -@property(nonatomic, retain) NSScreen *previousScreen; -@property(nonatomic, retain) NSScreen *currentScreen; -@property(nonatomic, retain) NSScreen *unfScreen; - -- (NSRect)frameRect:(NSRect)frameRect forCenteredContentSize:(NSSize)newSize; -- (void)setCenteredContentSize:(NSSize)newSize; -@end - -@implementation MpvVideoWindow { - NSSize _queued_video_size; - NSRect _unfs_content_frame; - int _is_animating; -} - -@synthesize adapter = _adapter; -@synthesize targetScreen = _target_screen; -@synthesize previousScreen = _previous_screen; -@synthesize currentScreen = _current_screen; -@synthesize unfScreen = _unf_screen; - -- (id)initWithContentRect:(NSRect)content_rect - styleMask:(NSWindowStyleMask)style_mask - backing:(NSBackingStoreType)buffering_type - defer:(BOOL)flag - screen:(NSScreen *)screen -{ - if (self = [super initWithContentRect:content_rect - styleMask:style_mask - backing:buffering_type - defer:flag - screen:screen]) { - [self setBackgroundColor:[NSColor whiteColor]]; - [self setMinSize:NSMakeSize(50,50)]; - [self setCollectionBehavior: NSWindowCollectionBehaviorFullScreenPrimary]; - - self.targetScreen = screen; - self.currentScreen = screen; - self.unfScreen = screen; - _is_animating = 0; - _unfs_content_frame = [self convertRectToScreen:[[self contentView] frame]]; - } - return self; -} - -- (void)setStyleMask:(NSWindowStyleMask)style -{ - NSResponder *nR = [self firstResponder]; - [super setStyleMask:style]; - [self makeFirstResponder:nR]; -} - -- (void)toggleFullScreen:(id)sender -{ - if (_is_animating) - return; - - _is_animating = 1; - - self.targetScreen = [self.adapter getTargetScreen]; - if(![self targetScreen] && ![self previousScreen]) { - self.targetScreen = [self screen]; - } else if (![self targetScreen]) { - self.targetScreen = self.previousScreen; - self.previousScreen = nil; - } else { - self.previousScreen = [self screen]; - } - - if (![self.adapter isInFullScreenMode]) { - _unfs_content_frame = [self convertRectToScreen:[[self contentView] frame]]; - self.unfScreen = [self screen]; - } - - //move window to target screen when going to fullscreen - if (![self.adapter isInFullScreenMode] && ![[self targetScreen] isEqual:[self screen]]) { - NSRect frame = [self calculateWindowPositionForScreen:[self targetScreen] - withoutBounds:NO]; - [self setFrame:frame display:YES]; - } - - if ([self.adapter wantsNativeFullscreen]) - [super toggleFullScreen:sender]; - - if (![self.adapter isInFullScreenMode]) { - [self setToFullScreen]; - } else { - [self setToWindow]; - } -} - -- (void)setToFullScreen -{ - [self setStyleMask:([self styleMask] | NSWindowStyleMaskFullScreen)]; - NSRect frame = [[self targetScreen] frame]; - - if ([self.adapter wantsNativeFullscreen]) { - [self setFrame:frame display:YES]; - } else { - [NSApp setPresentationOptions:NSApplicationPresentationAutoHideMenuBar| - NSApplicationPresentationAutoHideDock]; - [self setFrame:frame display:YES]; - _is_animating = 0; - [self.adapter windowDidEnterFullScreen]; - } -} - -- (void)setToWindow -{ - [self setStyleMask:([self styleMask] & ~NSWindowStyleMaskFullScreen)]; - NSRect frame = [self calculateWindowPositionForScreen:[self targetScreen] - withoutBounds:[[self targetScreen] isEqual:[self screen]]]; - - if ([self.adapter wantsNativeFullscreen]) { - [self setFrame:frame display:YES]; - [self setContentAspectRatio:_unfs_content_frame.size]; - [self setCenteredContentSize:_unfs_content_frame.size]; - } else { - [NSApp setPresentationOptions:NSApplicationPresentationDefault]; - [self setFrame:frame display:YES]; - [self setContentAspectRatio:_unfs_content_frame.size]; - [self setCenteredContentSize:_unfs_content_frame.size]; - _is_animating = 0; - [self.adapter windowDidExitFullScreen]; - } -} - -- (NSArray *)customWindowsToEnterFullScreenForWindow:(NSWindow *)window -{ - return [NSArray arrayWithObject:window]; -} - -- (NSArray*)customWindowsToExitFullScreenForWindow:(NSWindow*)window -{ - return [NSArray arrayWithObject:window]; -} - -// we still need to keep those around or it will use the standard animation -- (void)window:(NSWindow *)window startCustomAnimationToEnterFullScreenWithDuration:(NSTimeInterval)duration {} - -- (void)window:(NSWindow *)window startCustomAnimationToExitFullScreenWithDuration:(NSTimeInterval)duration {} - -- (void)windowDidEnterFullScreen:(NSNotification *)notification -{ - _is_animating = 0; - [self.adapter windowDidEnterFullScreen]; -} - -- (void)windowDidExitFullScreen:(NSNotification *)notification -{ - _is_animating = 0; - [self.adapter windowDidExitFullScreen]; -} - -- (void)windowWillEnterFullScreen:(NSNotification *)notification -{ - [self.adapter windowWillEnterFullScreen:notification]; -} - -- (void)windowWillExitFullScreen:(NSNotification *)notification -{ - [self.adapter windowWillExitFullScreen:notification]; -} - -- (void)windowDidFailToEnterFullScreen:(NSWindow *)window -{ - _is_animating = 0; - [self setToWindow]; - [self.adapter windowDidFailToEnterFullScreen:window]; -} - -- (void)windowDidFailToExitFullScreen:(NSWindow *)window -{ - _is_animating = 0; - [self setToFullScreen]; - [self.adapter windowDidFailToExitFullScreen:window]; -} - -- (void)windowDidChangeBackingProperties:(NSNotification *)notification -{ - // XXX: we maybe only need expose for this - [self.adapter setNeedsResize]; -} - -- (void)windowDidChangeScreen:(NSNotification *)notification -{ - [self.adapter windowDidChangeScreen:notification]; - - if (!_is_animating && ![[self currentScreen] isEqual:[self screen]]) { - self.previousScreen = [self screen]; - } - if (![[self currentScreen] isEqual:[self screen]]) { - [self.adapter windowDidChangePhysicalScreen]; - } - - self.currentScreen = [self screen]; -} - -- (void)windowDidChangeScreenProfile:(NSNotification *)notification -{ - [self.adapter didChangeWindowedScreenProfile:notification]; -} - -- (void)windowDidResignKey:(NSNotification *)notification -{ - [self.adapter windowDidResignKey:notification]; -} - -- (void)windowDidBecomeKey:(NSNotification *)notification -{ - [self.adapter windowDidBecomeKey:notification]; -} - -- (void)windowWillMove:(NSNotification *)notification -{ - [self.adapter windowWillMove:notification]; -} - -- (BOOL)canBecomeMainWindow { return YES; } -- (BOOL)canBecomeKeyWindow { return YES; } - -- (BOOL)windowShouldClose:(id)sender -{ - cocoa_put_key(MP_KEY_CLOSE_WIN); - // We have to wait for MPlayer to handle this, - // otherwise we are in trouble if the - // MP_KEY_CLOSE_WIN handler is disabled - return NO; -} - -- (void)normalSize { [self mulSize:1.0f]; } - -- (void)halfSize { [self mulSize:0.5f];} - -- (void)doubleSize { [self mulSize:2.0f];} - -- (void)mulSize:(float)multiplier -{ - char cmd[50]; - snprintf(cmd, sizeof(cmd), "set window-scale %f", multiplier); - [self.adapter putCommand:cmd]; -} - -- (void)updateBorder:(int)border -{ - int borderStyle = NSWindowStyleMaskTitled|NSWindowStyleMaskClosable| - NSWindowStyleMaskMiniaturizable; - if (border) { - int window_mask = [self styleMask] & ~NSWindowStyleMaskBorderless; - window_mask |= borderStyle; - [self setStyleMask:window_mask]; - } else { - int window_mask = [self styleMask] & ~borderStyle; - window_mask |= NSWindowStyleMaskBorderless; - [self setStyleMask:window_mask]; - } - - if (![self.adapter isInFullScreenMode]) { - // XXX: workaround to force redrawing of window decoration - if (border) { - NSRect frame = [self frame]; - frame.size.width += 1; - [self setFrame:frame display:YES]; - frame.size.width -= 1; - [self setFrame:frame display:YES]; - } - - [self setContentAspectRatio:_unfs_content_frame.size]; - } -} - -- (NSRect)frameRect:(NSRect)f forCenteredContentSize:(NSSize)ns -{ - NSRect cr = [self contentRectForFrameRect:f]; - CGFloat dx = (cr.size.width - ns.width) / 2; - CGFloat dy = (cr.size.height - ns.height) / 2; - return NSInsetRect(f, dx, dy); -} - -- (void)setCenteredContentSize:(NSSize)ns -{ - [self setFrame:[self frameRect:[self frame] forCenteredContentSize:ns] - display:NO - animate:NO]; -} - -- (NSRect)calculateWindowPositionForScreen:(NSScreen *)screen withoutBounds:(BOOL)withoutBounds -{ - NSRect frame = [self frameRectForContentRect:_unfs_content_frame]; - NSRect targetFrame = [screen frame]; - NSRect targetVisibleFrame = [screen visibleFrame]; - NSRect unfsScreenFrame = [self.unfScreen frame]; - NSRect visibleWindow = NSIntersectionRect(unfsScreenFrame, frame); - - // calculate visible area of every side - CGFloat left = frame.origin.x - unfsScreenFrame.origin.x; - CGFloat right = unfsScreenFrame.size.width - - (frame.origin.x - unfsScreenFrame.origin.x + frame.size.width); - CGFloat bottom = frame.origin.y - unfsScreenFrame.origin.y; - CGFloat top = unfsScreenFrame.size.height - - (frame.origin.y - unfsScreenFrame.origin.y + frame.size.height); - - // normalize visible areas, decide which one to take horizontal/vertical - CGFloat x_per = (unfsScreenFrame.size.width - visibleWindow.size.width); - CGFloat y_per = (unfsScreenFrame.size.height - visibleWindow.size.height); - if (x_per != 0) x_per = (left >= 0 || right < 0 ? left : right)/x_per; - if (y_per != 0) y_per = (bottom >= 0 || top < 0 ? bottom : top)/y_per; - - // calculate visible area for every side for target screen - CGFloat x_new_left = targetFrame.origin.x + - (targetFrame.size.width - visibleWindow.size.width)*x_per; - CGFloat x_new_right = targetFrame.origin.x + targetFrame.size.width - - (targetFrame.size.width - visibleWindow.size.width)*x_per - frame.size.width; - CGFloat y_new_bottom = targetFrame.origin.y + - (targetFrame.size.height - visibleWindow.size.height)*y_per; - CGFloat y_new_top = targetFrame.origin.y + targetFrame.size.height - - (targetFrame.size.height - visibleWindow.size.height)*y_per - frame.size.height; - - // calculate new coordinates, decide which one to take horizontal/vertical - frame.origin.x = left >= 0 || right < 0 ? x_new_left : x_new_right; - frame.origin.y = bottom >= 0 || top < 0 ? y_new_bottom : y_new_top; - - // don't place new window on top of a visible menubar - CGFloat top_mar = targetFrame.size.height - - (frame.origin.y - targetFrame.origin.y + frame.size.height); - CGFloat menuBarHeight = targetFrame.size.height - - (targetVisibleFrame.size.height + targetVisibleFrame.origin.y); - - if (top_mar < menuBarHeight) - frame.origin.y -= top-menuBarHeight; - - if (withoutBounds) - return frame; - - //screen bounds right and left - if (frame.origin.x + frame.size.width > targetFrame.origin.x + targetFrame.size.width) - frame.origin.x = targetFrame.origin.x + targetFrame.size.width - frame.size.width; - if (frame.origin.x < targetFrame.origin.x) - frame.origin.x = targetFrame.origin.x; - - //screen bounds top and bottom - if (frame.origin.y + frame.size.height > targetFrame.origin.y + targetFrame.size.height) - frame.origin.y = targetFrame.origin.y + targetFrame.size.height - frame.size.height; - if (frame.origin.y < targetFrame.origin.y) - frame.origin.y = targetFrame.origin.y; - - return frame; -} - -- (NSRect)constrainFrameRect:(NSRect)nf toScreen:(NSScreen *)screen -{ - if ((_is_animating && ![self.adapter isInFullScreenMode]) || - (!_is_animating && [self.adapter isInFullScreenMode])) - { - return nf; - } - - screen = screen ?: self.screen ?: [NSScreen mainScreen]; - NSRect of = [self frame]; - NSRect vf = [_is_animating ? [self targetScreen] : screen visibleFrame]; - NSRect ncf = [self contentRectForFrameRect:nf]; - - // Prevent the window's titlebar from exiting the screen on the top edge. - // This introduces a 'snap to top' behaviour. - if (NSMaxY(nf) > NSMaxY(vf)) - nf.origin.y = NSMaxY(vf) - NSHeight(nf); - - // Prevent the window's titlebar from exiting the screen on the bottom edge. - if (NSMaxY(ncf) < NSMinY(vf)) - nf.origin.y = NSMinY(vf) + NSMinY(ncf) - NSMaxY(ncf); - - // Prevent window from exiting the screen on the right edge - if (NSMinX(nf) > NSMaxX(vf)) - nf.origin.x = NSMaxX(vf) - NSWidth(nf); - - // Prevent window from exiting the screen on the left - if (NSMaxX(nf) < NSMinX(vf)) - nf.origin.x = NSMinX(vf); - - if (NSHeight(nf) < NSHeight(vf) && NSHeight(of) > NSHeight(vf) && - ![self.adapter isInFullScreenMode]) - // If the window height is smaller than the visible frame, but it was - // bigger previously recenter the smaller window vertically. This is - // needed to counter the 'snap to top' behaviour. - nf.origin.y = (NSHeight(vf) - NSHeight(nf)) / 2; - - return nf; -} - -- (void)windowWillStartLiveResize:(NSNotification *)notification -{ - [self.adapter windowWillStartLiveResize:notification]; -} - -- (void)windowDidEndLiveResize:(NSNotification *)notification -{ - [self.adapter windowDidEndLiveResize:notification]; - [self setFrame:[self constrainFrameRect:self.frame toScreen:self.screen] - display:NO]; -} - -- (void)tryDequeueSize -{ - if (_queued_video_size.width <= 0.0 || _queued_video_size.height <= 0.0) - return; - - [self setContentAspectRatio:_queued_video_size]; - [self setCenteredContentSize:_queued_video_size]; - _queued_video_size = NSZeroSize; -} - -- (void)queueNewVideoSize:(NSSize)newSize -{ - _unfs_content_frame = [self frameRect:_unfs_content_frame forCenteredContentSize:newSize]; - if (![self.adapter isInFullScreenMode]) { - if (NSEqualSizes(_queued_video_size, newSize)) - return; - _queued_video_size = newSize; - [self tryDequeueSize]; - } -} - -- (void)windowDidBecomeMain:(NSNotification *)notification -{ - [self tryDequeueSize]; -} -@end diff --git a/video/out/cocoa_common.h b/video/out/cocoa_common.h deleted file mode 100644 index 076136dabe..0000000000 --- a/video/out/cocoa_common.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Cocoa OpenGL Backend - * - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see . - */ - -#ifndef MPLAYER_COCOA_COMMON_H -#define MPLAYER_COCOA_COMMON_H - -#include -#include -#include - -struct vo; -struct vo_cocoa_state; - -void vo_cocoa_init(struct vo *vo); -void vo_cocoa_uninit(struct vo *vo); - -int vo_cocoa_config_window(struct vo *vo); - -int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg); - -void vo_cocoa_swap_buffers(struct vo *vo); -void vo_cocoa_set_opengl_ctx(struct vo *vo, CGLContextObj ctx); - -#endif /* MPLAYER_COCOA_COMMON_H */ diff --git a/video/out/cocoa_common.m b/video/out/cocoa_common.m deleted file mode 100644 index 1a264986be..0000000000 --- a/video/out/cocoa_common.m +++ /dev/null @@ -1,1101 +0,0 @@ -/* - * Cocoa OpenGL Backend - * - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see . - */ - -#include - -#import -#import -#import -#import -#include - -#import "cocoa_common.h" -#import "video/out/cocoa/window.h" -#import "video/out/cocoa/events_view.h" -#import "video/out/cocoa/video_view.h" -#import "video/out/cocoa/mpvadapter.h" - -#include "osdep/threads.h" -#include "osdep/macosx_events_objc.h" - -#include "osdep/timer.h" -#include "osdep/macosx_application.h" -#include "osdep/macosx_application_objc.h" - -#include "options/options.h" -#include "video/out/vo.h" -#include "win_state.h" - -#include "input/input.h" -#include "mpv_talloc.h" - -#include "common/msg.h" - -static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, - const CVTimeStamp* outputTime, CVOptionFlags flagsIn, - CVOptionFlags* flagsOut, void* displayLinkContext); -static int vo_cocoa_fullscreen(struct vo *vo); -static void cocoa_add_screen_reconfiguration_observer(struct vo *vo); -static void cocoa_rm_screen_reconfiguration_observer(struct vo *vo); - -struct vo_cocoa_state { - // --- The following members can be accessed only by the main thread (i.e. - // where Cocoa runs), or if the main thread is fully blocked. - - NSWindow *window; - NSView *view; - MpvVideoView *video; - MpvCocoaAdapter *adapter; - - CGLContextObj cgl_ctx; - NSOpenGLContext *nsgl_ctx; - - NSScreen *current_screen; - CGDirectDisplayID display_id; - - NSInteger window_level; - int fullscreen; - NSRect unfs_window; - - bool cursor_visibility; - bool cursor_visibility_wanted; - bool window_is_dragged; - id event_monitor_mouseup; - - bool embedded; // whether we are embedding in another GUI - - IOPMAssertionID power_mgmt_assertion; - io_connect_t light_sensor; - uint64_t last_lmuvalue; - int last_lux; - IONotificationPortRef light_sensor_io_port; - - struct mp_log *log; - - uint32_t old_dwidth; - uint32_t old_dheight; - - mp_mutex anim_lock; - mp_cond anim_wakeup; - bool is_animating; - - CVDisplayLinkRef link; - mp_mutex sync_lock; - mp_cond sync_wakeup; - uint64_t sync_counter; - - mp_mutex lock; - mp_cond wakeup; - - // --- The following members are protected by the lock. - // If the VO and main threads are both blocked, locking is optional - // for members accessed only by VO and main thread. - - int pending_events; - - int vo_dwidth; // current or soon-to-be VO size - int vo_dheight; - - bool vo_ready; // the VO is in a state in which it can - // render frames - int frame_w, frame_h; // dimensions of the frame rendered - - char *window_title; -}; - -static void run_on_main_thread(struct vo *vo, void(^block)(void)) -{ - dispatch_sync(dispatch_get_main_queue(), block); -} - -static void queue_new_video_size(struct vo *vo, int w, int h) -{ - struct vo_cocoa_state *s = vo->cocoa; - id win = (id) s->window; - NSRect r = NSMakeRect(0, 0, w, h); - r = [s->current_screen convertRectFromBacking:r]; - [win queueNewVideoSize:r.size]; -} - -static void flag_events(struct vo *vo, int events) -{ - struct vo_cocoa_state *s = vo->cocoa; - mp_mutex_lock(&s->lock); - s->pending_events |= events; - mp_mutex_unlock(&s->lock); - if (events) - vo_wakeup(vo); -} - -static void enable_power_management(struct vo_cocoa_state *s) -{ - if (!s->power_mgmt_assertion) return; - IOPMAssertionRelease(s->power_mgmt_assertion); - s->power_mgmt_assertion = kIOPMNullAssertionID; -} - -static void disable_power_management(struct vo_cocoa_state *s) -{ - if (s->power_mgmt_assertion) return; - IOPMAssertionCreateWithName( - kIOPMAssertionTypePreventUserIdleDisplaySleep, - kIOPMAssertionLevelOn, - CFSTR("io.mpv.video_playing_back"), - &s->power_mgmt_assertion); -} - -static const char macosx_icon[] = -#include "TOOLS/osxbundle/icon.icns.inc" -; - -static void set_application_icon(NSApplication *app) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSBundle *bundle = [NSBundle mainBundle]; - if ([bundle pathForResource:@"icon" ofType:@"icns"]) - return; - - // The C string contains a trailing null, so we strip it away - NSData *icon_data = [NSData dataWithBytesNoCopy:(void *)macosx_icon - length:sizeof(macosx_icon) - 1 - freeWhenDone:NO]; - NSImage *icon = [[NSImage alloc] initWithData:icon_data]; - [app setApplicationIconImage:icon]; - [icon release]; - [pool release]; -} - -static int lmuvalue_to_lux(uint64_t v) -{ - // the polynomial approximation for apple lmu value -> lux was empirically - // derived by firefox developers (Apple provides no documentation). - // https://bugzilla.mozilla.org/show_bug.cgi?id=793728 - double power_c4 = 1/pow((double)10,27); - double power_c3 = 1/pow((double)10,19); - double power_c2 = 1/pow((double)10,12); - double power_c1 = 1/pow((double)10,5); - - double term4 = -3.0 * power_c4 * pow(v,4); - double term3 = 2.6 * power_c3 * pow(v,3); - double term2 = -3.4 * power_c2 * pow(v,2); - double term1 = 3.9 * power_c1 * v; - - int lux = ceil(term4 + term3 + term2 + term1 - 0.19); - return lux > 0 ? lux : 0; -} - -static void light_sensor_cb(void *ctx, io_service_t srv, natural_t mtype, void *msg) -{ - struct vo *vo = ctx; - struct vo_cocoa_state *s = vo->cocoa; - uint32_t outputs = 2; - uint64_t values[outputs]; - - kern_return_t kr = IOConnectCallMethod( - s->light_sensor, 0, NULL, 0, NULL, 0, values, &outputs, nil, 0); - - if (kr == KERN_SUCCESS) { - uint64_t mean = (values[0] + values[1]) / 2; - if (s->last_lmuvalue != mean) { - s->last_lmuvalue = mean; - s->last_lux = lmuvalue_to_lux(s->last_lmuvalue); - flag_events(vo, VO_EVENT_AMBIENT_LIGHTING_CHANGED); - } - } -} - -static void cocoa_init_light_sensor(struct vo *vo) -{ - run_on_main_thread(vo, ^{ - struct vo_cocoa_state *s = vo->cocoa; - io_service_t srv = IOServiceGetMatchingService( - kIOMasterPortDefault, IOServiceMatching("AppleLMUController")); - if (srv == IO_OBJECT_NULL) { - MP_VERBOSE(vo, "can't find an ambient light sensor\n"); - return; - } - - // subscribe to notifications from the light sensor driver - s->light_sensor_io_port = IONotificationPortCreate(kIOMasterPortDefault); - IONotificationPortSetDispatchQueue( - s->light_sensor_io_port, dispatch_get_main_queue()); - - io_object_t n; - IOServiceAddInterestNotification( - s->light_sensor_io_port, srv, kIOGeneralInterest, light_sensor_cb, - vo, &n); - - kern_return_t kr = IOServiceOpen(srv, mach_task_self(), 0, - &s->light_sensor); - IOObjectRelease(srv); - if (kr != KERN_SUCCESS) { - MP_WARN(vo, "can't start ambient light sensor connection\n"); - return; - } - - light_sensor_cb(vo, 0, 0, NULL); - }); -} - -static void cocoa_uninit_light_sensor(struct vo_cocoa_state *s) -{ - if (s->light_sensor_io_port) { - IONotificationPortDestroy(s->light_sensor_io_port); - IOObjectRelease(s->light_sensor); - } -} - -static NSScreen *get_screen_by_id(struct vo *vo, int screen_id) -{ - struct vo_cocoa_state *s = vo->cocoa; - - NSArray *screens = [NSScreen screens]; - int n_of_displays = [screens count]; - if (screen_id >= n_of_displays) { - MP_INFO(s, "Screen ID %d does not exist, falling back to main " - "device\n", screen_id); - return nil; - } else if (screen_id < 0) { - return nil; - } - return [screens objectAtIndex:(screen_id)]; -} - -static void vo_cocoa_update_screen_info(struct vo *vo) -{ - struct vo_cocoa_state *s = vo->cocoa; - struct mp_vo_opts *opts = vo->opts; - - if (s->embedded) - return; - - if (s->current_screen && s->window) { - s->current_screen = [s->window screen]; - } else if (!s->current_screen) { - s->current_screen = get_screen_by_id(vo, opts->screen_id); - if (!s->current_screen) - s->current_screen = [NSScreen mainScreen]; - } - - NSDictionary* sinfo = [s->current_screen deviceDescription]; - s->display_id = [[sinfo objectForKey:@"NSScreenNumber"] longValue]; -} - -static void vo_cocoa_anim_lock(struct vo *vo) -{ - struct vo_cocoa_state *s = vo->cocoa; - mp_mutex_lock(&s->anim_lock); - s->is_animating = true; - mp_mutex_unlock(&s->anim_lock); -} - -static void vo_cocoa_anim_unlock(struct vo *vo) -{ - struct vo_cocoa_state *s = vo->cocoa; - mp_mutex_lock(&s->anim_lock); - s->is_animating = false; - mp_cond_signal(&s->anim_wakeup); - mp_mutex_unlock(&s->anim_lock); -} - -static void vo_cocoa_signal_swap(struct vo_cocoa_state *s) -{ - mp_mutex_lock(&s->sync_lock); - s->sync_counter += 1; - mp_cond_signal(&s->sync_wakeup); - mp_mutex_unlock(&s->sync_lock); -} - -static void vo_cocoa_start_displaylink(struct vo_cocoa_state *s) -{ - if (!CVDisplayLinkIsRunning(s->link)) - CVDisplayLinkStart(s->link); -} - -static void vo_cocoa_stop_displaylink(struct vo_cocoa_state *s) -{ - if (CVDisplayLinkIsRunning(s->link)) { - CVDisplayLinkStop(s->link); - vo_cocoa_signal_swap(s); - } -} - -static void vo_cocoa_init_displaylink(struct vo *vo) -{ - struct vo_cocoa_state *s = vo->cocoa; - - CVDisplayLinkCreateWithCGDisplay(s->display_id, &s->link); - CVDisplayLinkSetOutputCallback(s->link, &displayLinkCallback, vo); - CVDisplayLinkStart(s->link); -} - -static void vo_cocoa_uninit_displaylink(struct vo_cocoa_state *s) -{ - vo_cocoa_stop_displaylink(s); - CVDisplayLinkRelease(s->link); -} - -static void cocoa_add_event_monitor(struct vo *vo) -{ - struct vo_cocoa_state *s = vo->cocoa; - - s->event_monitor_mouseup = [NSEvent - addLocalMonitorForEventsMatchingMask: NSEventMaskLeftMouseUp - handler:^NSEvent*(NSEvent* event) { - s->window_is_dragged = false; - return event; - }]; -} - -static void cocoa_rm_event_monitor(struct vo *vo) -{ - [NSEvent removeMonitor:vo->cocoa->event_monitor_mouseup]; -} - -void vo_cocoa_init(struct vo *vo) -{ - struct vo_cocoa_state *s = talloc_zero(NULL, struct vo_cocoa_state); - *s = (struct vo_cocoa_state){ - .power_mgmt_assertion = kIOPMNullAssertionID, - .log = mp_log_new(s, vo->log, "cocoa"), - .embedded = vo->opts->WinID >= 0, - .cursor_visibility = true, - .cursor_visibility_wanted = true, - .fullscreen = 0, - }; - mp_mutex_init(&s->lock); - mp_cond_init(&s->wakeup); - mp_mutex_init(&s->sync_lock); - mp_cond_init(&s->sync_wakeup); - mp_mutex_init(&s->anim_lock); - mp_cond_init(&s->anim_wakeup); - vo->cocoa = s; - vo_cocoa_update_screen_info(vo); - vo_cocoa_init_displaylink(vo); - cocoa_init_light_sensor(vo); - cocoa_add_screen_reconfiguration_observer(vo); - cocoa_add_event_monitor(vo); - - if (!s->embedded) { - run_on_main_thread(vo, ^{ - [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; - set_application_icon(NSApp); - }); - } -} - -static int vo_cocoa_update_cursor_visibility(struct vo *vo, bool forceVisible) -{ - struct vo_cocoa_state *s = vo->cocoa; - - if (s->embedded) - return VO_NOTIMPL; - - if (s->view) { - MpvEventsView *v = (MpvEventsView *) s->view; - bool visibility = !(!s->cursor_visibility_wanted && [v canHideCursor]); - - if ((forceVisible || visibility) && !s->cursor_visibility) { - [NSCursor unhide]; - s->cursor_visibility = YES; - } else if (!visibility && s->cursor_visibility) { - [NSCursor hide]; - s->cursor_visibility = NO; - } - } - return VO_TRUE; -} - -void vo_cocoa_uninit(struct vo *vo) -{ - struct vo_cocoa_state *s = vo->cocoa; - - mp_mutex_lock(&s->lock); - s->vo_ready = false; - mp_cond_signal(&s->wakeup); - mp_mutex_unlock(&s->lock); - - mp_mutex_lock(&s->anim_lock); - while(s->is_animating) - mp_cond_wait(&s->anim_wakeup, &s->anim_lock); - mp_mutex_unlock(&s->anim_lock); - - // close window beforehand to prevent undefined behavior when in fullscreen - // that resets the desktop to space 1 - run_on_main_thread(vo, ^{ - // if using --wid + libmpv there's no window to release - if (s->window) { - vo_cocoa_update_cursor_visibility(vo, true); - [s->window setDelegate:nil]; - [s->window close]; - } - }); - - run_on_main_thread(vo, ^{ - enable_power_management(s); - vo_cocoa_uninit_displaylink(s); - vo_cocoa_signal_swap(s); - cocoa_uninit_light_sensor(s); - cocoa_rm_screen_reconfiguration_observer(vo); - cocoa_rm_event_monitor(vo); - - [s->nsgl_ctx release]; - CGLReleaseContext(s->cgl_ctx); - - // needed to stop resize events triggered by the event's view -clear - // causing many uses after free - [s->video removeFromSuperview]; - - [s->view removeFromSuperview]; - [s->view release]; - - mp_cond_destroy(&s->anim_wakeup); - mp_mutex_destroy(&s->anim_lock); - mp_cond_destroy(&s->sync_wakeup); - mp_mutex_destroy(&s->sync_lock); - mp_cond_destroy(&s->wakeup); - mp_mutex_destroy(&s->lock); - talloc_free(s); - }); -} - -static void vo_cocoa_update_displaylink(struct vo *vo) -{ - struct vo_cocoa_state *s = vo->cocoa; - - vo_cocoa_uninit_displaylink(s); - vo_cocoa_init_displaylink(vo); -} - -static double vo_cocoa_update_screen_fps(struct vo *vo) -{ - struct vo_cocoa_state *s = vo->cocoa; - double actual_fps = CVDisplayLinkGetActualOutputVideoRefreshPeriod(s->link); - const CVTime t = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(s->link); - - if (!(t.flags & kCVTimeIsIndefinite)) { - double nominal_fps = (t.timeScale / (double) t.timeValue); - - if (actual_fps > 0) - actual_fps = 1/actual_fps; - - if (fabs(actual_fps - nominal_fps) > 0.1) { - MP_VERBOSE(vo, "Falling back to nominal display " - "refresh rate: %fHz\n", nominal_fps); - return nominal_fps; - } else { - return actual_fps; - } - } - - MP_WARN(vo, "Falling back to standard display refresh rate: 60Hz\n"); - return 60.0; -} - -static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, - const CVTimeStamp* outputTime, CVOptionFlags flagsIn, - CVOptionFlags* flagsOut, void* displayLinkContext) -{ - struct vo *vo = displayLinkContext; - struct vo_cocoa_state *s = vo->cocoa; - - vo_cocoa_signal_swap(s); - return kCVReturnSuccess; -} - -static void vo_set_level(struct vo *vo, int ontop, int ontop_level) -{ - struct vo_cocoa_state *s = vo->cocoa; - - if (ontop) { - switch (ontop_level) { - case -1: - s->window_level = NSFloatingWindowLevel; - break; - case -2: - s->window_level = NSStatusWindowLevel; - break; - default: - s->window_level = ontop_level; - } - } else { - s->window_level = NSNormalWindowLevel; - } - - [s->window setLevel:s->window_level]; - NSWindowCollectionBehavior behavior = [s->window collectionBehavior] & - ~NSWindowCollectionBehaviorTransient; - [s->window setCollectionBehavior:behavior|NSWindowCollectionBehaviorManaged]; -} - -static int vo_cocoa_ontop(struct vo *vo) -{ - struct vo_cocoa_state *s = vo->cocoa; - if (s->embedded) - return VO_NOTIMPL; - - struct mp_vo_opts *opts = vo->opts; - vo_set_level(vo, opts->ontop, opts->ontop_level); - return VO_TRUE; -} - -static MpvVideoWindow *create_window(NSRect rect, NSScreen *s, bool border, - MpvCocoaAdapter *adapter) -{ - int window_mask = 0; - if (border) { - window_mask = NSWindowStyleMaskTitled|NSWindowStyleMaskClosable| - NSWindowStyleMaskMiniaturizable|NSWindowStyleMaskResizable; - } else { - window_mask = NSWindowStyleMaskBorderless|NSWindowStyleMaskResizable; - } - - MpvVideoWindow *w = - [[MpvVideoWindow alloc] initWithContentRect:rect - styleMask:window_mask - backing:NSBackingStoreBuffered - defer:NO - screen:s]; - w.adapter = adapter; - [w setDelegate: w]; - - return w; -} - -static void create_ui(struct vo *vo, struct mp_rect *win, int geo_flags) -{ - struct vo_cocoa_state *s = vo->cocoa; - struct mp_vo_opts *opts = vo->opts; - - MpvCocoaAdapter *adapter = [[MpvCocoaAdapter alloc] init]; - adapter.vout = vo; - - NSView *parent; - if (s->embedded) { - parent = (NSView *) (intptr_t) opts->WinID; - } else { - NSRect wr = NSMakeRect(win->x0, win->y1, win->x1 - win->x0, win->y0 - win->y1); - wr = [s->current_screen convertRectFromBacking:wr]; - s->window = create_window(wr, s->current_screen, opts->border, adapter); - parent = [s->window contentView]; - } - - MpvEventsView *view = [[MpvEventsView alloc] initWithFrame:[parent bounds]]; - view.adapter = adapter; - s->view = view; - [parent addSubview:s->view]; - s->adapter = adapter; - - cocoa_register_menu_item_action(MPM_H_SIZE, @selector(halfSize)); - cocoa_register_menu_item_action(MPM_N_SIZE, @selector(normalSize)); - cocoa_register_menu_item_action(MPM_D_SIZE, @selector(doubleSize)); - cocoa_register_menu_item_action(MPM_MINIMIZE, @selector(performMiniaturize:)); - cocoa_register_menu_item_action(MPM_ZOOM, @selector(performZoom:)); - - s->video = [[MpvVideoView alloc] initWithFrame:[s->view bounds]]; - [s->video setWantsBestResolutionOpenGLSurface:YES]; - - [s->view addSubview:s->video]; - [s->nsgl_ctx setView:s->video]; - [s->video release]; - - s->video.adapter = adapter; - [adapter release]; - - if (!s->embedded) { - [s->window setRestorable:NO]; - [s->window makeMainWindow]; - [s->window makeKeyAndOrderFront:nil]; - if (!opts->fullscreen) - [s->window setMovableByWindowBackground:YES]; - [NSApp activateIgnoringOtherApps:YES]; - } -} - -static int cocoa_set_window_title(struct vo *vo) -{ - struct vo_cocoa_state *s = vo->cocoa; - if (s->embedded) - return VO_NOTIMPL; - - void *talloc_ctx = talloc_new(NULL); - struct bstr btitle = - bstr_sanitize_utf8_latin1(talloc_ctx, bstr0(s->window_title)); - if (btitle.start) { - NSString *nstitle = [NSString stringWithUTF8String:btitle.start]; - if (nstitle) { - [s->window setTitle: nstitle]; - [s->window displayIfNeeded]; - } - } - talloc_free(talloc_ctx); - return VO_TRUE; -} - -static int vo_cocoa_window_border(struct vo *vo) -{ - struct vo_cocoa_state *s = vo->cocoa; - if (s->embedded) - return VO_NOTIMPL; - - struct mp_vo_opts *opts = vo->opts; - id win = (id) s->window; - [win updateBorder:opts->border]; - if (opts->border) - cocoa_set_window_title(vo); - - return VO_TRUE; -} - -static void cocoa_screen_reconfiguration_observer( - CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *ctx) -{ - if (flags & kCGDisplaySetModeFlag) { - struct vo *vo = ctx; - struct vo_cocoa_state *s = vo->cocoa; - - if (s->display_id == display) { - MP_VERBOSE(vo, "detected display mode change, updating screen refresh rate\n"); - flag_events(vo, VO_EVENT_WIN_STATE); - } - } -} - -static void cocoa_add_screen_reconfiguration_observer(struct vo *vo) -{ - CGDisplayRegisterReconfigurationCallback( - cocoa_screen_reconfiguration_observer, vo); -} - -static void cocoa_rm_screen_reconfiguration_observer(struct vo *vo) -{ - CGDisplayRemoveReconfigurationCallback( - cocoa_screen_reconfiguration_observer, vo); -} - -void vo_cocoa_set_opengl_ctx(struct vo *vo, CGLContextObj ctx) -{ - struct vo_cocoa_state *s = vo->cocoa; - run_on_main_thread(vo, ^{ - s->cgl_ctx = CGLRetainContext(ctx); - s->nsgl_ctx = [[NSOpenGLContext alloc] initWithCGLContextObj:s->cgl_ctx]; - }); -} - -int vo_cocoa_config_window(struct vo *vo) -{ - struct vo_cocoa_state *s = vo->cocoa; - struct mp_vo_opts *opts = vo->opts; - - run_on_main_thread(vo, ^{ - NSRect r = [s->current_screen frame]; - r = [s->current_screen convertRectToBacking:r]; - struct mp_rect screenrc = {0, 0, r.size.width, r.size.height}; - struct vo_win_geometry geo; - vo_calc_window_geometry2(vo, &screenrc, [s->current_screen backingScaleFactor], &geo); - vo_apply_window_geometry(vo, &geo); - - //flip y coordinates - geo.win.y1 = r.size.height - geo.win.y1; - geo.win.y0 = r.size.height - geo.win.y0; - - uint32_t width = vo->dwidth; - uint32_t height = vo->dheight; - - bool reset_size = s->old_dwidth != width || s->old_dheight != height; - s->old_dwidth = width; - s->old_dheight = height; - - if (!s->view) { - create_ui(vo, &geo.win, geo.flags); - } - - s->unfs_window = NSMakeRect(0, 0, width, height); - - if (!s->embedded && s->window) { - if (reset_size) - queue_new_video_size(vo, width, height); - if (opts->fullscreen && !s->fullscreen) - vo_cocoa_fullscreen(vo); - cocoa_set_window_title(vo); - vo_set_level(vo, opts->ontop, opts->ontop_level); - - GLint o; - if (!CGLGetParameter(s->cgl_ctx, kCGLCPSurfaceOpacity, &o) && !o) { - [s->window setOpaque:NO]; - [s->window setBackgroundColor:[NSColor clearColor]]; - } - } - - s->vo_ready = true; - - // Use the actual size of the new window - NSRect frame = [s->video frameInPixels]; - vo->dwidth = s->vo_dwidth = frame.size.width; - vo->dheight = s->vo_dheight = frame.size.height; - - [s->nsgl_ctx update]; - }); - return 0; -} - -// Trigger a VO resize - called from the main thread. This is done async, -// because the VO must resize and redraw while vo_cocoa_resize_redraw() is -// blocking. -static void resize_event(struct vo *vo) -{ - struct vo_cocoa_state *s = vo->cocoa; - NSRect frame = [s->video frameInPixels]; - - mp_mutex_lock(&s->lock); - s->vo_dwidth = frame.size.width; - s->vo_dheight = frame.size.height; - s->pending_events |= VO_EVENT_RESIZE | VO_EVENT_EXPOSE; - // Live-resizing: make sure at least one frame will be drawn - s->frame_w = s->frame_h = 0; - mp_mutex_unlock(&s->lock); - - [s->nsgl_ctx update]; - - vo_wakeup(vo); -} - -static void vo_cocoa_resize_redraw(struct vo *vo, int width, int height) -{ - struct vo_cocoa_state *s = vo->cocoa; - - resize_event(vo); - - mp_mutex_lock(&s->lock); - - // Wait until a new frame with the new size was rendered. For some reason, - // Cocoa requires this to be done before drawRect() returns. - int64_t e = mp_time_ns() + MP_TIME_MS_TO_NS(100); - while (s->frame_w != width && s->frame_h != height && s->vo_ready) { - if (mp_cond_timedwait_until(&s->wakeup, &s->lock, e)) - break; - } - - mp_mutex_unlock(&s->lock); -} - -void vo_cocoa_swap_buffers(struct vo *vo) -{ - struct vo_cocoa_state *s = vo->cocoa; - - // Don't swap a frame with wrong size - mp_mutex_lock(&s->lock); - bool skip = s->pending_events & VO_EVENT_RESIZE; - mp_mutex_unlock(&s->lock); - if (skip) - return; - - mp_mutex_lock(&s->sync_lock); - uint64_t old_counter = s->sync_counter; - while(CVDisplayLinkIsRunning(s->link) && old_counter == s->sync_counter) { - mp_cond_wait(&s->sync_wakeup, &s->sync_lock); - } - mp_mutex_unlock(&s->sync_lock); - - mp_mutex_lock(&s->lock); - s->frame_w = vo->dwidth; - s->frame_h = vo->dheight; - mp_cond_signal(&s->wakeup); - mp_mutex_unlock(&s->lock); -} - -static int vo_cocoa_check_events(struct vo *vo) -{ - struct vo_cocoa_state *s = vo->cocoa; - - mp_mutex_lock(&s->lock); - int events = s->pending_events; - s->pending_events = 0; - if (events & VO_EVENT_RESIZE) { - vo->dwidth = s->vo_dwidth; - vo->dheight = s->vo_dheight; - } - mp_mutex_unlock(&s->lock); - - return events; -} - -static int vo_cocoa_fullscreen(struct vo *vo) -{ - struct vo_cocoa_state *s = vo->cocoa; - - if (s->embedded) - return VO_NOTIMPL; - - if (!s->fullscreen) - s->unfs_window = [s->view frame]; - - [s->window toggleFullScreen:nil]; - - return VO_TRUE; -} - -static void vo_cocoa_control_get_icc_profile(struct vo *vo, void *arg) -{ - struct vo_cocoa_state *s = vo->cocoa; - bstr *p = arg; - - NSData *profile = [[s->current_screen colorSpace] ICCProfileData]; - - p->start = talloc_memdup(NULL, (void *)[profile bytes], [profile length]); - p->len = [profile length]; -} - -static int vo_cocoa_control_on_main_thread(struct vo *vo, int request, void *arg) -{ - struct vo_cocoa_state *s = vo->cocoa; - - switch (request) { - case VOCTRL_GET_UNFS_WINDOW_SIZE: { - int *sz = arg; - NSRect rect = (s->fullscreen || vo->opts->fullscreen) ? - s->unfs_window : [s->view frame]; - if(!vo->opts->hidpi_window_scale) - rect = [s->current_screen convertRectToBacking:rect]; - sz[0] = rect.size.width; - sz[1] = rect.size.height; - return VO_TRUE; - } - case VOCTRL_SET_UNFS_WINDOW_SIZE: { - int *sz = arg; - NSRect r = NSMakeRect(0, 0, sz[0], sz[1]); - if(vo->opts->hidpi_window_scale) - r = [s->current_screen convertRectToBacking:r]; - queue_new_video_size(vo, r.size.width, r.size.height); - return VO_TRUE; - } - case VOCTRL_SET_CURSOR_VISIBILITY: - s->cursor_visibility_wanted = *(bool *)arg; - return vo_cocoa_update_cursor_visibility(vo, false); - case VOCTRL_UPDATE_WINDOW_TITLE: { - talloc_free(s->window_title); - s->window_title = talloc_strdup(s, (char *) arg); - return cocoa_set_window_title(vo); - } - case VOCTRL_RESTORE_SCREENSAVER: - enable_power_management(s); - return VO_TRUE; - case VOCTRL_KILL_SCREENSAVER: - disable_power_management(s); - return VO_TRUE; - case VOCTRL_GET_ICC_PROFILE: - vo_cocoa_control_get_icc_profile(vo, arg); - return VO_TRUE; - case VOCTRL_GET_DISPLAY_FPS: - *(double *)arg = vo_cocoa_update_screen_fps(vo); - return VO_TRUE; - break; - case VOCTRL_GET_AMBIENT_LUX: - if (s->light_sensor != IO_OBJECT_NULL) { - *(int *)arg = s->last_lux; - return VO_TRUE; - } - break; - } - return VO_NOTIMPL; -} - -static int vo_cocoa_control_async(struct vo *vo, int *events, int request, void *arg) -{ - switch (request) { - case VOCTRL_CHECK_EVENTS: - *events |= vo_cocoa_check_events(vo); - return VO_TRUE; - } - return VO_NOTIMPL; -} - -int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg) -{ - __block int r = vo_cocoa_control_async(vo, events, request, arg); - if (r == VO_NOTIMPL) { - run_on_main_thread(vo, ^{ - r = vo_cocoa_control_on_main_thread(vo, request, arg); - }); - } - return r; -} - -@implementation MpvCocoaAdapter -@synthesize vout = _video_output; - -- (void)performAsyncResize:(NSSize)size -{ - vo_cocoa_resize_redraw(self.vout, size.width, size.height); -} - -- (BOOL)keyboardEnabled -{ - return !!mp_input_vo_keyboard_enabled(self.vout->input_ctx); -} - -- (BOOL)mouseEnabled -{ - return !!mp_input_mouse_enabled(self.vout->input_ctx); -} - -- (void)setNeedsResize -{ - resize_event(self.vout); -} - -- (void)recalcMovableByWindowBackground:(NSPoint)p -{ - BOOL movable = NO; - if (!self.vout->cocoa->fullscreen) { - movable = !mp_input_test_dragging(self.vout->input_ctx, p.x, p.y); - } - - [self.vout->cocoa->window setMovableByWindowBackground:movable]; -} - -- (void)signalMouseMovement:(NSPoint)point -{ - [self recalcMovableByWindowBackground:point]; - if (!self.vout->cocoa->window_is_dragged) - mp_input_set_mouse_pos(self.vout->input_ctx, point.x, point.y); -} - -- (void)putKey:(int)mpkey withModifiers:(int)modifiers -{ - cocoa_put_key_with_modifiers(mpkey, modifiers); -} - -- (void)putWheel:(int)mpkey delta:(float)delta; -{ - mp_input_put_wheel(self.vout->input_ctx, mpkey, delta); -} - -- (void)putCommand:(char*)cmd -{ - char *cmd_ = ta_strdup(NULL, cmd); - mp_cmd_t *cmdt = mp_input_parse_cmd(self.vout->input_ctx, bstr0(cmd_), ""); - mp_input_queue_cmd(self.vout->input_ctx, cmdt); - ta_free(cmd_); -} - -- (BOOL)isInFullScreenMode -{ - return self.vout->cocoa->fullscreen; -} - -- (BOOL)wantsNativeFullscreen -{ - return self.vout->opts->native_fs; -} - -- (NSScreen *)getTargetScreen -{ - struct vo_cocoa_state *s = self.vout->cocoa; - struct mp_vo_opts *opts = self.vout->opts; - - int screen_id = s->fullscreen ? opts->screen_id : opts->fsscreen_id; - return get_screen_by_id(self.vout, screen_id); -} - -- (void)handleFilesArray:(NSArray *)files -{ - [[EventsResponder sharedInstance] handleFilesArray:files]; -} - -- (void)windowDidChangeScreen:(NSNotification *)notification -{ - vo_cocoa_update_screen_info(self.vout); -} - -- (void)windowDidChangePhysicalScreen -{ - vo_cocoa_update_displaylink(self.vout); - flag_events(self.vout, VO_EVENT_WIN_STATE); -} - -- (void)windowDidEnterFullScreen -{ - struct vo_cocoa_state *s = self.vout->cocoa; - s->fullscreen = 1; - vo_cocoa_anim_unlock(self.vout); -} - -- (void)windowDidExitFullScreen -{ - struct vo_cocoa_state *s = self.vout->cocoa; - s->fullscreen = 0; - vo_cocoa_anim_unlock(self.vout); -} - -- (void)windowWillEnterFullScreen:(NSNotification *)notification -{ - vo_cocoa_anim_lock(self.vout); -} - -- (void)windowWillExitFullScreen:(NSNotification *)notification -{ - vo_cocoa_anim_lock(self.vout); -} - -- (void)windowDidFailToEnterFullScreen:(NSWindow *)window -{ - vo_cocoa_anim_unlock(self.vout); -} - -- (void)windowDidFailToExitFullScreen:(NSWindow *)window -{ - vo_cocoa_anim_unlock(self.vout); -} - -- (void)windowWillStartLiveResize:(NSNotification *)notification -{ - // Make vo.c not do video timing, which would slow down resizing. - vo_event(self.vout, VO_EVENT_LIVE_RESIZING); - vo_cocoa_stop_displaylink(self.vout->cocoa); -} - -- (void)windowDidEndLiveResize:(NSNotification *)notification -{ - vo_query_and_reset_events(self.vout, VO_EVENT_LIVE_RESIZING); - vo_cocoa_start_displaylink(self.vout->cocoa); -} - -- (void)didChangeWindowedScreenProfile:(NSNotification *)notification -{ - vo_cocoa_update_screen_info(self.vout); - flag_events(self.vout, VO_EVENT_ICC_PROFILE_CHANGED); -} - -- (void)windowDidResignKey:(NSNotification *)notification -{ - vo_cocoa_update_cursor_visibility(self.vout, true); -} - -- (void)windowDidBecomeKey:(NSNotification *)notification -{ - vo_cocoa_update_cursor_visibility(self.vout, false); -} - -- (void)windowWillMove:(NSNotification *)notification -{ - self.vout->cocoa->window_is_dragged = true; -} - -@end diff --git a/video/out/gpu/context.c b/video/out/gpu/context.c index 28f88014aa..5ce18afbe2 100644 --- a/video/out/gpu/context.c +++ b/video/out/gpu/context.c @@ -37,7 +37,6 @@ extern const struct ra_ctx_fns ra_ctx_glx; extern const struct ra_ctx_fns ra_ctx_x11_egl; extern const struct ra_ctx_fns ra_ctx_drm_egl; -extern const struct ra_ctx_fns ra_ctx_cocoa; extern const struct ra_ctx_fns ra_ctx_wayland_egl; extern const struct ra_ctx_fns ra_ctx_wgl; extern const struct ra_ctx_fns ra_ctx_angle; @@ -71,9 +70,6 @@ static const struct ra_ctx_fns *contexts[] = { #if HAVE_RPI &ra_ctx_rpi, #endif -#if HAVE_GL_COCOA - &ra_ctx_cocoa, -#endif #if HAVE_EGL_ANGLE_WIN32 &ra_ctx_angle, #endif diff --git a/video/out/opengl/context_cocoa.c b/video/out/opengl/context_cocoa.c deleted file mode 100644 index ec8ec27458..0000000000 --- a/video/out/opengl/context_cocoa.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see . - */ - -#include -#include -#include "options/m_config.h" -#include "video/out/cocoa_common.h" -#include "context.h" -#include "osdep/macosx_application.h" - -struct priv { - GL gl; - void (GLAPIENTRY *Flush)(void); - CGLPixelFormatObj pix; - CGLContextObj ctx; - - struct macos_opts *macos_opts; -}; - -static int set_swap_interval(int enabled) -{ - CGLContextObj ctx = CGLGetCurrentContext(); - CGLError err = CGLSetParameter(ctx, kCGLCPSwapInterval, &enabled); - return (err == kCGLNoError) ? 0 : -1; -} - -static void glFlushDummy(void) { } - -static void *cocoa_glgetaddr(const char *s) -{ - void *ret = NULL; - void *handle = dlopen( - "/System/Library/Frameworks/OpenGL.framework/OpenGL", - RTLD_LAZY | RTLD_LOCAL); - if (!handle) - return NULL; - ret = dlsym(handle, s); - dlclose(handle); - return ret; -} - -static CGLError test_gl_version(struct ra_ctx *ctx, CGLOpenGLProfile ver) -{ - struct priv *p = ctx->priv; - - CGLPixelFormatAttribute attrs[] = { - // let this array ordered by the inverse order of the most probably - // rejected attribute to preserve the fallback code - kCGLPFAOpenGLProfile, - (CGLPixelFormatAttribute) ver, - kCGLPFAAccelerated, - kCGLPFAAllowOfflineRenderers, - // keep this one last to apply the cocoa-force-dedicated-gpu option - kCGLPFASupportsAutomaticGraphicsSwitching, - 0 - }; - - GLint npix; - CGLError err; - int supported_attribute = MP_ARRAY_SIZE(attrs)-1; - - if (p->macos_opts->macos_force_dedicated_gpu) - attrs[--supported_attribute] = 0; - - err = CGLChoosePixelFormat(attrs, &p->pix, &npix); - while (err == kCGLBadAttribute && supported_attribute > 3) { - // kCGLPFASupportsAutomaticGraphicsSwitching is probably not - // supported by the current hardware. Falling back to not using - // it and disallowing Offline Renderers if further restrictions - // apply - attrs[--supported_attribute] = 0; - err = CGLChoosePixelFormat(attrs, &p->pix, &npix); - } - - if (err != kCGLNoError) { - MP_ERR(ctx->vo, "error creating CGL pixel format: %s (%d)\n", - CGLErrorString(err), err); - goto error_out; - } - - err = CGLCreateContext(p->pix, 0, &p->ctx); - -error_out: - return err; -} - -static bool create_gl_context(struct ra_ctx *ctx) -{ - struct priv *p = ctx->priv; - GL *gl = &p->gl; - CGLError err; - - CGLOpenGLProfile gl_versions[] = { - kCGLOGLPVersion_3_2_Core, - kCGLOGLPVersion_Legacy, - }; - - for (int n = 0; n < MP_ARRAY_SIZE(gl_versions); n++) { - err = test_gl_version(ctx, gl_versions[n]); - if (err == kCGLNoError) - break; - } - - if (err != kCGLNoError) { - MP_FATAL(ctx->vo, "error creating CGL context: %s (%d)\n", - CGLErrorString(err), err); - return false; - } - - vo_cocoa_set_opengl_ctx(ctx->vo, p->ctx); - CGLSetCurrentContext(p->ctx); - - if (ctx->opts.want_alpha) - CGLSetParameter(p->ctx, kCGLCPSurfaceOpacity, &(GLint){0}); - - mpgl_load_functions(gl, (void *)cocoa_glgetaddr, NULL, ctx->vo->log); - gl->SwapInterval = set_swap_interval; - p->Flush = gl->Flush; - gl->Flush = glFlushDummy; - - CGLReleasePixelFormat(p->pix); - - return true; -} - -static void cocoa_uninit(struct ra_ctx *ctx) -{ - struct priv *p = ctx->priv; - ra_gl_ctx_uninit(ctx); - CGLReleaseContext(p->ctx); - vo_cocoa_uninit(ctx->vo); -} - -static void cocoa_swap_buffers(struct ra_ctx *ctx) -{ - struct priv *p = ctx->priv; - vo_cocoa_swap_buffers(ctx->vo); - p->Flush(); -} - -static bool cocoa_init(struct ra_ctx *ctx) -{ - struct priv *p = ctx->priv = talloc_zero(ctx, struct priv); - GL *gl = &p->gl; - p->macos_opts = mp_get_config_group(ctx, ctx->global, &macos_conf); - vo_cocoa_init(ctx->vo); - - MP_WARN(ctx->vo, "opengl cocoa backend is deprecated, use vo=libmpv instead\n"); - - if (!create_gl_context(ctx)) - goto fail; - - struct ra_gl_ctx_params params = { - .swap_buffers = cocoa_swap_buffers, - }; - - if (!ra_gl_ctx_init(ctx, gl, params)) - goto fail; - - return true; - -fail: - cocoa_uninit(ctx); - return false; -} - -static void resize(struct ra_ctx *ctx) -{ - ra_gl_ctx_resize(ctx->swapchain, ctx->vo->dwidth, ctx->vo->dheight, 0); -} - -static bool cocoa_reconfig(struct ra_ctx *ctx) -{ - vo_cocoa_config_window(ctx->vo); - resize(ctx); - return true; -} - -static int cocoa_control(struct ra_ctx *ctx, int *events, int request, - void *arg) -{ - int ret = vo_cocoa_control(ctx->vo, events, request, arg); - if (*events & VO_EVENT_RESIZE) - resize(ctx); - return ret; -} - -const struct ra_ctx_fns ra_ctx_cocoa = { - .type = "opengl", - .name = "cocoa", - .init = cocoa_init, - .reconfig = cocoa_reconfig, - .control = cocoa_control, - .uninit = cocoa_uninit, -}; diff --git a/video/out/vo.h b/video/out/vo.h index f73cbf5989..1fb83ddd65 100644 --- a/video/out/vo.h +++ b/video/out/vo.h @@ -446,7 +446,6 @@ struct vo { struct mpv_global *global; struct vo_x11_state *x11; struct vo_w32_state *w32; - struct vo_cocoa_state *cocoa; struct vo_wayland_state *wl; struct vo_android_state *android; struct vo_drm_state *drm;