Skip to content

feat(windows): option to open each document in its own window - #57

Merged
b451c merged 1 commit into
b451c:mainfrom
atorresg:feature/separate-document-windows
Nov 11, 2026
Merged

b451c merged 1 commit into
b451c:mainfrom
atorresg:feature/separate-document-windows

Conversation

@atorresg

Copy link
Copy Markdown
Contributor

What

Adds Settings ▸ General ▸ Windows ▸ "Open each document in its own window".

QuickMD deliberately puts every document in the frontmost window as a tab
(WindowTabbing.preferTabsAlways() plus the manual merge in
joinExistingTabs), so two documents can never be read side by side. With
the new option on, each document gets its own window instead.

Off by default — the tab behaviour is unchanged.

Why

Reading two documents at once (a spec and the code that implements it, two
related notes) is a normal thing to want, and the tab layout makes it
impossible without a second app instance.

How

Three AppKit levers, with different lifetimes — the distinction is the
whole difficulty here:

Lever Scope When it takes effect
NSWindow.userTabbingPreference (AppleWindowTabbingMode in the argument domain) global At launch only
NSWindow.allowsAutomaticWindowTabbing global any time
NSWindow.tabbingMode per window when the window is shown
  • At launch, the preference is written as "manual" instead of "always",
    and allowsAutomaticWindowTabbing is set to false. The preference has
    to be chosen here: AppKit reads userTabbingPreference once per process
    and caches it, so rewriting the defaults domain later has no effect.
  • While the app runs, the two levers that do work at runtime are used:
    allowsAutomaticWindowTabbing (global) and tabbingMode (per window).
  • The manual merge that joins a new window to an existing tab group is
    skipped in separate-windows mode.

Note for the record: the raw value for "never tab" is "manual", not
"never" — "never" is an old alias for "inFullScreen".

Limitation

Documents that are already open keep the tab group they are in. AppKit
gives an app no way to take a tab group apart (addTabbedWindow(_:ordered:)
is public, removeTabbedWindow is not), so the option applies to documents
opened from the moment it is switched on. At launch it applies to
everything.

Tests

WindowTabbingTests covers the preference values written to the argument
domain, allowsAutomaticWindowTabbing in both modes, the per-window mode,
that the manual merge is skipped, and that switching the option back and
forth restores the previous behaviour.

Checked by hand as well: with the option on, every document is its own
window (window.tabbedWindows is nil for each); with it off, they all
join one tab group.

QuickMD forces every document into the frontmost window as a tab
(WindowTabbing.preferTabsAlways + a manual merge), so two documents can
never be read side by side.

Settings ▸ General ▸ Windows ▸ "Open each document in its own window"
turns that off: each document then gets its own window.

How it works:
- At launch, the tabbing preference is written to the argument domain as
  "manual" instead of "always", and NSWindow.allowsAutomaticWindowTabbing
  is set to false. The preference is what AppKit reads when it shows a
  window, and AppKit caches it for the whole process, so it can only be
  chosen at launch.
- While the app runs, the two levers that do work at runtime are used:
  NSWindow.allowsAutomaticWindowTabbing (global) and NSWindow.tabbingMode
  (per window). The manual merge that joins a new window to an existing
  tab group is skipped in separate-windows mode.

Documents already open keep the tab group they are in — AppKit gives an
app no way to take a tab group apart — but every document opened from
then on honours the new mode.
@atorresg atorresg mentioned this pull request Nov 11, 2026
10 tasks done
@b451c b451c mentioned this pull request Nov 11, 2026
@b451c
b451c merged commit 474db65 into b451c:main Nov 11, 2026
@b451c

b451c commented Nov 11, 2026

Copy link
Copy Markdown
Owner

Thank you, this is in 1.15.0: Settings > General > "Open documents in separate windows", off by default.

Changes on top of your branch:

  • with the option on QuickMD uses the same mode as the system's "Prefer tabs: Never", so Merge All Windows and Move Tab to New Window stay available when it is on from launch;
  • new windows cascade and remember the last size;
  • the caption says that documents already open stay as they are and that it takes full effect after a restart, for the reason you described (the tabbing preference is read once per process).

You are credited in the changelog.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants