Navigation Menu

Skip to content

Commit

Permalink
Merge pull request #42 from mikkoharju/platformsurfaceevent
Browse files Browse the repository at this point in the history
Cherry-pick QPlatformSurfaceEvent
  • Loading branch information
mikkoharju committed Jun 9, 2015
2 parents e2d669a + 8f1c7f4 commit 3f0086c
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/corelib/kernel/qcoreevent.cpp
Expand Up @@ -189,6 +189,7 @@ QT_BEGIN_NAMESPACE
\value ParentAboutToChange The widget parent is about to change.
\value ParentChange The widget parent has changed.
\value PlatformPanel A platform specific panel has been requested.
\value PlatformSurface A native platform surface has been created or is about to be destroyed.
\value Polish The widget is polished.
\value PolishRequest The widget should be polished.
\value QueryWhatsThis The widget should accept the event if it has "What's This?" help.
Expand Down
2 changes: 2 additions & 0 deletions src/corelib/kernel/qcoreevent.h
Expand Up @@ -278,6 +278,8 @@ class Q_CORE_EXPORT QEvent // event base class
StyleAnimationUpdate = 213, // style animation target should be updated
ApplicationStateChange = 214,

PlatformSurface = 217, // Platform surface created or about to be destroyed

// 512 reserved for Qt Jambi's MetaCall event
// 513 reserved for Qt Jambi's DeleteOnMainThread event

Expand Down
49 changes: 49 additions & 0 deletions src/gui/kernel/qevent.cpp
Expand Up @@ -1303,6 +1303,55 @@ QExposeEvent::~QExposeEvent()
{
}

/*!
\class QPlatformSurfaceEvent
\since 5.5
\brief The QPlatformSurfaceEvent class is used to notify about native platform surface events.
\inmodule QtGui
\ingroup events
Platform window events are synchronously sent to windows and offscreen surfaces when their
underlying native surfaces are created or are about to be destroyed.
Applications can respond to these events to know when the underlying platform
surface exists.
*/

/*!
\enum QPlatformSurfaceEvent::SurfaceEventType
This enum describes the type of platform surface event. The possible types are:
\value SurfaceCreated The underlying native surface has been created
\value SurfaceAboutToBeDestroyed The underlying native surface will be destroyed immediately after this event
The \c SurfaceAboutToBeDestroyed event type is useful as a means of stopping rendering to
a platform window before it is destroyed.
*/

/*!
\fn QPlatformSurfaceEvent::SurfaceEventType QPlatformSurfaceEvent::surfaceEventType() const
Returns the specific type of platform surface event.
*/

/*!
Constructs a platform surface event for the given \a surfaceEventType.
*/
QPlatformSurfaceEvent::QPlatformSurfaceEvent(SurfaceEventType surfaceEventType)
: QEvent(PlatformSurface)
, m_surfaceEventType(surfaceEventType)
{
}

/*!
\internal
*/
QPlatformSurfaceEvent::~QPlatformSurfaceEvent()
{
}

