Controller cursor highlight fixes

This resolves two issues:
1) Ensure that cursor tooltips stay displayed when buying spells or selling or consuming items and any other place where actions can highlight new items.
2) Ignore small mouse movements if we've just warped the mouse pointer a long distance.  This resolves an issue where slight cursor wiggle will trigger after changing the dpad highlight.
This commit is contained in:
bmdhacks 2025-09-04 18:09:09 -07:00
parent 12aef44fe1
commit cf51812a6f
12 changed files with 104 additions and 51 deletions

View File

@ -392,10 +392,10 @@ namespace MWBase
/// Cycle to the next window to receive controller events
virtual void cycleActiveControllerWindow(bool next) = 0;
virtual void setActiveControllerWindow(MWGui::GuiMode mode, int activeIndex) = 0;
virtual bool getControllerTooltip() const = 0;
virtual void setControllerTooltip(bool enabled) = 0;
virtual bool getControllerTooltipUserPreference() const = 0;
virtual void setControllerTooltipUserPreference(bool enabled) = 0;
virtual bool getControllerTooltipVisible() const = 0;
virtual void setControllerTooltipVisible(bool visible) = 0;
virtual bool getControllerTooltipEnabled() const = 0;
virtual void setControllerTooltipEnabled(bool enabled) = 0;
virtual void updateControllerButtonsOverlay() = 0;
// Used in Lua bindings

View File

@ -190,7 +190,7 @@ namespace MWGui
{
mControllerActiveWindow = active;
MWBase::Environment::get().getWindowManager()->setControllerTooltip(
MWBase::Environment::get().getWindowManager()->setControllerTooltipVisible(
active && Settings::gui().mControllerTooltips);
if (active)
@ -219,34 +219,38 @@ namespace MWGui
break;
case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
// Toggle info tooltip
winMgr->setControllerTooltipUserPreference(!winMgr->getControllerTooltip());
winMgr->setControllerTooltipEnabled(!winMgr->getControllerTooltipEnabled());
updateControllerFocus(-1, mControllerFocus);
break;
case SDL_CONTROLLER_BUTTON_DPAD_UP:
if (winMgr->getControllerTooltipUserPreference() && !winMgr->getControllerTooltip())
winMgr->setControllerTooltip(true);
// Restore tooltip visibility if user has them enabled but they were hidden by mouse
if (winMgr->getControllerTooltipEnabled() && !winMgr->getControllerTooltipVisible())
winMgr->setControllerTooltipVisible(true);
if (mControllerFocus % mRows == 0)
mControllerFocus = std::min(mControllerFocus + mRows - 1, mItemCount - 1);
else
mControllerFocus--;
break;
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
if (winMgr->getControllerTooltipUserPreference() && !winMgr->getControllerTooltip())
winMgr->setControllerTooltip(true);
// Restore tooltip visibility if user has them enabled but they were hidden by mouse
if (winMgr->getControllerTooltipEnabled() && !winMgr->getControllerTooltipVisible())
winMgr->setControllerTooltipVisible(true);
if (mControllerFocus % mRows == mRows - 1 || mControllerFocus == mItemCount - 1)
mControllerFocus -= mControllerFocus % mRows;
else
mControllerFocus++;
break;
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
if (winMgr->getControllerTooltipUserPreference() && !winMgr->getControllerTooltip())
winMgr->setControllerTooltip(true);
// Restore tooltip visibility if user has them enabled but they were hidden by mouse
if (winMgr->getControllerTooltipEnabled() && !winMgr->getControllerTooltipVisible())
winMgr->setControllerTooltipVisible(true);
if (mControllerFocus >= mRows)
mControllerFocus -= mRows;
break;
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
if (winMgr->getControllerTooltipUserPreference() && !winMgr->getControllerTooltip())
winMgr->setControllerTooltip(true);
// Restore tooltip visibility if user has them enabled but they were hidden by mouse
if (winMgr->getControllerTooltipEnabled() && !winMgr->getControllerTooltipVisible())
winMgr->setControllerTooltipVisible(true);
if (mControllerFocus + mRows < mItemCount)
mControllerFocus += mRows;
else if (mControllerFocus / mRows != (mItemCount - 1) / mRows)
@ -265,7 +269,7 @@ namespace MWGui
void ItemView::updateControllerFocus(int prevFocus, int newFocus)
{
MWBase::Environment::get().getWindowManager()->setCursorVisible(
!MWBase::Environment::get().getWindowManager()->getControllerTooltip());
!MWBase::Environment::get().getWindowManager()->getControllerTooltipVisible());
if (!mItemCount)
return;
@ -293,7 +297,12 @@ namespace MWGui
else
mScrollView->setViewOffset(MyGUI::IntPoint(-42 * (column - 3), 0));
if (MWBase::Environment::get().getWindowManager()->getControllerTooltip())
// Restore tooltip visibility if user has them enabled but they were hidden by mouse movement
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
if (winMgr->getControllerTooltipEnabled() && !winMgr->getControllerTooltipVisible())
winMgr->setControllerTooltipVisible(true);
if (winMgr->getControllerTooltipVisible())
MWBase::Environment::get().getInputManager()->warpMouseToWidget(focused);
}
}

