File indexing completed on 2024-05-05 17:39:21
0001 /* 0002 * Copyright 2018 Michail Vourlakos <mvourlakos@gmail.com> 0003 * 0004 * This file is part of Latte-Dock 0005 * 0006 * Latte-Dock is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU General Public License as 0008 * published by the Free Software Foundation; either version 2 of 0009 * the License, or (at your option) any later version. 0010 * 0011 * Latte-Dock is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 * GNU General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU General Public License 0017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0018 */ 0019 0020 #include "positioner.h" 0021 0022 // local 0023 #include "effects.h" 0024 #include "view.h" 0025 #include "../lattecorona.h" 0026 #include "../screenpool.h" 0027 #include "../settings/universalsettings.h" 0028 #include "../../liblatte2/types.h" 0029 0030 // Qt 0031 #include <QDebug> 0032 0033 // KDE 0034 #include <KWayland/Client/plasmashell.h> 0035 #include <KWayland/Client/surface.h> 0036 #include <KWindowSystem> 0037 0038 namespace Latte { 0039 namespace ViewPart { 0040 0041 Positioner::Positioner(Latte::View *parent) 0042 : QObject(parent), 0043 m_view(parent) 0044 { 0045 m_screenSyncTimer.setSingleShot(true); 0046 m_screenSyncTimer.setInterval(2000); 0047 connect(&m_screenSyncTimer, &QTimer::timeout, this, &Positioner::reconsiderScreen); 0048 0049 //! under X11 it was identified that windows many times especially under screen changes 0050 //! don't end up at the correct position and size. This timer will enforce repositionings 0051 //! and resizes every 500ms if the window hasn't end up to correct values and until this 0052 //! is achieved 0053 m_validateGeometryTimer.setSingleShot(true); 0054 m_validateGeometryTimer.setInterval(500); 0055 connect(&m_validateGeometryTimer, &QTimer::timeout, this, &Positioner::syncGeometry); 0056 0057 m_corona = qobject_cast<Latte::Corona *>(m_view->corona()); 0058 0059 if (m_corona) { 0060 if (KWindowSystem::isPlatformX11()) { 0061 m_trackedWindowId = m_view->winId(); 0062 m_corona->wm()->registerIgnoredWindow(m_trackedWindowId); 0063 0064 connect(m_view, &Latte::View::forcedShown, this, [&]() { 0065 m_corona->wm()->unregisterIgnoredWindow(m_trackedWindowId); 0066 m_trackedWindowId = m_view->winId(); 0067 m_corona->wm()->registerIgnoredWindow(m_trackedWindowId); 0068 }); 0069 } else { 0070 connect(m_corona->wm(), &WindowSystem::AbstractWindowInterface::latteWindowAdded, this, [&]() { 0071 if (m_trackedWindowId.isNull()) { 0072 m_trackedWindowId = m_corona->wm()->winIdFor("latte-dock", m_view->geometry()); 0073 m_corona->wm()->registerIgnoredWindow(m_trackedWindowId); 0074 } 0075 }); 0076 } 0077 0078 ///// 0079 0080 m_screenSyncTimer.setInterval(qMax(m_corona->universalSettings()->screenTrackerInterval() - 500, 1000)); 0081 connect(m_corona->universalSettings(), &UniversalSettings::screenTrackerIntervalChanged, this, [&]() { 0082 m_screenSyncTimer.setInterval(qMax(m_corona->universalSettings()->screenTrackerInterval() - 500, 1000)); 0083 }); 0084 0085 connect(m_corona, &Latte::Corona::viewLocationChanged, this, [&]() { 0086 //! check if an edge has been freed for a primary dock 0087 //! from another screen 0088 if (m_view->onPrimary()) { 0089 m_screenSyncTimer.start(); 0090 } 0091 }); 0092 } 0093 0094 init(); 0095 } 0096 0097 Positioner::~Positioner() 0098 { 0099 m_inDelete = true; 0100 m_corona->wm()->unregisterIgnoredWindow(m_trackedWindowId); 0101 0102 m_screenSyncTimer.stop(); 0103 m_validateGeometryTimer.stop(); 0104 } 0105 0106 void Positioner::init() 0107 { 0108 //! connections 0109 connect(this, &Positioner::screenGeometryChanged, this, &Positioner::syncGeometry); 0110 0111 connect(m_view, &QQuickWindow::xChanged, this, &Positioner::validateDockGeometry); 0112 connect(m_view, &QQuickWindow::yChanged, this, &Positioner::validateDockGeometry); 0113 connect(m_view, &QQuickWindow::widthChanged, this, &Positioner::validateDockGeometry); 0114 connect(m_view, &QQuickWindow::heightChanged, this, &Positioner::validateDockGeometry); 0115 connect(m_view, &QQuickWindow::screenChanged, this, &Positioner::currentScreenChanged); 0116 connect(m_view, &QQuickWindow::screenChanged, this, &Positioner::screenChanged); 0117 0118 connect(m_view, &Latte::View::behaveAsPlasmaPanelChanged, this, &Positioner::syncGeometry); 0119 connect(m_view, &Latte::View::maxThicknessChanged, this, &Positioner::syncGeometry); 0120 connect(m_view, &Latte::View::maxLengthChanged, this, &Positioner::syncGeometry); 0121 connect(m_view, &Latte::View::offsetChanged, this, &Positioner::syncGeometry); 0122 0123 connect(m_view, &Latte::View::absoluteGeometryChanged, this, [&]() { 0124 if (m_view->behaveAsPlasmaPanel()) { 0125 syncGeometry(); 0126 } 0127 }); 0128 0129 connect(m_view, &Latte::View::locationChanged, this, [&]() { 0130 updateFormFactor(); 0131 syncGeometry(); 0132 }); 0133 0134 connect(m_view, &Latte::View::normalThicknessChanged, this, [&]() { 0135 if (m_view->behaveAsPlasmaPanel()) { 0136 syncGeometry(); 0137 } 0138 }); 0139 0140 connect(m_view->effects(), &Latte::ViewPart::Effects::drawShadowsChanged, this, [&]() { 0141 if (!m_view->behaveAsPlasmaPanel()) { 0142 syncGeometry(); 0143 } 0144 }); 0145 0146 connect(m_view->effects(), &Latte::ViewPart::Effects::innerShadowChanged, this, [&]() { 0147 if (m_view->behaveAsPlasmaPanel()) { 0148 syncGeometry(); 0149 } 0150 }); 0151 0152 connect(qGuiApp, &QGuiApplication::screenAdded, this, &Positioner::screenChanged); 0153 connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, &Positioner::screenChanged); 0154 0155 initSignalingForLocationChangeSliding(); 0156 } 0157 0158 int Positioner::currentScreenId() const 0159 { 0160 auto *latteCorona = qobject_cast<Latte::Corona *>(m_view->corona()); 0161 0162 if (latteCorona) { 0163 return latteCorona->screenPool()->id(m_screenToFollowId); 0164 } 0165 0166 return -1; 0167 } 0168 0169 QString Positioner::currentScreenName() const 0170 { 0171 return m_screenToFollowId; 0172 } 0173 0174 bool Positioner::setCurrentScreen(const QString id) 0175 { 0176 QScreen *nextScreen{qGuiApp->primaryScreen()}; 0177 0178 if (id != "primary") { 0179 for (const auto scr : qGuiApp->screens()) { 0180 if (scr && scr->name() == id) { 0181 nextScreen = scr; 0182 break; 0183 } 0184 } 0185 } 0186 0187 if (m_screenToFollow == nextScreen) { 0188 return true; 0189 } 0190 0191 if (nextScreen) { 0192 if (m_view->layout()) { 0193 auto freeEdges = m_view->layout()->freeEdges(nextScreen); 0194 0195 if (!freeEdges.contains(m_view->location())) { 0196 return false; 0197 } else { 0198 m_goToScreen = nextScreen; 0199 0200 //! asynchronous call in order to not crash from configwindow 0201 //! deletion from sliding out animation 0202 QTimer::singleShot(100, [this]() { 0203 emit hideDockDuringScreenChangeStarted(); 0204 }); 0205 } 0206 } 0207 } 0208 0209 return true; 0210 } 0211 0212 //! this function updates the dock's associated screen. 0213 //! updateScreenId = true, update also the m_screenToFollowId 0214 //! updateScreenId = false, do not update the m_screenToFollowId 0215 //! that way an explicit dock can be shown in another screen when 0216 //! there isnt a tasks dock running in the system and for that 0217 //! dock its first origin screen is stored and that way when 0218 //! that screen is reconnected the dock will return to its original 0219 //! place 0220 void Positioner::setScreenToFollow(QScreen *scr, bool updateScreenId) 0221 { 0222 if (!scr || (scr && (m_screenToFollow == scr) && (m_view->screen() == scr))) { 0223 return; 0224 } 0225 0226 qDebug() << "setScreenToFollow() called for screen:" << scr->name() << " update:" << updateScreenId; 0227 0228 m_screenToFollow = scr; 0229 0230 if (updateScreenId) { 0231 m_screenToFollowId = scr->name(); 0232 } 0233 0234 qDebug() << "adapting to screen..."; 0235 m_view->setScreen(scr); 0236 0237 if (m_view->containment()) { 0238 m_view->containment()->reactToScreenChange(); 0239 } 0240 0241 connect(scr, &QScreen::geometryChanged, this, &Positioner::screenGeometryChanged); 0242 syncGeometry(); 0243 m_view->updateAbsoluteGeometry(true); 0244 qDebug() << "setScreenToFollow() ended..."; 0245 0246 emit screenGeometryChanged(); 0247 emit currentScreenChanged(); 0248 } 0249 0250 //! the main function which decides if this dock is at the 0251 //! correct screen 0252 void Positioner::reconsiderScreen() 0253 { 0254 if (m_inDelete) { 0255 return; 0256 } 0257 0258 qDebug() << "reconsiderScreen() called..."; 0259 qDebug() << " Delayer "; 0260 0261 for (const auto scr : qGuiApp->screens()) { 0262 qDebug() << " D, found screen: " << scr->name(); 0263 } 0264 0265 bool screenExists{false}; 0266 0267 //!check if the associated screen is running 0268 for (const auto scr : qGuiApp->screens()) { 0269 if (m_screenToFollowId == scr->name() 0270 || (m_view->onPrimary() && scr == qGuiApp->primaryScreen())) { 0271 screenExists = true; 0272 } 0273 } 0274 0275 qDebug() << "dock screen exists ::: " << screenExists; 0276 0277 //! 1.a primary dock must be always on the primary screen 0278 if (m_view->onPrimary() && (m_screenToFollowId != qGuiApp->primaryScreen()->name() 0279 || m_screenToFollow != qGuiApp->primaryScreen() 0280 || m_view->screen() != qGuiApp->primaryScreen())) { 0281 using Plasma::Types; 0282 QList<Types::Location> edges{Types::BottomEdge, Types::LeftEdge, 0283 Types::TopEdge, Types::RightEdge}; 0284 0285 edges = m_view->layout() ? m_view->layout()->availableEdgesForView(qGuiApp->primaryScreen(), m_view) : edges; 0286 0287 //change to primary screen only if the specific edge is free 0288 qDebug() << "updating the primary screen for dock..."; 0289 qDebug() << "available primary screen edges:" << edges; 0290 qDebug() << "dock location:" << m_view->location(); 0291 0292 if (edges.contains(m_view->location())) { 0293 //! case 1 0294 qDebug() << "reached case 1: of updating dock primary screen..."; 0295 setScreenToFollow(qGuiApp->primaryScreen()); 0296 } 0297 } else if (!m_view->onPrimary()) { 0298 //! 2.an explicit dock must be always on the correct associated screen 0299 //! there are cases that window manager misplaces the dock, this function 0300 //! ensures that this dock will return at its correct screen 0301 for (const auto scr : qGuiApp->screens()) { 0302 if (scr && scr->name() == m_screenToFollowId) { 0303 qDebug() << "reached case 2: updating the explicit screen for dock..."; 0304 setScreenToFollow(scr); 0305 break; 0306 } 0307 } 0308 } 0309 0310 syncGeometry(); 0311 qDebug() << "reconsiderScreen() ended..."; 0312 } 0313 0314 void Positioner::screenChanged(QScreen *scr) 0315 { 0316 m_screenSyncTimer.start(); 0317 0318 //! this is needed in order to update the struts on screen change 0319 //! and even though the geometry has been set correctly the offsets 0320 //! of the screen must be updated to the new ones 0321 if (m_view->visibility() && m_view->visibility()->mode() == Latte::Types::AlwaysVisible) { 0322 m_view->updateAbsoluteGeometry(true); 0323 } 0324 } 0325 0326 void Positioner::syncGeometry() 0327 { 0328 if (!(m_view->screen() && m_view->containment()) || m_inDelete) { 0329 return; 0330 } 0331 0332 bool found{false}; 0333 0334 qDebug() << "syncGeometry() called..."; 0335 0336 //! before updating the positioning and geometry of the dock 0337 //! we make sure that the dock is at the correct screen 0338 if (m_view->screen() != m_screenToFollow) { 0339 qDebug() << "Sync Geometry screens inconsistent!!!! "; 0340 0341 if (m_screenToFollow) { 0342 qDebug() << "Sync Geometry screens inconsistent for m_screenToFollow:" << m_screenToFollow->name() << " dock screen:" << m_view->screen()->name(); 0343 } 0344 0345 if (!m_screenSyncTimer.isActive()) { 0346 m_screenSyncTimer.start(); 0347 } 0348 } else { 0349 found = true; 0350 } 0351 0352 //! if the dock isnt at the correct screen the calculations 0353 //! are not executed 0354 if (found) { 0355 //! compute the free screen rectangle for vertical panels only once 0356 //! this way the costly QRegion computations are calculated only once 0357 //! instead of two times (both inside the resizeWindow and the updatePosition) 0358 QRegion freeRegion;; 0359 QRect maximumRect; 0360 QRect availableScreenRect{m_view->screen()->geometry()}; 0361 0362 if (m_view->formFactor() == Plasma::Types::Vertical) { 0363 QString layoutName = m_view->layout() ? m_view->layout()->name() : QString(); 0364 auto latteCorona = qobject_cast<Latte::Corona *>(m_view->corona()); 0365 int fixedScreen = m_view->onPrimary() ? latteCorona->screenPool()->primaryScreenId() : m_view->containment()->screen(); 0366 0367 QList<Types::Visibility> modes({Latte::Types::AlwaysVisible, 0368 Latte::Types::DodgeActive, 0369 Latte::Types::DodgeMaximized, 0370 Latte::Types::DodgeAllWindows, 0371 Latte::Types::WindowsGoBelow}); 0372 0373 QList<Plasma::Types::Location> edges({Plasma::Types::TopEdge, 0374 Plasma::Types::BottomEdge}); 0375 0376 freeRegion = latteCorona->availableScreenRegionWithCriteria(fixedScreen, layoutName, modes, edges); 0377 0378 maximumRect = maximumNormalGeometry(); 0379 QRegion availableRegion = freeRegion.intersected(maximumRect); 0380 availableScreenRect = freeRegion.intersected(maximumRect).boundingRect(); 0381 float area = 0; 0382 0383 //! it is used to choose which or the availableRegion rectangles will 0384 //! be the one representing dock geometry 0385 for (QRegion::const_iterator p_rect=availableRegion.begin(); p_rect!=availableRegion.end(); ++p_rect) { 0386 //! the area of each rectangle in calculated in squares of 50x50 0387 //! this is a way to avoid enourmous numbers for area value 0388 float tempArea = (float)((*p_rect).width() * (*p_rect).height()) / 2500; 0389 0390 if (tempArea > area) { 0391 availableScreenRect = (*p_rect); 0392 area = tempArea; 0393 } 0394 } 0395 0396 if (availableRegion.rectCount() > 1 && m_view->behaveAsPlasmaPanel()) { 0397 m_view->effects()->setForceDrawCenteredBorders(true); 0398 } else { 0399 m_view->effects()->setForceDrawCenteredBorders(false); 0400 } 0401 } else { 0402 m_view->effects()->setForceDrawCenteredBorders(false); 0403 } 0404 0405 m_view->effects()->updateEnabledBorders(); 0406 resizeWindow(availableScreenRect); 0407 updatePosition(availableScreenRect); 0408 0409 qDebug() << "syncGeometry() calculations for screen: " << m_view->screen()->name() << " _ " << m_view->screen()->geometry(); 0410 qDebug() << "syncGeometry() calculations for edge: " << m_view->location(); 0411 } 0412 0413 qDebug() << "syncGeometry() ended..."; 0414 0415 // qDebug() << "dock geometry:" << qRectToStr(geometry()); 0416 } 0417 0418 void Positioner::validateDockGeometry() 0419 { 0420 if (m_view->geometry() != m_validGeometry) { 0421 m_validateGeometryTimer.start(); 0422 } 0423 } 0424 0425 //! this is used mainly from vertical panels in order to 0426 //! to get the maximum geometry that can be used from the dock 0427 //! based on their alignment type and the location dock 0428 QRect Positioner::maximumNormalGeometry() 0429 { 0430 int xPos = 0; 0431 int yPos = m_view->screen()->geometry().y();; 0432 int maxHeight = m_view->screen()->geometry().height(); 0433 int maxWidth = m_view->normalThickness(); 0434 QRect maxGeometry; 0435 maxGeometry.setRect(0, 0, maxWidth, maxHeight); 0436 0437 switch (m_view->location()) { 0438 case Plasma::Types::LeftEdge: 0439 xPos = m_view->screen()->geometry().x(); 0440 maxGeometry.setRect(xPos, yPos, maxWidth, maxHeight); 0441 break; 0442 0443 case Plasma::Types::RightEdge: 0444 xPos = m_view->screen()->geometry().right() - maxWidth + 1; 0445 maxGeometry.setRect(xPos, yPos, maxWidth, maxHeight); 0446 break; 0447 0448 default: 0449 //! bypass clang warnings 0450 break; 0451 } 0452 0453 //! this is needed in order to preserve that the top dock will be above 0454 //! the others in case flag bypasswindowmanagerhint hasn't be set, 0455 //! such a case is the AlwaysVisible mode 0456 if (m_view->location() == Plasma::Types::TopEdge) { 0457 KWindowSystem::setState(m_view->winId(), NET::KeepAbove); 0458 } else { 0459 KWindowSystem::clearState(m_view->winId(), NET::KeepAbove); 0460 } 0461 0462 return maxGeometry; 0463 } 0464 0465 void Positioner::updatePosition(QRect availableScreenRect) 0466 { 0467 QRect screenGeometry{availableScreenRect}; 0468 QPoint position; 0469 position = {0, 0}; 0470 0471 const auto length = [&](int length) -> int { 0472 float offs = static_cast<float>(m_view->offset()); 0473 return static_cast<int>(length * ((1 - m_view->maxLength()) / 2) + length * (offs / 100)); 0474 }; 0475 int cleanThickness = m_view->normalThickness() - m_view->effects()->innerShadow(); 0476 0477 switch (m_view->location()) { 0478 case Plasma::Types::TopEdge: 0479 if (m_view->behaveAsPlasmaPanel()) { 0480 position = {screenGeometry.x() + length(screenGeometry.width()), screenGeometry.y()}; 0481 } else { 0482 position = {screenGeometry.x(), screenGeometry.y()}; 0483 } 0484 0485 break; 0486 0487 case Plasma::Types::BottomEdge: 0488 if (m_view->behaveAsPlasmaPanel()) { 0489 position = {screenGeometry.x() + length(screenGeometry.width()), 0490 screenGeometry.y() + screenGeometry.height() - cleanThickness 0491 }; 0492 } else { 0493 position = {screenGeometry.x(), screenGeometry.y() + screenGeometry.height() - m_view->height()}; 0494 } 0495 0496 break; 0497 0498 case Plasma::Types::RightEdge: 0499 if (m_view->behaveAsPlasmaPanel()) { 0500 position = {availableScreenRect.right() - cleanThickness + 1, 0501 availableScreenRect.y() + length(availableScreenRect.height()) 0502 }; 0503 } else { 0504 position = {availableScreenRect.right() - m_view->width() + 1, availableScreenRect.y()}; 0505 } 0506 0507 break; 0508 0509 case Plasma::Types::LeftEdge: 0510 if (m_view->behaveAsPlasmaPanel()) { 0511 position = {availableScreenRect.x(), availableScreenRect.y() + length(availableScreenRect.height())}; 0512 } else { 0513 position = {availableScreenRect.x(), availableScreenRect.y()}; 0514 } 0515 0516 break; 0517 0518 default: 0519 qWarning() << "wrong location, couldn't update the panel position" 0520 << m_view->location(); 0521 } 0522 0523 m_validGeometry.setTopLeft(position); 0524 0525 m_view->setPosition(position); 0526 0527 if (m_view->surface()) { 0528 m_view->surface()->setPosition(position); 0529 } 0530 } 0531 0532 void Positioner::resizeWindow(QRect availableScreenRect) 0533 { 0534 QSize screenSize = m_view->screen()->size(); 0535 QSize size = (m_view->formFactor() == Plasma::Types::Vertical) ? QSize(m_view->maxThickness(), availableScreenRect.height()) : QSize(screenSize.width(), m_view->maxThickness()); 0536 0537 if (m_view->formFactor() == Plasma::Types::Vertical) { 0538 //qDebug() << "MAXIMUM RECT :: " << maximumRect << " - AVAILABLE RECT :: " << availableRect; 0539 if (m_view->behaveAsPlasmaPanel()) { 0540 size.setWidth(m_view->normalThickness()); 0541 size.setHeight(static_cast<int>(m_view->maxLength() * availableScreenRect.height())); 0542 } 0543 } else { 0544 if (m_view->behaveAsPlasmaPanel()) { 0545 size.setWidth(static_cast<int>(m_view->maxLength() * screenSize.width())); 0546 size.setHeight(m_view->normalThickness()); 0547 } 0548 } 0549 0550 m_validGeometry.setSize(size); 0551 0552 m_view->setMinimumSize(size); 0553 m_view->setMaximumSize(size); 0554 m_view->resize(size); 0555 0556 if (m_view->formFactor() == Plasma::Types::Horizontal) { 0557 emit windowSizeChanged(); 0558 } 0559 } 0560 0561 void Positioner::updateFormFactor() 0562 { 0563 if (!m_view->containment()) 0564 return; 0565 0566 switch (m_view->location()) { 0567 case Plasma::Types::TopEdge: 0568 case Plasma::Types::BottomEdge: 0569 m_view->containment()->setFormFactor(Plasma::Types::Horizontal); 0570 break; 0571 0572 case Plasma::Types::LeftEdge: 0573 case Plasma::Types::RightEdge: 0574 m_view->containment()->setFormFactor(Plasma::Types::Vertical); 0575 break; 0576 0577 default: 0578 qWarning() << "wrong location, couldn't update the panel position" << m_view->location(); 0579 } 0580 } 0581 0582 void Positioner::initSignalingForLocationChangeSliding() 0583 { 0584 //! signals to handle the sliding-in/out during location changes 0585 connect(this, &Positioner::hideDockDuringLocationChangeStarted, this, &Positioner::onHideWindowsForSlidingOut); 0586 0587 connect(m_view, &View::locationChanged, this, [&]() { 0588 if (m_goToLocation != Plasma::Types::Floating) { 0589 m_goToLocation = Plasma::Types::Floating; 0590 QTimer::singleShot(100, [this]() { 0591 m_view->effects()->setAnimationsBlocked(false); 0592 emit showDockAfterLocationChangeFinished(); 0593 m_view->showSettingsWindow(); 0594 0595 if (m_view->layout()) { 0596 //! This is needed in case the edge is occupied and the occupying 0597 //! view must be deleted 0598 m_view->layout()->syncLatteViewsToScreens(); 0599 } 0600 0601 emit edgeChanged(); 0602 }); 0603 } 0604 }); 0605 0606 //! signals to handle the sliding-in/out during screen changes 0607 connect(this, &Positioner::hideDockDuringScreenChangeStarted, this, &Positioner::onHideWindowsForSlidingOut); 0608 0609 connect(this, &Positioner::currentScreenChanged, this, [&]() { 0610 if (m_goToScreen) { 0611 m_goToScreen = nullptr; 0612 QTimer::singleShot(100, [this]() { 0613 m_view->effects()->setAnimationsBlocked(false); 0614 emit showDockAfterScreenChangeFinished(); 0615 m_view->showSettingsWindow(); 0616 0617 if (m_view->layout()) { 0618 //! This is needed in case the edge is occupied and the occupying 0619 //! view must be deleted 0620 m_view->layout()->syncLatteViewsToScreens(); 0621 } 0622 0623 emit edgeChanged(); 0624 }); 0625 } 0626 }); 0627 0628 //! signals to handle the sliding-in/out during moving to another layout 0629 connect(this, &Positioner::hideDockDuringMovingToLayoutStarted, this, &Positioner::onHideWindowsForSlidingOut); 0630 0631 connect(m_view, &View::layoutChanged, this, [&]() { 0632 if (!m_moveToLayout.isEmpty() && m_view->layout()) { 0633 m_moveToLayout = ""; 0634 QTimer::singleShot(100, [this]() { 0635 m_view->effects()->setAnimationsBlocked(false); 0636 emit showDockAfterMovingToLayoutFinished(); 0637 m_view->showSettingsWindow(); 0638 emit edgeChanged(); 0639 }); 0640 } 0641 }); 0642 0643 //! ---- both cases ---- !// 0644 //! this is used for both location and screen change cases, this signal 0645 //! is send when the sliding-out animation has finished 0646 connect(this, &Positioner::hideDockDuringLocationChangeFinished, this, [&]() { 0647 m_view->effects()->setAnimationsBlocked(true); 0648 0649 if (m_goToLocation != Plasma::Types::Floating) { 0650 m_view->setLocation(m_goToLocation); 0651 } else if (m_goToScreen) { 0652 setScreenToFollow(m_goToScreen); 0653 } else if (!m_moveToLayout.isEmpty()) { 0654 m_view->moveToLayout(m_moveToLayout); 0655 } 0656 }); 0657 } 0658 0659 bool Positioner::inLocationChangeAnimation() 0660 { 0661 return ((m_goToLocation != Plasma::Types::Floating) || (m_moveToLayout != "") || m_goToScreen); 0662 } 0663 0664 void Positioner::hideDockDuringLocationChange(int goToLocation) 0665 { 0666 m_goToLocation = static_cast<Plasma::Types::Location>(goToLocation); 0667 emit hideDockDuringLocationChangeStarted(); 0668 } 0669 0670 void Positioner::hideDockDuringMovingToLayout(QString layoutName) 0671 { 0672 m_moveToLayout = layoutName; 0673 emit hideDockDuringMovingToLayoutStarted(); 0674 } 0675 0676 } 0677 }