Commit a3943400 authored by Niccolò Venerandi's avatar Niccolò Venerandi Committed by Nate Graham
Browse files

Implement floating panel support

Please refer to plasma-desktop!714
for explanation and discussion.
parent 9756b911
Pipeline #171932 passed with stage
in 6 minutes and 38 seconds
......@@ -57,6 +57,7 @@ PanelView::PanelView(ShellCorona *corona, QScreen *targetScreen, QWindow *parent
, m_distance(0)
, m_thickness(30)
, m_initCompleted(false)
, m_floating(false)
, m_alignment(Qt::AlignLeft)
, m_corona(corona)
, m_visibilityMode(NormalPanel)
......@@ -104,6 +105,7 @@ PanelView::PanelView(ShellCorona *corona, QScreen *targetScreen, QWindow *parent
rootContext()->setContextProperty(QStringLiteral("panel"), this);
setSource(m_corona->kPackage().fileUrl("views", QStringLiteral("Panel.qml")));
updatePadding();
updateFloating();
}
PanelView::~PanelView()
......@@ -228,6 +230,21 @@ int PanelView::thickness() const
return m_thickness;
}
int PanelView::totalThickness() const {
switch (containment()->location()) {
case Plasma::Types::TopEdge:
return thickness() + m_topFloatingPadding + m_bottomFloatingPadding;
case Plasma::Types::LeftEdge:
return thickness() + m_leftFloatingPadding + m_rightFloatingPadding;
case Plasma::Types::RightEdge:
return thickness() + m_rightFloatingPadding + m_leftFloatingPadding;
case Plasma::Types::BottomEdge:
return thickness() + m_bottomFloatingPadding + m_topFloatingPadding;
default:
return thickness();
}
}
void PanelView::setThickness(int value)
{
if (value == thickness()) {
......@@ -323,6 +340,29 @@ void PanelView::setDistance(int dist)
positionPanel();
}
bool PanelView::floating() const
{
return m_floating;
}
void PanelView::setFloating(bool floating)
{
if (m_floating == floating) {
return;
}
m_floating = floating;
if (config().isValid() && config().parent().isValid()) {
config().parent().writeEntry("floating", (int)floating);
m_corona->requestApplicationConfigSync();
}
Q_EMIT floatingChanged();
updateFloating();
updateEnabledBorders();
updateMask();
}
Plasma::Types::BackgroundHints PanelView::backgroundHints() const
{
return m_backgroundHints;
......@@ -516,17 +556,17 @@ QRect PanelView::geometryByDistance(int distance) const
switch (m_alignment) {
case Qt::AlignCenter:
// Never use rect.right(); for historical reasons it returns left() + width() - 1; see https://doc.qt.io/qt-5/qrect.html#right
position = QPoint(QPoint(screenGeometry.x() + screenGeometry.width(), screenGeometry.center().y()) - QPoint(thickness() + distance, 0)
position = QPoint(QPoint(screenGeometry.x() + screenGeometry.width(), screenGeometry.center().y()) - QPoint(totalThickness() + distance, 0)
+ QPoint(0, m_offset - height() / 2));
break;
case Qt::AlignRight:
position = QPoint(QPoint(screenGeometry.x() + screenGeometry.width(), screenGeometry.y() + screenGeometry.height())
- QPoint(thickness() + distance, 0) - QPoint(0, m_offset + height()));
- QPoint(totalThickness() + distance, 0) - QPoint(0, m_offset + height()));
break;
case Qt::AlignLeft:
default:
position =
QPoint(QPoint(screenGeometry.x() + screenGeometry.width(), screenGeometry.y()) - QPoint(thickness() + distance, 0) + QPoint(0, m_offset));
QPoint(QPoint(screenGeometry.x() + screenGeometry.width(), screenGeometry.y()) - QPoint(totalThickness() + distance, 0) + QPoint(0, m_offset));
}
break;
......@@ -534,17 +574,17 @@ QRect PanelView::geometryByDistance(int distance) const
default:
switch (m_alignment) {
case Qt::AlignCenter:
position = QPoint(QPoint(screenGeometry.center().x(), screenGeometry.bottom() - thickness() - distance) + QPoint(m_offset - width() / 2, 1));
position = QPoint(QPoint(screenGeometry.center().x(), screenGeometry.bottom() - totalThickness() - distance) + QPoint(m_offset - width() / 2, 1));
break;
case Qt::AlignRight:
position = QPoint(screenGeometry.bottomRight() - QPoint(0, thickness() + distance) - QPoint(m_offset + width(), -1));
position = QPoint(screenGeometry.bottomRight() - QPoint(0, totalThickness() + distance) - QPoint(m_offset + width(), -1));
break;
case Qt::AlignLeft:
default:
position = QPoint(screenGeometry.bottomLeft() - QPoint(0, thickness() + distance) + QPoint(m_offset, 1));
position = QPoint(screenGeometry.bottomLeft() - QPoint(0, totalThickness() + distance) + QPoint(m_offset, 1));
}
}
QRect ret = formFactor() == Plasma::Types::Vertical ? QRect(position, QSize(thickness(), height())) : QRect(position, QSize(width(), thickness()));
QRect ret = formFactor() == Plasma::Types::Vertical ? QRect(position, QSize(totalThickness(), height())) : QRect(position, QSize(width(), totalThickness()));
ret = ret.intersected(screenGeometry);
return ret;
}
......@@ -569,15 +609,15 @@ void PanelView::resizePanel()
if (formFactor() == Plasma::Types::Vertical) {
const int minSize = qMax(MINSIZE, m_minLength);
const int maxSize = qMin(m_maxLength, m_screenToFollow->size().height() - m_offset);
targetMinSize = QSize(thickness(), minSize);
targetMaxSize = QSize(thickness(), maxSize);
targetSize = QSize(thickness(), qBound(minSize, m_contentLength, maxSize));
targetMinSize = QSize(totalThickness(), minSize);
targetMaxSize = QSize(totalThickness(), maxSize);
targetSize = QSize(totalThickness(), qBound(minSize, m_contentLength, maxSize));
} else {
const int minSize = qMax(MINSIZE, m_minLength);
const int maxSize = qMin(m_maxLength, m_screenToFollow->size().width() - m_offset);
targetMinSize = QSize(minSize, thickness());
targetMaxSize = QSize(maxSize, thickness());
targetSize = QSize(qBound(minSize, m_contentLength, maxSize), thickness());
targetMinSize = QSize(minSize, totalThickness());
targetMaxSize = QSize(maxSize, totalThickness());
targetSize = QSize(std::clamp(m_contentLength, minSize, maxSize), totalThickness());
}
if (minimumSize() != targetMinSize) {
setMinimumSize(targetMinSize);
......@@ -617,6 +657,7 @@ void PanelView::restore()
m_offset = qMax(0, m_offset);
}
setFloating((bool)config().parent().readEntry<int>("floating", configDefaults().parent().readEntry<int>("floating", false)));
setThickness(readConfigValueWithFallBack("thickness", m_thickness));
const QSize screenSize = m_screenToFollow->size();
......@@ -1049,6 +1090,7 @@ bool PanelView::event(QEvent *e)
case QPlatformSurfaceEvent::SurfaceCreated:
setupWaylandIntegration();
PanelShadows::self()->addWindow(this, enabledBorders());
updateEnabledBorders();
break;
case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
delete m_shellSurface;
......@@ -1108,9 +1150,10 @@ void PanelView::updateMask()
const QVariant maskProperty = rootObject->property("panelMask");
if (static_cast<QMetaType::Type>(maskProperty.type()) == QMetaType::QRegion) {
mask = maskProperty.value<QRegion>();
mask.translate(rootObject->property("maskOffsetX").toInt(),
rootObject->property("maskOffsetY").toInt());
}
}
KWindowEffects::enableBlurBehind(this, m_theme.blurBehindEnabled(), mask);
KWindowEffects::enableBackgroundContrast(this,
m_theme.backgroundContrastEnabled(),
......@@ -1217,28 +1260,28 @@ void PanelView::updateStruts()
switch (location()) {
case Plasma::Types::TopEdge:
strut.top_width = thickness() + topOffset;
strut.top_width = totalThickness() + topOffset;
strut.top_start = x();
strut.top_end = x() + width() - 1;
// qDebug() << "setting top edge to" << strut.top_width << strut.top_start << strut.top_end;
break;
case Plasma::Types::BottomEdge:
strut.bottom_width = thickness() + bottomOffset;
strut.bottom_width = totalThickness() + bottomOffset;
strut.bottom_start = x();
strut.bottom_end = x() + width() - 1;
// qDebug() << "setting bottom edge to" << strut.bottom_width << strut.bottom_start << strut.bottom_end;
break;
case Plasma::Types::RightEdge:
strut.right_width = thickness() + rightOffset;
strut.right_width = totalThickness() + rightOffset;
strut.right_start = y();
strut.right_end = y() + height() - 1;
// qDebug() << "setting right edge to" << strut.right_width << strut.right_start << strut.right_end;
break;
case Plasma::Types::LeftEdge:
strut.left_width = thickness() + leftOffset;
strut.left_width = totalThickness() + leftOffset;
strut.left_start = y();
strut.left_end = y() + height() - 1;
// qDebug() << "setting left edge to" << strut.left_width << strut.left_start << strut.left_end;
......@@ -1305,13 +1348,24 @@ void PanelView::handleQmlStatusChange(QQmlComponent::Status status)
disconnect(this, &QuickViewSharedEngine::statusChanged, this, &PanelView::handleQmlStatusChange);
updatePadding();
int paddingSignal = rootObject->metaObject()->indexOfSignal(SIGNAL(bottomPaddingChanged()));
updateFloating();
int paddingSignal = rootObject->metaObject()->indexOfSignal("bottomPaddingChanged()");
if (paddingSignal >= 0) {
connect(rootObject, SIGNAL(bottomPaddingChanged()), this, SLOT(updatePadding()));
connect(rootObject, SIGNAL(topPaddingChanged()), this, SLOT(updatePadding()));
connect(rootObject, SIGNAL(rightPaddingChanged()), this, SLOT(updatePadding()));
connect(rootObject, SIGNAL(leftPaddingChanged()), this, SLOT(updatePadding()));
}
const int floatingSignal = rootObject->metaObject()->indexOfSignal("bottomFloatingPaddingChanged()");
if (floatingSignal >= 0) {
connect(rootObject, SIGNAL(bottomFloatingPaddingChanged()), this, SLOT(updateFloating()));
connect(rootObject, SIGNAL(topFloatingPaddingChanged()), this, SLOT(updateFloating()));
connect(rootObject, SIGNAL(rightFloatingPaddingChanged()), this, SLOT(updateFloating()));
connect(rootObject, SIGNAL(leftFloatingPaddingChanged()), this, SLOT(updateFloating()));
connect(rootObject, SIGNAL(hasShadowsChanged()), this, SLOT(updateShadows()));
connect(rootObject, SIGNAL(maskOffsetXChanged()), this, SLOT(updateMask()));
connect(rootObject, SIGNAL(maskOffsetYChanged()), this, SLOT(updateMask()));
}
const QVariant maskProperty = rootObject->property("panelMask");
if (static_cast<QMetaType::Type>(maskProperty.type()) == QMetaType::QRegion) {
......@@ -1394,7 +1448,6 @@ bool PanelView::edgeActivated() const
void PanelView::updateEnabledBorders()
{
Plasma::FrameSvg::EnabledBorders borders = Plasma::FrameSvg::AllBorders;
if (m_backgroundHints == Plasma::Types::NoBackground) {
borders = Plasma::FrameSvg::NoBorder;
} else {
......@@ -1448,4 +1501,32 @@ void PanelView::updatePadding()
m_bottomPadding = rootObject()->property("bottomPadding").toInt();
}
void PanelView::updateShadows()
{
if (!rootObject()) {
return;
}
bool hasShadows = rootObject()->property("hasShadows").toBool();
if (hasShadows) {
PanelShadows::self()->addWindow(this, enabledBorders());
} else {
PanelShadows::self()->removeWindow(this);
}
}
void PanelView::updateFloating()
{
if (!rootObject()) {
return;
}
m_leftFloatingPadding = rootObject()->property("leftFloatingPadding").toInt();
m_rightFloatingPadding = rootObject()->property("rightFloatingPadding").toInt();
m_topFloatingPadding = rootObject()->property("topFloatingPadding").toInt();
m_bottomFloatingPadding = rootObject()->property("bottomFloatingPadding").toInt();
positionPanel();
resizePanel();
updateMask();
}
#include "moc_panelview.cpp"
......@@ -99,6 +99,12 @@ class PanelView : public PlasmaQuick::ContainmentView
*/
Q_PROPERTY(bool adaptiveOpacityEnabled READ adaptiveOpacityEnabled NOTIFY adaptiveOpacityEnabledChanged)
/**
* Property that determines whether the panel is currently floating or not
* @since 5.25
*/
Q_PROPERTY(int floating READ floating WRITE setFloating NOTIFY floatingChanged)
public:
enum VisibilityMode {
NormalPanel = 0, /** default, always visible panel, the windowmanager reserves a places for it */
......@@ -133,6 +139,7 @@ public:
int thickness() const;
void setThickness(int thickness);
int totalThickness() const;
int length() const;
void setLength(int value);
......@@ -146,6 +153,9 @@ public:
int distance() const;
void setDistance(int dist);
bool floating() const;
void setFloating(bool floating);
Plasma::Types::BackgroundHints backgroundHints() const;
void setBackgroundHints(Plasma::Types::BackgroundHints hint);
......@@ -194,6 +204,7 @@ Q_SIGNALS:
void distanceChanged();
void backgroundHintsChanged();
void enabledBordersChanged();
void floatingChanged();
// QWindow does not have a property for screen. Adding this property requires re-implementing the signal
void screenToFollowChanged(QScreen *screen);
......@@ -221,6 +232,8 @@ private Q_SLOTS:
void updateMask();
void updateEnabledBorders();
void updatePadding();
void updateFloating();
void updateShadows();
private:
int readConfigValueWithFallBack(const QString &key, int defaultValue);
......@@ -243,7 +256,12 @@ private:
int m_topPadding;
int m_leftPadding;
int m_rightPadding;
int m_bottomFloatingPadding;
int m_topFloatingPadding;
int m_leftFloatingPadding;
int m_rightFloatingPadding;
bool m_initCompleted;
bool m_floating;
bool m_containsMouse = false;
bool m_fakeEventPending = false;
Qt::Alignment m_alignment;
......
......@@ -478,7 +478,7 @@ QByteArray ShellCorona::dumpCurrentLayoutJS() const
const qreal height =
// If we do not have a panel, fallback to 4 units
!view ? 4 : (qreal)view->thickness() / gridUnit;
!view ? 4 : (qreal)view->totalThickness() / gridUnit;
panelJson.insert("height", height);
if (view) {
......@@ -1064,16 +1064,16 @@ QRect ShellCorona::_availableScreenRect(int id) const
if (v->isVisible() && v->screen() == view->screen() && v->visibilityMode() != PanelView::AutoHide) {
switch (v->location()) {
case Plasma::Types::LeftEdge:
r.setLeft(r.left() + v->thickness());
r.setLeft(r.left() + v->totalThickness());
break;
case Plasma::Types::RightEdge:
r.setRight(r.right() - v->thickness());
r.setRight(r.right() - v->totalThickness());
break;
case Plasma::Types::TopEdge:
r.setTop(r.top() + v->thickness());
r.setTop(r.top() + v->totalThickness());
break;
case Plasma::Types::BottomEdge:
r.setBottom(r.bottom() - v->thickness());
r.setBottom(r.bottom() - v->totalThickness());
default:
break;
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment