Added QWindow::isActive() and focus in / out events.
Renamed QGuiApplication::activeWindow() to QGuiApplication::focusWindow(), implemented QWindow::isActive() as a style hint, and added focus in / out events. Change-Id: I71866e76c5a817def3e17bcc20a4fc32081a0e7a Reviewed-on: http://codereview.qt-project.org/5811 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com>bb10
parent
253497b744
commit
11070a090a
|
|
@ -114,7 +114,7 @@ QClipboard *QGuiApplicationPrivate::qt_clipboard = 0;
|
|||
QList<QScreen *> QGuiApplicationPrivate::screen_list;
|
||||
|
||||
QWindowList QGuiApplicationPrivate::window_list;
|
||||
QWindow *QGuiApplicationPrivate::active_window = 0;
|
||||
QWindow *QGuiApplicationPrivate::focus_window = 0;
|
||||
|
||||
Q_GLOBAL_STATIC(QMutex, applicationFontMutex)
|
||||
QFont *QGuiApplicationPrivate::app_font = 0;
|
||||
|
|
@ -181,9 +181,9 @@ QGuiApplicationPrivate::QGuiApplicationPrivate(int &argc, char **argv, int flags
|
|||
self = this;
|
||||
}
|
||||
|
||||
QWindow *QGuiApplication::activeWindow()
|
||||
QWindow *QGuiApplication::focusWindow()
|
||||
{
|
||||
return QGuiApplicationPrivate::active_window;
|
||||
return QGuiApplicationPrivate::focus_window;
|
||||
}
|
||||
|
||||
QWindowList QGuiApplication::topLevelWindows()
|
||||
|
|
@ -678,8 +678,20 @@ void QGuiApplicationPrivate::processActivatedEvent(QWindowSystemInterfacePrivate
|
|||
if (!e->activated)
|
||||
return;
|
||||
|
||||
QWindow *previous = QGuiApplicationPrivate::active_window;
|
||||
QGuiApplicationPrivate::active_window = e->activated.data();
|
||||
QWindow *previous = QGuiApplicationPrivate::focus_window;
|
||||
QGuiApplicationPrivate::focus_window = e->activated.data();
|
||||
|
||||
if (previous == QGuiApplicationPrivate::focus_window)
|
||||
return;
|
||||
|
||||
if (previous) {
|
||||
QFocusEvent focusOut(QEvent::FocusOut);
|
||||
QCoreApplication::sendSpontaneousEvent(previous, &focusOut);
|
||||
}
|
||||
|
||||
QFocusEvent focusIn(QEvent::FocusIn);
|
||||
QCoreApplication::sendSpontaneousEvent(QGuiApplicationPrivate::focus_window, &focusIn);
|
||||
|
||||
if (self)
|
||||
self->notifyActiveWindowChange(previous);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,9 @@ public:
|
|||
static QWindowList topLevelWindows();
|
||||
static QWindow *topLevelAt(const QPoint &pos);
|
||||
|
||||
static QWindow *activeWindow();
|
||||
static QT_DEPRECATED QWindow *activeWindow() { return focusWindow(); }
|
||||
static QWindow *focusWindow();
|
||||
|
||||
static QScreen *primaryScreen();
|
||||
static QList<QScreen *> screens();
|
||||
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ public:
|
|||
static QPalette *app_pal;
|
||||
|
||||
static QWindowList window_list;
|
||||
static QWindow *active_window;
|
||||
static QWindow *focus_window;
|
||||
|
||||
#ifndef QT_NO_CURSOR
|
||||
QList<QCursor> cursor_list;
|
||||
|
|
|
|||
|
|
@ -95,8 +95,8 @@ QWindow::QWindow(QWindowPrivate &dd, QWindow *parent)
|
|||
|
||||
QWindow::~QWindow()
|
||||
{
|
||||
if (QGuiApplicationPrivate::active_window == this)
|
||||
QGuiApplicationPrivate::active_window = 0;
|
||||
if (QGuiApplicationPrivate::focus_window == this)
|
||||
QGuiApplicationPrivate::focus_window = 0;
|
||||
QGuiApplicationPrivate::window_list.removeAll(this);
|
||||
destroy();
|
||||
}
|
||||
|
|
@ -320,9 +320,32 @@ void QWindow::setOpacity(qreal level)
|
|||
void QWindow::requestActivateWindow()
|
||||
{
|
||||
Q_D(QWindow);
|
||||
QGuiApplicationPrivate::active_window = this;
|
||||
if (d->platformWindow) {
|
||||
if (d->platformWindow)
|
||||
d->platformWindow->requestActivateWindow();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if the window should appear active from a style perspective.
|
||||
|
||||
This is the case for the window that has input focus as well as windows
|
||||
that are in the same parent / transient parent chain as the focus window.
|
||||
|
||||
To get the window that currently has focus, use QGuiApplication::focusWindow().
|
||||
*/
|
||||
bool QWindow::isActive() const
|
||||
{
|
||||
Q_D(const QWindow);
|
||||
if (!d->platformWindow)
|
||||
return false;
|
||||
|
||||
QWindow *focus = QGuiApplication::focusWindow();
|
||||
if (focus == this)
|
||||
return true;
|
||||
|
||||
if (!parent() && !transientParent()) {
|
||||
return isAncestorOf(focus);
|
||||
} else {
|
||||
return (parent() && parent()->isActive()) || (transientParent() && transientParent()->isActive());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -335,7 +358,7 @@ Qt::WindowState QWindow::windowState() const
|
|||
void QWindow::setWindowState(Qt::WindowState state)
|
||||
{
|
||||
if (state == Qt::WindowActive) {
|
||||
requestActivateWindow();
|
||||
qWarning() << "QWindow::setWindowState does not accept Qt::WindowActive";
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -361,6 +384,29 @@ QWindow *QWindow::transientParent() const
|
|||
return d->transientParent.data();
|
||||
}
|
||||
|
||||
/*!
|
||||
\enum QWindow::AncestorMode
|
||||
|
||||
This enum is used to control whether or not transient parents
|
||||
should be considered ancestors.
|
||||
|
||||
\value ExcludeTransients Transient parents are not considered ancestors.
|
||||
\value IncludeTransients Transient parents are considered ancestors.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Returns true if the window is an ancestor of the given child. If mode is
|
||||
IncludeTransients transient parents are also considered ancestors.
|
||||
*/
|
||||
bool QWindow::isAncestorOf(const QWindow *child, AncestorMode mode) const
|
||||
{
|
||||
if (child->parent() == this || (mode == IncludeTransients && child->transientParent() == this))
|
||||
return true;
|
||||
|
||||
return (child->parent() && isAncestorOf(child->parent(), mode))
|
||||
|| (mode == IncludeTransients && child->transientParent() && isAncestorOf(child->transientParent(), mode));
|
||||
}
|
||||
|
||||
QSize QWindow::minimumSize() const
|
||||
{
|
||||
Q_D(const QWindow);
|
||||
|
|
@ -670,6 +716,14 @@ bool QWindow::event(QEvent *event)
|
|||
keyReleaseEvent(static_cast<QKeyEvent *>(event));
|
||||
break;
|
||||
|
||||
case QEvent::FocusIn:
|
||||
focusInEvent(static_cast<QFocusEvent *>(event));
|
||||
break;
|
||||
|
||||
case QEvent::FocusOut:
|
||||
focusOutEvent(static_cast<QFocusEvent *>(event));
|
||||
break;
|
||||
|
||||
#ifndef QT_NO_WHEELEVENT
|
||||
case QEvent::Wheel:
|
||||
wheelEvent(static_cast<QWheelEvent*>(event));
|
||||
|
|
@ -710,6 +764,14 @@ void QWindow::keyReleaseEvent(QKeyEvent *)
|
|||
{
|
||||
}
|
||||
|
||||
void QWindow::focusInEvent(QFocusEvent *)
|
||||
{
|
||||
}
|
||||
|
||||
void QWindow::focusOutEvent(QFocusEvent *)
|
||||
{
|
||||
}
|
||||
|
||||
void QWindow::inputMethodEvent(QInputMethodEvent *)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ QT_MODULE(Gui)
|
|||
class QWindowPrivate;
|
||||
|
||||
class QExposeEvent;
|
||||
class QFocusEvent;
|
||||
class QMoveEvent;
|
||||
class QResizeEvent;
|
||||
class QShowEvent;
|
||||
|
|
@ -123,12 +124,21 @@ public:
|
|||
void setOpacity(qreal level);
|
||||
void requestActivateWindow();
|
||||
|
||||
bool isActive() const;
|
||||
|
||||
Qt::WindowState windowState() const;
|
||||
void setWindowState(Qt::WindowState state);
|
||||
|
||||
void setTransientParent(QWindow *parent);
|
||||
QWindow *transientParent() const;
|
||||
|
||||
enum AncestorMode {
|
||||
ExcludeTransients,
|
||||
IncludeTransients
|
||||
};
|
||||
|
||||
bool isAncestorOf(const QWindow *child, AncestorMode mode = IncludeTransients) const;
|
||||
|
||||
QSize minimumSize() const;
|
||||
QSize maximumSize() const;
|
||||
QSize baseSize() const;
|
||||
|
|
@ -205,6 +215,8 @@ protected:
|
|||
virtual void exposeEvent(QExposeEvent *);
|
||||
virtual void resizeEvent(QResizeEvent *);
|
||||
virtual void moveEvent(QMoveEvent *);
|
||||
virtual void focusInEvent(QFocusEvent *);
|
||||
virtual void focusOutEvent(QFocusEvent *);
|
||||
|
||||
virtual void showEvent(QShowEvent *);
|
||||
virtual void hideEvent(QHideEvent *);
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ void QApplicationPrivate::notifyActiveWindowChange(QWindow *previous)
|
|||
{
|
||||
Q_UNUSED(previous);
|
||||
Q_Q(QApplication);
|
||||
QWindow *wnd = QGuiApplicationPrivate::active_window;
|
||||
QWindow *wnd = QGuiApplicationPrivate::focus_window;
|
||||
if (inPopupMode()) // some delayed focus event to ignore
|
||||
return;
|
||||
QWidget *tlw = qt_tlw_for_window(wnd);
|
||||
|
|
|
|||
|
|
@ -79,6 +79,12 @@ bool QWidgetWindow::event(QEvent *event)
|
|||
handleEnterLeaveEvent(event);
|
||||
return true;
|
||||
|
||||
// these should not be sent to QWidget, the corresponding events
|
||||
// are sent by QApplicationPrivate::notifyActiveWindowChange()
|
||||
case QEvent::FocusIn:
|
||||
case QEvent::FocusOut:
|
||||
return false;
|
||||
|
||||
case QEvent::KeyPress:
|
||||
case QEvent::KeyRelease:
|
||||
handleKeyEvent(static_cast<QKeyEvent *>(event));
|
||||
|
|
|
|||
|
|
@ -589,7 +589,7 @@ void tst_QFileDialog2::completionOnLevelAfterRoot()
|
|||
QCOMPARE(edit->text(), QString("completionOnLevelAfterRootTest"));
|
||||
current.rmdir("completionOnLevelAfterRootTest");
|
||||
#else
|
||||
QCOMPARE(edit->text(), QString("etc"));
|
||||
QTRY_COMPARE(edit->text(), QString("etc"));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ class tst_QWindow: public QObject
|
|||
private slots:
|
||||
void mapGlobal();
|
||||
void positioning();
|
||||
void isActive();
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -78,35 +79,30 @@ class Window : public QWindow
|
|||
{
|
||||
public:
|
||||
Window()
|
||||
: gotResizeEvent(false)
|
||||
, gotMapEvent(false)
|
||||
, gotMoveEvent(false)
|
||||
{
|
||||
reset();
|
||||
setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_received.clear();
|
||||
}
|
||||
|
||||
bool event(QEvent *event)
|
||||
{
|
||||
switch (event->type()) {
|
||||
case QEvent::Map:
|
||||
gotMapEvent = true;
|
||||
break;
|
||||
case QEvent::Resize:
|
||||
gotResizeEvent = true;
|
||||
break;
|
||||
case QEvent::Move:
|
||||
gotMoveEvent = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
m_received[event->type()]++;
|
||||
|
||||
return QWindow::event(event);
|
||||
}
|
||||
|
||||
bool gotResizeEvent;
|
||||
bool gotMapEvent;
|
||||
bool gotMoveEvent;
|
||||
int received(QEvent::Type type)
|
||||
{
|
||||
return m_received.value(type, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
QHash<QEvent::Type, int> m_received;
|
||||
};
|
||||
|
||||
void tst_QWindow::positioning()
|
||||
|
|
@ -118,7 +114,8 @@ void tst_QWindow::positioning()
|
|||
QCOMPARE(window.geometry(), geometry);
|
||||
window.show();
|
||||
|
||||
QTRY_VERIFY(window.gotResizeEvent && window.gotMapEvent);
|
||||
QTRY_COMPARE(window.received(QEvent::Resize), 1);
|
||||
QTRY_COMPARE(window.received(QEvent::Map), 1);
|
||||
|
||||
QMargins originalMargins = window.frameMargins();
|
||||
|
||||
|
|
@ -128,14 +125,11 @@ void tst_QWindow::positioning()
|
|||
QPoint originalPos = window.pos();
|
||||
QPoint originalFramePos = window.framePos();
|
||||
|
||||
window.gotResizeEvent = false;
|
||||
|
||||
window.setWindowState(Qt::WindowFullScreen);
|
||||
QTRY_VERIFY(window.gotResizeEvent);
|
||||
QTRY_COMPARE(window.received(QEvent::Resize), 2);
|
||||
|
||||
window.gotResizeEvent = false;
|
||||
window.setWindowState(Qt::WindowNoState);
|
||||
QTRY_VERIFY(window.gotResizeEvent);
|
||||
QTRY_COMPARE(window.received(QEvent::Resize), 3);
|
||||
|
||||
QTRY_COMPARE(originalPos, window.pos());
|
||||
QTRY_COMPARE(originalFramePos, window.framePos());
|
||||
|
|
@ -146,22 +140,88 @@ void tst_QWindow::positioning()
|
|||
if (originalPos == geometry.topLeft() && (originalMargins.top() != 0 || originalMargins.left() != 0)) {
|
||||
QPoint framePos(40, 40);
|
||||
|
||||
window.gotMoveEvent = false;
|
||||
window.reset();
|
||||
window.setFramePos(framePos);
|
||||
|
||||
QTRY_VERIFY(window.gotMoveEvent);
|
||||
QTRY_VERIFY(window.received(QEvent::Move));
|
||||
QTRY_COMPARE(framePos, window.framePos());
|
||||
QTRY_COMPARE(originalMargins, window.frameMargins());
|
||||
QCOMPARE(window.pos(), window.framePos() + QPoint(originalMargins.left(), originalMargins.top()));
|
||||
|
||||
// and back to regular positioning
|
||||
|
||||
window.gotMoveEvent = false;
|
||||
window.reset();
|
||||
window.setPos(originalPos);
|
||||
QTRY_VERIFY(window.gotMoveEvent);
|
||||
QTRY_VERIFY(window.received(QEvent::Move));
|
||||
QTRY_COMPARE(originalPos, window.pos());
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QWindow::isActive()
|
||||
{
|
||||
Window window;
|
||||
window.setGeometry(80, 80, 40, 40);
|
||||
window.show();
|
||||
|
||||
QTRY_COMPARE(window.received(QEvent::Map), 1);
|
||||
QTRY_COMPARE(window.received(QEvent::Resize), 1);
|
||||
QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
|
||||
QVERIFY(window.isActive());
|
||||
|
||||
Window child;
|
||||
child.setParent(&window);
|
||||
child.setGeometry(10, 10, 20, 20);
|
||||
child.show();
|
||||
|
||||
QTRY_COMPARE(child.received(QEvent::Map), 1);
|
||||
|
||||
child.requestActivateWindow();
|
||||
|
||||
QTRY_VERIFY(QGuiApplication::focusWindow() == &child);
|
||||
QVERIFY(child.isActive());
|
||||
|
||||
// parent shouldn't receive new map or resize events from child being shown
|
||||
QTRY_COMPARE(window.received(QEvent::Map), 1);
|
||||
QTRY_COMPARE(window.received(QEvent::Resize), 1);
|
||||
QTRY_COMPARE(window.received(QEvent::FocusIn), 1);
|
||||
QTRY_COMPARE(window.received(QEvent::FocusOut), 1);
|
||||
QTRY_COMPARE(child.received(QEvent::FocusIn), 1);
|
||||
|
||||
// child has focus
|
||||
QVERIFY(window.isActive());
|
||||
|
||||
Window dialog;
|
||||
dialog.setTransientParent(&window);
|
||||
dialog.setGeometry(110, 110, 30, 30);
|
||||
dialog.show();
|
||||
|
||||
dialog.requestActivateWindow();
|
||||
|
||||
QTRY_COMPARE(dialog.received(QEvent::Map), 1);
|
||||
QTRY_COMPARE(dialog.received(QEvent::Resize), 1);
|
||||
QTRY_VERIFY(QGuiApplication::focusWindow() == &dialog);
|
||||
QVERIFY(dialog.isActive());
|
||||
|
||||
// transient child has focus
|
||||
QVERIFY(window.isActive());
|
||||
|
||||
// parent is active
|
||||
QVERIFY(child.isActive());
|
||||
|
||||
window.requestActivateWindow();
|
||||
|
||||
QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
|
||||
QTRY_COMPARE(dialog.received(QEvent::FocusOut), 1);
|
||||
QTRY_COMPARE(window.received(QEvent::FocusIn), 2);
|
||||
|
||||
QVERIFY(window.isActive());
|
||||
|
||||
// transient parent has focus
|
||||
QVERIFY(dialog.isActive());
|
||||
|
||||
// parent has focus
|
||||
QVERIFY(child.isActive());
|
||||
}
|
||||
|
||||
#include <tst_qwindow.moc>
|
||||
QTEST_MAIN(tst_QWindow);
|
||||
|
|
|
|||
Loading…
Reference in New Issue