From 2bf647db8ee0e9828da3d3a7dc9ca8a41baebbf9 Mon Sep 17 00:00:00 2001
From: Michail Vourlakos <mvourlakos@gmail.com>
Date: Tue, 27 Apr 2021 16:58:50 +0300
Subject: [PATCH] provide nice internal Compact.qml implementation

---
 declarativeimports/core/dialog.cpp            | 66 +++++++++++++++++++
 declarativeimports/core/dialog.h              | 14 ++++
 .../package/contents/applet/CompactApplet.qml | 10 ++-
 3 files changed, 88 insertions(+), 2 deletions(-)

diff --git a/declarativeimports/core/dialog.cpp b/declarativeimports/core/dialog.cpp
index 73fcb9402..eaefc7a9f 100644
--- a/declarativeimports/core/dialog.cpp
+++ b/declarativeimports/core/dialog.cpp
@@ -19,6 +19,10 @@
 
 #include "dialog.h"
 
+// Qt
+#include <QScreen>
+#include <QWindow>
+
 
 namespace Latte {
 namespace Quick {
@@ -43,6 +47,68 @@ void Dialog::setContainsMouse(bool contains)
     emit containsMouseChanged();
 }
 
+Plasma::Types::Location Dialog::edge() const
+{
+    return m_edge;
+}
+
+void Dialog::setEdge(const Plasma::Types::Location &edge)
+{
+    if (m_edge == edge) {
+        return;
+    }
+
+    m_edge = edge;
+    emit edgeChanged();
+}
+
+
+void Dialog::adjustGeometry(const QRect &geom)
+{
+    if (location() != Plasma::Types::Floating) {
+        PlasmaQuick::Dialog::adjustGeometry(geom);
+        return;
+    }
+
+    auto visualparent = visualParent();
+
+    if (visualparent && visualparent->window() && visualparent->window()->screen()) {
+        QPointF parenttopleftf = visualparent->mapToGlobal(QPointF(0, 0));
+        QPoint parenttopleft = parenttopleftf.toPoint();
+        QScreen *screen = visualparent->window()->screen();
+        QRect screengeometry = screen->geometry();
+
+        int x = 0;
+        int y = 0;
+
+        if (m_edge == Plasma::Types::LeftEdge || m_edge == Plasma::Types::RightEdge) {
+            y = parenttopleft.y() + (visualparent->height()/2) - (geom.height()/2);
+        } else {
+            x = parenttopleft.x() + (visualparent->width()/2) - (geom.width()/2);
+        }
+
+        if (m_edge == Plasma::Types::LeftEdge) {
+            x = parenttopleft.x() + visualparent->width() - 1;
+        } else if (m_edge == Plasma::Types::RightEdge) {
+            x = parenttopleft.x() - geom.width() + 1;
+        } else if (m_edge == Plasma::Types::TopEdge) {
+            y = parenttopleft.y() + visualparent->height() - 1;
+        } else { // bottom case
+            y = parenttopleft.y() - geom.height() + 1;
+        }
+
+        x = qBound(screengeometry.x(), x, screengeometry.right()-1);
+        y = qBound(screengeometry.y(), y, screengeometry.bottom()-1);
+
+        QRect repositionedrect(x, y, geom.width(), geom.height());
+        setGeometry(repositionedrect);
+        return;
+    }
+
+    PlasmaQuick::Dialog::adjustGeometry(geom);
+}
+
+
 bool Dialog::event(QEvent *e)
 {
     if (e->type() == QEvent::Enter) {
diff --git a/declarativeimports/core/dialog.h b/declarativeimports/core/dialog.h
index 72f087ed7..a7848b1a3 100644
--- a/declarativeimports/core/dialog.h
+++ b/declarativeimports/core/dialog.h
@@ -25,6 +25,7 @@
 #include <QObject>
 
 // Plasma
+#include <Plasma>
 #include <PlasmaQuick/Dialog>
 
 namespace Latte {
@@ -34,15 +35,26 @@ class Dialog : public PlasmaQuick::Dialog {
     Q_OBJECT
     Q_PROPERTY (bool containsMouse READ containsMouse NOTIFY containsMouseChanged)
 
+    /**
+     * Plasma Location of the dialog window. Useful if this dialog is a popup for a panel
+     */
+    Q_PROPERTY(Plasma::Types::Location edge READ edge WRITE setEdge NOTIFY edgeChanged)
+
 public:
     explicit Dialog(QQuickItem *parent = nullptr);
 
     bool containsMouse() const;
 
+    Plasma::Types::Location edge() const;
+    void setEdge(const Plasma::Types::Location &edge);
+
 signals:
     void containsMouseChanged();
+    void edgeChanged();
 
 protected:
+    void adjustGeometry(const QRect &geom) override;
+
     bool event(QEvent *e) override;
 
 private slots:
@@ -51,6 +63,8 @@ private slots:
 private:
     bool m_containsMouse{false};
 
+    Plasma::Types::Location m_edge{Plasma::Types::BottomEdge};
+
 
 };
 
diff --git a/shell/package/contents/applet/CompactApplet.qml b/shell/package/contents/applet/CompactApplet.qml
index 3a13ec005..2f2af4d0c 100644
--- a/shell/package/contents/applet/CompactApplet.qml
+++ b/shell/package/contents/applet/CompactApplet.qml
@@ -39,10 +39,15 @@ PlasmaCore.ToolTipArea {
 
     property Item fullRepresentation
     property Item compactRepresentation
-   // property Item expandedFeedback: expandedItem
+    /*Discover real visual parent - the following code points to Applet::ItemWrapper*/
+    property Item originalCompactRepresenationParent
+    property Item compactRepresentationVisualParent: originalCompactRepresenationParent && originalCompactRepresenationParent.parent
+                                                     ? originalCompactRepresenationParent.parent.parent : null
 
     onCompactRepresentationChanged: {
         if (compactRepresentation) {
+            originalCompactRepresenationParent = compactRepresentation.parent;
+
             compactRepresentation.parent = root;
             compactRepresentation.anchors.fill = root;
             compactRepresentation.visible = true;
@@ -152,8 +157,9 @@ PlasmaCore.ToolTipArea {
         objectName: "popupWindow"
         flags: Qt.WindowStaysOnTopHint
         visible: plasmoid.expanded && fullRepresentation
-        visualParent: compactRepresentation ? compactRepresentation : null
+        visualParent: compactRepresentationVisualParent ? compactRepresentationVisualParent : (compactRepresentation ? compactRepresentation : null)
         location: PlasmaCore.Types.Floating //plasmoid.location
+        edge: plasmoid.location /*this way dialog borders are not updated and it is used only for adjusting dialog position*/
         hideOnWindowDeactivate: plasmoid.hideOnWindowDeactivate
         backgroundHints: (plasmoid.containmentDisplayHints & PlasmaCore.Types.DesktopFullyCovered) ? PlasmaCore.Dialog.SolidBackground : PlasmaCore.Dialog.StandardBackground