mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-09-24 04:11:50 -04:00
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:
parent
12aef44fe1
commit
cf51812a6f
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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]);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,8 @@ namespace MWInput
|
||||
int mMouseWheel;
|
||||
bool mMouseLookEnabled;
|
||||
bool mGuiCursorEnabled;
|
||||
float mLastWarpX;
|
||||
float mLastWarpY;
|
||||
|
||||
int mMouseMoveX;
|
||||
int mMouseMoveY;
|
||||
|
Loading…
x
Reference in New Issue
Block a user