mirror of
https://github.com/KDE/latte-dock.git
synced 2024-12-23 01:33:50 +03:00
support drawing panel shadows outside dock window
--this is set by default only in case of Always Visible, zoom factor 1.0, Justify alignment and maximum panel thickness
This commit is contained in:
parent
f9a2226457
commit
09629b774b
@ -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)
|
||||
|
||||
|
@ -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})
|
||||
|
1
app/config-latte.h.cmake
Normal file
1
app/config-latte.h.cmake
Normal file
@ -0,0 +1 @@
|
||||
#cmakedefine01 HAVE_X11
|
175
app/dockview.cpp
175
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:
|
||||
if (m_drawShadows) {
|
||||
position = {screenGeometry.x() + (screenGeometry.width() / 2 - maxLengthWidth / 2), screenGeometry.y()};
|
||||
} else {
|
||||
position = {screenGeometry.x(), screenGeometry.y()};
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Plasma::Types::BottomEdge:
|
||||
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:
|
||||
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:
|
||||
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
|
||||
|
@ -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<QScreen> 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<PlasmaQuick::ConfigView> m_configView;
|
||||
QPointer<VisibilityManager> m_visibility;
|
||||
|
||||
//only for the mask, not to actually paint
|
||||
Plasma::FrameSvg::EnabledBorders m_enabledBorders = Plasma::FrameSvg::AllBorders;
|
||||
};
|
||||
|
||||
}
|
||||
|
750
app/panelshadows.cpp
Normal file
750
app/panelshadows.cpp
Normal file
@ -0,0 +1,750 @@
|
||||
/*
|
||||
* Copyright 2011 by Aaron Seigo <aseigo@kde.org>
|
||||
*
|
||||
* 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 <QWindow>
|
||||
#include <QPainter>
|
||||
|
||||
#include <config-latte.h>
|
||||
|
||||
#include <KWindowSystem>
|
||||
#if HAVE_X11
|
||||
#include <QX11Info>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include <fixx11h.h>
|
||||
#endif
|
||||
|
||||
#include <KWayland/Client/connection_thread.h>
|
||||
#include <KWayland/Client/registry.h>
|
||||
#include <KWayland/Client/shadow.h>
|
||||
#include <KWayland/Client/shm_pool.h>
|
||||
#include <KWayland/Client/surface.h>
|
||||
|
||||
#include <qdebug.h>
|
||||
|
||||
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<QPixmap> 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<KWayland::Client::Buffer::Ptr> shadowBuffers;
|
||||
};
|
||||
Wayland m_wayland;
|
||||
|
||||
QHash<Plasma::FrameSvg::EnabledBorders, QVector<unsigned long>> data;
|
||||
QHash<const QWindow *, Plasma::FrameSvg::EnabledBorders> 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<QWindow *>(deletedObject));
|
||||
|
||||
if (m_windows.isEmpty()) {
|
||||
clearPixmaps();
|
||||
}
|
||||
}
|
||||
|
||||
void PanelShadows::Private::updateShadows()
|
||||
{
|
||||
setupPixmaps();
|
||||
QHash<const QWindow *, Plasma::FrameSvg::EnabledBorders>::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<unsigned long>(createPixmap(m_shadowPixmaps[0]));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyHorizontalPix));
|
||||
}
|
||||
|
||||
//shadow-topright
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[1]));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::TopBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerTopPix));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerRightPix));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerPix));
|
||||
}
|
||||
|
||||
//shadow-right
|
||||
if (enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[2]));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyVerticalPix));
|
||||
}
|
||||
|
||||
//shadow-bottomright
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[3]));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerBottomPix));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerRightPix));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerPix));
|
||||
}
|
||||
|
||||
//shadow-bottom
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[4]));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyHorizontalPix));
|
||||
}
|
||||
|
||||
//shadow-bottomleft
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[5]));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerBottomPix));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerLeftPix));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerPix));
|
||||
}
|
||||
|
||||
//shadow-left
|
||||
if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[6]));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyVerticalPix));
|
||||
}
|
||||
|
||||
//shadow-topleft
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[7]));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::TopBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerTopPix));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerLeftPix));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(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<unsigned long>(createPixmap(pixmap)));
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_emptyCornerPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerPix)));
|
||||
}
|
||||
|
||||
if (!m_emptyCornerBottomPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerBottomPix)));
|
||||
}
|
||||
|
||||
if (!m_emptyCornerLeftPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerLeftPix)));
|
||||
}
|
||||
|
||||
if (!m_emptyCornerRightPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerRightPix)));
|
||||
}
|
||||
|
||||
if (!m_emptyCornerTopPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerTopPix)));
|
||||
}
|
||||
|
||||
if (!m_emptyVerticalPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyVerticalPix)));
|
||||
}
|
||||
|
||||
if (!m_emptyHorizontalPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(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<const unsigned char *>(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<QWindow *>(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<const QSurface *>(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<QWindow *>(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"
|
52
app/panelshadows_p.h
Normal file
52
app/panelshadows_p.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2011 by Aaron Seigo <aseigo@kde.org>
|
||||
*
|
||||
* 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 <QSet>
|
||||
|
||||
#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
|
@ -305,5 +305,18 @@ Window{
|
||||
text: visibilityManager.panelIsBiggerFromIconSize
|
||||
}
|
||||
|
||||
Text{
|
||||
text: "Draw Shadows (external)"+space
|
||||
}
|
||||
|
||||
Text{
|
||||
text: {
|
||||
if (root.drawShadowsExternal)
|
||||
return "Yes";
|
||||
else
|
||||
return "No";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -35,11 +35,12 @@ Item{
|
||||
|
||||
opacity: root.useThemePanel ? 1 : 0
|
||||
// parent: root
|
||||
z:0
|
||||
|
||||
property int panelWidth: (root.panelAlignment === Latte.Dock.Justify) && root.isHorizontal && !root.editMode ?
|
||||
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.panelAlignment === Latte.Dock.Justify) && root.isVertical && !root.editMode ?
|
||||
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
|
||||
@ -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 = "";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -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
|
||||
@ -1040,6 +1044,19 @@ DragDrop.DropArea {
|
||||
|
||||
EditModeVisual{
|
||||
id:editModeVisual
|
||||
z: root.drawShadowsExternal ? 1 : 0
|
||||
}
|
||||
|
||||
Loader{
|
||||
anchors.fill: layoutsContainer
|
||||
|
||||
// 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{}
|
||||
z: root.drawShadowsExternal ? 0 : 1
|
||||
}
|
||||
|
||||
Item {
|
||||
@ -1048,6 +1065,7 @@ DragDrop.DropArea {
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
z:10
|
||||
|
||||
Rectangle{
|
||||
anchors.fill: parent
|
||||
@ -1069,6 +1087,7 @@ DragDrop.DropArea {
|
||||
Layout.preferredWidth: width
|
||||
Layout.preferredHeight: height
|
||||
opacity: 0
|
||||
z:10
|
||||
|
||||
AddWidgetVisual{}
|
||||
}
|
||||
@ -1076,6 +1095,7 @@ DragDrop.DropArea {
|
||||
Loader{
|
||||
anchors.fill: parent
|
||||
active: root.debugMode
|
||||
z:10
|
||||
|
||||
sourceComponent: Item{
|
||||
Rectangle{
|
||||
@ -1100,15 +1120,16 @@ DragDrop.DropArea {
|
||||
property int hoveredIndex: -1
|
||||
|
||||
x: (plasmoid.configuration.panelPosition === Latte.Dock.Justify) && root.isHorizontal
|
||||
&& !root.editMode && windowSystem.compositingActive ?
|
||||
&& !root.editMode && windowSystem.compositingActive && !root.drawShadowsExternal ?
|
||||
(dock.width/2) - (root.maxLength/2): 0
|
||||
y: (plasmoid.configuration.panelPosition === Latte.Dock.Justify) && root.isVertical
|
||||
&& !root.editMode && windowSystem.compositingActive ?
|
||||
&& !root.editMode && windowSystem.compositingActive && !root.drawShadowsExternal ?
|
||||
(dock.height/2) - (root.maxLength/2): 0
|
||||
width: (plasmoid.configuration.panelPosition === Latte.Dock.Justify) && root.isHorizontal && !root.editMode ?
|
||||
width: (plasmoid.configuration.panelPosition === Latte.Dock.Justify) && root.isHorizontal && !root.editMode && !root.drawShadowsExternal ?
|
||||
root.maxLength : parent.width
|
||||
height: (plasmoid.configuration.panelPosition === Latte.Dock.Justify) && root.isVertical && !root.editMode ?
|
||||
height: (plasmoid.configuration.panelPosition === Latte.Dock.Justify) && root.isVertical && !root.editMode && !root.drawShadowsExternal ?
|
||||
root.maxLength : parent.height
|
||||
z:10
|
||||
|
||||
property bool shouldCheckHalfs: (plasmoid.configuration.panelPosition === Latte.Dock.Justify) && (mainLayout.children>1)
|
||||
|
||||
@ -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
|
||||
|
||||
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user