概要
- 自分のアプリを最前面に表示するための調査・実装です。
参考
- NSWindow.Level
-
NSWindowLevel Enum
- NSWindowLevelの数値定義
-
Swift4でのクラス名取得方法まとめ - Qiita
-
windowNibName
で使用
-
- 他アプリのフルスクリーン上にウインドウを表示する
GitHub
各LevelのWindowを表示する
- 最前面ということで、まず
NSWindowLevel
を考えます。 - テストのため、
Swift
で表向きに定義されているwindowLevelでウィンドウをまとめて表示します。
PowerPointで最前面
-
Power Point
やGoogle 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
のみが表示されていますね。
-
実装
- ほぼ他アプリのフルスクリーン上にウインドウを表示するの実装の通りです。
-
NSPanel
を使うのがミソです。
-
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
}
}