X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_output%2Fmacosx.m;h=5fa24a7d0e101ae278fbea7bb76dfa2e6add44d5;hb=2c613666ad3fd4fbadc6e177a044cd2c94cf0e80;hp=e278113b5f90526c9ba371c31ea9097adfbd7f07;hpb=2f9de9352d04f834e585aa2f20716735f0fa4f7c;p=vlc diff --git a/modules/video_output/macosx.m b/modules/video_output/macosx.m index e278113b5f..5fa24a7d0e 100644 --- a/modules/video_output/macosx.m +++ b/modules/video_output/macosx.m @@ -1,32 +1,33 @@ /***************************************************************************** * macosx.m: MacOS X OpenGL provider ***************************************************************************** - * Copyright (C) 2001-2012 the VideoLAN team + * Copyright (C) 2001-2013 VLC authors and VideoLAN * $Id$ * - * Authors: Colin Delacroix - * Florian G. Pflug - * Jon Lech Johansen - * Derk-Jan Hartman + * Authors: Derk-Jan Hartman * Eric Petit * Benjamin Pracht * Damien Fouilleul * Pierre d'Herbemont * Felix Paul Kühne + * David Fuhrmann + * Rémi Denis-Courmont + * Juho Vähä-Herttua + * Laurent Aimar * - * 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 - * the Free Software Foundation; either version 2 of the License, or + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program 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. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** @@ -35,6 +36,7 @@ #import #import +#import #ifdef HAVE_CONFIG_H # include "config.h" @@ -47,38 +49,47 @@ #include #include "opengl.h" -@interface NSWindow (VLCCustomCode) -- (BOOL)isFullscreen; +/* compilation support for 10.5 and 10.6 */ +#define OSX_LION NSAppKitVersionNumber >= 1115.2 +#ifndef MAC_OS_X_VERSION_10_7 + +@interface NSView (IntroducedInLion) +- (NSRect)convertRectToBacking:(NSRect)aRect; +- (void)setWantsBestResolutionOpenGLSurface:(BOOL)aBool; @end +#endif + /** * Forward declarations */ -static int Open(vlc_object_t *); -static void Close(vlc_object_t *); +static int Open (vlc_object_t *); +static void Close (vlc_object_t *); -static picture_pool_t *Pool(vout_display_t *vd, unsigned requested_count); -static void PictureRender(vout_display_t *vd, picture_t *pic, subpicture_t *subpicture); -static void PictureDisplay(vout_display_t *vd, picture_t *pic, subpicture_t *subpicture); +static picture_pool_t *Pool (vout_display_t *vd, unsigned requested_count); +static void PictureRender (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture); +static void PictureDisplay (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture); static int Control (vout_display_t *vd, int query, va_list ap); -static int OpenglLock(vlc_gl_t *gl); -static void OpenglUnlock(vlc_gl_t *gl); -static void OpenglSwap(vlc_gl_t *gl); +static void *OurGetProcAddress(vlc_gl_t *, const char *); + +static int OpenglLock (vlc_gl_t *gl); +static void OpenglUnlock (vlc_gl_t *gl); +static void OpenglSwap (vlc_gl_t *gl); /** * Module declaration */ vlc_module_begin () /* Will be loaded even without interface module. see voutgl.m */ - set_shortname("Mac OS X") - set_description( N_("Mac OS X OpenGL video output (requires drawable-nsobject)")) - set_category(CAT_VIDEO) - set_subcategory(SUBCAT_VIDEO_VOUT ) - set_capability("vout display", 300) - set_callbacks(Open, Close) - - add_shortcut("macosx", "vout_macosx") + set_shortname ("Mac OS X") + set_description (N_("Mac OS X OpenGL video output (requires drawable-nsobject)")) + set_category (CAT_VIDEO) + set_subcategory (SUBCAT_VIDEO_VOUT) + set_capability ("vout display", 300) + set_callbacks (Open, Close) + + add_shortcut ("macosx", "vout_macosx") vlc_module_end () /** @@ -95,7 +106,6 @@ vlc_module_end () BOOL _hasPendingReshape; } - (void)setVoutDisplay:(vout_display_t *)vd; -- (vout_display_t *)voutDisplay; - (void)setVoutFlushing:(BOOL)flushing; @end @@ -112,24 +122,32 @@ struct vout_display_sys_t picture_pool_t *pool; picture_t *current; bool has_first_frame; + + vout_display_place_t place; }; -static int Open(vlc_object_t *this) + +static void *OurGetProcAddress(vlc_gl_t *gl, const char *name) +{ + VLC_UNUSED(gl); + + return dlsym(RTLD_DEFAULT, name); +} + +static int Open (vlc_object_t *this) { vout_display_t *vd = (vout_display_t *)this; - vout_display_sys_t *sys = calloc(1, sizeof(*sys)); + vout_display_sys_t *sys = calloc (1, sizeof(*sys)); NSAutoreleasePool *nsPool = nil; if (!sys) return VLC_ENOMEM; - if( !CGDisplayUsesOpenGLAcceleration( kCGDirectMainDisplay ) ) - { - msg_Err( this, "no OpenGL hardware acceleration found. this can lead to slow output and unexpected results" ); - dialog_Fatal( this, _("OpenGL acceleration is not supported on your Mac"), _("Your Mac lacks Quartz Extreme acceleration, which is required for video output. It will still work, but much slower and with possibly unexpected results.") ); - } - else - msg_Dbg( this, "Quartz Extreme acceleration is active" ); + if (!CGDisplayUsesOpenGLAcceleration (kCGDirectMainDisplay)) { + msg_Err (this, "no OpenGL hardware acceleration found. this can lead to slow output and unexpected results"); + dialog_Fatal (this, _("OpenGL acceleration is not supported on your Mac"), _("Your Mac lacks Quartz Extreme acceleration, which is required for video output. It will still work, but much slower and with possibly unexpected results.")); + } else + msg_Dbg (this, "Quartz Extreme acceleration is active"); vd->sys = sys; sys->pool = NULL; @@ -137,13 +155,10 @@ static int Open(vlc_object_t *this) sys->embed = NULL; /* Get the drawable object */ - id container = var_CreateGetAddress(vd, "drawable-nsobject"); + id container = var_CreateGetAddress (vd, "drawable-nsobject"); if (container) - { - vout_display_DeleteWindow(vd, NULL); - } - else - { + vout_display_DeleteWindow (vd, NULL); + else { vout_window_cfg_t wnd_cfg; memset (&wnd_cfg, 0, sizeof (wnd_cfg)); @@ -157,8 +172,7 @@ static int Open(vlc_object_t *this) if (sys->embed) container = sys->embed->handle.nsobject; - if (!container) - { + if (!container) { msg_Dbg(vd, "No drawable-nsobject nor vout_window_t found, passing over."); goto error; } @@ -182,14 +196,11 @@ static int Open(vlc_object_t *this) * That's why we'll release on main thread in Close(). */ if ([(id)container respondsToSelector:@selector(addVoutSubview:)]) [(id)container performSelectorOnMainThread:@selector(addVoutSubview:) withObject:sys->glView waitUntilDone:NO]; - else if ([container isKindOfClass:[NSView class]]) - { + else if ([container isKindOfClass:[NSView class]]) { NSView *parentView = container; [parentView performSelectorOnMainThread:@selector(addSubview:) withObject:sys->glView waitUntilDone:NO]; - [sys->glView performSelectorOnMainThread:@selector(setFrameWithValue:) withObject:[NSValue valueWithRect:[parentView bounds]] waitUntilDone:NO]; - } - else - { + [sys->glView performSelectorOnMainThread:@selector(setFrameToBoundsOfView:) withObject:[NSValue valueWithPointer:parentView] waitUntilDone:NO]; + } else { msg_Err(vd, "Invalid drawable-nsobject object. drawable-nsobject must either be an NSView or comply to the @protocol VLCOpenGLVideoViewEmbedding."); goto error; } @@ -202,14 +213,13 @@ static int Open(vlc_object_t *this) sys->gl.lock = OpenglLock; sys->gl.unlock = OpenglUnlock; sys->gl.swap = OpenglSwap; - sys->gl.getProcAddress = NULL; + sys->gl.getProcAddress = OurGetProcAddress; sys->gl.sys = sys; const vlc_fourcc_t *subpicture_chromas; video_format_t fmt = vd->fmt; - sys->vgl = vout_display_opengl_New(&vd->fmt, &subpicture_chromas, &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; } @@ -219,6 +229,7 @@ static int Open(vlc_object_t *this) info.has_pictures_invalid = false; info.has_event_thread = true; info.subpicture_chromas = subpicture_chromas; + info.has_hide_mouse = true; /* Setup vout_display_t once everything is fine */ vd->info = info; @@ -229,7 +240,6 @@ static int Open(vlc_object_t *this) vd->control = Control; /* */ - vout_display_SendEventFullscreen (vd, false); vout_display_SendEventDisplaySize (vd, vd->source.i_visible_width, vd->source.i_visible_height, false); return VLC_SUCCESS; @@ -240,33 +250,29 @@ error: return VLC_EGENERIC; } -void Close(vlc_object_t *this) +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"); + var_Destroy (vd, "drawable-nsobject"); if ([(id)sys->container respondsToSelector:@selector(removeVoutSubview:)]) - { /* This will retain sys->glView */ [(id)sys->container performSelectorOnMainThread:@selector(removeVoutSubview:) withObject:sys->glView waitUntilDone:NO]; - } + /* release on main thread as explained in Open() */ [(id)sys->container performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO]; [sys->glView performSelectorOnMainThread:@selector(removeFromSuperview) withObject:nil waitUntilDone:NO]; - [sys->glView release]; - if (sys->gl.sys != NULL) - vout_display_opengl_Delete(sys->vgl); + vout_display_opengl_Delete (sys->vgl); + + [sys->glView release]; if (sys->embed) - vout_display_DeleteWindow(vd, sys->embed); + vout_display_DeleteWindow (vd, sys->embed); free (sys); } @@ -274,7 +280,7 @@ void Close(vlc_object_t *this) * vout display callbacks *****************************************************************************/ -static picture_pool_t *Pool(vout_display_t *vd, unsigned requested_count) +static picture_pool_t *Pool (vout_display_t *vd, unsigned requested_count) { vout_display_sys_t *sys = vd->sys; @@ -284,19 +290,19 @@ static picture_pool_t *Pool(vout_display_t *vd, unsigned requested_count) return sys->pool; } -static void PictureRender(vout_display_t *vd, picture_t *pic, subpicture_t *subpicture) +static void PictureRender (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture) { vout_display_sys_t *sys = vd->sys; - vout_display_opengl_Prepare( sys->vgl, pic, subpicture ); + vout_display_opengl_Prepare (sys->vgl, pic, subpicture); } -static void PictureDisplay(vout_display_t *vd, picture_t *pic, subpicture_t *subpicture) +static void PictureDisplay (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture) { vout_display_sys_t *sys = vd->sys; [sys->glView setVoutFlushing:YES]; - vout_display_opengl_Display(sys->vgl, &vd->fmt ); + vout_display_opengl_Display (sys->vgl, &vd->source); [sys->glView setVoutFlushing:NO]; picture_Release (pic); sys->has_first_frame = true; @@ -321,11 +327,8 @@ static int Control (vout_display_t *vd, int query, va_list ap) } case VOUT_DISPLAY_CHANGE_WINDOW_STATE: { - 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; + return vout_window_SetState (sys->embed, state); } case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED: case VOUT_DISPLAY_CHANGE_ZOOM: @@ -343,22 +346,15 @@ static int Control (vout_display_t *vd, int query, va_list ap) return VLC_SUCCESS; // this is okay, since the event will occur again when we have a window NSSize windowMinSize = [o_window minSize]; - int i_width = 0; - int i_height = 0; const vout_display_cfg_t *cfg; const video_format_t *source; bool is_forced = false; - vout_display_place_t place; - - if (query == VOUT_DISPLAY_CHANGE_SOURCE_ASPECT || query == VOUT_DISPLAY_CHANGE_SOURCE_CROP) - { + if (query == VOUT_DISPLAY_CHANGE_SOURCE_ASPECT || query == VOUT_DISPLAY_CHANGE_SOURCE_CROP) { source = (const video_format_t *)va_arg (ap, const video_format_t *); cfg = vd->cfg; - } - else - { + } else { source = &vd->source; cfg = (const vout_display_cfg_t*)va_arg (ap, const vout_display_cfg_t *); if (query == VOUT_DISPLAY_CHANGE_DISPLAY_SIZE) @@ -371,55 +367,30 @@ static int Control (vout_display_t *vd, int query, va_list ap) && vout_window_SetSize (sys->embed, cfg->display.width, cfg->display.height)) return VLC_EGENERIC; - /* for the case that the core wants to resize below minimum window size we correct the size here - to ensure a centered picture */ + /* we always use our current frame here, because we have some size constraints + in the ui vout provider */ vout_display_cfg_t cfg_tmp = *cfg; - if (cfg_tmp.display.width < windowMinSize.width) - cfg_tmp.display.width = windowMinSize.width; - if (cfg_tmp.display.height < windowMinSize.height) - cfg_tmp.display.height = windowMinSize.height; + NSRect bounds; + /* on HiDPI displays, the point bounds don't equal the actual pixel based bounds */ + if (OSX_LION) + bounds = [sys->glView convertRectToBacking:[sys->glView bounds]]; + else + bounds = [sys->glView bounds]; + cfg_tmp.display.width = bounds.size.width; + cfg_tmp.display.height = bounds.size.height; + vout_display_place_t place; vout_display_PlacePicture (&place, source, &cfg_tmp, false); - - if (query == VOUT_DISPLAY_CHANGE_SOURCE_CROP || query == VOUT_DISPLAY_CHANGE_SOURCE_ASPECT) - { - vd->fmt.i_width = vd->source.i_width * place.width / vd->source.i_visible_width; - vd->fmt.i_height = vd->source.i_height * place.height / vd->source.i_visible_height; - vd->fmt.i_visible_width = vd->source.i_visible_width; - vd->fmt.i_visible_height = vd->source.i_visible_height; - vd->fmt.i_x_offset = vd->source.i_x_offset * place.width / vd->source.i_visible_width; - vd->fmt.i_y_offset = vd->source.i_y_offset * place.height / vd->source.i_visible_height; - - if (vd->fmt.i_x_offset > 0) - { - if (vd->source.i_width / vd->fmt.i_x_offset <= 4) - { - /* hack and special case for the "Default" state - * The 'Default' state tries to set the dimensions with a huge x offset and a weird - * width / height ratio, which definitely isn't the default for the played media. - * That's why, we enforce the media's actual dimensions here. - * The quotient of 4 is a stochastic value, which isn't reached by any other crop state. */ - vd->fmt.i_width = vd->source.i_width; - vd->fmt.i_height = vd->source.i_height; - vd->fmt.i_visible_width = vd->source.i_width; - vd->fmt.i_visible_height = vd->source.i_height; - vd->fmt.i_x_offset = 0; - vd->fmt.i_y_offset = 0; - } - } + @synchronized (sys->glView) { + sys->place = place; } /* For resize, we call glViewport in reshape and not here. This has the positive side effect that we avoid erratic sizing as we animate every resize. */ if (query != VOUT_DISPLAY_CHANGE_DISPLAY_SIZE) - { // x / y are top left corner, but we need the lower left one glViewport (place.x, cfg_tmp.display.height - (place.y + place.height), place.width, place.height); - } - // this should not be needed, but currently it improves crop somehow, when we are in fullscreen - if (query == VOUT_DISPLAY_CHANGE_SOURCE_CROP) - [sys->glView performSelectorOnMainThread:@selector(reshapeView:) withObject:nil waitUntilDone:NO]; [o_pool release]; return VLC_SUCCESS; @@ -449,26 +420,28 @@ static int Control (vout_display_t *vd, int query, va_list ap) /***************************************************************************** * vout opengl callbacks *****************************************************************************/ -static int OpenglLock(vlc_gl_t *gl) +static int OpenglLock (vlc_gl_t *gl) { vout_display_sys_t *sys = (vout_display_sys_t *)gl->sys; + if (!sys->glView || ![sys->glView respondsToSelector:@selector(openGLContext)]) + return 1; + NSOpenGLContext *context = [sys->glView openGLContext]; - CGLError err = CGLLockContext([context CGLContextObj]); - if (kCGLNoError == err) - { + CGLError err = CGLLockContext ([context CGLContextObj]); + if (kCGLNoError == err) { [context makeCurrentContext]; return 0; } return 1; } -static void OpenglUnlock(vlc_gl_t *gl) +static void OpenglUnlock (vlc_gl_t *gl) { vout_display_sys_t *sys = (vout_display_sys_t *)gl->sys; - CGLUnlockContext([[sys->glView openGLContext] CGLContextObj]); + CGLUnlockContext ([[sys->glView openGLContext] CGLContextObj]); } -static void OpenglSwap(vlc_gl_t *gl) +static void OpenglSwap (vlc_gl_t *gl) { vout_display_sys_t *sys = (vout_display_sys_t *)gl->sys; [[sys->glView openGLContext] flushBuffer]; @@ -520,22 +493,42 @@ static void OpenglSwap(vlc_gl_t *gl) if (!self) return nil; + /* enable HiDPI support on OS X 10.7 and later */ + if (OSX_LION) + [self setWantsBestResolutionOpenGLSurface:YES]; + /* Swap buffers only during the vertical retrace of the monitor. http://developer.apple.com/documentation/GraphicsImaging/ Conceptual/OpenGL/chap5/chapter_5_section_44.html */ GLint params[] = { 1 }; - CGLSetParameter([[self openGLContext] CGLContextObj], kCGLCPSwapInterval, params); + CGLSetParameter ([[self openGLContext] CGLContextObj], kCGLCPSwapInterval, params); + + [[NSNotificationCenter defaultCenter] addObserverForName:NSApplicationDidChangeScreenParametersNotification + object:[NSApplication sharedApplication] + queue:nil + usingBlock:^(NSNotification *notification) { + [self performSelectorOnMainThread:@selector(reshape) + withObject:nil + waitUntilDone:NO]; + }]; [self setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; return self; } +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [super dealloc]; +} + /** * Gets called by the Open() method. */ -- (void)setFrameWithValue:(NSValue *)value +- (void)setFrameToBoundsOfView:(NSValue *)value { - [self setFrame:[value rectValue]]; + NSView *parentView = [value pointerValue]; + [self setFrame:[parentView bounds]]; } /** @@ -549,11 +542,6 @@ static void OpenglSwap(vlc_gl_t *gl) } } -- (vout_display_t *)voutDisplay -{ - return vd; -} - /** * Gets called when the vout will aquire the lock and flush. * (Non main thread). @@ -588,7 +576,7 @@ static void OpenglSwap(vlc_gl_t *gl) { VLCAssertMainThread(); NSOpenGLContext *context = [self openGLContext]; - CGLError err = CGLLockContext([context CGLContextObj]); + CGLError err = CGLLockContext ([context CGLContextObj]); if (err == kCGLNoError) [context makeCurrentContext]; return err == kCGLNoError; @@ -600,7 +588,7 @@ static void OpenglSwap(vlc_gl_t *gl) - (void)unlockgl { VLCAssertMainThread(); - CGLUnlockContext([[self openGLContext] CGLContextObj]); + CGLUnlockContext ([[self openGLContext] CGLContextObj]); } /** @@ -621,17 +609,11 @@ static void OpenglSwap(vlc_gl_t *gl) hasFirstFrame = vd && vd->sys->has_first_frame; } - if (hasFirstFrame) { + if (hasFirstFrame) // This will lock gl. - vout_display_opengl_Display( vd->sys->vgl, &vd->source ); - } + vout_display_opengl_Display (vd->sys->vgl, &vd->source); else - glClear(GL_COLOR_BUFFER_BIT); -} - -- (void)reshapeView:(id)sender -{ - [self reshape]; + glClear (GL_COLOR_BUFFER_BIT); } /** @@ -641,9 +623,14 @@ static void OpenglSwap(vlc_gl_t *gl) { VLCAssertMainThread(); - NSRect bounds = [self bounds]; + NSRect bounds; + /* on HiDPI displays, the point bounds don't equal the actual pixel based bounds */ + if (OSX_LION) + bounds = [self convertRectToBacking:[self bounds]]; + else + bounds = [self bounds]; vout_display_place_t place; - + @synchronized(self) { if (vd) { vout_display_cfg_t cfg_tmp = *(vd->cfg); @@ -651,6 +638,7 @@ static void OpenglSwap(vlc_gl_t *gl) cfg_tmp.display.height = bounds.size.height; vout_display_PlacePicture (&place, &vd->source, &cfg_tmp, false); + vd->sys->place = place; vout_display_SendEventDisplaySize (vd, bounds.size.width, bounds.size.height, vd->cfg->is_fullscreen); } } @@ -719,21 +707,120 @@ static void OpenglSwap(vlc_gl_t *gl) [super renewGState]; } -- (BOOL)mouseDownCanMoveWindow +- (BOOL)isOpaque { return YES; } -- (BOOL)isOpaque +#pragma mark - +#pragma mark Mouse handling + +- (void)mouseDown:(NSEvent *)o_event { - return YES; + @synchronized (self) { + if (vd) { + if ([o_event type] == NSLeftMouseDown && !([o_event modifierFlags] & NSControlKeyMask)) { + if ([o_event clickCount] <= 1) + vout_display_SendEventMousePressed (vd, MOUSE_BUTTON_LEFT); + } + } + } + + [super mouseDown:o_event]; +} + +- (void)otherMouseDown:(NSEvent *)o_event +{ + @synchronized (self) { + if (vd) + vout_display_SendEventMousePressed (vd, MOUSE_BUTTON_CENTER); + } + + [super otherMouseDown: o_event]; +} + +- (void)mouseUp:(NSEvent *)o_event +{ + @synchronized (self) { + if (vd) { + if ([o_event type] == NSLeftMouseUp) + vout_display_SendEventMouseReleased (vd, MOUSE_BUTTON_LEFT); + } + } + + [super mouseUp: o_event]; +} + +- (void)otherMouseUp:(NSEvent *)o_event +{ + @synchronized (self) { + if (vd) + vout_display_SendEventMouseReleased (vd, MOUSE_BUTTON_CENTER); + } + + [super otherMouseUp: o_event]; } -- (void)setWindowLevel:(NSNumber*)state +- (void)mouseMoved:(NSEvent *)o_event { - if( [state unsignedIntValue] & VOUT_WINDOW_STATE_ABOVE ) - [[self window] setLevel: NSStatusWindowLevel]; + NSPoint ml; + NSRect s_rect; + BOOL b_inside; + + /* on HiDPI displays, the point bounds don't equal the actual pixel based bounds */ + if (OSX_LION) + s_rect = [self convertRectToBacking:[self bounds]]; else - [[self window] setLevel: NSNormalWindowLevel]; + s_rect = [self bounds]; + ml = [self convertPoint: [o_event locationInWindow] fromView: nil]; + b_inside = [self mouse: ml inRect: s_rect]; + + if (b_inside) { + @synchronized (self) { + if (vd) { + vout_display_place_t place = vd->sys->place; + + if (place.width > 0 && place.height > 0) { + const int x = vd->source.i_x_offset + + (int64_t)(ml.x - place.x) * vd->source.i_visible_width / place.width; + const int y = vd->source.i_y_offset + + (int64_t)((int)s_rect.size.height - (int)ml.y - place.y) * vd->source.i_visible_height / place.height; + + vout_display_SendEventMouseMoved (vd, x, y); + } + } + } + } + + [super mouseMoved: o_event]; +} + +- (void)mouseDragged:(NSEvent *)o_event +{ + [self mouseMoved: o_event]; + [super mouseDragged: o_event]; +} + +- (void)otherMouseDragged:(NSEvent *)o_event +{ + [self mouseMoved: o_event]; + [super otherMouseDragged: o_event]; +} + +- (void)rightMouseDragged:(NSEvent *)o_event +{ + [self mouseMoved: o_event]; + [super rightMouseDragged: o_event]; +} + +- (BOOL)acceptsFirstResponder +{ + return YES; } + +- (BOOL)mouseDownCanMoveWindow +{ + return YES; +} + @end