diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 950b362e..f7010e7f 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -1,85 +1,86 @@ set(lattedock-app_SRCS ../liblattedock/dock.cpp packageplugins/shell/dockpackage.cpp abstractwindowinterface.cpp alternativeshelper.cpp commontools.cpp dockcorona.cpp globalshortcuts.cpp importer.cpp infoview.cpp launcherssignals.cpp layout.cpp layoutmanager.cpp plasmathemeextended.cpp schemecolors.cpp screenpool.cpp settingsdialog.cpp sortedactivitiesmodel.cpp universalsettings.cpp waylandinterface.cpp windowinfowrap.cpp xwindowinterface.cpp dock/dockconfigview.cpp dock/dockmenumanager.cpp dock/docksecconfigview.cpp dock/dockview.cpp + dock/effects.cpp dock/panelshadows.cpp dock/positioner.cpp dock/screenedgeghostwindow.cpp dock/visibilitymanager.cpp layoutsDelegates/activitycmbboxdelegate.cpp layoutsDelegates/checkboxdelegate.cpp layoutsDelegates/colorcmbboxdelegate.cpp layoutsDelegates/colorcmbboxitemdelegate.cpp layoutsDelegates/layoutnamedelegate.cpp main.cpp ) set(latte_dbusXML dbus/org.kde.LatteDock.xml) qt5_add_dbus_adaptor(lattedock-app_SRCS ${latte_dbusXML} dockcorona.h Latte::DockCorona lattedockadaptor) ki18n_wrap_ui(lattedock-app_SRCS settingsdialog.ui) add_executable(latte-dock ${lattedock-app_SRCS}) include(FakeTarget.cmake) target_link_libraries(latte-dock Qt5::DBus Qt5::Quick Qt5::Qml KF5::I18n KF5::DBusAddons KF5::Declarative KF5::CoreAddons KF5::GlobalAccel KF5::Archive KF5::Crash KF5::XmlGui KF5::Plasma KF5::PlasmaQuick KF5::Activities KF5::Notifications KF5::NewStuff KF5::QuickAddons KF5::WaylandClient ) if(HAVE_X11) target_link_libraries(latte-dock Qt5::X11Extras KF5::WindowSystem ${X11_LIBRARIES} ${XCB_LIBRARIES} ) endif() configure_file(org.kde.latte-dock.desktop.cmake org.kde.latte-dock.desktop) configure_file(org.kde.latte-dock.appdata.xml.cmake org.kde.latte-dock.appdata.xml) install(TARGETS latte-dock ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.latte-dock.desktop DESTINATION ${KDE_INSTALL_APPDIR}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.kde.latte-dock.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) install(FILES dbus/org.kde.LatteDock.xml DESTINATION ${KDE_INSTALL_DBUSINTERFACEDIR}) install(FILES lattedock.notifyrc DESTINATION ${KNOTIFYRC_INSTALL_DIR}) install(FILES latte-layouts.knsrc DESTINATION ${CONFIG_INSTALL_DIR}) diff --git a/app/dock/dockview.cpp b/app/dock/dockview.cpp index d7c4db55..08bf6c8a 100644 --- a/app/dock/dockview.cpp +++ b/app/dock/dockview.cpp @@ -1,1497 +1,1239 @@ /* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "dockview.h" #include "dockconfigview.h" #include "dockmenumanager.h" - +#include "effects.h" #include "panelshadows_p.h" #include "positioner.h" #include "visibilitymanager.h" #include "../dockcorona.h" #include "../layout.h" #include "../layoutmanager.h" #include "../screenpool.h" #include "../plasmathemeextended.h" #include "../universalsettings.h" #include "../../liblattedock/extras.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Latte { //! both alwaysVisible and dockWinBehavior are passed through corona because //! during the dock window creation containment hasn't been set, but these variables //! are needed in order for window flags to be set correctly DockView::DockView(Plasma::Corona *corona, QScreen *targetScreen, bool dockWindowBehavior) : PlasmaQuick::ContainmentView(corona), m_menuManager(new DockMenuManager(this)), - m_positioner(new Positioner(this)) + m_effects(new View::Effects(this)), + m_positioner(new Positioner(this)) //needs to be created after Effects becuase it catches some of its signals { setTitle(corona->kPackage().metadata().name()); setIcon(qGuiApp->windowIcon()); setResizeMode(QuickViewSharedEngine::SizeRootObjectToView); setColor(QColor(Qt::transparent)); setClearBeforeRendering(true); const auto flags = Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::NoDropShadowWindowHint | Qt::WindowDoesNotAcceptFocus; if (dockWindowBehavior) { setFlags(flags); } else { setFlags(flags | Qt::BypassWindowManagerHint); } KWindowSystem::setOnAllDesktops(winId(), true); if (targetScreen) m_positioner->setScreenToFollow(targetScreen); else m_positioner->setScreenToFollow(qGuiApp->primaryScreen()); connect(this, &DockView::containmentChanged , this, [ &, dockWindowBehavior]() { qDebug() << "dock view c++ containment changed 1..."; if (!this->containment()) return; qDebug() << "dock view c++ containment changed 2..."; //! First load default values from file restoreConfig(); //! Afterwards override that values in case during creation something different is needed setDockWinBehavior(dockWindowBehavior); //! Check the screen assigned to this dock reconsiderScreen(); if (!m_visibility) { m_visibility = new VisibilityManager(this); connect(m_visibility, &VisibilityManager::isHiddenChanged, this, [&]() { if (m_visibility->isHidden()) { deactivateApplets(); } }); } connect(this->containment(), SIGNAL(statusChanged(Plasma::Types::ItemStatus)), SLOT(statusChanged(Plasma::Types::ItemStatus))); }, Qt::DirectConnection); auto *dockCorona = qobject_cast(this->corona()); if (dockCorona) { connect(dockCorona, &DockCorona::docksCountChanged, this, &DockView::docksCountChanged); connect(this, &DockView::docksCountChanged, this, &DockView::totalDocksCountChanged); connect(dockCorona, &DockCorona::dockLocationChanged, this, &DockView::dockLocationChanged); } } DockView::~DockView() { m_inDelete = true; disconnect(corona(), &Plasma::Corona::availableScreenRectChanged, this, &DockView::availableScreenRectChanged); disconnect(containment(), SIGNAL(statusChanged(Plasma::Types::ItemStatus)), this, SLOT(statusChanged(Plasma::Types::ItemStatus))); qDebug() << "dock view deleting..."; rootContext()->setContextProperty(QStringLiteral("dock"), nullptr); //! this disconnect does not free up connections correctly when //! dockView is deleted. A crash for this example is the following: //! switch to Alternative Session and disable compositing, //! the signal creating the crash was probably from deleted //! windows. //! this->disconnect(); if (m_configView) { m_configView->setVisible(false);//hide(); } if (m_menuManager) { - m_menuManager->deleteLater(); + delete m_menuManager; } - if (m_visibility) - delete m_visibility; - + //needs to be deleted before Effects becuase it catches some of its signals if (m_positioner) { delete m_positioner; } + + if (m_effects) { + delete m_effects; + } + + if (m_visibility) + delete m_visibility; } void DockView::init() { connect(this, &QQuickWindow::screenChanged, this, &DockView::docksCountChanged); connect(this, &QQuickWindow::xChanged, this, &DockView::xChanged); connect(this, &QQuickWindow::xChanged, this, &DockView::updateAbsDockGeometry); connect(this, &QQuickWindow::yChanged, this, &DockView::yChanged); connect(this, &QQuickWindow::yChanged, this, &DockView::updateAbsDockGeometry); connect(this, &QQuickWindow::widthChanged, this, &DockView::widthChanged); connect(this, &QQuickWindow::widthChanged, this, &DockView::updateAbsDockGeometry); connect(this, &QQuickWindow::heightChanged, this, &DockView::heightChanged); connect(this, &QQuickWindow::heightChanged, this, &DockView::updateAbsDockGeometry); connect(corona(), &Plasma::Corona::availableScreenRectChanged, this, &DockView::availableScreenRectChanged); connect(m_positioner, &Positioner::currentScreenChanged, this, &DockView::currentScreenChanged); connect(m_positioner, &Positioner::screenGeometryChanged, this, &DockView::screenGeometryChanged); - connect(this, &DockView::drawShadowsChanged, this, [&]() { - if (m_behaveAsPlasmaPanel) { - updateEnabledBorders(); - } - }); - - connect(this, &DockView::alignmentChanged, this, &DockView::updateEnabledBorders); - connect(this, &DockView::dockWinBehaviorChanged, this, &DockView::saveConfig); connect(this, &DockView::onPrimaryChanged, this, &DockView::saveConfig); connect(this, &DockView::isPreferredForShortcutsChanged, this, &DockView::saveConfig); - connect(this, &DockView::dockTransparencyChanged, this, &DockView::updateEffects); - connect(this, &DockView::drawEffectsChanged, this, &DockView::updateEffects); - connect(this, &DockView::effectsAreaChanged, this, &DockView::updateEffects); - connect(&m_theme, &Plasma::Theme::themeChanged, this, &DockView::themeChanged); connect(&m_theme, &Plasma::Theme::themeChanged, this, &DockView::themeHasShadowChanged); connect(this, SIGNAL(normalThicknessChanged()), corona(), SIGNAL(availableScreenRectChanged())); connect(this, SIGNAL(shadowChanged()), corona(), SIGNAL(availableScreenRectChanged())); connect(m_menuManager, &DockMenuManager::contextMenuChanged, this, &DockView::contextMenuIsShownChanged); ///!!!!! rootContext()->setContextProperty(QStringLiteral("dock"), this); auto *dockCorona = qobject_cast(this->corona()); if (dockCorona) { rootContext()->setContextProperty(QStringLiteral("universalSettings"), dockCorona->universalSettings()); rootContext()->setContextProperty(QStringLiteral("layoutManager"), dockCorona->layoutManager()); rootContext()->setContextProperty(QStringLiteral("themeExtended"), dockCorona->themeExtended()); } setSource(corona()->kPackage().filePath("lattedockui")); // setVisible(true); m_positioner->syncGeometry(); if (!KWindowSystem::isPlatformWayland()) { setVisible(true); } qDebug() << "SOURCE:" << source(); } bool DockView::inDelete() const { return m_inDelete; } void DockView::disconnectSensitiveSignals() { disconnect(corona(), &Plasma::Corona::availableScreenRectChanged, this, &DockView::availableScreenRectChanged); setManagedLayout(nullptr); if (visibility()) { visibility()->setEnabledDynamicBackground(false); } } void DockView::availableScreenRectChanged() { if (m_inDelete) return; if (formFactor() == Plasma::Types::Vertical) { m_positioner->syncGeometry(); } } void DockView::setupWaylandIntegration() { if (m_shellSurface) return; if (DockCorona *c = qobject_cast(corona())) { using namespace KWayland::Client; PlasmaShell *interface {c->waylandDockCoronaInterface()}; if (!interface) return; Surface *s{Surface::fromWindow(this)}; if (!s) return; m_shellSurface = interface->createSurface(s, this); qDebug() << "WAYLAND dock window surface was created..."; m_shellSurface->setSkipTaskbar(true); m_shellSurface->setRole(PlasmaShellSurface::Role::Panel); m_shellSurface->setPanelBehavior(PlasmaShellSurface::PanelBehavior::WindowsGoBelow); } } KWayland::Client::PlasmaShellSurface *DockView::surface() { return m_shellSurface; } //! the main function which decides if this dock is at the //! correct screen void DockView::reconsiderScreen() { m_positioner->reconsiderScreen(); } void DockView::addNewDock() { auto *dockCorona = qobject_cast(this->corona()); if (dockCorona) { dockCorona->loadDefaultLayout(); } } void DockView::copyDock() { m_managedLayout->copyDock(containment()); } void DockView::removeDock() { if (totalDocksCount() > 1) { QAction *removeAct = this->containment()->actions()->action(QStringLiteral("remove")); if (removeAct) { removeAct->trigger(); } } } QQmlListProperty DockView::screens() { return QQmlListProperty(this, nullptr, &countScreens, &atScreens); } int DockView::countScreens(QQmlListProperty *property) { Q_UNUSED(property) return qGuiApp->screens().count(); } QScreen *DockView::atScreens(QQmlListProperty *property, int index) { Q_UNUSED(property) return qGuiApp->screens().at(index); } QString DockView::currentScreen() const { return m_positioner->currentScreenName(); } bool DockView::settingsWindowIsShown() { auto configView = qobject_cast(m_configView); return (configView != nullptr); } void DockView::showSettingsWindow() { showConfigurationInterface(containment()); applyActivitiesToWindows(); } void DockView::showConfigurationInterface(Plasma::Applet *applet) { if (!applet || !applet->containment()) return; Plasma::Containment *c = qobject_cast(applet); if (m_configView && c && c->isContainment() && c == this->containment()) { if (m_configView->isVisible()) { m_configView->setVisible(false); //m_configView->hide(); } else { m_configView->setVisible(true); //m_configView->show(); } return; } else if (m_configView) { if (m_configView->applet() == applet) { m_configView->setVisible(true); //m_configView->show(); m_configView->requestActivate(); return; } else { m_configView->setVisible(false); //m_configView->hide(); m_configView->deleteLater(); } } bool delayConfigView = false; if (c && containment() && c->isContainment() && c->id() == this->containment()->id()) { m_configView = new DockConfigView(c, this); delayConfigView = true; } else { m_configView = new PlasmaQuick::ConfigView(applet); } m_configView.data()->init(); if (!delayConfigView) { m_configView->setVisible(true); //m_configView.data()->show(); } else { //add a timer for showing the configuration window the first time it is //created in order to give the containmnent's layouts the time to //calculate the window's height if (!KWindowSystem::isPlatformWayland()) { QTimer::singleShot(150, m_configView, SLOT(show())); } else { QTimer::singleShot(150, [this]() { m_configView->setVisible(true); }); } } } QRect DockView::localGeometry() const { return m_localGeometry; } void DockView::setLocalGeometry(const QRect &geometry) { if (m_localGeometry == geometry) { return; } m_localGeometry = geometry; emit localGeometryChanged(); updateAbsDockGeometry(); } void DockView::updateAbsDockGeometry(bool bypassChecks) { //! there was a -1 in height and width here. The reason of this //! if I remember correctly was related to multi-screen but I cant //! remember exactly the reason, something related to rigth edge in //! multi screen environment. BUT this was breaking the entire AlwaysVisible //! experience with struts. Removing them in order to restore correct //! behavior and keeping this comment in order to check for //! multi-screen breakage QRect absGeometry {x() + m_localGeometry.x(), y() + m_localGeometry.y() , m_localGeometry.width(), m_localGeometry.height()}; if (m_absGeometry == absGeometry && !bypassChecks) return; m_absGeometry = absGeometry; emit absGeometryChanged(m_absGeometry); //! this is needed in order to update correctly the screenGeometries if (visibility() && corona() && visibility()->mode() == Dock::AlwaysVisible) { emit corona()->availableScreenRectChanged(); emit corona()->availableScreenRegionChanged(); } } void DockView::statusChanged(Plasma::Types::ItemStatus status) { if (containment()) { if (containment()->status() >= Plasma::Types::NeedsAttentionStatus && containment()->status() != Plasma::Types::HiddenStatus) { setBlockHiding(true); } else { setBlockHiding(false); } } } bool DockView::alternativesIsShown() const { return m_alternativesIsShown; } void DockView::setAlternativesIsShown(bool show) { if (m_alternativesIsShown == show) { return; } m_alternativesIsShown = show; setBlockHiding(show); emit alternativesIsShownChanged(); } bool DockView::contextMenuIsShown() const { if (!m_menuManager) { return false; } return m_menuManager->contextMenu(); } int DockView::currentThickness() const { if (formFactor() == Plasma::Types::Vertical) { - return m_maskArea.isNull() ? width() : m_maskArea.width() - m_shadow; + return m_effects->maskArea().isNull() ? width() : m_effects->maskArea().width() - m_shadow; } else { - return m_maskArea.isNull() ? height() : m_maskArea.height() - m_shadow; + return m_effects->maskArea().isNull() ? height() : m_effects->maskArea().height() - m_shadow; } } int DockView::normalThickness() const { return m_normalThickness; } void DockView::setNormalThickness(int thickness) { if (m_normalThickness == thickness) { return; } m_normalThickness = thickness; emit normalThicknessChanged(); } int DockView::docksCount() const { if (!m_managedLayout) { return 0; } return m_managedLayout->docksCount(screen()); } int DockView::totalDocksCount() const { if (!m_managedLayout) { return 0; } return m_managedLayout->docksCount(); } int DockView::docksWithTasks() { if (!m_managedLayout) return 0; return m_managedLayout->noDocksWithTasks(); } void DockView::updateFormFactor() { if (!this->containment()) return; switch (location()) { case Plasma::Types::TopEdge: case Plasma::Types::BottomEdge: this->containment()->setFormFactor(Plasma::Types::Horizontal); break; case Plasma::Types::LeftEdge: case Plasma::Types::RightEdge: this->containment()->setFormFactor(Plasma::Types::Vertical); break; default: qWarning() << "wrong location, couldn't update the panel position" << location(); } } bool DockView::dockWinBehavior() const { return m_dockWinBehavior; } void DockView::setDockWinBehavior(bool dock) { if (m_dockWinBehavior == dock) { return; } m_dockWinBehavior = dock; emit dockWinBehaviorChanged(); } bool DockView::behaveAsPlasmaPanel() const { return m_behaveAsPlasmaPanel; } void DockView::setBehaveAsPlasmaPanel(bool behavior) { if (m_behaveAsPlasmaPanel == behavior) { return; } m_behaveAsPlasmaPanel = behavior; - if (m_behaveAsPlasmaPanel && m_drawShadows) { - PanelShadows::self()->addWindow(this, enabledBorders()); + if (m_behaveAsPlasmaPanel && m_effects->drawShadows()) { + PanelShadows::self()->addWindow(this, m_effects->enabledBorders()); } else { PanelShadows::self()->removeWindow(this); - // m_enabledBorders = Plasma::FrameSvg::AllBorders; - // emit enabledBordersChanged(); } - updateEffects(); emit behaveAsPlasmaPanelChanged(); } -bool DockView::drawShadows() const -{ - return m_drawShadows; -} - -void DockView::setDrawShadows(bool draw) -{ - if (m_drawShadows == draw) { - return; - } - - m_drawShadows = draw; - - if (m_behaveAsPlasmaPanel && m_drawShadows) { - PanelShadows::self()->addWindow(this, enabledBorders()); - } else { - PanelShadows::self()->removeWindow(this); - //m_enabledBorders = Plasma::FrameSvg::AllBorders; - //emit enabledBordersChanged(); - } - - emit drawShadowsChanged(); -} - -bool DockView::drawEffects() const -{ - return m_drawEffects; -} - -void DockView::setDrawEffects(bool draw) -{ - if (m_drawEffects == draw) { - return; - } - - m_drawEffects = draw; - - emit drawEffectsChanged(); -} - bool DockView::inEditMode() const { return m_inEditMode; } void DockView::setInEditMode(bool edit) { if (m_inEditMode == edit) { return; } m_inEditMode = edit; emit inEditModeChanged(); } bool DockView::isPreferredForShortcuts() const { return m_isPreferredForShortcuts; } void DockView::setIsPreferredForShortcuts(bool preferred) { if (m_isPreferredForShortcuts == preferred) { return; } m_isPreferredForShortcuts = preferred; emit isPreferredForShortcutsChanged(); if (m_isPreferredForShortcuts && m_managedLayout) { emit m_managedLayout->preferredViewForShortcutsChanged(this); } } void DockView::preferredViewForShortcutsChangedSlot(DockView *view) { if (view != this) { setIsPreferredForShortcuts(false); } } bool DockView::onPrimary() const { return m_onPrimary; } void DockView::setOnPrimary(bool flag) { if (m_onPrimary == flag) { return; } m_onPrimary = flag; emit onPrimaryChanged(); } float DockView::maxLength() const { return m_maxLength; } void DockView::setMaxLength(float length) { if (m_maxLength == length) { return; } m_maxLength = length; emit maxLengthChanged(); } int DockView::maxThickness() const { return m_maxThickness; } void DockView::setMaxThickness(int thickness) { if (m_maxThickness == thickness) return; m_maxThickness = thickness; emit maxThicknessChanged(); } int DockView::alignment() const { return m_alignment; } void DockView::setAlignment(int alignment) { Dock::Alignment align = static_cast(alignment); if (m_alignment == alignment) { return; } m_alignment = align; emit alignmentChanged(); } bool DockView::blockAnimations() const { return m_blockAnimations; } void DockView::setBlockAnimations(bool block) { if (m_blockAnimations == block) { return; } m_blockAnimations = block; emit blockAnimationsChanged(); } bool DockView::colorizerSupport() const { return m_colorizerSupport; } void DockView::setColorizerSupport(bool support) { if (m_colorizerSupport == support) { return; } m_colorizerSupport = support; emit colorizerSupportChanged(); } -QRect DockView::maskArea() const -{ - return m_maskArea; -} - -void DockView::setMaskArea(QRect area) -{ - if (m_maskArea == area) - return; - - m_maskArea = area; - - if (KWindowSystem::compositingActive()) { - if (m_behaveAsPlasmaPanel) { - setMask(QRect()); - } else { - setMask(m_maskArea); - } - } else { - //! this is used when compositing is disabled and provides - //! the correct way for the mask to be painted in order for - //! rounded corners to be shown correctly - //! the enabledBorders check was added because there was cases - //! that the mask region wasnt calculated correctly after location changes - if (!m_background || m_background->enabledBorders() != enabledBorders()) { - m_background = new Plasma::FrameSvg(this); - } - - if (m_background->imagePath() != "opaque/dialogs/background") { - m_background->setImagePath(QStringLiteral("opaque/dialogs/background")); - } - - m_background->setEnabledBorders(enabledBorders()); - m_background->resizeFrame(area.size()); - QRegion fixedMask = m_background->mask(); - fixedMask.translate(m_maskArea.x(), m_maskArea.y()); - - //! fix for KF5.32 that return empty QRegion's for the mask - if (fixedMask.isEmpty()) { - fixedMask = QRegion(m_maskArea); - } - - setMask(fixedMask); - } - - // qDebug() << "dock mask set:" << m_maskArea; - emit maskAreaChanged(); -} - bool DockView::themeHasShadow() const { return PanelShadows::self()->enabled(); } -QRect DockView::effectsArea() const -{ - return m_effectsArea; -} - -void DockView::setEffectsArea(QRect area) -{ - QRect inWindowRect = area.intersected(QRect(0, 0, width(), height())); - - if (m_effectsArea == inWindowRect) { - return; - } - - m_effectsArea = inWindowRect; - emit effectsAreaChanged(); -} QRect DockView::absGeometry() const { return m_absGeometry; } QRect DockView::screenGeometry() const { if (this->screen()) { QRect geom = this->screen()->geometry(); return geom; } return QRect(); } int DockView::offset() const { return m_offset; } void DockView::setOffset(int offset) { if (m_offset == offset) { return; } m_offset = offset; emit offsetChanged(); } int DockView::dockTransparency() const { return m_dockTransparency; } void DockView::setDockTransparency(int transparency) { if (m_dockTransparency == transparency) { return; } m_dockTransparency = transparency; emit dockTransparencyChanged(); } int DockView::shadow() const { return m_shadow; } void DockView::setShadow(int shadow) { if (m_shadow == shadow) return; m_shadow = shadow; emit shadowChanged(); } int DockView::fontPixelSize() const { return m_fontPixelSize; } void DockView::setFontPixelSize(int size) { if (m_fontPixelSize == size) { return; } m_fontPixelSize = size; emit fontPixelSizeChanged(); } void DockView::applyActivitiesToWindows() { if (m_visibility) { QStringList activities = m_managedLayout->appliedActivities(); m_visibility->setWindowOnActivities(*this, activities); if (m_configView) { m_visibility->setWindowOnActivities(*m_configView, activities); auto configView = qobject_cast(m_configView); if (configView && configView->secondaryWindow()) { m_visibility->setWindowOnActivities(*configView->secondaryWindow(), activities); } } if (m_visibility->supportsKWinEdges()) { m_visibility->applyActivitiesToHiddenWindows(activities); } } } Layout *DockView::managedLayout() const { return m_managedLayout; } void DockView::setManagedLayout(Layout *layout) { if (m_managedLayout == layout) { return; } // clear mode for (auto &c : connectionsManagedLayout) { disconnect(c); } m_managedLayout = layout; if (m_managedLayout) { //! Sometimes the activity isnt completely ready, by adding a delay //! we try to catch up QTimer::singleShot(100, [this]() { if (m_managedLayout && m_visibility) { qDebug() << "DOCK VIEW FROM LAYOUT ::: " << m_managedLayout->name() << " - activities: " << m_managedLayout->appliedActivities(); applyActivitiesToWindows(); emit activitiesChanged(); } }); connectionsManagedLayout[0] = connect(m_managedLayout, &Layout::preferredViewForShortcutsChanged, this, &DockView::preferredViewForShortcutsChangedSlot); } DockCorona *dockCorona = qobject_cast(this->corona()); if (dockCorona->layoutManager()->memoryUsage() == Dock::MultipleLayouts) { connectionsManagedLayout[1] = connect(dockCorona->activitiesConsumer(), &KActivities::Consumer::runningActivitiesChanged, this, [&]() { if (m_managedLayout && m_visibility) { qDebug() << "DOCK VIEW FROM LAYOUT (runningActivitiesChanged) ::: " << m_managedLayout->name() << " - activities: " << m_managedLayout->appliedActivities(); applyActivitiesToWindows(); emit activitiesChanged(); } }); connectionsManagedLayout[2] = connect(m_managedLayout, &Layout::activitiesChanged, this, [&]() { if (m_managedLayout) { applyActivitiesToWindows(); emit activitiesChanged(); } }); connectionsManagedLayout[3] = connect(dockCorona->layoutManager(), &LayoutManager::layoutsChanged, this, [&]() { if (m_managedLayout) { applyActivitiesToWindows(); emit activitiesChanged(); } }); //!IMPORTANT!!! ::: This fixes a bug when closing an Activity all docks from all Activities are //! disappearing! With this they reappear!!! connectionsManagedLayout[4] = connect(this, &QWindow::visibleChanged, this, [&]() { if (!isVisible() && m_managedLayout) { QTimer::singleShot(100, [this]() { if (m_managedLayout && containment() && !containment()->destroyed()) { setVisible(true); applyActivitiesToWindows(); emit activitiesChanged(); } }); QTimer::singleShot(1500, [this]() { if (m_managedLayout && containment() && !containment()->destroyed()) { setVisible(true); applyActivitiesToWindows(); emit activitiesChanged(); } }); } }); } emit managedLayoutChanged(); } void DockView::moveToLayout(QString layoutName) { if (!m_managedLayout) { return; } QList containments = m_managedLayout->unassignFromLayout(this); DockCorona *dockCorona = qobject_cast(this->corona()); if (dockCorona && containments.size() > 0) { Layout *newLayout = dockCorona->layoutManager()->activeLayout(layoutName); if (newLayout) { newLayout->assignToLayout(this, containments); } } } void DockView::setBlockHiding(bool block) { if (!block) { auto *configView = qobject_cast(m_configView); if (m_alternativesIsShown || (configView && configView->sticker() && configView->isVisible())) { return; } if (m_visibility) { m_visibility->setBlockHiding(false); } } else { if (m_visibility) { m_visibility->setBlockHiding(true); } } } -void DockView::setForceDrawCenteredBorders(bool draw) -{ - if (m_forceDrawCenteredBorders == draw) { - return; - } - - m_forceDrawCenteredBorders = draw; -} - -void DockView::updateEffects() -{ - //! Don't apply any effect before the wayland surface is created under wayland - //! https://bugs.kde.org/show_bug.cgi?id=392890 - if (KWindowSystem::isPlatformWayland() && !m_shellSurface) { - return; - } - - if (!m_behaveAsPlasmaPanel) { - if (m_drawEffects && !m_effectsArea.isNull() && !m_effectsArea.isEmpty()) { - //! this is used when compositing is disabled and provides - //! the correct way for the mask to be painted in order for - //! rounded corners to be shown correctly - if (!m_background) { - m_background = new Plasma::FrameSvg(this); - } - - if (m_background->imagePath() != "widgets/panel-background") { - m_background->setImagePath(QStringLiteral("widgets/panel-background")); - } - - m_background->setEnabledBorders(enabledBorders()); - m_background->resizeFrame(m_effectsArea.size()); - QRegion fixedMask = m_background->mask(); - fixedMask.translate(m_effectsArea.x(), m_effectsArea.y()); - - //! fix1, for KF5.32 that return empty QRegion's for the mask - if (fixedMask.isEmpty()) { - fixedMask = QRegion(m_effectsArea); - } - - KWindowEffects::enableBlurBehind(winId(), true, fixedMask); - - bool drawBackgroundEffect = m_theme.backgroundContrastEnabled() && (m_dockTransparency == 100); - //based on Breeze Dark theme behavior the enableBackgroundContrast even though it does accept - //a QRegion it uses only the first rect. The bug was that for Breeze Dark there was a line - //at the dock bottom that was distinguishing it from other themes - KWindowEffects::enableBackgroundContrast(winId(), drawBackgroundEffect, - m_theme.backgroundContrast(), - m_theme.backgroundIntensity(), - m_theme.backgroundSaturation(), - fixedMask.boundingRect()); - } else { - KWindowEffects::enableBlurBehind(winId(), false); - KWindowEffects::enableBackgroundContrast(winId(), false); - } - } else if (m_behaveAsPlasmaPanel && m_drawEffects) { - KWindowEffects::enableBlurBehind(winId(), true); - - bool drawBackgroundEffect = m_theme.backgroundContrastEnabled() && (m_dockTransparency == 100); - - KWindowEffects::enableBackgroundContrast(winId(), drawBackgroundEffect, - m_theme.backgroundContrast(), - m_theme.backgroundIntensity(), - m_theme.backgroundSaturation()); - } else { - KWindowEffects::enableBlurBehind(winId(), false); - KWindowEffects::enableBackgroundContrast(winId(), false); - } -} - //! remove latte tasks plasmoid void DockView::removeTasksPlasmoid() { if (!tasksPresent() || !containment()) { return; } foreach (Plasma::Applet *applet, containment()->applets()) { KPluginMetaData meta = applet->kPackage().metadata(); if (meta.pluginId() == "org.kde.latte.plasmoid") { QAction *closeApplet = applet->actions()->action(QStringLiteral("remove")); if (closeApplet) { closeApplet->trigger(); //! remove only the first found return; } } } } //! check if the tasks plasmoid exist in the dock bool DockView::tasksPresent() { if (!this->containment()) { return false; } foreach (Plasma::Applet *applet, this->containment()->applets()) { const auto &provides = KPluginMetaData::readStringList(applet->pluginMetaData().rawData(), QStringLiteral("X-Plasma-Provides")); if (provides.contains(QLatin1String("org.kde.plasma.multitasking"))) { return true; } } return false; } //! check if the tasks plasmoid exist in the dock bool DockView::latteTasksPresent() { if (!this->containment()) { return false; } foreach (Plasma::Applet *applet, this->containment()->applets()) { KPluginMetaData metadata = applet->pluginMetaData(); if (metadata.pluginId() == "org.kde.latte.plasmoid") { return true; } } return false; } //!check if the plasmoid with _name_ exists in the midedata bool DockView::mimeContainsPlasmoid(QMimeData *mimeData, QString name) { if (!mimeData) { return false; } if (mimeData->hasFormat(QStringLiteral("text/x-plasmoidservicename"))) { QString data = mimeData->data(QStringLiteral("text/x-plasmoidservicename")); const QStringList appletNames = data.split('\n', QString::SkipEmptyParts); foreach (const QString &appletName, appletNames) { if (appletName == name) return true; } } return false; } +View::Effects *DockView::effects() const +{ + return m_effects; +} + Positioner *DockView::positioner() const { return m_positioner; } VisibilityManager *DockView::visibility() const { return m_visibility; } bool DockView::event(QEvent *e) { if (!m_inDelete) { emit eventTriggered(e); switch (e->type()) { case QEvent::Leave: engine()->trimComponentCache(); break; case QEvent::PlatformSurface: if (auto pe = dynamic_cast(e)) { switch (pe->surfaceEventType()) { case QPlatformSurfaceEvent::SurfaceCreated: setupWaylandIntegration(); if (m_shellSurface) { m_positioner->syncGeometry(); - if (m_drawShadows) { - PanelShadows::self()->addWindow(this, enabledBorders()); + if (m_effects->drawShadows()) { + PanelShadows::self()->addWindow(this, m_effects->enabledBorders()); } } break; case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed: if (m_shellSurface) { delete m_shellSurface; m_shellSurface = nullptr; qDebug() << "WAYLAND dock window surface was deleted..."; PanelShadows::self()->removeWindow(this); } break; } } break; default: break; } } return ContainmentView::event(e);; } QList DockView::freeEdges() const { if (!m_managedLayout) { const QList emptyEdges; return emptyEdges; } const auto edges = m_managedLayout->freeEdges(screen()); QList edgesInt; foreach (Plasma::Types::Location edge, edges) { edgesInt.append(static_cast(edge)); } return edgesInt; } void DockView::deactivateApplets() { if (!containment()) { return; } foreach (auto applet, containment()->applets()) { PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value(); if (ai) { ai->setExpanded(false); } } } void DockView::toggleAppletExpanded(const int id) { if (!containment()) { return; } foreach (auto applet, containment()->applets()) { if (applet->id() == id) { PlasmaQuick::AppletQuickItem *ai = applet->property("_plasma_graphicObject").value(); if (ai) { if (!ai->isActivationTogglesExpanded()) { ai->setActivationTogglesExpanded(true); } emit applet->activated(); } } } } QVariantList DockView::containmentActions() { QVariantList actions; /*if (containment()->corona()->immutability() != Plasma::Types::Mutable) { return actions; }*/ //FIXME: the trigger string it should be better to be supported this way //const QString trigger = Plasma::ContainmentActions::eventToString(event); const QString trigger = "RightButton;NoModifier"; Plasma::ContainmentActions *plugin = this->containment()->containmentActions().value(trigger); if (!plugin) { return actions; } if (plugin->containment() != this->containment()) { plugin->setContainment(this->containment()); // now configure it KConfigGroup cfg(this->containment()->corona()->config(), "ActionPlugins"); cfg = KConfigGroup(&cfg, QString::number(this->containment()->containmentType())); KConfigGroup pluginConfig = KConfigGroup(&cfg, trigger); plugin->restore(pluginConfig); } foreach (QAction *ac, plugin->contextualActions()) { actions << QVariant::fromValue(ac); } return actions; } void DockView::disableGrabItemBehavior() { setMouseGrabEnabled(false); } void DockView::restoreGrabItemBehavior() { setMouseGrabEnabled(true); if (mouseGrabberItem()) { mouseGrabberItem()->ungrabMouse(); } } //!BEGIN overriding context menus behavior void DockView::mousePressEvent(QMouseEvent *event) { bool result = m_menuManager->mousePressEvent(event); emit contextMenuIsShownChanged(); if (result) { PlasmaQuick::ContainmentView::mousePressEvent(event); } } //!END overriding context menus behavior -//!BEGIN draw panel shadows outside the dock window -Plasma::FrameSvg::EnabledBorders DockView::enabledBorders() const -{ - return m_enabledBorders; -} - -void DockView::updateEnabledBorders() -{ - if (!this->screen()) { - return; - } - - Plasma::FrameSvg::EnabledBorders borders = Plasma::FrameSvg::AllBorders; - - switch (location()) { - case Plasma::Types::TopEdge: - borders &= ~Plasma::FrameSvg::TopBorder; - break; - - case Plasma::Types::LeftEdge: - borders &= ~Plasma::FrameSvg::LeftBorder; - break; - - case Plasma::Types::RightEdge: - borders &= ~Plasma::FrameSvg::RightBorder; - break; - - case Plasma::Types::BottomEdge: - borders &= ~Plasma::FrameSvg::BottomBorder; - break; - - default: - break; - } - - if ((location() == Plasma::Types::LeftEdge || location() == Plasma::Types::RightEdge)) { - if (maxLength() == 1 && m_alignment == Dock::Justify && !m_forceDrawCenteredBorders) { - borders &= ~Plasma::FrameSvg::TopBorder; - borders &= ~Plasma::FrameSvg::BottomBorder; - } - - if (m_alignment == Dock::Top && !m_forceDrawCenteredBorders && m_offset == 0) { - borders &= ~Plasma::FrameSvg::TopBorder; - } - - if (m_alignment == Dock::Bottom && !m_forceDrawCenteredBorders && m_offset == 0) { - borders &= ~Plasma::FrameSvg::BottomBorder; - } - } - - if (location() == Plasma::Types::TopEdge || location() == Plasma::Types::BottomEdge) { - if (maxLength() == 1 && m_alignment == Dock::Justify) { - borders &= ~Plasma::FrameSvg::LeftBorder; - borders &= ~Plasma::FrameSvg::RightBorder; - } - - if (m_alignment == Dock::Left && m_offset == 0) { - borders &= ~Plasma::FrameSvg::LeftBorder; - } - - if (m_alignment == Dock::Right && m_offset == 0) { - borders &= ~Plasma::FrameSvg::RightBorder; - } - } - - if (m_enabledBorders != borders) { - m_enabledBorders = borders; - emit enabledBordersChanged(); - } - - if (!m_behaveAsPlasmaPanel || !m_drawShadows) { - PanelShadows::self()->removeWindow(this); - } else { - PanelShadows::self()->setEnabledBorders(this, borders); - } -} - -//!END draw panel shadows outside the dock window - //!BEGIN configuration functions void DockView::saveConfig() { if (!this->containment()) return; auto config = this->containment()->config(); config.writeEntry("onPrimary", onPrimary()); config.writeEntry("dockWindowBehavior", dockWinBehavior()); config.writeEntry("isPreferredForShortcuts", isPreferredForShortcuts()); config.sync(); } void DockView::restoreConfig() { if (!this->containment()) return; auto config = this->containment()->config(); m_onPrimary = config.readEntry("onPrimary", true); m_dockWinBehavior = config.readEntry("dockWindowBehavior", true); m_isPreferredForShortcuts = config.readEntry("isPreferredForShortcuts", false); //! Send changed signals at the end in order to be sure that saveConfig //! wont rewrite default/invalid values emit onPrimaryChanged(); emit dockWinBehaviorChanged(); } //!END configuration functions } //!END namespace diff --git a/app/dock/dockview.h b/app/dock/dockview.h index a2aa0d6b..c7b6eabe 100644 --- a/app/dock/dockview.h +++ b/app/dock/dockview.h @@ -1,371 +1,339 @@ /* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef DOCKVIEW_H #define DOCKVIEW_H #include "dockconfigview.h" +#include "effects.h" #include "visibilitymanager.h" #include "../layout.h" #include "../plasmaquick/containmentview.h" #include "../plasmaquick/configview.h" #include "../../liblattedock/dock.h" #include #include #include #include #include #include #include #include #include namespace Plasma { class Types; class Corona; class Containment; } namespace KWayland { namespace Client { class PlasmaShellSurface; } } namespace Latte { class DockMenuManager; class Layout; class Positioner; } namespace Latte { class DockView : public PlasmaQuick::ContainmentView { Q_OBJECT Q_PROPERTY(bool alternativesIsShown READ alternativesIsShown NOTIFY alternativesIsShownChanged) Q_PROPERTY(bool behaveAsPlasmaPanel READ behaveAsPlasmaPanel WRITE setBehaveAsPlasmaPanel NOTIFY behaveAsPlasmaPanelChanged) Q_PROPERTY(bool blockAnimations READ blockAnimations WRITE setBlockAnimations NOTIFY blockAnimationsChanged) Q_PROPERTY(bool colorizerSupport READ colorizerSupport WRITE setColorizerSupport NOTIFY colorizerSupportChanged) Q_PROPERTY(bool contextMenuIsShown READ contextMenuIsShown NOTIFY contextMenuIsShownChanged) Q_PROPERTY(bool dockWinBehavior READ dockWinBehavior WRITE setDockWinBehavior NOTIFY dockWinBehaviorChanged) - Q_PROPERTY(bool drawShadows READ drawShadows WRITE setDrawShadows NOTIFY drawShadowsChanged) - Q_PROPERTY(bool drawEffects READ drawEffects WRITE setDrawEffects NOTIFY drawEffectsChanged) //! Because Latte uses animations, changing to edit mode it may be different than //! when the isUserConfiguring changes value Q_PROPERTY(bool inEditMode READ inEditMode WRITE setInEditMode NOTIFY inEditModeChanged) Q_PROPERTY(bool isPreferredForShortcuts READ isPreferredForShortcuts WRITE setIsPreferredForShortcuts NOTIFY isPreferredForShortcutsChanged) Q_PROPERTY(bool themeHasShadow READ themeHasShadow NOTIFY themeHasShadowChanged) Q_PROPERTY(bool onPrimary READ onPrimary WRITE setOnPrimary NOTIFY onPrimaryChanged) Q_PROPERTY(int alignment READ alignment WRITE setAlignment NOTIFY alignmentChanged) Q_PROPERTY(int docksCount READ docksCount NOTIFY docksCountChanged) Q_PROPERTY(int dockTransparency READ dockTransparency WRITE setDockTransparency NOTIFY dockTransparencyChanged) Q_PROPERTY(int fontPixelSize READ fontPixelSize WRITE setFontPixelSize NOTIFY fontPixelSizeChanged) Q_PROPERTY(int totalDocksCount READ totalDocksCount NOTIFY totalDocksCountChanged) Q_PROPERTY(int x READ x NOTIFY xChanged) Q_PROPERTY(int y READ y NOTIFY yChanged) Q_PROPERTY(int width READ width NOTIFY widthChanged) Q_PROPERTY(int height READ height NOTIFY heightChanged) Q_PROPERTY(int maxThickness READ maxThickness WRITE setMaxThickness NOTIFY maxThicknessChanged) Q_PROPERTY(int normalThickness READ normalThickness WRITE setNormalThickness NOTIFY normalThicknessChanged) Q_PROPERTY(int offset READ offset WRITE setOffset NOTIFY offsetChanged) Q_PROPERTY(int shadow READ shadow WRITE setShadow NOTIFY shadowChanged) Q_PROPERTY(QString currentScreen READ currentScreen NOTIFY currentScreenChanged) Q_PROPERTY(float maxLength READ maxLength WRITE setMaxLength NOTIFY maxLengthChanged) - Q_PROPERTY(Plasma::FrameSvg::EnabledBorders enabledBorders READ enabledBorders NOTIFY enabledBordersChanged) - + Q_PROPERTY(Latte::View::Effects *effects READ effects NOTIFY effectsChanged) Q_PROPERTY(Layout *managedLayout READ managedLayout WRITE setManagedLayout NOTIFY managedLayoutChanged) Q_PROPERTY(Positioner *positioner READ positioner NOTIFY positionerChanged) Q_PROPERTY(VisibilityManager *visibility READ visibility NOTIFY visibilityChanged) + Q_PROPERTY(QQmlListProperty screens READ screens) - Q_PROPERTY(QRect effectsArea READ effectsArea WRITE setEffectsArea NOTIFY effectsAreaChanged) Q_PROPERTY(QRect absoluteGeometry READ absGeometry NOTIFY absGeometryChanged) Q_PROPERTY(QRect localGeometry READ localGeometry WRITE setLocalGeometry NOTIFY localGeometryChanged) - Q_PROPERTY(QRect maskArea READ maskArea WRITE setMaskArea NOTIFY maskAreaChanged) Q_PROPERTY(QRect screenGeometry READ screenGeometry NOTIFY screenGeometryChanged) public: DockView(Plasma::Corona *corona, QScreen *targetScreen = nullptr, bool dockWindowBehavior = false); virtual ~DockView(); void init(); bool alternativesIsShown() const; void setAlternativesIsShown(bool show); bool inDelete() const; bool onPrimary() const; void setOnPrimary(bool flag); int currentThickness() const; int docksCount() const; int totalDocksCount() const; bool behaveAsPlasmaPanel() const; void setBehaveAsPlasmaPanel(bool behavior); bool blockAnimations() const; void setBlockAnimations(bool block); bool colorizerSupport() const; void setColorizerSupport(bool support); bool contextMenuIsShown() const; bool dockWinBehavior() const; void setDockWinBehavior(bool dock); - bool drawShadows() const; - void setDrawShadows(bool draw); - - bool drawEffects() const; - void setDrawEffects(bool draw); - bool inEditMode() const; void setInEditMode(bool edit); bool isPreferredForShortcuts() const; void setIsPreferredForShortcuts(bool preferred); bool themeHasShadow() const; float maxLength() const; void setMaxLength(float length); int dockTransparency() const; void setDockTransparency(int transparency); int fontPixelSize() const; void setFontPixelSize(int size); int maxThickness() const; void setMaxThickness(int thickness); int normalThickness() const; void setNormalThickness(int thickness); int offset() const; void setOffset(int offset); int shadow() const; void setShadow(int shadow); int alignment() const; void setAlignment(int alignment); - QRect maskArea() const; - void setMaskArea(QRect area); - - QRect effectsArea() const; - void setEffectsArea(QRect area); - QRect absGeometry() const; QRect screenGeometry() const; - Plasma::FrameSvg::EnabledBorders enabledBorders() const; - QString currentScreen() const; QRect localGeometry() const; void setLocalGeometry(const QRect &geometry); bool settingsWindowIsShown(); void showSettingsWindow(); - void setForceDrawCenteredBorders(bool draw); - + View::Effects *effects() const; Positioner *positioner() const; VisibilityManager *visibility() const; Layout *managedLayout() const; void setManagedLayout(Layout *layout); KWayland::Client::PlasmaShellSurface *surface(); void reconsiderScreen(); QQmlListProperty screens(); //! is needed by screens() static int countScreens(QQmlListProperty *property); //! is needed by screens() static QScreen *atScreens(QQmlListProperty *property, int index); //! these are signals that create crashes, such a example is the availableScreenRectChanged from corona //! when its containment is destroyed void disconnectSensitiveSignals(); public slots: Q_INVOKABLE void addNewDock(); Q_INVOKABLE void removeDock(); Q_INVOKABLE void copyDock(); Q_INVOKABLE QList freeEdges() const; Q_INVOKABLE QVariantList containmentActions(); Q_INVOKABLE void deactivateApplets(); Q_INVOKABLE void moveToLayout(QString layoutName); Q_INVOKABLE void removeTasksPlasmoid(); Q_INVOKABLE void setBlockHiding(bool block); Q_INVOKABLE void toggleAppletExpanded(const int id); - Q_INVOKABLE void updateEnabledBorders(); Q_INVOKABLE int docksWithTasks(); Q_INVOKABLE bool mimeContainsPlasmoid(QMimeData *mimeData, QString name); Q_INVOKABLE bool tasksPresent(); Q_INVOKABLE bool latteTasksPresent(); void updateAbsDockGeometry(bool bypassChecks = false); Q_INVOKABLE void disableGrabItemBehavior(); Q_INVOKABLE void restoreGrabItemBehavior(); protected slots: void showConfigurationInterface(Plasma::Applet *applet) override; protected: bool event(QEvent *ev) override; void mousePressEvent(QMouseEvent *event) override; signals: void addInternalViewSplitter(); void removeInternalViewSplitter(); void eventTriggered(QEvent *ev); void activitiesChanged(); void alternativesIsShownChanged(); void alignmentChanged(); void behaveAsPlasmaPanelChanged(); void blockAnimationsChanged(); void colorizerSupportChanged(); void contextMenuIsShownChanged(); void currentScreenChanged(); void dockLocationChanged(); void docksCountChanged(); void dockTransparencyChanged(); void dockWinBehaviorChanged(); - void drawShadowsChanged(); - void drawEffectsChanged(); - void effectsAreaChanged(); - void enabledBordersChanged(); + void effectsChanged(); void fontPixelSizeChanged(); void widthChanged(); void heightChanged(); void inEditModeChanged(); void isPreferredForShortcutsChanged(); void localGeometryChanged(); void managedLayoutChanged(); void maxLengthChanged(); void maxThicknessChanged(); void normalThicknessChanged(); void offsetChanged(); void onPrimaryChanged(); void visibilityChanged(); - void maskAreaChanged(); void positionerChanged(); void screenGeometryChanged(); void shadowChanged(); void themeChanged(); void themeHasShadowChanged(); void totalDocksCountChanged(); void xChanged(); void yChanged(); void absGeometryChanged(const QRect &geometry); private slots: void availableScreenRectChanged(); void preferredViewForShortcutsChangedSlot(DockView *view); void statusChanged(Plasma::Types::ItemStatus); - void updateEffects(); void restoreConfig(); void saveConfig(); private: void applyActivitiesToWindows(); void initSignalingForLocationChangeSliding(); void setupWaylandIntegration(); void updateFormFactor(); void updateAppletContainsMethod(); private: Plasma::Containment *containmentById(uint id); bool m_alternativesIsShown{false}; bool m_behaveAsPlasmaPanel{false}; bool m_blockAnimations{false}; bool m_colorizerSupport{false}; bool m_dockWinBehavior{true}; - bool m_drawShadows{true}; - bool m_drawEffects{false}; - bool m_forceDrawCenteredBorders{false}; bool m_inDelete{false}; bool m_inEditMode{false}; bool m_isPreferredForShortcuts{false}; bool m_onPrimary{true}; int m_dockTransparency{100}; int m_fontPixelSize{ -1}; int m_maxThickness{24}; int m_normalThickness{24}; int m_offset{0}; int m_shadow{0}; float m_maxLength{1}; Dock::Alignment m_alignment{Dock::Center}; - QRect m_effectsArea; QRect m_localGeometry; QRect m_absGeometry; - QRect m_maskArea; Layout *m_managedLayout{nullptr}; QPointer m_configView; - QPointer m_visibility; QPointer m_menuManager; + QPointer m_effects; QPointer m_positioner; + QPointer m_visibility; //! Connections to release and bound for the managed layout std::array connectionsManagedLayout; Plasma::Theme m_theme; - //only for the mask on disabled compositing, not to actually paint - Plasma::FrameSvg *m_background{nullptr}; - //only for the mask, not to actually paint - Plasma::FrameSvg::EnabledBorders m_enabledBorders{Plasma::FrameSvg::AllBorders}; KWayland::Client::PlasmaShellSurface *m_shellSurface{nullptr}; friend class Positioner; }; } #endif diff --git a/app/dock/effects.cpp b/app/dock/effects.cpp new file mode 100644 index 00000000..c0df0f62 --- /dev/null +++ b/app/dock/effects.cpp @@ -0,0 +1,321 @@ +/* +* Copyright 2018 Michail Vourlakos +* +* This file is part of Latte-Dock +* +* Latte-Dock is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License, or (at your option) any later version. +* +* Latte-Dock is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#include "effects.h" +#include "dockview.h" +#include "panelshadows_p.h" +#include "../../liblattedock/dock.h" + +#include + +#include +#include + +namespace Latte { +namespace View { + +Effects::Effects(Latte::DockView *parent) + : QObject(parent), + m_view(parent) +{ + init(); +} + +Effects::~Effects() +{ +} + +void Effects::init() +{ + connect(this, &Effects::drawEffectsChanged, this, &Effects::updateEffects); + connect(this, &Effects::effectsAreaChanged, this, &Effects::updateEffects); + + connect(this, &Effects::drawShadowsChanged, this, [&]() { + if (m_view->behaveAsPlasmaPanel()) { + updateEnabledBorders(); + } + }); + + connect(m_view, &Latte::DockView::alignmentChanged, this, &Effects::updateEnabledBorders); + connect(m_view, &Latte::DockView::behaveAsPlasmaPanelChanged, this, &Effects::updateEffects); + connect(m_view, &Latte::DockView::dockTransparencyChanged, this, &Effects::updateEffects); +} + +bool Effects::drawShadows() const +{ + return m_drawShadows; +} + +void Effects::setDrawShadows(bool draw) +{ + if (m_drawShadows == draw) { + return; + } + + m_drawShadows = draw; + + if (m_view->behaveAsPlasmaPanel() && m_drawShadows) { + PanelShadows::self()->addWindow(m_view, m_enabledBorders); + } else { + PanelShadows::self()->removeWindow(m_view); + } + + emit drawShadowsChanged(); +} + +bool Effects::drawEffects() const +{ + return m_drawEffects; +} + +void Effects::setDrawEffects(bool draw) +{ + if (m_drawEffects == draw) { + return; + } + + m_drawEffects = draw; + + emit drawEffectsChanged(); +} + +bool Effects::forceDrawCenteredBorders() const +{ + return m_forceDrawCenteredBorders; +} + +void Effects::setForceDrawCenteredBorders(bool draw) +{ + if (m_forceDrawCenteredBorders == draw) { + return; + } + + m_forceDrawCenteredBorders = draw; +} + +QRect Effects::effectsArea() const +{ + return m_effectsArea; +} + +void Effects::setEffectsArea(QRect area) +{ + QRect inWindowRect = area.intersected(QRect(0, 0, m_view->width(), m_view->height())); + + if (m_effectsArea == inWindowRect) { + return; + } + + m_effectsArea = inWindowRect; + emit effectsAreaChanged(); +} + +QRect Effects::maskArea() const +{ + return m_maskArea; +} + +void Effects::setMaskArea(QRect area) +{ + if (m_maskArea == area) + return; + + m_maskArea = area; + + if (KWindowSystem::compositingActive()) { + if (m_view->behaveAsPlasmaPanel()) { + m_view->setMask(QRect()); + } else { + m_view->setMask(m_maskArea); + } + } else { + //! this is used when compositing is disabled and provides + //! the correct way for the mask to be painted in order for + //! rounded corners to be shown correctly + //! the enabledBorders check was added because there was cases + //! that the mask region wasnt calculated correctly after location changes + if (!m_background || m_background->enabledBorders() != m_enabledBorders) { + m_background = new Plasma::FrameSvg(this); + } + + if (m_background->imagePath() != "opaque/dialogs/background") { + m_background->setImagePath(QStringLiteral("opaque/dialogs/background")); + } + + m_background->setEnabledBorders(m_enabledBorders); + m_background->resizeFrame(area.size()); + QRegion fixedMask = m_background->mask(); + fixedMask.translate(m_maskArea.x(), m_maskArea.y()); + + //! fix for KF5.32 that return empty QRegion's for the mask + if (fixedMask.isEmpty()) { + fixedMask = QRegion(m_maskArea); + } + + m_view->setMask(fixedMask); + } + + // qDebug() << "dock mask set:" << m_maskArea; + emit maskAreaChanged(); +} + + + + +void Effects::updateEffects() +{ + //! Don't apply any effect before the wayland surface is created under wayland + //! https://bugs.kde.org/show_bug.cgi?id=392890 + if (KWindowSystem::isPlatformWayland() && !m_view->surface()) { + return; + } + + if (!m_view->behaveAsPlasmaPanel()) { + if (m_drawEffects && !m_effectsArea.isNull() && !m_effectsArea.isEmpty()) { + //! this is used when compositing is disabled and provides + //! the correct way for the mask to be painted in order for + //! rounded corners to be shown correctly + if (!m_background) { + m_background = new Plasma::FrameSvg(this); + } + + if (m_background->imagePath() != "widgets/panel-background") { + m_background->setImagePath(QStringLiteral("widgets/panel-background")); + } + + m_background->setEnabledBorders(m_enabledBorders); + m_background->resizeFrame(m_effectsArea.size()); + QRegion fixedMask = m_background->mask(); + fixedMask.translate(m_effectsArea.x(), m_effectsArea.y()); + + //! fix1, for KF5.32 that return empty QRegion's for the mask + if (fixedMask.isEmpty()) { + fixedMask = QRegion(m_effectsArea); + } + + KWindowEffects::enableBlurBehind(m_view->winId(), true, fixedMask); + + bool drawBackgroundEffect = m_theme.backgroundContrastEnabled() && (m_view->dockTransparency() == 100); + //based on Breeze Dark theme behavior the enableBackgroundContrast even though it does accept + //a QRegion it uses only the first rect. The bug was that for Breeze Dark there was a line + //at the dock bottom that was distinguishing it from other themes + KWindowEffects::enableBackgroundContrast(m_view->winId(), drawBackgroundEffect, + m_theme.backgroundContrast(), + m_theme.backgroundIntensity(), + m_theme.backgroundSaturation(), + fixedMask.boundingRect()); + } else { + KWindowEffects::enableBlurBehind(m_view->winId(), false); + KWindowEffects::enableBackgroundContrast(m_view->winId(), false); + } + } else if (m_view->behaveAsPlasmaPanel() && m_drawEffects) { + KWindowEffects::enableBlurBehind(m_view->winId(), true); + + bool drawBackgroundEffect = m_theme.backgroundContrastEnabled() && (m_view->dockTransparency() == 100); + + KWindowEffects::enableBackgroundContrast(m_view->winId(), drawBackgroundEffect, + m_theme.backgroundContrast(), + m_theme.backgroundIntensity(), + m_theme.backgroundSaturation()); + } else { + KWindowEffects::enableBlurBehind(m_view->winId(), false); + KWindowEffects::enableBackgroundContrast(m_view->winId(), false); + } +} + +//!BEGIN draw panel shadows outside the dock window +Plasma::FrameSvg::EnabledBorders Effects::enabledBorders() const +{ + return m_enabledBorders; +} + +void Effects::updateEnabledBorders() +{ + if (!m_view->screen()) { + return; + } + + Plasma::FrameSvg::EnabledBorders borders = Plasma::FrameSvg::AllBorders; + + switch (m_view->location()) { + case Plasma::Types::TopEdge: + borders &= ~Plasma::FrameSvg::TopBorder; + break; + + case Plasma::Types::LeftEdge: + borders &= ~Plasma::FrameSvg::LeftBorder; + break; + + case Plasma::Types::RightEdge: + borders &= ~Plasma::FrameSvg::RightBorder; + break; + + case Plasma::Types::BottomEdge: + borders &= ~Plasma::FrameSvg::BottomBorder; + break; + + default: + break; + } + + if ((m_view->location() == Plasma::Types::LeftEdge || m_view->location() == Plasma::Types::RightEdge)) { + if (m_view->maxLength() == 1 && m_view->alignment() == Latte::Dock::Justify && !m_forceDrawCenteredBorders) { + borders &= ~Plasma::FrameSvg::TopBorder; + borders &= ~Plasma::FrameSvg::BottomBorder; + } + + if (m_view->alignment() == Latte::Dock::Top && !m_forceDrawCenteredBorders && m_view->offset() == 0) { + borders &= ~Plasma::FrameSvg::TopBorder; + } + + if (m_view->alignment() == Latte::Dock::Bottom && !m_forceDrawCenteredBorders && m_view->offset() == 0) { + borders &= ~Plasma::FrameSvg::BottomBorder; + } + } + + if (m_view->location() == Plasma::Types::TopEdge || m_view->location() == Plasma::Types::BottomEdge) { + if (m_view->maxLength() == 1 && m_view->alignment() == Latte::Dock::Justify) { + borders &= ~Plasma::FrameSvg::LeftBorder; + borders &= ~Plasma::FrameSvg::RightBorder; + } + + if (m_view->alignment() == Latte::Dock::Left && m_view->offset() == 0) { + borders &= ~Plasma::FrameSvg::LeftBorder; + } + + if (m_view->alignment() == Latte::Dock::Right && m_view->offset() == 0) { + borders &= ~Plasma::FrameSvg::RightBorder; + } + } + + if (m_enabledBorders != borders) { + m_enabledBorders = borders; + emit enabledBordersChanged(); + } + + if (!m_view->behaveAsPlasmaPanel() || !m_drawShadows) { + PanelShadows::self()->removeWindow(m_view); + } else { + PanelShadows::self()->setEnabledBorders(m_view, borders); + } +} +//!END draw panel shadows outside the dock window + +} +} diff --git a/app/dock/effects.h b/app/dock/effects.h new file mode 100644 index 00000000..f28757dc --- /dev/null +++ b/app/dock/effects.h @@ -0,0 +1,104 @@ +/* +* Copyright 2018 Michail Vourlakos +* +* This file is part of Latte-Dock +* +* Latte-Dock is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License, or (at your option) any later version. +* +* Latte-Dock is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#ifndef EFFECTS_H +#define EFFECTS_H + +#include +#include +#include + +#include +#include + +namespace Latte { +class DockView; +} + +namespace Latte { +namespace View { + +class Effects: public QObject +{ + Q_OBJECT + Q_PROPERTY(bool drawShadows READ drawShadows WRITE setDrawShadows NOTIFY drawShadowsChanged) + Q_PROPERTY(bool drawEffects READ drawEffects WRITE setDrawEffects NOTIFY drawEffectsChanged) + + Q_PROPERTY(QRect effectsArea READ effectsArea WRITE setEffectsArea NOTIFY effectsAreaChanged) + Q_PROPERTY(QRect maskArea READ maskArea WRITE setMaskArea NOTIFY maskAreaChanged) + + Q_PROPERTY(Plasma::FrameSvg::EnabledBorders enabledBorders READ enabledBorders NOTIFY enabledBordersChanged) + +public: + Effects(DockView *parent); + virtual ~Effects(); + + bool drawShadows() const; + void setDrawShadows(bool draw); + + bool drawEffects() const; + void setDrawEffects(bool draw); + + bool forceDrawCenteredBorders() const; + void setForceDrawCenteredBorders(bool draw); + + QRect maskArea() const; + void setMaskArea(QRect area); + + QRect effectsArea() const; + void setEffectsArea(QRect area); + + Plasma::FrameSvg::EnabledBorders enabledBorders() const; + +public slots: + void updateEffects(); + void updateEnabledBorders(); + +signals: + void drawShadowsChanged(); + void drawEffectsChanged(); + void effectsAreaChanged(); + void enabledBordersChanged(); + void maskAreaChanged(); + +private slots: + void init(); + +private: + bool m_drawShadows{true}; + bool m_drawEffects{false}; + bool m_forceDrawCenteredBorders{false}; + + QRect m_effectsArea; + QRect m_maskArea; + + QPointer m_view; + + Plasma::Theme m_theme; + //only for the mask on disabled compositing, not to actually paint + Plasma::FrameSvg *m_background{nullptr}; + + //only for the mask, not to actually paint + Plasma::FrameSvg::EnabledBorders m_enabledBorders{Plasma::FrameSvg::AllBorders}; +}; + +} +} + +#endif diff --git a/app/dock/positioner.cpp b/app/dock/positioner.cpp index 2256522d..02c09707 100644 --- a/app/dock/positioner.cpp +++ b/app/dock/positioner.cpp @@ -1,646 +1,647 @@ /* * Copyright 2018 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "positioner.h" #include "dockview.h" +#include "effects.h" #include "../dockcorona.h" #include "../screenpool.h" #include "../universalsettings.h" #include "../../liblattedock/dock.h" #include #include #include #include namespace Latte { Positioner::Positioner(DockView *parent) : QObject(parent), m_view(parent) { m_screenSyncTimer.setSingleShot(true); m_screenSyncTimer.setInterval(2000); connect(&m_screenSyncTimer, &QTimer::timeout, this, &Positioner::reconsiderScreen); //! under X11 it was identified that windows many times especially under screen changes //! don't end up at the correct position and size. This timer will enforce repositionings //! and resizes every 500ms if the window hasn't end up to correct values and until this //! is achieved m_validateGeometryTimer.setSingleShot(true); m_validateGeometryTimer.setInterval(500); connect(&m_validateGeometryTimer, &QTimer::timeout, this, &Positioner::syncGeometry); auto *dockCorona = qobject_cast(m_view->corona()); if (dockCorona) { m_screenSyncTimer.setInterval(qMax(dockCorona->universalSettings()->screenTrackerInterval() - 500, 1000)); connect(dockCorona->universalSettings(), &UniversalSettings::screenTrackerIntervalChanged, this, [this, dockCorona]() { m_screenSyncTimer.setInterval(qMax(dockCorona->universalSettings()->screenTrackerInterval() - 500, 1000)); }); connect(dockCorona, &DockCorona::dockLocationChanged, this, [&]() { //! check if an edge has been freed for a primary dock //! from another screen if (m_view->onPrimary()) { m_screenSyncTimer.start(); } }); } init(); } Positioner::~Positioner() { m_inDelete = true; m_screenSyncTimer.stop(); m_validateGeometryTimer.stop(); } void Positioner::init() { //! connections connect(this, &Positioner::screenGeometryChanged, this, &Positioner::syncGeometry); connect(m_view, &QQuickWindow::xChanged, this, &Positioner::validateDockGeometry); connect(m_view, &QQuickWindow::yChanged, this, &Positioner::validateDockGeometry); connect(m_view, &QQuickWindow::widthChanged, this, &Positioner::validateDockGeometry); connect(m_view, &QQuickWindow::heightChanged, this, &Positioner::validateDockGeometry); connect(m_view, &QQuickWindow::screenChanged, this, &Positioner::screenChanged); connect(m_view, &DockView::absGeometryChanged, this, &Positioner::syncGeometry); connect(m_view, &DockView::behaveAsPlasmaPanelChanged, this, &Positioner::syncGeometry); connect(m_view, &DockView::maxThicknessChanged, this, &Positioner::syncGeometry); connect(m_view, &DockView::maxLengthChanged, this, &Positioner::syncGeometry); connect(m_view, &DockView::offsetChanged, this, &Positioner::syncGeometry); - connect(m_view, &DockView::drawShadowsChanged, this, [&]() { + connect(m_view->effects(), &Latte::View::Effects::drawShadowsChanged, this, [&]() { if (!m_view->behaveAsPlasmaPanel()) { syncGeometry(); } }); connect(m_view, &DockView::locationChanged, this, [&]() { m_view->updateFormFactor(); syncGeometry(); }); connect(m_view, &DockView::normalThicknessChanged, this, [&]() { if (m_view->behaveAsPlasmaPanel()) { syncGeometry(); } }); connect(m_view, &DockView::shadowChanged, this, [&]() { if (m_view->behaveAsPlasmaPanel()) { syncGeometry(); } }); connect(qGuiApp, &QGuiApplication::screenAdded, this, &Positioner::screenChanged); connect(qGuiApp, &QGuiApplication::primaryScreenChanged, this, &Positioner::screenChanged); initSignalingForLocationChangeSliding(); } QString Positioner::currentScreenName() const { return m_screenToFollowId; } bool Positioner::setCurrentScreen(const QString id) { QScreen *nextScreen{qGuiApp->primaryScreen()}; if (id != "primary") { foreach (auto scr, qGuiApp->screens()) { if (scr && scr->name() == id) { nextScreen = scr; break; } } } if (m_screenToFollow == nextScreen) { return true; } if (nextScreen) { if (m_view->managedLayout()) { auto freeEdges = m_view->managedLayout()->freeEdges(nextScreen); if (!freeEdges.contains(m_view->location())) { return false; } else { m_goToScreen = nextScreen; //! asynchronous call in order to not crash from configwindow //! deletion from sliding out animation QTimer::singleShot(100, [this]() { emit hideDockDuringScreenChangeStarted(); }); } } } return true; } //! this function updates the dock's associated screen. //! updateScreenId = true, update also the m_screenToFollowId //! updateScreenId = false, do not update the m_screenToFollowId //! that way an explicit dock can be shown in another screen when //! there isnt a tasks dock running in the system and for that //! dock its first origin screen is stored and that way when //! that screen is reconnected the dock will return to its original //! place void Positioner::setScreenToFollow(QScreen *scr, bool updateScreenId) { if (!scr || (scr && (m_screenToFollow == scr) && (m_view->screen() == scr))) { return; } qDebug() << "setScreenToFollow() called for screen:" << scr->name() << " update:" << updateScreenId; m_screenToFollow = scr; if (updateScreenId) { m_screenToFollowId = scr->name(); } qDebug() << "adapting to screen..."; m_view->setScreen(scr); if (m_view->containment()) { m_view->containment()->reactToScreenChange(); } connect(scr, &QScreen::geometryChanged, this, &Positioner::screenGeometryChanged); syncGeometry(); m_view->updateAbsDockGeometry(true); qDebug() << "setScreenToFollow() ended..."; emit screenGeometryChanged(); emit currentScreenChanged(); } //! the main function which decides if this dock is at the //! correct screen void Positioner::reconsiderScreen() { if (m_inDelete) { return; } qDebug() << "reconsiderScreen() called..."; qDebug() << " Delayer "; foreach (auto scr, qGuiApp->screens()) { qDebug() << " D, found screen: " << scr->name(); } bool screenExists{false}; //!check if the associated screen is running foreach (auto scr, qGuiApp->screens()) { if (m_screenToFollowId == scr->name() || (m_view->onPrimary() && scr == qGuiApp->primaryScreen())) { screenExists = true; } } qDebug() << "dock screen exists ::: " << screenExists; //! 1.a primary dock must be always on the primary screen if (m_view->onPrimary() && (m_screenToFollowId != qGuiApp->primaryScreen()->name() || m_screenToFollow != qGuiApp->primaryScreen() || m_view->screen() != qGuiApp->primaryScreen())) { using Plasma::Types; QList edges{Types::BottomEdge, Types::LeftEdge, Types::TopEdge, Types::RightEdge}; edges = m_view->managedLayout() ? m_view->managedLayout()->availableEdgesForView(qGuiApp->primaryScreen(), m_view) : edges; //change to primary screen only if the specific edge is free qDebug() << "updating the primary screen for dock..."; qDebug() << "available primary screen edges:" << edges; qDebug() << "dock location:" << m_view->location(); if (edges.contains(m_view->location())) { //! case 1 qDebug() << "reached case 1: of updating dock primary screen..."; setScreenToFollow(qGuiApp->primaryScreen()); } } else if (!m_view->onPrimary()) { //! 2.an explicit dock must be always on the correct associated screen //! there are cases that window manager misplaces the dock, this function //! ensures that this dock will return at its correct screen foreach (auto scr, qGuiApp->screens()) { if (scr && scr->name() == m_screenToFollowId) { qDebug() << "reached case 2: updating the explicit screen for dock..."; setScreenToFollow(scr); break; } } } syncGeometry(); qDebug() << "reconsiderScreen() ended..."; emit m_view->docksCountChanged(); } void Positioner::screenChanged(QScreen *scr) { m_screenSyncTimer.start(); //! this is needed in order to update the struts on screen change //! and even though the geometry has been set correctly the offsets //! of the screen must be updated to the new ones if (m_view->visibility() && m_view->visibility()->mode() == Latte::Dock::AlwaysVisible) { m_view->updateAbsDockGeometry(true); } } void Positioner::syncGeometry() { if (!(m_view->screen() && m_view->containment()) || m_inDelete) { return; } bool found{false}; qDebug() << "syncGeometry() called..."; //! before updating the positioning and geometry of the dock //! we make sure that the dock is at the correct screen if (m_view->screen() != m_screenToFollow) { qDebug() << "Sync Geometry screens inconsistent!!!! "; if (m_screenToFollow) { qDebug() << "Sync Geometry screens inconsistent for m_screenToFollow:" << m_screenToFollow->name() << " dock screen:" << m_view->screen()->name(); } if (!m_screenSyncTimer.isActive()) { m_screenSyncTimer.start(); } } else { found = true; } //! if the dock isnt at the correct screen the calculations //! are not executed if (found) { //! compute the free screen rectangle for vertical panels only once //! this way the costly QRegion computations are calculated only once //! instead of two times (both inside the resizeWindow and the updatePosition) QRegion freeRegion;; QRect maximumRect; QRect availableScreenRect{m_view->screen()->geometry()}; if (m_view->formFactor() == Plasma::Types::Vertical) { QString layoutName = m_view->managedLayout() ? m_view->managedLayout()->name() : QString(); auto dockCorona = qobject_cast(m_view->corona()); int fixedScreen = m_view->onPrimary() ? dockCorona->screenPool()->primaryScreenId() : m_view->containment()->screen(); freeRegion = dockCorona->availableScreenRegionWithCriteria(fixedScreen, layoutName); maximumRect = maximumNormalGeometry(); QRegion availableRegion = freeRegion.intersected(maximumRect); availableScreenRect = freeRegion.intersected(maximumRect).boundingRect(); float area = 0; //! it is used to choose which or the availableRegion rectangles will //! be the one representing dock geometry for (int i = 0; i < availableRegion.rectCount(); ++i) { QRect rect = availableRegion.rects().at(i); //! the area of each rectangle in calculated in squares of 50x50 //! this is a way to avoid enourmous numbers for area value float tempArea = (float)(rect.width() * rect.height()) / 2500; if (tempArea > area) { availableScreenRect = rect; area = tempArea; } } if (availableRegion.rectCount() > 1 && m_view->behaveAsPlasmaPanel()) { - m_view->setForceDrawCenteredBorders(true); + m_view->effects()->setForceDrawCenteredBorders(true); } else { - m_view->setForceDrawCenteredBorders(false); + m_view->effects()->setForceDrawCenteredBorders(false); } } else { - m_view->setForceDrawCenteredBorders(false); + m_view->effects()->setForceDrawCenteredBorders(false); } - m_view->updateEnabledBorders(); + m_view->effects()->updateEnabledBorders(); resizeWindow(availableScreenRect); updatePosition(availableScreenRect); qDebug() << "syncGeometry() calculations for screen: " << m_view->screen()->name() << " _ " << m_view->screen()->geometry(); } qDebug() << "syncGeometry() ended..."; // qDebug() << "dock geometry:" << qRectToStr(geometry()); } void Positioner::validateDockGeometry() { if (m_view->geometry() != m_validGeometry) { m_validateGeometryTimer.start(); } } //! this is used mainly from vertical panels in order to //! to get the maximum geometry that can be used from the dock //! based on their alignment type and the location dock QRect Positioner::maximumNormalGeometry() { int xPos = 0; int yPos = 0; int maxHeight = m_view->maxLength() * m_view->screen()->geometry().height(); int maxWidth = m_view->normalThickness(); QRect maxGeometry; maxGeometry.setRect(0, 0, maxWidth, maxHeight); switch (m_view->location()) { case Plasma::Types::LeftEdge: xPos = m_view->screen()->geometry().x(); switch (m_view->alignment()) { case Latte::Dock::Top: yPos = m_view->screen()->geometry().y(); break; case Latte::Dock::Center: case Latte::Dock::Justify: yPos = qMax(m_view->screen()->geometry().center().y() - maxHeight / 2, m_view->screen()->geometry().y()); break; case Latte::Dock::Bottom: yPos = m_view->screen()->geometry().bottom() - maxHeight + 1; break; } maxGeometry.setRect(xPos, yPos, maxWidth, maxHeight); break; case Plasma::Types::RightEdge: xPos = m_view->screen()->geometry().right() - maxWidth + 1; switch (m_view->alignment()) { case Latte::Dock::Top: yPos = m_view->screen()->geometry().y(); break; case Latte::Dock::Center: case Latte::Dock::Justify: yPos = qMax(m_view->screen()->geometry().center().y() - maxHeight / 2, m_view->screen()->geometry().y()); break; case Latte::Dock::Bottom: yPos = m_view->screen()->geometry().bottom() - maxHeight + 1; break; } maxGeometry.setRect(xPos, yPos, maxWidth, maxHeight); break; default: //! bypass clang warnings break; } //! this is needed in order to preserve that the top dock will be above //! the others in case flag bypasswindowmanagerhint hasn't be set, //! such a case is the AlwaysVisible mode if (m_view->location() == Plasma::Types::TopEdge) { KWindowSystem::setState(m_view->winId(), NET::KeepAbove); } else { KWindowSystem::clearState(m_view->winId(), NET::KeepAbove); } return maxGeometry; } void Positioner::updatePosition(QRect availableScreenRect) { QRect screenGeometry{availableScreenRect}; QPoint position; position = {0, 0}; const auto length = [&](int length) -> int { float offs = static_cast(m_view->offset()); return static_cast(length * ((1 - m_view->maxLength()) / 2) + length * (offs / 100)); }; int cleanThickness = m_view->normalThickness() - m_view->shadow(); switch (m_view->location()) { case Plasma::Types::TopEdge: if (m_view->behaveAsPlasmaPanel()) { position = {screenGeometry.x() + length(screenGeometry.width()), screenGeometry.y()}; } else { position = {screenGeometry.x(), screenGeometry.y()}; } break; case Plasma::Types::BottomEdge: if (m_view->behaveAsPlasmaPanel()) { position = {screenGeometry.x() + length(screenGeometry.width()), screenGeometry.y() + screenGeometry.height() - cleanThickness }; } else { position = {screenGeometry.x(), screenGeometry.y() + screenGeometry.height() - m_view->height()}; } break; case Plasma::Types::RightEdge: if (m_view->behaveAsPlasmaPanel() && !m_view->mask().isNull()) { position = {availableScreenRect.right() - cleanThickness + 1, availableScreenRect.y() + length(availableScreenRect.height()) }; } else { position = {availableScreenRect.right() - m_view->width() + 1, availableScreenRect.y()}; } break; case Plasma::Types::LeftEdge: if (m_view->behaveAsPlasmaPanel() && !m_view->mask().isNull()) { position = {availableScreenRect.x(), availableScreenRect.y() + length(availableScreenRect.height())}; } else { position = {availableScreenRect.x(), availableScreenRect.y()}; } break; default: qWarning() << "wrong location, couldn't update the panel position" << m_view->location(); } m_validGeometry.setTopLeft(position); m_view->setPosition(position); if (m_view->surface()) { m_view->surface()->setPosition(position); } } void Positioner::resizeWindow(QRect availableScreenRect) { QSize screenSize = m_view->screen()->size(); QSize size = (m_view->formFactor() == Plasma::Types::Vertical) ? QSize(m_view->maxThickness(), availableScreenRect.height()) : QSize(screenSize.width(), m_view->maxThickness()); if (m_view->formFactor() == Plasma::Types::Vertical) { //qDebug() << "MAXIMUM RECT :: " << maximumRect << " - AVAILABLE RECT :: " << availableRect; if (m_view->behaveAsPlasmaPanel()) { size.setWidth(m_view->normalThickness()); size.setHeight(static_cast(m_view->maxLength() * availableScreenRect.height())); } } else { if (m_view->behaveAsPlasmaPanel()) { size.setWidth(static_cast(m_view->maxLength() * screenSize.width())); size.setHeight(m_view->normalThickness()); } } m_validGeometry.setSize(size); m_view->setMinimumSize(size); m_view->setMaximumSize(size); m_view->resize(size); if (m_view->formFactor() == Plasma::Types::Horizontal && m_view->corona()) { emit m_view->corona()->availableScreenRectChanged(); } } void Positioner::hideWindowsForSlidingOut() { m_view->setBlockHiding(false); if (m_view->m_configView) { auto configDialog = qobject_cast(m_view->m_configView); if (configDialog) { configDialog->hideConfigWindow(); } } } void Positioner::initSignalingForLocationChangeSliding() { //! signals to handle the sliding-in/out during location changes connect(this, &Positioner::hideDockDuringLocationChangeStarted, this, [&]() { hideWindowsForSlidingOut(); }); connect(m_view, &DockView::locationChanged, this, [&]() { if (m_goToLocation != Plasma::Types::Floating) { m_goToLocation = Plasma::Types::Floating; QTimer::singleShot(100, [this]() { m_view->setBlockAnimations(false); emit showDockAfterLocationChangeFinished(); m_view->showSettingsWindow(); if (m_view->managedLayout()) { m_view->managedLayout()->syncDockViewsToScreens(); } }); } }); //! signals to handle the sliding-in/out during screen changes connect(this, &Positioner::hideDockDuringScreenChangeStarted, this, [&]() { hideWindowsForSlidingOut(); }); connect(m_view, &DockView::currentScreenChanged, this, [&]() { if (m_goToScreen) { m_goToScreen = nullptr; QTimer::singleShot(100, [this]() { m_view->setBlockAnimations(false); emit showDockAfterScreenChangeFinished(); m_view->showSettingsWindow(); if (m_view->managedLayout()) { m_view->managedLayout()->syncDockViewsToScreens(); } }); } }); //! signals to handle the sliding-in/out during moving to another layout connect(this, &Positioner::hideDockDuringMovingToLayoutStarted, this, [&]() { hideWindowsForSlidingOut(); }); connect(m_view, &DockView::managedLayoutChanged, this, [&]() { if (!m_moveToLayout.isEmpty() && m_view->managedLayout()) { m_moveToLayout = ""; QTimer::singleShot(100, [this]() { m_view->setBlockAnimations(false); emit showDockAfterMovingToLayoutFinished(); m_view->showSettingsWindow(); }); } }); //! ---- both cases ---- !// //! this is used for both location and screen change cases, this signal //! is send when the sliding-out animation has finished connect(this, &Positioner::hideDockDuringLocationChangeFinished, this, [&]() { m_view->setBlockAnimations(true); if (m_goToLocation != Plasma::Types::Floating) { m_view->setLocation(m_goToLocation); } else if (m_goToScreen) { setScreenToFollow(m_goToScreen); } else if (!m_moveToLayout.isEmpty()) { m_view->moveToLayout(m_moveToLayout); } }); } bool Positioner::inLocationChangeAnimation() { return ((m_goToLocation != Plasma::Types::Floating) || (m_moveToLayout != "") || m_goToScreen); } void Positioner::hideDockDuringLocationChange(int goToLocation) { m_goToLocation = static_cast(goToLocation); emit hideDockDuringLocationChangeStarted(); } void Positioner::hideDockDuringMovingToLayout(QString layoutName) { m_moveToLayout = layoutName; emit hideDockDuringMovingToLayoutStarted(); } } diff --git a/containment/package/contents/ui/DebugWindow.qml b/containment/package/contents/ui/DebugWindow.qml index 21e3aed1..df82814f 100644 --- a/containment/package/contents/ui/DebugWindow.qml +++ b/containment/package/contents/ui/DebugWindow.qml @@ -1,756 +1,756 @@ /* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import QtQuick 2.1 import QtQuick.Window 2.2 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.latte 0.1 as Latte Window{ width: mainGrid.width + 10 height: Math.min(mainGrid.height+10, Screen.height-root.realSize) visible: true property string space:" : " PlasmaExtras.ScrollArea { id: scrollArea anchors.fill: parent verticalScrollBarPolicy: Qt.ScrollBarAsNeeded horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff flickableItem.flickableDirection: Flickable.VerticalFlick Grid{ id:mainGrid columns: 2 Text{ text: "Screen id"+space } Text{ text: dock && dock.currentScreen ? dock.currentScreen : "___" } Text{ text: "Screen Geometry"+space } Text{ text: { if (dock && dock.screenGeometry){ return dock.screenGeometry.x+","+dock.screenGeometry.y+ " "+dock.screenGeometry.width+"x"+dock.screenGeometry.height; } else { return "_,_ _x_"; } } } Text{ text: "Window Geometry"+space } Text{ text: { if (dock) { return dock.x + "," + dock.y + " "+dock.width+ "x"+dock.height; } else { return "_,_ _x_"; } } } Text{ text: "On Primary"+space } Text{ text: { if (dock && dock.onPrimary) return "Yes"; else return "No"; } } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Contents Width"+space } Text{ text: layoutsContainer.contentsWidth } Text{ text: "Contents Height"+space } Text{ text: layoutsContainer.contentsHeight } Text{ text: "Max Length (user)"+space } Text{ text: plasmoid.configuration.maxLength +"%" } Text{ text: "Max Length (pixels)"+space } Text{ text: root.maxLength } Text{ text: "Offset (pixels)"+space } Text{ text: root.offset } Text{ text: "Mask"+space } Text{ text: { - if (dock && dock.maskArea) { - return dock.maskArea.x +", "+ dock.maskArea.y+" "+dock.maskArea.width+"x"+dock.maskArea.height; + if (dock && dock.effects && dock.effects.maskArea) { + return dock.effects.maskArea.x +", "+ dock.effects.maskArea.y+" "+dock.effects.maskArea.width+"x"+dock.effects.maskArea.height; } else { return "_,_ _x_"; } } } Text{ text: "Absolute Geometry"+space } Text{ text: { if (dock && dock.absoluteGeometry) { return dock.absoluteGeometry.x + ", " + dock.absoluteGeometry.y + " " + dock.absoluteGeometry.width + "x" + dock.absoluteGeometry.height; } else { return "_,_ _x_"; } } } Text{ text: "Local Geometry"+space } Text{ text: { if (dock && dock.localGeometry) { return dock.localGeometry.x + ", " + dock.localGeometry.y + " " + dock.localGeometry.width + "x" + dock.localGeometry.height; } else { return "_,_ _x_"; } } } Text{ text: "Draw Effects"+space } Text{ text: { - if (dock && dock.drawEffects) + if (dock && dock.effects && dock.effects.drawEffects) return "Yes"; else return "No"; } } Text{ text: "Effects Area"+space } Text{ text: { - if (dock && dock.effectsArea) { - return dock.effectsArea.x + ", " + dock.effectsArea.y + " " +dock.effectsArea.width + "x" + dock.effectsArea.height; + if (dock && dock.effects && dock.effects.effectsArea) { + return dock.effects.effectsArea.x + ", " + dock.effects.effectsArea.y + " " +dock.effects.effectsArea.width + "x" + dock.effects.effectsArea.height; } else { return "_,_ _x_"; } } } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Is Hidden (flag)"+space } Text{ text: { if (dock && dock.visibility && dock.visibility.isHidden) return "Yes"; else return "No"; } } Text{ text: "Actions Block Hiding "+space } Text{ text: root.actionsBlockHiding } Text{ text: "Contains Mouse (flag)"+space } Text{ text: { if (dock && dock.visibility && dock.visibility.containsMouse) return "Yes"; else return "No"; } } Text{ text: "Edit Mode"+space } Text{ text: { if (root.editMode) return "Yes"; else return "No"; } } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Location"+space } Text{ text: { switch(plasmoid.location){ case PlasmaCore.Types.LeftEdge: return "Left Edge"; break; case PlasmaCore.Types.RightEdge: return "Right Edge"; break; case PlasmaCore.Types.TopEdge: return "Top Edge"; break; case PlasmaCore.Types.BottomEdge: return "Bottom Edge"; break; } return " : " + plasmoid.location; } } Text{ text: "Alignment"+space } Text{ text: { switch(plasmoid.configuration.panelPosition){ case Latte.Dock.Left: return "Left"; break; case Latte.Dock.Right: return "Right"; break; case Latte.Dock.Center: return "Center"; break; case Latte.Dock.Top: return "Top"; break; case Latte.Dock.Bottom: return "Bottom"; break; case Latte.Dock.Justify: return "Justify"; break; } return " : " + plasmoid.configuration.panelPosition; } } Text{ text: "Visibility"+space } Text{ text: { if (!dock || !dock.visibility) return ""; switch(dock.visibility.mode){ case Latte.Dock.AlwaysVisible: return "Always Visible"; break; case Latte.Dock.AutoHide: return "Auto Hide"; break; case Latte.Dock.DodgeActive: return "Dodge Active"; break; case Latte.Dock.DodgeMaximized: return "Dodge Maximized"; break; case Latte.Dock.DodgeAllWindows: return "Dodge All Windows"; break; case Latte.Dock.None: return "None"; break; } return " : " + dock.visibility.mode; } } Text{ text: "Zoom Factor"+space } Text{ text: root.zoomFactor } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Icon Size (current)"+space } Text{ text: root.iconSize } Text{ text: "Icon Size (user)"+space } Text{ text: plasmoid.configuration.iconSize } Text{ text: "Icon Size (proportion)"+space } Text{ text: root.proportionIconSize } Text{ text: "Icon Size (auto decrease), Enabled"+space } Text{ text: root.autoDecreaseIconSize } Text{ text: "Icon Size (auto decrease)"+space } Text{ text: root.automaticIconSizeBasedSize } Text{ text: "Icon Margin (pixels)"+space } Text{ text: root.iconMargin } Text{ text: "Icon Margin (user set)"+space } Text{ text: plasmoid.configuration.iconMargin+"%" } Text{ text: "Thick Margin Base"+space } Text{ text: root.thickMarginBase } Text{ text: "Thick Margin High"+space } Text{ text: root.thickMarginHigh } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Show Panel Background (user)"+space } Text{ text: { if (plasmoid.configuration.useThemePanel) return "Yes"; else return "No"; } } Text{ text: "Force Transparent Panel (auto)"+space } Text{ text: { if (root.forceTransparentPanel) return "Yes"; else return "No"; } } Text{ text: "Panel Background Length"+space } Text{ text: root.realPanelLength } Text{ text: "Panel Background Thickness(user)"+space } Text{ text: plasmoid.configuration.panelSize + "%" } Text{ text: "Panel Background Thickness(automatic)"+space } Text{ text: root.realPanelSize } Text{ text: "Panel Transparency"+space } Text{ text: root.panelTransparency + "%" } Text{ text: "Panel Shadows Active"+space } Text{ text: { if (root.panelShadowsActive) return "Yes"; else return "No"; } } Text{ text: "Panel Background Shadow"+space } Text{ text: root.panelShadow } Text{ text: "Panel Background Margin"+space } Text{ text: root.panelMargin } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Mask - Normal Thickness"+space } Text{ text: visibilityManager.thicknessNormal } Text{ text: "Thickness Uses Panel Size"+space } Text{ text: visibilityManager.panelIsBiggerFromIconSize } Text{ text: "Behave As Plasma Panel"+space } Text{ text: { if (root.behaveAsPlasmaPanel) return "Yes"; else return "No"; } } Text{ text: "Draw Shadows (external)"+space } Text{ text: { if (root.drawShadowsExternal) return "Yes"; else return "No"; } } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Applet Hovered"+space } Text{ text: layoutsContainer.hoveredIndex } Text{ text: "Task Hovered"+space } Text{ text: root.latteAppletHoveredIndex } Text{ text: "In Normal State"+space } Text{ text: visibilityManager.normalState } Text{ text: "Animations Both Axis"+space } Text{ text: root.animationsNeedBothAxis } Text{ text: "Animations Only Length"+space } Text{ text: root.animationsNeedLength } Text{ text: "Animations Need Thickness"+space } Text{ text: root.animationsNeedThickness } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Start Layout Shown Applets"+space } Text{ text: layoutsContainer.startLayout.shownApplets } Text{ text: "Start Layout Applets (with fill)"+space } Text{ text: layoutsContainer.startLayout.fillApplets } Text{ text: "Start Layout Size (no fill applets)"+space } Text{ text: layoutsContainer.startLayout.sizeWithNoFillApplets+" px." } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "Main Layout Shown Applets"+space } Text{ text: layoutsContainer.mainLayout.shownApplets } Text{ text: "Main Layout Applets (with fill)"+space } Text{ text: layoutsContainer.mainLayout.fillApplets } Text{ text: "Main Layout Size (no fill applets)"+space } Text{ text: layoutsContainer.mainLayout.sizeWithNoFillApplets+" px." } Text{ text: " ----------- " } Text{ text: " ----------- " } Text{ text: "End Layout Shown Applets"+space } Text{ text: layoutsContainer.endLayout.shownApplets } Text{ text: "End Layout Applets (with fill)"+space } Text{ text: layoutsContainer.endLayout.fillApplets } Text{ text: "End Layout Size (no fill applets)"+space } Text{ text: layoutsContainer.endLayout.sizeWithNoFillApplets+" px." } } } } diff --git a/containment/package/contents/ui/EditModeVisual.qml b/containment/package/contents/ui/EditModeVisual.qml index 060d8939..cb3f2d17 100644 --- a/containment/package/contents/ui/EditModeVisual.qml +++ b/containment/package/contents/ui/EditModeVisual.qml @@ -1,371 +1,371 @@ /* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import QtQuick 2.1 import QtGraphicalEffects 1.0 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.latte 0.1 as Latte Item{ id: editVisual width: root.isHorizontal ? (dock ? dock.width : root.width) : visibilityManager.thicknessNormalOriginal + theme.defaultFont.pixelSize height: root.isVertical ? (dock ? dock.height : root.height) : visibilityManager.thicknessNormalOriginal + theme.defaultFont.pixelSize opacity: 0 property int speed: Latte.WindowSystem.compositingActive ? root.durationTime*2.8*units.longDuration : 10 property int thickness: visibilityManager.thicknessNormalOriginalValue + root.editShadow property int rootThickness: visibilityManager.thicknessZoomOriginal + root.editShadow - theme.defaultFont.pixelSize property int editLength: root.isHorizontal ? (root.behaveAsPlasmaPanel ? root.width - root.maxIconSize/4 : root.width)://root.maxLength) : (root.behaveAsPlasmaPanel ? root.height - root.maxIconSize/4 : root.height) property real editStateOpacity: 0.95 //root.behaveAsPlasmaPanel ? 0.5 : 0.95// root.blurEnabled ? 0.8 : 0.9 property bool animationSent: false property bool farEdge: (plasmoid.location===PlasmaCore.Types.BottomEdge) || (plasmoid.location===PlasmaCore.Types.RightEdge) property bool editAnimationEnded: false property bool plasmaEditMode: plasmoid.userConfiguring property bool inEditMode: false property rect efGeometry property string layoutColor: root.dockManagedLayout ? root.dockManagedLayout.color : "blue" Item{ id: shadow width: root.isHorizontal ? imageTiler.width + 2*root.editShadow : root.editShadow height: root.isHorizontal ? root.editShadow : imageTiler.height + 2*root.editShadow clip: true visible: !editTransition.running EditShadow{ id: editShadow } states: [ ///topShadow State { name: "topShadow" when: (plasmoid.location === PlasmaCore.Types.BottomEdge) AnchorChanges { target: shadow anchors{ top:undefined; bottom:imageTiler.top; left:undefined; right:undefined; horizontalCenter:imageTiler.horizontalCenter; verticalCenter:undefined} } AnchorChanges { target: editShadow anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:parent.undefined} } PropertyChanges{ target: editShadow anchors{ leftMargin: 0; rightMargin:0; topMargin:root.editShadow; bottomMargin:0} } }, ///bottomShadow State { name: "bottomShadow" when: (plasmoid.location === PlasmaCore.Types.TopEdge) AnchorChanges { target: shadow anchors{ top:imageTiler.bottom; bottom:undefined; left:undefined; right:undefined; horizontalCenter:imageTiler.horizontalCenter; verticalCenter:undefined} } AnchorChanges { target: editShadow anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } PropertyChanges{ target: editShadow anchors{ leftMargin: 0; rightMargin:0; topMargin:0; bottomMargin:root.editShadow} } }, ///leftShadow State { name: "leftShadow" when: (plasmoid.location === PlasmaCore.Types.RightEdge) AnchorChanges { target: shadow anchors{ top:undefined; bottom:undefined; left:undefined; right:imageTiler.left; horizontalCenter:undefined; verticalCenter:imageTiler.verticalCenter} } AnchorChanges { target: editShadow anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: editShadow anchors{ leftMargin: root.editShadow; rightMargin:0; topMargin:0; bottomMargin:0} } }, ///rightShadow State { name: "rightShadow" when: (plasmoid.location === PlasmaCore.Types.LeftEdge) AnchorChanges { target: shadow anchors{ top:undefined; bottom:undefined; left:imageTiler.right; right:undefined; horizontalCenter:undefined; verticalCenter:imageTiler.verticalCenter} } AnchorChanges { target: editShadow anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: editShadow anchors{ leftMargin: 0; rightMargin:root.editShadow; topMargin:0; bottomMargin:0} } } ] } Image{ id: imageTiler anchors.centerIn: parent width: parent.width height: parent.height opacity: editVisual.editStateOpacity fillMode: Image.Tile source: hasBackground ? dock.managedLayout.background : "../icons/"+editVisual.layoutColor+"print.jpg" readonly property bool hasBackground: (dock && dock.managedLayout && dock.managedLayout.background.startsWith("/")) ? true : false } Connections{ target: plasmoid onLocationChanged: initializeEditPosition(); } onRootThicknessChanged: { initializeEditPosition(); } onThicknessChanged: { initializeEditPosition(); } onEditAnimationEndedChanged: { if (!dock) { return; } if (editAnimationEnded && !root.behaveAsPlasmaPanel) { dock.shadow = root.editShadow; } else { dock.shadow = root.panelShadow; } } onXChanged: updateEffectsArea(); onYChanged: updateEffectsArea(); onWidthChanged: { /*if (root.isHorizontal) { initializeEditPosition(); }*/ updateEffectsArea(); } onHeightChanged: { /* if (root.isVertical) { initializeEditPosition(); }*/ updateEffectsArea(); } function updateEffectsArea(){ if (!dock || state !== "edit" || !editAnimationEnded) return; var rootGeometry = mapToItem(root, 0, 0); efGeometry.x = rootGeometry.x; efGeometry.y = rootGeometry.y; efGeometry.width = width; efGeometry.height = height; - dock.effectsArea = efGeometry; + dock.effects.effectsArea = efGeometry; } function initializeNormalPosition() { if (plasmoid.location === PlasmaCore.Types.BottomEdge) { y = rootThickness; x = 0; } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { x = rootThickness; y = 0; } else if (plasmoid.location === PlasmaCore.Types.LeftEdge) { x = -editVisual.thickness; y = 0; } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { y = -editVisual.thickness; x = 0; } } function initializeEditPosition() { if (root.editMode) { if (plasmoid.location === PlasmaCore.Types.LeftEdge){ x = 0; y = 0; } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { x = 0; y = 0; } else if (plasmoid.location === PlasmaCore.Types.BottomEdge) { x = 0; y = rootThickness - thickness; } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { x = rootThickness - thickness; y = 0; } } } //////////// States //////////////////// states: [ State{ name: "*" when: !plasmaEditMode }, State{ name: "edit" when: plasmaEditMode } ] transitions: [ Transition{ id: editTransition from: "*" to: "edit" SequentialAnimation{ id:normalAnimationTransition ScriptAction{ script:{ editVisual.inEditMode = true; editVisual.opacity = 0 editVisual.editAnimationEnded = false; initializeNormalPosition(); if(!animationSent) { animationSent = true; root.slotAnimationsNeedLength(1); } } } ParallelAnimation{ PropertyAnimation { target: editVisual property: "opacity" to: 1 duration: editVisual.speed / 2 easing.type: Easing.OutQuad } PropertyAnimation { target: editVisual property: root.isHorizontal ? "y" : "x" to: editVisual.farEdge ? editVisual.rootThickness - editVisual.thickness : 0 duration: editVisual.speed easing.type: Easing.OutQuad } } ScriptAction{ script:{ editVisual.editAnimationEnded = true; updateEffectsArea(); updateAutomaticIconSize(); visibilityManager.updateMaskArea(); } } } }, Transition{ from: "edit" to: "*" SequentialAnimation{ ScriptAction{ script: { //! remove kwin effects when starting the animation - dock.effectsArea = Qt.rect(-1, -1, 0, 0); + dock.effects.effectsArea = Qt.rect(-1, -1, 0, 0); } } ParallelAnimation{ PropertyAnimation { target: editVisual property: root.isHorizontal ? "y" : "x" to: editVisual.farEdge ? editVisual.rootThickness : -editVisual.thickness duration: editVisual.speed easing.type: Easing.InQuad } PropertyAnimation { target: editVisual property: "opacity" to: 0 duration: editVisual.speed easing.type: Easing.InQuad } } ScriptAction{ script:{ editVisual.inEditMode = false; editVisual.editAnimationEnded = false; if (editVisual.animationSent) { root.slotAnimationsNeedLength(-1); editVisual.animationSent = false; } if (visibilityManager.inTempHiding) { visibilityManager.sendHideDockDuringLocationChangeFinished(); } } } } } ] } diff --git a/containment/package/contents/ui/PanelBox.qml b/containment/package/contents/ui/PanelBox.qml index 08843943..2c3e5e09 100644 --- a/containment/package/contents/ui/PanelBox.qml +++ b/containment/package/contents/ui/PanelBox.qml @@ -1,753 +1,753 @@ /* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import QtQuick 2.1 import QtQuick.Layouts 1.1 import QtQuick.Window 2.2 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.kquickcontrolsaddons 2.0 import "colorizer" as Colorizer import org.kde.latte 0.1 as Latte Item{ id:barLine width: root.isHorizontal ? panelWidth : smallSize height: root.isVertical ? panelHeight : smallSize opacity: root.useThemePanel ? 1 : 0 property int animationTime: 6*root.durationTime*units.shortDuration property int lengthMargins: { return root.isVertical ? shadowsSvgItem.marginsHeight : shadowsSvgItem.marginsWidth } property int panelWidth: { if (root.behaveAsPlasmaPanel && !root.editMode) { return root.width; } else { if ((root.panelAlignment === Latte.Dock.Justify) && root.isHorizontal) { return root.maxLength; } else { return layoutsContainer.mainLayout.width + spacing; } } } property int panelHeight: { if (root.behaveAsPlasmaPanel && !root.editMode) { return root.height; } else { if ((root.panelAlignment === Latte.Dock.Justify) && root.isVertical) { return root.maxLength; } else { return layoutsContainer.mainLayout.height + spacing; } } } property int spacing: { if (!Latte.WindowSystem.compositingActive) { return 0; } else if (root.panelAlignment === Latte.Dock.Justify && plasmoid.configuration.maxLength === 100) { return 0; } else if (root.panelAlignment === Latte.Dock.Center || root.panelAlignment === Latte.Dock.Justify || root.offset!==0) { return root.panelEdgeSpacing/2; } else { return root.panelEdgeSpacing/4; } } property int smallSize: Math.max(3.7*root.statesLineSize, 16) Behavior on opacity{ enabled: Latte.WindowSystem.compositingActive NumberAnimation { duration: barLine.animationTime } } Behavior on opacity{ enabled: !Latte.WindowSystem.compositingActive NumberAnimation { duration: 0 } } Binding { target: root property: "realPanelLength" value: root.isVertical ? barLine.height : barLine.width } Binding { target: root property: "totalPanelEdgeSpacing" value: spacing } onXChanged: solidBackground.updateEffectsArea(); onYChanged: solidBackground.updateEffectsArea(); /// plasmoid's default panel /* BorderImage{ anchors.fill:parent source: "../images/panel-west.png" border { left:8; right:8; top:8; bottom:8 } opacity: (!root.useThemePanel) ? 1 : 0 visible: (opacity == 0) ? false : true horizontalTileMode: BorderImage.Stretch verticalTileMode: BorderImage.Stretch Behavior on opacity{ NumberAnimation { duration: 200 } } }*/ /// the current theme's panel PlasmaCore.FrameSvgItem{ id: shadowsSvgItem width: root.isVertical ? panelSize + marginsWidth - (solidBackground.leftIncreaser + solidBackground.rightIncreaser) : Math.min(parent.width + marginsWidth, root.width - marginsWidth) height: root.isVertical ? Math.min(parent.height + marginsHeight, root.height - marginsHeight) : panelSize + marginsHeight - (solidBackground.topIncreaser + solidBackground.bottomIncreaser) imagePath: root.behaveAsPlasmaPanel || !Latte.WindowSystem.compositingActive || !root.panelShadowsActive || !themeHasShadow ? "" : "widgets/panel-background" prefix: root.behaveAsPlasmaPanel || !Latte.WindowSystem.compositingActive || !root.panelShadowsActive || !themeHasShadow ? "" : "shadow" visible: (opacity == 0) ? false : true opacity: { if (root.forceTransparentPanel || !root.useThemePanel) return 0; else return 1; } - enabledBorders: dock ? dock.enabledBorders : PlasmaCore.FrameSvg.NoBorder + enabledBorders: dock && dock.effects ? dock.effects.enabledBorders : PlasmaCore.FrameSvg.NoBorder property bool themeHasShadow: dock ? dock.themeHasShadow : false Behavior on opacity { enabled: Latte.WindowSystem.compositingActive NumberAnimation { duration: barLine.animationTime } } Behavior on opacity{ enabled: !Latte.WindowSystem.compositingActive NumberAnimation { duration: 0 } } property int marginsWidth: { if (imagePath === "") { return 0; } else { if (root.panelAlignment === Latte.Dock.Left && root.offset===0) return margins.right; else if (root.panelAlignment === Latte.Dock.Right && root.offset===0) return margins.left; else return margins.left+margins.right; } } property int marginsHeight: { if (imagePath === "") { return 0; } else { if (root.panelAlignment === Latte.Dock.Top && root.offset===0) return margins.bottom; else if (root.panelAlignment === Latte.Dock.Bottom && root.offset===0) return margins.top; else return margins.top + margins.bottom; } } property int panelSize: automaticPanelSize property int automaticPanelSize: { if (root.behaveAsPlasmaPanel) { return root.statesLineSize + root.iconSize + root.thickMargin; } else { var icons = root.statesLineSize + root.iconSize + root.thickMargin + 1; var panels = root.themePanelSize + root.panelMargin; root.realPanelThickness = icons; if (icons > panels) { return panels; } else { return icons; } } } property int shadowsSize: 0 Binding{ target: shadowsSvgItem property: "shadowsSize" value:{ if (shadowsSvgItem && !root.behaveAsPlasmaPanel && root.useThemePanel && root.panelShadowsActive){ if (root.isVertical){ if (plasmoid.location === PlasmaCore.Types.LeftEdge) return shadowsSvgItem.margins.right; else if (plasmoid.location === PlasmaCore.Types.RightEdge) return shadowsSvgItem.margins.left; } else { if (plasmoid.location === PlasmaCore.Types.BottomEdge) return shadowsSvgItem.margins.top; else if (plasmoid.location === PlasmaCore.Types.TopEdge) return shadowsSvgItem.margins.bottom; } } else { return 0; } } } Behavior on opacity{ enabled: Latte.WindowSystem.compositingActive NumberAnimation { duration: barLine.animationTime } } Behavior on opacity{ enabled: !Latte.WindowSystem.compositingActive NumberAnimation { duration: 0 } } Binding { target: root property: "panelShadow" when: shadowsSvgItem value: shadowsSvgItem.shadowsSize } Binding { target: root property: "realPanelSize" when: shadowsSvgItem value: shadowsSvgItem.panelSize } Binding { target: root property: "panelMarginLength" when: shadowsSvgItem value: root.isVertical ? shadowsSvgItem.marginsHeight : shadowsSvgItem.marginsWidth } //! This is used to provide real solidness without any transparency from the plasma theme Rectangle{ id: solidBackgroundRectangle anchors.fill: solidBackground color: theme.backgroundColor opacity: behaveAsPlasmaPanel && solidBackground.forceSolidness && plasmoid.configuration.maxLength === 100 ? 1 : 0 Behavior on opacity{ enabled: Latte.WindowSystem.compositingActive NumberAnimation { duration: 2 * barLine.animationTime } } Behavior on opacity{ enabled: !Latte.WindowSystem.compositingActive NumberAnimation { duration: 0 } } } PlasmaCore.FrameSvgItem{ id: solidBackground anchors.leftMargin: Latte.WindowSystem.compositingActive ? shadowsSvgItem.margins.left - leftIncreaser : 0 anchors.rightMargin: Latte.WindowSystem.compositingActive ? shadowsSvgItem.margins.right - rightIncreaser : 0 anchors.topMargin: Latte.WindowSystem.compositingActive ? shadowsSvgItem.margins.top - topIncreaser : 0 anchors.bottomMargin: Latte.WindowSystem.compositingActive ? shadowsSvgItem.margins.bottom - bottomIncreaser : 0 anchors.fill:parent opacity: { if (forceSolidness) { return 1; } else if (!plasmoid.configuration.useThemePanel && plasmoid.configuration.solidBackgroundForMaximized) { return 0; } else { return plasmoid.configuration.panelTransparency / 100; } } readonly property bool forceSolidness: (root.solidPanel && !plasmoid.configuration.solidBackgroundForMaximized) || root.forceSolidPanel || !Latte.WindowSystem.compositingActive property rect efGeometry: Qt.rect(-1,-1,0,0) imagePath: root.solidPanel ? "opaque/dialogs/background" : "widgets/panel-background" onWidthChanged: updateEffectsArea(); onHeightChanged: updateEffectsArea(); Component.onCompleted: { root.updateEffectsArea.connect(updateEffectsArea); adjustPrefix(); } Component.onDestruction: { root.updateEffectsArea.disconnect(updateEffectsArea); } Binding{ target: root property: "currentPanelTransparency" value: solidBackground.opacity * 100 } Connections{ target: root onEditModeChanged: { if (!root.editMode){ solidBackground.updateEffectsArea(); } } onSolidPanelChanged: { adjustPrefix(); } } //! Fix for FrameSvgItem QML version not updating its margins after a theme change //! with this hack we enforce such update. I could use the repaintNeeded signal but //! it is called more often than the themeChanged one. Connections{ target: dock onThemeChanged: { solidBackground.adjustPrefix(); plasmoid.configuration.panelShadows = !plasmoid.configuration.panelShadows; plasmoid.configuration.panelShadows = !plasmoid.configuration.panelShadows; updateEffectsArea(); } } Connections{ target: plasmoid onLocationChanged: solidBackground.adjustPrefix(); } function updateEffectsArea(){ if (!dock || root.editMode) return; var rootGeometry = mapToItem(root, 0, 0); efGeometry.x = rootGeometry.x; efGeometry.y = rootGeometry.y; efGeometry.width = width; efGeometry.height = height; - dock.effectsArea = efGeometry; + dock.effects.effectsArea = efGeometry; if (!Latte.WindowSystem.compositingActive) { visibilityManager.updateMaskArea(); } } //! the increases used when the user forces a solid background and the background //! must be increased in order to look ok in the corners property int rightIncreaser: { if (!(root.solidPanel && root.isVertical && plasmoid.location === PlasmaCore.Types.LeftEdge) || !Latte.WindowSystem.compositingActive) return 0; else return hiddenPanelBackground.margins.right; } property int leftIncreaser: { if (!(root.solidPanel && root.isVertical && plasmoid.location === PlasmaCore.Types.RightEdge) || !Latte.WindowSystem.compositingActive) return 0; else return hiddenPanelBackground.margins.left; } property int topIncreaser: { if (!(root.solidPanel && root.isVertical && plasmoid.location === PlasmaCore.Types.BottomEdge) || !Latte.WindowSystem.compositingActive) return 0; else return hiddenPanelBackground.margins.top; } property int bottomIncreaser: { if (!(root.solidPanel && root.isVertical && plasmoid.location === PlasmaCore.Types.TopEdge) || !Latte.WindowSystem.compositingActive) return 0; else return hiddenPanelBackground.margins.bottom; } Binding { target: root property: "panelMargin" value: { if (root.useThemePanel){ if (root.isVertical){ if (plasmoid.location === PlasmaCore.Types.LeftEdge) return solidBackground.margins.right; else if (plasmoid.location === PlasmaCore.Types.RightEdge) return solidBackground.margins.left; } else { if (plasmoid.location === PlasmaCore.Types.BottomEdge) return solidBackground.margins.top; else if (plasmoid.location === PlasmaCore.Types.TopEdge) return solidBackground.margins.bottom; } } } } onRepaintNeeded: { if (root.behaveAsPlasmaPanel) adjustPrefix(); } - enabledBorders: dock ? dock.enabledBorders : PlasmaCore.FrameSvg.NoBorder + enabledBorders: dock && dock.effects ? dock.effects.enabledBorders : PlasmaCore.FrameSvg.NoBorder Behavior on opacity{ enabled: Latte.WindowSystem.compositingActive NumberAnimation { duration: barLine.animationTime } } Behavior on opacity{ enabled: !Latte.WindowSystem.compositingActive NumberAnimation { duration: 0 } } function adjustPrefix() { if (!plasmoid) { return ""; } var pre; switch (plasmoid.location) { case PlasmaCore.Types.LeftEdge: pre = "west"; break; case PlasmaCore.Types.TopEdge: pre = "north"; break; case PlasmaCore.Types.RightEdge: pre = "east"; break; case PlasmaCore.Types.BottomEdge: pre = "south"; break; default: prefix = ""; } prefix = [pre, ""]; } } Colorizer.CustomBackground { anchors.fill: solidBackground opacity: root.forceColorizeFromActiveWindowScheme ? solidBackground.opacity : 0 backgroundColor: root.forceColorizeFromActiveWindowScheme ? dock.visibility.touchingWindowScheme.backgroundColor : "transparent" roundness: { if (themeExtended) { switch(plasmoid.location) { case PlasmaCore.Types.BottomEdge: return themeExtended.bottomEdgeRoundness; case PlasmaCore.Types.LeftEdge: return themeExtended.leftEdgeRoundness; case PlasmaCore.Types.TopEdge: return themeExtended.topEdgeRoundness; case PlasmaCore.Types.RightEdge: return themeExtended.rightEdgeRoundness; default: return 0; } } return 0; } } PlasmaCore.FrameSvgItem{ id: hiddenPanelBackground imagePath: "widgets/panel-background" visible: false } } transitions: Transition { enabled: editModeVisual.plasmaEditMode AnchorAnimation { duration: 0.8 * root.animationTime easing.type: Easing.OutCubic } } //BEGIN states //user set Panel Positions //0-Center, 1-Left, 2-Right, 3-Top, 4-Bottom states: [ ///Left State { name: "leftCenterOrJustify" when: (plasmoid.location === PlasmaCore.Types.LeftEdge)&&(root.panelAlignment === Latte.Dock.Center || root.panelAlignment === Latte.Dock.Justify) AnchorChanges { target: barLine anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } AnchorChanges { target: shadowsSvgItem anchors{ top:undefined; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } PropertyChanges{ target: barLine anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: (root.panelAlignment === Latte.Dock.Center ? root.offset : 0); } }, ///Left State { name: "leftTop" when: (plasmoid.location === PlasmaCore.Types.LeftEdge)&&(root.panelAlignment === Latte.Dock.Top) AnchorChanges { target: barLine anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: shadowsSvgItem anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:root.offset; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, ///Left State { name: "leftBottom" when: (plasmoid.location === PlasmaCore.Types.LeftEdge)&&(root.panelAlignment === Latte.Dock.Bottom) AnchorChanges { target: barLine anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: shadowsSvgItem anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:root.offset; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, ///Right State { name: "rightCenterOrJustify" when: (plasmoid.location === PlasmaCore.Types.RightEdge)&&(root.panelAlignment === Latte.Dock.Center || root.panelAlignment === Latte.Dock.Justify) AnchorChanges { target: barLine anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } AnchorChanges { target: shadowsSvgItem anchors{ top:undefined; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:parent.verticalCenter} } PropertyChanges{ target: barLine anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: (root.panelAlignment === Latte.Dock.Center ? root.offset : 0); } }, State { name: "rightTop" when: (plasmoid.location === PlasmaCore.Types.RightEdge)&&(root.panelAlignment === Latte.Dock.Top) AnchorChanges { target: barLine anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: shadowsSvgItem anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:root.offset; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State { name: "rightBottom" when: (plasmoid.location === PlasmaCore.Types.RightEdge)&&(root.panelAlignment === Latte.Dock.Bottom) AnchorChanges { target: barLine anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined } } AnchorChanges { target: shadowsSvgItem anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:root.offset; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, ///Bottom State { name: "bottomCenterOrJustify" when: (plasmoid.location === PlasmaCore.Types.BottomEdge)&&(root.panelAlignment === Latte.Dock.Center || root.panelAlignment === Latte.Dock.Justify) AnchorChanges { target: barLine anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } AnchorChanges { target: shadowsSvgItem anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: (root.panelAlignment === Latte.Dock.Center ? root.offset : 0); anchors.verticalCenterOffset: 0; } }, State { name: "bottomLeft" when: (plasmoid.location === PlasmaCore.Types.BottomEdge) &&(((root.panelAlignment === Latte.Dock.Left)&&(Qt.application.layoutDirection !== Qt.RightToLeft)) || ((root.panelAlignment === Latte.Dock.Right)&&(Qt.application.layoutDirection === Qt.RightToLeft))) AnchorChanges { target: barLine anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: shadowsSvgItem anchors{ top:undefined; bottom:parent.bottom; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: root.offset; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State { name: "bottomRight" when: (plasmoid.location === PlasmaCore.Types.BottomEdge) &&(((root.panelAlignment === Latte.Dock.Right)&&(Qt.application.layoutDirection !== Qt.RightToLeft)) ||((root.panelAlignment === Latte.Dock.Left)&&(Qt.application.layoutDirection === Qt.RightToLeft))) AnchorChanges { target: barLine anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: shadowsSvgItem anchors{ top:undefined; bottom:parent.bottom; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: 0; anchors.rightMargin:root.offset; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, ///Top State { name: "topCenterOrJustify" when: (plasmoid.location === PlasmaCore.Types.TopEdge)&&(root.panelAlignment === Latte.Dock.Center || root.panelAlignment === Latte.Dock.Justify) AnchorChanges { target: barLine anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } AnchorChanges { target: shadowsSvgItem anchors{ top:parent.top; bottom:undefined; left:undefined; right:undefined; horizontalCenter:parent.horizontalCenter; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: 0; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: (root.panelAlignment === Latte.Dock.Center ? root.offset : 0); anchors.verticalCenterOffset: 0; } }, State { name: "topLeft" when: (plasmoid.location === PlasmaCore.Types.TopEdge) &&(((root.panelAlignment === Latte.Dock.Left)&&(Qt.application.layoutDirection !== Qt.RightToLeft)) || ((root.panelAlignment === Latte.Dock.Right)&&(Qt.application.layoutDirection === Qt.RightToLeft))) AnchorChanges { target: barLine anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: shadowsSvgItem anchors{ top:parent.top; bottom:undefined; left:parent.left; right:undefined; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: root.offset; anchors.rightMargin:0; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } }, State { name: "topRight" when: (plasmoid.location === PlasmaCore.Types.TopEdge) &&(((root.panelAlignment === Latte.Dock.Right)&&(Qt.application.layoutDirection !== Qt.RightToLeft)) ||((root.panelAlignment === Latte.Dock.Left)&&(Qt.application.layoutDirection === Qt.RightToLeft))) AnchorChanges { target: barLine anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } AnchorChanges { target: shadowsSvgItem anchors{ top:parent.top; bottom:undefined; left:undefined; right:parent.right; horizontalCenter:undefined; verticalCenter:undefined} } PropertyChanges{ target: barLine anchors.leftMargin: 0; anchors.rightMargin:root.offset; anchors.topMargin:0; anchors.bottomMargin:0; anchors.horizontalCenterOffset: 0; anchors.verticalCenterOffset: 0; } } ] //END states } diff --git a/containment/package/contents/ui/VisibilityManager.qml b/containment/package/contents/ui/VisibilityManager.qml index d56ce7d1..6031a800 100644 --- a/containment/package/contents/ui/VisibilityManager.qml +++ b/containment/package/contents/ui/VisibilityManager.qml @@ -1,657 +1,657 @@ /* * Copyright 2016 Smith AR * Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import QtQuick 2.1 import QtQuick.Window 2.2 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.plasmoid 2.0 import org.kde.latte 0.1 as Latte Item{ id: manager anchors.fill: parent property QtObject window property bool debugMagager: Qt.application.arguments.indexOf("--mask") >= 0 property bool blockUpdateMask: false property bool inForceHiding: false //is used when the docks are forced in hiding e.g. when changing layouts property bool normalState : false // this is being set from updateMaskArea property bool previousNormalState : false // this is only for debugging purposes property bool panelIsBiggerFromIconSize: root.useThemePanel && (root.themePanelSize >= root.iconSize) property int animationSpeed: Latte.WindowSystem.compositingActive ? root.durationTime * 1.2 * units.longDuration : 0 property bool inSlidingIn: false //necessary because of its init structure property alias inSlidingOut: slidingAnimationAutoHiddenOut.running property bool inTempHiding: false property int length: root.isVertical ? Screen.height : Screen.width //screenGeometry.height : screenGeometry.width property int slidingOutToPos: ((plasmoid.location===PlasmaCore.Types.LeftEdge)||(plasmoid.location===PlasmaCore.Types.TopEdge)) ? -thicknessNormal : thicknessNormal; property int statesLineSizeOriginal: root.latteApplet ? Math.ceil( root.maxIconSize/13 ) : 0 property int thickReverseAndGlowExtraSize: (root.reverseLinesPosition && root.showGlow && !behaveAsPlasmaPanel) ? 2*statesLineSize : 0; property int thickReverseAndGlowExtraSizeOriginal: Math.ceil(2*root.maxIconSize/13 ) property int thicknessAutoHidden: Latte.WindowSystem.compositingActive ? 2 : 1 property int thicknessMid: root.statesLineSize + (1 + (0.65 * (root.zoomFactor-1)))*(root.iconSize+root.thickMargin + thickReverseAndGlowExtraSize) //needed in some animations property int thicknessNormal: Math.max(root.statesLineSize + root.iconSize + root.thickMargin + thickReverseAndGlowExtraSize +1, root.realPanelSize + root.panelShadow) property int thicknessZoom: root.statesLineSize + ((root.iconSize+root.thickMargin + thickReverseAndGlowExtraSize) * root.zoomFactor) + 2 //it is used to keep thickness solid e.g. when iconSize changes from auto functions property int thicknessMidOriginal: Math.max(thicknessNormalOriginal, statesLineSizeOriginal + thickReverseAndGlowExtraSizeOriginal + (1 + (0.65 * (root.zoomFactor-1)))*(root.maxIconSize+root.thickMarginOriginal)) //needed in some animations property int thicknessNormalOriginal: !root.behaveAsPlasmaPanel || root.editMode ? thicknessNormalOriginalValue : root.realPanelSize + root.panelShadow property int thicknessNormalOriginalValue: statesLineSizeOriginal + thickReverseAndGlowExtraSizeOriginal + root.maxIconSize + root.thickMarginOriginal + 1 property int thicknessZoomOriginal: Math.max(statesLineSizeOriginal + thickReverseAndGlowExtraSizeOriginal + ((root.maxIconSize+root.thickMarginOriginal) * root.zoomFactor) + 2, root.realPanelSize + root.panelShadow, thicknessEditMode) property int thicknessEditMode: thicknessNormalOriginalValue + theme.defaultFont.pixelSize + root.editShadow Binding{ target: dock property:"maxThickness" //! prevents updating window geometry during closing window in wayland and such fixes a crash when: dock && !inTempHiding && !inForceHiding value: thicknessZoomOriginal } Binding{ target: dock property:"normalThickness" when: dock value: thicknessNormalOriginal } Binding{ target: dock property: "behaveAsPlasmaPanel" when: dock value: root.editMode ? false : root.behaveAsPlasmaPanel } Binding{ target: dock property: "colorizerSupport" when: dock value: root.forceColorizer && plasmoid.configuration.solidBackgroundForMaximized } Binding{ target: dock property: "dockTransparency" when: dock value: root.currentPanelTransparency } Binding{ - target: dock + target: dock.effects property: "drawShadows" - when: dock + when: dock && dock.effects value: root.drawShadowsExternal && (!root.inStartup || inForceHiding || inTempHiding) } Binding{ - target: dock + target: dock.effects property: "drawEffects" - when: dock + when: dock && dock.effects value: Latte.WindowSystem.compositingActive && (((root.blurEnabled && root.useThemePanel) || (root.blurEnabled && root.forceSolidPanel && dock.visibility.existsWindowMaximized && Latte.WindowSystem.compositingActive)) && (!root.inStartup || inForceHiding || inTempHiding)) } Binding{ target: dock property: "fontPixelSize" when: theme value: theme.defaultFont.pixelSize } Binding{ target: dock property:"inEditMode" when: dock value: root.editMode } Binding{ target: dock property:"shadow" when: dock value: root.panelShadow } Binding{ target: dock property: "maxLength" when: dock value: root.editMode ? 1 : plasmoid.configuration.maxLength/100 } Binding{ target: dock property: "offset" when: dock value: plasmoid.configuration.offset } Binding{ target: dock property: "alignment" when: dock value: root.panelAlignment } Binding{ target: dock && dock.visibility ? dock.visibility : null property: "enabledDynamicBackground" when: dock && dock.visibility value: (root.backgroundOnlyOnMaximized || plasmoid.configuration.solidBackgroundForMaximized || root.disablePanelShadowMaximized) && Latte.WindowSystem.compositingActive } Connections{ target:root onPanelShadowChanged: updateMaskArea(); onPanelMarginChanged: updateMaskArea(); } Connections{ target: universalLayoutManager onCurrentLayoutIsSwitching: { if (Latte.WindowSystem.compositingActive && root.dockManagedLayout && root.dockManagedLayout.name === layoutName) { manager.inTempHiding = true; manager.inForceHiding = true; root.clearZoom(); manager.slotMustBeHide(); } } } onNormalStateChanged: { if (normalState) { root.updateAutomaticIconSize(); root.updateSizeForAppletsInFill(); } } onThicknessZoomOriginalChanged: { updateMaskArea(); } function slotContainsMouseChanged() { if(dock.visibility.containsMouse) { updateMaskArea(); } } function slotMustBeShown() { // console.log("show..."); if (!slidingAnimationAutoHiddenIn.running && !inTempHiding && !inForceHiding){ slidingAnimationAutoHiddenIn.init(); } } function slotMustBeHide() { //! prevent sliding-in on startup if the dodge modes have sent a hide signal if (inStartupTimer.running && root.inStartup) { root.inStartup = false; } // console.log("hide...."); if((!slidingAnimationAutoHiddenOut.running && !dock.visibility.blockHiding && !dock.visibility.containsMouse) || inForceHiding) { slidingAnimationAutoHiddenOut.init(); } } //! functions used for sliding out/in during location/screen changes function slotHideDockDuringLocationChange() { inTempHiding = true; blockUpdateMask = true; slotMustBeHide(); } function slotShowDockAfterLocationChange() { slidingAnimationAutoHiddenIn.init(); } function sendHideDockDuringLocationChangeFinished(){ blockUpdateMask = false; dock.positioner.hideDockDuringLocationChangeFinished(); } ///test maskArea function updateMaskArea() { if (!dock || blockUpdateMask) { return; } var localX = 0; var localY = 0; normalState = ((root.animationsNeedBothAxis === 0) && (root.animationsNeedLength === 0)) || (dock.visibility.isHidden && !dock.visibility.containsMouse && root.animationsNeedThickness == 0); // debug maskArea criteria if (debugMagager) { console.log(root.animationsNeedBothAxis + ", " + root.animationsNeedLength + ", " + root.animationsNeedThickness + ", " + dock.visibility.isHidden); if (previousNormalState !== normalState) { console.log("normal state changed to:" + normalState); previousNormalState = normalState; } } var tempLength = root.isHorizontal ? width : height; var tempThickness = root.isHorizontal ? height : width; var space = 0; if (Latte.WindowSystem.compositingActive) { if (root.useThemePanel){ space = root.totalPanelEdgeSpacing + root.panelMarginLength + 1; } else { space = root.totalPanelEdgeSpacing + 1; } } else { space = root.totalPanelEdgeSpacing + root.panelMarginLength; } if (Latte.WindowSystem.compositingActive) { if (normalState) { //console.log("entered normal state..."); //count panel length var noCompositingEdit = !Latte.WindowSystem.compositingActive && root.editMode; //used when !compositing and in editMode if (noCompositingEdit) { tempLength = root.isHorizontal ? root.width : root.height; } else { if(root.isHorizontal) { tempLength = plasmoid.configuration.panelPosition === Latte.Dock.Justify ? layoutsContainer.width + space : layoutsContainer.mainLayout.width + space; } else { tempLength = plasmoid.configuration.panelPosition === Latte.Dock.Justify ? layoutsContainer.height + space : layoutsContainer.mainLayout.height + space; } } tempThickness = thicknessNormal; if (root.animationsNeedThickness > 0) { tempThickness = Latte.WindowSystem.compositingActive ? thicknessZoom : thicknessNormal; } if (dock.visibility.isHidden && !slidingAnimationAutoHiddenOut.running ) { tempThickness = thicknessAutoHidden; } //configure x,y based on plasmoid position and root.panelAlignment(Alignment) if ((plasmoid.location === PlasmaCore.Types.BottomEdge) || (plasmoid.location === PlasmaCore.Types.TopEdge)) { if (plasmoid.location === PlasmaCore.Types.BottomEdge) { localY = dock.visibility.isHidden && dock.visibility.supportsKWinEdges ? dock.height + tempThickness : dock.height - tempThickness; } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { localY = dock.visibility.isHidden && dock.visibility.supportsKWinEdges ? -tempThickness : 0; } if (noCompositingEdit) { localX = 0; } else if (plasmoid.configuration.panelPosition === Latte.Dock.Justify) { localX = (dock.width/2) - tempLength/2 + root.offset; } else if (root.panelAlignment === Latte.Dock.Left) { localX = root.offset; } else if (root.panelAlignment === Latte.Dock.Center) { localX = (dock.width/2) - tempLength/2 + root.offset; } else if (root.panelAlignment === Latte.Dock.Right) { localX = dock.width - layoutsContainer.mainLayout.width - space - root.offset; } } else if ((plasmoid.location === PlasmaCore.Types.LeftEdge) || (plasmoid.location === PlasmaCore.Types.RightEdge)){ if (plasmoid.location === PlasmaCore.Types.LeftEdge) { localX = dock.visibility.isHidden && dock.visibility.supportsKWinEdges ? -tempThickness : 0; } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { localX = dock.visibility.isHidden && dock.visibility.supportsKWinEdges ? dock.width + tempThickness : dock.width - tempThickness; } if (noCompositingEdit) { localY = 0; } else if (plasmoid.configuration.panelPosition === Latte.Dock.Justify) { localY = (dock.height/2) - tempLength/2 + root.offset; } else if (root.panelAlignment === Latte.Dock.Top) { localY = root.offset; } else if (root.panelAlignment === Latte.Dock.Center) { localY = (dock.height/2) - tempLength/2 + root.offset; } else if (root.panelAlignment === Latte.Dock.Bottom) { localY = dock.height - layoutsContainer.mainLayout.height - space - root.offset; } } } else { if(root.isHorizontal) tempLength = Screen.width; //screenGeometry.width; else tempLength = Screen.height; //screenGeometry.height; //grow only on length and not thickness if(root.animationsNeedLength>0 && root.animationsNeedBothAxis === 0) { //this is used to fix a bug with shadow showing when the animation of edit mode //is triggered tempThickness = editModeVisual.editAnimationEnded ? thicknessNormalOriginal + theme.defaultFont.pixelSize + root.editShadow : thicknessNormalOriginal + theme.defaultFont.pixelSize if (dock.visibility.isHidden && !slidingAnimationAutoHiddenOut.running ) { tempThickness = thicknessAutoHidden; } else if (root.animationsNeedThickness > 0) { tempThickness = thicknessZoomOriginal; } } else{ //use all thickness space if (dock.visibility.isHidden && !slidingAnimationAutoHiddenOut.running ) { tempThickness = Latte.WindowSystem.compositingActive ? thicknessAutoHidden : thicknessNormalOriginal; } else { tempThickness = thicknessZoomOriginal; } } //configure the x,y position based on thickness if(plasmoid.location === PlasmaCore.Types.RightEdge) localX = Math.max(0,dock.width - tempThickness); else if(plasmoid.location === PlasmaCore.Types.BottomEdge) localY = Math.max(0,dock.height - tempThickness); } } // end of compositing calculations - var maskArea = dock.maskArea; + var maskArea = dock.effects.maskArea; if (Latte.WindowSystem.compositingActive) { var maskLength = maskArea.width; //in Horizontal if (root.isVertical) { maskLength = maskArea.height; } var maskThickness = maskArea.height; //in Horizontal if (root.isVertical) { maskThickness = maskArea.width; } } else { //! no compositing case if (!dock.visibility.isHidden || !dock.visibility.supportsKWinEdges) { - localX = dock.effectsArea.x; - localY = dock.effectsArea.y; + localX = dock.effects.effectsArea.x; + localY = dock.effects.effectsArea.y; } else { if (plasmoid.location === PlasmaCore.Types.BottomEdge) { - localX = dock.effectsArea.x; - localY = dock.effectsArea.y+dock.effectsArea.height+thicknessAutoHidden; + localX = dock.effects.effectsArea.x; + localY = dock.effects.effectsArea.y+dock.effects.effectsArea.height+thicknessAutoHidden; } else if (plasmoid.location === PlasmaCore.Types.TopEdge) { - localX = dock.effectsArea.x; - localY = dock.effectsArea.y - thicknessAutoHidden; + localX = dock.effects.effectsArea.x; + localY = dock.effects.effectsArea.y - thicknessAutoHidden; } else if (plasmoid.location === PlasmaCore.Types.LeftEdge) { - localX = dock.effectsArea.x - thicknessAutoHidden; - localY = dock.effectsArea.y; + localX = dock.effects.effectsArea.x - thicknessAutoHidden; + localY = dock.effects.effectsArea.y; } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { - localX = dock.effectsArea.x + dock.effectsArea.width + 1; - localY = dock.effectsArea.y; + localX = dock.effects.effectsArea.x + dock.effects.effectsArea.width + 1; + localY = dock.effects.effectsArea.y; } } if (root.isHorizontal) { - tempThickness = dock.effectsArea.height; - tempLength = dock.effectsArea.width; + tempThickness = dock.effects.effectsArea.height; + tempLength = dock.effects.effectsArea.width; } else { - tempThickness = dock.effectsArea.width; - tempLength = dock.effectsArea.height; + tempThickness = dock.effects.effectsArea.width; + tempLength = dock.effects.effectsArea.height; } } // console.log("Not updating mask..."); if( maskArea.x !== localX || maskArea.y !== localY || maskLength !== tempLength || maskThickness !== tempThickness) { // console.log("Updating mask..."); var newMaskArea = Qt.rect(-1,-1,0,0); newMaskArea.x = localX; newMaskArea.y = localY; if (isHorizontal) { newMaskArea.width = tempLength; newMaskArea.height = tempThickness; } else { newMaskArea.width = tempThickness; newMaskArea.height = tempLength; } if (!Latte.WindowSystem.compositingActive) { - dock.maskArea = newMaskArea;//dock.effectsArea; + dock.effects.maskArea = newMaskArea;//dock.effectsArea; } else { if (dock.behaveAsPlasmaPanel && !root.editMode) { - dock.maskArea = Qt.rect(0,0,root.width,root.height); + dock.effects.maskArea = Qt.rect(0,0,root.width,root.height); } else { - dock.maskArea = newMaskArea; + dock.effects.maskArea = newMaskArea; } } } //console.log("reached updating geometry ::: "+dock.maskArea); if(normalState){ - var tempGeometry = Qt.rect(dock.maskArea.x, dock.maskArea.y, dock.maskArea.width, dock.maskArea.height); + var tempGeometry = Qt.rect(dock.effects.maskArea.x, dock.effects.maskArea.y, dock.effects.maskArea.width, dock.effects.maskArea.height); //the shadows size must be removed from the maskArea //before updating the localDockGeometry if ((!dock.behaveAsPlasmaPanel || root.editMode) && Latte.WindowSystem.compositingActive) { var fixedThickness = root.realPanelThickness; if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { tempGeometry.width = fixedThickness; } else { tempGeometry.height = fixedThickness; } if (plasmoid.location === PlasmaCore.Types.BottomEdge) { tempGeometry.y = dock.height - fixedThickness; } else if (plasmoid.location === PlasmaCore.Types.RightEdge) { tempGeometry.x = dock.width - fixedThickness; } //set the boundaries for dock local geometry //qBound = qMax(min, qMin(value, max)). tempGeometry.x = Math.max(0, Math.min(tempGeometry.x, dock.width)); tempGeometry.y = Math.max(0, Math.min(tempGeometry.y, dock.height)); tempGeometry.width = Math.min(tempGeometry.width, dock.width); tempGeometry.height = Math.min(tempGeometry.height, dock.height); } //console.log("update geometry ::: "+tempGeometry); if (!Latte.WindowSystem.compositingActive) { - dock.localGeometry = dock.effectsArea; + dock.localGeometry = dock.effects.effectsArea; } else { dock.localGeometry = tempGeometry; } } } Loader{ anchors.fill: parent active: root.debugMode sourceComponent: Item{ anchors.fill:parent Rectangle{ id: windowBackground anchors.fill: parent border.color: "red" border.width: 1 color: "transparent" } Rectangle{ - x: dock ? dock.maskArea.x : -1 - y: dock ? dock.maskArea.y : -1 - height: dock ? dock.maskArea.height : 0 - width: dock ? dock.maskArea.width : 0 + x: dock ? dock.effects.maskArea.x : -1 + y: dock ? dock.effects.maskArea.y : -1 + height: dock ? dock.effects.maskArea.height : 0 + width: dock ? dock.effects.maskArea.width : 0 border.color: "green" border.width: 1 color: "transparent" } } } /***Hiding/Showing Animations*****/ //////////////// Animations - Slide In - Out SequentialAnimation{ id: slidingAnimationAutoHiddenOut ScriptAction{ script: { root.isHalfShown = true; } } PropertyAnimation { target: layoutsContainer property: root.isVertical ? "x" : "y" to: { if (Latte.WindowSystem.compositingActive) { return slidingOutToPos; } else { if ((plasmoid.location===PlasmaCore.Types.LeftEdge)||(plasmoid.location===PlasmaCore.Types.TopEdge)) { return slidingOutToPos + 1; } else { return slidingOutToPos - 1; } } } duration: manager.animationSpeed easing.type: Easing.InQuad } ScriptAction{ script: { dock.visibility.isHidden = true; } } onStarted: { if (manager.debugMagager) { console.log("hiding animation started..."); } } onStopped: { dock.visibility.isHidden = true; if (manager.debugMagager) { console.log("hiding animation ended..."); } if (!manager.inTempHiding) { updateMaskArea(); } else if (plasmoid.configuration.durationTime === 0) { sendHideDockDuringLocationChangeFinished(); } } function init() { if (!dock.visibility.blockHiding) start(); } } SequentialAnimation{ id: slidingAnimationAutoHiddenIn PauseAnimation{ duration: manager.inTempHiding && root.durationTime>0 ? 500 : 0 } PropertyAnimation { target: layoutsContainer property: root.isVertical ? "x" : "y" to: 0 duration: manager.animationSpeed easing.type: Easing.OutQuad } ScriptAction{ script: { root.isHalfShown = false; root.inStartup = false; } } onStarted: { if (manager.debugMagager) { console.log("showing animation started..."); } } onStopped: { inSlidingIn = false; if (manager.inTempHiding) { manager.inTempHiding = false; updateAutomaticIconSize(); } manager.inTempHiding = false; updateAutomaticIconSize(); if (manager.debugMagager) { console.log("showing animation ended..."); } } function init() { // if (!dock.visibility.blockHiding) inSlidingIn = true; if (slidingAnimationAutoHiddenOut.running) { slidingAnimationAutoHiddenOut.stop(); } dock.visibility.isHidden = false; updateMaskArea(); start(); } } } diff --git a/containment/package/contents/ui/colorizer/CustomBackground.qml b/containment/package/contents/ui/colorizer/CustomBackground.qml index 8ca8a648..f0498fcb 100644 --- a/containment/package/contents/ui/colorizer/CustomBackground.qml +++ b/containment/package/contents/ui/colorizer/CustomBackground.qml @@ -1,201 +1,201 @@ /* * Copyright 2018 Michail Vourlakos * * This file is part of Latte-Dock * * Latte-Dock is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * Latte-Dock is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import QtQuick 2.7 import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.latte 0.1 as Latte Item{ id: main anchors.fill: parent clip: true property int roundness: 0 property color backgroundColor property bool topBorder: false property bool leftBorder: false property bool bottomBorder: false property bool rightBorder: false property int noOfBorders: { var i = 0; if (topBorder) { i = i + 1; } if (leftBorder) { i = i + 1; } if (rightBorder) { i = i + 1; } if (bottomBorder) { i = i + 1; } return i; } readonly property bool drawWithoutRoundness: noOfBorders === 1 || !Latte.WindowSystem.compositingActive Binding{ target: main property: "topBorder" when: dock value: { - return ((dock && (dock.enabledBorders & PlasmaCore.FrameSvg.TopBorder)) > 0); + return ((dock && dock.effects && (dock.effects.enabledBorders & PlasmaCore.FrameSvg.TopBorder)) > 0); } } Binding{ target: main property: "leftBorder" when: dock value: { - return ((dock && (dock.enabledBorders & PlasmaCore.FrameSvg.LeftBorder)) > 0); + return ((dock && dock.effects && (dock.effects.enabledBorders & PlasmaCore.FrameSvg.LeftBorder)) > 0); } } Binding{ target: main property: "bottomBorder" when: dock value: { - return ((dock && (dock.enabledBorders & PlasmaCore.FrameSvg.BottomBorder)) > 0); + return ((dock && dock.effects && (dock.effects.enabledBorders & PlasmaCore.FrameSvg.BottomBorder)) > 0); } } Binding{ target: main property: "rightBorder" when: dock value: { - return ((dock && (dock.enabledBorders & PlasmaCore.FrameSvg.RightBorder)) > 0); + return ((dock && dock.effects && (dock.effects.enabledBorders & PlasmaCore.FrameSvg.RightBorder)) > 0); } } Rectangle{ id: painter anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter width: { if (plasmoid.formFactor === PlasmaCore.Types.Horizontal) { if (drawWithoutRoundness || noOfBorders === 3) { return parent.width; } else if (noOfBorders === 2) { return parent.width + roundness; } } else if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { if (drawWithoutRoundness) { return parent.width; } else if (noOfBorders === 2 || noOfBorders === 3) { return parent.width + roundness; } } } height: { if (plasmoid.formFactor === PlasmaCore.Types.Horizontal) { if (drawWithoutRoundness) { return parent.height; } else if (noOfBorders === 2 || noOfBorders === 3) { return parent.height + roundness; } } else if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { if (drawWithoutRoundness || noOfBorders === 3) { return parent.height; } else if (noOfBorders === 2) { return parent.height + roundness; } } } radius: drawWithoutRoundness ? 0 : roundness color: parent.backgroundColor border.width: 0; border.color: "transparent" readonly property int centerStep: roundness / 2 states: [ State { name: "horizontal" when: (plasmoid.formFactor === PlasmaCore.Types.Horizontal) PropertyChanges{ target: painter anchors.horizontalCenterOffset: { if (drawWithoutRoundness || noOfBorders === 3) { return 0; } else if (noOfBorders === 2) { if (leftBorder) { return centerStep; } else if (rightBorder) { return -centerStep; } } return 0; } anchors.verticalCenterOffset: { if (drawWithoutRoundness) { return 0; } else { //top edge and bottom edge return plasmoid.location === PlasmaCore.Types.TopEdge ? -centerStep : centerStep; } } } }, State { name: "vertical" when: (plasmoid.formFactor === PlasmaCore.Types.Vertical) PropertyChanges{ target: painter anchors.verticalCenterOffset: { if (drawWithoutRoundness || noOfBorders === 3) { return 0; } else if (noOfBorders === 2) { if (bottomBorder) { return -centerStep; } else if (topBorder) { return centerStep; } } } anchors.horizontalCenterOffset: { if (drawWithoutRoundness) { return 0; } else { //left edge and right edge return plasmoid.location === PlasmaCore.Types.LeftEdge ? -centerStep : centerStep; } } } } ] } } diff --git a/effects.cpp b/effects.cpp new file mode 100644 index 00000000..e69de29b