Macos mode - #6
Merged
Merged
Conversation
Left CTRL keeps its Windows/Linux muscle memory on macOS: when the active BLE profile is a mac (indices 2/3 = WORK MAC / MISC MAC; USB is always PC mode for BIOS use), mac_mode.c activates the M_BASE overlay and CTRL emits left-cmd. Four sparse M-layers (&trans everywhere except mac deltas) sit directly above their PC siblings and compose via conditional_layers; PC layers are untouched. Mac deltas: - CTRL -> left cmd (copy/paste/find/save/tabs all follow) - GUI: hold = right cmd (distinct so iTerm2's Left-Cmd->Ctrl remap leaves a real cmd), tap = cmd+space Spotlight - CTRL+TAB / CTRL+SHIFT+TAB -> ctrl(+shift)+tab morphs (in-app tabs) - ALT+TAB -> hold-and-cycle app switcher via mac_swap behavior: holds RIGHT cmd (left-cmd-keyed morphs stay dormant so FUNC+arrows navigate the switcher), masks ALT, drops TAB before cmd on commit, 5s self-heal watchdog so a bug can never stick cmd - CTRL+BACKSPACE -> option+delete (word delete) - CTRL(+SHIFT)+ARROWS on FUNC/FUNCSHFT -> option(+shift)+arrow morphs (word jump/select; shift explicit - SHIFT here is a layer) - PRINTSCREEN -> cmd+shift+ctrl+4 (area snip to clipboard) - Combos: mod-click chords swap LC()->LG() on mac layers (highest-layer combo filtering verified in combo.c) Also: profile nicknames renamed and widened to 8 visible chars (HOME PC / MISC PC / WORK MAC / MISC MAC / ANDROID); layer names exposed on both OLEDs distinguish the mode (M-BASE etc. via the relay). Caveats documented in-tree: never bind &mo/&tog to M-layers (the conditional engine force-deactivates then-layers); do not reorder layers in Studio (index-order dependent; REORDERING is hard-selected by ZMK_STUDIO so it cannot be compiled out). Kill switch: CONFIG_ANAPHASE_MACOS_MODE=n leaves M-layers dormant. Cost: +0.6% flash / +1.3% RAM on the central; right half unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Hardware test found cmd+option+esc (Force Quit) firing when cancelling the app switcher with ESC. Root cause: upstream mod-morph clears the global modifier mask unconditionally on EVERY release, even when the morph took its default branch (behavior_mod_morph.c release path) - so the first TAB release through the enclosing mm_tab_mac morph un-masked ALT mid-session, leaving cmd+option held; a habitual ESC tap completed the Force Quit chord. Fix: delete mm_tab_mac; bind &mac_swap directly to the TAB cell and make it the mask's only owner. The swapper now implements all three tab behaviours itself: plain TAB, masked ctrl+tab with left-cmd held, and the ALT-masked right-cmd switcher session. ESC during a session is now a clean switcher-cancel (cmd+esc, option properly masked). Also from the same test round, no firmware change: Firefox's default MRU ctrl-tab order made discrete ctrl+tab chords toggle between the two most-recent tabs; unticking 'Ctrl+Tab cycles through tabs in recently used order' restores strip cycling (noted in the code comments). Known residual, documented: the M_SHIFT prev-tab morph fired INSIDE the switcher would still clear the ALT mask (exotic; tolerated). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v2 made the swapper the modifier-mask's owner, but EVERY mod-morph release clears the global mask - including the FUNC+arrow morphs used to navigate the switcher. Arrow-release then ESC while phys-ALT was still held reproduced cmd+option+esc (Force Quit) deterministically (confirmed on hardware with that exact ordering). v3 stops using the mask for sessions entirely: a synthetic LALT-release keycode at session start drops the alt refcount 1->0 (OS sees alt up for the whole session), raised before 'swapping' is set so our own session-ending listener ignores it. The eventual physical ALT release clamps at zero in hid.c with only a log line - verified upstream unregister_mod refuses to go negative. Nothing shared remains for morphs to clobber. Residual, documented: the brief LGUI mask around a ctrl+tab press can be clobbered by a simultaneous morph release (sub-100ms window, wrong tab action at worst). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
v3's synthetic ALT release left ZMK believing alt was up after the 5s watchdog committed a session with phys-ALT still physically held - the next TAB then typed a stray tab into the committed app instead of reopening the switcher. The watchdog path now re-presses ALT synthetically (safe inference: had ALT been released, the keycode listener would have ended the session before the watchdog could), so ZMK's state matches the finger and post-heal TAB starts a fresh session. Listener-ended sessions are unchanged - alt is genuinely up there. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.