benilla's layer now uses only the 1.12 API and the 1.12 Lua forms, and the host hooks it used are gone from the VM. - **The VM calls handlers as 1.12.1 does.** A handler body is compiled as the chunk itself, so `self` in it is an ordinary global (`0x704c70`). A handler is called with no arguments (`0x705199`). The loader reads no `function=` attribute. - **`GetBinding`/`GetNumBindings` answer the 1.12 list** (`0x4b7f60`): `HEADER_*` section rows, plus every key bound to a command, with no category column. The stock `KeyBindingFrame` now shows its section headers and both key columns. - **The Key Bindings page captures keys through its own window**, as `Blizzard_BindingUI` does: the frame's `OnKeyDown` for keys, clicks for mouse buttons, and the wheel. It takes the `Benilla` prefix, so loading the stock binding addon no longer breaks it. The UI pointer feed now hands frames mouse buttons 4 and 5. - **`/errors` keeps its log by chaining the Lua error handler**, and the stock ScriptErrors dialog is unchanged. Load failures that never raise now print one chat line each at world entry. - **Slash commands:** `/reload` and `/errors` are `SlashCmdList` rows in the layer. `/convertraid` is gone; 1.12.1 has no such command. The dev commands are host rows in dev builds only, so a player build answers them with the unknown-command line once. - **Naming:** every global the layer defines is `Benilla`-prefixed. `BenillaBindCapture`, `KeyBindings_OnHostKey`, the three script-error globals and `SubmitChatInput` are removed. Verified: - New tests for each rule and each removed surface; 16 mutations each fail a test. - Region dumps of the Options window (general page, Key Bindings, armed) are identical before and after. - `scripts/gates.sh` and `scripts/smoke.sh` are green. - A live run bound a key, a Shift chord and the middle button through the page, and opened `/errors`. Built on macOS; no platform seam touched. Fixes #539 Fixes #544 Fixes #407 Part of #171 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
133 lines
6.5 KiB
XML
133 lines
6.5 KiB
XML
<Ui>
|
|
<!--
|
|
The ESC menu: the stock GameMenuFrame.xml, reshaped in place as a 1.12 addon reshapes it.
|
|
Deviation: the rungs are the 1.15 era client's ESC menu, because its settings screens
|
|
replace 1.12's, which are much worse to use; the era's AddOns rung is dropped, since the
|
|
character-select AddOns screen is the only addon UI.
|
|
-->
|
|
|
|
<!-- The era's header font, which 1.12's Fonts.xml lacks. -->
|
|
<Font name="BenillaGameFontNormalMed1" inherits="GameFontNormal" virtual="true">
|
|
<FontHeight><AbsValue val="13"/></FontHeight>
|
|
</Font>
|
|
|
|
<Script><![CDATA[
|
|
-- ══ The frame: the era layout, 28+144+28 wide, 32 top, 28 bottom, 7 rungs of 21 and
|
|
-- three gaps of 20 ═══════════════════════════════════════════════════════════════════════
|
|
GameMenuFrame:SetWidth(200)
|
|
GameMenuFrame:SetHeight(267)
|
|
|
|
-- The stock title (`GameMenuFrame.xml:36`) has no name: found as addons find it.
|
|
for _, region in ipairs({ GameMenuFrame:GetRegions() }) do
|
|
if region:GetObjectType() == "FontString" and region:GetText() == MAIN_MENU then
|
|
region:SetFontObject(BenillaGameFontNormalMed1)
|
|
end
|
|
end
|
|
|
|
-- BENILLA_ERA_WINDOW_SCALE (OptionsFrame.xml) stands in for the era's UIParent scale;
|
|
-- read at every show, then the stock OnShow.
|
|
local Ref_GameMenuFrame_OnShow = GameMenuFrame:GetScript("OnShow")
|
|
GameMenuFrame:SetScript("OnShow", function()
|
|
this:SetScale(BENILLA_ERA_WINDOW_SCALE or 1)
|
|
Ref_GameMenuFrame_OnShow()
|
|
end)
|
|
|
|
-- ══ The rungs ═══════════════════════════════════════════════════════════════════════════
|
|
-- Every stock rung stays, anchored TOP to a BOTTOM as in the stock file, so an addon's
|
|
-- `SetPoint("TOP", …)` replaces its one anchor. The three the era menu lacks are hidden
|
|
-- in place, with Sound and UI Options each laid over the rung above it, so they take no
|
|
-- space: a width or height of 0 is no size in 1.12's layout, not a flat rect.
|
|
|
|
-- Literal: 1.12 has no GAMEMENU_OPTIONS; its OPTIONS_MENU is "Options Menu".
|
|
GameMenuButtonOptions:SetText("Options")
|
|
GameMenuButtonOptions:ClearAllPoints()
|
|
GameMenuButtonOptions:SetPoint("TOP", GameMenuFrame, "TOP", 0, -32)
|
|
GameMenuButtonOptions:SetScript("OnClick", function()
|
|
PlaySound("igMainMenuOption")
|
|
HideUIPanel(GameMenuFrame)
|
|
ShowUIPanel(BenillaOptionsFrame)
|
|
end)
|
|
|
|
for _, fold in ipairs({
|
|
{ GameMenuButtonSoundOptions, GameMenuButtonOptions },
|
|
{ GameMenuButtonUIOptions, GameMenuButtonSoundOptions },
|
|
}) do
|
|
local button, above = fold[1], fold[2]
|
|
button:Hide()
|
|
button:ClearAllPoints()
|
|
button:SetPoint("TOP", above, "BOTTOM", 0, button:GetHeight())
|
|
end
|
|
-- Key Bindings keeps its stock anchor, 1 under UI Options: the era rungs hang from its
|
|
-- top, so an addon that inserts a button above it and re-anchors it under that button
|
|
-- (ShaguTweaks) moves them down as it moves the stock rungs.
|
|
GameMenuButtonKeybindings:Hide()
|
|
|
|
-- The era's Edit Mode and Support, with nothing behind them yet: disabled.
|
|
local editMode = CreateFrame("Button", "BenillaGameMenuButtonEditMode", GameMenuFrame,
|
|
"GameMenuButtonTemplate")
|
|
editMode:SetPoint("TOP", GameMenuButtonKeybindings, "TOP", 0, -19)
|
|
editMode:SetText("Edit Mode")
|
|
editMode:Disable()
|
|
local support = CreateFrame("Button", "BenillaGameMenuButtonSupport", GameMenuFrame,
|
|
"GameMenuButtonTemplate")
|
|
support:SetPoint("TOP", editMode, "BOTTOM", 0, 0)
|
|
support:SetText("Support")
|
|
support:Disable()
|
|
|
|
GameMenuButtonMacros:SetPoint("TOP", support, "BOTTOM", 0, 0)
|
|
GameMenuButtonLogout:SetPoint("TOP", GameMenuButtonMacros, "BOTTOM", 0, -20)
|
|
GameMenuButtonQuit:SetPoint("TOP", GameMenuButtonLogout, "BOTTOM", 0, 0)
|
|
GameMenuButtonContinue:SetPoint("TOP", GameMenuButtonQuit, "BOTTOM", 0, -20)
|
|
|
|
-- ══ Our options window in the stock "is an options window open?" checks ═══════════════
|
|
-- Each wraps the stock function to add `BenillaOptionsFrame`.
|
|
local Ref_IsOptionFrameOpen = IsOptionFrameOpen
|
|
local Ref_ToggleGameMenu = ToggleGameMenu
|
|
local Ref_UpdateMicroButtons = UpdateMicroButtons
|
|
|
|
-- Guarded for a test kit that loads the game menu without the options window.
|
|
local function BenillaOptions_IsOpen()
|
|
return BenillaOptionsFrame and BenillaOptionsFrame:IsVisible()
|
|
end
|
|
|
|
-- `UIParent.lua:996`: a yes keeps the ESC sweep off the centre panel, which our window is.
|
|
function IsOptionFrameOpen()
|
|
if BenillaOptions_IsOpen() then
|
|
return 1
|
|
end
|
|
return Ref_IsOptionFrameOpen()
|
|
end
|
|
|
|
-- `UIParent.lua:1465-1497`: static popup, then an open options window, then the stock
|
|
-- ladder. Our Close click is the discard-and-hide of the reference's `OptionsFrameCancel`.
|
|
function ToggleGameMenu(clicked)
|
|
if clicked then
|
|
-- As the reference's `clicked` arm: close an options window, then toggle.
|
|
if BenillaOptions_IsOpen() then
|
|
BenillaOptionsFrameCloseButton:Click()
|
|
end
|
|
return Ref_ToggleGameMenu(clicked)
|
|
end
|
|
if StaticPopup_EscapePressed() then
|
|
return
|
|
end
|
|
if BenillaOptions_IsOpen() then
|
|
BenillaOptionsFrameCloseButton:Click()
|
|
return
|
|
end
|
|
return Ref_ToggleGameMenu(clicked)
|
|
end
|
|
|
|
-- `MainMenuBarMicroButtons.lua:47-58`: only ever pushes the button, so the stock decision
|
|
-- stands and ours adds our window. Guarded for a test kit that loads no micro buttons.
|
|
function UpdateMicroButtons()
|
|
if Ref_UpdateMicroButtons then
|
|
Ref_UpdateMicroButtons()
|
|
end
|
|
if MainMenuMicroButton and BenillaOptions_IsOpen() then
|
|
MainMenuMicroButton:SetButtonState("PUSHED", 1)
|
|
end
|
|
end
|
|
]]></Script>
|
|
</Ui>
|