File indexing completed on 2024-12-01 05:02:24

0001 /*
0002     SPDX-FileCopyrightText: 2018 Michail Vourlakos <mvourlakos@gmail.com>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "canvasconfigview.h"
0007 
0008 // local
0009 #include "primaryconfigview.h"
0010 #include "../panelshadows_p.h"
0011 #include "../view.h"
0012 #include "../../lattecorona.h"
0013 #include "../../wm/abstractwindowinterface.h"
0014 
0015 // Qt
0016 #include <QQuickItem>
0017 #include <QScreen>
0018 
0019 // KDE
0020 #include <KWindowSystem>
0021 #include <KWayland/Client/plasmashell.h>
0022 
0023 // Plasma
0024 #include <Plasma/Package>
0025 
0026 namespace Latte {
0027 namespace ViewPart {
0028 
0029 CanvasConfigView::CanvasConfigView(Latte::View *view, PrimaryConfigView *parent)
0030     : SubConfigView(view, QString("#canvasconfigview#"), false),
0031       m_parent(parent)
0032 {
0033     setResizeMode(QQuickView::SizeRootObjectToView);
0034 
0035     setParentView(view);
0036     init();
0037 }
0038 
0039 void CanvasConfigView::init()
0040 {
0041     SubConfigView::init();
0042 
0043     QByteArray tempFilePath = "canvasconfigurationui";
0044 
0045     updateEnabledBorders();
0046 
0047     auto source = QUrl::fromLocalFile(m_latteView->containment()->corona()->kPackage().filePath(tempFilePath));
0048     setSource(source);
0049     syncGeometry();
0050 
0051     if (m_parent && KWindowSystem::isPlatformX11()) {
0052         m_parent->requestActivate();
0053     }
0054 }
0055 
0056 QRect CanvasConfigView::geometryWhenVisible() const
0057 {
0058     return m_geometryWhenVisible;
0059 }
0060 
0061 void CanvasConfigView::initParentView(Latte::View *view)
0062 {
0063     SubConfigView::initParentView(view);
0064 
0065     rootContext()->setContextProperty(QStringLiteral("primaryConfigView"), m_parent);
0066 
0067     updateEnabledBorders();
0068     syncGeometry();
0069 }
0070 
0071 void CanvasConfigView::syncGeometry()
0072 {
0073     if (!m_latteView || !m_latteView->layout() || !m_latteView->containment() || !m_parent || !rootObject()) {
0074         return;
0075     }
0076 
0077     updateEnabledBorders();
0078 
0079     auto geometry = m_latteView->positioner()->canvasGeometry();
0080 
0081     if (m_geometryWhenVisible == geometry) {
0082         return;
0083     }
0084 
0085     m_geometryWhenVisible = geometry;
0086 
0087     setPosition(geometry.topLeft());
0088 
0089     if (m_shellSurface) {
0090         m_shellSurface->setPosition(geometry.topLeft());
0091     }
0092 
0093     setMaximumSize(geometry.size());
0094     setMinimumSize(geometry.size());
0095     resize(geometry.size());
0096 
0097     //! after placement request to activate the main config window in order to avoid
0098     //! rare cases of closing settings window from secondaryConfigView->focusOutEvent
0099     if (m_parent && KWindowSystem::isPlatformX11()) {
0100         m_parent->requestActivate();
0101     }
0102 }
0103 
0104 bool CanvasConfigView::event(QEvent *e)
0105 {
0106     bool result = SubConfigView::event(e);
0107 
0108     switch (e->type()) {
0109     case QEvent::Enter:
0110     case QEvent::MouseButtonPress:
0111     case QEvent::MouseButtonRelease:
0112         if (m_parent) {
0113             m_parent->requestActivate();
0114         }
0115         break;
0116     default:
0117         break;
0118     }
0119 
0120     return result;
0121 }
0122 
0123 void CanvasConfigView::showEvent(QShowEvent *ev)
0124 {
0125     if (m_shellSurface) {
0126         //! under wayland it needs to be set again after its hiding
0127         m_shellSurface->setPosition(m_geometryWhenVisible.topLeft());
0128     }
0129 
0130     SubConfigView::showEvent(ev);
0131 
0132     if (!m_latteView) {
0133         return;
0134     }
0135 
0136     syncGeometry();
0137 
0138     //! show Canvas on top of all other panels/docks and show
0139     //! its parent view on top afterwards
0140     m_corona->wm()->setViewExtraFlags(this, true);
0141 
0142     QTimer::singleShot(100, [this]() {
0143         //! delay execution in order to take influence after last Canvas on top call
0144         if (m_parent) {
0145             m_parent->requestActivate();
0146         }
0147     });
0148 
0149     m_screenSyncTimer.start();
0150     QTimer::singleShot(400, this, &CanvasConfigView::syncGeometry);
0151 
0152     emit showSignal();
0153 }
0154 
0155 void CanvasConfigView::focusOutEvent(QFocusEvent *ev)
0156 {
0157     Q_UNUSED(ev);
0158 
0159     if (!m_latteView) {
0160         return;
0161     }
0162 
0163     const auto *focusWindow = qGuiApp->focusWindow();
0164 
0165     if (focusWindow && (focusWindow->flags().testFlag(Qt::Popup)
0166                          || focusWindow->flags().testFlag(Qt::ToolTip))) {
0167         return;
0168     }
0169 
0170     const auto parent = qobject_cast<PrimaryConfigView *>(m_parent);
0171 
0172     if (!parent->hasFocus()) {
0173         parent->hideConfigWindow();
0174     }
0175 }
0176 
0177 void CanvasConfigView::hideConfigWindow()
0178 {
0179     if (m_shellSurface) {
0180         //!NOTE: Avoid crash in wayland environment with qt5.9
0181         close();
0182     } else {
0183         hide();
0184     }
0185 }
0186 
0187 //!BEGIN borders
0188 void CanvasConfigView::updateEnabledBorders()
0189 {
0190     if (!this->screen()) {
0191         return;
0192     }
0193 
0194     Plasma::FrameSvg::EnabledBorders borders = Plasma::FrameSvg::TopBorder;
0195 
0196     switch (m_latteView->location()) {
0197     case Plasma::Types::TopEdge:
0198         borders = Plasma::FrameSvg::BottomBorder;
0199         break;
0200 
0201     case Plasma::Types::LeftEdge:
0202         borders = Plasma::FrameSvg::RightBorder;
0203         break;
0204 
0205     case Plasma::Types::RightEdge:
0206         borders = Plasma::FrameSvg::LeftBorder;
0207         break;
0208 
0209     case Plasma::Types::BottomEdge:
0210         borders = Plasma::FrameSvg::TopBorder;
0211         break;
0212 
0213     default:
0214         break;
0215     }
0216 
0217     if (m_enabledBorders != borders) {
0218         m_enabledBorders = borders;
0219         m_corona->dialogShadows()->addWindow(this, m_enabledBorders);
0220 
0221         emit enabledBordersChanged();
0222     }
0223 }
0224 
0225 //!END borders
0226 
0227 }
0228 }
0229