A little app which shows different ways to simulate NSPanel using NSWindow

Related tags

UI FunWithPanels
Overview

FunWithPanels

A little app which shows different ways to simulate NSPanel using NSWindow, for better or worse.

fun with panels

Settings

FunWithPanels uses a combination of swizzling and other techniques which you can mix and match.

1. Window Type

Generally you want this to be NSWindow, but a real NSPanel is included for comparison.

2. Swizzle Type

Some properties which make a window behave like a panel are ignored if set on NSWindow, but we can swizzle the window to apply them anyway. Two forms of swizzling are implemented, method and class:

  • Method swizzling exchanges computed properties on NSWindow with our own versions. This exchange affects all instances of NSWindow, so we set an associated object on our panel window to make it possible for the property getters to know whether or not to apply the custom behaviour.
extension NSWindow {
    @objc var nonActivatingStyleMask: NSWindow.StyleMask {
        if let _ = objc_getAssociatedObject(self, &NonActivatingHandle) {
            return [.fullSizeContentView, .nonactivatingPanel]
        } else {
            // Not an infinite loop because because method swizzling
            // swapped the original NSWindow property for this one.
            return self.nonActivatingStyleMask
        }
    }
}

// Exchange properties
let styleMaskOriginal = class_getInstanceMethod(NSWindow.self, #selector(getter: NSWindow.styleMask))
let styleMaskNew = class_getInstanceMethod(NSWindow.self, #selector(getter: NSWindow.nonActivatingStyleMask))
method_exchangeImplementations(styleMaskOriginal!, styleMaskNew!)

// Flag our window as a panel
objc_setAssociatedObject(window, &NonActivatingHandle, true, .OBJC_ASSOCIATION_COPY)
  • Class swizzling is both a bit simpler and potentially more invasive. It converts the panel window to our own subclass with overriden properties. No other windows are affected and no associated object is required, but our window may run into trouble if it was originally a different subclass of NSWindow.
class NonactivatingWindow: NSWindow {
    override var styleMask: NSWindow.StyleMask {
        get {
            [.fullSizeContentView, .nonactivatingPanel]
        }
        set {
            super.styleMask = newValue
        }
    }
}

object_setClass(window, NonactivatingWindow.self)

3. Remove titlebar from view

Normal windows (including NSPanel) have a titlebar area, even if it is completely hidden. The titlebar area provides a drag region and is also responsible for drawing the window border and shadow. But it poses a problem for us, because clicking into it can activate the app even after swizzling the window.

We can remove the titlebar forcefully with styleMask.remove(.titled), but this requires us to recreate a custom window border and frame. The result won't look or work exactly the same as a titled window. (Compare Alfred, which does not use a titled panel, with Spotlight, which does.)

More importantly, removing the titlebar from an existing window may break any code which expects it to exist.

Titled window with hidden title:

Non-titled window with custom frame:

4. _setPreventsActivation

This API completely stops the window from activating, even when clicking the titlebar area. The two caveats are 1) it's a private API, and 2) swizzling must still be used to allow the window to appear over fullscreen apps.

5. Transform Process Type

One way to prevent activation is to transform the process type to UIElement. Transforming the process type allows the window to appear over full screen apps, and it does not require swizzling or private APIs. But it affects every window in the app, and it makes the Dock icon disappear. So it's only suitable if the window will only appear when no windows are open and the Dock icon is already hidden, or if the window belongs to its own process.

6. Delay

Show the panel after a delay, giving you time to switch to a different window, space, or full screen app.

You might also like...
We-split - A study app made using SwiftUI

We Split We Split is a study app made using SwiftUI, being part of 100 Days of S

Play BreakOut while loading - A playable pull to refresh view using SpriteKit
Play BreakOut while loading - A playable pull to refresh view using SpriteKit

BreakOutToRefresh Play BreakOut while loading - A playable pull to refresh view using SpriteKit BreakOutToRefresh uses SpriteKit to add a playable min

Full configurable spreadsheet view user interfaces for iOS applications. With this framework, you can easily create complex layouts like schedule, gantt chart or timetable as if you are using Excel.
Full configurable spreadsheet view user interfaces for iOS applications. With this framework, you can easily create complex layouts like schedule, gantt chart or timetable as if you are using Excel.

kishikawakatsumi/SpreadsheetView has moved! It is being actively maintained at bannzai/SpreadsheetView. This fork was created when the project was mov

Search jailbreak packages using the Tweakio API, Parcility API or Canister API straight from Cydia, Installer, Sileo and Zebra!

Tweakio Search packages globally directly from your favourite package manager! Works with Cydia, Installer, Zebra and Sileo! How does it work The twea

Work in progress gallery of controls available to Catalyst apps using Optimized for Mac
Work in progress gallery of controls available to Catalyst apps using Optimized for Mac

Catalyst Controls Gallery Very simple work-in-progress demonstration of many common controls available to Mac Catalyst as of macOS 11. Provided moreso

 💻This is an open source project of the Windows 11 desktop client implemented using SwiftUI.
💻This is an open source project of the Windows 11 desktop client implemented using SwiftUI.

💻 💻This is an open source project of the Windows 11 desktop client implemented using SwiftUI.

Fetch the star wars api from all the planets and list and show details using Swift UI and Combine

Star Wars Planets Fetch the star wars planet data by using stat war api, list and show details using SwiftUI and Combine frameworks 🔖 Swift UI Framew

Telegram Redesign using SwiftUI
Telegram Redesign using SwiftUI

Telegram Redesign using SwiftUI Decided to code this Telegram redesign concept I found on Instagram (link to post). Screenshots Vídeos Vídeo on YouTub

Compose views using enums swiftly: `let label: UILabel = [.text("Hello"), .textColor(.red)]`

ViewComposer Style views using an enum array with its attributes: let label: UILabel = [.text("Hello World"), .textColor(.red)] Table of Contents Inst

Comments
  • It's not a issue.

    It's not a issue.

    Dear Mitchchn, I really appreciate you.

    I wanna make some app and it must have floating, without titllebar and ignore focusing.

    Your example absolutely perfect 👍👍👍

    You are my life saver 🙇🙇🙇

    opened by dev-wow 0
Owner
Mitchell Cohen
Mitchell Cohen
A custom UIControl which functions like UISlider where you can set multiple intervals with different step values for each interval.

MultiStepSlider A custom UIControl which functions like UISlider where you can set multiple intervals with different step values for each interval. Th

Susmita Horrow 25 Apr 28, 2022
A drop-in universal library helps you to manage the navigation bar styles and makes transition animations smooth between different navigation bar styles

A drop-in universal library helps you to manage the navigation bar styles and makes transition animations smooth between different navigation bar styles while pushing or popping a view controller for all orientations. And you don't need to write any line of code for it, it all happens automatically.

Zhouqi Mo 3.3k Dec 21, 2022
Advanced List View for SwiftUI with pagination & different states

AdvancedList This package provides a wrapper view around the SwiftUI List view which adds pagination (through my ListPagination package) and an empty,

Chris 246 Jan 3, 2023
Demonstrate the toolbar view modifier for SwiftUI with different placements

ToolbarProject Demonstrate the toolbar view modifier for SwiftUI with different placements Youtube tutorial --> https://youtu.be/jTW5Z-kyL8g Use toolb

Karin Prater 2 Mar 24, 2022
A library, which adds the ability to hide navigation bar when view controller is pushed via hidesNavigationBarWhenPushed flag

HidesNavigationBarWhenPushed A library, which adds the ability to hide navigation bar when view controller is pushed via hidesNavigationBarWhenPushed

Danil Gontovnik 55 Oct 19, 2022
☠️ An elegant way to show users that something is happening and also prepare them to which contents they are awaiting

Features • Guides • Installation • Usage • Miscellaneous • Contributing ?? README is available in other languages: ???? . ???? . ???? . ???? . ???? To

Juanpe Catalán 11.7k Jan 6, 2023
A framework which helps you attach observers to `UIView`s to get updates on its frame changes

FrameObserver is a framework that lets you attach observers to any UIView subclass and get notified when its size changes. It doesn't use any Method S

null 11 Jul 25, 2022
A Swift material design UI module which paints over the parent view when the switch is on.

:octocat: ?? RAMPaperSwitch is a Swift material design UI module which paints over the parent view when the switch is turned on. iOS library by @Ramotion

Ramotion 2.9k Dec 29, 2022
A nice iOS View Capture Swift Library which can capture all content.

SwViewCapture A nice iOS View Capture Library which can capture all content. SwViewCapture could convert all content of UIWebView to a UIImage. 一个用起来还

Xing Chen 597 Nov 22, 2022
IHTypeWriterLabel - A simple, UILabel subclass which poulates itself as if being typed

IHTypeWriterLabel A simple, UILabel subclass which poulates itself as if being typed. HighLights Written purely in SWIFT. Very simple and lightweight.

Md Ibrahim Hassan 24 May 7, 2019