Skip to content

Commit

Permalink
Fix black window after exiting PiP, #4268
Browse files Browse the repository at this point in the history
This commit will:
- Add a VideoPIPViewController class that extends PIPViewController
- This class will force drawing when entering and exiting PiP
- Change MainWindowController to use VideoPIPViewController for the PiP
  controller
- Remove the pendingRedrawsAfterEnteringPIP property from VideoView
- Remove the layout method from VideoView
- Remove code that set pendingRedrawsAfterEnteringPIP from the
  MainWindowController.enterPIP method
  • Loading branch information
low-batt committed Mar 30, 2023
1 parent c0da90f commit 0ece322
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 22 deletions.
4 changes: 4 additions & 0 deletions iina.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
513A4FFA29B53F8100A8EA7D /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 513A4FF929B53F8100A8EA7D /* Atomic.swift */; };
519872FF26879B9B00F84BCC /* AccessibilityPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519872FE26879B9B00F84BCC /* AccessibilityPreferences.swift */; };
51C1BA3A291CA76700C1208A /* InfoDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51C1BA39291CA76700C1208A /* InfoDictionary.swift */; };
51CACB9529D500290034CEE5 /* VideoPIPViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51CACB9429D500290034CEE5 /* VideoPIPViewController.swift */; };
51F7974728C7E00200812D0D /* Lock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F7974628C7E00200812D0D /* Lock.swift */; };
6100FF2B1EDF9806002CF0FB /* dsa_pub.pem in Resources */ = {isa = PBXBuildFile; fileRef = 6100FF2A1EDF9806002CF0FB /* dsa_pub.pem */; };
8400D5C41E17C6D2006785F5 /* AboutWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8400D5C21E17C6D2006785F5 /* AboutWindowController.swift */; };
Expand Down Expand Up @@ -778,6 +779,7 @@
513A4FF929B53F8100A8EA7D /* Atomic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Atomic.swift; sourceTree = "<group>"; };
519872FE26879B9B00F84BCC /* AccessibilityPreferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityPreferences.swift; sourceTree = "<group>"; };
51C1BA39291CA76700C1208A /* InfoDictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InfoDictionary.swift; sourceTree = "<group>"; };
51CACB9429D500290034CEE5 /* VideoPIPViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPIPViewController.swift; sourceTree = "<group>"; };
51F7974628C7E00200812D0D /* Lock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Lock.swift; sourceTree = "<group>"; };
5879479521A87DD700757A6F /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/MiniPlayerWindowController.strings; sourceTree = "<group>"; };
5879479621A87E6100757A6F /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/PreferenceWindowController.strings; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2043,6 +2045,7 @@
E38BD4AE20054BD9007635FC /* MainWindow.swift */,
84CFC92523F8DDE000381E5B /* PlayerWindowController.swift */,
84A0BA9C1D2FAD4000BC8DA1 /* MainWindowController.swift */,
51CACB9429D500290034CEE5 /* VideoPIPViewController.swift */,
84D123B31ECAA405004E0D53 /* TouchBarSupport.swift */,
8400D5C81E1AB2F1006785F5 /* MainWindowController.xib */,
8466BE161D5CDD0300039D03 /* QuickSettingViewController.swift */,
Expand Down Expand Up @@ -2943,6 +2946,7 @@
847557141F405F8C0006B0FF /* MainWindowMenuActions.swift in Sources */,
841B14281E941DFF00744AB8 /* TimeLabelOverflowedStackView.swift in Sources */,
E33BA5C7204BD9FE0069A0F6 /* SubChooseViewController.swift in Sources */,
51CACB9529D500290034CEE5 /* VideoPIPViewController.swift in Sources */,
8460FBA91D6497490081841B /* PlaylistViewController.swift in Sources */,
8450404A1E0B13230079C194 /* CropBoxView.swift in Sources */,
84F7258F1D486185000DEF1B /* MPVProperty.swift in Sources */,
Expand Down
13 changes: 1 addition & 12 deletions iina/MainWindowController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ class MainWindowController: PlayerWindowController {
// MARK: - PIP

lazy var _pip: PIPViewController = {
let pip = PIPViewController()
let pip = VideoPIPViewController()
if #available(macOS 10.12, *) {
pip.delegate = self
}
Expand Down Expand Up @@ -2817,17 +2817,6 @@ extension MainWindowController: PIPViewControllerDelegate {
pip.presentAsPicture(inPicture: pipVideo)
pipOverlayView.isHidden = false

// If the video is paused, it will end up in a weird state due to the
// animation. By forcing a redraw it will keep its paused image throughout.
// (At least) in 10.15, presentAsPictureInPicture: behaves asynchronously.
// Therefore we should wait until the view is moved to the PIP superview.
let currentTrackIsAlbumArt = player.info.currentTrack(.video)?.isAlbumart ?? false
if player.info.isPaused || currentTrackIsAlbumArt {
// It takes two `layout` before finishing entering PIP (tested on macOS 12, but
// could be earlier). Force redraw for the first two `layout`s.
videoView.pendingRedrawsAfterEnteringPIP = 2
}

if let window = self.window {
let windowShouldDoNothing = window.styleMask.contains(.fullScreen) || window.isMiniaturized
let pipBehavior = windowShouldDoNothing ? .doNothing : Preference.enum(for: .windowBehaviorWhenPip) as Preference.WindowBehaviorWhenPip
Expand Down
35 changes: 35 additions & 0 deletions iina/VideoPIPViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// VideoPIPViewController.swift
// iina
//
// Created by low-batt on 3/29/23.
// Copyright © 2023 lhc. All rights reserved.
//

import Cocoa

class VideoPIPViewController: PIPViewController {

/// Force a draw after entering PiP.
///
/// If playback is paused then after entering PiP mode the PiP window will sometimes be white. Force a draw to ensure this does not
/// happen and a frame is displayed. See PR #3973 for details.
///
/// Any changes in this area must be tested on multiple macOS versions. Under 10.15, `presentAsPictureInPicture` behaves
/// asynchronously.
override func viewDidLayout() {
super.viewDidLayout()
guard let controller = delegate as? MainWindowController else { return }
controller.videoView.videoLayer.draw(forced: true)
}

/// Force a draw after exiting PiP.
///
/// If playback is paused then after exiting PiP mode the main window will sometimes be black. Force a draw to ensure this does not
/// happen and a frame is displayed. See issue #4268 and PR #4286 for details.
override func viewDidDisappear() {
super.viewDidDisappear()
guard let controller = delegate as? MainWindowController else { return }
controller.videoView.videoLayer.draw(forced: true)
}
}
10 changes: 0 additions & 10 deletions iina/VideoView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ class VideoView: NSView {
// cached indicator to prevent unnecessary updates of DisplayLink
var currentDisplay: UInt32?

var pendingRedrawsAfterEnteringPIP = 0;

private var displayIdleTimer: Timer?

lazy var hdrSubsystem = Logger.Subsystem(rawValue: "hdr")
Expand Down Expand Up @@ -95,14 +93,6 @@ class VideoView: NSView {
uninit()
}

override func layout() {
super.layout()
if pendingRedrawsAfterEnteringPIP != 0 && superview != nil {
pendingRedrawsAfterEnteringPIP -= 1
videoLayer.draw(forced: true)
}
}

override func draw(_ dirtyRect: NSRect) {
// do nothing
}
Expand Down

0 comments on commit 0ece322

Please sign in to comment.