[vlc-commits] [Git][videolan/vlc][master] 9 commits: macosx: Delete callback for WindowFloatOnTop when removing vout for display
Steve Lhomme (@robUx4)
gitlab at videolan.org
Wed Jun 18 05:15:49 UTC 2025
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
71fe2203 by Claudio Cambra at 2025-06-18T05:01:08+00:00
macosx: Delete callback for WindowFloatOnTop when removing vout for display
Prevents a crash when vout is stopped and then started later
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
e1dfad10 by Claudio Cambra at 2025-06-18T05:01:08+00:00
macosx: Handle video playback appearance for library window via video output provider
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
0425c22f by Claudio Cambra at 2025-06-18T05:01:08+00:00
macosx: Port handling of end-of-playback view to all video windows
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
c1af1d50 by Claudio Cambra at 2025-06-18T05:01:08+00:00
macosx: Fix returnToLibrary behaviour when the main video view is assigned onto a non-library window video window
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
74a2a16b by Claudio Cambra at 2025-06-18T05:01:08+00:00
macosx: Extract video window's dismissal procedure to block variable, reuse for playback end view dismissal handling
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
5ae75479 by Claudio Cambra at 2025-06-18T05:01:08+00:00
macosx: Ensure animation context and full screen closing isn't started until end of playback view is dismissed
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
f9f441a3 by Claudio Cambra at 2025-06-18T05:01:08+00:00
macosx: Do not set fullscreen on window parent when setting up fullscreen
In native fullscreen mode, windowWillEnterFullscreen already does this
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
a009d7fe by Claudio Cambra at 2025-06-18T05:01:08+00:00
macosx: Apply fullscreen bool to vout thread within window class when using non-native fullscreen
Match behaviour to native fullscreen
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
a091acfd by Claudio Cambra at 2025-06-18T05:01:08+00:00
macosx: Use dispatch async to toggle fullscreen state for windows in video output provider
Avoids deadlocks when handling WindowEnable callback and setting of fullscreen variable on the windows' vout thread
Signed-off-by: Claudio Cambra <developer at claudiocambra.com>
- - - - -
5 changed files:
- modules/gui/macosx/library/VLCLibraryWindow.m
- modules/gui/macosx/windows/video/VLCMainVideoViewController.h
- modules/gui/macosx/windows/video/VLCMainVideoViewController.m
- modules/gui/macosx/windows/video/VLCVideoOutputProvider.m
- modules/gui/macosx/windows/video/VLCVideoWindowCommon.m
Changes:
=====================================
modules/gui/macosx/library/VLCLibraryWindow.m
=====================================
@@ -412,34 +412,6 @@ static void addShadow(NSImageView *__unsafe_unretained imageView)
#pragma mark - video output controlling
-- (void)setHasActiveVideo:(BOOL)hasActiveVideo
-{
- [super setHasActiveVideo:hasActiveVideo];
- if (hasActiveVideo) {
- [self enableVideoPlaybackAppearance];
- } else if (!self.videoViewController.view.hidden) {
- // If we are switching to audio media then keep the active main video view open
- NSURL * const currentMediaUrl = _playQueueController.playerController.URLOfCurrentMediaItem;
- VLCMediaLibraryMediaItem * const mediaItem = [VLCMediaLibraryMediaItem mediaItemForURL:currentMediaUrl];
- const BOOL decorativeViewVisible = mediaItem != nil && mediaItem.mediaType == VLC_ML_MEDIA_TYPE_AUDIO;
-
- // If the playback end view is enabled and the player is stopped, display playback end view.
- // We want to still display the decorative view for audio items.
- // In other cases, we need to check that the player itself is in a stopped state. Removal of
- // the active video can be triggered by more than just end of playback (e.g. disabling the
- // video track).
- if (!decorativeViewVisible &&
- [NSUserDefaults.standardUserDefaults boolForKey:VLCPlaybackEndViewEnabledKey] &&
- self.playerController.playerState == VLC_PLAYER_STATE_STOPPED) {
- [self.videoViewController displayPlaybackEndView];
- } else if (!decorativeViewVisible) {
- [self disableVideoPlaybackAppearance];
- }
- } else {
- [self disableVideoPlaybackAppearance];
- }
-}
-
- (void)playerStateChanged:(NSNotification *)notification
{
if (_playQueueController.playerController.playerState == VLC_PLAYER_STATE_STOPPED) {
=====================================
modules/gui/macosx/windows/video/VLCMainVideoViewController.h
=====================================
@@ -66,6 +66,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (readonly) BOOL pipIsActive;
@property (readonly) VLCPlaybackEndViewController *playbackEndViewController;
+ at property (readwrite) void (^endViewDismissHandler)(void);
- (void)showControls;
- (void)hideControls;
=====================================
modules/gui/macosx/windows/video/VLCMainVideoViewController.m
=====================================
@@ -557,9 +557,10 @@
[self.playbackEndViewController.countdownTimer invalidate];
[self.playbackEndViewController.view removeFromSuperview];
}
- VLCLibraryWindow *libraryWindow = (VLCLibraryWindow*)self.view.window;
- if (libraryWindow != nil) {
- [libraryWindow disableVideoPlaybackAppearance];
+ if (self.view.window.class == VLCLibraryWindow.class) {
+ [(VLCLibraryWindow *)self.view.window disableVideoPlaybackAppearance];
+ } else {
+ [self.view.window close];
}
}
@@ -607,12 +608,17 @@
- (void)playbackEndViewReturnToLibrary:(NSNotification *)notification
{
- [self returnToLibrary:self];
+ if (self.endViewDismissHandler)
+ self.endViewDismissHandler();
+ else
+ [self returnToLibrary:self];
}
- (void)playbackEndViewHide:(NSNotification *)notification
{
[self.playbackEndViewController.view removeFromSuperview];
+ if (self.endViewDismissHandler)
+ self.endViewDismissHandler();
}
#pragma mark - PIPViewControllerDelegate
=====================================
modules/gui/macosx/windows/video/VLCVideoOutputProvider.m
=====================================
@@ -25,6 +25,7 @@
#import "extensions/NSScreen+VLCAdditions.h"
+#import "library/VLCLibraryDataTypes.h"
#import "library/VLCLibraryWindow.h"
#import "main/CompatibilityFixes.h"
@@ -40,6 +41,8 @@
#import "playqueue/VLCPlayQueueController.h"
#import "playqueue/VLCPlayerController.h"
+#import "views/VLCPlaybackEndViewController.h"
+
#import "windows/video/VLCAspectRatioRetainingVideoWindow.h"
#import "windows/video/VLCMainVideoViewController.h"
#import "windows/video/VLCVoutView.h"
@@ -423,6 +426,8 @@ static int WindowFloatOnTop(vlc_object_t *obj,
voutView.voutThread = p_vout;
voutView.voutWindow = p_wnd;
videoWindow.hasActiveVideo = YES;
+ if (videoWindow.class == VLCLibraryWindow.class)
+ [(VLCLibraryWindow *)videoWindow enableVideoPlaybackAppearance];
_playerController.activeVideoPlayback = YES;
VLCMain.sharedInstance.libraryWindow.nonembedded = !b_mainWindowHasVideo;
}
@@ -443,7 +448,6 @@ static int WindowFloatOnTop(vlc_object_t *obj,
if (!videoWallpaper && !b_have_splitter && (var_InheritBool(getIntf(), "fullscreen") || _playerController.fullscreen)) {
// this is not set when we start in fullscreen because of
// fullscreen settings in video prefs the second time
- var_SetBool(vlc_object_parent(p_wnd), "fullscreen", 1);
[self setFullscreen:1 forWindow:p_wnd withAnimation:NO];
}
}
@@ -474,41 +478,92 @@ static int WindowFloatOnTop(vlc_object_t *obj,
- (void)removeVoutForDisplay:(NSValue *)key
{
- VLCMain *mainInstance = VLCMain.sharedInstance;
- VLCVideoWindowCommon *videoWindow = [_voutWindows objectForKey:key];
+ VLCVideoWindowCommon * const videoWindow = [_voutWindows objectForKey:key];
if (!videoWindow) {
msg_Err(getIntf(), "Cannot close nonexisting window");
return;
}
+ vlc_window_t * const p_wnd = (vlc_window_t *)key.pointerValue;
+ if (p_wnd) {
+ vout_thread_t * const p_vout = (vout_thread_t *)vlc_object_parent(p_wnd);
+ if (p_vout) {
+ var_DelCallback(p_vout, "video-on-top", WindowFloatOnTop, (__bridge void *)videoWindow);
+ } else {
+ msg_Warn(getIntf(),
+ "Could not get p_vout to unregister WindowFloatOnTop callback for window %p",
+ p_wnd);
+ }
+ } else {
+ msg_Warn(getIntf(), "Could not get p_wnd from key to unregister WindowFloatOnTop callback");
+ }
+
[videoWindow.videoViewController.voutView releaseVoutThread];
// set active video to no BEFORE closing the window and exiting fullscreen
// (avoid stopping playback due to NSWindowWillCloseNotification, preserving fullscreen state)
- [videoWindow setHasActiveVideo: NO];
+ videoWindow.hasActiveVideo = NO;
+
+ // do not close the window if we have the decorative view for audio visible
+ // or if we have enabled end-of-playback screens.
+ NSURL * const currentMediaUrl = _playerController.URLOfCurrentMediaItem;
+ VLCMediaLibraryMediaItem * const mediaItem =
+ [VLCMediaLibraryMediaItem mediaItemForURL:currentMediaUrl];
+ const BOOL decorativeViewVisible =
+ mediaItem != nil && mediaItem.mediaType == VLC_ML_MEDIA_TYPE_AUDIO;
+ const BOOL endOfPlaybackScreenEnabled =
+ [NSUserDefaults.standardUserDefaults boolForKey:VLCPlaybackEndViewEnabledKey];
+
+ // we need to check that the player itself is in a stopped state. Removal of the active video
+ // can be triggered by more than just end of playback (e.g. disabling the video track).
+ if (!decorativeViewVisible
+ && endOfPlaybackScreenEnabled
+ && _playerController.playerState == VLC_PLAYER_STATE_STOPPED) {
+ [videoWindow.videoViewController displayPlaybackEndView];
+ videoWindow.videoViewController.endViewDismissHandler = ^{
+ [self handleVideoCloseForDisplay:key];
+ };
+ } else if (!decorativeViewVisible) {
+ [self handleVideoCloseForDisplay:key];
+ }
+}
+
+- (void)handleVideoCloseForDisplay:(NSValue *)key
+{
+ VLCVideoWindowCommon * const videoWindow = [_voutWindows objectForKey:key];
+ if (!videoWindow) {
+ msg_Err(getIntf(), "Cannot handle close for nonexistent window");
+ return;
+ }
// prevent visible extra window if in fullscreen
[NSAnimationContext beginGrouping];
- BOOL b_native = var_InheritBool(getIntf(), "macosx-nativefullscreenmode");
+ const BOOL b_native = var_InheritBool(getIntf(), "macosx-nativefullscreenmode");
// close fullscreen, without changing fullscreen vars
- if (!b_native && ([videoWindow fullscreen] || [videoWindow inFullscreenTransition]))
+ if (!b_native && (videoWindow.fullscreen || videoWindow.inFullscreenTransition))
[videoWindow leaveFullscreenWithAnimation:NO];
// native fullscreen window will not be closed if
// fullscreen was triggered without video
- if ((b_native && [videoWindow class] == [VLCLibraryWindow class] && [videoWindow fullscreen] && [videoWindow windowShouldExitFullscreenWhenFinished])) {
+ if (b_native
+ && videoWindow.class == VLCLibraryWindow.class
+ && videoWindow.fullscreen
+ && videoWindow.windowShouldExitFullscreenWhenFinished) {
[videoWindow toggleFullScreen:self];
}
- if ([videoWindow class] != [VLCLibraryWindow class]) {
+ if (videoWindow.class == VLCLibraryWindow.class
+ && !videoWindow.videoViewController.view.hidden) {
+ [(VLCLibraryWindow *)videoWindow disableVideoPlaybackAppearance];
+ } else {
[videoWindow close];
}
[NSAnimationContext endGrouping];
[_voutWindows removeObjectForKey:key];
- if ([_voutWindows count] == 0) {
- [_playerController setActiveVideoPlayback:NO];
+ if (_voutWindows.count == 0) {
+ _playerController.activeVideoPlayback = NO;
_statusLevelWindowCounter = 0;
}
@@ -516,12 +571,11 @@ static int WindowFloatOnTop(vlc_object_t *obj,
b_mainWindowHasVideo = NO;
// video in main window might get stopped while another vout is open
- if ([_voutWindows count] > 0)
- [[mainInstance libraryWindow] setNonembedded:YES];
+ if (_voutWindows.count > 0)
+ VLCMain.sharedInstance.libraryWindow.nonembedded = YES;
}
}
-
- (void)setNativeVideoSize:(NSSize)size forWindow:(vlc_window_t *)p_wnd
{
VLCVideoWindowCommon *o_window = [_voutWindows objectForKey:[NSValue valueWithPointer:p_wnd]];
@@ -603,7 +657,9 @@ static int WindowFloatOnTop(vlc_object_t *obj,
if((b_fullscreen && !([o_current_window fullscreen] || [o_current_window inFullscreenTransition])) ||
(!b_fullscreen && [o_current_window fullscreen])) {
- [o_current_window toggleFullScreen:self];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [o_current_window toggleFullScreen:self];
+ });
}
} else {
assert(o_current_window);
@@ -612,11 +668,15 @@ static int WindowFloatOnTop(vlc_object_t *obj,
if (_playerController.playerState != VLC_PLAYER_STATE_STOPPED && [_playerController activeVideoPlayback]) {
// activate app, as method can also be triggered from outside the app (prevents nasty window layout)
[NSApp activateIgnoringOtherApps:YES];
- [o_current_window enterFullscreenWithAnimation:b_animation];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [o_current_window enterFullscreenWithAnimation:b_animation];
+ });
}
} else {
// leaving fullscreen is always allowed
- [o_current_window leaveFullscreenWithAnimation:YES];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [o_current_window leaveFullscreenWithAnimation:YES];
+ });
}
}
}
=====================================
modules/gui/macosx/windows/video/VLCVideoWindowCommon.m
=====================================
@@ -492,6 +492,15 @@ NSString *VLCWindowShouldShowController = @"VLCWindowShouldShowController";
[self orderOut: self];
_inFullscreenTransition = NO;
+
+ if ([self hasActiveVideo]) {
+ vout_thread_t *p_vout = [_playerController videoOutputThreadForKeyWindow];
+ if (p_vout) {
+ var_SetBool(p_vout, "fullscreen", true);
+ vout_Release(p_vout);
+ }
+ }
+
[self setFullscreen:YES];
}
@@ -618,6 +627,14 @@ NSString *VLCWindowShouldShowController = @"VLCWindowShouldShowController";
[self setLevel:i_originalLevel];
[self setAlphaValue: config_GetFloat("macosx-opaqueness")];
+
+ if ([self hasActiveVideo]) {
+ vout_thread_t *p_vout = [_playerController videoOutputThreadForKeyWindow];
+ if (p_vout) {
+ var_SetBool(p_vout, "fullscreen", false);
+ vout_Release(p_vout);
+ }
+ }
}
- (void)animationDidEnd:(NSAnimation*)animation
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/bf1ef7069fd472b553712e4121e7468ffab595d4...a091acfd81056502faee103023b53261dd05865b
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/bf1ef7069fd472b553712e4121e7468ffab595d4...a091acfd81056502faee103023b53261dd05865b
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list