File indexing completed on 2024-04-28 16:49:27

0001 /*
0002 *  Copyright 2016  Smith AR <audoban@openmailbox.org>
0003 *                  Michail Vourlakos <mvourlakos@gmail.com>
0004 *
0005 *  This file is part of Latte-Dock
0006 *
0007 *  Latte-Dock is free software; you can redistribute it and/or
0008 *  modify it under the terms of the GNU General Public License as
0009 *  published by the Free Software Foundation; either version 2 of
0010 *  the License, or (at your option) any later version.
0011 *
0012 *  Latte-Dock is distributed in the hope that it will be useful,
0013 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0014 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0015 *  GNU General Public License for more details.
0016 *
0017 *  You should have received a copy of the GNU General Public License
0018 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
0019 */
0020 
0021 #include "primaryconfigview.h"
0022 
0023 // local
0024 #include <config-latte.h>
0025 #include "secondaryconfigview.h"
0026 #include "../effects.h"
0027 #include "../panelshadows_p.h"
0028 #include "../view.h"
0029 #include "../../lattecorona.h"
0030 #include "../../layouts/manager.h"
0031 #include "../../layout/genericlayout.h"
0032 #include "../../settings/universalsettings.h"
0033 #include "../../shortcuts/globalshortcuts.h"
0034 #include "../../shortcuts/shortcutstracker.h"
0035 #include "../../wm/abstractwindowinterface.h"
0036 
0037 // Qt
0038 #include <QQuickItem>
0039 #include <QQmlContext>
0040 #include <QQmlEngine>
0041 #include <QScreen>
0042 
0043 // KDE
0044 #include <KLocalizedContext>
0045 #include <KDeclarative/KDeclarative>
0046 #include <KWayland/Client/plasmashell.h>
0047 #include <KWayland/Client/surface.h>
0048 #include <KWindowEffects>
0049 #include <KWindowSystem>
0050 
0051 // Plasma
0052 #include <Plasma/Package>
0053 
0054 namespace Latte {
0055 namespace ViewPart {
0056 
0057 PrimaryConfigView::PrimaryConfigView(Plasma::Containment *containment, Latte::View *view, QWindow *parent)
0058     : PlasmaQuick::ConfigView(containment, parent),
0059       m_latteView(view)
0060 {
0061     m_corona = qobject_cast<Latte::Corona *>(m_latteView->containment()->corona());
0062 
0063     setupWaylandIntegration();
0064 
0065     if (KWindowSystem::isPlatformX11()) {
0066         m_corona->wm()->registerIgnoredWindow(winId());
0067     } else {
0068         connect(m_corona->wm(), &WindowSystem::AbstractWindowInterface::latteWindowAdded, this, [&]() {
0069             if (m_waylandWindowId.isNull()) {
0070                 m_waylandWindowId = m_corona->wm()->winIdFor("latte-dock", geometry());
0071                 m_corona->wm()->registerIgnoredWindow(m_waylandWindowId);
0072             }
0073         });
0074     }
0075 
0076     setScreen(m_latteView->screen());
0077 
0078     if (containment) {
0079         setIcon(qGuiApp->windowIcon());
0080     }
0081 
0082     m_screenSyncTimer.setSingleShot(true);
0083     m_screenSyncTimer.setInterval(100);
0084 
0085     connect(this, &QQuickView::widthChanged, this, &PrimaryConfigView::updateEffects);
0086     connect(this, &QQuickView::heightChanged, this, &PrimaryConfigView::updateEffects);
0087 
0088     connect(this, &PrimaryConfigView::availableScreenGeometryChanged, this, &PrimaryConfigView::syncGeometry);
0089     connect(this, &PrimaryConfigView::complexityChanged, this, &PrimaryConfigView::saveConfig);
0090     connect(this, &PrimaryConfigView::complexityChanged, this, &PrimaryConfigView::updateShowInlineProperties);
0091     connect(this, &PrimaryConfigView::complexityChanged, this, &PrimaryConfigView::syncGeometry);
0092 
0093     connect(this, &QQuickView::statusChanged, [&](QQuickView::Status status) {
0094         if (status == QQuickView::Ready) {
0095             updateEffects();
0096         }
0097     });
0098 
0099     connections << connect(&m_screenSyncTimer, &QTimer::timeout, this, [this]() {
0100         setScreen(m_latteView->screen());
0101         setFlags(wFlags());
0102 
0103         if (KWindowSystem::isPlatformX11()) {
0104 #if KF5_VERSION_MINOR >= 45
0105             KWindowSystem::setState(winId(), NET::SkipTaskbar | NET::SkipPager | NET::SkipSwitcher);
0106 #else
0107             KWindowSystem::setState(winId(), NET::SkipTaskbar | NET::SkipPager);
0108 #endif
0109 
0110             KWindowSystem::setOnAllDesktops(winId(), true);
0111         }
0112 
0113         syncGeometry();
0114         syncSlideEffect();
0115     });
0116     connections << connect(m_latteView->visibility(), &VisibilityManager::modeChanged, this, &PrimaryConfigView::syncGeometry);
0117     connections << connect(containment, &Plasma::Containment::immutabilityChanged, this, &PrimaryConfigView::immutabilityChanged);
0118 
0119     m_thicknessSyncTimer.setSingleShot(true);
0120     m_thicknessSyncTimer.setInterval(200);
0121     connections << connect(&m_thicknessSyncTimer, &QTimer::timeout, this, [this]() {
0122         syncGeometry();
0123     });
0124 
0125     connections << connect(m_latteView, &Latte::View::normalThicknessChanged, [&]() {
0126         m_thicknessSyncTimer.start();
0127     });
0128 
0129     if (m_corona) {
0130         connections << connect(m_corona, &Latte::Corona::raiseViewsTemporaryChanged, this, &PrimaryConfigView::raiseDocksTemporaryChanged);
0131         connections << connect(m_corona, &Latte::Corona::availableScreenRectChangedFrom, this, &PrimaryConfigView::updateAvailableScreenGeometry);
0132     }
0133 
0134     if (m_latteView->layout()) {
0135         emit m_latteView->layout()->setLastConfigViewFor(m_latteView);
0136     }
0137 }
0138 
0139 PrimaryConfigView::~PrimaryConfigView()
0140 {
0141     qDebug() << "ConfigView deleting ...";
0142 
0143     m_corona->dialogShadows()->removeWindow(this);
0144 
0145     m_corona->wm()->unregisterIgnoredWindow(KWindowSystem::isPlatformX11() ? winId() : m_waylandWindowId);
0146 
0147     deleteSecondaryWindow();
0148 
0149     for (const auto &var : connections) {
0150         QObject::disconnect(var);
0151     }
0152 }
0153 
0154 void PrimaryConfigView::init()
0155 {
0156     qDebug() << "dock config view : initialization started...";
0157     m_originalByPassWM = m_latteView->byPassWM();
0158     m_originalMode = m_latteView->visibility()->mode();
0159 
0160     loadConfig();
0161 
0162     setDefaultAlphaBuffer(true);
0163     setColor(Qt::transparent);
0164     m_corona->dialogShadows()->addWindow(this);
0165     rootContext()->setContextProperty(QStringLiteral("latteView"), m_latteView);
0166     rootContext()->setContextProperty(QStringLiteral("shortcutsEngine"), m_corona->globalShortcuts()->shortcutsTracker());
0167     rootContext()->setContextProperty(QStringLiteral("viewConfig"), this);
0168 
0169     if (m_corona) {
0170         rootContext()->setContextProperty(QStringLiteral("universalSettings"), m_corona->universalSettings());
0171         rootContext()->setContextProperty(QStringLiteral("layoutsManager"), m_corona->layoutsManager());
0172     }
0173 
0174     KDeclarative::KDeclarative kdeclarative;
0175     kdeclarative.setDeclarativeEngine(engine());
0176     kdeclarative.setTranslationDomain(QStringLiteral("latte-dock"));
0177 #if KF5_VERSION_MINOR >= 45
0178     kdeclarative.setupContext();
0179     kdeclarative.setupEngine(engine());
0180 #else
0181     kdeclarative.setupBindings();
0182 #endif
0183 
0184     QByteArray tempFilePath = "lattedockconfigurationui";
0185 
0186     updateEnabledBorders();
0187     updateAvailableScreenGeometry();
0188 
0189     auto source = QUrl::fromLocalFile(m_latteView->containment()->corona()->kPackage().filePath(tempFilePath));
0190     setSource(source);
0191     syncGeometry();
0192     syncSlideEffect();
0193 
0194     qDebug() << "dock config view : initialization ended...";
0195 }
0196 
0197 inline Qt::WindowFlags PrimaryConfigView::wFlags() const
0198 {
0199     return (flags() | Qt::FramelessWindowHint /*| Qt::WindowStaysOnTopHint*/) & ~Qt::WindowDoesNotAcceptFocus;
0200 }
0201 
0202 QQuickView *PrimaryConfigView::secondaryWindow()
0203 {
0204     return m_secConfigView;
0205 }
0206 
0207 void PrimaryConfigView::createSecondaryWindow()
0208 {
0209     if (m_secConfigView) {
0210         return;
0211     }
0212 
0213     m_secConfigView = new SecondaryConfigView(m_latteView, this);
0214     m_secConfigView->init();
0215 }
0216 
0217 void PrimaryConfigView::deleteSecondaryWindow()
0218 {
0219     if (m_secConfigView) {
0220         auto secWindow = m_secConfigView;
0221         m_secConfigView = nullptr;
0222         secWindow->deleteLater();
0223 
0224         if (KWindowSystem::isPlatformX11()) {
0225             //! this is needed in order for subtracked mask of secondary window to
0226             //! be released properly when changing for Advanced to Basic mode.
0227             //! Under wayland this is not needed because masks do not break any visuals.
0228             m_latteView->effects()->updateMask();
0229         }
0230     }
0231 }
0232 
0233 void PrimaryConfigView::updateAvailableScreenGeometry(View *origin)
0234 {    
0235     int currentScrId = m_latteView->positioner()->currentScreenId();
0236     m_availableScreenGeometry = m_corona->availableScreenRectWithCriteria(currentScrId, QString(), {}, {}, true);
0237 
0238     emit availableScreenGeometryChanged();
0239 }
0240 
0241 QRect PrimaryConfigView::availableScreenGeometry() const
0242 {
0243     return m_availableScreenGeometry;
0244 }
0245 
0246 QRect PrimaryConfigView::geometryWhenVisible() const
0247 {
0248     return m_geometryWhenVisible;
0249 }
0250 
0251 void PrimaryConfigView::requestActivate()
0252 {
0253     if (KWindowSystem::isPlatformWayland() && m_shellSurface) {
0254         if (m_waylandWindowId.isNull()) {
0255             m_waylandWindowId = m_corona->wm()->winIdFor("latte-dock", geometry());
0256         }
0257 
0258         m_corona->wm()->requestActivate(m_waylandWindowId);
0259     } else {
0260         QQuickView::requestActivate();
0261     }
0262 }
0263 
0264 void PrimaryConfigView::syncGeometry()
0265 {
0266     if (!m_latteView || !m_latteView->layout() || !m_latteView->containment() || !rootObject()) {
0267         return;
0268     }
0269 
0270     const QSize size(rootObject()->width(), rootObject()->height());
0271     setMaximumSize(size);
0272     setMinimumSize(size);
0273     resize(size);
0274 
0275     const auto location = m_latteView->containment()->location();
0276     const auto scrGeometry = m_latteView->screenGeometry();
0277     const auto availGeometry = m_availableScreenGeometry;
0278 
0279     int clearThickness = m_latteView->editThickness();
0280 
0281     QPoint position{0, 0};
0282 
0283     int xPos{0};
0284     int yPos{0};
0285 
0286     switch (m_latteView->formFactor()) {
0287     case Plasma::Types::Horizontal: {
0288         if (m_complexity == Latte::Types::ExpertSettings) {
0289             if (qApp->isLeftToRight()) {
0290                 xPos = availGeometry.x() + availGeometry.width() - size.width();
0291             } else {
0292                 xPos = availGeometry.x();
0293             }
0294         } else {
0295             xPos = scrGeometry.center().x() - size.width() / 2;
0296         }
0297 
0298         if (location == Plasma::Types::TopEdge) {
0299             yPos = scrGeometry.y() + clearThickness;
0300         } else if (location == Plasma::Types::BottomEdge) {
0301             yPos = scrGeometry.y() + scrGeometry.height() - clearThickness - size.height();
0302         }
0303     }
0304         break;
0305 
0306     case Plasma::Types::Vertical: {
0307         if (location == Plasma::Types::LeftEdge) {
0308             xPos = scrGeometry.x() + clearThickness;
0309             yPos =  availGeometry.y() + (availGeometry.height() - size.height())/2;
0310         } else if (location == Plasma::Types::RightEdge) {
0311             xPos = scrGeometry.x() + scrGeometry.width() - clearThickness - size.width();
0312             yPos =  availGeometry.y() + (availGeometry.height() - size.height())/2;
0313         }
0314     }
0315         break;
0316 
0317     default:
0318         qWarning() << "no sync geometry, wrong formFactor";
0319         break;
0320     }
0321 
0322     position = {xPos, yPos};
0323 
0324     updateEnabledBorders();    
0325 
0326     m_geometryWhenVisible = QRect(position.x(), position.y(), size.width(), size.height());
0327 
0328     setPosition(position);
0329 
0330     if (m_shellSurface) {
0331         m_shellSurface->setPosition(position);
0332     }
0333 
0334     updateShowInlineProperties();
0335 
0336     emit m_latteView->configWindowGeometryChanged();
0337 }
0338 
0339 void PrimaryConfigView::syncSlideEffect()
0340 {
0341     if (!m_latteView || !m_latteView->containment()) {
0342         return;
0343     }
0344 
0345     auto slideLocation = WindowSystem::AbstractWindowInterface::Slide::None;
0346 
0347     switch (m_latteView->containment()->location()) {
0348     case Plasma::Types::TopEdge:
0349         slideLocation = WindowSystem::AbstractWindowInterface::Slide::Top;
0350         break;
0351 
0352     case Plasma::Types::RightEdge:
0353         slideLocation = WindowSystem::AbstractWindowInterface::Slide::Right;
0354         break;
0355 
0356     case Plasma::Types::BottomEdge:
0357         slideLocation = WindowSystem::AbstractWindowInterface::Slide::Bottom;
0358         break;
0359 
0360     case Plasma::Types::LeftEdge:
0361         slideLocation = WindowSystem::AbstractWindowInterface::Slide::Left;
0362         break;
0363 
0364     default:
0365         qDebug() << staticMetaObject.className() << "wrong location";
0366         break;
0367     }
0368 
0369     m_corona->wm()->slideWindow(*this, slideLocation);
0370 }
0371 
0372 void PrimaryConfigView::showEvent(QShowEvent *ev)
0373 {
0374     QQuickWindow::showEvent(ev);
0375 
0376     if (!m_latteView) {
0377         return;
0378     }
0379 
0380     m_corona->wm()->setViewExtraFlags(*this);
0381     setFlags(wFlags());
0382 
0383     syncGeometry();
0384     syncSlideEffect();
0385 
0386     if (m_latteView && m_latteView->containment())
0387         m_latteView->containment()->setUserConfiguring(true);
0388 
0389     m_screenSyncTimer.start();
0390     QTimer::singleShot(400, this, &PrimaryConfigView::syncGeometry);
0391 
0392     emit showSignal();
0393 }
0394 
0395 void PrimaryConfigView::hideEvent(QHideEvent *ev)
0396 {
0397     if (!m_latteView) {
0398         deleteLater();
0399         //QQuickWindow::hideEvent(ev);
0400         return;
0401     }
0402 
0403     if (m_latteView->containment()) {
0404         m_latteView->containment()->setUserConfiguring(false);
0405     }
0406 
0407     // QQuickWindow::hideEvent(ev);
0408 
0409     const auto mode = m_latteView->visibility()->mode();
0410 
0411     if ((mode == Types::AlwaysVisible || mode == Types::WindowsGoBelow)
0412             && !(m_originalMode == Types::AlwaysVisible || m_originalMode == Types::WindowsGoBelow)) {
0413         //! mode changed to AlwaysVisible OR WindowsGoBelow FROM Dodge mode
0414         if (m_originalByPassWM) {
0415             //! if original by pass is active
0416             m_latteView->layout()->recreateView(m_latteView->containment());
0417         }
0418     } else if (m_latteView->byPassWM() != m_originalByPassWM) {
0419         m_latteView->layout()->recreateView(m_latteView->containment());
0420     }
0421 
0422     deleteLater();
0423 }
0424 
0425 void PrimaryConfigView::focusOutEvent(QFocusEvent *ev)
0426 {
0427     Q_UNUSED(ev);
0428 
0429     const auto *focusWindow = qGuiApp->focusWindow();
0430 
0431     if (!m_latteView
0432             || (focusWindow && (focusWindow->flags().testFlag(Qt::Popup)
0433                                 || focusWindow->flags().testFlag(Qt::ToolTip)))
0434             || m_latteView->alternativesIsShown()) {
0435         return;
0436     }
0437 
0438     if (!m_blockFocusLost && !m_latteView->containsMouse()
0439             && (!m_secConfigView || (m_secConfigView && !m_secConfigView->isActive()))) {
0440         hideConfigWindow();
0441     }
0442 }
0443 
0444 void PrimaryConfigView::setupWaylandIntegration()
0445 {
0446     if (m_shellSurface || !KWindowSystem::isPlatformWayland() || !m_latteView || !m_latteView->containment()) {
0447         // already setup
0448         return;
0449     }
0450 
0451     if (m_corona) {
0452         using namespace KWayland::Client;
0453         PlasmaShell *interface = m_corona->waylandCoronaInterface();
0454 
0455         if (!interface) {
0456             return;
0457         }
0458 
0459         Surface *s = Surface::fromWindow(this);
0460 
0461         if (!s) {
0462             return;
0463         }
0464 
0465         qDebug() << "wayland primary settings surface was created...";
0466 
0467         m_shellSurface = interface->createSurface(s, this);
0468         m_shellSurface->setSkipTaskbar(true);
0469 #if KF5_VERSION_MINOR >= 47
0470         m_shellSurface->setSkipSwitcher(true);
0471 #endif
0472 
0473         syncGeometry();
0474     }
0475 }
0476 
0477 bool PrimaryConfigView::event(QEvent *e)
0478 {
0479     if (e->type() == QEvent::PlatformSurface) {
0480         if (auto pe = dynamic_cast<QPlatformSurfaceEvent *>(e)) {
0481             switch (pe->surfaceEventType()) {
0482             case QPlatformSurfaceEvent::SurfaceCreated:
0483 
0484                 if (m_shellSurface) {
0485                     break;
0486                 }
0487 
0488                 setupWaylandIntegration();
0489                 break;
0490 
0491             case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
0492                 if (m_shellSurface) {
0493                     delete m_shellSurface;
0494                     m_shellSurface = nullptr;
0495                     qDebug() << "WAYLAND config window surface was deleted...";
0496                 }
0497 
0498                 break;
0499             }
0500         }
0501     }
0502 
0503     return PlasmaQuick::ConfigView::event(e);
0504 }
0505 
0506 
0507 void PrimaryConfigView::immutabilityChanged(Plasma::Types::ImmutabilityType type)
0508 {
0509     if (type != Plasma::Types::Mutable && isVisible())
0510         hideConfigWindow();
0511 }
0512 
0513 bool PrimaryConfigView::sticker() const
0514 {
0515     return m_blockFocusLost;
0516 }
0517 
0518 void PrimaryConfigView::setSticker(bool blockFocusLost)
0519 {
0520     if (m_blockFocusLost == blockFocusLost)
0521         return;
0522 
0523     m_blockFocusLost = blockFocusLost;
0524 }
0525 
0526 bool PrimaryConfigView::showInlineProperties() const
0527 {
0528     return m_showInlineProperties;
0529 }
0530 void PrimaryConfigView::setShowInlineProperties(bool show)
0531 {
0532     if (m_showInlineProperties == show) {
0533         return;
0534     }
0535 
0536     m_showInlineProperties = show;
0537     emit showInlinePropertiesChanged();
0538 }
0539 
0540 void PrimaryConfigView::updateShowInlineProperties()
0541 {
0542     if (!m_latteView) {
0543         return;
0544     }
0545 
0546     bool showSecWindow{false};
0547     bool complexityApprovedSecWindow{false};
0548 
0549 
0550     if (m_complexity != Latte::Types::BasicSettings
0551             && !(m_complexity == Latte::Types::ExpertSettings && m_latteView->formFactor() == Plasma::Types::Vertical)) {
0552         showSecWindow = true;
0553         complexityApprovedSecWindow = true;
0554     }
0555 
0556     //! consider screen geometry for showing or not the secondary window
0557     if (!geometryWhenVisible().isNull()) {
0558         createSecondaryWindow();
0559 
0560         if (m_secConfigView->geometryWhenVisible().intersects(geometryWhenVisible())) {
0561             showSecWindow = false;
0562         } else if (complexityApprovedSecWindow) {
0563             showSecWindow = true;
0564         }
0565     }
0566 
0567     if (showSecWindow) {
0568         if (!m_secConfigView) {
0569             createSecondaryWindow();
0570         }
0571 
0572         QTimer::singleShot(150, m_secConfigView, SLOT(show()));
0573         setShowInlineProperties(false);
0574     } else {
0575         deleteSecondaryWindow();
0576         setShowInlineProperties(true);
0577     }
0578 
0579     // qDebug() << " showSecWindow:" << showSecWindow << " _ " << " inline:"<< !showSecWindow;
0580 }
0581 
0582 int PrimaryConfigView::complexity() const
0583 {
0584     return (int)m_complexity;
0585 }
0586 
0587 void PrimaryConfigView::setComplexity(int complexity)
0588 {
0589     if ((int)m_complexity == complexity) {
0590         return;
0591     }
0592 
0593     m_complexity = static_cast<Latte::Types::SettingsComplexity>(complexity);
0594 
0595     emit complexityChanged();
0596 }
0597 
0598 void PrimaryConfigView::hideConfigWindow()
0599 {
0600     if (m_shellSurface) {
0601         //!NOTE: Avoid crash in wayland environment with qt5.9
0602         close();
0603     } else {
0604         hide();
0605     }
0606 }
0607 
0608 void PrimaryConfigView::updateLaunchersForGroup(int groupInt)
0609 {
0610     Types::LaunchersGroup group = (Types::LaunchersGroup)groupInt;
0611 
0612     //! when the layout/global launchers list is empty then the current dock launchers are used for them
0613     //! as a start point
0614     if (m_corona &&  m_latteView->layout()) {
0615         if ((group == Types::LayoutLaunchers && m_latteView->layout()->launchers().isEmpty())
0616                 || (group == Types::GlobalLaunchers && m_corona->universalSettings()->launchers().isEmpty())) {
0617 
0618             Plasma::Containment *c = m_latteView->containment();
0619 
0620             const auto &applets = c->applets();
0621 
0622             for (auto *applet : applets) {
0623                 KPluginMetaData meta = applet->kPackage().metadata();
0624 
0625                 if (meta.pluginId() == "org.kde.latte.plasmoid") {
0626                     if (QQuickItem *appletInterface = applet->property("_plasma_graphicObject").value<QQuickItem *>()) {
0627                         const auto &childItems = appletInterface->childItems();
0628 
0629                         if (childItems.isEmpty()) {
0630                             continue;
0631                         }
0632 
0633                         for (QQuickItem *item : childItems) {
0634                             if (auto *metaObject = item->metaObject()) {
0635                                 // not using QMetaObject::invokeMethod to avoid warnings when calling
0636                                 // this on applets that don't have it or other child items since this
0637                                 // is pretty much trial and error.
0638                                 // Also, "var" arguments are treated as QVariant in QMetaObject
0639 
0640                                 int methodIndex = metaObject->indexOfMethod("getLauncherList()");
0641 
0642                                 if (methodIndex == -1) {
0643                                     continue;
0644                                 }
0645 
0646                                 QMetaMethod method = metaObject->method(methodIndex);
0647 
0648                                 QVariant launchers;
0649 
0650                                 if (method.invoke(item, Q_RETURN_ARG(QVariant, launchers))) {
0651                                     if (group == Types::LayoutLaunchers) {
0652                                         m_latteView->layout()->setLaunchers(launchers.toStringList());
0653                                     } else if (group == Types::GlobalLaunchers) {
0654                                         m_corona->universalSettings()->setLaunchers(launchers.toStringList());
0655                                     }
0656                                 }
0657                             }
0658                         }
0659                     }
0660                 }
0661             }
0662         }
0663     }
0664 
0665 }
0666 
0667 //!BEGIN borders
0668 Plasma::FrameSvg::EnabledBorders PrimaryConfigView::enabledBorders() const
0669 {
0670     return m_enabledBorders;
0671 }
0672 
0673 void PrimaryConfigView::updateEnabledBorders()
0674 {
0675     if (!this->screen()) {
0676         return;
0677     }
0678 
0679     Plasma::FrameSvg::EnabledBorders borders = Plasma::FrameSvg::AllBorders;
0680 
0681     switch (m_latteView->location()) {
0682     case Plasma::Types::TopEdge:
0683         borders &= m_inReverse ? ~Plasma::FrameSvg::BottomBorder : ~Plasma::FrameSvg::TopBorder;
0684         break;
0685 
0686     case Plasma::Types::LeftEdge:
0687         borders &= ~Plasma::FrameSvg::LeftBorder;
0688         break;
0689 
0690     case Plasma::Types::RightEdge:
0691         borders &= ~Plasma::FrameSvg::RightBorder;
0692         break;
0693 
0694     case Plasma::Types::BottomEdge:
0695         borders &= m_inReverse ? ~Plasma::FrameSvg::TopBorder : ~Plasma::FrameSvg::BottomBorder;
0696         break;
0697 
0698     default:
0699         break;
0700     }
0701 
0702     if (m_enabledBorders != borders) {
0703         m_enabledBorders = borders;
0704 
0705         m_corona->dialogShadows()->addWindow(this, m_enabledBorders);
0706 
0707         emit enabledBordersChanged();
0708     }
0709 }
0710 //!END borders
0711 
0712 void PrimaryConfigView::updateEffects()
0713 {
0714     //! Don't apply any effect before the wayland surface is created under wayland
0715     //! https://bugs.kde.org/show_bug.cgi?id=392890
0716     if (KWindowSystem::isPlatformWayland() && !m_shellSurface) {
0717         return;
0718     }
0719 
0720     if (!m_background) {
0721         m_background = new Plasma::FrameSvg(this);
0722     }
0723 
0724     if (m_background->imagePath() != "widgets/panel-background") {
0725         m_background->setImagePath(QStringLiteral("widgets/panel-background"));
0726     }
0727 
0728     m_background->setEnabledBorders(m_enabledBorders);
0729     m_background->resizeFrame(size());
0730 
0731     QRegion mask = m_background->mask();
0732 
0733     QRegion fixedMask = mask.isNull() ? QRegion(QRect(0,0,width(),height())) : mask;
0734 
0735     if (!fixedMask.isEmpty()) {
0736         setMask(fixedMask);
0737     } else {
0738         setMask(QRegion());
0739     }
0740 
0741     if (KWindowSystem::compositingActive()) {
0742         KWindowEffects::enableBlurBehind(winId(), true, fixedMask);
0743     } else {
0744         KWindowEffects::enableBlurBehind(winId(), false);
0745     }
0746 }
0747 
0748 //!BEGIN configuration
0749 void PrimaryConfigView::loadConfig()
0750 {
0751     if (!m_latteView || !m_latteView->containment()) {
0752         return;
0753     }
0754     auto config = m_latteView->containment()->config();
0755     int complexity = config.readEntry("settingsComplexity", (int)Latte::Types::BasicSettings);
0756     setComplexity(static_cast<Latte::Types::SettingsComplexity>(complexity));
0757 }
0758 
0759 void PrimaryConfigView::saveConfig()
0760 {
0761     if (!m_latteView || !m_latteView->containment()) {
0762         return;
0763     }
0764 
0765     auto config = m_latteView->containment()->config();
0766     config.writeEntry("settingsComplexity", (int)m_complexity);
0767     config.sync();
0768 }
0769 //!END configuration
0770 
0771 }
0772 }
0773