Align Dialog Popups to align to be outside the docks.
For the WidgetExplorer we want to show the tooltips to the right of the scrollbar in the view, not to the right of the delegate the tooltip is for. This patch checks if the visualParent is in a dock. If so the popup is positioned outside I have also introduced a manual test for Dialog Positioning, and includied some fixes in the original logic. REVIEW: 115393
This commit is contained in:
parent
d3ae687cd7
commit
d7a3a10238
@ -31,6 +31,8 @@
|
||||
#include <QScreen>
|
||||
|
||||
#include <kwindowsystem.h>
|
||||
#include <KWindowSystem/KWindowInfo>
|
||||
|
||||
#include <kwindoweffects.h>
|
||||
#include <Plasma/Plasma>
|
||||
#include <Plasma/Corona>
|
||||
@ -61,8 +63,12 @@ DialogProxy::DialogProxy(QQuickItem *parent)
|
||||
m_syncTimer->setInterval(0);
|
||||
connect(m_syncTimer, &QTimer::timeout, this, &DialogProxy::syncToMainItemSize);
|
||||
|
||||
connect(this, &QWindow::xChanged, [=](){requestSyncToMainItemSize(true);});
|
||||
connect(this, &QWindow::yChanged, [=](){requestSyncToMainItemSize(true);});
|
||||
connect(this, &QWindow::xChanged, [=]() {
|
||||
requestSyncToMainItemSize(true);
|
||||
});
|
||||
connect(this, &QWindow::yChanged, [=]() {
|
||||
requestSyncToMainItemSize(true);
|
||||
});
|
||||
connect(this, &QWindow::visibleChanged, this, &DialogProxy::updateInputShape);
|
||||
connect(this, &DialogProxy::outputOnlyChanged, this, &DialogProxy::updateInputShape);
|
||||
// connect(this, &QWindow::visibleChanged, this, &DialogProxy::onVisibleChanged);
|
||||
@ -98,10 +104,14 @@ void DialogProxy::setMainItem(QQuickItem *mainItem)
|
||||
mainItem->setProperty("parent", QVariant::fromValue(contentItem()));
|
||||
|
||||
if (mainItem->metaObject()->indexOfSignal("widthChanged")) {
|
||||
connect(mainItem, &QQuickItem::widthChanged, [=](){m_syncTimer->start(0);});
|
||||
connect(mainItem, &QQuickItem::widthChanged, [=]() {
|
||||
m_syncTimer->start(0);
|
||||
});
|
||||
}
|
||||
if (mainItem->metaObject()->indexOfSignal("heightChanged")) {
|
||||
connect(mainItem, &QQuickItem::heightChanged, [=](){m_syncTimer->start(0);});
|
||||
connect(mainItem, &QQuickItem::heightChanged, [=]() {
|
||||
m_syncTimer->start(0);
|
||||
});
|
||||
}
|
||||
requestSyncToMainItemSize();
|
||||
}
|
||||
@ -166,7 +176,7 @@ void DialogProxy::updateVisibility(bool visible)
|
||||
case Plasma::Types::BottomEdge:
|
||||
slideLocation = KWindowEffects::BottomEdge;
|
||||
break;
|
||||
//no edge, no slide
|
||||
//no edge, no slide
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -192,7 +202,7 @@ void DialogProxy::updateVisibility(bool visible)
|
||||
|
||||
QPoint DialogProxy::popupPosition(QQuickItem *item, const QSize &size, Qt::AlignmentFlag alignment)
|
||||
{
|
||||
if (!item) {
|
||||
if (!item || !item->window()) {
|
||||
//If no item was specified try to align at the center of the parent view
|
||||
QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
|
||||
if (parentItem && parentItem->window()) {
|
||||
@ -209,7 +219,7 @@ QPoint DialogProxy::popupPosition(QQuickItem *item, const QSize &size, Qt::Align
|
||||
case Plasma::Types::BottomEdge:
|
||||
return QPoint(screen()->availableGeometry().center().x() - size.width()/2, screen()->availableGeometry().bottom() -size.height());
|
||||
break;
|
||||
//Default center in the screen
|
||||
//Default center in the screen
|
||||
default:
|
||||
return screen()->geometry().center() - QPoint(size.width()/2, size.height()/2);
|
||||
}
|
||||
@ -217,6 +227,7 @@ QPoint DialogProxy::popupPosition(QQuickItem *item, const QSize &size, Qt::Align
|
||||
return QPoint();
|
||||
}
|
||||
}
|
||||
|
||||
QPointF pos = item->mapToScene(QPointF(0, 0));
|
||||
|
||||
if (item->window() && item->window()->screen()) {
|
||||
@ -234,72 +245,83 @@ QPoint DialogProxy::popupPosition(QQuickItem *item, const QSize &size, Qt::Align
|
||||
}
|
||||
}
|
||||
|
||||
const QPoint topPoint((item->boundingRect().width() - size.width())/2,
|
||||
-size.height());
|
||||
const QPoint bottomPoint((item->boundingRect().width() - size.width())/2,
|
||||
item->boundingRect().height());
|
||||
const QPoint leftPoint(-size.width(),
|
||||
(item->boundingRect().height() - size.height())/2);
|
||||
//if the item is in a dock we want to position the popups outside of the dock
|
||||
const KWindowInfo winInfo = KWindowSystem::windowInfo(item->window()->winId(), NET::WMWindowType);
|
||||
const bool isDock = winInfo.windowType((int)NET::AllTypesMask) == NET::Dock;
|
||||
QRect parentGeometryBounds;
|
||||
|
||||
const QPoint rightPoint(item->boundingRect().width(),
|
||||
(item->boundingRect().height() - size.height())/2);
|
||||
if (isDock) {
|
||||
parentGeometryBounds = item->window()->geometry();
|
||||
} else {
|
||||
parentGeometryBounds = QRect(pos.toPoint(), QSize(item->width(), item->height()));
|
||||
}
|
||||
|
||||
QPoint offset(0, 0);
|
||||
const QPoint topPoint(pos.x() + (item->boundingRect().width() - size.width())/2,
|
||||
parentGeometryBounds.top() - size.height());
|
||||
const QPoint bottomPoint(pos.x() + (item->boundingRect().width() - size.width())/2,
|
||||
parentGeometryBounds.bottom());
|
||||
|
||||
const QPoint leftPoint(parentGeometryBounds.left() - size.width(),
|
||||
pos.y() + (item->boundingRect().height() - size.height())/2);
|
||||
|
||||
const QPoint rightPoint(parentGeometryBounds.right(),
|
||||
pos.y() + (item->boundingRect().height() - size.height())/2);
|
||||
|
||||
|
||||
QPoint dialogPos;
|
||||
if (m_location == Plasma::Types::BottomEdge) {
|
||||
offset = bottomPoint;
|
||||
dialogPos = bottomPoint;
|
||||
} else if (m_location == Plasma::Types::LeftEdge) {
|
||||
offset = leftPoint;
|
||||
dialogPos = leftPoint;
|
||||
} else if (m_location == Plasma::Types::RightEdge) {
|
||||
offset = rightPoint;
|
||||
dialogPos = rightPoint;
|
||||
} else { // Types::TopEdge
|
||||
offset = topPoint;
|
||||
dialogPos = topPoint;
|
||||
}
|
||||
|
||||
const QRect avail = item->window()->screen()->availableGeometry();
|
||||
QPoint menuPos = pos.toPoint() + offset;
|
||||
|
||||
const int leftMargin = m_frameSvgItem->margins()->left();
|
||||
const int rightMargin = m_frameSvgItem->margins()->right();
|
||||
const int topMargin = m_frameSvgItem->margins()->top();
|
||||
const int bottomMargin = m_frameSvgItem->margins()->bottom();
|
||||
|
||||
if (menuPos.x() < leftMargin) {
|
||||
if (dialogPos.x() < leftMargin) {
|
||||
// popup hits lhs
|
||||
if (m_location == Plasma::Types::TopEdge || m_location == Plasma::Types::BottomEdge) {
|
||||
// move it
|
||||
menuPos.setX(0-leftMargin);
|
||||
dialogPos.setX(0-leftMargin);
|
||||
} else {
|
||||
// swap edge
|
||||
menuPos.setX(pos.x() + rightPoint.x());
|
||||
dialogPos.setX(rightPoint.x());
|
||||
}
|
||||
}
|
||||
if (menuPos.x() + size.width() > avail.width() - rightMargin) {
|
||||
if (dialogPos.x() + size.width() > avail.width() - rightMargin) {
|
||||
// popup hits rhs
|
||||
if (m_location == Plasma::Types::TopEdge || m_location == Plasma::Types::BottomEdge) {
|
||||
menuPos.setX(avail.width() - size.width());
|
||||
dialogPos.setX(avail.width() - size.width());
|
||||
} else {
|
||||
menuPos.setX(pos.x() + leftPoint.x());
|
||||
dialogPos.setX(leftPoint.x());
|
||||
}
|
||||
}
|
||||
if (menuPos.y() < topMargin) {
|
||||
if (dialogPos.y() < topMargin) {
|
||||
// hitting top
|
||||
if (m_location == Plasma::Types::LeftEdge || m_location == Plasma::Types::RightEdge) {
|
||||
menuPos.setY(0);
|
||||
dialogPos.setY(0);
|
||||
} else {
|
||||
menuPos.setY(pos.y() + bottomPoint.y());
|
||||
dialogPos.setY(bottomPoint.y());
|
||||
}
|
||||
}
|
||||
if (menuPos.y() + size.height() > avail.height() - bottomMargin) {
|
||||
if (dialogPos.y() + size.height() > avail.height() - bottomMargin) {
|
||||
// hitting bottom
|
||||
if (m_location == Plasma::Types::TopEdge || m_location == Plasma::Types::BottomEdge) {
|
||||
menuPos.setY(pos.y() + topPoint.y());
|
||||
dialogPos.setY(topPoint.y());
|
||||
} else {
|
||||
menuPos.setY(avail.height() - item->boundingRect().height() + bottomMargin);
|
||||
dialogPos.setY(avail.height() - item->boundingRect().height() + bottomMargin);
|
||||
}
|
||||
}
|
||||
|
||||
//qDebug() << "Popup position" << menuPos << " Location: Plasma::" <<locString(l);
|
||||
return menuPos;
|
||||
return dialogPos;
|
||||
}
|
||||
|
||||
Plasma::Types::Location DialogProxy::location() const
|
||||
@ -314,6 +336,7 @@ void DialogProxy::setLocation(Plasma::Types::Location location)
|
||||
}
|
||||
m_location = location;
|
||||
emit locationChanged();
|
||||
requestSyncToMainItemSize();
|
||||
}
|
||||
|
||||
|
||||
@ -442,7 +465,7 @@ bool DialogProxy::event(QEvent *event)
|
||||
} else if (event->type() == QEvent::Hide) {
|
||||
updateVisibility(false);
|
||||
}
|
||||
|
||||
|
||||
return QQuickWindow::event(event);
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,6 @@ public:
|
||||
|
||||
void setOutputOnly(bool outputOnly);
|
||||
bool isOutputOnly() const;
|
||||
|
||||
void updateInputShape();
|
||||
|
||||
Q_SIGNALS:
|
||||
|
@ -0,0 +1,97 @@
|
||||
import QtQuick 2.0
|
||||
|
||||
import QtQuick.Controls 1.1 as Controls
|
||||
import QtQuick.Layouts 1.1
|
||||
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
|
||||
|
||||
/*This test is for checking PlasmaDialog visualParent and related function work
|
||||
*To test move the window towards various edges and press the button.
|
||||
The Red rectangle should always be on screen and on the right screen
|
||||
|
||||
*/
|
||||
|
||||
PlasmaCore.Dialog {
|
||||
|
||||
type: windowIsDockControl.checked ? PlasmaCore.Dialog.Dock : PlasmaCore.Dialog.Normal
|
||||
visible: true
|
||||
|
||||
Rectangle {
|
||||
color: "#ffffff"
|
||||
width: 300
|
||||
height: 300
|
||||
|
||||
Rectangle {
|
||||
id: innerRect
|
||||
color: "#ddffdd"
|
||||
width: 200
|
||||
height: 200
|
||||
anchors.centerIn: parent
|
||||
|
||||
ColumnLayout {
|
||||
anchors.margins: 5
|
||||
anchors.top: parent.top
|
||||
anchors.left:parent.left
|
||||
anchors.right:parent.right
|
||||
|
||||
Controls.Label {
|
||||
Layout.fillWidth: true
|
||||
text: "alt + left click and move the window to various edges to test popup position"
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
Controls.ComboBox {
|
||||
id: alignmentControl
|
||||
//order must match Location in plasma.h
|
||||
model: ["Left", "Right", "Top", "Bottom"]
|
||||
currentIndex: 0
|
||||
}
|
||||
|
||||
Controls.CheckBox {
|
||||
id: windowIsDockControl
|
||||
text: "Window is a dock"
|
||||
}
|
||||
|
||||
Controls.Button {
|
||||
text: "Show Popup"
|
||||
onClicked: {
|
||||
dialog.visible = !dialog.visible
|
||||
console.log(alignmentControl.currentIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PlasmaCore.Dialog
|
||||
{
|
||||
id: dialog
|
||||
visualParent: innerRect
|
||||
location: {
|
||||
switch (alignmentControl.currentIndex) {
|
||||
case 0:
|
||||
return PlasmaCore.Types.LeftEdge
|
||||
case 1:
|
||||
return PlasmaCore.Types.RightEdge
|
||||
case 2:
|
||||
return PlasmaCore.Types.TopEdge
|
||||
default:
|
||||
return PlasmaCore.Types.BottomEdge
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
color: "#FF0000"
|
||||
width: 150
|
||||
height: 150
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
console.log(alignmentControl.currentIndex);
|
||||
console.log(dialog.location);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user