From 4062a53c9a3e51c0c436bb1ce8d1c1befd6b1cf6 Mon Sep 17 00:00:00 2001 From: Marco Martin Date: Tue, 21 Oct 2014 15:55:00 +0200 Subject: [PATCH] always have margins in dialogs always show full margins in dialogs this is to make things look less cramped with screen and panel edges since mouse still has to work on screen edges (fitts law) in that case it forwards mouse events inside the actual content item so things like menus at the edge of the screen keep working Change-Id: I4b8a5a5bac92eadbaf7ad5b9b7dc0d5f364888c3 --- src/plasmaquick/dialog.cpp | 111 +++++++++++++++++++++++++++++++++---- 1 file changed, 99 insertions(+), 12 deletions(-) diff --git a/src/plasmaquick/dialog.cpp b/src/plasmaquick/dialog.cpp index 67042b30b..5e479aba3 100644 --- a/src/plasmaquick/dialog.cpp +++ b/src/plasmaquick/dialog.cpp @@ -117,6 +117,9 @@ public: void syncToMainItemSize(); + bool mainItemContainsPosition(const QPointF &point) const; + QPointF positionAdjustedForMainItem(const QPointF &point) const; + Dialog *q; Plasma::Types::Location location; Plasma::FrameSvgItem *frameSvgItem; @@ -310,7 +313,7 @@ void DialogPrivate::updateMinimumWidth() //the flicker almost always happen anyways, so is *probably* useless //this other kind of flicker is the view not being always focused exactly //on the scene - auto margin = frameSvgItem->margins(); + auto margin = frameSvgItem->fixedMargins(); int minimumWidth = mainItemLayout->property("minimumWidth").toInt() + margin->left() + margin->right(); q->contentItem()->setHeight(qMax(q->width(), minimumWidth)); q->setHeight(qMax(q->width(), minimumWidth)); @@ -333,7 +336,7 @@ void DialogPrivate::updateMinimumHeight() //the flicker almost always happen anyways, so is *probably* useless //this other kind of flicker is the view not being always focused exactly //on the scene - auto margin = frameSvgItem->margins(); + auto margin = frameSvgItem->fixedMargins(); int minimumHeight = mainItemLayout->property("minimumHeight").toInt() + margin->top() + margin->bottom(); q->contentItem()->setHeight(qMax(q->height(), minimumHeight)); q->setHeight(qMax(q->height(), minimumHeight)); @@ -352,7 +355,7 @@ void DialogPrivate::updateMaximumWidth() q->setMaximumWidth(DIALOGSIZE_MAX); - auto margin = frameSvgItem->margins(); + auto margin = frameSvgItem->fixedMargins(); int maximumWidth = mainItemLayout->property("maximumWidth").toInt() + margin->left() + margin->right(); q->contentItem()->setHeight(qMax(q->width(), maximumWidth)); q->setHeight(qMax(q->width(), maximumWidth)); @@ -371,7 +374,7 @@ void DialogPrivate::updateMaximumHeight() q->setMaximumHeight(DIALOGSIZE_MAX); - auto margin = frameSvgItem->margins(); + auto margin = frameSvgItem->fixedMargins(); int maximumHeight = mainItemLayout->property("maximumHeight").toInt() + margin->top() + margin->bottom(); q->contentItem()->setHeight(qMax(q->height(), maximumHeight)); q->setHeight(qMin(q->height(), maximumHeight)); @@ -389,7 +392,7 @@ void DialogPrivate::updateLayoutParameters() mainItem->disconnect(q); - auto margin = frameSvgItem->margins(); + auto margin = frameSvgItem->fixedMargins(); int minimumHeight = mainItemLayout->property("minimumHeight").toInt(); int maximumHeight = mainItemLayout->property("maximumHeight").toInt(); @@ -539,8 +542,8 @@ void DialogPrivate::syncToMainItemSize() } const QSize s = QSize(mainItem->width(), mainItem->height()) + - QSize(frameSvgItem->margins()->left() + frameSvgItem->margins()->right(), - frameSvgItem->margins()->top() + frameSvgItem->margins()->bottom()); + QSize(frameSvgItem->fixedMargins()->left() + frameSvgItem->fixedMargins()->right(), + frameSvgItem->fixedMargins()->top() + frameSvgItem->fixedMargins()->bottom()); q->contentItem()->setSize(s); @@ -561,8 +564,8 @@ void DialogPrivate::syncToMainItemSize() q->resize(s); } - mainItem->setPosition(QPointF(frameSvgItem->margins()->left(), - frameSvgItem->margins()->top())); + mainItem->setPosition(QPointF(frameSvgItem->fixedMargins()->left(), + frameSvgItem->fixedMargins()->top())); updateTheme(); } @@ -579,7 +582,7 @@ void DialogPrivate::slotWindowPositionChanged() updateTheme(); if (mainItem) { - auto margin = frameSvgItem->margins(); + auto margin = frameSvgItem->fixedMargins(); mainItem->setX(margin->left()); mainItem->setY(margin->top()); mainItem->setWidth(q->width() - margin->left() - margin->right()); @@ -587,6 +590,27 @@ void DialogPrivate::slotWindowPositionChanged() } } +bool DialogPrivate::mainItemContainsPosition(const QPointF &point) const +{ + if (!mainItem) { + return false; + } + + return QRectF(mainItem->mapToScene(QPoint(0,0)), QSizeF(mainItem->width(), mainItem->height())).contains(point); +} + +QPointF DialogPrivate::positionAdjustedForMainItem(const QPointF &point) const +{ + if (!mainItem) { + return point; + } + + QRectF itemRect(mainItem->mapToScene(QPoint(0,0)), QSizeF(mainItem->width(), mainItem->height())); + + return QPointF(qBound(itemRect.left(), point.x(), itemRect.right()), + qBound(itemRect.top(), point.y(), itemRect.bottom())); +} + Dialog::Dialog(QQuickItem *parent) : QQuickWindow(parent ? parent->window() : 0), d(new DialogPrivate(this)) @@ -867,7 +891,7 @@ void Dialog::setLocation(Plasma::Types::Location location) QObject *Dialog::margins() const { - return d->frameSvgItem->margins(); + return d->frameSvgItem->fixedMargins(); } void Dialog::setFramelessFlags(Qt::WindowFlags flags) @@ -894,7 +918,7 @@ void Dialog::resizeEvent(QResizeEvent* re) d->frameSvgItem->setSize(QSizeF(re->size().width(), re->size().height())); - auto margin = d->frameSvgItem->margins(); + auto margin = d->frameSvgItem->fixedMargins(); d->mainItem->setPosition(QPointF(margin->left(), margin->top())); d->mainItem->setSize(QSize(re->size().width() - margin->left() - margin->right(), @@ -992,6 +1016,69 @@ bool Dialog::event(QEvent *event) d->updateVisibility(false); } + /*Fitt's law: if the containment has margins, and the mouse cursor clicked + * on the mouse edge, forward the click in the containment boundaries + */ + switch (event->type()) { + case QEvent::MouseMove: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: { + QMouseEvent *me = static_cast(event); + + if (!d->mainItemContainsPosition(me->windowPos())) { + QMouseEvent me2(me->type(), + d->positionAdjustedForMainItem(me->windowPos()), + d->positionAdjustedForMainItem(me->windowPos()), + d->positionAdjustedForMainItem(me->windowPos()) + position(), + me->button(), me->buttons(), me->modifiers()); + + QCoreApplication::sendEvent(this, &me2); + return true; + } + break; + } + + case QEvent::DragEnter: { + QDragEnterEvent *de = static_cast(event); + if (!d->mainItemContainsPosition(de->pos())) { + QDragEnterEvent de2(d->positionAdjustedForMainItem(de->pos()).toPoint(), + de->possibleActions(), de->mimeData(), de->mouseButtons(), de->keyboardModifiers()); + + QCoreApplication::sendEvent(this, &de2); + return true; + } + break; + } + //DragLeave just works + case QEvent::DragLeave: + break; + case QEvent::DragMove: { + QDragMoveEvent *de = static_cast(event); + if (!d->mainItemContainsPosition(de->pos())) { + QDragMoveEvent de2(d->positionAdjustedForMainItem(de->pos()).toPoint(), + de->possibleActions(), de->mimeData(), de->mouseButtons(), de->keyboardModifiers()); + + QCoreApplication::sendEvent(this, &de2); + return true; + } + break; + } + case QEvent::Drop: { + QDropEvent *de = static_cast(event); + if (!d->mainItemContainsPosition(de->pos())) { + QDropEvent de2(d->positionAdjustedForMainItem(de->pos()).toPoint(), + de->possibleActions(), de->mimeData(), de->mouseButtons(), de->keyboardModifiers()); + + QCoreApplication::sendEvent(this, &de2); + return true; + } + break; + } + + default: + break; + } + const bool retval = QQuickWindow::event(event); if (event->type() != QEvent::DeferredDelete) { KWindowSystem::setState(winId(), NET::SkipTaskbar | NET::SkipPager);