// // KMFullScreenWindow.swift // PDF Master // // Created by liujiajie on 2024/1/16. // import Cocoa let DURATION = 0.3 class KMFullScreenWindow: NSWindow, NSAnimationDelegate{ var animation: NSViewAnimation? var isMain = false convenience init(screen: NSScreen, bgColor: NSColor, level: Int, isMain flag: Bool){ self.init(contentRect: screen.frame, styleMask: .borderless, backing: .buffered, defer: false) isMain = flag self.backgroundColor = bgColor self.level = NSWindow.Level(rawValue: level) self.isReleasedWhenClosed = false self.displaysWhenScreenProfileChanges = flag self.acceptsMouseMovedEvents = flag self.isExcludedFromWindowsMenu = flag == false self.setFrame(screen.frame, display: false) let selector = NSSelectorFromString("setAnimationBehavior:") if self.responds(to: selector){ self.animationBehavior = .none } } deinit { stopAnimation() } func stopAnimation() { animation?.stop() animation = nil } func canBecomeKeyWindow() -> Bool { return isMain } func canBecomeMainWindow() -> Bool { return isMain } override func orderFront(_ sender: Any?) { self.stopAnimation() self.alphaValue = 1.0 super.orderFront(sender) } override func makeKeyAndOrderFront(_ sender: Any?) { self.stopAnimation() self.alphaValue = 1.0 super.makeKeyAndOrderFront(sender) } override func orderOut(_ sender: Any?) { self.stopAnimation() self.alphaValue = 1.0 super.orderOut(sender) } func fadeOutWithBlockingMode(blockingMode: NSAnimation.BlockingMode) { if UserDefaults.standard.bool(forKey: SKDisableAnimationsKey) { self.orderOut(nil) } else { let dict = NSMutableDictionary() dict.setObject(self as Any, forKey: NSViewAnimation.Key.target as NSCopying) dict.setObject(NSViewAnimation.EffectName.fadeOut, forKey: NSViewAnimation.Key.effect as NSCopying) animation = NSViewAnimation(viewAnimations: NSArray(object: dict) as! [[NSViewAnimation.Key : Any]]) animation?.animationBlockingMode = blockingMode animation?.duration = DURATION animation?.delegate = self animation?.start() } } func fadeInWithBlockingMode(blockingMode: NSAnimation.BlockingMode) { if UserDefaults.standard.bool(forKey: SKDisableAnimationsKey) { self.orderFront(nil) } else { let dict = NSMutableDictionary() dict.setObject(self as Any, forKey: NSViewAnimation.Key.target as NSCopying) dict.setObject(NSViewAnimation.EffectName.fadeIn, forKey: NSViewAnimation.Key.effect as NSCopying) self.alphaValue = 0.0 super.orderFront(nil) animation = NSViewAnimation(viewAnimations: NSArray(object: dict) as! [[NSViewAnimation.Key : Any]]) animation?.animationBlockingMode = blockingMode animation?.duration = DURATION animation?.delegate = self animation?.start() } } func fadeOutBlocking() { self.fadeOutWithBlockingMode(blockingMode: .blocking) } func fadeOut() { self.fadeOutWithBlockingMode(blockingMode: .nonblockingThreaded) } func fadeInBlocking() { self.fadeInWithBlockingMode(blockingMode: .blocking) } func fadeIn() { self.fadeInWithBlockingMode(blockingMode: .nonblockingThreaded) } func animationDidEnd(_ anAnimation: NSAnimation) { let ani: NSViewAnimation = animation ?? NSViewAnimation() let arr: [Any] = ani.viewAnimations let dict: [NSViewAnimation.Key: Any] = arr.last as! [NSViewAnimation.Key : Any] let isFadeOut: Bool = dict[NSViewAnimation.Key.effect] as! NSViewAnimation.EffectName == NSViewAnimation.EffectName.fadeOut animation = nil Task { @MainActor in if isFadeOut { self.orderOut(nil) } self.alphaValue = 1.0 } } func animationDidStop(_ anAnimation: NSAnimation) { animation = nil self.orderOut(nil) self.alphaValue = 1.0 } override func sendEvent(_ event: NSEvent) { if event.type == .rightMouseDown || (event.type == .leftMouseDown && (event.modifierFlags.rawValue & NSEvent.ModifierFlags.control.rawValue) != 0) { if self.windowController?.responds(to: Selector(("handleRightMouseDown:"))) == true && self.windowController?.handleRightMouseDown(theEvent: event) == true { return } } else if event.type == .keyDown { if event.keyCode == 53 { // esc // let sel = NSSelectorFromString("cancelOperation") self.cancelOperation(nil) return } } super.sendEvent(event) } override func cancelOperation(_ sender: Any?) { if self.windowController?.responds(to: #selector(NSStandardKeyBindingResponding.cancelOperation(_:))) == true { self.windowController?.cancelOperation(self) } } } extension NSWindowController{ func handleRightMouseDown(theEvent: NSEvent) -> Bool { return false } }