
Mac Catalyst runs an iPad application on macOS. That was a useful bridge for Codename One, but it remained a bridge. Once we added multiple desktop windows, the missing desktop operations and rendering compromises stopped being edge cases.
PR #5601 changes the default native Mac build to AppKit. The result is an NSApplication with NSWindow, NSMenu, NSTextInputClient, NSScreen, and a CAMetalLayer for each rendered window. It is a Mac application rather than an iOS application asking macOS to translate the experience.
For the complete release, including calls, VPN, OTP, contacts, and Android billing, read the weekly overview.
Catalyst was doing expensive work
The Catalyst port rendered a secondary Codename One window into a mutable image and then copied that image into the scene. A 4K BGRA surface is roughly 33 MB before another buffer or copy enters the picture. Moving or repainting several windows multiplies that cost.
AppKit gives each Window its own Metal-backed drawable:
Dirty regions stay attached to one native window. A repaint in an inspector does not need an intermediate image the size of the editor window. Monitor scale comes from the NSScreen that owns the window, not from an iOS scene approximation.

A Codename One component tree rendered into an AppKit window at 900 by 700.
Desktop operations are desktop operations again
The AppKit port implements always-on-top, utility windows, minimize, restore, maximize, modality, undecorated windows, and native dirty clipping. Menus use NSMenu. Text editing implements NSTextInputClient, including composition and input-method interaction. Multiple monitors come through NSScreen with their independent work areas and scale factors.
Those details matter to applications such as editors, trading terminals, control rooms, and internal tools. A utility palette that cannot remain above its owner is not a utility palette. A text editor that bypasses the input method works only for the developer who tested it.
The dialog work builds on this port. A dialog may stay in its owner’s layered pane or become a native modal window. Both paths now have a real Mac window model underneath them.
Existing build targets, different native foundation
The normal targets keep their names:
mvn -B \
-Dcodename1.platform=ios \
-Dcodename1.buildTarget=mac-source \
package
mvn -B \
-Dcodename1.platform=ios \
-Dcodename1.buildTarget=mac-os-x-native \
package
mac-source produces an Xcode project under the build target directory. mac-os-x-native produces the signed native result through the build service. Existing projects do not need a new application API.
Catalyst has no separate build target. An application that depends on it can preserve the previous behavior by setting the existing hint and building an ordinary iOS target:
codename1.arg.macNative.enabled=true
Use ios-source for a local Xcode project or ios-device for a build-server build. Catalyst is no longer the default definition of “native Mac.”
A port is a contract, not a screenshot
The pull request ran the full native screenshot suite plus platform and input tests. The same window layouts are captured at several aspect ratios. Text input, mouse routing, focus, resizing, modality, and screen scale have dedicated coverage.
Accessibility follows the window model too. IOSNative.updateAccessibilityTree() sends the framework semantics tree to CN1MacAccessibilityUpdateTree(), which installs a hierarchy of NSAccessibilityElement children on the relevant window. Roles, labels, values, states, standard and custom actions, and live-region announcements reach VoiceOver through AppKit instead of stopping at the portable tree.
Platform services with a UIKit-only implementation still need individual AppKit work. Switching the default port does not make those integrations native to macOS automatically.
Another Tuesday
A new Codename One platform port once deserved an entire release cycle and its own launch. This week the AppKit port arrived beside VoIP, VPN, phone verification, private contact selection, native dialogs, billing, browser density, and a documentation overhaul. A new native platform has become another Tuesday.
The common component model and builder contract carry most of the application unchanged. The Mac port owns native windows, input, menus, text, and rendering. It does not require a second application UI or a Mac-specific navigation architecture.
The same division strengthens secure defaults. Native platform integration belongs in a reviewed port and build pipeline, not in copied project fragments that drift across application repositories. Applications keep their own interface and data model. The builder supplies the narrow native product needed to run them.
Next, the OTP article removes an inbox permission from a common verification flow.
Discussion
What Mac behavior has been hardest to preserve when sharing code with mobile?