From 06d0d24c2997bc3421569c6e6fcef041d21a78e7 Mon Sep 17 00:00:00 2001 From: yono-code <68183371+yono-code@users.noreply.github.com> Date: Sat, 11 Jul 2026 08:43:48 +0900 Subject: [PATCH] Restore pet limit bar visibility --- src/CodexPetLimitWin/ApplicationController.cs | 23 ++++--------- .../Codex/PetFramePlacement.cs | 27 +++++++++++++++ .../PetFramePlacementTests.cs | 33 +++++++++++++++++++ 3 files changed, 67 insertions(+), 16 deletions(-) create mode 100644 src/CodexPetLimitWin/Codex/PetFramePlacement.cs create mode 100644 tests/CodexPetLimitWin.Tests/PetFramePlacementTests.cs diff --git a/src/CodexPetLimitWin/ApplicationController.cs b/src/CodexPetLimitWin/ApplicationController.cs index 5fb23c2..b6b7641 100644 --- a/src/CodexPetLimitWin/ApplicationController.cs +++ b/src/CodexPetLimitWin/ApplicationController.cs @@ -185,15 +185,15 @@ private void UpdatePetFrame() lastDetectedPetOverlayFrame = petWindowProbe.TryFindVisiblePetOverlay(lastPetState.OverlayFrame); lastPetWindowFound = lastDetectedPetOverlayFrame is not null; - if (lastDetectedPetOverlayFrame is null) - { - HandleMissingPet("pet-window-missing"); - return; - } consecutivePetMisses = 0; - lastOverlayStatus = "shown"; - overlayWindow.ShowAroundPet(RebasePetFrame(lastPetState.PetFrame, lastPetState.OverlayFrame, lastDetectedPetOverlayFrame)); + lastOverlayStatus = lastDetectedPetOverlayFrame is null + ? "shown: state-bounds" + : "shown: native-window-bounds"; + overlayWindow.ShowAroundPet(PetFramePlacement.Resolve( + lastPetState.PetFrame, + lastPetState.OverlayFrame, + lastDetectedPetOverlayFrame)); } finally { @@ -316,15 +316,6 @@ private TrayMenuState CreateTrayState(bool canRefresh) return new TrayMenuState(CreateStatusText(), settings.RingsVisible, settings.LiveUsageEnabled, canRefresh); } - private static PetFrame RebasePetFrame(PetFrame petFrame, PetFrame stateOverlayFrame, PetFrame detectedOverlayFrame) - { - return new PetFrame( - detectedOverlayFrame.X + (petFrame.X - stateOverlayFrame.X), - detectedOverlayFrame.Y + (petFrame.Y - stateOverlayFrame.Y), - petFrame.Width, - petFrame.Height); - } - private ControlsState CreateControlsState() { return new ControlsState( diff --git a/src/CodexPetLimitWin/Codex/PetFramePlacement.cs b/src/CodexPetLimitWin/Codex/PetFramePlacement.cs new file mode 100644 index 0000000..d1b65af --- /dev/null +++ b/src/CodexPetLimitWin/Codex/PetFramePlacement.cs @@ -0,0 +1,27 @@ +namespace CodexPetLimitWin.Codex; + +/// +/// Chooses the frame used to place the companion overlay. +/// The Codex global state is authoritative for whether the pet is open and +/// supplies a usable frame on current Codex versions. A detected native window +/// is used only when available to compensate for a transient position change. +/// +public static class PetFramePlacement +{ + public static PetFrame Resolve(PetFrame petFrame, PetFrame stateOverlayFrame, PetFrame? detectedOverlayFrame) + { + ArgumentNullException.ThrowIfNull(petFrame); + ArgumentNullException.ThrowIfNull(stateOverlayFrame); + + if (detectedOverlayFrame is null) + { + return petFrame; + } + + return new PetFrame( + detectedOverlayFrame.X + (petFrame.X - stateOverlayFrame.X), + detectedOverlayFrame.Y + (petFrame.Y - stateOverlayFrame.Y), + petFrame.Width, + petFrame.Height); + } +} diff --git a/tests/CodexPetLimitWin.Tests/PetFramePlacementTests.cs b/tests/CodexPetLimitWin.Tests/PetFramePlacementTests.cs new file mode 100644 index 0000000..eff18d0 --- /dev/null +++ b/tests/CodexPetLimitWin.Tests/PetFramePlacementTests.cs @@ -0,0 +1,33 @@ +using CodexPetLimitWin.Codex; +using Xunit; + +namespace CodexPetLimitWin.Tests; + +public sealed class PetFramePlacementTests +{ + [Fact] + public void ResolveUsesStateFrameWhenNoVisibleNativePetWindowIsFound() + { + var pet = new PetFrame(1784, 584, 80, 87); + var overlay = new PetFrame(1536, 486, 356, 320); + + var resolved = PetFramePlacement.Resolve(pet, overlay, detectedOverlayFrame: null); + + Assert.Equal(pet, resolved); + } + + [Fact] + public void ResolveRebasesStateFrameWhenNativePetWindowIsFound() + { + var pet = new PetFrame(1784, 584, 80, 87); + var stateOverlay = new PetFrame(1536, 486, 356, 320); + var detectedOverlay = new PetFrame(1600, 520, 356, 320); + + var resolved = PetFramePlacement.Resolve(pet, stateOverlay, detectedOverlay); + + Assert.Equal(1848, resolved.X); + Assert.Equal(618, resolved.Y); + Assert.Equal(80, resolved.Width); + Assert.Equal(87, resolved.Height); + } +}