Context
I have a Mac app that runs from the status bar. When an NSStatusItem is clicked, I display an NSWindow rather than the standard NSMenu.
Problem
Before Sonoma, when the NSStatusItem was clicked I used the activate(ignoringOtherApps: true) API that is now deprecated to ensure that my application became the active app.
On Sonoma, macOS now shows my window but does not activate the application, which means the user must click on the window before interacting with my UI. It also produces a very jarring experience when the user does click in the window, because the active application finally switches.
Worst of all, the problem occurs only about 85% of the time. 15% of the time, the system activates my app when the UI is shown. I cannot nail down a pattern for it yet, but this jives with the AppKit release notes that suggest the system "may" activate my App. (If some stupid, over-engineered, machine-learning gobbldegook thinks it's worth doing, no doubt.)
Question
What is the solution here? How do I tell the system that my app NEEDS to become active when my NSStatusItem is selected because (A) that's what the user expects and (B) the alternative looks like macOS is broken?
Attempts
I have tried setting NSApplication.shared.setActivationPolicy() with both .accessory and even .regular (even though that adds a Dock icon and menubar) and the problem persists.
AppKit
RSS for tagConstruct and manage a graphical, event-driven user interface for your macOS app using AppKit.
Post
Replies
Boosts
Views
Activity
I was wondering if there is a way to programmatically invoke a Finder "quick action" from a Mac app? I know "old school" services can be invoked using NSPerformService and was looking to do something similar with a quick action.
Thanks in advance.
Is there a way to programmatically launch a macOS Action Extension (related documentation: https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/Action.html)
I'm aware how to create "Action Extensions" but they only seem to be activated from NSTextView "rollover" button.
Say I know there is an action extension that works on a particular type of data can I launch it from my app? Obviously we can launch "regular" apps with NSWorkspace by bundle iD but I was wondering if there is any API where my app could directly launch an action extension as the "host app" programmatically.
What's the right way to implement key equivalent matching that handles non-Roman/Latin layouts?
E.g. pressing Cmd+Option+C in a Greek layout produces an NSEvent with chars="ç" unmodchars="ψ", neither of which is going to match a key equivalent of Cmd+Option+C by simile comparison, yet performKeyEquivalent on a button with that exact key equivalent returns YES and activates the button.
How would someone replicate that?
[NSEvent charactersByApplyingModifiers:] also reports "ç", and so does UCKeyTranslate. Yet the Keyboard Viewer shows a modifier layer with "c", not the "ç" that the event reports:
Hi,
Is there a way to detect if a shortcut key is set as a system shortcut. Or list all the assigned system shortcuts in code. I want to have users set custom shortcut keys in my application (for app functionality), but would want to show them a warning that the shortcut is already a system shortcut.
For eg, Cmd+Space is a system shortcut for Spotlight search and I wouldn't want the user to set it as a custom shortcut within the App.
Thanks
My app use modal window opened by NSApp.runModal(for: NSWindow).
This program works in macOS 13, but nothing happens when I press the button(Button("close ModalWindow")) in macOS 14.0 Sonoma.
Why is it not working in macOS 14 ?
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Button("runModal") {
let window = ModalWindow(
contentRect: NSRect(x: 20, y: 20, width: 500, height: 350),
styleMask: [.titled, .closable, .miniaturizable, .resizable],
backing: .buffered,
defer: false)
window.isReleasedWhenClosed = false
window.title = NSLocalizedString("subView", comment: "")
window.contentView = NSHostingView(rootView: SubView())
NSApp.runModal(for: window)
}
.buttonStyle(.borderedProminent)
.tint(.accentColor)
}
.padding(10)
.frame(minWidth: 150, maxWidth: .infinity, minHeight: 60, maxHeight: 60, alignment: .center)
}
}
#Preview {
ContentView()
}
final class ModalWindow: NSWindow {
override func becomeKey() {
super.becomeKey()
level = .modalPanel
}
override func close() {
super.close()
NSApp.stopModal()
}
}
struct SubView: View {
var body: some View {
HStack {
Button("close ModalWindow") {
NSApplication.shared.keyWindow?.close()
}
}
.padding(10)
.frame(minWidth: 150, maxWidth: .infinity, minHeight: 60, maxHeight: 60, alignment: .center)
}
}
Full crash log
Running on an M1-based iMac, macOS 13.6, if I trigger a save panel, I get a crash in com.apple.appkit.xpc.openAndSavePanelService if I expand the panel with the button next to the folder selection popup button (shrinking works fine). Since this is not code that I control, what can I do?
Here is the first part of the crash info:
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x00000001a2788728
Termination Reason: Namespace SIGNAL, Code 5 Trace/BPT trap: 5
Terminating Process: exc handler [2915]
Application Specific Backtrace 0:
0 CoreFoundation 0x000000019f2fb104 __exceptionPreprocess + 176
1 libobjc.A.dylib 0x000000019ee19fd0 objc_exception_throw + 60
2 CoreFoundation 0x000000019f324350 _CFBundleGetValueForInfoKey + 0
3 ViewBridge 0x00000001a6cae5b0 -[NSViewServiceMarshal addChildWindow:ordered:] + 604
4 ViewBridge 0x00000001a6ca6948 -[NSWindow(ViewBridgeSwizzle) swizzledAddChildWindow:ordered:] + 92
5 AppKit 0x00000001a2e85f4c -[NSWindow(NSLayoutConstraintVisualization) _updateConstraintVisualization] + 272
6 AppKit 0x00000001a2eb3cd4 -[NSView(NSConstraintBasedLayoutInternal) engine:willBreakConstraint:dueToMutuallyExclusiveConstraints:] + 104
7 CoreAutoLayout 0x00000001a6e0ce30 -[NSISEngine handleUnsatisfiableRow:usingInfeasibilityHandlingBehavior:prospectiveRowHead:mutuallyExclusiveConstraints:] + 888```
Hi,
Does MacOS support the "Insert" key (Overwrite mode) in general and in an NSTextField? There are Articles that say this can be done using "Fn + Enter", "Fn + i" or "Shift + 0" but I'm unable to trigger the same
https://discussions.apple.com/thread/8457698
https://discussions.apple.com/thread/5469511
Plugging in a Keyboard with a physical 'Insert' key also does nothing.
I have a customizable NSToolbar (using in a Mac Catalyst app "optimized for Mac").
When I right click and choose "Customize toolbar" I get the following error:
Conflicting constraints detected: (
"<NSLayoutConstraint:0x6000014a24e0 NSToolbarItemGroupView:0x13de568c0.width <= 88.5 (active)>",
"<NSAutoresizingMaskLayoutConstraint:0x6000014f5f90 h=--& v=--& NSToolbarItemGroupView:0x13de568c0.width == 89 (active)>"
).
Will attempt to recover by breaking <NSLayoutConstraint:0x6000014a24e0 NSToolbarItemGroupView:0x13de568c0.width <= 88.5 (active)>.
Unable to simultaneously satisfy constraints:
(
"<NSLayoutConstraint:0x6000014a24e0 NSToolbarItemGroupView:0x13de568c0.width <= 88.5 (active)>",
"<NSAutoresizingMaskLayoutConstraint:0x6000014f5f90 h=--& v=--& NSToolbarItemGroupView:0x13de568c0.width == 89 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x6000014a24e0 NSToolbarItemGroupView:0x13de568c0.width <= 88.5 (active)>
Set the NSUserDefault >NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints to YES to have ->[NSWindow visualizeConstraints:] automatically called when this happens. And/or, set a symbolic breakpoint on LAYOUT_CONSTRAINTS_NOT_SATISFIABLE to catch this in the debugger.
I have a non-shipping internal test app which is macOS only. It uses AppKit and .xib files to describe the UI.
On Sonoma, the app renders with most of its UI quite blurry, as if a 10 pixel Gaussian blur were applied to it. The blur is applied to entire views, not just the text. It doesn't vary with screen resolution. I observed this behavior with one of the Sonoma betas but I think it went away when I re-launched the app - at any rate, I forgot about it.
I've updated my dev machine to the shipping Sonoma and the problem is extant. I opened up the .xib file in Xcode and the blurriness is visible there too. I haven't applied any effect layers to my UI.
Not all of the views in my UI are blurry.
Has anyone else seen this?
This function on NSTextLayoutManager has the following signature
func enumerateTextSegments(
in textRange: NSTextRange,
type: NSTextLayoutManager.SegmentType,
options: NSTextLayoutManager.SegmentOptions = [],
using block: (NSTextRange?, CGRect, CGFloat, NSTextContainer) -> Bool
)
The documentation here doesn't define what the CGRect and CGFloat passed to block are. However, looking at sample code Using TextKit2 To Interact With Text, they seem to be the frame for the textsegment and baselineposition respectively.
But, the textSegmentFrame seems to start at origin.x = 5.0 when text is empty. Is this some starting offset for text segments? I don't seem to be able to find mention of this anywhere.
In macOS 14, NSAttributedString.Key.verticalGlyphForm has been deprecated. This key was previously used for rendering text vertically, particularly in languages like Chinese, Japanese, and Korean. I'm curious about the reasons behind its deprecation and would appreciate insights into alternative methods for displaying vertical text.
I have a UTI for "public.directory" and can drag-drop folders onto my app and open them. I also added this to the Info.plist to say the app supported directoryies.
But the default "Open" command seems to popup up an NSOpenPanel with folders not selectable. The "Open" button stays disabled.
How do I change this? I tried implementing "openDocument", but then it lets through any file type, not just the ones in my Info.plist. So I'd like to just use the default implementation, but need an override for the NSOpenPanel.
(IBAction)openDocument:(id)sender
{
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setCanChooseFiles:YES];
[panel setCanChooseDirectories:YES];
[panel setAllowsMultipleSelection:NO];
...
}
Given the below setup for NSOpenPanel, treatsFilePackagesAsDirectories = false is ignored when using the updated allowedContentTypes property with UTType.framework:
let openPanel = NSOpenPanel();
openPanel.canChooseFiles = true;
openPanel.canChooseDirectories = false;
openPanel.allowsMultipleSelection = false;
openPanel.treatsFilePackagesAsDirectories = false;
openPanel.message = "Select a framework for import...";
// deprecated, but works
openPanel.allowedFileTypes = ["framework"];
// not deprecated, but doesn't work
openPanel.allowedContentTypes = [.framework];
openPanel.begin(completionHandler: {
guard
$0 == .OK,
let url = openPanel.url
else { return }
self.frameworkPath = url.path();
});
Using the deprecated allowedFileTypes property with a value of "framework" produces an NSOpenPanel which respects the treatsFilePackagesAsDirectories property.
I'm seting this behavior in both Ventura and Sonoma. Is there something I'm missing?
In this code sample, the TextDocumentView has a variable set to 5.0. Any idea where this 5.0 number is coming from? It is used internally in other calculations within TextDocumentLayer. While it works, I'm not sure what it signifies, and how to adapt it to our projects? Thanks
Is there a way to customize the context menu that pops up when right clicking on a toolbar (or the title bar of the window containing it)?
As of Sonoma, the steps that worked (described here: https://developer.apple.com/forums/thread/21887) up to Ventura no longer work. I'm developing in Objective-C.
Using the screencapture CLI on macOS Sonoma 14.0 (23A344) results in a 72dpi image file, no matter if it was captured on a retina display or not.
For example, using
screencapture -i ~/Desktop/test.png in Terminal lets me create a selective screenshot, but the resulting file does not contain any DPI metadata (checked using mdls ~/Desktop/test.png), nor does the image itself have the correct DPI information (should be 144, but it's always 72; checked using Preview.app).
I noticed a (new?) flag option, -r, for which the documentation states:
-r Do not add screen dpi meta data to captured file.
Is that flag somehow automatically set? Setting it myself makes no difference and obviously results in a no-dpi-in-metadata and wrong-dpi-in-image file.
The only two ways I got the correct DPI information in a resulting image file was using the default options (forced by -p): screencapture -i -p, and by making the capture go to the clipboard screencapture -i -c. Sadly, I can't use those in my case.
Feedback filed: FB13208235
I'd appreciate any pointers,
Matthias
I'm making a menu bar app that has a timer, and when a timer expires I wanna show a fullscreen popup / window that goes above all other windows, and stays on top even if the user changes desktop via the "three finger swipe" gesture for example.
This is my current code:
class ZbBreakWindowController: NSWindowController {
convenience init() {
guard let screenFrame = NSScreen.main?.frame else {
fatalError("Failed to obtain the main screen's frame")
}
let window = ZbBreakWindow(
contentRect: screenFrame,
styleMask: [.borderless],
backing: .buffered,
defer: false
)
window.collectionBehavior = [.fullScreenPrimary]
window.contentView = NSHostingView(rootView: ZbBreakWindowView())
window.level = .floating
window.center()
self.init(window: window)
}
}
struct ZbBreakWindowView: View {
var body: some View {
Text("It works!")
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
This has two issues right now:
the window or content view height is not fullscreen, it's missing the menu bar height
I can use the swipe gesture to change desktop and the window does not stay on top
How should I go about this?
The window will have buttons to dismiss it of course, I'm just making a break timer kinda like (https://breaktimer.app/#download)
Our MacOS application has a single window which is occupied by an NSView-derived view. It's been working for the last ten years or so, but when using the Sonoma beta, window updates are badly broken.
We rely on using setNeedsDisplayInRect to redisplay any portions of the view that need to be redisplayed, but no matter how small a rectangle we specify, the entire window is repainted with the background colour before our drawRect implementation is called. We already provide an overload of isOpaque in our view which returns true, and in the past this was effective for suppressing the background fill, but it no longer seems to work (although I can confirm that it is still called along the way).
I've attached an image that shows an example of how a sample window looks after resizing (which is correct) and then what it looks like after using setNeedsDisplayInRect to invalidate the region occupied by the button in the centre. I've explicitly set the NSWindow background colour to blue to make it more obvious :
Is it still possible to inhibit the background fill? Repainting the entire view for every update is not really an option for us, for performance reasons
Our application is a login item which runs inactive in background, and in some cases, it shows its popovers in NSModalPanelWindowLevel over a window of an (unrelated) active application. That works well and without a glitch for years.
Now we'd like to change the mouse cursor when the mouse is over some subviews of our popover. Is there a way to do that?
I've tried essentially all the cursor-related APIs I know of, from the most obvious cursorRects through trackingAreas up to the low-level explicit NSCursor.push/set, but whatever I do, looks like macOS simply ignores it and keeps showing the arrow default cursor, even though the mouse is over our window whose views have proper cursorRects or explicitly call NSCursor.push/set etc. Is there a trick to change the cursor in this case? Thanks!