Fix mouse hover hitting removed controls (ghost hitboxes)

When removeControl() removes a Flash element (e.g. the Reinstall
button in Help & Options, or the Debug button when disabled), the
C++ control object stays in the m_controls vector. On Vita this was
handled by calling setHidden(true) and checking getHidden() in the
touch hit-test, but on Windows64 none of that was happening.

The result: removed buttons kept phantom bounds that the hover code
would match against, stealing focus from the buttons that shifted
into their visual position. In the Help & Options menu with debug
enabled, the removed Reinstall button (Button6) had ghost bounds
overlapping where the Debug button (Button7) moved to after the
removal, making Debug un-hoverable and snapping focus to Button1.

The fix has three parts:

- removeControl() now calls setHidden(true) on all platforms, not
  just Vita. The m_bHidden member was already declared on all
  platforms, only the accessors were ifdef'd behind __PSVITA__.

- Removed the __PSVITA__ ifdef from setHidden/getHidden in
  UIControl.h so they're available everywhere.

- Added getHidden() checks in both the hover and click hit-test
  loops, matching what the Vita touch code already does. The check
  is a simple bool read (no Flash/Iggy call), placed before the
  getVisible() query which hits Flash and can return stale values
  for removed elements.
This commit is contained in:
MrTheShy 2026-03-06 05:50:09 +01:00
parent c684f5e962
commit ae38a6912b
3 changed files with 5 additions and 6 deletions

View file

@ -64,10 +64,8 @@ public:
virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName);
void UpdateControl();
#ifdef __PSVITA__
void setHidden(bool bHidden) {m_bHidden=bHidden;}
bool getHidden(void) {return m_bHidden;}
#endif
IggyValuePath *getIggyValuePath();

View file

@ -865,7 +865,7 @@ void UIController::tickInput()
for (size_t i = 0; i < controls->size(); ++i)
{
UIControl *ctrl = (*controls)[i];
if (!ctrl || !ctrl->getVisible() || ctrl->getId() < 0)
if (!ctrl || ctrl->getHidden() || !ctrl->getVisible() || ctrl->getId() < 0)
continue;
UIControl::eUIControlType type = ctrl->getControlType();

View file

@ -478,7 +478,7 @@ bool UIScene::handleMouseClick(F32 x, F32 y)
for (size_t i = 0; i < controls->size(); ++i)
{
UIControl *ctrl = (*controls)[i];
if (!ctrl || !ctrl->getVisible() || ctrl->getId() < 0)
if (!ctrl || ctrl->getHidden() || !ctrl->getVisible() || ctrl->getId() < 0)
continue;
UIControl::eUIControlType type = ctrl->getControlType();
@ -607,12 +607,13 @@ void UIScene::removeControl( UIControl_Base *control, bool centreScene)
// update the button positions since they may have changed
UpdateSceneControls();
// mark the button as removed
control->setHidden(true);
// remove it from the touchboxes
ui.TouchBoxRebuild(control->getParentScene());
#endif
// mark the button as removed so hover/touch hit-tests skip it
control->setHidden(true);
}
void UIScene::slideLeft()