当移动到另一个屏幕时阻止子 NSWindow 消失

Gro*_*kys 6 macos user-interface cocoa

在 macOS Monetrey 上,当我将子 NSWindow 移动到另一个屏幕(通过手动拖动它)时,它会消失。使用 SwiftUI 进行最小重现:

import SwiftUI

struct ContentView: View {
    var body: some View {
        Button("Hello World", action:  openChild)
            .padding(50)
    }
    
    func openChild()  {
        let win = NSWindow();
        let parent = NSApp.mainWindow
        parent?.addChildWindow(win, ordered: NSWindow.OrderingMode.above)
        win.makeKeyAndOrderFront(self)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
Run Code Online (Sandbox Code Playgroud)

(我知道这可能不是“正确”的 SwiftUI 处理方式,它只是用尽可能少的代码演示问题 - 这实际上发生在低级 Obj-C 代码中)

有趣的是,如果您:

  • 显示子窗口
  • 将其移至另一个屏幕(它消失)
  • 选择“窗口 -> 移动到[其他屏幕的名称]”

子窗口重新出现,现在可以在屏幕之间自由移动。

从用户报告中我了解到这种行为不会发生在 Big Sur 上。

我知道有些应用程序可以显示子窗口并允许它们在屏幕之间移动,允许这样做的正确咒语是什么?

cat*_*lan 1

我相信您只是想添加第二个NSWindow或一个NSPanel. 没有子窗口关系。例如,在 AppKit 基于文档的应用程序中,您可以-[NSDocument makeWindowControllers]为一个文档覆盖并设置多个窗口控制器。

子窗口适用于特殊用例,例如:自动完成列表等功能,您需要一个无边框窗口,在文本字段下方有一个表格视图,移动时该窗口会自动跟随父窗口。

下面是带有这样一个自动补全窗口的 TextEdit 和相同的 Xcode 调试视图层次结构:

文本编辑 Xcode 调试视图层次结构

请参阅文档中的注释:

在将 childWin 添加为窗口的子窗口后,它会保持在 place 指示的相对位置,以供涉及任一窗口的后续排序操作。当此附件处于活动状态时,移动 childWin 不会导致窗口移动(如将抽屉滑入或滑出),但移动窗口将导致 childWin 移动。

我不相信子窗口曾经打算从其父窗口独立移动,尤其是不同的屏幕。