Dialog: Avoid adjusting the geometry twice when with visualparent

We are in a strange cycle when we have a visual parent. In order to
obtain our position, we need to know our size. Our size depends on the
borders visible. The borders visible depend on the size.

When we do not have a visual parent this is not a problem as we do not
have a position where we are supposed to be.

In order to solve this cycle, when we have a visual parent, we typically
assume we have all borders, call popupPosition, move to that position
and then use that new position to figure out the borders, get the new
size (incase any borders have changed) and move again. This double
moving is not good. With that patch, we still do the same but we avoid
moving twice.
This commit is contained in:
Vishesh Handa 2014-08-28 18:25:03 +02:00
parent e0ea93cb7e
commit f293888be6
2 changed files with 23 additions and 22 deletions

View File

@ -73,10 +73,11 @@ public:
/** /**
* Sync Borders updates the enabled borders of the frameSvgItem depending * Sync Borders updates the enabled borders of the frameSvgItem depending
* on the geometry of the window. * on the geometry of the window.
* Make sure the window is in the correct position + size before calling *
* this function * \param windowGeometry The window geometry which should be taken into
* consideration when activating/deactivating certain borders
*/ */
void syncBorders(); void syncBorders(const QRect& windowGeometry);
/** /**
* This function sets the blurBehind, background contrast and shadows. It * This function sets the blurBehind, background contrast and shadows. It
@ -150,24 +151,24 @@ QRect DialogPrivate::availableScreenGeometryForPosition(const QPoint& pos) const
return avail; return avail;
} }
void DialogPrivate::syncBorders() void DialogPrivate::syncBorders(const QRect& geom)
{ {
QRect avail = availableScreenGeometryForPosition(q->position()); QRect avail = availableScreenGeometryForPosition(geom.topLeft());
int borders = Plasma::FrameSvg::AllBorders; int borders = Plasma::FrameSvg::AllBorders;
//Tooltips always have all the borders //Tooltips always have all the borders
// floating windows have all borders // floating windows have all borders
if ((q->flags() & Qt::ToolTip) != Qt::ToolTip && location != Plasma::Types::Floating) { if ((q->flags() & Qt::ToolTip) != Qt::ToolTip && location != Plasma::Types::Floating) {
if (q->x() <= avail.x() || location == Plasma::Types::LeftEdge) { if (geom.x() <= avail.x() || location == Plasma::Types::LeftEdge) {
borders = borders & ~Plasma::FrameSvg::LeftBorder; borders = borders & ~Plasma::FrameSvg::LeftBorder;
} }
if (q->y() <= avail.y() || location == Plasma::Types::TopEdge) { if (geom.y() <= avail.y() || location == Plasma::Types::TopEdge) {
borders = borders & ~Plasma::FrameSvg::TopBorder; borders = borders & ~Plasma::FrameSvg::TopBorder;
} }
if (avail.right() <= q->x() + q->width() || location == Plasma::Types::RightEdge) { if (avail.right() <= geom.x() + geom.width() || location == Plasma::Types::RightEdge) {
borders = borders & ~Plasma::FrameSvg::RightBorder; borders = borders & ~Plasma::FrameSvg::RightBorder;
} }
if (avail.bottom() <= q->y() + q->height() || location == Plasma::Types::BottomEdge) { if (avail.bottom() <= geom.y() + geom.height() || location == Plasma::Types::BottomEdge) {
borders = borders & ~Plasma::FrameSvg::BottomBorder; borders = borders & ~Plasma::FrameSvg::BottomBorder;
} }
} }
@ -288,7 +289,7 @@ void DialogPrivate::updateMinimumWidth()
mainItem->disconnect(q); mainItem->disconnect(q);
syncBorders(); syncBorders(q->geometry());
int minimumWidth = mainItemLayout->property("minimumWidth").toInt(); int minimumWidth = mainItemLayout->property("minimumWidth").toInt();
auto margin = frameSvgItem->margins(); auto margin = frameSvgItem->margins();
@ -326,7 +327,7 @@ void DialogPrivate::updateMinimumHeight()
mainItem->disconnect(q); mainItem->disconnect(q);
syncBorders(); syncBorders(q->geometry());
int minimumHeight = mainItemLayout->property("minimumHeight").toInt(); int minimumHeight = mainItemLayout->property("minimumHeight").toInt();
auto margin = frameSvgItem->margins(); auto margin = frameSvgItem->margins();
@ -364,7 +365,7 @@ void DialogPrivate::updateMaximumWidth()
mainItem->disconnect(q); mainItem->disconnect(q);
syncBorders(); syncBorders(q->geometry());
int maximumWidth = mainItemLayout->property("maximumWidth").toInt(); int maximumWidth = mainItemLayout->property("maximumWidth").toInt();
maximumWidth = maximumWidth ? maximumWidth : DIALOGSIZE_MAX; maximumWidth = maximumWidth ? maximumWidth : DIALOGSIZE_MAX;
@ -397,7 +398,7 @@ void DialogPrivate::updateMaximumHeight()
mainItem->disconnect(q); mainItem->disconnect(q);
syncBorders(); syncBorders(q->geometry());
int maximumHeight = mainItemLayout->property("maximumHeight").toInt(); int maximumHeight = mainItemLayout->property("maximumHeight").toInt();
maximumHeight = maximumHeight ? maximumHeight : DIALOGSIZE_MAX; maximumHeight = maximumHeight ? maximumHeight : DIALOGSIZE_MAX;
@ -555,12 +556,13 @@ void DialogPrivate::syncToMainItemSize()
const QRect geom(q->popupPosition(visualParent, fullSize), fullSize); const QRect geom(q->popupPosition(visualParent, fullSize), fullSize);
// We're then moving the window to where we think we would be with all // We're then moving the window to where we think we would be with all
// the borders. This way when syncBorders is caleld, it has a geometry // the borders. This way when syncBorders is called, it has a geometry
// to work with. // to work with.
q->adjustGeometry(geom); syncBorders(geom);
}
else {
syncBorders(q->geometry());
} }
syncBorders();
const QSize s = QSize(mainItem->width(), mainItem->height()) + const QSize s = QSize(mainItem->width(), mainItem->height()) +
QSize(frameSvgItem->margins()->left() + frameSvgItem->margins()->right(), QSize(frameSvgItem->margins()->left() + frameSvgItem->margins()->right(),
@ -578,6 +580,9 @@ void DialogPrivate::syncToMainItemSize()
return; return;
} }
q->adjustGeometry(geom); q->adjustGeometry(geom);
// The borders will instantly be updated but the geometry might take a
// while as sub-classes can reimplement adjustGeometry and animate it.
syncBorders(geom);
} else { } else {
q->resize(s); q->resize(s);
} }
@ -596,7 +601,7 @@ void DialogPrivate::slotWindowPositionChanged()
return; return;
} }
syncBorders(); syncBorders(q->geometry());
updateTheme(); updateTheme();
if (mainItem) { if (mainItem) {
@ -961,7 +966,6 @@ void Dialog::focusOutEvent(QFocusEvent *ev)
bool childHasFocus = focusWindow && ((focusWindow->isActive() && isAncestorOf(focusWindow)) || focusWindow->type() & Qt::Popup); bool childHasFocus = focusWindow && ((focusWindow->isActive() && isAncestorOf(focusWindow)) || focusWindow->type() & Qt::Popup);
if (qobject_cast<const View *>(focusWindow) || (!parentHasFocus && !childHasFocus)) { if (qobject_cast<const View *>(focusWindow) || (!parentHasFocus && !childHasFocus)) {
qDebug() << "DIALOG: hiding dialog.";
setVisible(false); setVisible(false);
emit windowDeactivated(); emit windowDeactivated();
} }

View File

@ -212,10 +212,7 @@ private:
friend class DialogPrivate; friend class DialogPrivate;
DialogPrivate *const d; DialogPrivate *const d;
Q_PRIVATE_SLOT(d, void syncBorders())
Q_PRIVATE_SLOT(d, void updateTheme())
Q_PRIVATE_SLOT(d, void updateVisibility(bool visible)) Q_PRIVATE_SLOT(d, void updateVisibility(bool visible))
Q_PRIVATE_SLOT(d, void updateInputShape())
Q_PRIVATE_SLOT(d, void updateMinimumWidth()) Q_PRIVATE_SLOT(d, void updateMinimumWidth())
Q_PRIVATE_SLOT(d, void updateMinimumHeight()) Q_PRIVATE_SLOT(d, void updateMinimumHeight())