diff options
author | Prasanth Ullattil <prasanth.ullattil@nokia.com> | 2009-12-11 19:19:53 (GMT) |
---|---|---|
committer | Prasanth Ullattil <prasanth.ullattil@nokia.com> | 2009-12-18 14:07:15 (GMT) |
commit | d4005e273d4285d0b6a9c60f712cfd12c311c3a3 (patch) | |
tree | abf2c2e2e1b930608a725edb690a3163f7c3def0 /src/gui/widgets/qfocusframe.cpp | |
parent | 8cb83f37cc2e95002b44b48e851ec7672fb95df2 (diff) | |
download | Qt-d4005e273d4285d0b6a9c60f712cfd12c311c3a3.zip Qt-d4005e273d4285d0b6a9c60f712cfd12c311c3a3.tar.gz Qt-d4005e273d4285d0b6a9c60f712cfd12c311c3a3.tar.bz2 |
Focus frames in mac style gets clipped.
The focus frame on mac is a separate widget. The parent of the focus
frame is same as the parent of the widget who has the focus. So if
there is not enough room for a focus frame between the parent and
the widget, it gets clipped to the parent.
This parent is now changed to the nearest (in hierarchy) top level,
toolbar or scrollarea-viewport. A clip area is set on the focus
frame widget based on the visible region of the widget. This
reduces the chances of having clipped focus frames. It is always
better to leave enough margin for widgets which shows focus frames.
Task-number: 6567
Reviewed-by: Richard Moe Gustavsen
Reviewed-by: Jan-Arve
Diffstat (limited to 'src/gui/widgets/qfocusframe.cpp')
-rw-r--r-- | src/gui/widgets/qfocusframe.cpp | 91 |
1 files changed, 80 insertions, 11 deletions
diff --git a/src/gui/widgets/qfocusframe.cpp b/src/gui/widgets/qfocusframe.cpp index e96f50d..02f76f1 100644 --- a/src/gui/widgets/qfocusframe.cpp +++ b/src/gui/widgets/qfocusframe.cpp @@ -53,11 +53,14 @@ class QFocusFramePrivate : public QWidgetPrivate { Q_DECLARE_PUBLIC(QFocusFrame) QWidget *widget; - + QWidget *frameParent; + bool showFrameAboveWidget; public: QFocusFramePrivate() { widget = 0; + frameParent = 0; sendChildEvents = false; + showFrameAboveWidget = false; } void updateSize(); void update(); @@ -66,10 +69,10 @@ public: void QFocusFramePrivate::update() { Q_Q(QFocusFrame); - q->setParent(widget->parentWidget()); + q->setParent(frameParent); updateSize(); if (q->parentWidget()->rect().intersects(q->geometry())) { - if (q->style()->styleHint(QStyle::SH_FocusFrame_AboveWidget, 0, q)) + if (showFrameAboveWidget) q->raise(); else q->stackUnder(widget); @@ -84,7 +87,10 @@ void QFocusFramePrivate::updateSize() Q_Q(QFocusFrame); int vmargin = q->style()->pixelMetric(QStyle::PM_FocusFrameVMargin), hmargin = q->style()->pixelMetric(QStyle::PM_FocusFrameHMargin); - QRect geom(widget->x()-hmargin, widget->y()-vmargin, + QPoint pos(widget->x(), widget->y()); + if (q->parentWidget() != widget->parentWidget()) + pos = widget->parentWidget()->mapTo(q->parentWidget(), pos); + QRect geom(pos.x()-hmargin, pos.y()-vmargin, widget->width()+(hmargin*2), widget->height()+(vmargin*2)); if(q->geometry() == geom) return; @@ -176,14 +182,52 @@ void QFocusFrame::setWidget(QWidget *widget) { Q_D(QFocusFrame); - if(widget == d->widget) - return; - if(d->widget) - d->widget->removeEventFilter(this); - if(widget && !widget->isWindow() && widget->parentWidget()->windowType() != Qt::SubWindow) { + if (style()->styleHint(QStyle::SH_FocusFrame_AboveWidget, 0, this)) + d->showFrameAboveWidget = true; + else + d->showFrameAboveWidget = false; + + if (widget == d->widget) + return; + if (d->widget) { + // Remove event filters from the widget hierarchy. + QWidget *p = d->widget; + do { + p->removeEventFilter(this); + if (!d->showFrameAboveWidget || p == d->frameParent) + break; + p = p->parentWidget(); + }while (p); + } + if (widget && !widget->isWindow() && widget->parentWidget()->windowType() != Qt::SubWindow) { d->widget = widget; - widget->installEventFilter(this); + d->widget->installEventFilter(this); + QWidget *p = widget->parentWidget(); + QWidget *prev = 0; + if (d->showFrameAboveWidget) { + // Find the right parent for the focus frame. + while (p) { + // Traverse the hirerarchy of the 'widget' for setting event filter. + // During this if come across toolbar or a top level, use that + // as the parent for the focus frame. If we find a scroll area + // use its viewport as the parent. + bool isScrollArea = false; + if (p->isWindow() || p->inherits("QToolBar") || (isScrollArea = p->inherits("QAbstractScrollArea"))) { + d->frameParent = p; + // The previous one in the hierarchy will be the viewport. + if (prev && isScrollArea) + d->frameParent = prev; + break; + } else { + p->installEventFilter(this); + prev = p; + p = p->parentWidget(); + } + } + } else { + d->frameParent = p; + } d->update(); } else { d->widget = 0; @@ -210,9 +254,15 @@ QFocusFrame::widget() const void QFocusFrame::paintEvent(QPaintEvent *) { + Q_D(QFocusFrame); QStylePainter p(this); QStyleOption option; initStyleOption(&option); + int vmargin = style()->pixelMetric(QStyle::PM_FocusFrameVMargin); + int hmargin = style()->pixelMetric(QStyle::PM_FocusFrameHMargin); + QWidgetPrivate *wd = qt_widget_private(d->widget); + QRect rect = wd->clipRect().adjusted(0, 0, hmargin*2, vmargin*2); + p.setClipRect(rect); p.drawControl(QStyle::CE_FocusFrame, option); } @@ -233,7 +283,13 @@ QFocusFrame::eventFilter(QObject *o, QEvent *e) hide(); break; case QEvent::ParentChange: - d->update(); + if (d->showFrameAboveWidget) { + QWidget *w = d->widget; + setWidget(0); + setWidget(w); + } else { + d->update(); + } break; case QEvent::Show: d->update(); @@ -254,6 +310,19 @@ QFocusFrame::eventFilter(QObject *o, QEvent *e) default: break; } + } else if (d->showFrameAboveWidget) { + // Handle changes in the parent widgets we are monitoring. + switch(e->type()) { + case QEvent::Move: + case QEvent::Resize: + d->updateSize(); + break; + case QEvent::ZOrderChange: + raise(); + break; + default: + break; + } } return false; } |