]> git.sesse.net Git - vlc/blobdiff - modules/video_output/macosx.m
Revert "macosx: don't let the video window get larger than the screen it is on (close...
[vlc] / modules / video_output / macosx.m
index 4034858cff603eaaaf0f453c4b723b6f431b849a..1537325f37b2875362eb21b7bfa71087d05cc005 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
- * voutgl.m: MacOS X OpenGL provider
+ * macosx.m: MacOS X OpenGL provider
  *****************************************************************************
- * Copyright (C) 2001-2009 the VideoLAN team
+ * Copyright (C) 2001-2012 the VideoLAN team
  * $Id$
  *
  * Authors: Colin Delacroix <colin@zoy.org>
@@ -12,6 +12,7 @@
  *          Benjamin Pracht <bigben at videolan dot org>
  *          Damien Fouilleul <damienf at videolan dot org>
  *          Pierre d'Herbemont <pdherbemont at videolan dot org>
+ *          Felix Paul Kühne <fkuehne at videolan dot org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include <vlc_plugin.h>
 #include <vlc_vout_display.h>
 #include <vlc_opengl.h>
+#include <vlc_dialog.h>
 #include "opengl.h"
 
+@interface NSWindow (VLCCustomCode)
+- (BOOL)isFullscreen;
+@end
+
 /**
  * Forward declarations
  */
@@ -89,6 +95,7 @@ vlc_module_end ()
     BOOL _hasPendingReshape;
 }
 - (void)setVoutDisplay:(vout_display_t *)vd;
+- (vout_display_t *)voutDisplay;
 - (void)setVoutFlushing:(BOOL)flushing;
 @end
 
@@ -116,6 +123,15 @@ static int Open(vlc_object_t *this)
     if (!sys)
         return VLC_ENOMEM;
 
+    if( !CGDisplayUsesOpenGLAcceleration( kCGDirectMainDisplay ) )
+    {
+        msg_Err( this, "no OpenGL hardware acceleration found, video output will fail" );
+        dialog_Fatal( this, _("Video output is not supported"), _("Your Mac lacks Quartz Extreme acceleration, which is required for video output.") );
+        return VLC_EGENERIC;
+    }
+    else
+        msg_Dbg( this, "Quartz Extreme acceleration is active" );
+
     vd->sys = sys;
     sys->pool = NULL;
     sys->gl.sys = NULL;
@@ -189,9 +205,11 @@ static int Open(vlc_object_t *this)
     sys->gl.swap = OpenglSwap;
     sys->gl.getProcAddress = NULL;
     sys->gl.sys = sys;
+    const vlc_fourcc_t *subpicture_chromas;
+    video_format_t fmt = vd->fmt;
 
