diff --git a/src/controls/QskEvent.cpp b/src/controls/QskEvent.cpp index df755c8c..f3d15a0e 100644 --- a/src/controls/QskEvent.cpp +++ b/src/controls/QskEvent.cpp @@ -82,6 +82,14 @@ QskWindowChangeEvent::QskWindowChangeEvent( { } +// -- QskPopupEvent + +QskPopupEvent::QskPopupEvent( Type type, QskPopup* popup ) + : QskEvent( type ) + , m_popup( popup ) +{ +} + // -- QskGestureEvent QskGestureEvent::QskGestureEvent( diff --git a/src/controls/QskEvent.h b/src/controls/QskEvent.h index 51f6a417..a85b66f5 100644 --- a/src/controls/QskEvent.h +++ b/src/controls/QskEvent.h @@ -12,7 +12,9 @@ #include class QskGesture; +class QskPopup; class QQuickWindow; +class QQuickItem; class QSK_EXPORT QskEvent : public QEvent { @@ -24,6 +26,13 @@ class QSK_EXPORT QskEvent : public QEvent GeometryChange, WindowChange, + /* + Popups indicate their existence to the owning window + to allow for priority based stacking rules + */ + PopupAdded, + PopupRemoved, + Gesture, Animator, @@ -63,6 +72,17 @@ class QSK_EXPORT QskWindowChangeEvent : public QskEvent QQuickWindow* const m_window; }; +class QSK_EXPORT QskPopupEvent : public QskEvent +{ + public: + QskPopupEvent( Type, QskPopup* ); + + inline QskPopup* popup() const { return m_popup; } + + private: + QskPopup* const m_popup; +}; + class QSK_EXPORT QskGestureEvent : public QskEvent { public: diff --git a/src/controls/QskPopup.cpp b/src/controls/QskPopup.cpp index 5ad076a3..6c102f3c 100644 --- a/src/controls/QskPopup.cpp +++ b/src/controls/QskPopup.cpp @@ -8,6 +8,7 @@ #include "QskInputGrabber.h" #include "QskQuick.h" #include "QskWindow.h" +#include "QskEvent.h" QSK_QT_PRIVATE_BEGIN #include @@ -37,6 +38,18 @@ static void qskSetFocus( QQuickItem* item, bool on ) } } +static inline void qskSendPopupEvent( + QQuickWindow* window, QskPopup* popup, bool on ) +{ + if ( window ) + { + const auto type = on ? QskEvent::PopupAdded : QskEvent::PopupRemoved; + + QskPopupEvent event( type, popup ); + QCoreApplication::sendEvent( window, &event ); + } +} + namespace { class InputGrabber final : public QskInputGrabber @@ -86,8 +99,7 @@ class QskPopup::PrivateData { public: PrivateData() - : inputGrabber( nullptr ) - , flags( 0 ) + : flags( 0 ) , isModal( false ) , isOpen( false ) , autoGrabFocus( true ) @@ -95,7 +107,9 @@ class QskPopup::PrivateData { } - InputGrabber* inputGrabber; + InputGrabber* inputGrabber = nullptr; + + uint priority = 0; int flags : 4; bool isModal : 1; @@ -119,10 +133,13 @@ QskPopup::QskPopup( QQuickItem* parent ) setFlag( ItemIsFocusScope, true ); setTabFence( true ); setFocusPolicy( Qt::StrongFocus ); + + qskSendPopupEvent( window(), this, true ); } QskPopup::~QskPopup() { + qskSendPopupEvent( window(), this, false ); } void QskPopup::open() @@ -193,6 +210,20 @@ void QskPopup::updateInputGrabber() } } +void QskPopup::setPriority( uint priority ) +{ + if ( m_data->priority != priority ) + { + m_data->priority = priority; + Q_EMIT priorityChanged( priority ); + } +} + +uint QskPopup::priority() const +{ + return m_data->priority; +} + void QskPopup::setModal( bool on ) { if ( on == m_data->isModal ) @@ -417,6 +448,21 @@ void QskPopup::itemChange( QQuickItem::ItemChange change, } } } + else if ( change == QQuickItem::ItemParentHasChanged ) + { + delete m_data->inputGrabber; + m_data->inputGrabber = nullptr; + + updateInputGrabber(); + } +} + +void QskPopup::windowChangeEvent( QskWindowChangeEvent* event ) +{ + qskSendPopupEvent( event->oldWindow(), this, false ); + qskSendPopupEvent( event->window(), this, true ); + + Inherited::windowChangeEvent( event ); } #include "moc_QskPopup.cpp" diff --git a/src/controls/QskPopup.h b/src/controls/QskPopup.h index cdb5e17d..0a3995b7 100644 --- a/src/controls/QskPopup.h +++ b/src/controls/QskPopup.h @@ -14,6 +14,7 @@ class QSK_EXPORT QskPopup : public QskControl Q_PROPERTY( bool modal READ isModal WRITE setModal NOTIFY modalChanged ) Q_PROPERTY( bool overlay READ hasOverlay WRITE setOverlay NOTIFY overlayChanged ) + Q_PROPERTY( uint priority READ priority WRITE setPriority NOTIFY priorityChanged ) using Inherited = QskControl; @@ -45,6 +46,10 @@ class QSK_EXPORT QskPopup : public QskControl void setOverlay( bool on = true ); bool hasOverlay() const; + // allows for stacking according to priorities + void setPriority( uint ); + uint priority() const; + virtual QRectF overlayRect() const; bool isOpen() const; @@ -57,6 +62,7 @@ class QSK_EXPORT QskPopup : public QskControl void closed(); void modalChanged( bool ); void overlayChanged( bool ); + void priorityChanged( uint ); protected: void aboutToShow() override; @@ -65,6 +71,7 @@ class QSK_EXPORT QskPopup : public QskControl bool event( QEvent* ) override; void focusInEvent( QFocusEvent* ) override; void focusOutEvent( QFocusEvent* ) override; + void windowChangeEvent( QskWindowChangeEvent* ) override; void itemChange( QQuickItem::ItemChange, const QQuickItem::ItemChangeData& ) override; diff --git a/src/controls/QskWindow.cpp b/src/controls/QskWindow.cpp index 5572fcd2..ea2222da 100644 --- a/src/controls/QskWindow.cpp +++ b/src/controls/QskWindow.cpp @@ -50,13 +50,13 @@ namespace class ChildListener final : public QQuickItemChangeListener { public: - void setEnabled( QQuickItem* item, bool on ) + void setEnabled( QQuickItem* contentItem, bool on ) { - m_item = item; + m_contentItem = contentItem; const QQuickItemPrivate::ChangeTypes types = QQuickItemPrivate::Children; - QQuickItemPrivate* p = QQuickItemPrivate::get( item ); + QQuickItemPrivate* p = QQuickItemPrivate::get( contentItem ); if ( on ) p->addItemChangeListener( this, types ); else @@ -65,16 +65,16 @@ namespace void itemChildAdded( QQuickItem*, QQuickItem* ) override { - QskWindow* window = static_cast< QskWindow* >( m_item->window() ); + QskWindow* window = static_cast< QskWindow* >( m_contentItem->window() ); if ( window->isExposed() ) { - // the child might not be fully constructed, better delay update + // the child is not fully constructed QCoreApplication::postEvent( window, new QEvent( QEvent::LayoutRequest ) ); } } private: - QQuickItem* m_item; + QQuickItem* m_contentItem; }; }