View File

@ -151,8 +151,8 @@ namespace MWGui
mSpellButtons[0].first->setStateSelected(true);
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
winMgr->setControllerTooltip(Settings::gui().mControllerTooltips);
if (winMgr->getControllerTooltip())
winMgr->setControllerTooltipVisible(Settings::gui().mControllerTooltips);
if (winMgr->getControllerTooltipVisible())
MWBase::Environment::get().getInputManager()->warpMouseToWidget(mSpellButtons[0].first);
}
}
@ -230,6 +230,8 @@ namespace MWGui
bool SpellBuyingWindow::onControllerButtonEvent(const SDL_ControllerButtonEvent& arg)
{
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
if (arg.button == SDL_CONTROLLER_BUTTON_A)
{
if (mControllerFocus < mSpellButtons.size())
@ -242,11 +244,14 @@ namespace MWGui
else if (arg.button == SDL_CONTROLLER_BUTTON_RIGHTSTICK)
{
// Toggle info tooltip
MWBase::Environment::get().getWindowManager()->setControllerTooltip(
!MWBase::Environment::get().getWindowManager()->getControllerTooltip());
winMgr->setControllerTooltipEnabled(!winMgr->getControllerTooltipEnabled());
}
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
{
// Restore tooltip visibility if user has them enabled but they were hidden by mouse
if (winMgr->getControllerTooltipEnabled() && !winMgr->getControllerTooltipVisible())
winMgr->setControllerTooltipVisible(true);
if (mSpellButtons.size() <= 1)
return true;
@ -256,6 +261,10 @@ namespace MWGui
}
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
{
// Restore tooltip visibility if user has them enabled but they were hidden by mouse
if (winMgr->getControllerTooltipEnabled() && !winMgr->getControllerTooltipVisible())
winMgr->setControllerTooltipVisible(true);
if (mSpellButtons.size() <= 1)
return true;
@ -279,7 +288,7 @@ namespace MWGui
}
// Warp the mouse to the selected spell to show the tooltip
if (MWBase::Environment::get().getWindowManager()->getControllerTooltip())
if (MWBase::Environment::get().getWindowManager()->getControllerTooltipVisible())
MWBase::Environment::get().getInputManager()->warpMouseToWidget(mSpellButtons[mControllerFocus].first);
}

View File

@ -850,7 +850,7 @@ namespace MWGui
if (mAvailableButtons.size() > 0)
{
mAvailableButtons[0]->setStateSelected(true);
if (MWBase::Environment::get().getWindowManager()->getControllerTooltip())
if (MWBase::Environment::get().getWindowManager()->getControllerTooltipVisible())
MWBase::Environment::get().getInputManager()->warpMouseToWidget(mAvailableButtons[0]);
}
}
@ -1058,7 +1058,7 @@ namespace MWGui
else if (arg.button == SDL_CONTROLLER_BUTTON_RIGHTSTICK)
{
// Toggle info tooltip
winMgr->setControllerTooltip(!mRightColumn && !winMgr->getControllerTooltip());
winMgr->setControllerTooltipVisible(!mRightColumn && !winMgr->getControllerTooltipVisible());
}
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
{
@ -1102,7 +1102,7 @@ namespace MWGui
if (mAvailableFocus >= 0 && mAvailableFocus < static_cast<int>(mAvailableButtons.size()))
mAvailableButtons[mAvailableFocus]->setStateSelected(true);
winMgr->setControllerTooltip(Settings::gui().mControllerTooltips);
winMgr->setControllerTooltipVisible(Settings::gui().mControllerTooltips);
}
else if (arg.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT && !mRightColumn && mEffectButtons.size() > 0)
{
@ -1112,7 +1112,7 @@ namespace MWGui
if (mEffectFocus >= 0 && mEffectFocus < static_cast<int>(mEffectButtons.size()))
mEffectButtons[mEffectFocus].first->setStateSelected(true);
winMgr->setControllerTooltip(false);
winMgr->setControllerTooltipVisible(false);
}
else
return true;
@ -1129,7 +1129,7 @@ namespace MWGui
if (!mRightColumn && mAvailableFocus >= 0 && mAvailableFocus < static_cast<int>(mAvailableButtons.size()))
{
// Warp the mouse to the selected spell to show the tooltip
if (winMgr->getControllerTooltip())
if (winMgr->getControllerTooltipVisible())
MWBase::Environment::get().getInputManager()->warpMouseToWidget(mAvailableButtons[mAvailableFocus]);
}

