aboutsummaryrefslogtreecommitdiffhomepage
path: root/video/out/cocoa/window.m
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/cocoa/window.m')
-rw-r--r--video/out/cocoa/window.m173
1 files changed, 160 insertions, 13 deletions
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 {