File indexing completed on 2024-12-01 11:10:44

0001 /*
0002     SPDX-FileCopyrightText: 2016 Smith AR <audoban@openmailbox.org>
0003     SPDX-FileCopyrightText: 2016 Michail Vourlakos <mvourlakos@gmail.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "view.h"
0009 
0010 // local
0011 #include "effects.h"
0012 #include "positioner.h"
0013 #include "visibilitymanager.h"
0014 #include "settings/primaryconfigview.h"
0015 #include "settings/secondaryconfigview.h"
0016 #include "settings/viewsettingsfactory.h"
0017 #include "settings/widgetexplorerview.h"
0018 #include "../apptypes.h"
0019 #include "../lattecorona.h"
0020 #include "../data/layoutdata.h"
0021 #include "../data/viewstable.h"
0022 #include "../declarativeimports/interfaces.h"
0023 #include "../indicator/factory.h"
0024 #include "../layout/genericlayout.h"
0025 #include "../layouts/manager.h"
0026 #include "../layouts/storage.h"
0027 #include "../plasma/extended/theme.h"
0028 #include "../screenpool.h"
0029 #include "../settings/universalsettings.h"
0030 #include "../settings/exporttemplatedialog/exporttemplatedialog.h"
0031 #include "../shortcuts/globalshortcuts.h"
0032 #include "../shortcuts/shortcutstracker.h"
0033 
0034 // Qt
0035 #include <QAction>
0036 #include <QDragEnterEvent>
0037 #include <QDragMoveEvent>
0038 #include <QDropEvent>
0039 #include <QMouseEvent>
0040 #include <QQmlContext>
0041 #include <QQmlEngine>
0042 #include <QQmlProperty>
0043 #include <QQuickItem>
0044 #include <QMenu>
0045 
0046 // KDe
0047 #include <KActionCollection>
0048 #include <KActivities/Consumer>
0049 #include <KWayland/Client/plasmashell.h>
0050 #include <KWayland/Client/surface.h>
0051 #include <KWindowSystem>
0052 
0053 // Plasma
0054 #include <Plasma/Containment>
0055 #include <Plasma/ContainmentActions>
0056 #include <PlasmaQuick/AppletQuickItem>
0057 
0058 #define BLOCKHIDINGDRAGTYPE "View::ContainsDrag()"
0059 #define BLOCKHIDINGNEEDSATTENTIONTYPE "View::Containment::NeedsAttentionState()"
0060 #define BLOCKHIDINGREQUESTSINPUTTYPE "View::Containment::RequestsInputState()"
0061 
0062 namespace Latte {
0063 
0064 //! both alwaysVisible and byPassWMX11 are passed through corona because
0065 //! during the view window creation containment hasn't been set, but these variables
0066 //! are needed in order for window flags to be set correctly
0067 View::View(Plasma::Corona *corona, QScreen *targetScreen, bool byPassX11WM)
0068     : PlasmaQuick::ContainmentView(corona),
0069       m_effects(new ViewPart::Effects(this)),
0070       m_interface(new ViewPart::ContainmentInterface(this)),
0071       m_parabolic(new ViewPart::Parabolic(this)),
0072       m_sink(new ViewPart::EventsSink(this))
0073 {
0074     //this is disabled because under wayland breaks Views positioning
0075     //setVisible(false);
0076 
0077     m_corona = qobject_cast<Latte::Corona *>(corona);
0078 
0079     //! needs to be created after Effects because it catches some of its signals
0080     //! and avoid a crash from View::winId() at the same time
0081     m_positioner = new ViewPart::Positioner(this);
0082 
0083     // setTitle(corona->kPackage().metadata().name());
0084     setIcon(qGuiApp->windowIcon());
0085     setResizeMode(QuickViewSharedEngine::SizeRootObjectToView);
0086     setColor(QColor(Qt::transparent));
0087     setClearBeforeRendering(true);
0088 
0089     const auto flags = Qt::FramelessWindowHint
0090             | Qt::NoDropShadowWindowHint
0091             | Qt::WindowDoesNotAcceptFocus;
0092 
0093     if (byPassX11WM) {
0094         setFlags(flags | Qt::BypassWindowManagerHint);
0095         //! needs to be set early enough
0096         m_byPassWM = byPassX11WM;
0097     } else {
0098         setFlags(flags);
0099     }
0100 
0101     if (KWindowSystem::isPlatformX11()) {
0102         //! Enable OnAllDesktops during creation in order to protect corner cases that is ignored
0103         //! during startup. Such corner case is bug #447689.
0104         //! Best guess is that this is needed because OnAllDesktops is set through visibilitymanager
0105         //! after containment has been assigned. That delay might lead wm ignoring the flag
0106         //! until it is reapplied.
0107         KWindowSystem::setOnAllDesktops(winId(), true);
0108     }
0109 
0110     if (targetScreen) {
0111         m_positioner->setScreenToFollow(targetScreen);
0112     } else {
0113         qDebug() << "org.kde.view :::: corona was found properly!!!";
0114         m_positioner->setScreenToFollow(m_corona->screenPool()->primaryScreen());
0115     }
0116 
0117     m_releaseGrabTimer.setInterval(400);
0118     m_releaseGrabTimer.setSingleShot(true);
0119     connect(&m_releaseGrabTimer, &QTimer::timeout, this, &View::releaseGrab);
0120 
0121     connect(m_interface, &ViewPart::ContainmentInterface::hasExpandedAppletChanged, this, &View::updateTransientWindowsTracking);
0122 
0123     connect(this, &View::containmentChanged, this, &View::groupIdChanged);
0124     connect(this, &View::containmentChanged
0125             , this, [ &, byPassX11WM]() {
0126         qDebug() << "dock view c++ containment changed 1...";
0127 
0128         if (!this->containment())
0129             return;
0130 
0131         qDebug() << "dock view c++ containment changed 2...";
0132 
0133         setTitle(validTitle());
0134 
0135         //! First load default values from file
0136         restoreConfig();
0137 
0138         //! Afterwards override that values in case during creation something different is needed
0139         setByPassWM(byPassX11WM);
0140 
0141         //! Check the screen assigned to this dock
0142         reconsiderScreen();
0143 
0144         //! needs to be created before visibility creation because visibility uses it
0145         if (!m_windowsTracker) {
0146             m_windowsTracker = new ViewPart::WindowsTracker(this);
0147             emit windowsTrackerChanged();
0148         }
0149 
0150         if (!m_visibility) {
0151             m_visibility = new ViewPart::VisibilityManager(this);
0152 
0153             connect(m_visibility, &ViewPart::VisibilityManager::isHiddenChanged, this, [&]() {
0154                 if (m_visibility->isHidden()) {
0155                     m_interface->deactivateApplets();
0156                 }
0157             });
0158 
0159             connect(m_visibility, &ViewPart::VisibilityManager::containsMouseChanged,
0160                     this, &View::updateTransientWindowsTracking);
0161 
0162             //! Deprecated because with Plasma 5.19.3 the issue does not appear.
0163             //! The issue was that when FrameExtents where zero strange behaviors were
0164             //! occuring from KWin, e.g. the panels were moving outside of screen and
0165             //! panel external shadows were positioned out of place.
0166             /*connect(m_visibility, &ViewPart::VisibilityManager::frameExtentsCleared, this, [&]() {
0167                 if (behaveAsPlasmaPanel()) {
0168                     //! recreate view because otherwise compositor frame extents implementation
0169                     //! is triggering a crazy behavior of moving/hiding the view and freezing Latte
0170                     //! in some cases.
0171                     //reloadSource();
0172                 }
0173             });*/
0174 
0175             emit visibilityChanged();
0176         }
0177 
0178         if (!m_indicator) {
0179             m_indicator = new ViewPart::Indicator(this);
0180             emit indicatorChanged();
0181         }
0182 
0183         if (m_positioner) {
0184             //! immediateSyncGeometry helps avoiding binding loops from containment qml side
0185             m_positioner->immediateSyncGeometry();
0186         }
0187 
0188         connect(this->containment(), SIGNAL(statusChanged(Plasma::Types::ItemStatus)), SLOT(statusChanged(Plasma::Types::ItemStatus)));
0189         connect(this->containment(), &Plasma::Containment::showAddWidgetsInterface, this, &View::showWidgetExplorer);
0190         connect(this->containment(), &Plasma::Containment::userConfiguringChanged, this, [&]() {
0191             emit inEditModeChanged();
0192         });
0193 
0194         connect(this->containment(), &Plasma::Containment::destroyedChanged, this, [&]() {
0195             m_inDelete = containment()->destroyed();
0196         });
0197 
0198         if (m_corona->viewSettingsFactory()->hasOrphanSettings()
0199                 && m_corona->viewSettingsFactory()->hasVisibleSettings()
0200                 && m_corona->viewSettingsFactory()->lastContainment() == containment()) {
0201             //! used mostly from view recreations in order to inform config windows that view has been updated
0202             m_primaryConfigView = m_corona->viewSettingsFactory()->primaryConfigView();
0203             m_primaryConfigView->setParentView(this, true);
0204         }
0205 
0206         emit containmentActionsChanged();
0207     }, Qt::DirectConnection);
0208 
0209     if (m_corona) {
0210         connect(m_corona, &Latte::Corona::viewLocationChanged, this, &View::dockLocationChanged);
0211     }
0212 }
0213 
0214 View::~View()
0215 {
0216     m_inDelete = true;
0217 
0218     //! clear Layout connections
0219     m_visibleHackTimer1.stop();
0220     m_visibleHackTimer2.stop();
0221     for (auto &c : connectionsLayout) {
0222         disconnect(c);
0223     }
0224 
0225     //! unload indicators
0226     if (m_indicator) {
0227         m_indicator->unloadIndicators();
0228     }
0229 
0230     disconnectSensitiveSignals();
0231     disconnect(containment(), SIGNAL(statusChanged(Plasma::Types::ItemStatus)), this, SLOT(statusChanged(Plasma::Types::ItemStatus)));
0232 
0233     qDebug() << "dock view deleting...";
0234 
0235     //! this disconnect does not free up connections correctly when
0236     //! latteView is deleted. A crash for this example is the following:
0237     //! switch to Alternative Session and disable compositing,
0238     //! the signal creating the crash was probably from deleted
0239     //! windows.
0240     //! this->disconnect();
0241 
0242     if (m_primaryConfigView && m_corona->inQuit()) {
0243         //! delete only when application is quitting
0244         delete m_primaryConfigView;
0245     }
0246 
0247     if (m_appletConfigView) {
0248         delete m_appletConfigView;
0249     }
0250 
0251     //needs to be deleted before Effects because it catches some of its signals
0252     if (m_positioner) {
0253         delete m_positioner;
0254     }
0255 
0256     if (m_effects) {
0257         delete m_effects;
0258     }
0259 
0260     if (m_indicator) {
0261         delete m_indicator;
0262     }
0263 
0264     if (m_interface) {
0265         delete m_interface;
0266     }
0267 
0268     if (m_visibility) {
0269         delete m_visibility;
0270     }
0271 
0272     if (m_windowsTracker) {
0273         delete m_windowsTracker;
0274     }
0275 }
0276 
0277 void View::init(Plasma::Containment *plasma_containment)
0278 {
0279     connect(this, &QQuickWindow::xChanged, this, &View::geometryChanged);
0280     connect(this, &QQuickWindow::yChanged, this, &View::geometryChanged);
0281     connect(this, &QQuickWindow::widthChanged, this, &View::geometryChanged);
0282     connect(this, &QQuickWindow::heightChanged, this, &View::geometryChanged);
0283 
0284     connect(this, &QQuickWindow::xChanged, this, &View::xChanged);
0285     connect(this, &QQuickWindow::xChanged, this, &View::updateAbsoluteGeometry);
0286     connect(this, &QQuickWindow::yChanged, this, &View::yChanged);
0287     connect(this, &QQuickWindow::yChanged, this, &View::updateAbsoluteGeometry);
0288     connect(this, &QQuickWindow::widthChanged, this, &View::widthChanged);
0289     connect(this, &QQuickWindow::widthChanged, this, &View::updateAbsoluteGeometry);
0290     connect(this, &QQuickWindow::heightChanged, this, &View::heightChanged);
0291     connect(this, &QQuickWindow::heightChanged, this, &View::updateAbsoluteGeometry);
0292 
0293     connect(this, &View::fontPixelSizeChanged, this, &View::editThicknessChanged);
0294     connect(this, &View::maxNormalThicknessChanged, this, &View::editThicknessChanged);
0295 
0296     connect(this, &View::activitiesChanged, this, &View::applyActivitiesToWindows);
0297     connect(m_positioner, &ViewPart::Positioner::winIdChanged, this, &View::applyActivitiesToWindows);
0298 
0299     connect(this, &View::alignmentChanged, this, [&](){
0300         // inform neighbour vertical docks/panels to adjust their positioning
0301         if (m_inDelete || formFactor() == Plasma::Types::Vertical) {
0302             return;
0303         }
0304 
0305         emit availableScreenRectChangedFrom(this);
0306         emit availableScreenRegionChangedFrom(this);
0307     });
0308 
0309     connect(this, &View::maxLengthChanged, this, [&]() {
0310         if (m_inDelete) {
0311             return;
0312         }
0313 
0314         emit availableScreenRectChangedFrom(this);
0315         emit availableScreenRegionChangedFrom(this);
0316     });
0317 
0318     connect(this, &View::offsetChanged, this, [&]() {
0319         if (m_inDelete ) {
0320             return;
0321         }
0322 
0323         emit availableScreenRectChangedFrom(this);
0324         emit availableScreenRegionChangedFrom(this);
0325     });
0326 
0327     connect(this, &View::localGeometryChanged, this, [&]() {
0328         updateAbsoluteGeometry();
0329     });
0330     connect(this, &View::screenEdgeMarginEnabledChanged, this, [&]() {
0331         updateAbsoluteGeometry();
0332     });
0333 
0334     //! used in order to disconnect it when it should NOT be called because it creates crashes
0335     connect(this, &View::availableScreenRectChangedFrom, m_corona, &Latte::Corona::availableScreenRectChangedFrom);
0336     connect(this, &View::availableScreenRegionChangedFrom, m_corona, &Latte::Corona::availableScreenRegionChangedFrom);
0337     connect(m_corona, &Latte::Corona::availableScreenRectChangedFrom, this, &View::availableScreenRectChangedFromSlot);
0338     connect(m_corona, &Latte::Corona::verticalUnityViewHasFocus, this, &View::topViewAlwaysOnTop);
0339 
0340     connect(this, &View::byPassWMChanged, this, &View::saveConfig);
0341     connect(this, &View::isPreferredForShortcutsChanged, this, &View::saveConfig);
0342     connect(this, &View::nameChanged, this, &View::saveConfig);
0343     connect(this, &View::onPrimaryChanged, this, &View::saveConfig);
0344     connect(this, &View::typeChanged, this, &View::saveConfig);
0345 
0346     connect(this, &View::normalThicknessChanged, this, [&]() {
0347         emit availableScreenRectChangedFrom(this);
0348     });
0349 
0350     connect(m_effects, &ViewPart::Effects::innerShadowChanged, this, [&]() {
0351         emit availableScreenRectChangedFrom(this);
0352     });
0353     connect(m_positioner, &ViewPart::Positioner::onHideWindowsForSlidingOut, this, &View::hideWindowsForSlidingOut);
0354     connect(m_positioner, &ViewPart::Positioner::screenGeometryChanged, this, &View::screenGeometryChanged);
0355     connect(m_positioner, &ViewPart::Positioner::windowSizeChanged, this, [&]() {
0356         emit availableScreenRectChangedFrom(this);
0357     });
0358 
0359     connect(m_interface, &ViewPart::ContainmentInterface::hasExpandedAppletChanged, this, &View::verticalUnityViewHasFocus);
0360 
0361     //! View sends this signal in order to avoid crashes from ViewPart::Indicator when the view is recreated
0362     connect(m_corona->indicatorFactory(), &Latte::Indicator::Factory::indicatorChanged, this, [&](const QString &indicatorId) {
0363         emit indicatorPluginChanged(indicatorId);
0364     });
0365 
0366     connect(this, &View::indicatorPluginChanged, this, [&](const QString &indicatorId) {
0367         if (m_indicator && m_indicator->isCustomIndicator() && m_indicator->type() == indicatorId) {
0368             reloadSource();
0369         }
0370     });
0371 
0372     connect(m_corona->indicatorFactory(), &Latte::Indicator::Factory::indicatorRemoved, this, &View::indicatorPluginRemoved);
0373 
0374     //! Assign app interfaces in be accessible through containment graphic item
0375     QQuickItem *containmentGraphicItem = qobject_cast<QQuickItem *>(plasma_containment->property("_plasma_graphicObject").value<QObject *>());
0376 
0377     if (containmentGraphicItem) {
0378         containmentGraphicItem->setProperty("_latte_globalShortcuts_object", QVariant::fromValue(m_corona->globalShortcuts()->shortcutsTracker()));
0379         containmentGraphicItem->setProperty("_latte_layoutsManager_object", QVariant::fromValue(m_corona->layoutsManager()));
0380         containmentGraphicItem->setProperty("_latte_themeExtended_object", QVariant::fromValue(m_corona->themeExtended()));
0381         containmentGraphicItem->setProperty("_latte_universalSettings_object", QVariant::fromValue(m_corona->universalSettings()));
0382         containmentGraphicItem->setProperty("_latte_view_object", QVariant::fromValue(this));
0383 
0384         Latte::Interfaces *ifacesGraphicObject = qobject_cast<Latte::Interfaces *>(containmentGraphicItem->property("_latte_view_interfacesobject").value<QObject *>());
0385 
0386         if (ifacesGraphicObject) {
0387             ifacesGraphicObject->updateView();
0388             setInterfacesGraphicObj(ifacesGraphicObject);
0389         }
0390     }
0391 
0392     setSource(corona()->kPackage().filePath("lattedockui"));
0393 
0394     //! immediateSyncGeometry helps avoiding binding loops from containment qml side
0395     m_positioner->immediateSyncGeometry();
0396 
0397     qDebug() << "SOURCE:" << source();
0398 }
0399 
0400 void View::reloadSource()
0401 {
0402     if (m_layout && containment()) {
0403         // if (settingsWindowIsShown()) {
0404         //     m_configView->deleteLater();
0405         // }
0406 
0407         engine()->clearComponentCache();
0408         m_layout->recreateView(containment(), settingsWindowIsShown());
0409     }
0410 }
0411 
0412 bool View::inDelete() const
0413 {
0414     return m_inDelete;
0415 }
0416 
0417 bool View::inReadyState() const
0418 {
0419     return (m_layout != nullptr);
0420 }
0421 
0422 void View::disconnectSensitiveSignals()
0423 {
0424     m_initLayoutTimer.stop();
0425 
0426     disconnect(this, &View::availableScreenRectChangedFrom, m_corona, &Latte::Corona::availableScreenRectChangedFrom);
0427     disconnect(this, &View::availableScreenRegionChangedFrom, m_corona, &Latte::Corona::availableScreenRegionChangedFrom);
0428     disconnect(m_corona, &Latte::Corona::availableScreenRectChangedFrom, this, &View::availableScreenRectChangedFromSlot);
0429     disconnect(m_corona, &Latte::Corona::verticalUnityViewHasFocus, this, &View::topViewAlwaysOnTop);
0430 
0431     setLayout(nullptr);
0432 }
0433 
0434 void View::availableScreenRectChangedFromSlot(View *origin)
0435 {
0436     if (m_inDelete || origin == this || !origin) {
0437         return;
0438     }
0439 
0440     if (formFactor() == Plasma::Types::Vertical
0441             && origin->formFactor() == Plasma::Types::Horizontal //! accept only horizontal views
0442             && !(origin->location() == Plasma::Types::TopEdge && m_positioner->isStickedOnTopEdge()) //! ignore signals in such case
0443             && !(origin->location() == Plasma::Types::BottomEdge && m_positioner->isStickedOnBottomEdge()) //! ignore signals in such case
0444             && origin->layout()
0445             && m_layout
0446             && origin->layout()->lastUsedActivity() == m_layout->lastUsedActivity()) {
0447         //! must be in same activity
0448         m_positioner->syncGeometry();
0449     }
0450 }
0451 
0452 void View::setupWaylandIntegration()
0453 {
0454     if (m_shellSurface)
0455         return;
0456 
0457     if (Latte::Corona *c = qobject_cast<Latte::Corona *>(corona())) {
0458         using namespace KWayland::Client;
0459         PlasmaShell *interface {c->waylandCoronaInterface()};
0460 
0461         if (!interface)
0462             return;
0463 
0464         Surface *s{Surface::fromWindow(this)};
0465 
0466         if (!s)
0467             return;
0468 
0469         m_shellSurface = interface->createSurface(s, this);
0470         qDebug() << "WAYLAND dock window surface was created...";
0471         if (m_visibility) {
0472             m_visibility->initViewFlags();
0473         }
0474         if (m_positioner) {
0475             m_positioner->updateWaylandId();
0476         }
0477     }
0478 }
0479 
0480 KWayland::Client::PlasmaShellSurface *View::surface()
0481 {
0482     return m_shellSurface;
0483 }
0484 
0485 //! the main function which decides if this dock is at the
0486 //! correct screen
0487 void View::reconsiderScreen()
0488 {
0489     m_positioner->reconsiderScreen();
0490 }
0491 
0492 void View::duplicateView()
0493 {
0494     QString storedTmpViewFilepath = m_layout->storedView(containment()->id());
0495     newView(storedTmpViewFilepath);
0496 }
0497 
0498 void View::exportTemplate()
0499 {
0500     Latte::Settings::Dialog::ExportTemplateDialog *exportDlg = new Latte::Settings::Dialog::ExportTemplateDialog(this);
0501     exportDlg->show();
0502 }
0503 
0504 void View::newView(const QString &templateFile)
0505 {
0506     if (templateFile.isEmpty() || !m_layout) {
0507         return;
0508     }
0509 
0510     Data::ViewsTable templateviews = Layouts::Storage::self()->views(templateFile);
0511 
0512     if (templateviews.rowCount() <= 0) {
0513         return;
0514     }
0515 
0516     Data::View nextdata = templateviews[0];
0517     int scrId = onPrimary() ? m_corona->screenPool()->primaryScreenId() : m_positioner->currentScreenId();
0518 
0519     QList<Plasma::Types::Location> freeedges = m_layout->freeEdges(scrId);
0520 
0521     if (!freeedges.contains(nextdata.edge)) {
0522         nextdata.edge = (freeedges.count() > 0 ? freeedges[0] : Plasma::Types::BottomEdge);
0523     }
0524 
0525     nextdata.setState(Data::View::OriginFromViewTemplate, templateFile);
0526 
0527     m_layout->newView(nextdata);
0528 }
0529 
0530 void View::removeView()
0531 {
0532     if (m_layout) {
0533         QAction *removeAct = action("remove");
0534 
0535         if (removeAct) {
0536             removeAct->trigger();
0537         }
0538     }
0539 }
0540 
0541 bool View::settingsWindowIsShown()
0542 {
0543     return m_primaryConfigView && (m_primaryConfigView->parentView()==this) && m_primaryConfigView->isVisible();
0544 }
0545 
0546 void View::showSettingsWindow()
0547 {
0548     if (!settingsWindowIsShown()) {
0549         emit m_visibility->mustBeShown();
0550         showConfigurationInterface(containment());
0551         applyActivitiesToWindows();
0552     }
0553 }
0554 
0555 QQuickView *View::configView()
0556 {
0557     return m_primaryConfigView.data();
0558 }
0559 
0560 void View::showConfigurationInterface(Plasma::Applet *applet)
0561 {
0562     if (!applet || !applet->containment())
0563         return;
0564 
0565     Plasma::Containment *c = qobject_cast<Plasma::Containment *>(applet);
0566 
0567     if (m_primaryConfigView && c && c->isContainment() && c == this->containment()) {
0568         if (m_primaryConfigView->isVisible()) {
0569             m_primaryConfigView->hideConfigWindow();
0570         } else {
0571             m_primaryConfigView->showConfigWindow();
0572             applyActivitiesToWindows();
0573         }
0574 
0575         return;
0576     } else if (m_appletConfigView) {
0577         if (m_appletConfigView->applet() == applet) {
0578             m_appletConfigView->show();
0579 
0580             if (KWindowSystem::isPlatformX11()) {
0581                 m_appletConfigView->requestActivate();
0582             }
0583             return;
0584         } else {
0585             m_appletConfigView->hide();
0586         }
0587     }
0588 
0589     bool delayConfigView = false;
0590 
0591     if (c && containment() && c->isContainment() && c->id() == containment()->id()) {
0592         m_primaryConfigView = m_corona->viewSettingsFactory()->primaryConfigView(this);
0593         applyActivitiesToWindows();
0594     } else {
0595         m_appletConfigView = new PlasmaQuick::ConfigView(applet);
0596         m_appletConfigView.data()->init();
0597 
0598         //! center applet config window
0599         m_appletConfigView->setScreen(screen());
0600         QRect scrgeometry = screenGeometry();
0601         QPoint position{scrgeometry.center().x() - m_appletConfigView->width() / 2, scrgeometry.center().y() - m_appletConfigView->height() / 2 };
0602         //!under wayland probably needs another workaround
0603         m_appletConfigView->setPosition(position);
0604 
0605         m_appletConfigView->show();
0606     }
0607 }
0608 
0609 void View::showWidgetExplorer(const QPointF &point)
0610 {
0611     auto widgetExplorerView = m_corona->viewSettingsFactory()->widgetExplorerView(this);
0612 
0613     if (!widgetExplorerView->isVisible()) {
0614         widgetExplorerView->showAfter(250);
0615     }
0616 }
0617 
0618 QRect View::localGeometry() const
0619 {
0620     return m_localGeometry;
0621 }
0622 
0623 void View::setLocalGeometry(const QRect &geometry)
0624 {
0625     if (m_localGeometry == geometry) {
0626         return;
0627     }
0628 
0629     m_localGeometry = geometry;
0630     emit localGeometryChanged();
0631 }
0632 
0633 
0634 QString View::name() const
0635 {
0636     return m_name;
0637 }
0638 
0639 void View::setName(const QString &newname)
0640 {
0641     if (m_name == newname) {
0642         return;
0643     }
0644 
0645     m_name = newname;
0646     emit nameChanged();
0647 }
0648 
0649 QString View::validTitle() const
0650 {
0651     if (!containment()) {
0652         return QString();
0653     }
0654 
0655     return QString("#view#" + QString::number(containment()->id()));
0656 }
0657 
0658 void View::updateAbsoluteGeometry(bool bypassChecks)
0659 {
0660     //! there was a -1 in height and width here. The reason of this
0661     //! if I remember correctly was related to multi-screen but I cant
0662     //! remember exactly the reason, something related to right edge in
0663     //! multi screen environment. BUT this was breaking the entire AlwaysVisible
0664     //! experience with struts. Removing them in order to restore correct
0665     //! behavior and keeping this comment in order to check for
0666     //! multi-screen breakage
0667     QRect absGeometry = m_localGeometry;
0668     absGeometry.moveLeft(x() + m_localGeometry.x());
0669     absGeometry.moveTop(y() + m_localGeometry.y());
0670 
0671     if (behaveAsPlasmaPanel()) {
0672         int currentScreenEdgeMargin = m_screenEdgeMarginEnabled ? qMax(0, m_screenEdgeMargin) : 0;
0673 
0674         if (location() == Plasma::Types::BottomEdge) {
0675             absGeometry.moveTop(screenGeometry().bottom() - currentScreenEdgeMargin - m_normalThickness);
0676         } else if (location() == Plasma::Types::TopEdge) {
0677             absGeometry.moveTop(screenGeometry().top() + currentScreenEdgeMargin);
0678         } else if (location() == Plasma::Types::LeftEdge) {
0679             absGeometry.moveLeft(screenGeometry().left() + currentScreenEdgeMargin);
0680         } else if (location() == Plasma::Types::RightEdge) {
0681             absGeometry.moveLeft(screenGeometry().right() - currentScreenEdgeMargin - m_normalThickness);
0682         }
0683     }
0684 
0685     if (KWindowSystem::isPlatformX11() && devicePixelRatio() != 1.0) {
0686         //!Fix for X11 Global Scale, I dont think this could be pixel perfect accurate
0687         auto factor = devicePixelRatio();
0688         absGeometry = QRect(qRound(absGeometry.x() * factor),
0689                             qRound(absGeometry.y() * factor),
0690                             qRound(absGeometry.width() * factor),
0691                             qRound(absGeometry.height() * factor));
0692     }
0693 
0694     if (m_absoluteGeometry == absGeometry && !bypassChecks) {
0695         return;
0696     }
0697 
0698     if (m_absoluteGeometry != absGeometry) {
0699         m_absoluteGeometry = absGeometry;
0700         emit absoluteGeometryChanged(m_absoluteGeometry);
0701     }
0702 
0703     if ((m_absoluteGeometry != absGeometry) || bypassChecks) {
0704         //! inform others such as neighbour vertical views that new geometries are applied
0705         //! main use of BYPASSCKECKS is from Positioner when the view changes screens
0706         emit availableScreenRectChangedFrom(this);
0707         emit availableScreenRegionChangedFrom(this);
0708     }
0709 }
0710 
0711 void View::statusChanged(Plasma::Types::ItemStatus status)
0712 {
0713     if (!containment()) {
0714         return;
0715     }
0716 
0717     //! Fix for #443236, following setFlags(...) need to be added at all three cases
0718     //! but initViewFlags() should be called afterwards because setFlags(...) breaks
0719     //! the Dock window default behavior under x11
0720     if (status == Plasma::Types::NeedsAttentionStatus || status == Plasma::Types::RequiresAttentionStatus) {
0721         m_visibility->addBlockHidingEvent(BLOCKHIDINGNEEDSATTENTIONTYPE);
0722         setFlags(flags() | Qt::WindowDoesNotAcceptFocus);
0723         m_visibility->initViewFlags();
0724         if (m_shellSurface) {
0725             m_shellSurface->setPanelTakesFocus(false);
0726         }
0727     } else if (status == Plasma::Types::AcceptingInputStatus) {
0728         m_visibility->removeBlockHidingEvent(BLOCKHIDINGNEEDSATTENTIONTYPE);
0729         setFlags(flags() & ~Qt::WindowDoesNotAcceptFocus);
0730         m_visibility->initViewFlags();
0731         if (KWindowSystem::isPlatformX11()) {
0732             KWindowSystem::forceActiveWindow(winId());
0733         }
0734         if (m_shellSurface) {
0735             m_shellSurface->setPanelTakesFocus(true);
0736         }
0737     } else {
0738         updateTransientWindowsTracking();
0739         m_visibility->removeBlockHidingEvent(BLOCKHIDINGNEEDSATTENTIONTYPE);
0740         setFlags(flags() | Qt::WindowDoesNotAcceptFocus);
0741         m_visibility->initViewFlags();
0742         if (m_shellSurface) {
0743             m_shellSurface->setPanelTakesFocus(false);
0744         }
0745     }
0746 }
0747 
0748 void View::addTransientWindow(QWindow *window)
0749 {
0750     if (!m_transientWindows.contains(window) && !window->flags().testFlag(Qt::ToolTip) && !window->title().startsWith("#debugwindow#")) {
0751         m_transientWindows.append(window);
0752 
0753         QString winPtrStr = "0x" + QString::number((qulonglong)window,16);
0754         m_visibility->addBlockHidingEvent(winPtrStr);
0755 
0756         if (m_visibility->hasBlockHidingEvent(Latte::GlobalShortcuts::SHORTCUTBLOCKHIDINGTYPE)) {
0757             m_visibility->removeBlockHidingEvent(Latte::GlobalShortcuts::SHORTCUTBLOCKHIDINGTYPE);
0758         }
0759 
0760         connect(window, &QWindow::visibleChanged, this, &View::removeTransientWindow);
0761     }
0762 }
0763 
0764 void View::removeTransientWindow(const bool &visible)
0765 {
0766     QWindow *window = static_cast<QWindow *>(QObject::sender());
0767 
0768     if (window && !visible) {
0769         QString winPtrStr = "0x" + QString::number((qulonglong)window,16);
0770         m_visibility->removeBlockHidingEvent(winPtrStr);
0771         disconnect(window, &QWindow::visibleChanged, this, &View::removeTransientWindow);
0772         m_transientWindows.removeAll(window);
0773 
0774         if (m_visibility->hasBlockHidingEvent(Latte::GlobalShortcuts::SHORTCUTBLOCKHIDINGTYPE)) {
0775             m_visibility->removeBlockHidingEvent(Latte::GlobalShortcuts::SHORTCUTBLOCKHIDINGTYPE);
0776         }
0777 
0778         updateTransientWindowsTracking();
0779     }
0780 }
0781 
0782 void View::updateTransientWindowsTracking()
0783 {
0784     for(QWindow *window: qApp->topLevelWindows()) {
0785         if (window->transientParent() == this && window->isVisible()){
0786             addTransientWindow(window);
0787             break;
0788         }
0789     }
0790 }
0791 
0792 Types::ViewType View::type() const
0793 {
0794     return m_type;
0795 }
0796 
0797 void View::setType(Types::ViewType type)
0798 {
0799     if (m_type == type) {
0800         return;
0801     }
0802 
0803     m_type = type;
0804     emit typeChanged();
0805 }
0806 
0807 bool View::alternativesIsShown() const
0808 {
0809     return m_alternativesIsShown;
0810 }
0811 
0812 void View::setAlternativesIsShown(bool show)
0813 {
0814     if (m_alternativesIsShown == show) {
0815         return;
0816     }
0817 
0818     m_alternativesIsShown = show;
0819 
0820     emit alternativesIsShownChanged();
0821 }
0822 
0823 bool View::containsDrag() const
0824 {
0825     return m_containsDrag;
0826 }
0827 
0828 void View::setContainsDrag(bool contains)
0829 {
0830     if (m_containsDrag == contains) {
0831         return;
0832     }
0833 
0834     m_containsDrag = contains;
0835 
0836 
0837     if (m_containsDrag) {
0838         m_visibility->addBlockHidingEvent(BLOCKHIDINGDRAGTYPE);
0839     } else {
0840         m_visibility->removeBlockHidingEvent(BLOCKHIDINGDRAGTYPE);
0841     }
0842 
0843     emit containsDragChanged();
0844 }
0845 
0846 bool View::containsMouse() const
0847 {
0848     return m_containsMouse;
0849 }
0850 
0851 int View::normalThickness() const
0852 {
0853     return m_normalThickness;
0854 }
0855 
0856 void View::setNormalThickness(int thickness)
0857 {
0858     if (m_normalThickness == thickness) {
0859         return;
0860     }
0861 
0862     m_normalThickness = thickness;
0863     emit normalThicknessChanged();
0864 }
0865 
0866 int View::maxNormalThickness() const
0867 {
0868     return m_maxNormalThickness;
0869 }
0870 
0871 void View::setMaxNormalThickness(int thickness)
0872 {
0873     if (m_maxNormalThickness == thickness) {
0874         return;
0875     }
0876 
0877     m_maxNormalThickness = thickness;
0878     emit maxNormalThicknessChanged();
0879 }
0880 
0881 int View::headThicknessGap() const
0882 {
0883     return m_headThicknessGap;
0884 }
0885 
0886 void View::setHeadThicknessGap(int thickness)
0887 {
0888     if (m_headThicknessGap == thickness) {
0889         return;
0890     }
0891 
0892     m_headThicknessGap = thickness;
0893     emit headThicknessGapChanged();
0894 }
0895 
0896 bool View::byPassWM() const
0897 {
0898     return m_byPassWM;
0899 }
0900 
0901 void View::setByPassWM(bool bypass)
0902 {
0903     if (m_byPassWM == bypass) {
0904         return;
0905     }
0906 
0907     m_byPassWM = bypass;
0908     emit byPassWMChanged();
0909 }
0910 
0911 bool View::behaveAsPlasmaPanel() const
0912 {
0913     return m_behaveAsPlasmaPanel;
0914 }
0915 
0916 void View::setBehaveAsPlasmaPanel(bool behavior)
0917 {
0918     if (m_behaveAsPlasmaPanel == behavior) {
0919         return;
0920     }
0921 
0922     m_behaveAsPlasmaPanel = behavior;
0923 
0924     emit behaveAsPlasmaPanelChanged();
0925 }
0926 
0927 bool View::inEditMode() const
0928 {
0929     return containment() && containment()->isUserConfiguring();
0930 }
0931 
0932 bool View::isFloatingPanel() const
0933 {
0934     return m_behaveAsPlasmaPanel && m_screenEdgeMarginEnabled && (m_screenEdgeMargin>0);
0935 }
0936 
0937 bool View::isPreferredForShortcuts() const
0938 {
0939     return m_isPreferredForShortcuts;
0940 }
0941 
0942 void View::setIsPreferredForShortcuts(bool preferred)
0943 {
0944     if (m_isPreferredForShortcuts == preferred) {
0945         return;
0946     }
0947 
0948     m_isPreferredForShortcuts = preferred;
0949 
0950     emit isPreferredForShortcutsChanged();
0951 
0952     if (m_isPreferredForShortcuts && m_layout) {
0953         emit m_layout->preferredViewForShortcutsChanged(this);
0954     }
0955 }
0956 
0957 bool View::inSettingsAdvancedMode() const
0958 {
0959     return m_primaryConfigView && m_corona->universalSettings()->inAdvancedModeForEditSettings();
0960 }
0961 
0962 bool View::isTouchingBottomViewAndIsBusy() const
0963 {
0964     return m_isTouchingBottomViewAndIsBusy;
0965 }
0966 
0967 void View::setIsTouchingBottomViewAndIsBusy(bool touchAndBusy)
0968 {
0969     if (m_isTouchingBottomViewAndIsBusy == touchAndBusy) {
0970         return;
0971     }
0972 
0973     m_isTouchingBottomViewAndIsBusy = touchAndBusy;
0974 
0975     emit isTouchingBottomViewAndIsBusyChanged();
0976 }
0977 
0978 bool View::isTouchingTopViewAndIsBusy() const
0979 {
0980     return m_isTouchingTopViewAndIsBusy;
0981 }
0982 
0983 void View::setIsTouchingTopViewAndIsBusy(bool touchAndBusy)
0984 {
0985     if (m_isTouchingTopViewAndIsBusy == touchAndBusy) {
0986         return;
0987     }
0988 
0989     m_isTouchingTopViewAndIsBusy = touchAndBusy;
0990     emit isTouchingTopViewAndIsBusyChanged();
0991 }
0992 
0993 void View::preferredViewForShortcutsChangedSlot(Latte::View *view)
0994 {
0995     if (view != this) {
0996         setIsPreferredForShortcuts(false);
0997     }
0998 }
0999 
1000 bool View::onPrimary() const
1001 {
1002     return m_onPrimary;
1003 }
1004 
1005 void View::setOnPrimary(bool flag)
1006 {
1007     if (m_onPrimary == flag) {
1008         return;
1009     }
1010 
1011     m_onPrimary = flag;
1012     emit onPrimaryChanged();
1013 }
1014 
1015 int View::groupId() const
1016 {
1017     if (!containment()) {
1018         return -1;
1019     }
1020 
1021     return containment()->id();
1022 }
1023 
1024 float View::maxLength() const
1025 {
1026     return m_maxLength;
1027 }
1028 
1029 void View::setMaxLength(float length)
1030 {
1031     if (m_maxLength == length) {
1032         return;
1033     }
1034 
1035     m_maxLength = length;
1036     emit maxLengthChanged();
1037 }
1038 
1039 int View::editThickness() const
1040 {
1041     int smallspacing = 4;
1042     int ruler_height{m_fontPixelSize};
1043     int header_height{m_fontPixelSize + 2*smallspacing};
1044 
1045     int edgeThickness = behaveAsPlasmaPanel() && screenEdgeMarginEnabled() ? m_screenEdgeMargin : 0;
1046 
1047     return edgeThickness + m_maxNormalThickness + ruler_height + header_height + 6*smallspacing;
1048 }
1049 
1050 int View::maxThickness() const
1051 {
1052     return m_maxThickness;
1053 }
1054 
1055 void View::setMaxThickness(int thickness)
1056 {
1057     if (m_maxThickness == thickness)
1058         return;
1059 
1060     m_maxThickness = thickness;
1061     emit maxThicknessChanged();
1062 }
1063 
1064 int View::alignment() const
1065 {
1066     return m_alignment;
1067 }
1068 
1069 void View::setAlignment(int alignment)
1070 {
1071     Types::Alignment align = static_cast<Types::Alignment>(alignment);
1072 
1073     if (m_alignment == alignment) {
1074         return;
1075     }
1076 
1077     m_alignment = align;
1078     emit alignmentChanged();
1079 }
1080 
1081 QRect View::absoluteGeometry() const
1082 {
1083     return m_absoluteGeometry;
1084 }
1085 
1086 QRect View::screenGeometry() const
1087 {
1088     if (this->screen()) {
1089         QRect geom = this->screen()->geometry();
1090         return geom;
1091     }
1092 
1093     return QRect();
1094 }
1095 
1096 float View::offset() const
1097 {
1098     return m_offset;
1099 }
1100 
1101 void View::setOffset(float offset)
1102 {
1103     if (m_offset == offset) {
1104         return;
1105     }
1106 
1107     m_offset = offset;
1108     emit offsetChanged();
1109 }
1110 
1111 bool View::screenEdgeMarginEnabled() const
1112 {
1113     return m_screenEdgeMarginEnabled;
1114 }
1115 
1116 void View::setScreenEdgeMarginEnabled(bool enabled)
1117 {
1118     if (m_screenEdgeMarginEnabled == enabled) {
1119         return;
1120     }
1121 
1122     m_screenEdgeMarginEnabled = enabled;
1123     emit screenEdgeMarginEnabledChanged();
1124 }
1125 
1126 int View::screenEdgeMargin() const
1127 {
1128     return m_screenEdgeMargin;
1129 }
1130 
1131 void View::setScreenEdgeMargin(int margin)
1132 {
1133     if (m_screenEdgeMargin == margin) {
1134         return;
1135     }
1136 
1137 
1138 
1139     m_screenEdgeMargin = margin;
1140     emit screenEdgeMarginChanged();
1141 }
1142 
1143 int View::fontPixelSize() const
1144 {
1145     return m_fontPixelSize;
1146 }
1147 
1148 void View::setFontPixelSize(int size)
1149 {
1150     if (m_fontPixelSize == size) {
1151         return;
1152     }
1153 
1154     m_fontPixelSize = size;
1155 
1156     emit fontPixelSizeChanged();
1157 }
1158 
1159 bool View::isOnAllActivities() const
1160 {
1161     return m_activities.isEmpty() || m_activities[0] == Data::Layout::ALLACTIVITIESID;
1162 }
1163 
1164 bool View::isOnActivity(const QString &activity) const
1165 {
1166     return isOnAllActivities() || m_activities.contains(activity);
1167 }
1168 
1169 QStringList View::activities() const
1170 {
1171     QStringList running;
1172 
1173     QStringList runningAll = m_corona->activitiesConsumer()->runningActivities();
1174 
1175     for(int i=0; i<m_activities.count(); ++i) {
1176         if (runningAll.contains(m_activities[i])) {
1177             running << m_activities[i];
1178         }
1179     }
1180 
1181     return running;
1182 }
1183 
1184 void View::setActivities(const QStringList &ids)
1185 {
1186     if (m_activities == ids) {
1187         return;
1188     }
1189 
1190     m_activities = ids;
1191     emit activitiesChanged();
1192 }
1193 
1194 void View::applyActivitiesToWindows()
1195 {
1196     if (m_visibility && m_positioner && m_layout) {
1197         QStringList runningActivities = activities();
1198 
1199         m_positioner->setWindowOnActivities(m_positioner->trackedWindowId(), runningActivities);
1200 
1201         //! config windows
1202         if (m_primaryConfigView) {
1203             m_primaryConfigView->setOnActivities(runningActivities);
1204         }
1205 
1206         if (m_appletConfigView) {
1207             Latte::WindowSystem::WindowId appletconfigviewid;
1208 
1209             if (KWindowSystem::isPlatformX11()) {
1210                 appletconfigviewid = m_appletConfigView->winId();
1211             } else {
1212                 appletconfigviewid = m_corona->wm()->winIdFor("latte-dock", m_appletConfigView->title());
1213             }
1214 
1215             m_positioner->setWindowOnActivities(appletconfigviewid, runningActivities);
1216         }
1217 
1218         //! hidden windows
1219         if (m_visibility->supportsKWinEdges()) {
1220             m_visibility->applyActivitiesToHiddenWindows(runningActivities);
1221         }
1222     }
1223 }
1224 
1225 void View::showHiddenViewFromActivityStopping()
1226 {
1227     if (m_layout && m_visibility && !inDelete() && !isVisible() && !m_visibility->isHidden()) {
1228         show();
1229 
1230         if (m_effects) {
1231             m_effects->updateEnabledBorders();
1232         }
1233 
1234         //qDebug() << "View:: Enforce reshow from timer 1...";
1235         emit forcedShown();
1236     } else if (m_layout && isVisible()) {
1237         m_inDelete = false;
1238         //qDebug() << "View:: No needed reshow from timer 1...";
1239     }
1240 }
1241 
1242 Layout::GenericLayout *View::layout() const
1243 {
1244     return m_layout;
1245 }
1246 
1247 void View::setLayout(Layout::GenericLayout *layout)
1248 {
1249     if (m_layout == layout) {
1250         return;
1251     }
1252 
1253     // clear mode
1254     for (auto &c : connectionsLayout) {
1255         disconnect(c);
1256     }
1257 
1258     m_layout = layout;
1259 
1260     if (m_layout) {
1261         connectionsLayout << connect(containment(), &Plasma::Applet::destroyedChanged, m_layout, &Layout::GenericLayout::destroyedChanged);
1262         connectionsLayout << connect(containment(), &Plasma::Applet::locationChanged, m_corona, &Latte::Corona::viewLocationChanged);
1263         connectionsLayout << connect(containment(), &Plasma::Containment::appletAlternativesRequested, m_corona, &Latte::Corona::showAlternativesForApplet, Qt::QueuedConnection);
1264 
1265         if (m_corona->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) {
1266             connectionsLayout << connect(containment(), &Plasma::Containment::appletCreated, m_layout, &Layout::GenericLayout::appletCreated);
1267         }
1268 
1269         connectionsLayout << connect(m_positioner, &Latte::ViewPart::Positioner::edgeChanged, m_layout, &Layout::GenericLayout::viewEdgeChanged);
1270         connectionsLayout << connect(m_layout, &Layout::GenericLayout::popUpMarginChanged, m_effects, &Latte::ViewPart::Effects::popUpMarginChanged);
1271 
1272         //! Sometimes the activity isnt completely ready, by adding a delay
1273         //! we try to catch up
1274         m_initLayoutTimer.setInterval(100);
1275         m_initLayoutTimer.setSingleShot(true);
1276         connectionsLayout << connect(&m_initLayoutTimer, &QTimer::timeout, this, [&]() {
1277             if (m_layout && m_visibility) {
1278                 setActivities(m_layout->appliedActivities());
1279                 qDebug() << "DOCK VIEW FROM LAYOUT ::: " << m_layout->name() << " - activities: " << m_activities;
1280             }
1281         });
1282         m_initLayoutTimer.start();
1283 
1284         connectionsLayout << connect(m_layout, &Layout::GenericLayout::preferredViewForShortcutsChanged, this, &View::preferredViewForShortcutsChangedSlot);
1285 
1286         Latte::Corona *latteCorona = qobject_cast<Latte::Corona *>(this->corona());
1287 
1288         connectionsLayout << connect(latteCorona->activitiesConsumer(), &KActivities::Consumer::currentActivityChanged, this, [&]() {
1289             if (m_layout && m_visibility) {
1290                 setActivities(m_layout->appliedActivities());
1291                 //! update activities in case KWin did its magic and assigned windows to faulty activities
1292                 applyActivitiesToWindows();
1293                 showHiddenViewFromActivityStopping();
1294                 qDebug() << "DOCK VIEW FROM LAYOUT (currentActivityChanged) ::: " << m_layout->name() << " - activities: " << m_activities;
1295             }
1296         });
1297 
1298         if (latteCorona->layoutsManager()->memoryUsage() == MemoryUsage::MultipleLayouts) {
1299             connectionsLayout << connect(latteCorona->activitiesConsumer(), &KActivities::Consumer::runningActivitiesChanged, this, [&]() {
1300                 if (m_layout && m_visibility) {
1301                     setActivities(m_layout->appliedActivities());
1302                     qDebug() << "DOCK VIEW FROM LAYOUT (runningActivitiesChanged) ::: " << m_layout->name()
1303                              << " - activities: " << m_activities;
1304                 }
1305             });
1306 
1307             connectionsLayout << connect(m_layout, &Layout::GenericLayout::activitiesChanged, this, [&]() {
1308                 if (m_layout) {
1309                     setActivities(m_layout->appliedActivities());
1310                 }
1311             });
1312 
1313             connectionsLayout << connect(latteCorona->layoutsManager()->synchronizer(), &Layouts::Synchronizer::layoutsChanged, this, [&]() {
1314                 if (m_layout) {
1315                     setActivities(m_layout->appliedActivities());
1316                 }
1317             });
1318 
1319             //! BEGIN OF KWIN HACK
1320             //! IMPORTANT ::: Fixing KWin Faulty Behavior that KWin hides ALL Views when an Activity stops
1321             //! with no reason!!
1322 
1323             m_visibleHackTimer1.setInterval(400);
1324             m_visibleHackTimer2.setInterval(2500);
1325             m_visibleHackTimer1.setSingleShot(true);
1326             m_visibleHackTimer2.setSingleShot(true);
1327 
1328             connectionsLayout << connect(this, &QWindow::visibleChanged, this, [&]() {
1329                 if (m_layout && !inDelete() && !isVisible() && !m_positioner->inLayoutUnloading()) {
1330                     m_visibleHackTimer1.start();
1331                     m_visibleHackTimer2.start();
1332                 }
1333             });
1334 
1335             connectionsLayout << connect(&m_visibleHackTimer1, &QTimer::timeout, this, [&]() {
1336                 applyActivitiesToWindows();
1337                 showHiddenViewFromActivityStopping();
1338                 emit activitiesChanged();
1339             });
1340 
1341             connectionsLayout << connect(&m_visibleHackTimer2, &QTimer::timeout, this, [&]() {
1342                 applyActivitiesToWindows();
1343                 showHiddenViewFromActivityStopping();
1344                 emit activitiesChanged();
1345             });
1346 
1347             //! END OF KWIN HACK
1348         }
1349 
1350         emit layoutChanged();
1351     } else {
1352         m_activities.clear();
1353     }
1354 }
1355 
1356 void View::hideWindowsForSlidingOut()
1357 {
1358     if (m_primaryConfigView) {
1359         m_primaryConfigView->hideConfigWindow();
1360     }
1361 }
1362 
1363 //!check if the plasmoid with _name_ exists in the midedata
1364 bool View::mimeContainsPlasmoid(QMimeData *mimeData, QString name)
1365 {
1366     if (!mimeData) {
1367         return false;
1368     }
1369 
1370     if (mimeData->hasFormat(QStringLiteral("text/x-plasmoidservicename"))) {
1371         QString data = mimeData->data(QStringLiteral("text/x-plasmoidservicename"));
1372         const QStringList appletNames = data.split('\n', QString::SkipEmptyParts);
1373 
1374         for (const QString &appletName : appletNames) {
1375             if (appletName == name)
1376                 return true;
1377         }
1378     }
1379 
1380     return false;
1381 }
1382 
1383 Latte::Data::View View::data() const
1384 {
1385     Latte::Data::View vdata;
1386     vdata.id = QString::number(containment()->id());
1387     vdata.name = name();
1388     vdata.isActive = true;
1389     vdata.onPrimary = onPrimary();
1390 
1391     vdata.screen = containment()->screen();
1392     if (!Layouts::Storage::isValid(vdata.screen)) {
1393         vdata.screen = containment()->lastScreen();
1394     }
1395 
1396     vdata.screensGroup = screensGroup();
1397 
1398     //!screen edge margin can be more accurate in the config file
1399     vdata.screenEdgeMargin = m_screenEdgeMargin > 0 ? m_screenEdgeMargin : containment()->config().group("General").readEntry("screenEdgeMargin", (int)-1);
1400 
1401     vdata.edge = location();
1402     vdata.maxLength = m_maxLength * 100;
1403     vdata.alignment = m_alignment;
1404     vdata.subcontainments = Layouts::Storage::self()->subcontainments(layout(), containment());
1405 
1406     vdata.setState(Latte::Data::View::IsCreated);
1407     return vdata;
1408 }
1409 
1410 QQuickItem *View::colorizer() const
1411 {
1412     return m_colorizer;
1413 }
1414 
1415 void View::setColorizer(QQuickItem *colorizer)
1416 {
1417     if (m_colorizer == colorizer) {
1418         return;
1419     }
1420 
1421     m_colorizer = colorizer;
1422     emit colorizerChanged();
1423 }
1424 
1425 QQuickItem *View::metrics() const
1426 {
1427     return m_metrics;
1428 }
1429 
1430 void View::setMetrics(QQuickItem *metrics)
1431 {
1432     if (m_metrics == metrics) {
1433         return;
1434     }
1435 
1436     m_metrics = metrics;
1437     emit metricsChanged();
1438 }
1439 
1440 ViewPart::Effects *View::effects() const
1441 {
1442     return m_effects;
1443 }
1444 
1445 ViewPart::Indicator *View::indicator() const
1446 {
1447     return m_indicator;
1448 }
1449 
1450 ViewPart::ContainmentInterface *View::extendedInterface() const
1451 {
1452     return m_interface;
1453 }
1454 
1455 ViewPart::Parabolic *View::parabolic() const
1456 {
1457     return m_parabolic;
1458 }
1459 
1460 ViewPart::Positioner *View::positioner() const
1461 {
1462     return m_positioner;
1463 }
1464 
1465 ViewPart::EventsSink *View::sink() const
1466 {
1467     return m_sink;
1468 }
1469 
1470 ViewPart::VisibilityManager *View::visibility() const
1471 {
1472     return m_visibility;
1473 }
1474 
1475 ViewPart::WindowsTracker *View::windowsTracker() const
1476 {
1477     return m_windowsTracker;
1478 }
1479 
1480 Latte::Interfaces *View::interfacesGraphicObj() const
1481 {
1482     return m_interfacesGraphicObj;
1483 }
1484 
1485 void View::setInterfacesGraphicObj(Latte::Interfaces *ifaces)
1486 {
1487     if (m_interfacesGraphicObj == ifaces) {
1488         return;
1489     }
1490 
1491     m_interfacesGraphicObj = ifaces;
1492 
1493     if (containment()) {
1494         QQuickItem *containmentGraphicItem = qobject_cast<QQuickItem *>(containment()->property("_plasma_graphicObject").value<QObject *>());
1495 
1496         if (containmentGraphicItem) {
1497             containmentGraphicItem->setProperty("_latte_view_interfacesobject", QVariant::fromValue(m_interfacesGraphicObj));
1498         }
1499     }
1500 
1501     emit interfacesGraphicObjChanged();
1502 }
1503 
1504 bool View::event(QEvent *e)
1505 {   
1506     QEvent *sunkevent = e;
1507 
1508     if (!m_inDelete) {
1509         emit eventTriggered(e);
1510 
1511         bool sinkableevent{false};
1512 
1513         switch (e->type()) {
1514         case QEvent::Enter:
1515             m_containsMouse = true;
1516             break;
1517 
1518         case QEvent::Leave:
1519             m_containsMouse = false;
1520             setContainsDrag(false);
1521             sinkableevent = true;
1522             break;
1523 
1524         case QEvent::DragEnter:
1525             setContainsDrag(true);
1526             sinkableevent = true;
1527             break;
1528 
1529         case QEvent::DragLeave:
1530             setContainsDrag(false);
1531             break;
1532 
1533         case QEvent::DragMove:
1534             sinkableevent = true;
1535             break;
1536 
1537         case QEvent::Drop:
1538             setContainsDrag(false);
1539             sinkableevent = true;
1540             break;
1541 
1542         case QEvent::MouseMove:
1543             sinkableevent = true;
1544             break;
1545 
1546         case QEvent::MouseButtonPress:
1547             if (auto me = dynamic_cast<QMouseEvent *>(e)) {
1548                 emit mousePressed(me->pos(), me->button());
1549                 sinkableevent = true;
1550                 verticalUnityViewHasFocus();
1551             }
1552             break;
1553 
1554         case QEvent::MouseButtonRelease:
1555             if (auto me = dynamic_cast<QMouseEvent *>(e)) {
1556                 emit mouseReleased(me->pos(), me->button());
1557                 sinkableevent = true;
1558             }
1559             break;
1560 
1561         case QEvent::PlatformSurface:
1562             if (auto pe = dynamic_cast<QPlatformSurfaceEvent *>(e)) {
1563                 switch (pe->surfaceEventType()) {
1564                 case QPlatformSurfaceEvent::SurfaceCreated:
1565                     setupWaylandIntegration();
1566 
1567                     if (m_shellSurface) {
1568                         //! immediateSyncGeometry helps avoiding binding loops from containment qml side
1569                         m_positioner->immediateSyncGeometry();
1570                         m_effects->updateShadows();
1571                     }
1572 
1573                     break;
1574 
1575                 case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
1576                     if (m_shellSurface) {
1577                         delete m_shellSurface;
1578                         m_shellSurface = nullptr;
1579                         qDebug() << "WAYLAND dock window surface was deleted...";
1580                         m_effects->clearShadows();
1581                     }
1582 
1583                     break;
1584                 }
1585             }
1586 
1587             break;
1588 
1589         case QEvent::Show:
1590             if (m_visibility) {
1591                 m_visibility->initViewFlags();
1592             }
1593             break;
1594 
1595         case QEvent::Wheel:
1596             if (auto we = dynamic_cast<QWheelEvent *>(e)) {
1597                 QPoint pos = we->position().toPoint();
1598                 emit wheelScrolled(pos, we->angleDelta(), we->buttons());
1599                 sinkableevent = true;
1600             }
1601             break;
1602         default:
1603             break;
1604         }
1605 
1606         if (sinkableevent && m_sink->isActive()) {
1607             sunkevent = m_sink->onEvent(e);
1608         }
1609     }
1610 
1611     return ContainmentView::event(sunkevent);
1612 }
1613 
1614 void View::releaseConfigView()
1615 {
1616     m_primaryConfigView = nullptr;
1617 }
1618 
1619 //! release grab and restore mouse state
1620 void View::unblockMouse(int x, int y)
1621 {
1622     setMouseGrabEnabled(false);
1623 
1624     m_releaseGrab_x = x;
1625     m_releaseGrab_y = y;
1626     m_releaseGrabTimer.start();
1627 }
1628 
1629 void View::releaseGrab()
1630 {
1631     //! ungrab mouse
1632     if (mouseGrabberItem()) {
1633         mouseGrabberItem()->ungrabMouse();
1634     }
1635 
1636     //! properly release grabbed mouse in order to inform all views
1637     setMouseGrabEnabled(true);
1638     setMouseGrabEnabled(false);
1639 
1640     //! Send a fake QEvent::Leave to inform applets for mouse leaving the view
1641     QHoverEvent e(QEvent::Leave, QPoint(-5,-5),  QPoint(m_releaseGrab_x, m_releaseGrab_y));
1642     QCoreApplication::instance()->sendEvent(this, &e);
1643 }
1644 
1645 QAction *View::action(const QString &name)
1646 {
1647     if (!containment()) {
1648         return nullptr;
1649     }
1650 
1651     return this->containment()->actions()->action(name);
1652 }
1653 
1654 QVariantList View::containmentActions() const
1655 {
1656     QVariantList actions;
1657 
1658     if (!containment()) {
1659         return actions;
1660     }
1661 
1662     const QString trigger = "RightButton;NoModifier";
1663     Plasma::ContainmentActions *plugin = this->containment()->containmentActions().value(trigger);
1664 
1665     if (!plugin) {
1666         return actions;
1667     }
1668 
1669     if (plugin->containment() != this->containment()) {
1670         plugin->setContainment(this->containment());
1671         // now configure it
1672         KConfigGroup cfg(this->containment()->corona()->config(), "ActionPlugins");
1673         cfg = KConfigGroup(&cfg, QString::number(this->containment()->containmentType()));
1674         KConfigGroup pluginConfig = KConfigGroup(&cfg, trigger);
1675         plugin->restore(pluginConfig);
1676     }
1677 
1678     for (QAction *ac : plugin->contextualActions()) {
1679         actions << QVariant::fromValue<QAction *>(ac);
1680     }
1681 
1682     return actions;
1683 }
1684 
1685 bool View::isHighestPriorityView() {
1686     if (m_layout) {
1687         return this == m_layout->highestPriorityView();
1688     }
1689 
1690     return false;
1691 }
1692 
1693 //! BEGIN: WORKAROUND order to force top panels always on top and above left/right panels
1694 void View::topViewAlwaysOnTop()
1695 {
1696     if (!m_visibility) {
1697         return;
1698     }
1699 
1700     if (location() == Plasma::Types::TopEdge
1701             && m_visibility->mode() != Latte::Types::WindowsCanCover
1702             && m_visibility->mode() != Latte::Types::WindowsAlwaysCover) {
1703         //! this is needed in order to preserve that the top dock will be above others.
1704         //! Unity layout paradigm is a good example for this. The top panel shadow
1705         //! should be always on top compared to left panel
1706         m_visibility->setViewOnFrontLayer();
1707     }
1708 }
1709 
1710 void View::verticalUnityViewHasFocus()
1711 {
1712     if (formFactor() == Plasma::Types::Vertical
1713             && (y() != screenGeometry().y())
1714             && ( (m_alignment == Latte::Types::Justify && m_maxLength == 1.0)
1715                  ||(m_alignment == Latte::Types::Top && m_offset == 0.0) )) {
1716         emit m_corona->verticalUnityViewHasFocus();
1717     }
1718 }
1719 //! END: WORKAROUND
1720 
1721 //!BEGIN configuration functions
1722 void View::saveConfig()
1723 {
1724     if (!this->containment()) {
1725         return;
1726     }
1727 
1728     auto config = this->containment()->config();
1729     config.writeEntry("onPrimary", onPrimary());
1730     config.writeEntry("byPassWM", byPassWM());
1731     config.writeEntry("isPreferredForShortcuts", isPreferredForShortcuts());
1732     config.writeEntry("name", m_name);
1733     config.writeEntry("viewType", (int)m_type);
1734 }
1735 
1736 void View::restoreConfig()
1737 {
1738     if (!this->containment()) {
1739         return;
1740     }
1741 
1742     auto config = this->containment()->config();
1743     m_onPrimary = config.readEntry("onPrimary", true);
1744     m_alignment = static_cast<Latte::Types::Alignment>(config.group("General").readEntry("alignment", (int)Latte::Types::Center));
1745     m_byPassWM = config.readEntry("byPassWM", false);
1746     m_isPreferredForShortcuts = config.readEntry("isPreferredForShortcuts", false);
1747     m_name = config.readEntry("name", QString());
1748 
1749     //! Send changed signals at the end in order to be sure that saveConfig
1750     //! wont rewrite default/invalid values
1751     emit alignmentChanged();
1752     emit nameChanged();
1753     emit onPrimaryChanged();
1754     emit byPassWMChanged();
1755 }
1756 //!END configuration functions
1757 
1758 }
1759 //!END namespace