[vlc-commits] [Git][videolan/vlc][master] 8 commits: qt: introduce `PointingToolTipAttached`
Steve Lhomme (@robUx4)
gitlab at videolan.org
Thu Jul 16 16:58:34 UTC 2026
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
9869b724 by Fatih Uzunoglu at 2026-07-16T16:26:14+00:00
qt: introduce `PointingToolTipAttached`
Akin to `QQuickToolTipAttached`
- - - - -
ad2f05ea by Fatih Uzunoglu at 2026-07-16T16:26:14+00:00
qt: register `PointingToolTipAttached` as qml type
- - - - -
4b81481d by Fatih Uzunoglu at 2026-07-16T16:26:14+00:00
qml: set attached pointing tool tip instance in `MainInterface`
This is the same we are doing with attached regular tool tip.
- - - - -
55301b4e by Fatih Uzunoglu at 2026-07-16T16:26:14+00:00
qml: use attached pointing tool tip in `SliderExt`
- - - - -
82e5dafd by Fatih Uzunoglu at 2026-07-16T16:26:14+00:00
qml: use attached pointing tool tip in `SliderBar`
- - - - -
4cfb3a69 by Fatih Uzunoglu at 2026-07-16T16:26:14+00:00
qml: use attached pointing tool tip in `Bookmarks`
- - - - -
0ef901ca by Fatih Uzunoglu at 2026-07-16T16:26:14+00:00
qml: add note regarding window type in `ToolTipExt`
- - - - -
51d56322 by Fatih Uzunoglu at 2026-07-16T16:26:14+00:00
qml: add note regarding window type in `PointingTooltip`
- - - - -
11 changed files:
- modules/gui/qt/Makefile.am
- modules/gui/qt/maininterface/mainui.cpp
- modules/gui/qt/maininterface/qml/MainInterface.qml
- modules/gui/qt/medialibrary/qml/Bookmarks.qml
- modules/gui/qt/meson.build
- modules/gui/qt/player/qml/SliderBar.qml
- modules/gui/qt/player/qml/controlbarcontrols/VolumeWidget.qml
- + modules/gui/qt/util/pointingtooltipattached.hpp
- modules/gui/qt/widgets/qml/PointingTooltip.qml
- modules/gui/qt/widgets/qml/SliderExt.qml
- modules/gui/qt/widgets/qml/ToolTipExt.qml
Changes:
=====================================
modules/gui/qt/Makefile.am
=====================================
@@ -365,6 +365,7 @@ libqt_plugin_la_SOURCES = \
util/textureproviderindirection.hpp \
util/sgmanipulator.cpp \
util/sgmanipulator.hpp \
+ util/pointingtooltipattached.hpp \
widgets/native/animators.cpp \
widgets/native/animators.hpp \
widgets/native/customwidgets.cpp widgets/native/customwidgets.hpp \
@@ -527,6 +528,7 @@ nodist_libqt_plugin_la_SOURCES = \
util/kirigamiwheelhandler.moc.cpp \
util/textureproviderindirection.moc.cpp \
util/sgmanipulator.moc.cpp \
+ util/pointingtooltipattached.moc.cpp \
widgets/native/animators.moc.cpp \
widgets/native/csdthemeimage.moc.cpp \
widgets/native/customwidgets.moc.cpp \
=====================================
modules/gui/qt/maininterface/mainui.cpp
=====================================
@@ -55,6 +55,7 @@
#include "util/textureproviderobserver.hpp"
#include "util/textureproviderindirection.hpp"
#include "util/sgmanipulator.hpp"
+#include "util/pointingtooltipattached.hpp"
#include "dialogs/help/aboutmodel.hpp"
#include "dialogs/dialogs_provider.hpp"
@@ -433,6 +434,7 @@ void MainUI::registerQMLTypes()
// @uri VLC.Widgets
qmlRegisterType<CSDThemeImage>(uri, versionMajor, versionMinor, "CSDThemeImage");
qmlRegisterType<ViewBlockingRectangle>( uri, versionMajor, versionMinor, "ViewBlockingRectangle" );
+ qmlRegisterTypesAndRevisions<PointingToolTipAttached>( uri, versionMajor );
qmlRegisterModule(uri, versionMajor, versionMinor);
qmlProtectModule(uri, versionMajor);
=====================================
modules/gui/qt/maininterface/qml/MainInterface.qml
=====================================
@@ -217,6 +217,21 @@ Item {
}
}
+ Widgets.PointingTooltip {
+ parent: null
+ z: 99
+
+ colorContext.palette: parent && parent.colorContext ? parent.colorContext.palette
+ : VLCStyle.palette
+
+ Widgets.PointingToolTipAttached.instance: this
+
+ Component.onDestruction: {
+ console.assert(Widgets.PointingToolTipAttached.instance === this)
+ Widgets.PointingToolTipAttached.instance = null
+ }
+ }
+
Loader {
id: playlistWindowLoader
asynchronous: true
=====================================
modules/gui/qt/medialibrary/qml/Bookmarks.qml
=====================================
@@ -42,16 +42,9 @@ Item {
visible: false
opacity: 0
- Widgets.PointingTooltip {
- id: timeTooltip
-
- //tooltip is a Popup, palette should be passed explicitly
- colorContext.palette: theme.palette
-
- visible: control.bookmarkHovered
- text: control.bookmarkText
- pos: Qt.point(control.bookmarkPosition, - yShift)
- }
+ Widgets.PointingToolTipAttached.visible: control.bookmarkHovered
+ Widgets.PointingToolTipAttached.text: control.bookmarkText
+ Widgets.PointingToolTipAttached.pos: Qt.point(control.bookmarkPosition, - yShift)
transitions: [
Transition {
=====================================
modules/gui/qt/meson.build
=====================================
@@ -158,6 +158,7 @@ moc_headers = files(
'util/kirigamiwheelhandler.hpp',
'util/textureproviderindirection.hpp',
'util/sgmanipulator.hpp',
+ 'util/pointingtooltipattached.hpp',
'widgets/native/animators.hpp',
'widgets/native/csdthemeimage.hpp',
'widgets/native/customwidgets.hpp',
@@ -513,6 +514,7 @@ qt_plugin_sources = files(
'util/textureproviderindirection.hpp',
'util/sgmanipulator.cpp',
'util/sgmanipulator.hpp',
+ 'util/pointingtooltipattached.hpp',
'widgets/native/animators.cpp',
'widgets/native/animators.hpp',
'widgets/native/customwidgets.cpp',
=====================================
modules/gui/qt/player/qml/SliderBar.qml
=====================================
@@ -40,7 +40,7 @@ T.ProgressBar {
readonly property real _scaledSeekPointsRadius: _seekPointsRadius * _hoveredScalingFactor
property bool _currentChapterHovered: false
- property real _tooltipPosition: timeTooltip.pos.x / width
+ property real _tooltipPosition: (Widgets.PointingToolTipAttached.instance?.pos.x ?? 0.0) / width
property color backgroundColor: theme.bg.primary
property real touchHandlerMargin: VLCStyle.touchHandlerMargin
@@ -72,35 +72,31 @@ T.ProgressBar {
onTriggered: control._isSeekPointsShown = false
}
- Widgets.PointingTooltip {
- id: timeTooltip
+ Widgets.PointingToolTipAttached.visible: (hoverHandler.hovered || control.visualFocus || dragHandler.active)
- //tooltip is a Popup, palette should be passed explicitly
- colorContext.palette: theme.palette
+ Widgets.PointingToolTipAttached.text: {
+ if (!Widgets.PointingToolTipAttached.instance?.visible)
+ return ""
- visible: hoverHandler.hovered || control.visualFocus || dragHandler.active
+ let _text
- text: {
- let _text
+ const length = Player.length
+ if (hoverHandler.hovered)
+ _text = length.scale(Widgets.PointingToolTipAttached.instance.pos.x / control.width)
+ else
+ _text = Player.time
- const length = Player.length
- if (hoverHandler.hovered)
- _text = length.scale(pos.x / control.width)
- else
- _text = Player.time
+ _text = _text.formatHMS(length.isSubSecond() ? VLCTick.SubSecondFormattedAsMS : 0)
- _text = _text.formatHMS(length.isSubSecond() ? VLCTick.SubSecondFormattedAsMS : 0)
+ if (Player.hasChapters)
+ _text += " - " + Player.chapters.getNameAtPosition(control._tooltipPosition)
- if (Player.hasChapters)
- _text += " - " + Player.chapters.getNameAtPosition(control._tooltipPosition)
-
- return _text
- }
-
- pos: Qt.point(hoverHandler.hovered ? Helpers.clamp(hoverHandler.point.position.x, 0, control.availableWidth)
- : (control.visualPosition * control.width), 0)
+ return _text
}
+ Widgets.PointingToolTipAttached.pos: Qt.point(hoverHandler.hovered ? Helpers.clamp(hoverHandler.point.position.x, 0, control.availableWidth)
+ : (control.visualPosition * control.width), 0)
+
FSM {
id: fsm
signal playerUpdatePosition(real position)
=====================================
modules/gui/qt/player/qml/controlbarcontrols/VolumeWidget.qml
=====================================
@@ -196,7 +196,7 @@ T.Pane {
function onVolumeChanged() { volControl._syncVolumeWithPlayer() }
}
- Binding on toolTip.visible {
+ Binding on Widgets.PointingToolTipAttached.visible {
when: sliderMouseArea.pressed
value: true
}
=====================================
modules/gui/qt/util/pointingtooltipattached.hpp
=====================================
@@ -0,0 +1,184 @@
+/*****************************************************************************
+ * Copyright (C) 2026 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#ifndef POINTINGTOOLTIPATTACHED_HPP
+#define POINTINGTOOLTIPATTACHED_HPP
+
+#include <QQmlProperty>
+#include <QPointF>
+#include <QQuickItem>
+#include <QString>
+#include <QtQml>
+
+class PointingToolTipAttached : public QObject
+{
+ Q_OBJECT
+
+ // Note that instance is static:
+ Q_PROPERTY(QObject* instance MEMBER m_instance NOTIFY instanceChanged FINAL)
+
+ // Note that these properties are not bidirectionally synchronized. If you
+ // want to get the actual values that the tool tip uses, access it through
+ // the `instance` property:
+ Q_PROPERTY(QPointF pos MEMBER m_pos WRITE setPos NOTIFY posChanged FINAL)
+ Q_PROPERTY(bool visible MEMBER m_visible WRITE setVisible NOTIFY visibleChanged FINAL)
+ Q_PROPERTY(QString text MEMBER m_text WRITE setText NOTIFY textChanged FINAL)
+
+ // The name `PointingToolTip` is not used to not conflict with the already existing type.
+ QML_NAMED_ELEMENT(PointingToolTipAttached)
+ QML_UNCREATABLE("PointingToolTipAttached is meant to be used as attached.")
+ QML_ATTACHED(PointingToolTipAttached)
+
+public:
+ explicit PointingToolTipAttached(QObject *parent = nullptr)
+ : QObject(parent)
+ {
+ // This is an unlikely case, but we can still handle it:
+ connect(this, &PointingToolTipAttached::instanceChanged, this, [this]() {
+ m_posProperty.reset();
+ m_visibleProperty.reset();
+ m_textProperty.reset();
+ m_parentProperty.reset();
+
+ if (m_instance)
+ {
+ setPos(m_pos);
+ setText(m_text);
+ setVisible(m_visible);
+ }
+ });
+ }
+
+ static PointingToolTipAttached *qmlAttachedProperties(QObject* parent)
+ {
+ return new PointingToolTipAttached(parent);
+ }
+
+ void setPos(const QPointF& point)
+ {
+ if (m_pos != point)
+ {
+ m_pos = point;
+ emit posChanged();
+ }
+
+ if (instanceBoundToParent())
+ {
+ if (!m_posProperty)
+ m_posProperty = QQmlProperty(m_instance, QStringLiteral("pos"));
+
+ assert(m_posProperty->isWritable());
+
+ m_posProperty->write(point);
+ }
+ }
+
+ void setText(const QString& text)
+ {
+ if (m_text != text)
+ {
+ m_text = text;
+ emit textChanged();
+ }
+
+ if (instanceBoundToParent())
+ {
+ if (!m_textProperty)
+ m_textProperty = QQmlProperty(m_instance, QStringLiteral("text"));
+
+ assert(m_textProperty->isWritable());
+
+ m_textProperty->write(text);
+ }
+ }
+
+ // Setting visibility binds the attached tool tip to the parent of the
+ // attached tool tip:
+ void setVisible(bool visible)
+ {
+ if (m_visible != visible)
+ {
+ m_visible = visible;
+ emit visibleChanged();
+ }
+
+ assert(m_instance);
+
+ if (!m_visibleProperty)
+ m_visibleProperty = QQmlProperty(m_instance, QStringLiteral("visible"));
+
+ assert(m_visibleProperty->isWritable());
+
+ // Akin to `QQuickToolTipAttached`:
+ if (visible)
+ {
+ setPos(m_pos);
+ setText(m_text);
+
+ if (!m_parentProperty)
+ m_parentProperty = QQmlProperty(m_instance, QStringLiteral("parent"));
+
+ assert(m_parentProperty->isWritable());
+
+ m_parentProperty->write(QVariant::fromValue(qobject_cast<QQuickItem*>(parent())));
+
+ m_visibleProperty->write(true);
+ }
+ else
+ {
+ if (instanceBoundToParent())
+ m_visibleProperty->write(false);
+ }
+ }
+
+signals:
+ void instanceChanged();
+
+ void zChanged();
+ void posChanged();
+ void visibleChanged();
+ void textChanged();
+
+protected:
+ bool instanceBoundToParent() const
+ {
+ assert(m_instance);
+
+ if (!m_parentProperty)
+ m_parentProperty = QQmlProperty(m_instance, QStringLiteral("parent"));
+
+ assert(m_parentProperty->isValid());
+
+ return (m_parentProperty->read().value<QQuickItem*>() == qobject_cast<QQuickItem*>(parent()));
+ }
+
+private:
+ static inline QPointer<QObject> m_instance;
+
+ QPointF m_pos;
+ bool m_visible = false;
+ QString m_text;
+
+ std::optional<QQmlProperty> m_posProperty;
+ std::optional<QQmlProperty> m_visibleProperty;
+ std::optional<QQmlProperty> m_textProperty;
+ mutable std::optional<QQmlProperty> m_parentProperty;
+};
+
+QML_DECLARE_TYPEINFO(PointingToolTipAttached, QML_HAS_ATTACHED_PROPERTIES)
+
+#endif // POINTINGTOOLTIPATTACHED_HPP
=====================================
modules/gui/qt/widgets/qml/PointingTooltip.qml
=====================================
@@ -20,6 +20,7 @@ import QtQuick.Controls
import VLC.Style
+// NOTE: Attached pointing tool tip must be used if the popup type is `Popup.Window`.
ToolTipExt {
id: pointingTooltip
=====================================
modules/gui/qt/widgets/qml/SliderExt.qml
=====================================
@@ -21,7 +21,7 @@
import QtQuick
import QtQuick.Templates as T
-
+import VLC.Widgets as Widgets
import VLC.Style
import VLC.Util
@@ -51,8 +51,6 @@ T.Slider {
// else tooltip will always be shown at current value.
property bool toolTipFollowsMouse: false
- property alias toolTip: toolTip
-
// toolTipTextProvider -> function(value)
// arg "value" is between from and to, this is "value"
// at which pointing tool tip is currently shown
@@ -138,26 +136,17 @@ T.Slider {
target: background
}
- PointingTooltip {
- id: toolTip
-
- z: 1 // without this tooltips get placed below root's parent popup (if any)
-
- pos: Qt.point(control._tooltipX, control.handle.height / 2)
-
- visible: hoverHandler.hovered || control.visualFocus || control.pressed
-
- text: {
- if (!visible) return ""
-
- // position is only measured till half of handle width
- // pos.x may go beyond the position at the edges
- const p = Helpers.clamp(control.positionAt(pos.x), 0.0, 1.0)
- const v = control.valueAt(p)
- return control.toolTipTextProvider(v)
- }
-
- //tooltip is a Popup, palette should be passed explicitly
- colorContext.palette: theme.palette
+ Widgets.PointingToolTipAttached.pos: Qt.point(control._tooltipX, control.handle.height / 2)
+ Widgets.PointingToolTipAttached.visible: (hoverHandler.hovered || control.visualFocus || control.pressed)
+ Widgets.PointingToolTipAttached.text: {
+ if (!Widgets.PointingToolTipAttached.instance?.visible)
+ return ""
+
+ // position is only measured till half of handle width
+ // pos.x may go beyond the position at the edges
+ const p = Helpers.clamp(control.positionAt(Widgets.PointingToolTipAttached.instance.pos.x), 0.0, 1.0)
+ const v = control.valueAt(p)
+ return control.toolTipTextProvider(v)
}
+
}
=====================================
modules/gui/qt/widgets/qml/ToolTipExt.qml
=====================================
@@ -22,6 +22,7 @@ import QtQuick.Templates as T
import VLC.MainInterface
import VLC.Style
+// NOTE: Attached tool tip must be used if the popup type is `Popup.Window`.
T.ToolTip {
id: control
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/a4260c0dcfd61288552e81f36a10ade8ce5cff5f...51d563221b543ef87888a8e21aada922948929ba
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/a4260c0dcfd61288552e81f36a10ade8ce5cff5f...51d563221b543ef87888a8e21aada922948929ba
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help
More information about the vlc-commits
mailing list