View File

@ -350,6 +350,7 @@ namespace MWGui
return;
int prevFocus = mControllerFocus;
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
switch (button)
{
@ -363,19 +364,30 @@ namespace MWGui
break;
case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
// Toggle info tooltip
MWBase::Environment::get().getWindowManager()->setControllerTooltip(
!MWBase::Environment::get().getWindowManager()->getControllerTooltip());
winMgr->setControllerTooltipEnabled(!winMgr->getControllerTooltipEnabled());
break;
case SDL_CONTROLLER_BUTTON_DPAD_UP:
// Restore tooltip visibility if user has them enabled but they were hidden by mouse
if (winMgr->getControllerTooltipEnabled() && !winMgr->getControllerTooltipVisible())
winMgr->setControllerTooltipVisible(true);
mControllerFocus--;
break;
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
// Restore tooltip visibility if user has them enabled but they were hidden by mouse
if (winMgr->getControllerTooltipEnabled() && !winMgr->getControllerTooltipVisible())
winMgr->setControllerTooltipVisible(true);
mControllerFocus++;
break;
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
// Restore tooltip visibility if user has them enabled but they were hidden by mouse
if (winMgr->getControllerTooltipEnabled() && !winMgr->getControllerTooltipVisible())
winMgr->setControllerTooltipVisible(true);
mControllerFocus = std::max(0, mControllerFocus - 10);
break;
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
// Restore tooltip visibility if user has them enabled but they were hidden by mouse
if (winMgr->getControllerTooltipEnabled() && !winMgr->getControllerTooltipVisible())
winMgr->setControllerTooltipVisible(true);
mControllerFocus = std::min(mControllerFocus + 10, static_cast<int>(mButtons.size()) - 1);
break;
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
@ -451,7 +463,12 @@ namespace MWGui
mScrollView->setViewOffset(MyGUI::IntPoint(0, -lineHeight * (line - 5)));
}
if (MWBase::Environment::get().getWindowManager()->getControllerTooltip())
// Restore tooltip visibility if user has them enabled but they were hidden by mouse movement
MWBase::WindowManager* winMgr = MWBase::Environment::get().getWindowManager();
if (winMgr->getControllerTooltipEnabled() && !winMgr->getControllerTooltipVisible())
winMgr->setControllerTooltipVisible(true);
if (winMgr->getControllerTooltipVisible())
MWBase::Environment::get().getInputManager()->warpMouseToWidget(focused);
}
}

View File

@ -328,7 +328,7 @@ namespace MWGui
MyGUI::Window* window = mMainWidget->castType<MyGUI::Window>();
window->setCoord(x, active ? y : viewSize.height + 1, width, height);
MWBase::Environment::get().getWindowManager()->setControllerTooltip(
MWBase::Environment::get().getWindowManager()->setControllerTooltipVisible(
active && Settings::gui().mControllerTooltips);
}

View File