-       sys->vgl = vout_display_opengl_New(&vd->fmt, NULL, &sys->gl);
-       if (!sys->vgl)
+    sys->vgl = vout_display_opengl_New(&vd->fmt, &subpicture_chromas, &sys->gl);
+    if (!sys->vgl)
     {
         sys->gl.sys = NULL;
         goto error;
@@ -200,6 +218,8 @@ static int Open(vlc_object_t *this)
     /* */
     vout_display_info_t info = vd->info;
     info.has_pictures_invalid = false;
+    info.has_event_thread = true;
+    info.subpicture_chromas = subpicture_chromas;
 
     /* Setup vout_display_t once everything is fine */
     vd->info = info;
@@ -226,6 +246,9 @@ void Close(vlc_object_t *this)
     vout_display_t *vd = (vout_display_t *)this;
     vout_display_sys_t *sys = vd->sys;
 
+    if ([[sys->glView window] level] != NSNormalWindowLevel)
+        [[sys->glView window] setLevel: NSNormalWindowLevel];
+
     [sys->glView setVoutDisplay:nil];
 
     var_Destroy(vd, "drawable-nsobject");
@@ -278,7 +301,9 @@ static void PictureDisplay(vout_display_t *vd, picture_t *pic, subpicture_t *sub
     [sys->glView setVoutFlushing:NO];
     picture_Release (pic);
     sys->has_first_frame = true;
-       (void)subpicture;
+
+    if (subpicture)
+        subpicture_Delete(subpicture);
 }
 
 static int Control (vout_display_t *vd, int query, va_list ap)
@@ -288,44 +313,74 @@ static int Control (vout_display_t *vd, int query, va_list ap)
     switch (query)
     {
         case VOUT_DISPLAY_CHANGE_FULLSCREEN:
+        {
+            NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
+            [[sys->glView window] performSelectorOnMainThread:@selector(fullscreen:) withObject: nil waitUntilDone:NO];
+            [o_pool release];
+            return VLC_SUCCESS;
+        }
         case VOUT_DISPLAY_CHANGE_WINDOW_STATE:
         {
-            /* todo */
-            return VLC_EGENERIC;
+            NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
+            unsigned state = va_arg (ap, unsigned);
+            [sys->glView performSelectorOnMainThread:@selector(setWindowLevel:) withObject:[NSNumber numberWithUnsignedInt:state] waitUntilDone:NO];
+            [o_pool release];
+            return VLC_SUCCESS;
         }
-        case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
         case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
+        {
+            [[sys->glView window] performSelectorOnMainThread:@selector(performZoom:) withObject: nil waitUntilDone:NO];
+            return VLC_SUCCESS;
+        }
         case VOUT_DISPLAY_CHANGE_ZOOM:
         case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
         case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
+            return VLC_SUCCESS;
+        case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
         {
+            // is needed in the case we do not an actual resize
+            [sys->glView performSelectorOnMainThread:@selector(reshapeView:) withObject:nil waitUntilDone:NO];
+
+            if (!config_GetInt( vd, "macosx-video-autoresize" ))
+                return VLC_SUCCESS;
+
+            NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
             NSPoint topleftbase;
             NSPoint topleftscreen;
             NSRect new_frame;
             const vout_display_cfg_t *cfg;
+
+            id o_window = [sys->glView window];
+            if (!o_window)
+                return VLC_SUCCESS; // this is okay, since the event will occur again when we have a window
+            NSRect windowFrame = [o_window frame];
+            NSRect glViewFrame = [sys->glView frame];
+            NSSize windowMinSize = [o_window minSize];
+
             topleftbase.x = 0;
-            topleftbase.y = [[sys->glView window] frame].size.height;
-            topleftscreen = [[sys->glView window] convertBaseToScreen: topleftbase];
+            topleftbase.y = windowFrame.size.height;
+            topleftscreen = [o_window convertBaseToScreen: topleftbase];
             cfg = (const vout_display_cfg_t*)va_arg (ap, const vout_display_cfg_t *);
             int i_width = cfg->display.width;
             int i_height = cfg->display.height;
 
             /* Calculate the window's new size, if it is larger than our minimal size */
-            if (i_width < [[sys->glView window] minSize].width)
-                i_width = [[sys->glView window] minSize].width;
-            if (i_height < [[sys->glView window] minSize].height)
-                i_height = [[sys->glView window] minSize].height;
+            if (i_width < windowMinSize.width)
+                i_width = windowMinSize.width;
+            if (i_height < windowMinSize.height)
+                i_height = windowMinSize.height;
 
-            if( i_height != [sys->glView frame].size.height || i_width != [sys->glView frame].size.width )
+            if( i_height != glViewFrame.size.height || i_width != glViewFrame.size.width )
             {
-                new_frame.size.width = [[sys->glView window] frame].size.width - [sys->glView frame].size.width + i_width;
-                new_frame.size.height = [[sys->glView window] frame].size.height - [sys->glView frame].size.height + i_height;
+                new_frame.size.width = windowFrame.size.width - glViewFrame.size.width + i_width;
+                new_frame.size.height = windowFrame.size.height - glViewFrame.size.height + i_height;
 
                 new_frame.origin.x = topleftscreen.x;
                 new_frame.origin.y = topleftscreen.y - new_frame.size.height;
 
-                [[sys->glView window] setFrame:new_frame display:YES animate:YES];
+                [sys->glView performSelectorOnMainThread:@selector(setWindowFrameWithValue:) withObject:[NSValue valueWithRect:new_frame] waitUntilDone:NO];
             }
+            [o_pool release];
             return VLC_SUCCESS;
         }
 
@@ -441,6 +496,20 @@ static void OpenglSwap(vlc_gl_t *gl)
     [self setFrame:[value rectValue]];
 }
 
+/**
+ * Gets called by Control() to make sure that we're performing on the main thread
+ */
+- (void)setWindowFrameWithValue:(NSValue *)value
+{
+    if (![[self window] isFullscreen])
+    {
+        NSRect frame = [value rectValue];
+        if (frame.origin.x <= 0.0 && frame.origin.y <= 0.0)
+            [[self window] center];
+        [[self window] setFrame:frame display:YES animate: YES];
+    }
+}
+
 /**
  * Gets called by the Close and Open methods.
  * (Non main thread).
@@ -452,6 +521,10 @@ static void OpenglSwap(vlc_gl_t *gl)
     }
 }
 
+- (vout_display_t *)voutDisplay
+{
+    return vd;
+}
 
 /**
  * Gets called when the vout will aquire the lock and flush.
@@ -528,6 +601,11 @@ static void OpenglSwap(vlc_gl_t *gl)
         glClear(GL_COLOR_BUFFER_BIT);
 }
 
+- (void)reshapeView:(id)sender
+{
+    [self reshape];
+}
+
 /**
  * Method called by Cocoa when the view is resized.
  */
@@ -620,8 +698,8 @@ static void OpenglSwap(vlc_gl_t *gl)
     NSWindow *window = [self window];
 
     // Remove flashes with splitter view.
-       if ([window respondsToSelector:@selector(disableScreenUpdatesUntilFlush)])
-               [window disableScreenUpdatesUntilFlush];
+    if ([window respondsToSelector:@selector(disableScreenUpdatesUntilFlush)])
+        [window disableScreenUpdatesUntilFlush];
 
     [super renewGState];
 }
@@ -635,4 +713,12 @@ static void OpenglSwap(vlc_gl_t *gl)
 {
     return YES;
 }
+
+- (void)setWindowLevel:(NSNumber*)state
+{
+    if( [state unsignedIntValue] & VOUT_WINDOW_STATE_ABOVE )
+        [[self window] setLevel: NSStatusWindowLevel];
+    else
+        [[self window] setLevel: NSNormalWindowLevel];
+}
 @end