/*!
\fn const QRegion &QExposeEvent::region() const
Expand Down
17 changes: 17 additions & 0 deletions src/gui/kernel/qevent.h
Expand Up @@ -409,6 +409,23 @@ class Q_GUI_EXPORT QExposeEvent : public QEvent
QRegion rgn;
};

class Q_GUI_EXPORT QPlatformSurfaceEvent : public QEvent
{
public:
enum SurfaceEventType {
SurfaceCreated,
SurfaceAboutToBeDestroyed
};

explicit QPlatformSurfaceEvent(SurfaceEventType surfaceEventType);
~QPlatformSurfaceEvent();

inline SurfaceEventType surfaceEventType() const { return m_surfaceEventType; }

protected:
SurfaceEventType m_surfaceEventType;
};

class Q_GUI_EXPORT QResizeEvent : public QEvent
{
public:
Expand Down
7 changes: 7 additions & 0 deletions src/gui/kernel/qoffscreensurface.cpp
Expand Up @@ -168,6 +168,9 @@ void QOffscreenSurface::create()
d->offscreenWindow->setGeometry(0, 0, d->size.width(), d->size.height());
d->offscreenWindow->create();
}

QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceCreated);
QGuiApplication::sendEvent(this, &e);
}
}

Expand All @@ -179,6 +182,10 @@ void QOffscreenSurface::create()
void QOffscreenSurface::destroy()
{
Q_D(QOffscreenSurface);

QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed);
QGuiApplication::sendEvent(this, &e);

delete d->platformOffscreenSurface;
d->platformOffscreenSurface = 0;
if (d->offscreenWindow) {
Expand Down
9 changes: 9 additions & 0 deletions src/gui/kernel/qwindow.cpp
Expand Up @@ -487,6 +487,11 @@ void QWindow::create()
window->d_func()->platformWindow->setParent(d->platformWindow);
}
}

if (d->platformWindow) {
QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceCreated);
QGuiApplication::sendEvent(this, &e);
}
}
}

Expand Down Expand Up @@ -1500,6 +1505,10 @@ void QWindow::destroy()
}
}
setVisible(false);

QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed);
QGuiApplication::sendEvent(this, &e);

delete d->platformWindow;
d->resizeEventPending = true;
d->receivedExpose = false;
Expand Down
72 changes: 72 additions & 0 deletions tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
Expand Up @@ -62,6 +62,7 @@ private slots:
void resizeEventAfterResize();
void mapGlobal();
void positioning();
void platformSurface();
void isExposed();
void isActive();
void testInputEvents();
Expand Down Expand Up @@ -131,6 +132,14 @@ class Window : public QWindow
{
m_received[event->type()]++;
m_order << event->type();
switch (event->type()) {
case QEvent::PlatformSurface:
m_surfaceventType = static_cast<QPlatformSurfaceEvent *>(event)->surfaceEventType();
break;

default:
break;
}

return QWindow::event(event);
}
Expand All @@ -145,9 +154,15 @@ class Window : public QWindow
return m_order.indexOf(type);
}

QPlatformSurfaceEvent::SurfaceEventType surfaceEventType() const
{
return m_surfaceventType;
}

private:
QHash<QEvent::Type, int> m_received;
QVector<QEvent::Type> m_order;
QPlatformSurfaceEvent::SurfaceEventType m_surfaceventType;
};

void tst_QWindow::eventOrderOnShow()
Expand Down Expand Up @@ -258,6 +273,63 @@ void tst_QWindow::positioning()
}
}

class PlatformWindowFilter : public QObject
{
Q_OBJECT
public:
PlatformWindowFilter(QObject *parent = 0)
: QObject(parent)
, m_window(Q_NULLPTR)
, m_alwaysExisted(true)
{}

void setWindow(Window *window) { m_window = window; }

bool eventFilter(QObject *o, QEvent *e)
{
// Check that the platform surface events are delivered synchronously.
// If they are, the native platform surface should always exist when we
// receive a QPlatformSurfaceEvent
if (e->type() == QEvent::PlatformSurface && o == m_window) {
m_alwaysExisted &= (m_window->handle() != Q_NULLPTR);
}
return false;
}

bool surfaceExisted() const { return m_alwaysExisted; }

private:
Window *m_window;
bool m_alwaysExisted;
};

void tst_QWindow::platformSurface()
{
QRect geometry(80, 80, 40, 40);

Window window;
PlatformWindowFilter filter;
filter.setWindow(&window);
window.installEventFilter(&filter);

window.setGeometry(geometry);
QCOMPARE(window.geometry(), geometry);
window.create();

QTRY_VERIFY(window.received(QEvent::PlatformSurface) == 1);
QTRY_VERIFY(window.surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated);
QTRY_VERIFY(window.handle() != Q_NULLPTR);

window.destroy();
QTRY_VERIFY(window.received(QEvent::PlatformSurface) == 2);
QTRY_VERIFY(window.surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed);
QTRY_VERIFY(window.handle() == Q_NULLPTR);

// Check for synchronous delivery of platform surface events and that the platform
// surface always existed upon event delivery
QTRY_VERIFY(filter.surfaceExisted());
}

void tst_QWindow::isExposed()
{
QRect geometry(80, 80, 40, 40);
Expand Down

0 comments on commit 3f0086c

Please sign in to comment.