@ -95,7 +95,7 @@ namespace MWGui
if (guiMode)
{
if (!winMgr->getCursorVisible() && !winMgr->getControllerTooltip())
if (!winMgr->getCursorVisible() && !winMgr->getControllerTooltipVisible())
return;
const MyGUI::IntPoint& mousePos = MyGUI::InputManager::getInstance().getMousePosition();

View File

@ -520,7 +520,7 @@ namespace MWGui
mInventoryTabsOverlay = inventoryTabsOverlay.get();
mWindows.push_back(std::move(inventoryTabsOverlay));
mControllerTooltipUserPreference = Settings::gui().mControllerTooltips;
mControllerTooltipEnabled = Settings::gui().mControllerTooltips;
mActiveControllerWindows[GM_Inventory] = 1; // Start on Inventory page
mInputBlocker = MyGUI::Gui::getInstance().createWidget<MyGUI::Widget>(
@ -1498,7 +1498,7 @@ namespace MWGui
if (Settings::gui().mControllerMenus)
{
if (mGuiModes.empty())
setControllerTooltip(false);
setControllerTooltipVisible(false);
else
reapplyActiveControllerWindow();
}
@ -2642,21 +2642,22 @@ namespace MWGui
return height;
}
void WindowManager::setControllerTooltip(bool enabled)
void WindowManager::setControllerTooltipVisible(bool visible)
{
if (!Settings::gui().mControllerMenus)
return;
mControllerTooltip = enabled;
mControllerTooltipVisible = visible;
}
void WindowManager::setControllerTooltipUserPreference(bool enabled)
void WindowManager::setControllerTooltipEnabled(bool enabled)
{
if (!Settings::gui().mControllerMenus)
return;
mControllerTooltipUserPreference = enabled;
mControllerTooltip = enabled;
mControllerTooltipEnabled = enabled;
// When user toggles the setting, also update visibility
mControllerTooltipVisible = enabled;
}
void WindowManager::updateControllerButtonsOverlay()

View File

@ -395,10 +395,10 @@ namespace MWGui
int getControllerMenuHeight() override;
void cycleActiveControllerWindow(bool next) override;
void setActiveControllerWindow(GuiMode mode, int activeIndex) override;
bool getControllerTooltip() const override { return mControllerTooltip; }
void setControllerTooltip(bool enabled) override;
bool getControllerTooltipUserPreference() const override { return mControllerTooltipUserPreference; }
void setControllerTooltipUserPreference(bool enabled) override;
bool getControllerTooltipVisible() const override { return mControllerTooltipVisible; }
void setControllerTooltipVisible(bool visible) override;
bool getControllerTooltipEnabled() const override { return mControllerTooltipEnabled; }
void setControllerTooltipEnabled(bool enabled) override;
void updateControllerButtonsOverlay() override;
// Used in Lua bindings
@ -513,10 +513,10 @@ namespace MWGui
std::vector<GuiMode> mGuiModes;
// The active window for controller mode for each GUI mode.
std::map<GuiMode, int> mActiveControllerWindows;
// Current tooltip state (can be disabled by mouse movement)
bool mControllerTooltip = false;
// Toggleable preference. Restores tooltips on controller input after pointer movement
bool mControllerTooltipUserPreference = false;
// Current tooltip visibility state (can be disabled by mouse movement)
bool mControllerTooltipVisible = false;
// User preference for tooltips (persists across mouse/controller switches)
bool mControllerTooltipEnabled = false;
void reapplyActiveControllerWindow();

View File

@ -259,7 +259,7 @@ namespace MWInput
{
// When the inventory tooltip is visible, we don't actually want the A button to
// act like a mouse button; it should act normally.
if (treatAsMouse && arg.button == SDL_CONTROLLER_BUTTON_A && winMgr->getControllerTooltip())
if (treatAsMouse && arg.button == SDL_CONTROLLER_BUTTON_A && winMgr->getControllerTooltipVisible())
treatAsMouse = false;
mGamepadGuiCursorEnabled = topWin->isGamepadCursorAllowed();
@ -368,9 +368,9 @@ namespace MWInput
&& (arg.axis == SDL_CONTROLLER_AXIS_LEFTX || arg.axis == SDL_CONTROLLER_AXIS_LEFTY))
{
// Treat the left stick like a cursor, which is the default behavior.
if (winMgr->getControllerTooltip())
if (winMgr->getControllerTooltipVisible())
{
winMgr->setControllerTooltip(false);
winMgr->setControllerTooltipVisible(false);
winMgr->setCursorVisible(true);
}
else if (mGamepadGuiCursorEnabled)

View File

@ -32,6 +32,8 @@ namespace MWInput
, mMouseWheel(0)
, mMouseLookEnabled(false)
, mGuiCursorEnabled(true)
, mLastWarpX(-1)
, mLastWarpY(-1)
, mMouseMoveX(0)
, mMouseMoveY(0)
{
@ -72,13 +74,23 @@ namespace MWInput
static_cast<int>(mGuiCursorX), static_cast<int>(mGuiCursorY), mMouseWheel);
winMgr->setCursorActive(true);
// Check if this movement is from our recent mouse warp
bool isFromWarp = (mLastWarpX >= 0 && mLastWarpY >= 0
&& std::abs(mGuiCursorX - mLastWarpX) < 0.5f
&& std::abs(mGuiCursorY - mLastWarpY) < 0.5f);
if (Settings::gui().mControllerMenus && !winMgr->getCursorVisible()
&& (std::abs(arg.xrel) > 1 || std::abs(arg.yrel) > 1))
&& (std::abs(arg.xrel) > 1 || std::abs(arg.yrel) > 1) && !isFromWarp)
{
// Unhide the cursor if it was hidden to show a controller tooltip.
winMgr->setControllerTooltip(false);
winMgr->setControllerTooltipVisible(false);
winMgr->setCursorVisible(true);
}
// Clear warp tracking after processing
mLastWarpX = -1;
mLastWarpY = -1;
}
if (mMouseLookEnabled && !input->controlsDisabled())
@ -280,6 +292,9 @@ namespace MWInput
{
mGuiCursorX = widgetX;
mGuiCursorY = widgetY;
// Remember where we warped to so we can ignore movement from this warp
mLastWarpX = widgetX;
mLastWarpY = widgetY;
warpMouse();
}
}

View File

@ -49,6 +49,8 @@ namespace MWInput
int mMouseWheel;
bool mMouseLookEnabled;
bool mGuiCursorEnabled;
float mLastWarpX;
float mLastWarpY;
int mMouseMoveX;
int mMouseMoveY;