summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorStefano Pigozzi <stefano.pigozzi@gmail.com>2013-05-29 00:14:34 +0200
committerStefano Pigozzi <stefano.pigozzi@gmail.com>2013-05-30 23:01:12 +0200
commit0057aa476999138c4a5496a4af95a639c01df4d5 (patch)
treefac1ca5ce0fc5687c1787d139abe02503dd967f1 /video
parent3396e0565b39c5168777b78cc26ed3b985a81071 (diff)
downloadmpv-0057aa476999138c4a5496a4af95a639c01df4d5.tar.bz2
mpv-0057aa476999138c4a5496a4af95a639c01df4d5.tar.xz
cocoa_common: use cocoa APIs to go fullscreen
This removes a bit of ugly code and bookeeping which is never bad. `drawRect` needs to guard against different window instances since in fullscreen the view is wrapped in a fullscreen window provided by the toolkit (a instance of NSFullScreenWindow to be precise). The event handling was moved to the view so that it can still get all the events when in the fullscreen window. Ideally these should be moved to some NSResponder subclass within macosx_application and made available even when no window is present. I refrained from this because "small steps".
Diffstat (limited to 'video')
-rw-r--r--video/out/cocoa_common.h2
-rw-r--r--video/out/cocoa_common.m382
2 files changed, 165 insertions, 219 deletions
diff --git a/video/out/cocoa_common.h b/video/out/cocoa_common.h
index b352ce160b..f6af87f3b7 100644
--- a/video/out/cocoa_common.h
+++ b/video/out/cocoa_common.h
@@ -29,8 +29,6 @@ void *vo_cocoa_glgetaddr(const char *s);
int vo_cocoa_init(struct vo *vo);
void vo_cocoa_uninit(struct vo *vo);
-void vo_cocoa_update_xinerama_info(struct vo *vo);
-
int vo_cocoa_change_attributes(struct vo *vo);
int vo_cocoa_config_window(struct vo *vo, uint32_t d_width,
uint32_t d_height, uint32_t flags,
diff --git a/video/out/cocoa_common.m b/video/out/cocoa_common.m
index f5f1d9770f..e9873304c8 100644
--- a/video/out/cocoa_common.m
+++ b/video/out/cocoa_common.m
@@ -60,7 +60,6 @@ static bool RightAltPressed(NSEvent *event)
- (BOOL)canBecomeKeyWindow;
- (BOOL)canBecomeMainWindow;
- (void)fullscreen;
-- (void)mouseEvent:(NSEvent *)theEvent;
- (void)mulSize:(float)multiplier;
- (int)titleHeight;
- (NSRect)clipFrame:(NSRect)frame withContentAspect:(NSSize) aspect;
@@ -69,6 +68,8 @@ static bool RightAltPressed(NSEvent *event)
@end
@interface GLMPlayerOpenGLView : NSView
+@property(nonatomic, assign) struct vo *videoOutput;
+- (void)mouseEvent:(NSEvent *)theEvent;
@end
struct vo_cocoa_input_queue {
@@ -115,29 +116,21 @@ static int cocoa_sync_get_key(struct vo_cocoa_input_queue *iq)
struct vo_cocoa_state {
GLMPlayerWindow *window;
+ GLMPlayerOpenGLView *view;
NSOpenGLContext *glContext;
NSOpenGLPixelFormat *pixelFormat;
NSSize current_video_size;
NSSize previous_video_size;
- NSRect screen_frame;
- NSRect fsscreen_frame;
- NSScreen *screen_handle;
-
- NSInteger windowed_mask;
- NSInteger fullscreen_mask;
-
- NSRect windowed_frame;
-
- NSString *window_title;
+ NSScreen *current_screen;
+ NSScreen *fs_screen;
NSInteger window_level;
struct aspect_data aspdat;
bool will_make_front;
-
bool did_resize;
bool did_async_resize;
bool out_fs_resize;
@@ -147,7 +140,6 @@ struct vo_cocoa_state {
CGFloat accumulated_scroll;
NSLock *lock;
-
bool enable_resize_redraw;
void (*resize_redraw)(struct vo *vo, int w, int h);
@@ -162,10 +154,6 @@ static struct vo_cocoa_state *vo_cocoa_init_state(struct vo *vo)
.did_async_resize = NO,
.current_video_size = {0,0},
.previous_video_size = {0,0},
- .windowed_mask = NSTitledWindowMask|NSClosableWindowMask|
- NSMiniaturizableWindowMask|NSResizableWindowMask,
- .fullscreen_mask = NSBorderlessWindowMask,
- .windowed_frame = {{0,0},{0,0}},
.out_fs_resize = NO,
.will_make_front = YES,
.power_mgmt_assertion = kIOPMNullAssertionID,
@@ -174,16 +162,13 @@ static struct vo_cocoa_state *vo_cocoa_init_state(struct vo *vo)
.input_queue = vo_cocoa_input_queue_init(s),
.enable_resize_redraw = NO,
};
- if (!vo->opts->border) s->windowed_mask = NSBorderlessWindowMask;
-
return s;
}
static NSRect to_pixels(struct vo *vo, NSRect frame)
{
struct vo_cocoa_state *s = vo->cocoa;
- NSView *view = [s->window contentView];
- return [view convertRectToBacking: frame];
+ return [s->view convertRectToBacking: frame];
}
void *vo_cocoa_glgetaddr(const char *s)
@@ -268,14 +253,6 @@ void vo_cocoa_register_resize_callback(struct vo *vo,
s->resize_redraw = cb;
}
-static int current_screen_has_dock_or_menubar(struct vo *vo)
-{
- struct vo_cocoa_state *s = vo->cocoa;
- NSRect f = s->screen_frame;
- NSRect vf = [s->screen_handle visibleFrame];
- return f.size.height > vf.size.height || f.size.width > vf.size.width;
-}
-
static int get_screen_handle(int identifier, NSWindow *window, NSScreen **screen) {
NSArray *screens = [NSScreen screens];
int n_of_displays = [screens count];
@@ -302,34 +279,30 @@ static void update_screen_info(struct vo *vo)
{
struct vo_cocoa_state *s = vo->cocoa;
struct mp_vo_opts *opts = vo->opts;
- NSScreen *ws, *fss;
-
- get_screen_handle(opts->screen_id, s->window, &ws);
- s->screen_frame = [ws frame];
-
- get_screen_handle(opts->fsscreen_id, s->window, &fss);
- s->fsscreen_frame = [fss frame];
+ get_screen_handle(opts->screen_id, s->window, &s->current_screen);
+ get_screen_handle(opts->fsscreen_id, s->window, &s->fs_screen);
}
-void vo_cocoa_update_xinerama_info(struct vo *vo)
+static void vo_cocoa_update_screen_info(struct vo *vo)
{
struct vo_cocoa_state *s = vo->cocoa;
struct mp_vo_opts *opts = vo->opts;
update_screen_info(vo);
- aspect_save_screenres(vo, s->screen_frame.size.width,
- s->screen_frame.size.height);
- opts->screenwidth = s->screen_frame.size.width;
- opts->screenheight = s->screen_frame.size.height;
- vo->xinerama_x = s->screen_frame.origin.x;
- vo->xinerama_y = s->screen_frame.origin.y;
+
+ NSRect r = [s->current_screen frame];
+
+ aspect_save_screenres(vo, r.size.width, r.size.height);
+ opts->screenwidth = r.size.width;
+ opts->screenheight = r.size.height;
+ vo->xinerama_x = r.origin.x;
+ vo->xinerama_y = r.origin.y;
}
static void resize_window(struct vo *vo)
{
struct vo_cocoa_state *s = vo->cocoa;
- NSView *view = [s->window contentView];
- NSRect frame = to_pixels(vo, [view frame]);
+ NSRect frame = to_pixels(vo, [s->view frame]);
vo->dwidth = frame.size.width;
vo->dheight = frame.size.height;
[s->glContext update];
@@ -370,16 +343,22 @@ static int create_window(struct vo *vo, uint32_t d_width, uint32_t d_height,
d_width, d_height);
const NSRect glview_rect = NSMakeRect(0, 0, 100, 100);
+ int window_mask = 0;
+ if (vo->opts->border) {
+ window_mask = NSTitledWindowMask|NSClosableWindowMask|
+ NSMiniaturizableWindowMask|NSResizableWindowMask;
+ } else {
+ window_mask = NSBorderlessWindowMask;
+ }
+
s->window =
[[GLMPlayerWindow alloc] initWithContentRect:window_rect
- styleMask:s->windowed_mask
+ styleMask:window_mask
backing:NSBackingStoreBuffered
defer:NO];
- GLMPlayerOpenGLView *glView =
- [[GLMPlayerOpenGLView alloc] initWithFrame:glview_rect];
-
- [glView setWantsBestResolutionOpenGLSurface:YES];
+ s->view = [[GLMPlayerOpenGLView alloc] initWithFrame:glview_rect];
+ [s->view setWantsBestResolutionOpenGLSurface:YES];
int i = 0;
NSOpenGLPixelFormatAttribute attr[32];
@@ -411,11 +390,12 @@ static int create_window(struct vo *vo, uint32_t d_width, uint32_t d_height,
cocoa_register_menu_item_action(MPM_ZOOM, @selector(performZoom:));
[s->window setRestorable:NO];
- [s->window setContentView:glView];
- [glView release];
+ [s->window setContentView:s->view];
+ [s->view release];
[s->window setAcceptsMouseMovedEvents:YES];
- [s->glContext setView:glView];
+ [s->glContext setView:s->view];
s->window.videoOutput = vo;
+ s->view.videoOutput = vo;
[s->window setDelegate:s->window];
[s->window makeMainWindow];
@@ -426,21 +406,25 @@ static int create_window(struct vo *vo, uint32_t d_width, uint32_t d_height,
return 0;
}
+static void resize_window_from_stored_size(struct vo *vo)
+{
+ struct vo_cocoa_state *s = vo->cocoa;
+ [s->window setContentSize:s->current_video_size keepCentered:YES];
+ [s->window setContentAspectRatio:s->current_video_size];
+}
+
static void update_window(struct vo *vo)
{
struct vo_cocoa_state *s = vo->cocoa;
- if (s->current_video_size.width != s->previous_video_size.width ||
- s->current_video_size.height != s->previous_video_size.height) {
+ if (!CGSizeEqualToSize(s->current_video_size, s->previous_video_size)) {
if (vo->opts->fs) {
// we will resize as soon as we get out of fullscreen
s->out_fs_resize = YES;
} else {
// only if we are not in fullscreen and the video size did
// change we resize the window and set a new aspect ratio
- [s->window setContentSize:s->current_video_size
- keepCentered:YES];
- [s->window setContentAspectRatio:s->current_video_size];
+ resize_window_from_stored_size(vo);
}
}
}
@@ -486,7 +470,6 @@ int vo_cocoa_config_window(struct vo *vo, uint32_t d_width,
[s->window setFrameOrigin:NSMakePoint(vo->dx, vo->dy)];
-
if (flags & VOFLAG_HIDDEN) {
[s->window orderOut:nil];
} else if (![s->window isVisible] && s->will_make_front) {
@@ -502,12 +485,8 @@ int vo_cocoa_config_window(struct vo *vo, uint32_t d_width,
resize_window(vo);
- if (s->window_title)
- [s->window_title release];
-
- s->window_title =
- [[NSString alloc] initWithUTF8String:vo_get_window_title(vo)];
- [s->window setTitle: s->window_title];
+ [s->window setTitle:
+ [NSString stringWithUTF8String:vo_get_window_title(vo)]];
if (opts->native_fs) {
[s->window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
@@ -603,7 +582,7 @@ int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg)
vo_cocoa_ontop(vo);
return VO_TRUE;
case VOCTRL_UPDATE_SCREENINFO:
- vo_cocoa_update_xinerama_info(vo);
+ vo_cocoa_update_screen_info(vo);
return VO_TRUE;
case VOCTRL_SET_CURSOR_VISIBILITY: {
bool visible = *(bool *)arg;
@@ -682,41 +661,37 @@ int vo_cocoa_cgl_color_size(struct vo *vo)
[self toggleFullScreen:nil];
} else {
if (!opts->fs) {
- opts->fs = VO_TRUE;
+ NSDictionary *fsopts = @{
+ NSFullScreenModeWindowLevel :
+ @(NSFloatingWindowLevel),
+ NSFullScreenModeAllScreens :
+ @NO,
+ NSFullScreenModeApplicationPresentationOptions :
+ @(NSApplicationPresentationAutoHideDock |
+ NSApplicationPresentationAutoHideMenuBar)
+ };
+
+ [s->view enterFullScreenMode:s->fs_screen withOptions:fsopts];
vo_cocoa_set_cursor_visibility(false);
- update_screen_info(self.videoOutput);
- if (current_screen_has_dock_or_menubar(self.videoOutput))
- [NSApp setPresentationOptions:
- NSApplicationPresentationAutoHideDock|
- NSApplicationPresentationAutoHideMenuBar];
- s->windowed_frame = [self frame];
- [self setHasShadow:NO];
- [self setStyleMask:s->fullscreen_mask];
- [self setFrame:s->fsscreen_frame display:YES animate:NO];
+ opts->fs = VO_TRUE;
} else {
- opts->fs = VO_FALSE;
+ [s->view exitFullScreenModeWithOptions:nil];
vo_cocoa_set_cursor_visibility(true);
- [NSApp setPresentationOptions:NSApplicationPresentationDefault];
- [self setHasShadow:YES];
- [self setStyleMask:s->windowed_mask];
- [self setTitle:s->window_title];
- [self setFrame:s->windowed_frame display:YES animate:NO];
- if (s->out_fs_resize) {
- [self setContentSize:s->current_video_size keepCentered:YES];
- s->out_fs_resize = NO;
- }
- [self setContentAspectRatio:s->current_video_size];
+ [self makeFirstResponder:s->view];
+ opts->fs = VO_FALSE;
}
}
+ if (!opts->fs && s->out_fs_resize) {
+ resize_window_from_stored_size(self.videoOutput);
+ s->out_fs_resize = NO;
+ }
+
resize_window(self.videoOutput);
}
- (BOOL)canBecomeMainWindow { return YES; }
- (BOOL)canBecomeKeyWindow { return YES; }
-- (BOOL)acceptsFirstResponder { return YES; }
-- (BOOL)becomeFirstResponder { return YES; }
-- (BOOL)resignFirstResponder { return YES; }
- (BOOL)windowShouldClose:(id)sender
{
struct vo_cocoa_state *s = self.videoOutput->cocoa;
@@ -736,7 +711,94 @@ int vo_cocoa_cgl_color_size(struct vo *vo)
}
}
-- (void)keyDown:(NSEvent *)theEvent
+- (void)normalSize { [self mulSize:1.0f]; }
+
+- (void)halfSize { [self mulSize:0.5f];}
+
+- (void)doubleSize { [self mulSize:2.0f];}
+
+- (void)mulSize:(float)multiplier
+{
+ if (!self.videoOutput->opts->fs) {
+ NSSize size = {
+ .width = self.videoOutput->cocoa->aspdat.prew * multiplier,
+ .height = self.videoOutput->cocoa->aspdat.preh * multiplier
+ };
+ [self setContentSize:size keepCentered:YES];
+ }
+}
+
+- (int)titleHeight
+{
+ NSRect of = [self frame];
+ NSRect cb = [[self contentView] bounds];
+ return of.size.height - cb.size.height;
+}
+
+- (NSRect)clipFrame:(NSRect)frame withContentAspect:(NSSize) aspect
+{
+ NSRect vf = [[self screen] visibleFrame];
+ double ratio = (double)aspect.width / (double)aspect.height;
+
+ // clip frame to screens visibile frame
+ frame = CGRectIntersection(frame, vf);
+
+ NSSize s = frame.size;
+ s.height -= [self titleHeight];
+
+ if (s.width > s.height) {
+ s.width = ((double)s.height * ratio);
+ } else {
+ s.height = ((double)s.width * 1.0/ratio);
+ }
+
+ s.height += [self titleHeight];
+ frame.size = s;
+
+ return frame;
+}
+
+- (void)setCenteredContentSize:(NSSize)ns
+{
+#define get_center(x) NSMakePoint(CGRectGetMidX((x)), CGRectGetMidY((x)))
+ NSRect of = [self frame];
+ NSRect vf = [[self screen] visibleFrame];
+ NSPoint old_center = get_center(of);
+
+ NSRect nf = NSMakeRect(vf.origin.x, vf.origin.y,
+ ns.width, ns.height + [self titleHeight]);
+
+ nf = [self clipFrame:nf withContentAspect:ns];
+
+ NSPoint new_center = get_center(nf);
+
+ int dx0 = old_center.x - new_center.x;
+ int dy0 = old_center.y - new_center.y;
+
+ nf.origin.x += dx0;
+ nf.origin.y += dy0;
+
+ [self setFrame:nf display:YES animate:NO];
+#undef get_center
+}
+
+- (void)setContentSize:(NSSize)ns keepCentered:(BOOL)keepCentered
+{
+ if (keepCentered) {
+ [self setCenteredContentSize:ns];
+ } else {
+ [self setContentSize:ns];
+ }
+}
+@end
+
+@implementation GLMPlayerOpenGLView
+@synthesize videoOutput = _video_output;
+- (BOOL)acceptsFirstResponder { return YES; }
+- (BOOL)becomeFirstResponder { return YES; }
+- (BOOL)resignFirstResponder { return YES; }
+
+ - (void)keyDown:(NSEvent *)theEvent
{
struct vo_cocoa_state *s = self.videoOutput->cocoa;
NSString *chars;
@@ -764,9 +826,8 @@ int vo_cocoa_cgl_color_size(struct vo *vo)
- (void)signalMouseMovement:(NSEvent *)theEvent
{
- NSView *view = self.contentView;
- NSPoint loc = [view convertPoint:[theEvent locationInWindow] fromView:nil];
- NSRect bounds = [view bounds];
+ NSPoint loc = [self convertPoint:[theEvent locationInWindow] fromView:nil];
+ NSRect bounds = [self bounds];
int x = loc.x;
int y = - loc.y + bounds.size.height; // convert to x11-like coord system
@@ -775,45 +836,14 @@ int vo_cocoa_cgl_color_size(struct vo *vo)
}
}
-- (void)mouseMoved:(NSEvent *)theEvent
-{
- [self signalMouseMovement:theEvent];
-}
-
-- (void)mouseDragged:(NSEvent *)theEvent
-{
- [self signalMouseMovement:theEvent];
-}
-
-- (void)mouseDown:(NSEvent *)theEvent
-{
- [self mouseEvent: theEvent];
-}
-
-- (void)mouseUp:(NSEvent *)theEvent
-{
- [self mouseEvent: theEvent];
-}
-
-- (void)rightMouseDown:(NSEvent *)theEvent
-{
- [self mouseEvent: theEvent];
-}
-
-- (void)rightMouseUp:(NSEvent *)theEvent
-{
- [self mouseEvent: theEvent];
-}
-
-- (void)otherMouseDown:(NSEvent *)theEvent
-{
- [self mouseEvent: theEvent];
-}
-
-- (void)otherMouseUp:(NSEvent *)theEvent
-{
- [self mouseEvent: theEvent];
-}
+- (void)mouseMoved:(NSEvent *)evt { [self signalMouseMovement:evt]; }
+- (void)mouseDragged:(NSEvent *)evt { [self signalMouseMovement:evt]; }
+- (void)mouseDown:(NSEvent *)evt { [self mouseEvent:evt]; }
+- (void)mouseUp:(NSEvent *)evt { [self mouseEvent:evt]; }
+- (void)rightMouseDown:(NSEvent *)evt { [self mouseEvent:evt]; }
+- (void)rightMouseUp:(NSEvent *)evt { [self mouseEvent:evt]; }
+- (void)otherMouseDown:(NSEvent *)evt { [self mouseEvent:evt]; }
+- (void)otherMouseUp:(NSEvent *)evt { [self mouseEvent:evt]; }
- (void)scrollWheel:(NSEvent *)theEvent
{
@@ -878,92 +908,10 @@ int vo_cocoa_cgl_color_size(struct vo *vo)
}
}
-- (void)normalSize { [self mulSize:1.0f]; }
-
-- (void)halfSize { [self mulSize:0.5f];}
-
-- (void)doubleSize { [self mulSize:2.0f];}
-
-- (void)mulSize:(float)multiplier
-{
- if (!self.videoOutput->opts->fs) {
- NSSize size = {
- .width = self.videoOutput->cocoa->aspdat.prew * multiplier,
- .height = self.videoOutput->cocoa->aspdat.preh * multiplier
- };
- [self setContentSize:size keepCentered:YES];
- }
-}
-
-- (int)titleHeight
-{
- NSRect of = [self frame];
- NSRect cb = [[self contentView] bounds];
- return of.size.height - cb.size.height;
-}
-
-- (NSRect)clipFrame:(NSRect)frame withContentAspect:(NSSize) aspect
-{
- NSRect vf = [[self screen] visibleFrame];
- double ratio = (double)aspect.width / (double)aspect.height;
-
- // clip frame to screens visibile frame
- frame = CGRectIntersection(frame, vf);
-
- NSSize s = frame.size;
- s.height -= [self titleHeight];
-
- if (s.width > s.height) {
- s.width = ((double)s.height * ratio);
- } else {
- s.height = ((double)s.width * 1.0/ratio);
- }
-
- s.height += [self titleHeight];
- frame.size = s;
-
- return frame;
-}
-
-- (void)setCenteredContentSize:(NSSize)ns
-{
-#define get_center(x) NSMakePoint(CGRectGetMidX((x)), CGRectGetMidY((x)))
- NSRect of = [self frame];
- NSRect vf = [[self screen] visibleFrame];
- NSPoint old_center = get_center(of);
-
- NSRect nf = NSMakeRect(vf.origin.x, vf.origin.y,
- ns.width, ns.height + [self titleHeight]);
-
- nf = [self clipFrame:nf withContentAspect:ns];
-
- NSPoint new_center = get_center(nf);
-
- int dx0 = old_center.x - new_center.x;
- int dy0 = old_center.y - new_center.y;
-
- nf.origin.x += dx0;
- nf.origin.y += dy0;
-
- [self setFrame:nf display:YES animate:NO];
-#undef get_center
-}
-
-- (void)setContentSize:(NSSize)ns keepCentered:(BOOL)keepCentered
-{
- if (keepCentered) {
- [self setCenteredContentSize:ns];
- } else {
- [self setContentSize:ns];
- }
-}
-@end
-
-@implementation GLMPlayerOpenGLView
- (void)drawRect: (NSRect)rect
{
- GLMPlayerWindow *window = (GLMPlayerWindow *)[self window];
- struct vo *vo = [window videoOutput];
+ struct vo *vo = [self videoOutput];
+
if (vo && resize_callback_registered(vo)) {
NSSize size = to_pixels(vo, [self bounds]).size;
resize_redraw(vo, size.width, size.height);