File indexing completed on 2024-04-21 05:31:18

0001 /*
0002     SPDX-FileCopyrightText: 2020 Michail Vourlakos <mvourlakos@gmail.com>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "dialog.h"
0007 
0008 // Qt
0009 #include <QScreen>
0010 #include <QWindow>
0011 
0012 
0013 namespace Latte {
0014 namespace Quick {
0015 
0016 Dialog::Dialog(QQuickItem *parent)
0017     : PlasmaQuick::Dialog(parent)
0018 {
0019     connect(this, &PlasmaQuick::Dialog::visualParentChanged, this, &Dialog::onVisualParentChanged);
0020 }
0021 
0022 bool Dialog::containsMouse() const
0023 {
0024     return m_containsMouse;
0025 }
0026 
0027 void Dialog::setContainsMouse(bool contains)
0028 {
0029     if (m_containsMouse == contains) {
0030         return;
0031     }
0032 
0033     m_containsMouse = contains;
0034     emit containsMouseChanged();
0035 }
0036 
0037 Plasma::Types::Location Dialog::edge() const
0038 {
0039     return m_edge;
0040 }
0041 
0042 void Dialog::setEdge(const Plasma::Types::Location &edge)
0043 {
0044     if (m_edge == edge) {
0045         return;
0046     }
0047 
0048     m_edge = edge;
0049     emit edgeChanged();
0050 }
0051 
0052 bool Dialog::isRespectingAppletsLayoutGeometry() const
0053 {
0054     //! As it appears plasma applets popups are defining their popups to Normal window.
0055     //! Dock type is needed from wayland scenario. In wayland after a while popups from Normal become Dock types
0056     return (type() == Dialog::Normal || type() == Dialog::PopupMenu || type() == Dialog::Tooltip || type() == Dialog::Dock);
0057 }
0058 
0059 QRect Dialog::appletsLayoutGeometryFromContainment() const
0060 {
0061     QVariant geom = visualParent() && visualParent()->window() ? visualParent()->window()->property("_applets_layout_geometry") : QVariant();
0062     return geom.isValid() ? geom.toRect() : QRect();
0063 }
0064 
0065 int Dialog::appletsPopUpMargin() const
0066 {
0067     QVariant margin = visualParent() && visualParent()->window() ? visualParent()->window()->property("_applets_popup_margin") : QVariant();
0068     return margin.isValid() ? margin.toInt() : -1;
0069 }
0070 
0071 void Dialog::onVisualParentChanged()
0072 {
0073     // clear mode
0074     for (auto &c : m_visualParentConnections) {
0075         disconnect(c);
0076     }
0077 
0078     if (!visualParent() || !flags().testFlag(Qt::ToolTip) || !visualParent()->metaObject())  {
0079         return;
0080     }
0081 
0082     bool hassignal = (visualParent()->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("anchoredTooltipPositionChanged()")) != -1);
0083 
0084     if (hassignal) {
0085         m_visualParentConnections[0] = connect(visualParent(), SIGNAL(anchoredTooltipPositionChanged()) , this, SLOT(updateGeometry()));
0086     }
0087 }
0088 
0089 void Dialog::updateGeometry()
0090 {
0091     if (visualParent()) {
0092         setPosition(popupPosition(visualParent(), size()));
0093     }
0094 }
0095 
0096 void Dialog::updatePopUpEnabledBorders()
0097 {
0098     QRect appletslayoutgeometry = appletsLayoutGeometryFromContainment();
0099     int appletspopupmargin = appletsPopUpMargin();
0100 
0101     //! Plasma Scenario
0102     bool hideEdgeBorder = isRespectingAppletsLayoutGeometry() && !appletslayoutgeometry.isEmpty() && appletspopupmargin==-1;
0103 
0104     if (hideEdgeBorder) {
0105         setLocation(m_edge);
0106     } else {
0107         setLocation(Plasma::Types::Floating);
0108     }
0109 }
0110 
0111 QPoint Dialog::popupPosition(QQuickItem *item, const QSize &size)
0112 {
0113     auto visualparent = item;
0114 
0115     if (visualparent && visualparent->window() && visualparent->window()->screen()) {
0116         updatePopUpEnabledBorders();
0117 
0118         QPointF parenttopleftf = visualparent->mapToGlobal(QPointF(0, 0));
0119         QPoint parenttopleft = parenttopleftf.toPoint();
0120         QScreen *screen = visualparent->window()->screen();
0121         QRect screengeometry = screen->geometry();
0122 
0123         int x = 0;
0124         int y = 0;
0125 
0126         int popupmargin = qMax(0, appletsPopUpMargin());
0127 
0128         if (m_edge == Plasma::Types::LeftEdge || m_edge == Plasma::Types::RightEdge) {
0129             //! vertical scenario
0130             screengeometry -= QMargins(0, popupmargin, 0, popupmargin);
0131             y = parenttopleft.y() + (visualparent->height()/2) - (size.height()/2);
0132         } else {
0133             //! horizontal scenario
0134             screengeometry -= QMargins(popupmargin, 0, popupmargin, 0);
0135             x = parenttopleft.x() + (visualparent->width()/2) - (size.width()/2);
0136         }
0137 
0138         if (m_edge == Plasma::Types::LeftEdge) {
0139             x = parenttopleft.x() + visualparent->width() + popupmargin;
0140         } else if (m_edge == Plasma::Types::RightEdge) {
0141             x = parenttopleft.x() - size.width() - popupmargin;
0142         } else if (m_edge == Plasma::Types::TopEdge) {
0143             y = parenttopleft.y() + visualparent->height() + popupmargin;
0144         } else { // bottom case
0145             y = parenttopleft.y() - size.height() - popupmargin;
0146         }
0147 
0148         x = qBound(screengeometry.x(), x, screengeometry.right() - size.width() + 1);
0149         y = qBound(screengeometry.y(), y, screengeometry.bottom() - size.height() + 1);
0150 
0151         QRect appletslayoutgeometry = appletsLayoutGeometryFromContainment();
0152 
0153 
0154 
0155         if (isRespectingAppletsLayoutGeometry() && !appletslayoutgeometry.isEmpty()) {
0156             QPoint appletsglobaltopleft = visualparent->window()->mapToGlobal(appletslayoutgeometry.topLeft());
0157 
0158             QRect appletsglobalgeometry(appletsglobaltopleft.x(), appletsglobaltopleft.y(), appletslayoutgeometry.width(), appletslayoutgeometry.height());
0159 
0160             if (m_edge == Plasma::Types::LeftEdge || m_edge == Plasma::Types::RightEdge) {
0161                 int bottomy = appletsglobalgeometry.bottom()-size.height();
0162 
0163                 if (appletsglobalgeometry.height() >= size.height()) {
0164                     y = qBound(appletsglobalgeometry.y(), y, bottomy + 1);
0165                 }
0166             } else {
0167                 int rightx = appletsglobalgeometry.right()-size.width();
0168 
0169                 if (appletsglobalgeometry.width() >= size.width()) {
0170                     x = qBound(appletsglobalgeometry.x(), x, rightx + 1);
0171                 }
0172             }
0173         }
0174 
0175         return QPoint(x,y);
0176     }
0177 
0178     return PlasmaQuick::Dialog::popupPosition(item, size);
0179 }
0180 
0181 /*
0182 void Dialog::adjustGeometry(const QRect &geom)
0183 {
0184     auto visualparent = visualParent();
0185 
0186     if (visualparent && visualparent->window() && visualparent->window()->screen()) {
0187         updatePopUpEnabledBorders();
0188 
0189         QPointF parenttopleftf = visualparent->mapToGlobal(QPointF(0, 0));
0190         QPoint parenttopleft = parenttopleftf.toPoint();
0191         QScreen *screen = visualparent->window()->screen();
0192         QRect screengeometry = screen->geometry();
0193 
0194         int x = 0;
0195         int y = 0;
0196 
0197         if (m_edge == Plasma::Types::LeftEdge || m_edge == Plasma::Types::RightEdge) {
0198             y = parenttopleft.y() + (visualparent->height()/2) - (geom.height()/2);
0199         } else {
0200             x = parenttopleft.x() + (visualparent->width()/2) - (geom.width()/2);
0201         }
0202 
0203         int popupmargin = qMax(0, appletsPopUpMargin());
0204 
0205         if (m_edge == Plasma::Types::LeftEdge) {
0206             x = parenttopleft.x() + visualparent->width() + popupmargin;
0207         } else if (m_edge == Plasma::Types::RightEdge) {
0208             x = parenttopleft.x() - geom.width() - popupmargin;
0209         } else if (m_edge == Plasma::Types::TopEdge) {
0210             y = parenttopleft.y() + visualparent->height() + popupmargin;
0211         } else { // bottom case
0212             y = parenttopleft.y() - geom.height() - popupmargin;
0213         }
0214 
0215         x = qBound(screengeometry.x(), x, screengeometry.right()-1);
0216         y = qBound(screengeometry.y(), y, screengeometry.bottom()-1);
0217 
0218         QRect appletslayoutgeometry = appletsLayoutGeometryFromContainment();
0219 
0220         if (isRespectingAppletsLayoutGeometry() && !appletslayoutgeometry.isEmpty()) {
0221             QPoint appletsglobaltopleft = visualparent->window()->mapToGlobal(appletslayoutgeometry.topLeft());
0222 
0223             QRect appletsglobalgeometry(appletsglobaltopleft.x(), appletsglobaltopleft.y(), appletslayoutgeometry.width(), appletslayoutgeometry.height());
0224 
0225             if (m_edge == Plasma::Types::LeftEdge || m_edge == Plasma::Types::RightEdge) {
0226                 int bottomy = appletsglobalgeometry.bottom()-geom.height();
0227 
0228                 if (appletsglobalgeometry.height() >= geom.height()) {
0229                     y = qBound(appletsglobalgeometry.y(), y, bottomy + 1);
0230                 }
0231             } else {
0232                 int rightx = appletsglobalgeometry.right()-geom.width();
0233 
0234                 if (appletsglobalgeometry.width() >= geom.width()) {
0235                     x = qBound(appletsglobalgeometry.x(), x, rightx + 1);
0236                 }
0237             }
0238         }
0239 
0240         QRect repositionedrect(x, y, geom.width(), geom.height());
0241         setGeometry(repositionedrect);
0242         return;
0243     }
0244 
0245     PlasmaQuick::Dialog::adjustGeometry(geom);
0246 }
0247 */
0248 
0249 bool Dialog::event(QEvent *e)
0250 {
0251     if (e->type() == QEvent::Enter) {
0252         setContainsMouse(true);
0253     } else if (e->type() == QEvent::Leave
0254                || e->type() == QEvent::Hide) {
0255         setContainsMouse(false);
0256     }
0257 
0258     return PlasmaQuick::Dialog::event(e);
0259 }
0260 
0261 }
0262 }