Advance Wayland and KDE package bring-up
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 ivan tkachenko <me@ratijas.tk>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "overlayzstackingattached.h"
|
||||
|
||||
#include "loggingcategory.h"
|
||||
|
||||
#include <QQuickItem>
|
||||
|
||||
OverlayZStackingAttached::OverlayZStackingAttached(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_layer(defaultLayerForPopupType(parent))
|
||||
, m_parentPopup(nullptr)
|
||||
, m_pending(false)
|
||||
{
|
||||
Q_ASSERT(parent);
|
||||
if (!isPopup(parent)) {
|
||||
qCWarning(KirigamiLog) << "OverlayZStacking must be attached to a Popup";
|
||||
return;
|
||||
}
|
||||
|
||||
connect(parent, SIGNAL(parentChanged()), this, SLOT(updateParentPopup()));
|
||||
connect(parent, SIGNAL(closed()), this, SLOT(dispatchPendingSignal()));
|
||||
// Note: aboutToShow is too late, as QQuickPopup has already created modal
|
||||
// dimmer based off current z index.
|
||||
}
|
||||
|
||||
OverlayZStackingAttached::~OverlayZStackingAttached()
|
||||
{
|
||||
}
|
||||
|
||||
qreal OverlayZStackingAttached::z() const
|
||||
{
|
||||
if (!m_parentPopup) {
|
||||
const_cast<OverlayZStackingAttached *>(this)->updateParentPopupSilent();
|
||||
}
|
||||
|
||||
qreal layerZ = defaultZForLayer(m_layer);
|
||||
qreal parentZ = parentPopupZ() + 1;
|
||||
|
||||
return std::max(layerZ, parentZ);
|
||||
}
|
||||
|
||||
OverlayZStackingAttached::Layer OverlayZStackingAttached::layer() const
|
||||
{
|
||||
return m_layer;
|
||||
}
|
||||
|
||||
void OverlayZStackingAttached::setLayer(Layer layer)
|
||||
{
|
||||
if (m_layer == layer) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_layer = layer;
|
||||
Q_EMIT layerChanged();
|
||||
enqueueSignal();
|
||||
}
|
||||
|
||||
OverlayZStackingAttached *OverlayZStackingAttached::qmlAttachedProperties(QObject *object)
|
||||
{
|
||||
return new OverlayZStackingAttached(object);
|
||||
}
|
||||
|
||||
void OverlayZStackingAttached::enqueueSignal()
|
||||
{
|
||||
if (isVisible(parent())) {
|
||||
m_pending = true;
|
||||
} else {
|
||||
Q_EMIT zChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void OverlayZStackingAttached::dispatchPendingSignal()
|
||||
{
|
||||
if (m_pending) {
|
||||
m_pending = false;
|
||||
Q_EMIT zChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void OverlayZStackingAttached::updateParentPopup()
|
||||
{
|
||||
const qreal oldZ = parentPopupZ();
|
||||
|
||||
updateParentPopupSilent();
|
||||
|
||||
if (oldZ != parentPopupZ()) {
|
||||
enqueueSignal();
|
||||
}
|
||||
}
|
||||
|
||||
void OverlayZStackingAttached::updateParentPopupSilent()
|
||||
{
|
||||
auto popup = findParentPopup(parent());
|
||||
setParentPopup(popup);
|
||||
}
|
||||
|
||||
void OverlayZStackingAttached::setParentPopup(QObject *parentPopup)
|
||||
{
|
||||
if (m_parentPopup == parentPopup) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_parentPopup) {
|
||||
disconnect(m_parentPopup.data(), SIGNAL(zChanged()), this, SLOT(enqueueSignal()));
|
||||
}
|
||||
|
||||
// Ideally, we would also connect to all the parent items' parentChanged() on the way to parent popup.
|
||||
m_parentPopup = parentPopup;
|
||||
|
||||
if (m_parentPopup) {
|
||||
connect(m_parentPopup.data(), SIGNAL(zChanged()), this, SLOT(enqueueSignal()));
|
||||
}
|
||||
}
|
||||
|
||||
qreal OverlayZStackingAttached::parentPopupZ() const
|
||||
{
|
||||
if (m_parentPopup) {
|
||||
return m_parentPopup->property("z").toReal();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool OverlayZStackingAttached::isVisible(const QObject *popup)
|
||||
{
|
||||
if (!isPopup(popup)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return popup->property("visible").toBool();
|
||||
}
|
||||
|
||||
bool OverlayZStackingAttached::isPopup(const QObject *object)
|
||||
{
|
||||
return object && object->inherits("QQuickPopup");
|
||||
}
|
||||
|
||||
QObject *OverlayZStackingAttached::findParentPopup(const QObject *popup)
|
||||
{
|
||||
auto item = findParentPopupItem(popup);
|
||||
if (!item) {
|
||||
return nullptr;
|
||||
}
|
||||
auto parentPopup = item->parent();
|
||||
if (!isPopup(popup)) {
|
||||
return nullptr;
|
||||
}
|
||||
return parentPopup;
|
||||
}
|
||||
|
||||
QQuickItem *OverlayZStackingAttached::findParentPopupItem(const QObject *popup)
|
||||
{
|
||||
if (!isPopup(popup)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QQuickItem *parentItem = popup->property("parent").value<QQuickItem *>();
|
||||
if (!parentItem) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QQuickItem *item = parentItem;
|
||||
do {
|
||||
if (item && item->inherits("QQuickPopupItem")) {
|
||||
return item;
|
||||
}
|
||||
item = item->parentItem();
|
||||
} while (item);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
OverlayZStackingAttached::Layer OverlayZStackingAttached::defaultLayerForPopupType(const QObject *popup)
|
||||
{
|
||||
if (popup) {
|
||||
if (popup->inherits("QQuickDialog")) {
|
||||
return Layer::Dialog;
|
||||
} else if (popup->inherits("QQuickDrawer")) {
|
||||
return Layer::Drawer;
|
||||
} else if (popup->inherits("QQuickMenu")) {
|
||||
return Layer::Menu;
|
||||
} else if (popup->inherits("QQuickToolTip")) {
|
||||
return Layer::ToolTip;
|
||||
}
|
||||
}
|
||||
return DefaultLowest;
|
||||
}
|
||||
|
||||
qreal OverlayZStackingAttached::defaultZForLayer(Layer layer)
|
||||
{
|
||||
switch (layer) {
|
||||
case DefaultLowest:
|
||||
return 0;
|
||||
case Drawer:
|
||||
return 100;
|
||||
case FullScreen:
|
||||
return 200;
|
||||
case Dialog:
|
||||
return 300;
|
||||
case Menu:
|
||||
return 400;
|
||||
case Notification:
|
||||
return 500;
|
||||
case ToolTip:
|
||||
return 600;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "moc_overlayzstackingattached.cpp"
|
||||
Reference in New Issue
Block a user