diff --git a/CMakeLists.txt b/CMakeLists.txt index dfb37c646..a93a6afe0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Plasma PlasmaQuick WindowSystem Declarative - I18n CoreAddons XmlGui DBusAddons IconThemes) + I18n CoreAddons XmlGui DBusAddons IconThemes Wayland) FIND_PROGRAM(GETTEXT_MSGFMT_EXECUTABLE msgfmt) diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 0ab87f80d..09d93f1c0 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -1,7 +1,3 @@ -find_package(Qt5 ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE COMPONENTS Quick Qml) -find_package(KF5I18n NO_MODULE) -find_package(KF5Activities REQUIRED) - include(KDEInstallDirs) include(KDECMakeSettings) #include(KDECompilerSettings NO_POLICY_SCOPE) @@ -13,6 +9,32 @@ include(ECMOptionalAddSubdirectory) include(ECMQtDeclareLoggingCategory) include(KDEPackageAppTemplates) +find_package(Qt5 ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE COMPONENTS Quick Qml) +find_package(KF5I18n NO_MODULE) +find_package(KF5Activities REQUIRED) + +find_package(X11 REQUIRED) +set_package_properties(X11 PROPERTIES DESCRIPTION "X11 libraries" + URL "http://www.x.org" + TYPE OPTIONAL + PURPOSE "Required for building the X11 based workspace") + +if(X11_FOUND) + find_package(XCB MODULE REQUIRED COMPONENTS XCB RANDR) + set_package_properties(XCB PROPERTIES TYPE REQUIRED) + if(NOT X11_SM_FOUND) + message(FATAL_ERROR "\nThe X11 Session Management (SM) development package could not be found.\nPlease install libSM.\n") + endif(NOT X11_SM_FOUND) + + find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED COMPONENTS X11Extras) +endif() + +if(X11_FOUND AND XCB_XCB_FOUND) + set(HAVE_X11 true) +endif() + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config-latte.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-latte.h) + set(lattedock-app_SRCS ../liblattedock/dock.cpp ../liblattedock/windowsystem.cpp @@ -25,6 +47,7 @@ set(lattedock-app_SRCS dockview.cpp dockconfigview.cpp packageplugins/shell/dockpackage.cpp + panelshadows.cpp main.cpp ) @@ -48,8 +71,13 @@ target_link_libraries( KF5::Activities KF5::QuickAddons KF5::WindowSystem + KF5::WaylandClient ) +if(HAVE_X11) + target_link_libraries(latte-dock ${X11_LIBRARIES} ${XCB_LIBRARIES} ) +endif() + install(TARGETS latte-dock ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) #even if hidden, the desktop file is needed anyways for kdbusservice::unique install(FILES latte-dock.desktop DESTINATION ${KDE_INSTALL_APPDIR}) diff --git a/app/config-latte.h.cmake b/app/config-latte.h.cmake new file mode 100644 index 000000000..89858d17d --- /dev/null +++ b/app/config-latte.h.cmake @@ -0,0 +1 @@ +#cmakedefine01 HAVE_X11 diff --git a/app/dockview.cpp b/app/dockview.cpp index 4e119b0d8..3419fbc64 100644 --- a/app/dockview.cpp +++ b/app/dockview.cpp @@ -22,6 +22,7 @@ #include "dockconfigview.h" #include "dockcorona.h" #include "visibilitymanager.h" +#include "panelshadows_p.h" #include "../liblattedock/extras.h" #include "../liblattedock/windowsystem.h" @@ -113,6 +114,8 @@ void DockView::init() connect(this, &QQuickWindow::widthChanged, this, &DockView::widthChanged); connect(this, &QQuickWindow::heightChanged, this, &DockView::heightChanged); connect(this, &DockView::localDockGeometryChanged, this, &DockView::updateAbsDockGeometry); + connect(this, &DockView::drawShadowsChanged, this, &DockView::syncGeometry); + connect(this, &DockView::maxLengthChanged, this, &DockView::syncGeometry); connect(this, &DockView::locationChanged, this, [&]() { updateFormFactor(); syncGeometry(); @@ -232,12 +235,24 @@ void DockView::resizeWindow() QSize screenSize = screen()->size(); if (formFactor() == Plasma::Types::Vertical) { - const QSize size{maxThickness(), screenSize.height()}; + QSize size{maxThickness(), screenSize.height()}; + + if (m_drawShadows) { + size.setWidth(normalThickness()); + size.setHeight(maxLength() * screenSize.height()); + } + setMinimumSize(size); setMaximumSize(size); resize(size); } else { - const QSize size{screenSize.width(), maxThickness()}; + QSize size{screenSize.width(), maxThickness()}; + + if (m_drawShadows) { + size.setWidth(maxLength() * screenSize.width()); + size.setHeight(normalThickness()); + } + setMinimumSize(size); setMaximumSize(size); resize(size); @@ -251,6 +266,7 @@ void DockView::setLocalDockGeometry(const QRect &geometry) } m_localDockGeometry = geometry; + emit localDockGeometryChanged(); } @@ -272,19 +288,51 @@ void DockView::updatePosition() QPoint position; position = {0, 0}; + int maxLengthWidth = maxLength() * screenGeometry.width(); + int maxLengthHeight = maxLength() * screenGeometry.height(); + int cleanThickness = normalThickness() - shadow(); + switch (location()) { case Plasma::Types::TopEdge: - position = {screenGeometry.x(), screenGeometry.y()}; + if (m_drawShadows) { + position = {screenGeometry.x() + (screenGeometry.width() / 2 - maxLengthWidth / 2), screenGeometry.y()}; + } else { + position = {screenGeometry.x(), screenGeometry.y()}; + } + break; + case Plasma::Types::BottomEdge: - position = {screenGeometry.x(), screenGeometry.y() + screenGeometry.height() - height()}; + if (m_drawShadows) { + position = {screenGeometry.x() + (screenGeometry.width() / 2 - maxLengthWidth / 2), + screenGeometry.y() + screenGeometry.height() - cleanThickness + }; + } else { + position = {screenGeometry.x(), screenGeometry.y() + screenGeometry.height() - height()}; + } + break; + case Plasma::Types::RightEdge: - position = {screenGeometry.x() + screenGeometry.width() - width(), screenGeometry.y()}; + if (m_drawShadows && !mask().isNull()) { + position = {screenGeometry.x() + screenGeometry.width() - cleanThickness, + screenGeometry.y() + (screenGeometry.height() / 2 - maxLengthHeight / 2) + }; + } else { + position = {screenGeometry.x() + screenGeometry.width() - width(), screenGeometry.y()}; + } + break; + case Plasma::Types::LeftEdge: - position = {screenGeometry.x(), screenGeometry.y()}; + if (m_drawShadows && !mask().isNull()) { + position = {screenGeometry.x(), screenGeometry.y() + (screenGeometry.height() / 2 - maxLengthHeight / 2)}; + } else { + position = {screenGeometry.x(), screenGeometry.y()}; + } + break; + default: qWarning() << "wrong location, couldn't update the panel position" << location(); @@ -295,6 +343,7 @@ void DockView::updatePosition() inline void DockView::syncGeometry() { + updateEnabledBorders(); resizeWindow(); updatePosition(); updateAbsDockGeometry(); @@ -367,6 +416,46 @@ void DockView::updateFormFactor() } } +bool DockView::drawShadows() const +{ + return m_drawShadows; +} + +void DockView::setDrawShadows(bool draw) +{ + if (m_drawShadows == draw) { + return; + } + + m_drawShadows = draw; + + if (m_drawShadows) { + PanelShadows::self()->addWindow(this, enabledBorders()); + } else { + PanelShadows::self()->removeWindow(this); + m_enabledBorders = Plasma::FrameSvg::AllBorders; + emit enabledBordersChanged(); + } + + emit drawShadowsChanged(); +} + +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; @@ -409,6 +498,11 @@ void DockView::setShadow(int shadow) return; m_shadow = shadow; + + if (m_drawShadows) { + syncGeometry(); + } + emit shadowChanged(); } @@ -442,6 +536,7 @@ VisibilityManager *DockView::visibility() bool DockView::event(QEvent *e) { emit eventTriggered(e); + return ContainmentView::event(e); } @@ -757,7 +852,6 @@ void DockView::addAppletActions(QMenu *desktopMenu, Plasma::Applet *applet, QEve } } - void DockView::addContainmentActions(QMenu *desktopMenu, QEvent *event) { if (!containment()) { @@ -818,5 +912,80 @@ Plasma::Containment *DockView::containmentById(int id) //!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() +{ + // qDebug() << "draw shadow!!!! :" << m_drawShadows; + + if (!screen()) { + return; + } + + if (!m_drawShadows) { + PanelShadows::self()->removeWindow(this); + return; + } + + Plasma::FrameSvg::EnabledBorders borders = Plasma::FrameSvg::AllBorders; + + if (!m_drawShadows) { + borders = Plasma::FrameSvg::NoBorder; + } else { + 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 (x() <= screen()->geometry().x()) { + borders &= ~Plasma::FrameSvg::LeftBorder; + } + + if (x() + width() >= screen()->geometry().x() + screen()->geometry().width()) { + borders &= ~Plasma::FrameSvg::RightBorder; + } + + if (y() <= screen()->geometry().y()) { + borders &= ~Plasma::FrameSvg::TopBorder; + } + + if (y() + height() >= screen()->geometry().y() + screen()->geometry().height()) { + borders &= ~Plasma::FrameSvg::BottomBorder; + } + + } + + PanelShadows::self()->setEnabledBorders(this, borders); + + if (m_enabledBorders != borders) { + PanelShadows::self()->setEnabledBorders(this, borders); + + m_enabledBorders = borders; + emit enabledBordersChanged(); + } +} + +//!END draw panel shadows outside the dock window + } //!END namespace diff --git a/app/dockview.h b/app/dockview.h index 4762836ab..2c2b258d9 100644 --- a/app/dockview.h +++ b/app/dockview.h @@ -42,6 +42,7 @@ namespace Latte { class DockView : public PlasmaQuick::ContainmentView { Q_OBJECT + Q_PROPERTY(bool drawShadows READ drawShadows WRITE setDrawShadows NOTIFY drawShadowsChanged) Q_PROPERTY(int docksCount READ docksCount NOTIFY docksCountChanged) Q_PROPERTY(int width READ width NOTIFY widthChanged) @@ -51,6 +52,10 @@ class DockView : public PlasmaQuick::ContainmentView { Q_PROPERTY(int shadow READ shadow WRITE setShadow NOTIFY shadowChanged) Q_PROPERTY(QStringList debugFlags READ debugFlags NOTIFY debugFlagsChanged) + Q_PROPERTY(float maxLength READ maxLength WRITE setMaxLength NOTIFY maxLengthChanged) + + Q_PROPERTY(Plasma::FrameSvg::EnabledBorders enabledBorders READ enabledBorders NOTIFY enabledBordersChanged) + Q_PROPERTY(QRect maskArea READ maskArea WRITE setMaskArea NOTIFY maskAreaChanged) Q_PROPERTY(VisibilityManager *visibility READ visibility NOTIFY visibilityChanged) Q_PROPERTY(QQmlListProperty screens READ screens) @@ -71,6 +76,12 @@ public: int docksCount() const; + bool drawShadows() const; + void setDrawShadows(bool draw); + + float maxLength() const; + void setMaxLength(float length); + int maxThickness() const; void setMaxThickness(int thickness); @@ -83,6 +94,8 @@ public: QRect maskArea() const; void setMaskArea(QRect area); + Plasma::FrameSvg::EnabledBorders enabledBorders() const; + QStringList debugFlags() const; VisibilityManager *visibility(); @@ -99,6 +112,7 @@ public slots: Q_INVOKABLE QVariantList containmentActions(); Q_INVOKABLE void setLocalDockGeometry(const QRect &geometry); Q_INVOKABLE bool tasksPresent(); + Q_INVOKABLE void updateEnabledBorders(); Q_INVOKABLE void closeApplication(); @@ -118,8 +132,11 @@ signals: void debugFlagsChanged(); void dockLocationChanged(); void docksCountChanged(); + void drawShadowsChanged(); + void enabledBordersChanged(); void widthChanged(); void heightChanged(); + void maxLengthChanged(); void maxThicknessChanged(); void normalThicknessChanged(); void visibilityChanged(); @@ -143,15 +160,20 @@ private: private: Plasma::Containment *containmentById(int id); + bool m_drawShadows{false}; int m_maxThickness{24}; int m_normalThickness{24}; int m_shadow{0}; + float m_maxLength{1}; QRect m_localDockGeometry; QRect m_maskArea; QMenu *m_contextMenu; QPointer m_configView; QPointer m_visibility; + + //only for the mask, not to actually paint + Plasma::FrameSvg::EnabledBorders m_enabledBorders = Plasma::FrameSvg::AllBorders; }; } diff --git a/app/panelshadows.cpp b/app/panelshadows.cpp new file mode 100644 index 000000000..4c81059c6 --- /dev/null +++ b/app/panelshadows.cpp @@ -0,0 +1,750 @@ +/* +* Copyright 2011 by Aaron Seigo +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License version 2, +* or (at your option) any later version. +* +* This program 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 Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "panelshadows_p.h" + +#include +#include + +#include + +#include +#if HAVE_X11 + #include + #include + #include + #include + #include +#endif + +#include +#include +#include +#include +#include + +#include + +class PanelShadows::Private { +public: + Private(PanelShadows *shadows) + : q(shadows) +#if HAVE_X11 + , _connection(0x0), + _gc(0x0) + , m_isX11(KWindowSystem::isPlatformX11()) +#endif + { + setupWaylandIntegration(); + } + + ~Private() { + // Do not call clearPixmaps() from here: it creates new QPixmap(), + // which causes a crash when application is stopping. + freeX11Pixmaps(); + } + + void freeX11Pixmaps(); + void freeWaylandBuffers(); + void clearPixmaps(); + void setupPixmaps(); + Qt::HANDLE createPixmap(const QPixmap &source); + void initPixmap(const QString &element); + QPixmap initEmptyPixmap(const QSize &size); + void updateShadow(const QWindow *window, Plasma::FrameSvg::EnabledBorders); + void updateShadowX11(const QWindow *window, Plasma::FrameSvg::EnabledBorders); + void updateShadowWayland(const QWindow *window, Plasma::FrameSvg::EnabledBorders); + void clearShadow(const QWindow *window); + void clearShadowX11(const QWindow *window); + void clearShadowWayland(const QWindow *window); + void updateShadows(); + void windowDestroyed(QObject *deletedObject); + void setupData(Plasma::FrameSvg::EnabledBorders enabledBorders); + + void setupWaylandIntegration(); + + PanelShadows *q; + QList m_shadowPixmaps; + + QPixmap m_emptyCornerPix; + QPixmap m_emptyCornerLeftPix; + QPixmap m_emptyCornerTopPix; + QPixmap m_emptyCornerRightPix; + QPixmap m_emptyCornerBottomPix; + QPixmap m_emptyVerticalPix; + QPixmap m_emptyHorizontalPix; + +#if HAVE_X11 + //! xcb connection + xcb_connection_t *_connection; + + //! graphical context + xcb_gcontext_t _gc; + bool m_isX11; +#endif + + struct Wayland { + KWayland::Client::ShadowManager *manager = nullptr; + KWayland::Client::ShmPool *shmPool = nullptr; + + QList shadowBuffers; + }; + Wayland m_wayland; + + QHash> data; + QHash m_windows; +}; + +class PanelShadowsSingleton { +public: + PanelShadowsSingleton() { + } + + PanelShadows self; +}; + +Q_GLOBAL_STATIC(PanelShadowsSingleton, privatePanelShadowsSelf) + +PanelShadows::PanelShadows(QObject *parent, const QString &prefix) + : Plasma::Svg(parent), + d(new Private(this)) +{ + setImagePath(prefix); + connect(this, SIGNAL(repaintNeeded()), this, SLOT(updateShadows())); +} + +PanelShadows::~PanelShadows() +{ + delete d; +} + +PanelShadows *PanelShadows::self() +{ + return &privatePanelShadowsSelf->self; +} + +void PanelShadows::addWindow(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders) +{ + if (!window) { + return; + } + + d->m_windows[window] = enabledBorders; + d->updateShadow(window, enabledBorders); + connect(window, SIGNAL(destroyed(QObject *)), + this, SLOT(windowDestroyed(QObject *)), Qt::UniqueConnection); +} + +void PanelShadows::removeWindow(const QWindow *window) +{ + if (!d->m_windows.contains(window)) { + return; + } + + d->m_windows.remove(window); + disconnect(window, 0, this, 0); + d->clearShadow(window); + + if (d->m_windows.isEmpty()) { + d->clearPixmaps(); + } +} + +void PanelShadows::setEnabledBorders(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders) +{ + if (!window || !d->m_windows.contains(window)) { + return; + } + + d->updateShadow(window, enabledBorders); +} + + +void PanelShadows::Private::windowDestroyed(QObject *deletedObject) +{ + m_windows.remove(static_cast(deletedObject)); + + if (m_windows.isEmpty()) { + clearPixmaps(); + } +} + +void PanelShadows::Private::updateShadows() +{ + setupPixmaps(); + QHash::const_iterator i; + + for (i = m_windows.constBegin(); i != m_windows.constEnd(); ++i) { + updateShadow(i.key(), i.value()); + } +} + +Qt::HANDLE PanelShadows::Private::createPixmap(const QPixmap &source) +{ + + // do nothing for invalid pixmaps + if (source.isNull()) return 0; + + /* + in some cases, pixmap handle is invalid. This is the case notably + when Qt uses to RasterEngine. In this case, we create an X11 Pixmap + explicitly and draw the source pixmap on it. + */ + +#if HAVE_X11 + + if (!m_isX11) { + return 0; + } + + // check connection + if (!_connection) _connection = QX11Info::connection(); + + const int width(source.width()); + const int height(source.height()); + + // create X11 pixmap + Pixmap pixmap = XCreatePixmap(QX11Info::display(), QX11Info::appRootWindow(), width, height, 32); + + // check gc + if (!_gc) { + _gc = xcb_generate_id(_connection); + xcb_create_gc(_connection, _gc, pixmap, 0, 0x0); + } + +// // create explicitly shared QPixmap from it +// QPixmap dest( QPixmap::fromX11Pixmap( pixmap, QPixmap::ExplicitlyShared ) ); +// +// // create surface for pixmap +// { +// QPainter painter( &dest ); +// painter.setCompositionMode( QPainter::CompositionMode_Source ); +// painter.drawPixmap( 0, 0, source ); +// } +// +// +// return pixmap; + QImage image(source.toImage()); + xcb_put_image( + _connection, XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, _gc, + image.width(), image.height(), 0, 0, + 0, 32, + image.byteCount(), image.constBits()); + + return (Qt::HANDLE)pixmap; + +#else + return 0; +#endif + +} + +void PanelShadows::Private::initPixmap(const QString &element) +{ + m_shadowPixmaps << q->pixmap(element); +} + +QPixmap PanelShadows::Private::initEmptyPixmap(const QSize &size) +{ +#if HAVE_X11 + + if (!m_isX11) { + return QPixmap(); + } + + QPixmap tempEmptyPix(size); + + if (!size.isEmpty()) { + tempEmptyPix.fill(Qt::transparent); + } + + return tempEmptyPix; +#else + Q_UNUSED(size) + return QPixmap(); +#endif +} + +void PanelShadows::Private::setupPixmaps() +{ + clearPixmaps(); + initPixmap(QStringLiteral("shadow-top")); + initPixmap(QStringLiteral("shadow-topright")); + initPixmap(QStringLiteral("shadow-right")); + initPixmap(QStringLiteral("shadow-bottomright")); + initPixmap(QStringLiteral("shadow-bottom")); + initPixmap(QStringLiteral("shadow-bottomleft")); + initPixmap(QStringLiteral("shadow-left")); + initPixmap(QStringLiteral("shadow-topleft")); + + m_emptyCornerPix = initEmptyPixmap(QSize(1, 1)); + m_emptyCornerLeftPix = initEmptyPixmap(QSize(q->elementSize(QStringLiteral("shadow-topleft")).width(), 1)); + m_emptyCornerTopPix = initEmptyPixmap(QSize(1, q->elementSize(QStringLiteral("shadow-topleft")).height())); + m_emptyCornerRightPix = initEmptyPixmap(QSize(q->elementSize(QStringLiteral("shadow-bottomright")).width(), 1)); + m_emptyCornerBottomPix = initEmptyPixmap(QSize(1, q->elementSize(QStringLiteral("shadow-bottomright")).height())); + m_emptyVerticalPix = initEmptyPixmap(QSize(1, q->elementSize(QStringLiteral("shadow-left")).height())); + m_emptyHorizontalPix = initEmptyPixmap(QSize(q->elementSize(QStringLiteral("shadow-top")).width(), 1)); + + if (m_wayland.shmPool) { + for (auto it = m_shadowPixmaps.constBegin(); it != m_shadowPixmaps.constEnd(); ++it) { + m_wayland.shadowBuffers << m_wayland.shmPool->createBuffer(it->toImage()); + } + } +} + + +void PanelShadows::Private::setupData(Plasma::FrameSvg::EnabledBorders enabledBorders) +{ +#if HAVE_X11 + + if (!m_isX11) { + return; + } + + //shadow-top + if (enabledBorders & Plasma::FrameSvg::TopBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_shadowPixmaps[0])); + } else { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyHorizontalPix)); + } + + //shadow-topright + if (enabledBorders & Plasma::FrameSvg::TopBorder && + enabledBorders & Plasma::FrameSvg::RightBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_shadowPixmaps[1])); + } else if (enabledBorders & Plasma::FrameSvg::TopBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerTopPix)); + } else if (enabledBorders & Plasma::FrameSvg::RightBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerRightPix)); + } else { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerPix)); + } + + //shadow-right + if (enabledBorders & Plasma::FrameSvg::RightBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_shadowPixmaps[2])); + } else { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyVerticalPix)); + } + + //shadow-bottomright + if (enabledBorders & Plasma::FrameSvg::BottomBorder && + enabledBorders & Plasma::FrameSvg::RightBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_shadowPixmaps[3])); + } else if (enabledBorders & Plasma::FrameSvg::BottomBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerBottomPix)); + } else if (enabledBorders & Plasma::FrameSvg::RightBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerRightPix)); + } else { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerPix)); + } + + //shadow-bottom + if (enabledBorders & Plasma::FrameSvg::BottomBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_shadowPixmaps[4])); + } else { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyHorizontalPix)); + } + + //shadow-bottomleft + if (enabledBorders & Plasma::FrameSvg::BottomBorder && + enabledBorders & Plasma::FrameSvg::LeftBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_shadowPixmaps[5])); + } else if (enabledBorders & Plasma::FrameSvg::BottomBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerBottomPix)); + } else if (enabledBorders & Plasma::FrameSvg::LeftBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerLeftPix)); + } else { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerPix)); + } + + //shadow-left + if (enabledBorders & Plasma::FrameSvg::LeftBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_shadowPixmaps[6])); + } else { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyVerticalPix)); + } + + //shadow-topleft + if (enabledBorders & Plasma::FrameSvg::TopBorder && + enabledBorders & Plasma::FrameSvg::LeftBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_shadowPixmaps[7])); + } else if (enabledBorders & Plasma::FrameSvg::TopBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerTopPix)); + } else if (enabledBorders & Plasma::FrameSvg::LeftBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerLeftPix)); + } else { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerPix)); + } + +#endif + + int left, top, right, bottom = 0; + + QSize marginHint; + + if (enabledBorders & Plasma::FrameSvg::TopBorder) { + marginHint = q->elementSize(QStringLiteral("shadow-hint-top-margin")); + + if (marginHint.isValid()) { + top = marginHint.height(); + } else { + top = m_shadowPixmaps[0].height(); // top + } + } else { + top = 1; + } + + if (enabledBorders & Plasma::FrameSvg::RightBorder) { + marginHint = q->elementSize(QStringLiteral("shadow-hint-right-margin")); + + if (marginHint.isValid()) { + right = marginHint.width(); + } else { + right = m_shadowPixmaps[2].width(); // right + } + } else { + right = 1; + } + + if (enabledBorders & Plasma::FrameSvg::BottomBorder) { + marginHint = q->elementSize(QStringLiteral("shadow-hint-bottom-margin")); + + if (marginHint.isValid()) { + bottom = marginHint.height(); + } else { + bottom = m_shadowPixmaps[4].height(); // bottom + } + } else { + bottom = 1; + } + + if (enabledBorders & Plasma::FrameSvg::LeftBorder) { + marginHint = q->elementSize(QStringLiteral("shadow-hint-left-margin")); + + if (marginHint.isValid()) { + left = marginHint.width(); + } else { + left = m_shadowPixmaps[6].width(); // left + } + } else { + left = 1; + } + + data[enabledBorders] << top << right << bottom << left; +} + +void PanelShadows::Private::freeX11Pixmaps() +{ +#if HAVE_X11 + + if (!m_isX11) { + return; + } + + auto *display = QX11Info::display(); + + if (!display) { + return; + } + + foreach (const QPixmap &pixmap, m_shadowPixmaps) { + if (!pixmap.isNull()) { + XFreePixmap(display, reinterpret_cast(createPixmap(pixmap))); + } + } + + if (!m_emptyCornerPix.isNull()) { + XFreePixmap(display, reinterpret_cast(createPixmap(m_emptyCornerPix))); + } + + if (!m_emptyCornerBottomPix.isNull()) { + XFreePixmap(display, reinterpret_cast(createPixmap(m_emptyCornerBottomPix))); + } + + if (!m_emptyCornerLeftPix.isNull()) { + XFreePixmap(display, reinterpret_cast(createPixmap(m_emptyCornerLeftPix))); + } + + if (!m_emptyCornerRightPix.isNull()) { + XFreePixmap(display, reinterpret_cast(createPixmap(m_emptyCornerRightPix))); + } + + if (!m_emptyCornerTopPix.isNull()) { + XFreePixmap(display, reinterpret_cast(createPixmap(m_emptyCornerTopPix))); + } + + if (!m_emptyVerticalPix.isNull()) { + XFreePixmap(display, reinterpret_cast(createPixmap(m_emptyVerticalPix))); + } + + if (!m_emptyHorizontalPix.isNull()) { + XFreePixmap(display, reinterpret_cast(createPixmap(m_emptyHorizontalPix))); + } + +#endif +} + +void PanelShadows::Private::clearPixmaps() +{ +#if HAVE_X11 + freeX11Pixmaps(); + + m_emptyCornerPix = QPixmap(); + m_emptyCornerBottomPix = QPixmap(); + m_emptyCornerLeftPix = QPixmap(); + m_emptyCornerRightPix = QPixmap(); + m_emptyCornerTopPix = QPixmap(); + m_emptyVerticalPix = QPixmap(); + m_emptyHorizontalPix = QPixmap(); +#endif + freeWaylandBuffers(); + m_shadowPixmaps.clear(); + data.clear(); +} + +void PanelShadows::Private::freeWaylandBuffers() +{ + m_wayland.shadowBuffers.clear(); +} + +void PanelShadows::Private::updateShadow(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders) +{ +#if HAVE_X11 + + if (m_isX11) { + updateShadowX11(window, enabledBorders); + } + +#endif + + if (m_wayland.manager) { + updateShadowWayland(window, enabledBorders); + } +} + +void PanelShadows::Private::updateShadowX11(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders) +{ +#if HAVE_X11 + + if (m_shadowPixmaps.isEmpty()) { + setupPixmaps(); + } + + if (!data.contains(enabledBorders)) { + setupData(enabledBorders); + } + + Display *dpy = QX11Info::display(); + Atom atom = XInternAtom(dpy, "_KDE_NET_WM_SHADOW", False); + + qDebug() << "going to set the shadow of" << window->winId() << "to" << data; + XChangeProperty(dpy, window->winId(), atom, XA_CARDINAL, 32, PropModeReplace, + reinterpret_cast(data[enabledBorders].constData()), data[enabledBorders].size()); +#endif +} + +void PanelShadows::Private::updateShadowWayland(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders) +{ + if (!m_wayland.shmPool) { + return; + } + + if (m_wayland.shadowBuffers.isEmpty()) { + setupPixmaps(); + } + + // TODO: check whether the surface already has a shadow + KWayland::Client::Surface *surface = KWayland::Client::Surface::fromWindow(const_cast(window)); + + if (!surface) { + return; + } + + auto shadow = m_wayland.manager->createShadow(surface, surface); + + //shadow-top + if (enabledBorders & Plasma::FrameSvg::TopBorder) { + shadow->attachTop(m_wayland.shadowBuffers.at(0)); + } + + //shadow-topright + if (enabledBorders & Plasma::FrameSvg::TopBorder && + enabledBorders & Plasma::FrameSvg::RightBorder) { + shadow->attachTopRight(m_wayland.shadowBuffers.at(1)); + } + + //shadow-right + if (enabledBorders & Plasma::FrameSvg::RightBorder) { + shadow->attachRight(m_wayland.shadowBuffers.at(2)); + } + + //shadow-bottomright + if (enabledBorders & Plasma::FrameSvg::BottomBorder && + enabledBorders & Plasma::FrameSvg::RightBorder) { + shadow->attachBottomRight(m_wayland.shadowBuffers.at(3)); + } + + //shadow-bottom + if (enabledBorders & Plasma::FrameSvg::BottomBorder) { + shadow->attachBottom(m_wayland.shadowBuffers.at(4)); + } + + //shadow-bottomleft + if (enabledBorders & Plasma::FrameSvg::BottomBorder && + enabledBorders & Plasma::FrameSvg::LeftBorder) { + shadow->attachBottomLeft(m_wayland.shadowBuffers.at(5)); + } + + //shadow-left + if (enabledBorders & Plasma::FrameSvg::LeftBorder) { + shadow->attachLeft(m_wayland.shadowBuffers.at(6)); + } + + //shadow-topleft + if (enabledBorders & Plasma::FrameSvg::TopBorder && + enabledBorders & Plasma::FrameSvg::LeftBorder) { + shadow->attachTopLeft(m_wayland.shadowBuffers.at(7)); + } + + QSize marginHint; + QMarginsF margins = QMarginsF(1, 1, 1, 1); + + if (enabledBorders & Plasma::FrameSvg::TopBorder) { + marginHint = q->elementSize(QStringLiteral("shadow-hint-top-margin")); + + if (marginHint.isValid()) { + margins.setTop(marginHint.height()); + } else { + margins.setTop(m_shadowPixmaps[0].height()); + } + } + + if (enabledBorders & Plasma::FrameSvg::RightBorder) { + marginHint = q->elementSize(QStringLiteral("shadow-hint-right-margin")); + + if (marginHint.isValid()) { + margins.setRight(marginHint.width()); + } else { + margins.setRight(m_shadowPixmaps[2].width()); + } + } + + if (enabledBorders & Plasma::FrameSvg::BottomBorder) { + marginHint = q->elementSize(QStringLiteral("shadow-hint-bottom-margin")); + + if (marginHint.isValid()) { + margins.setBottom(marginHint.height()); + } else { + margins.setBottom(m_shadowPixmaps[4].height()); + } + } + + if (enabledBorders & Plasma::FrameSvg::LeftBorder) { + marginHint = q->elementSize(QStringLiteral("shadow-hint-left-margin")); + + if (marginHint.isValid()) { + margins.setLeft(marginHint.width()); + } else { + margins.setLeft(m_shadowPixmaps[6].width()); + } + } + + shadow->setOffsets(margins); + shadow->commit(); + surface->commit(KWayland::Client::Surface::CommitFlag::None); +} + +void PanelShadows::Private::clearShadow(const QWindow *window) +{ + if (!static_cast(window)->surfaceHandle()) { + qWarning() << "Cannot clear shadow from window without native surface!"; + return; + } + +#if HAVE_X11 + + if (m_isX11) { + clearShadowX11(window); + } + +#endif + + if (m_wayland.manager) { + clearShadowWayland(window); + } +} + +void PanelShadows::Private::clearShadowX11(const QWindow *window) +{ +#if HAVE_X11 + Display *dpy = QX11Info::display(); + Atom atom = XInternAtom(dpy, "_KDE_NET_WM_SHADOW", False); + XDeleteProperty(dpy, window->winId(), atom); +#endif +} + +void PanelShadows::Private::clearShadowWayland(const QWindow *window) +{ + KWayland::Client::Surface *surface = KWayland::Client::Surface::fromWindow(const_cast(window)); + + if (!surface) { + return; + } + + m_wayland.manager->removeShadow(surface); + surface->commit(KWayland::Client::Surface::CommitFlag::None); +} + +bool PanelShadows::enabled() const +{ + return hasElement(QStringLiteral("shadow-left")); +} + +void PanelShadows::Private::setupWaylandIntegration() +{ + if (!KWindowSystem::isPlatformWayland()) { + return; + } + + using namespace KWayland::Client; + ConnectionThread *connection = ConnectionThread::fromApplication(q); + + if (!connection) { + return; + } + + Registry *registry = new Registry(q); + registry->create(connection); + connect(registry, &Registry::shadowAnnounced, q, + [this, registry](quint32 name, quint32 version) { + m_wayland.manager = registry->createShadowManager(name, version, q); + updateShadows(); + }, Qt::QueuedConnection + ); + connect(registry, &Registry::shmAnnounced, q, + [this, registry](quint32 name, quint32 version) { + m_wayland.shmPool = registry->createShmPool(name, version, q); + updateShadows(); + }, Qt::QueuedConnection + ); + registry->setup(); + connection->roundtrip(); +} + +#include "moc_panelshadows_p.cpp" diff --git a/app/panelshadows_p.h b/app/panelshadows_p.h new file mode 100644 index 000000000..de54409c0 --- /dev/null +++ b/app/panelshadows_p.h @@ -0,0 +1,52 @@ +/* +* Copyright 2011 by Aaron Seigo +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License version 2, +* or (at your option) any later version. +* +* This program 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 Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef PLASMA_PANELSHADOWS_H +#define PLASMA_PANELSHADOWS_H + +#include + +#include "plasma/framesvg.h" +#include "plasma/svg.h" + + +class PanelShadows : public Plasma::Svg { + Q_OBJECT + +public: + explicit PanelShadows(QObject *parent = 0, const QString &prefix = QStringLiteral("widgets/panel-background")); + ~PanelShadows() override; + + static PanelShadows *self(); + + void addWindow(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders = Plasma::FrameSvg::AllBorders); + void removeWindow(const QWindow *window); + + void setEnabledBorders(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders = Plasma::FrameSvg::AllBorders); + + bool enabled() const; + +private: + class Private; + Private *const d; + + Q_PRIVATE_SLOT(d, void updateShadows()) + Q_PRIVATE_SLOT(d, void windowDestroyed(QObject *deletedObject)) +}; + +#endif diff --git a/containment/contents/ui/DebugWindow.qml b/containment/contents/ui/DebugWindow.qml index 0f90ed229..2f0788a51 100644 --- a/containment/contents/ui/DebugWindow.qml +++ b/containment/contents/ui/DebugWindow.qml @@ -305,5 +305,18 @@ Window{ text: visibilityManager.panelIsBiggerFromIconSize } + Text{ + text: "Draw Shadows (external)"+space + } + + Text{ + text: { + if (root.drawShadowsExternal) + return "Yes"; + else + return "No"; + } + } + } } diff --git a/containment/contents/ui/EditModeVisual.qml b/containment/contents/ui/EditModeVisual.qml index 3b5b62d3e..0755176f9 100644 --- a/containment/contents/ui/EditModeVisual.qml +++ b/containment/contents/ui/EditModeVisual.qml @@ -27,8 +27,8 @@ import org.kde.latte 0.1 as Latte Image{ id: editVisual - width: root.isHorizontal ? root.maxLength : visibilityManager.thicknessNormalOriginal - height: root.isVertical ? root.maxLength : visibilityManager.thicknessNormalOriginal + width: root.isHorizontal ? editLength : visibilityManager.thicknessNormalOriginal + height: root.isVertical ? editLength : visibilityManager.thicknessNormalOriginal fillMode: Image.Tile source: "../icons/blueprint.jpg" @@ -37,6 +37,8 @@ Image{ property int speed: root.durationTime*4*units.longDuration property int thickness: visibilityManager.thicknessNormalOriginal + root.editShadow property int rootThickness: visibilityManager.thicknessZoomOriginal + root.editShadow + property int editLength: root.isHorizontal ? (root.drawShadowsExternal ? root.width - plasmoid.configuration.iconSize/4 : root.maxLength) : + (root.drawShadowsExternal ? root.height - plasmoid.configuration.iconSize/4 : root.maxLength) property bool animationSent: false property bool farEdge: (plasmoid.location===PlasmaCore.Types.BottomEdge) || (plasmoid.location===PlasmaCore.Types.RightEdge) @@ -49,7 +51,6 @@ Image{ color: "#ee080808" } - /*Behavior on width { NumberAnimation { duration: 300 } enabled: root.isHorizontal @@ -76,7 +77,7 @@ Image{ } onEditAnimationEndedChanged: { - if (editAnimationEnded) { + if (editAnimationEnded && !root.drawShadowsExternal) { dock.shadow = root.editShadow; } else { dock.shadow = 0; @@ -108,23 +109,23 @@ Image{ if (root.isHorizontal) { if (plasmoid.configuration.panelPosition === Latte.Dock.Justify) { - x = root.width/2 - root.maxLength/2; + x = root.width/2 - editVisual.editLength/2; } else if (root.panelAlignment === Latte.Dock.Left) { x = 0; } else if (root.panelAlignment === Latte.Dock.Center) { - x = root.width/2 - root.maxLength/2; + x = root.width/2 - editVisual.editLength/2; } else if (root.panelAlignment === Latte.Dock.Right) { - x = root.width - root.maxLength; + x = root.width - editVisual.editLength; } } else if (root.isVertical) { if (plasmoid.configuration.panelPosition === Latte.Dock.Justify) { - y = root.height/2 - root.maxLength/2; + y = root.height/2 - editVisual.editLength/2; } else if (root.panelAlignment === Latte.Dock.Top) { y = 0; } else if (root.panelAlignment === Latte.Dock.Center) { - y = root.height/2 - root.maxLength/2; + y = root.height/2 - editVisual.editLength/2; } else if (root.panelAlignment === Latte.Dock.Bottom) { - y = root.height - root.maxLength; + y = root.height - editVisual.editLength; } } } @@ -204,7 +205,7 @@ Image{ PropertyAnimation { target: editVisual property: "opacity" - to: 0.6 + to: root.drawShadowsExternal ? 0.3 : 0.6 duration: editVisual.speed / 2 easing.type: Easing.OutQuad } diff --git a/containment/contents/ui/PanelBox.qml b/containment/contents/ui/PanelBox.qml index fefcb9931..4fee9d182 100644 --- a/containment/contents/ui/PanelBox.qml +++ b/containment/contents/ui/PanelBox.qml @@ -34,13 +34,14 @@ Item{ id:barLine opacity: root.useThemePanel ? 1 : 0 - // parent: root - z:0 + // parent: root - property int panelWidth: (root.panelAlignment === Latte.Dock.Justify) && root.isHorizontal && !root.editMode ? - layoutsContainer.width + spacing : mainLayout.width + spacing - property int panelHeight: (root.panelAlignment === Latte.Dock.Justify) && root.isVertical && !root.editMode ? - layoutsContainer.height + spacing : mainLayout.height + spacing + property int panelWidth: root.drawShadowsExternal ? root.width : + (root.panelAlignment === Latte.Dock.Justify) && root.isHorizontal && !root.editMode ? + layoutsContainer.width + spacing : mainLayout.width + spacing + property int panelHeight: root.drawShadowsExternal ? root.height : + (root.panelAlignment === Latte.Dock.Justify) && root.isVertical && !root.editMode ? + layoutsContainer.height + spacing : mainLayout.height + spacing width: root.isHorizontal ? panelWidth : smallSize height: root.isVertical ? panelHeight : smallSize @@ -86,21 +87,40 @@ Item{ PlasmaCore.FrameSvgItem{ id: shadowsSvgItem - width: root.isVertical ? panelSize + margins.left + margins.right: parent.width + margins.left + margins.right - height: root.isVertical ? parent.height + margins.left + margins.right : panelSize + margins.top + margins.bottom + width: root.isVertical ? panelSize + marginsWidth: parent.width + marginsWidth + height: root.isVertical ? parent.height + marginsHeight : panelSize + marginsHeight - imagePath: "translucent/widgets/panel-background" - prefix:"shadow" + imagePath: root.drawShadowsExternal ? "" : "translucent/widgets/panel-background" + prefix: root.drawShadowsExternal ? "" : "shadow" opacity: root.useThemePanel ? 1 : 0 visible: (opacity == 0) ? false : true + property int marginsWidth: root.drawShadowsExternal ? 0 : margins.left + margins.right + property int marginsHeight: root.drawShadowsExternal ? 0 : margins.top + margins.bottom + property int panelSize: automaticPanelSize + property int automaticPanelSize: root.drawShadowsExternal ? root.themePanelSize + root.panelShadow: + Math.min(root.themePanelSize + root.panelShadow + 1, + root.statesLineSize + root.iconSize + root.iconMargin + 1) - property int automaticPanelSize: Math.min(root.themePanelSize + root.panelShadow, root.statesLineSize + root.iconSize + root.iconMargin) - - property int shadowsSize: shadowsSvgItem && root.useThemePanel ? - (root.isVertical ? shadowsSvgItem.margins.right : shadowsSvgItem.margins.bottom) : 0 + property int shadowsSize: { + if (shadowsSvgItem && root.useThemePanel){ + 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{ NumberAnimation { duration: 200 } @@ -122,11 +142,47 @@ Item{ PlasmaCore.FrameSvgItem{ - anchors.margins: belower.width-1 + anchors.margins: root.drawShadowsExternal ? 0 : belower.width-1 anchors.fill:parent // imagePath: root.transparentPanel ? "translucent/widgets/panel-background" : // "widgets/panel-background" imagePath: "widgets/panel-background" + + onRepaintNeeded: { + if (root.drawShadowsExternal) + adjustPrefix(); + } + + enabledBorders: dock.enabledBorders + + 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 = ""; + } + if (hasElementPrefix(pre)) { + prefix = pre; + } else { + prefix = ""; + } + } + } } diff --git a/containment/contents/ui/VisibilityManager.qml b/containment/contents/ui/VisibilityManager.qml index 83c75c235..2a1127959 100644 --- a/containment/contents/ui/VisibilityManager.qml +++ b/containment/contents/ui/VisibilityManager.qml @@ -40,7 +40,7 @@ Item{ property bool inStartup: root.inStartup property bool normalState : false // this is being set from updateMaskArea property bool previousNormalState : false // this is only for debugging purposes - property bool panelIsBiggerFromIconSize: root.realPanelSize+root.panelShadow > root.statesLineSize + root.iconSize + root.iconMargin + 1 + property bool panelIsBiggerFromIconSize: root.useThemePanel && (root.themePanelSize >= (root.iconSize + root.iconMargin + 1)) property int animationSpeed: root.durationTime * 1.2 * units.longDuration property int length: root.isVertical ? Screen.height : Screen.width //screenGeometry.height : screenGeometry.width @@ -75,6 +75,20 @@ Item{ value: thicknessNormalOriginal } + Binding{ + target: dock + property: "drawShadows" + when: dock + value: root.drawShadowsExternal + } + + Binding{ + target: dock + property: "maxLength" + when: dock + value: plasmoid.configuration.maxLength/100 + } + onInStartupChanged: { if (!inStartup) { delayAnimationTimer.start(); @@ -263,7 +277,11 @@ Item{ newMaskArea.height = tempLength; } - dock.maskArea = newMaskArea; + if (root.drawShadowsExternal) { + dock.maskArea = Qt.rect(0,0,root.width,root.height); + } else { + dock.maskArea = newMaskArea; + } //console.log("update mask area:"+newMaskArea); if(normalState && !dock.visibility.isHidden){ @@ -271,7 +289,7 @@ Item{ //the shadows size must be removed from the maskArea //before updating the localDockGeometry - if(panelIsBiggerFromIconSize) { + if(panelIsBiggerFromIconSize && !root.drawShadowsExternal) { var shadow = root.panelShadow; if (plasmoid.formFactor === PlasmaCore.Types.Vertical) { diff --git a/containment/contents/ui/main.qml b/containment/contents/ui/main.qml index d399c2f7f..db326a34e 100644 --- a/containment/contents/ui/main.qml +++ b/containment/contents/ui/main.qml @@ -46,6 +46,10 @@ DragDrop.DropArea { property bool automaticSize: plasmoid.configuration.automaticIconSize property bool confirmedDragEntered: false + property bool drawShadowsExternal: visibilityManager.panelIsBiggerFromIconSize && (zoomFactor === 1.0) + && (dock.visibility.mode === Latte.Dock.AlwaysVisible) + && (plasmoid.configuration.panelPosition === Latte.Dock.Justify) + property bool editMode: plasmoid.userConfiguring property bool immutable: plasmoid.immutable property bool inStartup: true @@ -946,7 +950,7 @@ DragDrop.DropArea { function updateLayouts(){ if(!root.editMode){ - // console.log("update layout - internal view splitters count:"+internalViewSplittersCount()); + // console.log("update layout - internal view splitters count:"+internalViewSplittersCount()); if (internalViewSplittersCount() === 2) { var splitter = -1; var splitter2 = -1; @@ -962,14 +966,14 @@ DragDrop.DropArea { } } - // console.log("update layouts 1:"+splitter + " - "+splitter2); + // console.log("update layouts 1:"+splitter + " - "+splitter2); for (var i=0; i<=splitter; ++i){ var item = mainLayout.children[0]; item.parent = startLayout; } splitter2 = splitter2 - splitter - 1; - // console.log("update layouts 2:"+splitter + " - "+splitter2); + // console.log("update layouts 2:"+splitter + " - "+splitter2); totalChildren = mainLayout.children.length; for (var i=splitter2+1; i1) @@ -1147,20 +1168,6 @@ DragDrop.DropArea { } } - - Loader{ - anchors.fill: parent - - // FIX IT && TEST IT: it is crashing Plasma with two Now Docks one of which has only - // task manager (small) - //active: root.useThemePanel - active: windowSystem.compositingActive - - sourceComponent: PanelBox{} - } - - - Grid{ id:startLayout diff --git a/shell/contents/configuration/AppearanceConfig.qml b/shell/contents/configuration/AppearanceConfig.qml index 206ec308d..292ca2748 100644 --- a/shell/contents/configuration/AppearanceConfig.qml +++ b/shell/contents/configuration/AppearanceConfig.qml @@ -250,7 +250,7 @@ PlasmaComponents.Page { value: plasmoid.configuration.panelSize minimumValue: 0 - maximumValue: Number(1.12 * plasmoid.configuration.iconSize).toFixed(0) //0.12*iconSize is the iconMargin + maximumValue: Number(1.2 * plasmoid.configuration.iconSize).toFixed(0) //0.12*iconSize is the iconMargin, 0.08 for statesLine stepSize: 2 function updatePanelSize() {