diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 36c60553..588f23af 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -251,6 +251,8 @@ set(KDDW_QTQUICK_FRONTEND_SRCS qtquick/views/View_qtquick.h qtquick/views/ViewWrapper_qtquick.cpp qtquick/views/ViewWrapper_qtquick.h + # qtquick/views/ClassicIndicatorsWindow_qtquick.cpp + # qtquick/views/ClassicIndicatorsWindow_qtquick.h kddockwidgets_qtquick.qrc ) diff --git a/src/qtquick/views/ClassicIndicatorsWindow_qtquick.cpp b/src/qtquick/views/ClassicIndicatorsWindow_qtquick.cpp index 64c5b5e9..5a6346dd 100644 --- a/src/qtquick/views/ClassicIndicatorsWindow_qtquick.cpp +++ b/src/qtquick/views/ClassicIndicatorsWindow_qtquick.cpp @@ -9,9 +9,12 @@ Contact KDAB at for commercial licensing options. */ -#include "ClassicIndicatorsWindow_p.h" +#include "ClassicIndicatorsWindow_qtquick.h" #include "controllers/indicators/ClassicIndicators.h" -#include "../Utils_p.h" +#include "private/Utils_p.h" + +#include +#include using namespace KDDockWidgets; using namespace KDDockWidgets::Controllers; @@ -62,211 +65,8 @@ static QString iconName(DropLocation loc, bool active) } } -#ifdef KDDOCKWIDGETS_QTWIDGETS -#include - -#define INDICATOR_WIDTH 40 -#define OUTTER_INDICATOR_MARGIN 10 - -void Indicator::paintEvent(QPaintEvent *) -{ - QPainter p(this); - if (m_hovered) - p.drawImage(rect(), m_imageActive, rect()); - else - p.drawImage(rect(), m_image, rect()); -} - -void Indicator::setHovered(bool hovered) -{ - if (hovered != m_hovered) { - m_hovered = hovered; - update(); - if (hovered) { - q->setDropLocation(m_dropLocation); - } else if (q->currentDropLocation() == m_dropLocation) { - q->setDropLocation(DropLocation_None); - } - } -} - -QString Indicator::iconName(bool active) const -{ - return KDDockWidgets::iconName(m_dropLocation, active); -} - -QString Indicator::iconFileName(bool active) const -{ - const QString name = iconName(active); - return KDDockWidgets::windowManagerHasTranslucency() ? QStringLiteral(":/img/classic_indicators/%1.png").arg(name) - : QStringLiteral(":/img/classic_indicators/opaque/%1.png").arg(name); -} - -static QWidget *parentForIndicatorWindow(ClassicIndicators *classicIndicators_) -{ - // On Wayland it can't be a top-level, as we have no way of positioning it - - return isWayland() ? qobject_cast(classicIndicators_->view()->asQObject()) - : nullptr; -} - -static Qt::WindowFlags flagsForIndicatorWindow() -{ - return isWayland() ? Qt::Widget - : (Qt::Tool | Qt::BypassWindowManagerHint); -} - -IndicatorWindow::IndicatorWindow(ClassicIndicators *classicIndicators_) - : QWidget(parentForIndicatorWindow(classicIndicators_), flagsForIndicatorWindow()) - , classicIndicators(classicIndicators_) - , m_center(new Indicator(classicIndicators, this, DropLocation_Center)) // Each indicator is not a top-level. Otherwise there's noticeable delay. - , m_left(new Indicator(classicIndicators, this, DropLocation_Left)) - , m_right(new Indicator(classicIndicators, this, DropLocation_Right)) - , m_bottom(new Indicator(classicIndicators, this, DropLocation_Bottom)) - , m_top(new Indicator(classicIndicators, this, DropLocation_Top)) - , m_outterLeft(new Indicator(classicIndicators, this, DropLocation_OutterLeft)) - , m_outterRight(new Indicator(classicIndicators, this, DropLocation_OutterRight)) - , m_outterBottom(new Indicator(classicIndicators, this, DropLocation_OutterBottom)) - , m_outterTop(new Indicator(classicIndicators, this, DropLocation_OutterTop)) -{ - setWindowFlag(Qt::FramelessWindowHint, true); - - if (Config::self().flags() & Config::Flag_KeepAboveIfNotUtilityWindow) { - // Ensure the overlay window is on top - setWindowFlag(Qt::WindowStaysOnTopHint, true); - } - - setAttribute(Qt::WA_TranslucentBackground); - - connect(classicIndicators, &ClassicIndicators::indicatorsVisibleChanged, - this, &IndicatorWindow::updateIndicatorVisibility); - connect(classicIndicators, &ClassicIndicators::indicatorsVisibleChanged, - this, &IndicatorWindow::updateIndicatorVisibility); - - m_indicators << m_center << m_left << m_right << m_top << m_bottom - << m_outterBottom << m_outterTop << m_outterLeft << m_outterRight; -} - -Indicator *IndicatorWindow::indicatorForLocation(DropLocation loc) const -{ - switch (loc) { - case DropLocation_Center: - return m_center; - case DropLocation_Left: - return m_left; - case DropLocation_Right: - return m_right; - case DropLocation_Bottom: - return m_bottom; - case DropLocation_Top: - return m_top; - case DropLocation_OutterLeft: - return m_outterLeft; - case DropLocation_OutterBottom: - return m_outterBottom; - case DropLocation_OutterRight: - return m_outterRight; - case DropLocation_OutterTop: - return m_outterTop; - case DropLocation_None: - case DropLocation_Outter: - case DropLocation_Inner: - return nullptr; - } - - return nullptr; -} - -void IndicatorWindow::updateMask() -{ - QRegion region; - - if (!KDDockWidgets::windowManagerHasTranslucency()) { - for (Indicator *indicator : qAsConst(m_indicators)) { - if (indicator->isVisible()) - region = region.united(QRegion(indicator->geometry(), QRegion::Rectangle)); - } - } - - setMask(region); -} - -void IndicatorWindow::resizeEvent(QResizeEvent *ev) -{ - QWidget::resizeEvent(ev); - updatePositions(); -} - -void IndicatorWindow::updateIndicatorVisibility() -{ - for (Indicator *indicator : { m_left, m_right, m_bottom, m_top, - m_outterTop, m_outterLeft, m_outterRight, m_outterBottom, - m_center }) - indicator->setVisible(classicIndicators->dropIndicatorVisible(indicator->m_dropLocation)); - - updateMask(); -} - -QPoint IndicatorWindow::posForIndicator(DropLocation loc) const -{ - Indicator *indicator = indicatorForLocation(loc); - return indicator->mapToGlobal(indicator->rect().center()); -} - -DropLocation IndicatorWindow::hover(QPoint globalPos) -{ - DropLocation loc = DropLocation_None; - - for (Indicator *indicator : qAsConst(m_indicators)) { - if (indicator->isVisible()) { - const bool hovered = indicator->rect().contains(indicator->mapFromGlobal(globalPos)); - indicator->setHovered(hovered); - if (hovered) - loc = indicator->m_dropLocation; - } - } - - return loc; -} - -void IndicatorWindow::updatePositions() -{ - QRect r = rect(); - const int indicatorWidth = m_outterBottom->width(); - const int halfIndicatorWidth = m_outterBottom->width() / 2; - - m_outterLeft->move(r.x() + OUTTER_INDICATOR_MARGIN, r.center().y() - halfIndicatorWidth); - m_outterBottom->move(r.center().x() - halfIndicatorWidth, r.y() + height() - indicatorWidth - OUTTER_INDICATOR_MARGIN); - m_outterTop->move(r.center().x() - halfIndicatorWidth, r.y() + OUTTER_INDICATOR_MARGIN); - m_outterRight->move(r.x() + width() - indicatorWidth - OUTTER_INDICATOR_MARGIN, r.center().y() - halfIndicatorWidth); - Controllers::Frame *hoveredFrame = classicIndicators->m_hoveredFrame; - if (hoveredFrame) { - QRect hoveredRect = hoveredFrame->view()->geometry(); - m_center->move(r.topLeft() + hoveredRect.center() - QPoint(halfIndicatorWidth, halfIndicatorWidth)); - m_top->move(m_center->pos() - QPoint(0, indicatorWidth + OUTTER_INDICATOR_MARGIN)); - m_right->move(m_center->pos() + QPoint(indicatorWidth + OUTTER_INDICATOR_MARGIN, 0)); - m_bottom->move(m_center->pos() + QPoint(0, indicatorWidth + OUTTER_INDICATOR_MARGIN)); - m_left->move(m_center->pos() - QPoint(indicatorWidth + OUTTER_INDICATOR_MARGIN, 0)); - } -} - -Indicator::Indicator(ClassicIndicators *classicIndicators, IndicatorWindow *parent, DropLocation location) - : QWidget(parent) - , q(classicIndicators) - , m_dropLocation(location) -{ - m_image = QImage(iconFileName(/*active=*/false)).scaled(INDICATOR_WIDTH, INDICATOR_WIDTH); - m_imageActive = QImage(iconFileName(/*active=*/true)).scaled(INDICATOR_WIDTH, INDICATOR_WIDTH); - setFixedSize(m_image.size()); - setVisible(true); -} - -#else - -#include - -IndicatorWindow::IndicatorWindow(KDDockWidgets::ClassicIndicators *classicIndicators) +IndicatorWindow::IndicatorWindow(Controllers::ClassicIndicators *classicIndicators) : QQuickView() , m_classicIndicators(classicIndicators) { @@ -386,5 +186,3 @@ QVector IndicatorWindow::indicatorItems() const return indicators; } - -#endif // QtQuick diff --git a/src/qtquick/views/ClassicIndicatorsWindow_qtquick.h b/src/qtquick/views/ClassicIndicatorsWindow_qtquick.h index 439e7104..ed5f21d4 100644 --- a/src/qtquick/views/ClassicIndicatorsWindow_qtquick.h +++ b/src/qtquick/views/ClassicIndicatorsWindow_qtquick.h @@ -9,107 +9,40 @@ Contact KDAB at for commercial licensing options. */ -#ifndef KD_INDICATORS_CLASSICINDICATORS_WINDOW_P_H -#define KD_INDICATORS_CLASSICINDICATORS_WINDOW_P_H +#ifndef KD_CLASSICINDICATORS_WINDOW_QTQUICK_H +#define KD_CLASSICINDICATORS_WINDOW_QTQUICK_H +#pragma once #include "controllers/DropIndicatorOverlay.h" #include "controllers/indicators/ClassicIndicators.h" -#ifdef KDDOCKWIDGETS_QTWIDGETS - -#include -#include -#include +#include namespace KDDockWidgets { -class Indicator; - namespace Controllers { class ClassicIndicators; } -class IndicatorWindow : public QWidget -{ - Q_OBJECT -public: - explicit IndicatorWindow(Controllers::ClassicIndicators *classicIndicators); - DropLocation hover(QPoint globalPos); - void updatePositions(); - QPoint posForIndicator(DropLocation) const; - -private: - void updateIndicatorVisibility(); - void resizeEvent(QResizeEvent *ev) override; - - // When the compositor doesn't support translucency, we use a mask instead - // Only happens on Linux - void updateMask(); - - Indicator *indicatorForLocation(DropLocation loc) const; - - Controllers::ClassicIndicators *const classicIndicators; - Indicator *const m_center; - Indicator *const m_left; - Indicator *const m_right; - Indicator *const m_bottom; - Indicator *const m_top; - Indicator *const m_outterLeft; - Indicator *const m_outterRight; - Indicator *const m_outterBottom; - Indicator *const m_outterTop; - QVector m_indicators; -}; - -class Indicator : public QWidget -{ - Q_OBJECT -public: - typedef QList List; - explicit Indicator(Controllers::ClassicIndicators *classicIndicators, IndicatorWindow *parent, - DropLocation location); - void paintEvent(QPaintEvent *) override; - - void setHovered(bool hovered); - QString iconName(bool active) const; - QString iconFileName(bool active) const; - - QImage m_image; - QImage m_imageActive; - Controllers::ClassicIndicators *const q; - bool m_hovered = false; - const DropLocation m_dropLocation; -}; -} - -#else - -#include - -namespace KDDockWidgets { -class ClassicIndicators; - class IndicatorWindow : public QQuickView { Q_OBJECT - Q_PROPERTY(KDDockWidgets::ClassicIndicators *classicIndicators READ classicIndicators CONSTANT) + Q_PROPERTY(KDDockWidgets::Controllers::ClassicIndicators *classicIndicators READ classicIndicators CONSTANT) public: - explicit IndicatorWindow(ClassicIndicators *); + explicit IndicatorWindow(Controllers::ClassicIndicators *); DropLocation hover(QPoint); void updatePositions(); QPoint posForIndicator(DropLocation) const; Q_INVOKABLE QString iconName(int loc, bool active) const; - KDDockWidgets::ClassicIndicators *classicIndicators() const; + Controllers::ClassicIndicators *classicIndicators() const; QQuickItem *indicatorForLocation(DropLocation loc) const; private: DropLocation locationForIndicator(const QQuickItem *) const; QQuickItem *indicatorForPos(QPoint) const; QVector indicatorItems() const; - ClassicIndicators *const m_classicIndicators; + Controllers::ClassicIndicators *const m_classicIndicators; }; } #endif - -#endif diff --git a/src/qtwidgets/views/ClassicIndicatorsWindow_qtwidgets.cpp b/src/qtwidgets/views/ClassicIndicatorsWindow_qtwidgets.cpp index a65aac7c..9725bc19 100644 --- a/src/qtwidgets/views/ClassicIndicatorsWindow_qtwidgets.cpp +++ b/src/qtwidgets/views/ClassicIndicatorsWindow_qtwidgets.cpp @@ -62,8 +62,6 @@ static QString iconName(DropLocation loc, bool active) } } -#ifdef KDDOCKWIDGETS_QTWIDGETS - #include #define INDICATOR_WIDTH 40 @@ -261,130 +259,3 @@ Indicator::Indicator(ClassicIndicators *classicIndicators, IndicatorWindow *pare setFixedSize(m_image.size()); setVisible(true); } - -#else - -#include - -IndicatorWindow::IndicatorWindow(KDDockWidgets::ClassicIndicators *classicIndicators) - : QQuickView() - , m_classicIndicators(classicIndicators) -{ - setFlags(flags() | Qt::FramelessWindowHint | Qt::BypassWindowManagerHint | Qt::Tool); - setColor(Qt::transparent); - - rootContext()->setContextProperty(QStringLiteral("_window"), QVariant::fromValue(this)); - setSource(QUrl(QStringLiteral("qrc:/kddockwidgets/qtquick/views/qml/ClassicIndicatorsOverlay.qml"))); - - - // Two workarounds for two unrelated bugs: - if (KDDockWidgets::isOffscreen()) { - // 1. We need to create the window asap, otherwise, if a drag triggers the indicator window - // to show, that creates a QOffscreenWindow, which flushes events in the ctor, triggering - // more hover events which will trigger another QOffscreenWindow. - // We then end up with a QWindow with two QPlatformWindow, and only one is deleted in - // at shutdown, meaning some timers aren't unregistered, meaning we get a crash when - // the timer event is sent to the destroyed QWindow. - create(); - } else { - // 2. - // Small hack to avoid flickering when we drag over a window the first time - // Not sure why a simply create() doesn't work instead - // Not if offscreen though, as that QPA is flaky with window activation/focus - resize(QSize(1, 1)); - show(); - hide(); - } -} - -DropLocation IndicatorWindow::hover(QPoint pt) -{ - QQuickItem *item = indicatorForPos(pt); - const DropLocation loc = item ? locationForIndicator(item) - : DropLocation_None; - classicIndicators()->setDropLocation(loc); - return loc; -} - -QQuickItem *IndicatorWindow::indicatorForPos(QPoint pt) const -{ - const QVector indicators = indicatorItems(); - Q_ASSERT(indicators.size() == 9); - - for (QQuickItem *item : indicators) { - if (item->isVisible()) { - QRect rect(0, 0, int(item->width()), int(item->height())); - rect.moveTopLeft(item->mapToGlobal(QPointF(0, 0)).toPoint()); - if (rect.contains(pt)) { - return item; - } - } - } - - return nullptr; -} - -void IndicatorWindow::updatePositions() -{ - // Not needed to implement, the Indicators use QML anchors -} - -QPoint IndicatorWindow::posForIndicator(KDDockWidgets::DropLocation loc) const -{ - QQuickItem *indicator = IndicatorWindow::indicatorForLocation(loc); - return indicator->mapToGlobal(indicator->boundingRect().center()).toPoint(); -} - -QString IndicatorWindow::iconName(int loc, bool active) const -{ - return KDDockWidgets::iconName(DropLocation(loc), active); -} - -ClassicIndicators *IndicatorWindow::classicIndicators() const -{ - return m_classicIndicators; -} - -QQuickItem *IndicatorWindow::indicatorForLocation(DropLocation loc) const -{ - const QVector indicators = indicatorItems(); - Q_ASSERT(indicators.size() == 9); - - for (QQuickItem *item : indicators) { - if (locationForIndicator(item) == loc) - return item; - } - - qWarning() << Q_FUNC_INFO << "Couldn't find indicator for location" << loc; - return nullptr; -} - -DropLocation IndicatorWindow::locationForIndicator(const QQuickItem *item) const -{ - return DropLocation(item->property("indicatorType").toInt()); -} - -QVector IndicatorWindow::indicatorItems() const -{ - QVector indicators; - indicators.reserve(9); - - QQuickItem *root = rootObject(); - const QList items = root->childItems(); - for (QQuickItem *item : items) { - if (QString::fromLatin1(item->metaObject()->className()).startsWith(QLatin1String("ClassicIndicator_QMLTYPE"))) { - indicators.push_back(item); - } else if (item->objectName() == QLatin1String("innerIndicators")) { - const QList innerIndicators = item->childItems(); - for (QQuickItem *innerItem : innerIndicators) { - if (QString::fromLatin1(innerItem->metaObject()->className()).startsWith(QLatin1String("ClassicIndicator_QMLTYPE"))) { - indicators.push_back(innerItem); - } - } - } - } - - return indicators; -} - -#endif // QtQuick diff --git a/src/qtwidgets/views/ClassicIndicatorsWindow_qtwidgets.h b/src/qtwidgets/views/ClassicIndicatorsWindow_qtwidgets.h index 439e7104..a982385c 100644 --- a/src/qtwidgets/views/ClassicIndicatorsWindow_qtwidgets.h +++ b/src/qtwidgets/views/ClassicIndicatorsWindow_qtwidgets.h @@ -9,14 +9,13 @@ Contact KDAB at for commercial licensing options. */ -#ifndef KD_INDICATORS_CLASSICINDICATORS_WINDOW_P_H -#define KD_INDICATORS_CLASSICINDICATORS_WINDOW_P_H +#ifndef KD_CLASSICINDICATORS_WINDOW_QTWIDGETS_H +#define KD_CLASSICINDICATORS_WINDOW_QTWIDGETS_H +#pragma once #include "controllers/DropIndicatorOverlay.h" #include "controllers/indicators/ClassicIndicators.h" -#ifdef KDDOCKWIDGETS_QTWIDGETS - #include #include #include @@ -80,36 +79,7 @@ public: bool m_hovered = false; const DropLocation m_dropLocation; }; -} -#else - -#include - -namespace KDDockWidgets { -class ClassicIndicators; - -class IndicatorWindow : public QQuickView -{ - Q_OBJECT - Q_PROPERTY(KDDockWidgets::ClassicIndicators *classicIndicators READ classicIndicators CONSTANT) -public: - explicit IndicatorWindow(ClassicIndicators *); - DropLocation hover(QPoint); - void updatePositions(); - QPoint posForIndicator(DropLocation) const; - Q_INVOKABLE QString iconName(int loc, bool active) const; - KDDockWidgets::ClassicIndicators *classicIndicators() const; - QQuickItem *indicatorForLocation(DropLocation loc) const; - -private: - DropLocation locationForIndicator(const QQuickItem *) const; - QQuickItem *indicatorForPos(QPoint) const; - QVector indicatorItems() const; - ClassicIndicators *const m_classicIndicators; -}; } #endif - -#endif