Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .context/patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ Prefer thin domain modules ending in a façade that re-exports the public `CM.*`
Canonical rules live in **`.cursor/rules/combatmode-lua-safety.mdc`** (Secret values and instance taint).

Summary: never `==`/`</>` on possibly secret UnitGUID/cast GUID/reaction/health/name/width; use `issecretvalue` first, `PublicBool` / `PublicNumber`, `UnitExists`/`UnitIsUnit`/frame identity, color curves / `EvaluateColorFromBoolean`, and combat-deferred binding flushes. Reference Crosshair, FocusNameplateMarker, CastProgress, InteractionHUD Target, PartyRadial HealthBars/RoleIcons/Visual.

## macOS stuck-cursor freeze

A `MouselookStop()` issued while the window is backgrounded (a watched frame auto-unlocks Mouse Look during an alt-tab, e.g. bags/LFG) leaves the OS mouse capture stuck — frozen cursor/camera on return while `IsMouselooking()` lies. There is no window-focus event and the background keeps rendering, so it can't be detected from `OnUpdate`. Recovery is the manual `Combat Mode - Reset Mouse Look` keybind (`CombatMode_ResetMouseLook`, `Core/FreeLook/FreeLookController.lua`): re-grab + release through `CM.LockFreeLook` / `CM.UnlockFreeLook` (keeps UI in sync). The config keybind (`UI/Options/Tabs/TabGeneral.lua`) is shown macOS-only via `IsMacClient()`.
3 changes: 3 additions & 0 deletions CombatMode/Bindings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
CombatMode_CursorModeKey(keystate)
end
</Binding>
<Binding name="Combat Mode - Reset Mouse Look" description="Recover the cursor if it gets stuck after switching windows (re-grabs and releases Mouse Look)" category="|A:::|a|TInterface\Addons\CombatMode\assets\cmtitle:22:95|t">
CombatMode_ResetMouseLook()
</Binding>
<Binding name="Combat Mode - Party Radial" description="Hold to open Party Radial for party targeting" header="Party Radial" category="|A:::|a|TInterface\Addons\CombatMode\assets\cmtitle:22:95|t" runOnUp="true">
if keystate == "down" or keystate == "up" then
CombatMode_PartyRadialKey(keystate)
Expand Down
18 changes: 18 additions & 0 deletions CombatMode/Core/FreeLook/FreeLookController.lua
Original file line number Diff line number Diff line change
Expand Up @@ -435,3 +435,21 @@ function _G.CombatMode_CursorModeKey(keystate)
FreeLookOverride = false
end
end

-- Manual recovery for the macOS stuck-cursor freeze (a MouselookStop issued while the
-- window was backgrounded leaves the OS capture stuck). Re-grab and release through the
-- free-look state machine so the crosshair/tooltip/CVar side effects stay in sync rather
-- than trusting IsMouselooking(); OnUpdate re-locks afterward if free look should be active.
function _G.CombatMode_ResetMouseLook()
CM.LockFreeLook()
local function settle()
if CM.ShouldFreeLookBeOff() then
CM.UnlockFreeLook()
end
end
if C_Timer and C_Timer.After then
C_Timer.After(0, settle)
else
settle()
end
end
17 changes: 17 additions & 0 deletions CombatMode/UI/Options/Tabs/TabGeneral.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ local _G = _G
-- WoW API
local GetBindingKey = _G.GetBindingKey
local GetCurrentBindingSet = _G.GetCurrentBindingSet
local IsMacClient = _G.IsMacClient
local ReloadUI = _G.ReloadUI
local SaveBindings = _G.SaveBindings
local SetBinding = _G.SetBinding
Expand Down Expand Up @@ -110,6 +111,22 @@ UI.Options.AddTab({
end)
end,
})
-- macOS only: on other clients the stuck-cursor freeze does not occur, so this
-- recovery keybind is hidden to avoid clutter.
if IsMacClient() then
ctx:Keybind({
label = "Reset Mouse Look",
desc = "Recover a stuck cursor after switching windows on macOS. Re-grabs and releases Mouse Look to clear a capture the game left stuck while running in the background.",
get = function()
return (GetBindingKey("Combat Mode - Reset Mouse Look"))
end,
set = function(key)
CM.TryApplyBindingChange("reset mouse look keybinding", function()
CM.AssignNamedKeybind("Combat Mode - Reset Mouse Look", key)
end)
end,
})
end
ctx:Toggle({
label = "Pulse Cursor on Unlock",
desc = "Flash the cursor when Mouse Look ends.",
Expand Down
Loading