mirror of
https://github.com/mpv-player/mpv
synced 2025-01-24 08:33:34 +00:00
c8ed4736ef
This is just temporary code but is a good base for future work (and baby steps are required for these changes). The 'final destination' is embedding the video view into any NSView but that requires some more work (the mechanism will be the same: pass the view's pointer casted to int64_t through -wid). For instance we will need to remove as much usage of the window instance as possible, and use nil guards where not possible. For this reason I will remove stuff like the mission control fullscreen feature (it's a cute feature but annoying to support and quite limited, go make your GUIs), and a way to lookup the current screen directly from the NSView absolute coordinates (this is needed for ICC detection mostly, and reporting back the screen to mpv's core). Moreover the current view.m will need to be separated into 2 views: the actual video view that will be embedded, and a parent view that will not be embedded and will be responsibile for tracking events.
205 lines
6.0 KiB
Objective-C
205 lines
6.0 KiB
Objective-C
/*
|
|
* This file is part of mpv.
|
|
*
|
|
* mpv is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with mpv. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <libavutil/common.h>
|
|
|
|
#include "input/keycodes.h"
|
|
|
|
#include "osdep/macosx_events.h"
|
|
#include "osdep/macosx_compat.h"
|
|
|
|
#include "video/out/cocoa/additions.h"
|
|
#include "video/out/cocoa_common.h"
|
|
|
|
#include "window.h"
|
|
|
|
@interface MpvVideoWindow()
|
|
- (NSRect)frameRect:(NSRect)frameRect forCenteredContentSize:(NSSize)newSize;
|
|
- (void)setCenteredContentSize:(NSSize)newSize;
|
|
@end
|
|
|
|
@implementation MpvVideoWindow {
|
|
NSSize _queued_video_size;
|
|
}
|
|
|
|
@synthesize adapter = _adapter;
|
|
- (id)initWithContentRect:(NSRect)content_rect
|
|
styleMask:(NSUInteger)style_mask
|
|
backing:(NSBackingStoreType)buffering_type
|
|
defer:(BOOL)flag
|
|
{
|
|
if (self = [super initWithContentRect:content_rect
|
|
styleMask:style_mask
|
|
backing:buffering_type
|
|
defer:flag]) {
|
|
[self setBackgroundColor:[NSColor blackColor]];
|
|
[self setMinSize:NSMakeSize(50,50)];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)windowDidChangeBackingProperties:(NSNotification *)notification
|
|
{
|
|
// XXX: we maybe only need expose for this
|
|
[self.adapter setNeedsResize];
|
|
}
|
|
|
|
- (void)windowDidChangeScreenProfile:(NSNotification *)notification
|
|
{
|
|
[self.adapter didChangeWindowedScreenProfile:[self screen]];
|
|
}
|
|
|
|
- (BOOL)isInFullScreenMode
|
|
{
|
|
return !!([self styleMask] & NSFullScreenWindowMask);
|
|
}
|
|
|
|
- (void)setFullScreen:(BOOL)willBeFullscreen
|
|
{
|
|
if (willBeFullscreen != [self isInFullScreenMode]) {
|
|
[super toggleFullScreen:nil];
|
|
}
|
|
}
|
|
|
|
- (void)toggleFullScreen:(id)sender {
|
|
if ([self isInFullScreenMode]) {
|
|
[self.adapter putCommand:"set fullscreen no"];
|
|
} else {
|
|
[self.adapter putCommand:"set fullscreen yes"];
|
|
}
|
|
}
|
|
|
|
- (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];
|
|
}
|
|
|
|
- (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)constrainFrameRect:(NSRect)nf toScreen:(NSScreen *)screen
|
|
{
|
|
if ([self isInFullScreenMode])
|
|
return [super constrainFrameRect:nf toScreen:screen];
|
|
|
|
NSRect of = [self frame];
|
|
NSRect vf = [screen ?: self.screen ?: [NSScreen mainScreen] 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 top 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))
|
|
// 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)windowDidEndLiveResize:(NSNotification *)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;
|
|
|
|
if (![self.adapter isInFullScreenMode]) {
|
|
[self setContentAspectRatio:_queued_video_size];
|
|
[self setCenteredContentSize:_queued_video_size];
|
|
_queued_video_size = NSZeroSize;
|
|
}
|
|
}
|
|
|
|
- (void)queueNewVideoSize:(NSSize)new_size
|
|
{
|
|
if (NSEqualSizes(_queued_video_size, new_size))
|
|
return;
|
|
_queued_video_size = new_size;
|
|
[self tryDequeueSize];
|
|
}
|
|
|
|
- (void)windowDidBecomeMain:(NSNotification *)notification {
|
|
[self tryDequeueSize];
|
|
}
|
|
|
|
- (NSSize)window:(NSWindow *)window willUseFullScreenContentSize:(NSSize)size {
|
|
return window.screen.frame.size;
|
|
}
|
|
|
|
- (NSApplicationPresentationOptions)window:(NSWindow *)window
|
|
willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)opts {
|
|
return NSApplicationPresentationFullScreen |
|
|
NSApplicationPresentationAutoHideDock |
|
|
NSApplicationPresentationAutoHideMenuBar |
|
|
NSApplicationPresentationAutoHideToolbar;
|
|
}
|
|
|
|
- (void)windowDidExitFullScreen:(NSNotification *)notification {
|
|
[self tryDequeueSize];
|
|
}
|
|
@end
|