2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

NSWindowを最前面に表示する - Keynote, PowerPointのプレゼンモードに対応

Last updated at Posted at 2020-03-16

概要

  • 自分のアプリを最前面に表示するための調査・実装です。

参考

GitHub

Qiita_NSWIndowLevelSample

各LevelのWindowを表示する

  • 最前面ということで、まずNSWindowLevelを考えます。
  • テストのため、Swiftで表向きに定義されているwindowLevelでウィンドウをまとめて表示します。

-w628

PowerPointで最前面

  • Power PointGoogle Slideのプレゼンテーションモードでは、WindowdowLevelはそのままでフルスクリーンとなっています。
  • NSPanelに対して、下記の通り設定を行います。
  • またNSWindowLevel.normalよりも大きければOKですね。
// フルスクリーン時に表示するための設定
myWindowController.myWindow.styleMask.insert(.nonactivatingPanel)
myWindowController.myWindow.collectionBehavior.insert(.canJoinAllSpaces)
myWindowController.myWindow.collectionBehavior.insert(.fullScreenAuxiliary)

Keynoteで最前面

  • 一方Keynoteのプレゼンテーションモードで最前面表示をするには、WindowLevel.popUpMenu以上にする必要があります。
    • PowerPointと目的は同じですが手段が違うということですね。
  • 下記が実際に試してみた所
    • .popUpMenu.screenSaverのみが表示されていますね。

実装

MyWindowController.swift
import Cocoa

class MyWindowController: NSWindowController {
    
    @IBOutlet weak var myWindow: NSPanel!
    @IBOutlet weak var windowLevelLabel: NSTextField!
    
    override var windowNibName : String? {
        return String(describing: type(of: self))
    }
    
    override func windowDidLoad() {
        super.windowDidLoad()
        
        // フルスクリーン時に表示するための設定
        self.myWindow.styleMask.insert(.nonactivatingPanel)
        self.myWindow.collectionBehavior.insert(.canJoinAllSpaces)
        self.myWindow.collectionBehavior.insert(.fullScreenAuxiliary)
    }
}

AppDelegate.swift
import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
    
    @IBOutlet weak var window: NSWindow!
    var myWindowControllerList = [MyWindowController]()
    
    struct WindowControllerPropertyKey {
        static let nameKey        = "name"
        static let windowLevelKey = "windowLevel"
    }
    
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Insert code here to initialize your application
        
        var windowSettings:[Dictionary<String, Any>] = []

        // [NSWindow\.Level](https://developer.apple.com/documentation/appkit/nswindow/level)
        // [NSWindowLevel Enum](https://docs.microsoft.com/en-us/dotnet/api/appkit.nswindowlevel?view=xamarin-mac-sdk-14)
        // 上表の通り、数字の順で間違い無さそう。下に行くほど最前面
//        windowSettings.append([WindowControllerPropertyKey.nameKey        : ".normal",
//                               WindowControllerPropertyKey.windowLevelKey : NSWindow.Level.normal])
        
        // 以下3つは同じ優先度
        windowSettings.append([WindowControllerPropertyKey.nameKey        : ".submenu",
                               WindowControllerPropertyKey.windowLevelKey : NSWindow.Level.submenu])
        windowSettings.append([WindowControllerPropertyKey.nameKey        : ".tornOffMenu",
                               WindowControllerPropertyKey.windowLevelKey : NSWindow.Level.tornOffMenu])
        windowSettings.append([WindowControllerPropertyKey.nameKey        : ".floating",
                               WindowControllerPropertyKey.windowLevelKey : NSWindow.Level.floating])
        
        windowSettings.append([WindowControllerPropertyKey.nameKey        : ".modalPanel",
                               WindowControllerPropertyKey.windowLevelKey : NSWindow.Level.modalPanel])
        windowSettings.append([WindowControllerPropertyKey.nameKey        : ".mainMenu",
                               WindowControllerPropertyKey.windowLevelKey : NSWindow.Level.mainMenu])
        windowSettings.append([WindowControllerPropertyKey.nameKey        : ".statusBar",
                               WindowControllerPropertyKey.windowLevelKey : NSWindow.Level.statusBar])
        windowSettings.append([WindowControllerPropertyKey.nameKey        : ".popUpMenu",
                               WindowControllerPropertyKey.windowLevelKey : NSWindow.Level.popUpMenu])
        windowSettings.append([WindowControllerPropertyKey.nameKey        : ".screenSaver",
                               WindowControllerPropertyKey.windowLevelKey : NSWindow.Level.screenSaver])
        
        for windowSetting:Dictionary<String, Any> in windowSettings {
            let myWindowController = MyWindowController()

            myWindowController.showWindow(self)
            myWindowController.myWindow.title               = windowSetting[WindowControllerPropertyKey.nameKey] as! String
            myWindowController.windowLevelLabel.stringValue = windowSetting[WindowControllerPropertyKey.nameKey] as! String
            myWindowController.myWindow.level               = windowSetting[WindowControllerPropertyKey.windowLevelKey] as! NSWindow.Level
            
            myWindowControllerList.append(myWindowController)
        }
    }
    
    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }
    

}

補足

NSColorPanelをKeynoteのプレゼンモードで表示する

概要

  • NSColorPanelのWindowLevelを一旦設定しても、再度NSColorWellを押下して表示した際に、.floatingに戻ってしまっています(なぜだろう?)
  • そこでorder(_:relativeTo:)で表示前にアクションを挟み込むことで対応しました。

参考

実装

import Cocoa

extension NSColorPanel {    
    // [How to get notified when NSWindow opens?](https://stackoverflow.com/questions/20453965/how-to-get-notified-when-nswindow-opens)
    open override func order(_ place: NSWindow.OrderingMode, relativeTo otherWin: Int) {
        super.order(place, relativeTo: otherWin)
        NSColorPanel.shared.level = .screenSaver
    }
}
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?