dolphin/Source/Core/DolphinQt/Config/ToolTipControls/ToolTipWidget.h
Dentomologist 7b52555a5f BalloonTip: Don't hide when BalloonTip blocks the cursor
Keep the BalloonTip open when the BalloonTip's arrow prevents the cursor
from being inside the spawning ToolTipWidget, which triggers the
ToolTipWidget's leaveEvent and would previously close the BalloonTip.

When that happens track the cursor until it either leaves the
ToolTipWidget's bounding box or leaves the BalloonTip and goes back to
the ToolTipWidget, and respectively close the BalloonTip or leave it
open.
2025-08-01 12:30:05 -07:00

85 lines
2.1 KiB
C++

// Copyright 2020 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <optional>
#include <QString>
#include "DolphinQt/Config/ToolTipControls/BalloonTip.h"
class QEnterEvent;
class QEvent;
class QHideEvent;
class QTimerEvent;
constexpr int TOOLTIP_DELAY = 300;
template <class Derived>
class ToolTipWidget : public Derived
{
public:
using Derived::Derived;
void SetTitle(QString title) { m_title = std::move(title); }
void SetDescription(QString description) { m_description = std::move(description); }
private:
void enterEvent(QEnterEvent* const event) override
{
// If the timer is already running, or the cursor is reentering the ToolTipWidget after having
// hovered over the BalloonTip, don't start a new timer.
if (!m_timer_id && !BalloonTip::IsWidgetBalloonTipActive(*this))
m_timer_id = this->startTimer(TOOLTIP_DELAY);
Derived::enterEvent(event);
}
void leaveEvent(QEvent* const event) override
{
// If the cursor would still be inside the ToolTipWidget but the BalloonTip is covering that
// part of it, keep the BalloonTip open. In that case the BalloonTip will then track the cursor
// and close itself if it leaves the bounding box of this ToolTipWidget.
if (!BalloonTip::IsCursorInsideWidgetBoundingBox(*this) || !BalloonTip::IsCursorOnBalloonTip())
KillTimerAndHideBalloon();
Derived::leaveEvent(event);
}
void hideEvent(QHideEvent* const event) override
{
KillTimerAndHideBalloon();
Derived::hideEvent(event);
}
void timerEvent(QTimerEvent* const event) override
{
this->killTimer(*m_timer_id);
m_timer_id.reset();
BalloonTip::ShowBalloon(m_title, m_description,
this->parentWidget()->mapToGlobal(GetToolTipPosition()), this);
Derived::timerEvent(event);
}
virtual QPoint GetToolTipPosition() const = 0;
void KillTimerAndHideBalloon()
{
if (m_timer_id)
{
this->killTimer(*m_timer_id);
m_timer_id.reset();
}
BalloonTip::HideBalloon();
}
std::optional<int> m_timer_id;
QString m_title;
QString m_description;
};