7#include "QskItemPrivate.h"
11#include "QskSkinManager.h"
13#include "QskDirtyItemFilter.h"
15#include <qglobalstatic.h>
16#include <qquickwindow.h>
18#if defined( QT_DEBUG )
22#if QT_VERSION >= QT_VERSION_CHECK( 6, 2, 0 )
25 #include <private/qabstractanimation_p.h>
30#if defined( QT_DEBUG )
31#include <private/qquickpositioners_p.h>
34#include <private/qquickitemchangelistener_p.h>
40#include <unordered_set>
42static inline void qskSendEventTo( QObject*
object, QEvent::Type type )
45 QCoreApplication::sendEvent(
object, &event );
48static inline void qskApplyUpdateFlags(
49 QskItem::UpdateFlags flags,
QskItem* item )
51 auto d =
static_cast< QskItemPrivate*
>( QskItemPrivate::get( item ) );
52 d->applyUpdateFlags( flags );
55static inline void qskFilterWindow( QQuickWindow* window )
57 if ( window ==
nullptr )
61 itemFilter.addWindow( window );
78 QObject::connect( qskSkinManager, &QskSkinManager::skinChanged,
79 qskSkinManager, [
this ] { updateSkin(); } );
81 QObject::connect( qskSkinManager, &QskSkinManager::colorSchemeChanged,
82 qskSkinManager, [
this ] { updateSkin(); } );
85 inline void insert(
QskItem* item )
87 m_items.insert( item );
90 inline void remove(
QskItem* item )
92 m_items.erase( item );
95 void updateItemFlags()
97 const auto flags = QskSetup::updateFlags();
99 for (
auto item : m_items )
100 qskApplyUpdateFlags( flags, item );
105 QEvent event( QEvent::StyleChange );
107 for (
auto item : m_items )
109 event.setAccepted(
true );
110 QCoreApplication::sendEvent( item, &event );
115 std::unordered_set< QskItem* > m_items;
130 , m_window( nullptr )
134 void setWindow( QQuickWindow* window )
136 if ( m_window != window )
146 QQuickWindow* window()
148 QQuickWindow* w = m_window;
152 if ( --m_refCount == 0 )
161 QQuickWindow* m_window;
169 class QskParentListener final :
public QQuickItemChangeListener
172 void update( QQuickItem* parentItem )
174 if ( parentItem ==
nullptr )
177 const auto changeTypes =
178 QQuickItemPrivate::Geometry | QQuickItemPrivate::Children;
180 auto d = QQuickItemPrivate::get( parentItem );
182 if ( needListening( parentItem ) )
183 d->updateOrAddItemChangeListener(
this, changeTypes );
185 d->removeItemChangeListener(
this, changeTypes );
189 inline bool needListening(
const QQuickItem* parentItem )
const
191 const auto children = parentItem->childItems();
192 for (
auto child : children )
194 if (
auto item = qobject_cast< const QskItem* >( child ) )
196 if ( item->polishOnParentResize() )
204 void itemGeometryChanged( QQuickItem* parentItem,
205 QQuickGeometryChange,
const QRectF& )
override
207 const auto children = parentItem->childItems();
208 for (
auto child : children )
210 if (
auto item = qobject_cast< QskItem* >( child ) )
212 if ( item->polishOnParentResize() )
221 void itemChildRemoved( QQuickItem* parentItem, QQuickItem* )
223 update( parentItem );
228Q_GLOBAL_STATIC( QskItemRegistry, qskRegistry )
229Q_GLOBAL_STATIC( QskWindowStore, qskReleasedWindowCounter )
230Q_GLOBAL_STATIC( QskParentListener, qskParentListener )
233 : QQuickItem( dd, parent )
235 setFlag( QQuickItem::ItemHasContents,
true );
236 Inherited::setActiveFocusOnTab(
false );
239 qskFilterWindow( window() );
241 qskRegistry->insert(
this );
256 d_func()->componentComplete =
false;
259 qskRegistry->remove(
this );
264 return metaObject()->className();
269 Inherited::classBegin();
274#if defined( QT_DEBUG )
277 if ( qobject_cast< const QQuickBasePositioner* >( parent() ) )
279 qWarning(
"QskItem in DeferredLayout mode under control of a positioner" );
284 Inherited::componentComplete();
289 Inherited::releaseResources();
297 qskReleasedWindowCounter->setWindow( window() );
302 Inherited::setEnabled( !on );
307 Inherited::setVisible( !on );
312 Inherited::setVisible(
true );
317 Inherited::setVisible(
false );
322 return qskIsVisibleTo(
this, ancestor );
327 return d_func()->explicitVisible;
338#if QT_VERSION >= QT_VERSION_CHECK( 6, 2, 0 )
339 d->heightValidFlag =
true;
340 d->widthValidFlag =
true;
342 d->heightValid =
true;
343 d->widthValid =
true;
346 const QRectF oldRect( d->x, d->y, d->width, d->height );
350 if ( d->x != x || d->y != y )
355 dirtyType |= QQuickItemPrivate::Position;
358 if ( d->width != width || d->height != height )
363 dirtyType |= QQuickItemPrivate::Size;
368 if ( dirtyType & QQuickItemPrivate::Position )
369 d->dirty( QQuickItemPrivate::Position );
371 if ( dirtyType & QQuickItemPrivate::Size )
372 d->dirty( QQuickItemPrivate::Size );
379 const QRectF newRect( d->x, d->y, d->width, d->height );
380#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
383 geometryChanged( newRect, oldRect );
390 Q_D(
const QQuickItem );
391 return QRectF( 0, 0, d->width, d->height );
396 Q_D(
const QQuickItem );
397 return QRectF( d->x, d->y, d->width, d->height );
403 if ( on != d->isTabFence )
412 return d_func()->isTabFence;
415void QskItem::setFocusPolicy( Qt::FocusPolicy policy )
424 if ( policy != d->focusPolicy )
426 d->focusPolicy = ( policy & ~Qt::TabFocus );
428 const bool tabFocus = policy & Qt::TabFocus;
430 if ( !tabFocus && window() )
433 if ( window()->activeFocusItem() == this )
435 if (
auto focusItem = nextItemInFocusChain(
true ) )
436 focusItem->setFocus(
true );
440 Inherited::setActiveFocusOnTab( tabFocus );
442 Q_EMIT focusPolicyChanged( focusPolicy() );
446Qt::FocusPolicy QskItem::focusPolicy()
const
448 uint policy = d_func()->focusPolicy;
449 if ( Inherited::activeFocusOnTab() )
450 policy |= Qt::TabFocus;
452 return static_cast< Qt::FocusPolicy
>( policy );
455void QskItem::setWheelEnabled(
bool on )
458 if ( on != d->wheelEnabled )
460 d->wheelEnabled = on;
461 Q_EMIT wheelEnabledChanged( on );
465bool QskItem::isWheelEnabled()
const
467 return d_func()->wheelEnabled;
473 if ( on != d->polishOnResize )
475 d->polishOnResize = on;
484 return d_func()->polishOnResize;
487void QskItem::setPolishOnParentResize(
bool on )
490 if ( on != d->polishOnParentResize )
492 d->polishOnParentResize = on;
494 if ( parentItem() && qskParentListener )
496 qskParentListener->update( parentItem() );
506bool QskItem::polishOnParentResize()
const
508 return d_func()->polishOnParentResize;
521 return d_func()->effectiveLayoutMirror;
537 if ( childrenInherit != d->inheritMirrorFromItem )
539 d->inheritMirrorFromItem = childrenInherit;
540 d->resolveLayoutMirror();
543 d->isMirrorImplicit =
false;
545 if ( on != d->effectiveLayoutMirror )
547 d->setLayoutMirror( on );
548 if ( childrenInherit )
549 d->resolveLayoutMirror();
557 if ( d && !d->isMirrorImplicit )
559 d->isMirrorImplicit =
true;
561 d->resolveLayoutMirror();
567 return d_func()->polishScheduled;
574 return ( d->dirtyAttributes & QQuickItemPrivate::ContentUpdateMask ) &&
575 ( d->flags & QQuickItem::ItemHasContents );
580 return d_func()->initiallyPainted;
587 if ( d->width <= 0.0 && d->height <= 0.0 )
596 if ( d->polishOnResize && qskIsPolishScheduled( parentItem() ) )
613 d->updateFlagsMask = 0;
614 d->applyUpdateFlags( QskSetup::updateFlags() );
621 d->updateFlagsMask |= flag;
625 applyUpdateFlag( flag, on );
634 d->updateFlagsMask &= ~flag;
636 const bool on = QskSetup::testUpdateFlag( flag );
640 applyUpdateFlag( flag, on );
647 return d_func()->updateFlags & flag;
650void QskItem::applyUpdateFlag( UpdateFlag flag,
bool on )
658 d->updateFlags |= flag;
660 d->updateFlags &= ~flag;
668 qskFilterWindow( window() );
680 if ( !on && d->blockedPolish )
692#if QT_VERSION >= QT_VERSION_CHECK( 6, 2, 0 )
693 d->widthValidFlag = d->heightValidFlag =
false;
695 d->widthValid = d->heightValid =
false;
697 d->updateImplicitSize(
false );
704 if ( on && !isVisible() )
712 if ( flags() & QQuickItem::ItemHasContents )
727 d->blockedImplicitSize =
true;
728 d->layoutConstraintChanged();
732 d->updateImplicitSize(
true );
738 const int eventType =
event->type();
739 const bool hasContents = flags() & QQuickItem::ItemHasContents;
743 case QEvent::StyleChange:
745 d_func()->clearPreviousNodes =
true;
756 case QEvent::ContentsRectChange:
769 case QEvent::ReadOnlyChange:
770 case QEvent::EnabledChange:
771 case QEvent::LocaleChange:
772 case QEvent::ParentChange:
773 case QEvent::LayoutDirectionChange:
778 case QskEvent::GeometryChange:
783 case QskEvent::WindowChange:
788 case QEvent::LayoutRequest:
795 case QEvent::FocusIn:
797 if ( window() ==
nullptr )
810 case QEvent::MouseButtonPress:
811 case QEvent::MouseButtonRelease:
813 if ( ( focusPolicy() & Qt::ClickFocus ) == Qt::ClickFocus )
815 if ( QGuiApplication::styleHints()->setFocusOnTouchRelease() )
817 if (
event->type() == QEvent::MouseButtonRelease )
818 forceActiveFocus( Qt::MouseFocusReason );
822 if (
event->type() == QEvent::MouseButtonPress )
823 forceActiveFocus( Qt::MouseFocusReason );
830 if ( !isWheelEnabled() )
841 if ( ( focusPolicy() & Qt::WheelFocus ) == Qt::WheelFocus )
842 forceActiveFocus( Qt::MouseFocusReason );
848 return Inherited::event(
event );
864 const QQuickItem::ItemChangeData& changeData )
868 case QQuickItem::ItemSceneChange:
870 if ( changeData.window )
874 qskFilterWindow( changeData.window );
878 auto oldWindow = qskReleasedWindowCounter->window();
880 if ( oldWindow && oldWindow->contentItem()
881 && ( oldWindow->activeFocusItem() ==
this ) )
894#if QT_VERSION >= QT_VERSION_CHECK( 6, 1, 0 )
895 auto wd = QQuickWindowPrivate::get( oldWindow )->deliveryAgentPrivate();
897 auto wd = QQuickWindowPrivate::get( oldWindow );
899 if (
auto scope = qskNearestFocusScope(
this ) )
901 wd->clearFocusInScope( scope,
this, Qt::OtherFocusReason );
905 wd->activeFocusItem =
nullptr;
911 if ( changeData.window ==
nullptr )
932 QCoreApplication::sendEvent(
this, &
event );
936 case QQuickItem::ItemEnabledHasChanged:
938 qskSendEventTo(
this, QEvent::EnabledChange );
941 case QQuickItem::ItemVisibleHasChanged:
952 if ( changeData.boolValue )
954 if ( d->blockedPolish )
959 if ( d->dirtyAttributes && ( d->flags & QQuickItem::ItemHasContents ) )
968 d->initiallyPainted =
false;
971 if ( parentItem() && parentItem()->isVisible() )
982 d->layoutConstraintChanged();
987 case QQuickItem::ItemParentHasChanged:
989 if( polishOnParentResize() && qskParentListener )
990 qskParentListener->update( parentItem() );
994 case QQuickItem::ItemChildAddedChange:
995 case QQuickItem::ItemChildRemovedChange:
1001 case QQuickItem::ItemOpacityHasChanged:
1002 case QQuickItem::ItemActiveFocusHasChanged:
1003 case QQuickItem::ItemRotationHasChanged:
1004 case QQuickItem::ItemAntialiasingHasChanged:
1005 case QQuickItem::ItemDevicePixelRatioHasChanged:
1011 Inherited::itemChange( change, changeData );
1014#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
1016void QskItem::geometryChanged(
1017 const QRectF& newGeometry,
const QRectF& oldGeometry )
1025 const QRectF& newGeometry,
const QRectF& oldGeometry )
1027#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
1028 Inherited::geometryChanged( newGeometry, oldGeometry );
1030 Inherited::geometryChange( newGeometry, oldGeometry );
1034 if ( !d->polishScheduled && d->polishOnResize )
1036 if ( newGeometry.size() != oldGeometry.size() )
1041 QCoreApplication::sendEvent(
this, &
event );
1046 Inherited::mouseUngrabEvent();
1051 Inherited::touchUngrabEvent();
1054#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
1056void QskItem::windowDeactivateEvent()
1058 Inherited::windowDeactivateEvent();
1063void QskItem::updatePolish()
1071 d->blockedPolish =
true;
1076 d->blockedPolish =
false;
1078 if ( !d->initiallyPainted )
1095void QskItem::updateItemPolish()
1099QSGNode* QskItem::updatePaintNode( QSGNode* node, UpdatePaintNodeData* data )
1107 d->initiallyPainted =
true;
1109 if ( d->clearPreviousNodes )
1124 d->paintNode =
nullptr;
1127 d->clearPreviousNodes =
false;
1130 return updateItemPaintNode( node );
1133QSGNode* QskItem::updateItemPaintNode( QSGNode* node )
1138void qskUpdateItemFlags()
1141 qskRegistry->updateItemFlags();
1144#include "moc_QskItem.cpp"
bool isPolishScheduled() const
void mouseUngrabEvent() override
bool isVisibleToParent() const
void geometryChange(const QRectF &, const QRectF &) override
void itemChange(ItemChange, const ItemChangeData &) override
bool event(QEvent *) override
void setPolishOnResize(bool)
void classBegin() override
virtual void aboutToShow()
void resetLayoutMirroring()
void touchUngrabEvent() override
void releaseResources() override
const char * className() const
void setLayoutMirroring(bool on, bool childrenInherit=false)
virtual void geometryChangeEvent(QskGeometryChangeEvent *)
bool isInitiallyPainted() const
void resetUpdateFlag(UpdateFlag)
virtual void changeEvent(QEvent *)
virtual void windowChangeEvent(QskWindowChangeEvent *)
bool isUpdateNodeScheduled() const
void updateFlagsChanged(UpdateFlags)
bool maybeUnresized() const
void setUpdateFlag(UpdateFlag, bool on=true)
bool isVisibleTo(const QQuickItem *) const
bool testUpdateFlag(UpdateFlag) const
void componentComplete() override
void setGeometry(qreal x, qreal y, qreal width, qreal height)
bool layoutMirroring() const