summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorAkemi <der.richter@gmx.de>2016-12-04 22:52:14 +0100
committerAkemi <der.richter@gmx.de>2016-12-15 20:55:16 +0100
commita8347eb9ba9e09177da50592fde7f3ae7261ce59 (patch)
treee84d02a7642560b586df4352798d21075feb04f4 /video
parent870a6a11d99d67e5fcf1a1cb28c3de3167494470 (diff)
downloadmpv-a8347eb9ba9e09177da50592fde7f3ae7261ce59.tar.bz2
mpv-a8347eb9ba9e09177da50592fde7f3ae7261ce59.tar.xz
cocoa: fullscreen refactoring
this replaces the old fullscreen with the native macOS fullscreen. additional the --fs-black-out-screens was removed since the new API doesn't support it in a way the old one did. it can possibly be re-added if done manually. Fixes #2857 #3272 #1352 #2062 #3864
Diffstat (limited to 'video')
-rw-r--r--video/out/cocoa/events_view.h2
-rw-r--r--video/out/cocoa/events_view.m71
-rw-r--r--video/out/cocoa/mpvadapter.h6
-rw-r--r--video/out/cocoa/window.m173
-rw-r--r--video/out/cocoa_common.m280
5 files changed, 278 insertions, 254 deletions
diff --git a/video/out/cocoa/events_view.h b/video/out/cocoa/events_view.h
index 3429563b4d..6ad51cc133 100644
--- a/video/out/cocoa/events_view.h
+++ b/video/out/cocoa/events_view.h
@@ -20,8 +20,6 @@
@interface MpvEventsView : NSView <NSDraggingDestination>
@property(nonatomic, retain) MpvCocoaAdapter *adapter;
-- (void)setFullScreen:(BOOL)willBeFullscreen;
-- (void)clear;
- (BOOL)canHideCursor;
- (void)signalMousePosition;
@end
diff --git a/video/out/cocoa/events_view.m b/video/out/cocoa/events_view.m
index 5de4a99eec..53d1da86ff 100644
--- a/video/out/cocoa/events_view.m
+++ b/video/out/cocoa/events_view.m
@@ -28,8 +28,6 @@
@property(nonatomic, assign) BOOL clearing;
@property(nonatomic, assign) BOOL hasMouseDown;
@property(nonatomic, retain) NSTrackingArea *tracker;
-- (BOOL)hasDock:(NSScreen*)screen;
-- (BOOL)hasMenubar:(NSScreen*)screen;
- (int)mpvButtonNumber:(NSEvent*)event;
- (void)mouseDownEvent:(NSEvent *)event;
- (void)mouseUpEvent:(NSEvent *)event;
@@ -51,54 +49,6 @@
return self;
}
-- (void)setFullScreen:(BOOL)willBeFullscreen
-{
- if (willBeFullscreen && ![self isInFullScreenMode]) {
- NSApplicationPresentationOptions popts =
- NSApplicationPresentationDefault;
-
- if ([self hasMenubar:[self.adapter fsScreen]])
- // Cocoa raises an exception when autohiding the menubar but
- // not the dock. They probably got bored while programming the
- // multi screen support and took some shortcuts (tested on 10.8).
- popts |= NSApplicationPresentationAutoHideMenuBar |
- NSApplicationPresentationAutoHideDock;
-
- if ([self hasDock:[self.adapter fsScreen]])
- popts |= NSApplicationPresentationAutoHideDock;
-
- NSDictionary *fsopts = @{
- NSFullScreenModeAllScreens : @([self.adapter fsModeAllScreens]),
- NSFullScreenModeApplicationPresentationOptions : @(popts)
- };
-
- // The original "windowed" window will stay around since sending a
- // view fullscreen wraps it in another window. This is noticeable when
- // sending the View fullscreen to another screen. Make it go away
- // manually.
- [self.window orderOut:self];
-
- [self enterFullScreenMode:[self.adapter fsScreen]
- withOptions:fsopts];
- }
-
- if (!willBeFullscreen && [self isInFullScreenMode]) {
- [self exitFullScreenModeWithOptions:nil];
-
- // Show the "windowed" window again.
- [self.window makeKeyAndOrderFront:self];
- [self.window makeFirstResponder:self];
- }
-}
-
-- (void)clear
-{
- if ([self isInFullScreenMode]) {
- self.clearing = YES;
- [self exitFullScreenModeWithOptions:nil];
- }
-}
-
// 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; }
@@ -379,27 +329,6 @@
return NO;
}
-- (BOOL)hasDock:(NSScreen*)screen
-{
- NSRect vF = [screen visibleFrame];
- NSRect f = [screen frame];
- return
- // The visible frame's width is smaller: dock is on left or right end
- // of this method's receiver.
- vF.size.width < f.size.width ||
- // The visible frame's veritical origin is bigger: dock is
- // on the bottom of this method's receiver.
- vF.origin.y > f.origin.y;
-
-}
-
-- (BOOL)hasMenubar:(NSScreen*)screen
-{
- NSRect vF = [screen visibleFrame];
- NSRect f = [screen frame];
- return f.size.height + f.origin.y > vF.size.height + vF.origin.y;
-}
-
- (int)mpvButtonNumber:(NSEvent*)event
{
int buttonNumber = [event buttonNumber];
diff --git a/video/out/cocoa/mpvadapter.h b/video/out/cocoa/mpvadapter.h
index 5b87e89d04..e547708e17 100644
--- a/video/out/cocoa/mpvadapter.h
+++ b/video/out/cocoa/mpvadapter.h
@@ -26,14 +26,14 @@
- (void)putAxis:(int)mpkey delta:(float)delta;
- (void)putCommand:(char*)cmd;
- (void)handleFilesArray:(NSArray *)files;
-- (void)didChangeWindowedScreenProfile:(NSScreen *)screen;
+- (void)didChangeWindowedScreenProfile:(NSNotification *)notification;
- (void)performAsyncResize:(NSSize)size;
- (void)didChangeMousePosition;
- (BOOL)isInFullScreenMode;
- (BOOL)keyboardEnabled;
- (BOOL)mouseEnabled;
-- (NSScreen *)fsScreen;
-- (BOOL)fsModeAllScreens;
+
+- (NSScreen *)getTargetScreen;
@property(nonatomic, assign) struct vo *vout;
@end
diff --git a/video/out/cocoa/window.m b/video/out/cocoa/window.m
index d89e296b40..6d63263cb4 100644
--- a/video/out/cocoa/window.m
+++ b/video/out/cocoa/window.m
@@ -26,15 +26,25 @@
#include "window.h"
@interface MpvVideoWindow()
+@property(nonatomic, retain) NSScreen *targetScreen;
+@property(nonatomic, retain) NSScreen *previousScreen;
+@property(nonatomic, retain) NSScreen *currentScreen;
+
- (NSRect)frameRect:(NSRect)frameRect forCenteredContentSize:(NSSize)newSize;
- (void)setCenteredContentSize:(NSSize)newSize;
@end
@implementation MpvVideoWindow {
NSSize _queued_video_size;
+ NSRect _unfs_content_frame;
+ NSRect _unfs_screen_frame;
+ int _is_animating;
}
@synthesize adapter = _adapter;
+@synthesize targetScreen = _target_screen;
+@synthesize previousScreen = _previous_screen;
+@synthesize currentScreen = _current_screen;
- (id)initWithContentRect:(NSRect)content_rect
styleMask:(NSUInteger)style_mask
backing:(NSBackingStoreType)buffering_type
@@ -46,10 +56,96 @@
defer:flag]) {
[self setBackgroundColor:[NSColor blackColor]];
[self setMinSize:NSMakeSize(50,50)];
+ [self setCollectionBehavior: NSWindowCollectionBehaviorFullScreenPrimary];
+
+ self.targetScreen = [self screen];
+ self.currentScreen = [self screen];
+ _is_animating = 0;
+ _unfs_content_frame = [self convertRectToScreen:[[self contentView] frame]];
+ _unfs_screen_frame = [[self screen] frame];
}
return self;
}
+- (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]];
+ _unfs_screen_frame = [[self screen] frame];
+ }
+
+ //move window to target screen when going to fullscreen
+ if (![self.adapter isInFullScreenMode] && ![[self targetScreen] isEqual:[self screen]]) {
+ [self setFrame:[self calculateWindowPositionForScreen:[self targetScreen]] display:YES];
+ }
+
+ [super toggleFullScreen:sender];
+
+ if (![self.adapter isInFullScreenMode]) {
+ [self setStyleMask:([self styleMask] | NSWindowStyleMaskFullScreen)];
+ NSRect frame = [[self targetScreen] frame];
+ [self setFrame:frame display:YES];
+ } else {
+ [self setStyleMask:([self styleMask] & ~NSWindowStyleMaskFullScreen)];
+ NSRect frame = [self calculateWindowPositionForScreen:[self targetScreen]];
+ [self setFrame:frame display:YES];
+ [self setContentAspectRatio:_unfs_content_frame.size];
+ [self setCenteredContentSize:_unfs_content_frame.size];
+ }
+}
+
+- (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:notification];
+}
+
+- (void)windowDidExitFullScreen:(NSNotification *)notification
+{
+ _is_animating = 0;
+ [self.adapter windowDidExitFullScreen:notification];
+}
+
+- (void)windowDidFailToEnterFullScreen:(NSWindow *)window
+{
+ _is_animating = 0;
+}
+
+- (void)windowDidFailToExitFullScreen:(NSWindow *)window
+{
+ _is_animating = 0;
+}
+
- (void)windowDidChangeBackingProperties:(NSNotification *)notification
{
// XXX: we maybe only need expose for this
@@ -58,12 +154,18 @@
- (void)windowDidChangeScreen:(NSNotification *)notification
{
+ //this event doesn't exclusively trigger on screen change
+ //examples: screen reconfigure, toggling fullscreen
+ if (!_is_animating && ![[self currentScreen] isEqual:[self screen]]) {
+ self.previousScreen = [self screen];
+ }
+ self.currentScreen = [self screen];
[self.adapter windowDidChangeScreen:notification];
}
- (void)windowDidChangeScreenProfile:(NSNotification *)notification
{
- [self.adapter didChangeWindowedScreenProfile:[self screen]];
+ [self.adapter didChangeWindowedScreenProfile:notification];
}
- (void)windowDidResignKey:(NSNotification *)notification
@@ -125,8 +227,41 @@
animate:NO];
}
+- (NSRect)calculateWindowPositionForScreen:(NSScreen *)screen
+{
+ NSRect frame = [self frameRectForContentRect:_unfs_content_frame];
+ NSRect targetFrame = [screen frame];
+
+ CGFloat x_per = (_unfs_screen_frame.size.width - frame.size.width);
+ CGFloat y_per = (_unfs_screen_frame.size.height - frame.size.height);
+ if (x_per > 0) x_per = (frame.origin.x - _unfs_screen_frame.origin.x)/x_per;
+ if (y_per > 0) y_per = (frame.origin.y - _unfs_screen_frame.origin.y)/y_per;
+
+ frame.origin.x = targetFrame.origin.x +
+ (targetFrame.size.width - frame.size.width)*x_per;
+ frame.origin.y = targetFrame.origin.y +
+ (targetFrame.size.height - frame.size.height)*y_per;
+
+ //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)
+ screen = [self targetScreen];
+
NSRect of = [self frame];
NSRect vf = [screen ?: self.screen ?: [NSScreen mainScreen] visibleFrame];
NSRect ncf = [self contentRectForFrameRect:nf];
@@ -136,7 +271,7 @@
if (NSMaxY(nf) > NSMaxY(vf))
nf.origin.y = NSMaxY(vf) - NSHeight(nf);
- // Prevent the window's titlebar from exiting the screen on the top edge.
+ // 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);
@@ -157,30 +292,42 @@
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)updateWindowFrame:(NSSize)newSize
+{
+ _unfs_content_frame = [self frameRect:_unfs_content_frame forCenteredContentSize:newSize];
+}
+
- (void)tryDequeueSize {
if (_queued_video_size.width <= 0.0 || _queued_video_size.height <= 0.0)
return;
- // XXX find a way to kill this state
- if (![self.adapter isInFullScreenMode]) {
- [self setContentAspectRatio:_queued_video_size];
- [self setCenteredContentSize:_queued_video_size];
- _queued_video_size = NSZeroSize;
- }
+ [self setContentAspectRatio:_queued_video_size];
+ [self setCenteredContentSize:_queued_video_size];
+ _queued_video_size = NSZeroSize;
}
-- (void)queueNewVideoSize:(NSSize)new_size
+- (void)queueNewVideoSize:(NSSize)newSize
{
- if (NSEqualSizes(_queued_video_size, new_size))
- return;
- _queued_video_size = new_size;
- [self tryDequeueSize];
+ if ([self.adapter isInFullScreenMode]) {
+ [self updateWindowFrame:newSize];
+ } else {
+ if (NSEqualSizes(_queued_video_size, newSize))
+ return;
+ _queued_video_size = newSize;
+ [self tryDequeueSize];
+ }
}
- (void)windowDidBecomeMain:(NSNotification *)notification {
diff --git a/video/out/cocoa_common.m b/video/out/cocoa_common.m
index 719169df48..c1a65ef2ee 100644
--- a/video/out/cocoa_common.m
+++ b/video/out/cocoa_common.m
@@ -49,11 +49,10 @@
#include "common/msg.h"
-static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now,
- const CVTimeStamp* outputTime, CVOptionFlags flagsIn,
+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_rm_fs_screen_profile_observer(struct vo_cocoa_state *s);
static void cocoa_add_screen_reconfiguration_observer(struct vo *vo);
static void cocoa_rm_screen_reconfiguration_observer(struct vo *vo);
@@ -70,15 +69,13 @@ struct vo_cocoa_state {
NSOpenGLContext *nsgl_ctx;
NSScreen *current_screen;
- NSScreen *fs_screen;
double screen_fps;
NSInteger window_level;
+ int fullscreen;
bool embedded; // wether we are embedding in another GUI
- atomic_bool waiting_frame;
-
IOPMAssertionID power_mgmt_assertion;
io_connect_t light_sensor;
uint64_t last_lmuvalue;
@@ -90,8 +87,6 @@ struct vo_cocoa_state {
uint32_t old_dwidth;
uint32_t old_dheight;
- id fs_icc_changed_ns_observer;
-
pthread_mutex_t lock;
pthread_cond_t wakeup;
@@ -122,14 +117,11 @@ static void queue_new_video_size(struct vo *vo, int w, int h)
{
struct vo_cocoa_state *s = vo->cocoa;
struct mp_vo_opts *opts = vo->opts;
- if ([s->window conformsToProtocol: @protocol(MpvSizing)]) {
- id<MpvSizing> win = (id<MpvSizing>) s->window;
- NSRect r = NSMakeRect(0, 0, w, h);
- if(!opts->hidpi_window_scale) {
- r = [s->current_screen convertRectFromBacking:r];
- }
- [win queueNewVideoSize:NSMakeSize(r.size.width, r.size.height)];
- }
+ id<MpvSizing> win = (id<MpvSizing>) s->window;
+ NSRect r = NSMakeRect(0, 0, w, h);
+ if(!opts->hidpi_window_scale)
+ r = [s->current_screen convertRectFromBacking:r];
+ [win queueNewVideoSize:NSMakeSize(r.size.width, r.size.height)];
}
static void flag_events(struct vo *vo, int events)
@@ -258,6 +250,39 @@ static void cocoa_uninit_light_sensor(struct vo_cocoa_state *s)
}
}
+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];
+ }
+}
+
void vo_cocoa_init(struct vo *vo)
{
struct vo_cocoa_state *s = talloc_zero(NULL, struct vo_cocoa_state);
@@ -265,6 +290,7 @@ void vo_cocoa_init(struct vo *vo)
.power_mgmt_assertion = kIOPMNullAssertionID,
.log = mp_log_new(s, vo->log, "cocoa"),
.embedded = vo->opts->WinID >= 0,
+ .fullscreen = 0,
};
if (!s->embedded) {
NSImage* blankImage = [[NSImage alloc] initWithSize:NSMakeSize(1, 1)];
@@ -274,6 +300,7 @@ void vo_cocoa_init(struct vo *vo)
pthread_mutex_init(&s->lock, NULL);
pthread_cond_init(&s->wakeup, NULL);
vo->cocoa = s;
+ vo_cocoa_update_screen_info(vo);
cocoa_init_light_sensor(vo);
cocoa_add_screen_reconfiguration_observer(vo);
if (!s->embedded) {
@@ -314,7 +341,6 @@ void vo_cocoa_uninit(struct vo *vo)
run_on_main_thread(vo, ^{
enable_power_management(s);
cocoa_uninit_light_sensor(s);
- cocoa_rm_fs_screen_profile_observer(s);
cocoa_rm_screen_reconfiguration_observer(vo);
[s->nsgl_ctx release];
@@ -325,12 +351,13 @@ void vo_cocoa_uninit(struct vo *vo)
[s->video removeFromSuperview];
[s->view removeFromSuperview];
- [(MpvEventsView *)s->view clear];
[s->view release];
// if using --wid + libmpv there's no window to release
- if (s->window)
- [s->window release];
+ if (s->window) {
+ [s->window setDelegate:nil];
+ [s->window close];
+ }
if (!s->embedded)
[s->blankCursor release];
@@ -341,44 +368,11 @@ void vo_cocoa_uninit(struct vo *vo)
});
}
-static int get_screen_handle(struct vo *vo, int identifier, NSWindow *window,
- NSScreen **screen) {
- struct vo_cocoa_state *s = vo->cocoa;
- NSArray *screens = [NSScreen screens];
- int n_of_displays = [screens count];
-
- if (identifier >= n_of_displays) { // check if the identifier is out of bounds
- MP_INFO(s, "Screen ID %d does not exist, falling back to main "
- "device\n", identifier);
- identifier = -1;
- }
-
- if (identifier < 0) {
- // default behaviour gets either the window screen or the main screen
- // if window is not available
- if (! (*screen = [window screen]) )
- *screen = [screens objectAtIndex:0];
- return 0;
- } else {
- *screen = [screens objectAtIndex:(identifier)];
- return 1;
- }
-}
-
-static void vo_cocoa_update_screens_pointers(struct vo *vo)
-{
- struct vo_cocoa_state *s = vo->cocoa;
- struct mp_vo_opts *opts = vo->opts;
- get_screen_handle(vo, opts->screen_id, s->window, &s->current_screen);
- get_screen_handle(vo, opts->fsscreen_id, s->window, &s->fs_screen);
-}
-
static void vo_cocoa_update_screen_fps(struct vo *vo)
{
struct vo_cocoa_state *s = vo->cocoa;
- NSScreen *screen = vo->opts->fullscreen ? s->fs_screen : s->current_screen;
- NSDictionary* sinfo = [screen deviceDescription];
+ NSDictionary* sinfo = [s->current_screen deviceDescription];
NSNumber* sid = [sinfo objectForKey:@"NSScreenNumber"];
CGDirectDisplayID did = [sid longValue];
@@ -416,21 +410,6 @@ static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
return kCVReturnSuccess;
}
-static void vo_cocoa_update_screen_info(struct vo *vo, struct mp_rect *out_rc)
-{
- struct vo_cocoa_state *s = vo->cocoa;
-
- if (s->embedded)
- return;
-
- vo_cocoa_update_screens_pointers(vo);
-
- if (out_rc) {
- NSRect r = [s->current_screen frame];
- *out_rc = (struct mp_rect){0, 0, r.size.width, r.size.height};
- }
-}
-
static void vo_set_level(struct vo *vo, int ontop)
{
struct vo_cocoa_state *s = vo->cocoa;
@@ -553,40 +532,12 @@ static int cocoa_set_window_title(struct vo *vo)
return VO_TRUE;
}
-static void cocoa_rm_fs_screen_profile_observer(struct vo_cocoa_state *s)
-{
- [[NSNotificationCenter defaultCenter]
- removeObserver:s->fs_icc_changed_ns_observer];
-}
-
-static void cocoa_add_fs_screen_profile_observer(struct vo *vo)
-{
- struct vo_cocoa_state *s = vo->cocoa;
-
- if (s->fs_icc_changed_ns_observer)
- cocoa_rm_fs_screen_profile_observer(s);
-
- if (vo->opts->fsscreen_id < 0)
- return;
-
- void (^nblock)(NSNotification *n) = ^(NSNotification *n) {
- flag_events(vo, VO_EVENT_ICC_PROFILE_CHANGED);
- };
-
- s->fs_icc_changed_ns_observer = [[NSNotificationCenter defaultCenter]
- addObserverForName:NSScreenColorSpaceDidChangeNotification
- object:s->fs_screen
- queue:nil
- usingBlock:nblock];
-}
-
static void cocoa_screen_reconfiguration_observer(
CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *ctx)
{
if (flags & kCGDisplaySetModeFlag) {
struct vo *vo = ctx;
MP_WARN(vo, "detected display mode change, updating screen info\n");
- vo_cocoa_update_screen_info(vo, NULL);
vo_cocoa_update_screen_fps(vo);
}
}
@@ -615,11 +566,13 @@ void vo_cocoa_set_opengl_ctx(struct vo *vo, CGLContextObj 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, ^{
- struct mp_rect screenrc;
- vo_cocoa_update_screen_info(vo, &screenrc);
vo_cocoa_update_screen_fps(vo);
+ NSRect r = [s->current_screen frame];
+ struct mp_rect screenrc = {0, 0, r.size.width, r.size.height};
struct vo_win_geometry geo;
vo_calc_window_geometry(vo, &screenrc, &geo);
vo_apply_window_geometry(vo, &geo);
@@ -638,10 +591,10 @@ int vo_cocoa_config_window(struct vo *vo)
if (!s->embedded && s->window) {
if (reset_size)
queue_new_video_size(vo, width, height);
- vo_cocoa_fullscreen(vo);
- cocoa_add_fs_screen_profile_observer(vo);
+ if (opts->fullscreen && !s->fullscreen)
+ vo_cocoa_fullscreen(vo);
cocoa_set_window_title(vo);
- vo_set_level(vo, vo->opts->ontop);
+ vo_set_level(vo, opts->ontop);
GLint o;
if (!CGLGetParameter(s->cgl_ctx, kCGLCPSurfaceOpacity, &o) && !o) {
@@ -691,9 +644,6 @@ static void vo_cocoa_resize_redraw(struct vo *vo, int width, int height)
pthread_mutex_lock(&s->lock);
- // Make vo.c not do video timing, which would slow down resizing.
- vo_event(vo, VO_EVENT_LIVE_RESIZING);
-
// Wait until a new frame with the new size was rendered. For some reason,
// Cocoa requires this to be done before drawRect() returns.
struct timespec e = mp_time_us_to_timespec(mp_add_timeout(mp_time_us(), 0.1));
@@ -702,18 +652,9 @@ static void vo_cocoa_resize_redraw(struct vo *vo, int width, int height)
break;
}
- vo_query_and_reset_events(vo, VO_EVENT_LIVE_RESIZING);
-
pthread_mutex_unlock(&s->lock);
}
-static void draw_changes_after_next_frame(struct vo *vo)
-{
- struct vo_cocoa_state *s = vo->cocoa;
- if (atomic_compare_exchange_strong(&s->waiting_frame, &(bool){false}, true))
- NSDisableScreenUpdates();
-}
-
void vo_cocoa_swap_buffers(struct vo *vo)
{
struct vo_cocoa_state *s = vo->cocoa;
@@ -730,9 +671,6 @@ void vo_cocoa_swap_buffers(struct vo *vo)
s->frame_h = vo->dheight;
pthread_cond_signal(&s->wakeup);
pthread_mutex_unlock(&s->lock);
-
- if (atomic_compare_exchange_strong(&s->waiting_frame, &(bool){true}, false))
- NSEnableScreenUpdates();
}
static int vo_cocoa_check_events(struct vo *vo)
@@ -754,25 +692,14 @@ static int vo_cocoa_check_events(struct vo *vo)
static int vo_cocoa_fullscreen(struct vo *vo)
{
struct vo_cocoa_state *s = vo->cocoa;
- struct mp_vo_opts *opts = vo->opts;
if (s->embedded)
return VO_NOTIMPL;
- vo_cocoa_update_screen_info(vo, NULL);
-
- draw_changes_after_next_frame(vo);
- [(MpvEventsView *)s->view setFullScreen:opts->fullscreen];
-
- if ([s->view window] != s->window) {
- // cocoa implements fullscreen views by moving the view to a fullscreen
- // window. Set that window delegate to the cocoa adapter to trigger
- // calls to -windowDidResignKey: and -windowDidBecomeKey:
- [[s->view window] setDelegate:s->adapter];
- }
-
- flag_events(vo, VO_EVENT_ICC_PROFILE_CHANGED);
- resize_event(vo);
+ [s->window toggleFullScreen:nil];
+ // for whatever reason sometimes cocoa doesn't create an up event on
+ // the fullscreen input key
+ cocoa_put_key(MP_INPUT_RELEASE_ALL);
return VO_TRUE;
}
@@ -782,10 +709,7 @@ static void vo_cocoa_control_get_icc_profile(struct vo *vo, void *arg)
struct vo_cocoa_state *s = vo->cocoa;
bstr *p = arg;
- vo_cocoa_update_screen_info(vo, NULL);
-
- NSScreen *screen = vo->opts->fullscreen ? s->fs_screen : s->current_screen;
- NSData *profile = [[screen colorSpace] ICCProfileData];
+ NSData *profile = [[s->current_screen colorSpace] ICCProfileData];
p->start = talloc_memdup(NULL, (void *)[profile bytes], [profile length]);
p->len = [profile length];
@@ -793,59 +717,61 @@ static void vo_cocoa_control_get_icc_profile(struct vo *vo, void *arg)
static int vo_cocoa_control_on_main_thread(struct vo *vo, int request, void *arg)
{
- struct mp_vo_opts *opts = vo->opts;
+ struct vo_cocoa_state *s = vo->cocoa;
switch (request) {
case VOCTRL_FULLSCREEN:
return vo_cocoa_fullscreen(vo);
+ case VOCTRL_GET_FULLSCREEN:
+ *(int *)arg = s->fullscreen;
+ return VO_TRUE;
case VOCTRL_ONTOP:
return vo_cocoa_ontop(vo);
case VOCTRL_GET_UNFS_WINDOW_SIZE: {
- int *s = arg;
- NSSize size = [vo->cocoa->view frame].size;
- s[0] = size.width;
- s[1] = size.height;
+ int *sz = arg;
+ NSSize size = [s->view frame].size;
+ sz[0] = size.width;
+ sz[1] = size.height;
return VO_TRUE;
}
case VOCTRL_SET_UNFS_WINDOW_SIZE: {
- int *s = arg;
+ int *sz = arg;
int w, h;
- w = s[0];
- h = s[1];
+ w = sz[0];
+ h = sz[1];
queue_new_video_size(vo, w, h);
return VO_TRUE;
}
case VOCTRL_GET_WIN_STATE: {
- const bool minimized = [[vo->cocoa->view window] isMiniaturized];
+ const bool minimized = [[s->view window] isMiniaturized];
*(int *)arg = minimized ? VO_WIN_STATE_MINIMIZED : 0;
return VO_TRUE;
}
case VOCTRL_SET_CURSOR_VISIBILITY:
return vo_cocoa_set_cursor_visibility(vo, arg);
case VOCTRL_UPDATE_WINDOW_TITLE: {
- struct vo_cocoa_state *s = vo->cocoa;
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(vo->cocoa);
+ enable_power_management(s);
return VO_TRUE;
case VOCTRL_KILL_SCREENSAVER:
- disable_power_management(vo->cocoa);
+ 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:
- if (vo->cocoa->screen_fps > 0.0) {
- *(double *)arg = vo->cocoa->screen_fps;
+ if (s->screen_fps > 0.0) {
+ *(double *)arg = s->screen_fps;
return VO_TRUE;
}
break;
case VOCTRL_GET_AMBIENT_LUX:
- if (vo->cocoa->light_sensor != IO_OBJECT_NULL) {
- *(int *)arg = vo->cocoa->last_lux;
+ if (s->light_sensor != IO_OBJECT_NULL) {
+ *(int *)arg = s->last_lux;
return VO_TRUE;
}
break;
@@ -879,8 +805,7 @@ int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg)
- (void)performAsyncResize:(NSSize)size {
struct vo_cocoa_state *s = self.vout->cocoa;
- if (!atomic_load(&s->waiting_frame))
- vo_cocoa_resize_redraw(self.vout, size.width, size.height);
+ vo_cocoa_resize_redraw(self.vout, size.width, size.height);
}
- (BOOL)keyboardEnabled {
@@ -898,7 +823,7 @@ int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg)
- (void)recalcMovableByWindowBackground:(NSPoint)p
{
BOOL movable = NO;
- if (![self isInFullScreenMode]) {
+ if (!self.vout->cocoa->fullscreen) {
movable = !mp_input_test_dragging(self.vout->input_ctx, p.x, p.y);
}
@@ -933,18 +858,18 @@ int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg)
ta_free(cmd_);
}
-- (BOOL)isInFullScreenMode {
- return self.vout->opts->fullscreen;
+- (BOOL)isInFullScreenMode
+{
+ return self.vout->cocoa->fullscreen;
}
-- (NSScreen *)fsScreen {
+- (NSScreen *)getTargetScreen
+{
struct vo_cocoa_state *s = self.vout->cocoa;
- return s->fs_screen;
-}
+ struct mp_vo_opts *opts = self.vout->opts;
-- (BOOL)fsModeAllScreens
-{
- return self.vout->opts->fs_black_out_screens;
+ int screen_id = s->fullscreen ? opts->screen_id : opts->fsscreen_id;
+ return get_screen_by_id(self.vout, screen_id);
}
- (void)handleFilesArray:(NSArray *)files
@@ -954,11 +879,36 @@ int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg)
- (void)windowDidChangeScreen:(NSNotification *)notification
{
- vo_cocoa_update_screen_info(self.vout, NULL);
+ vo_cocoa_update_screen_info(self.vout);
vo_cocoa_update_screen_fps(self.vout);
}
-- (void)didChangeWindowedScreenProfile:(NSScreen *)screen
+- (void)windowDidEnterFullScreen:(NSNotification *)notification
+{
+ struct vo_cocoa_state *s = self.vout->cocoa;
+ s->fullscreen = 1;
+ s->pending_events |= VO_EVENT_FULLSCREEN_STATE;
+}
+
+- (void)windowDidExitFullScreen:(NSNotification *)notification
+{
+ struct vo_cocoa_state *s = self.vout->cocoa;
+ s->fullscreen = 0;
+ s->pending_events |= VO_EVENT_FULLSCREEN_STATE;
+}
+
+- (void)windowWillStartLiveResize:(NSNotification *)notification
+{
+ // Make vo.c not do video timing, which would slow down resizing.
+ vo_event(self.vout, VO_EVENT_LIVE_RESIZING);
+}
+
+- (void)windowDidEndLiveResize:(NSNotification *)notification
+{
+ vo_query_and_reset_events(self.vout, VO_EVENT_LIVE_RESIZING);
+}
+
+- (void)didChangeWindowedScreenProfile:(NSNotification *)notification
{
flag_events(self.vout, VO_EVENT_ICC_PROFILE_CHANGED);
}