summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/phonon/mmf/mmf_videoplayer.cpp179
-rw-r--r--src/3rdparty/phonon/mmf/mmf_videoplayer.h19
-rw-r--r--src/3rdparty/phonon/mmf/mmfphonondebug/objectdump_symbian.cpp100
-rw-r--r--src/3rdparty/phonon/mmf/mmfphonondebug/objectdump_symbian.h10
-rw-r--r--src/3rdparty/phonon/mmf/videooutput.cpp36
-rw-r--r--src/3rdparty/phonon/mmf/videooutput.h4
-rw-r--r--src/corelib/kernel/qcoreevent.cpp1
-rw-r--r--src/corelib/kernel/qcoreevent.h1
-rw-r--r--src/gui/kernel/qapplication_s60.cpp5
-rw-r--r--src/gui/kernel/qwidget.cpp23
-rw-r--r--src/gui/kernel/qwidget.h3
-rw-r--r--src/gui/kernel/qwidget_p.h3
-rw-r--r--src/gui/kernel/qwidget_s60.cpp78
13 files changed, 295 insertions, 167 deletions
diff --git a/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp b/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp
index c7fa791..6d7e0ed 100644
--- a/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp
+++ b/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp
@@ -45,8 +45,8 @@ using namespace Phonon::MMF;
//-----------------------------------------------------------------------------
MMF::VideoPlayer::VideoPlayer()
- : m_wsSession(0)
- , m_screenDevice(0)
+ : m_wsSession(CCoeEnv::Static()->WsSession())
+ , m_screenDevice(*CCoeEnv::Static()->ScreenDevice())
, m_window(0)
, m_totalTime(0)
, m_mmfOutputChangePending(false)
@@ -56,8 +56,8 @@ MMF::VideoPlayer::VideoPlayer()
MMF::VideoPlayer::VideoPlayer(const AbstractPlayer& player)
: AbstractMediaPlayer(player)
- , m_wsSession(0)
- , m_screenDevice(0)
+ , m_wsSession(CCoeEnv::Static()->WsSession())
+ , m_screenDevice(*CCoeEnv::Static()->ScreenDevice())
, m_window(0)
, m_totalTime(0)
, m_mmfOutputChangePending(false)
@@ -76,31 +76,31 @@ void MMF::VideoPlayer::construct()
const TInt priority = 0;
const TMdaPriorityPreference preference = EMdaPriorityPreferenceNone;
+ // Ignore return value - first call must always return true
getNativeWindowSystemHandles();
// TODO: is this the correct way to handle errors which occur when
// creating a Symbian object in the constructor of a Qt object?
-
- // TODO: check whether videoOutput is visible? If not, then the
- // corresponding window will not be active, meaning that the
+
+ // TODO: check whether videoOutput is visible? If not, then the
+ // corresponding window will not be active, meaning that the
// clipping region will be set to empty and the video will not be
// visible. If this is the case, we should set m_mmfOutputChangePending
// and respond to future showEvents from the videoOutput widget.
-
- TRAPD(err,
- m_player.reset(CVideoPlayerUtility::NewL
- (
- *this,
- priority, preference,
- *m_wsSession, *m_screenDevice,
- *m_window,
- m_windowRect, m_clipRect
- ))
- );
- if (KErrNone != err) {
+ TRAPD(err,
+ m_player.reset(CVideoPlayerUtility::NewL
+ (
+ *this,
+ priority, preference,
+ m_wsSession, m_screenDevice,
+ *m_window,
+ m_rect, m_rect
+ ))
+ );
+
+ if (KErrNone != err)
changeState(ErrorState);
- }
TRACE_EXIT_0();
}
@@ -120,13 +120,13 @@ MMF::VideoPlayer::~VideoPlayer()
void MMF::VideoPlayer::doPlay()
{
TRACE_CONTEXT(VideoPlayer::doPlay, EVideoApi);
-
+
// See comment in updateMmfOutput
if(m_mmfOutputChangePending) {
TRACE_0("MMF output change pending - pushing now");
updateMmfOutput();
}
-
+
m_player->Play();
}
@@ -149,7 +149,7 @@ void MMF::VideoPlayer::doStop()
void MMF::VideoPlayer::doSeek(qint64 ms)
{
TRACE_CONTEXT(VideoPlayer::doSeek, EVideoApi);
-
+
bool wasPlaying = false;
if(state() == PlayingState) {
// The call to SetPositionL does not have any effect if playback is
@@ -258,8 +258,8 @@ void MMF::VideoPlayer::MvpuoPrepareComplete(TInt aError)
if(m_mmfOutputChangePending) {
TRACE_0("MMF output change pending - pushing now");
updateMmfOutput();
- }
-
+ }
+
emit totalTimeChanged(totalTime());
changeState(StoppedState);
} else {
@@ -327,18 +327,26 @@ void MMF::VideoPlayer::videoOutputRegionChanged()
TRACE_CONTEXT(VideoPlayer::videoOutputRegionChanged, EVideoInternal);
TRACE_ENTRY("state %d", state());
- getNativeWindowSystemHandles();
+ const bool changed = getNativeWindowSystemHandles();
// See comment in updateMmfOutput
- if(state() == LoadingState)
- m_mmfOutputChangePending = true;
- else
- updateMmfOutput();
-
+ if(changed) {
+ if(state() == LoadingState)
+ m_mmfOutputChangePending = true;
+ else
+ updateMmfOutput();
+ }
+
TRACE_EXIT_0();
}
-// DEBUGGING *** DO NOT INTEGRATE ***
+
+#ifdef _DEBUG
+
+// The following code is for debugging problems related to video visibility. It allows
+// the VideoPlayer instance to query the window server in order to determine the
+// DSA drawing region for the video window.
+
class CDummyAO : public CActive
{
public:
@@ -349,7 +357,6 @@ public:
void SetActive() { CActive::SetActive(); }
};
-// DEBUGGING *** DO NOT INTEGRATE ***
void getDsaRegion(RWsSession &session, const RWindowBase &window)
{
RDirectScreenAccess dsa(session);
@@ -359,50 +366,52 @@ void getDsaRegion(RWsSession &session, const RWindowBase &window)
err = dsa.Request(region, ao.Status(), window);
ao.SetActive();
dsa.Close();
- ao.Cancel();
+ ao.Cancel();
if(region) {
qDebug() << "Phonon::MMF::getDsaRegion count" << region->Count();
for(int i=0; i<region->Count(); ++i) {
const TRect& rect = region->RectangleList()[i];
- qDebug() << "Phonon::MMF::getDsaRegion rect" << rect.iTl.iX << rect.iTl.iY << rect.iBr.iX << rect.iBr.iY;
+ qDebug() << "Phonon::MMF::getDsaRegion rect"
+ << rect.iTl.iX << rect.iTl.iY << rect.iBr.iX << rect.iBr.iY;
}
region->Close();
}
}
+#endif // _DEBUG
+
void MMF::VideoPlayer::updateMmfOutput()
{
TRACE_CONTEXT(VideoPlayer::updateMmfOutput, EVideoInternal);
TRACE_ENTRY_0();
-
- // Calling SetDisplayWindowL is a no-op unless the MMF controller has
+
+ // Calling SetDisplayWindowL is a no-op unless the MMF controller has
// been loaded, so we shouldn't do it. Instead, the
// m_mmfOutputChangePending flag is used to record the fact that we
- // need to call SetDisplayWindowL, and this is checked in
+ // need to call SetDisplayWindowL, and this is checked in
// MvpuoPrepareComplete, at which point the MMF controller has been
// loaded.
-
- getNativeWindowSystemHandles();
-
-// DEBUGGING *** DO NOT INTEGRATE ***
-getDsaRegion(*m_wsSession, *m_window);
+
+#ifdef _DEBUG
+ getDsaRegion(m_wsSession, *m_window);
+#endif
TRAPD(err,
- m_player->SetDisplayWindowL
- (
- *m_wsSession, *m_screenDevice,
- *m_window,
- m_windowRect, m_clipRect
- )
- );
+ m_player->SetDisplayWindowL
+ (
+ m_wsSession, m_screenDevice,
+ *m_window,
+ m_rect, m_rect
+ )
+ );
if (KErrNone != err) {
TRACE("SetDisplayWindowL error %d", err);
setError(NormalError);
}
-
+
m_mmfOutputChangePending = false;
-
+
TRACE_EXIT_0();
}
@@ -426,13 +435,13 @@ void MMF::VideoPlayer::videoOutputChanged()
TRACE_EXIT_0();
}
-void MMF::VideoPlayer::getNativeWindowSystemHandles()
+bool MMF::VideoPlayer::getNativeWindowSystemHandles()
{
TRACE_CONTEXT(VideoPlayer::getNativeWindowSystemHandles, EVideoInternal);
TRACE_ENTRY_0();
-
+
CCoeControl *control = 0;
-
+
if(m_videoOutput)
// Create native window
control = m_videoOutput->winId();
@@ -440,44 +449,42 @@ void MMF::VideoPlayer::getNativeWindowSystemHandles()
// Get top-level window
control = QApplication::activeWindow()->effectiveWinId();
- CCoeEnv* const coeEnv = control->ControlEnv();
- m_wsSession = &(coeEnv->WsSession());
- m_screenDevice = coeEnv->ScreenDevice();
- m_window = control->DrawableWindow();
-
#ifdef _DEBUG
if(m_videoOutput) {
- QScopedPointer<ObjectDump::QDumper> dumper(new ObjectDump::QDumper);
- dumper->setPrefix("Phonon::MMF"); // to aid searchability of logs
- ObjectDump::addDefaultAnnotators(*dumper);
- TRACE_0("Dumping VideoOutput:");
- dumper->dumpObject(*m_videoOutput);
+ QScopedPointer<ObjectDump::QDumper> dumper(new ObjectDump::QDumper);
+ dumper->setPrefix("Phonon::MMF"); // to aid searchability of logs
+ ObjectDump::addDefaultAnnotators(*dumper);
+ TRACE_0("Dumping VideoOutput:");
+ dumper->dumpObject(*m_videoOutput);
}
else {
- TRACE_0("m_videoOutput is null - dumping top-level control info:");
- TRACE("control %08x", control);
- TRACE("control.parent %08x", control->Parent());
- TRACE("control.isVisible %d", control->IsVisible());
- TRACE("control.rect %d,%d %dx%d",
- control->Position().iX, control->Position().iY,
- control->Size().iWidth, control->Size().iHeight);
- TRACE("control.ownsWindow %d", control->OwnsWindow());
+ TRACE_0("m_videoOutput is null - dumping top-level control info:");
+ TRACE("control %08x", control);
+ TRACE("control.parent %08x", control->Parent());
+ TRACE("control.isVisible %d", control->IsVisible());
+ TRACE("control.rect %d,%d %dx%d",
+ control->Position().iX, control->Position().iY,
+ control->Size().iWidth, control->Size().iHeight);
+ TRACE("control.ownsWindow %d", control->OwnsWindow());
}
#endif
- m_windowRect = TRect(
- control->DrawableWindow()->AbsPosition(),
- control->DrawableWindow()->Size());
- m_clipRect = m_windowRect;
-
- TRACE("windowRect %d %d - %d %d",
- m_windowRect.iTl.iX, m_windowRect.iTl.iY,
- m_windowRect.iBr.iX, m_windowRect.iBr.iY);
- TRACE("clipRect %d %d - %d %d",
- m_clipRect.iTl.iX, m_clipRect.iTl.iY,
- m_clipRect.iBr.iX, m_clipRect.iBr.iY);
-
- TRACE_EXIT_0();
+ RWindowBase *const window = control->DrawableWindow();
+ const TRect rect(window->AbsPosition(), window->Size());
+
+ TRACE("rect %d %d - %d %d",
+ rect.iTl.iX, rect.iTl.iY,
+ rect.iBr.iX, rect.iBr.iY);
+
+ bool changed = false;
+
+ if(window != m_window || rect != m_rect) {
+ m_window = window;
+ m_rect = rect;
+ changed = true;
+ }
+
+ TRACE_RETURN("changed %d", changed);
}
diff --git a/src/3rdparty/phonon/mmf/mmf_videoplayer.h b/src/3rdparty/phonon/mmf/mmf_videoplayer.h
index ee3650a..8072404 100644
--- a/src/3rdparty/phonon/mmf/mmf_videoplayer.h
+++ b/src/3rdparty/phonon/mmf/mmf_videoplayer.h
@@ -80,25 +80,26 @@ private:
// AbstractPlayer
virtual void videoOutputChanged();
-
- void getNativeWindowSystemHandles();
+
+ // Returns true if handles have changed
+ bool getNativeWindowSystemHandles();
+
void updateMmfOutput();
-
+
private:
QScopedPointer<CVideoPlayerUtility> m_player;
// Not owned
- RWsSession* m_wsSession;
- CWsScreenDevice* m_screenDevice;
+ RWsSession& m_wsSession;
+ CWsScreenDevice& m_screenDevice;
RWindowBase* m_window;
- TRect m_windowRect;
- TRect m_clipRect;
-
+ TRect m_rect;
+
QSize m_frameSize;
qint64 m_totalTime;
bool m_mmfOutputChangePending;
-
+
};
}
diff --git a/src/3rdparty/phonon/mmf/mmfphonondebug/objectdump_symbian.cpp b/src/3rdparty/phonon/mmf/mmfphonondebug/objectdump_symbian.cpp
index 5ae10f9..2fceb62 100644
--- a/src/3rdparty/phonon/mmf/mmfphonondebug/objectdump_symbian.cpp
+++ b/src/3rdparty/phonon/mmf/mmfphonondebug/objectdump_symbian.cpp
@@ -21,6 +21,8 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#include <coecntrl.h>
#include "objectdump_symbian.h"
+#include <QtGui/private/qwidget_p.h> // to access QWExtra
+
QT_BEGIN_NAMESPACE
namespace ObjectDump
@@ -28,92 +30,118 @@ namespace ObjectDump
namespace Symbian
{
+QList<QByteArray> QAnnotatorWidget::annotation(const QObject& object)
+{
+ QList<QByteArray> result;
+
+ const QWidget* widget = qobject_cast<const QWidget*>(&object);
+ if(widget) {
+
+ const QWExtra* extra = qt_widget_private(const_cast<QWidget *>(widget))->extraData();
+
+ if(extra) {
+
+ QByteArray array;
+ QTextStream stream(&array);
+
+ stream << "widget (Symbian): ";
+ stream << "activated " << extra->activated << ' ';
+ stream << "disableBlit " << extra->disableBlit << ' ';
+
+ stream.flush();
+ result.append(array);
+ }
+ }
+
+ return result;
+}
+
QList<QByteArray> QAnnotatorControl::annotation(const QObject& object)
{
QList<QByteArray> result;
-
+
const QWidget* widget = qobject_cast<const QWidget*>(&object);
if(widget) {
-
+
const CCoeControl* control = widget->effectiveWinId();
if(control) {
-
+
QByteArray array;
QTextStream stream(&array);
-
+
stream << "control: " << control << ' ';
stream << "parent " << control->Parent() << ' ';
-
+
if(control->IsVisible())
stream << "visible ";
else
stream << "invisible ";
-
+
stream << control->Position().iX << ',' << control->Position().iY << ' ';
stream << control->Size().iWidth << 'x' << control->Size().iHeight;
-
+
if(control->OwnsWindow())
stream << " ownsWindow ";
-
+
stream.flush();
result.append(array);
}
}
-
+
return result;
}
QList<QByteArray> QAnnotatorWindow::annotation(const QObject& object)
{
QList<QByteArray> result;
-
+
const QWidget* widget = qobject_cast<const QWidget*>(&object);
if(widget) {
-
+
const CCoeControl* control = widget->effectiveWinId();
- if(control) {
-
- RDrawableWindow& window = *(control->DrawableWindow());
-
+ RDrawableWindow *window = 0;
+
+ if(control && (window = control->DrawableWindow())) {
+
QByteArray array;
QTextStream stream(&array);
-
+
stream << "window: ";
-
+
// ClientHandle() is available first in 5.0.
#if !defined(__SERIES60_31__) && !defined(__S60_32__)
if (QSysInfo::s60Version() > QSysInfo::SV_S60_3_2)
// Client-side window handle
// Cast to a void pointer so that log output is in hexadecimal format.
- stream << "cli " << reinterpret_cast<const void*>(window.ClientHandle()) << ' ';
+ stream << "cli " << reinterpret_cast<const void*>(window->ClientHandle()) << ' ';
#endif
// Server-side address of CWsWindow object
// This is useful for correlation with the window tree dumped by the window
// server (see RWsSession::LogCommand).
// Cast to a void pointer so that log output is in hexadecimal format.
- stream << "srv " << reinterpret_cast<const void*>(window.WsHandle()) << ' ';
-
- stream << "group " << window.WindowGroupId() << ' ';
-
+ stream << "srv " << reinterpret_cast<const void*>(window->WsHandle()) << ' ';
+
+ stream << "group " << window->WindowGroupId() << ' ';
+
// Client-side handle to the parent window.
- // Cast to a void pointer so that log output is in hexadecimal format.
- stream << "parent " << reinterpret_cast<const void*>(window.Parent()) << ' ';
-
- stream << window.Position().iX << ',' << window.Position().iY << ' ';
- stream << '(' << window.AbsPosition().iX << ',' << window.AbsPosition().iY << ") ";
- stream << window.Size().iWidth << 'x' << window.Size().iHeight << ' ';
-
- const TDisplayMode displayMode = window.DisplayMode();
+ // Cast to a void pointer so that log output is in hexadecimal format.
+ stream << "parent " << reinterpret_cast<const void*>(window->Parent()) << ' ';
+
+ stream << window->Position().iX << ',' << window->Position().iY << ' ';
+ stream << '(' << window->AbsPosition().iX << ',' << window->AbsPosition().iY << ") ";
+ stream << window->Size().iWidth << 'x' << window->Size().iHeight << ' ';
+
+ const TDisplayMode displayMode = window->DisplayMode();
stream << "mode " << displayMode << ' ';
-
- stream << "ord " << window.OrdinalPosition();
-
+
+ stream << "ord " << window->OrdinalPosition();
+
stream.flush();
result.append(array);
- }
+ }
}
-
+
return result;
}
@@ -121,12 +149,14 @@ QList<QByteArray> QAnnotatorWindow::annotation(const QObject& object)
void addDefaultAnnotators_sys(QDumper& dumper)
{
+ dumper.addAnnotator(new Symbian::QAnnotatorWidget);
dumper.addAnnotator(new Symbian::QAnnotatorControl);
dumper.addAnnotator(new Symbian::QAnnotatorWindow);
}
void addDefaultAnnotators_sys(QVisitor& visitor)
{
+ visitor.addAnnotator(new Symbian::QAnnotatorWidget);
visitor.addAnnotator(new Symbian::QAnnotatorControl);
visitor.addAnnotator(new Symbian::QAnnotatorWindow);
}
diff --git a/src/3rdparty/phonon/mmf/mmfphonondebug/objectdump_symbian.h b/src/3rdparty/phonon/mmf/mmfphonondebug/objectdump_symbian.h
index 26ab308..563c862 100644
--- a/src/3rdparty/phonon/mmf/mmfphonondebug/objectdump_symbian.h
+++ b/src/3rdparty/phonon/mmf/mmfphonondebug/objectdump_symbian.h
@@ -29,6 +29,16 @@ namespace Symbian
{
/**
+ * Annotator which returns Symbian-specific widget information
+ */
+class QAnnotatorWidget : public QAnnotator
+{
+ Q_OBJECT
+public:
+ QList<QByteArray> annotation(const QObject& object);
+};
+
+/**
* Annotator which returns control information
*/
class QAnnotatorControl : public QAnnotator
diff --git a/src/3rdparty/phonon/mmf/videooutput.cpp b/src/3rdparty/phonon/mmf/videooutput.cpp
index 041b0a8..0541612 100644
--- a/src/3rdparty/phonon/mmf/videooutput.cpp
+++ b/src/3rdparty/phonon/mmf/videooutput.cpp
@@ -64,7 +64,7 @@ MMF::VideoOutput::VideoOutput(QWidget* parent)
qt_widget_private(this)->extraData()->disableBlit = true;
dump();
-
+
TRACE_EXIT_0();
}
@@ -123,9 +123,7 @@ void MMF::VideoOutput::paintEvent(QPaintEvent* event)
TRACE("regions %d", event->region().numRects());
TRACE("type %d", event->type());
- dump();
-
- // Do not paint anything
+ // Do nothing
}
void MMF::VideoOutput::resizeEvent(QResizeEvent* event)
@@ -135,10 +133,7 @@ void MMF::VideoOutput::resizeEvent(QResizeEvent* event)
event->oldSize().width(), event->oldSize().height(),
event->size().width(), event->size().height());
- QWidget::resizeEvent(event);
-
- if (m_observer)
- m_observer->videoOutputRegionChanged();
+ videoOutputRegionChanged();
}
void MMF::VideoOutput::moveEvent(QMoveEvent* event)
@@ -148,10 +143,20 @@ void MMF::VideoOutput::moveEvent(QMoveEvent* event)
event->oldPos().x(), event->oldPos().y(),
event->pos().x(), event->pos().y());
- QWidget::moveEvent(event);
+ videoOutputRegionChanged();
+}
- if (m_observer)
- m_observer->videoOutputRegionChanged();
+bool MMF::VideoOutput::event(QEvent* event)
+{
+ TRACE_CONTEXT(VideoOutput::event, EVideoInternal);
+
+ if(event->type() == QEvent::WinIdChange) {
+ TRACE_0("WinIdChange");
+ videoOutputRegionChanged();
+ return true;
+ }
+ else
+ return QWidget::event(event);
}
@@ -159,7 +164,14 @@ void MMF::VideoOutput::moveEvent(QMoveEvent* event)
// Private functions
//-----------------------------------------------------------------------------
-void VideoOutput::dump() const
+void MMF::VideoOutput::videoOutputRegionChanged()
+{
+ dump();
+ if (m_observer)
+ m_observer->videoOutputRegionChanged();
+}
+
+void MMF::VideoOutput::dump() const
{
#ifdef _DEBUG
TRACE_CONTEXT(VideoOutput::dump, EVideoInternal);
diff --git a/src/3rdparty/phonon/mmf/videooutput.h b/src/3rdparty/phonon/mmf/videooutput.h
index 639a5ed..7bc0b52 100644
--- a/src/3rdparty/phonon/mmf/videooutput.h
+++ b/src/3rdparty/phonon/mmf/videooutput.h
@@ -49,10 +49,12 @@ protected:
void paintEvent(QPaintEvent* event);
void resizeEvent(QResizeEvent* event);
void moveEvent(QMoveEvent* event);
+ bool event(QEvent* event);
private:
void dump() const;
-
+ void videoOutputRegionChanged();
+
private:
QSize m_frameSize;
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index 5883042..9098515 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -228,6 +228,7 @@ QT_BEGIN_NAMESPACE
\value TouchBegin Beginning of a sequence of touch-screen and/or track-pad events (QTouchEvent)
\value TouchUpdate Touch-screen event (QTouchEvent)
\value TouchEnd End of touch-event sequence (QTouchEvent)
+ \value WinIdChange The window system identifer for this native widget has changed
\value Gesture A gesture was triggered (QGestureEvent)
\value GestureOverride A gesture override was triggered (QGestureEvent)
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index ee1e1b9..6427d17 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -283,6 +283,7 @@ public:
UpdateSoftKeys = 201, // Internal for compressing soft key updates
+ WinIdChange = 203,
Gesture = 198,
GestureOverride = 202,
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index 6d50e55..c55d6e0 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -1123,6 +1123,11 @@ void qt_init(QApplicationPrivate * /* priv */, int)
;
}
*/
+
+ // Register WId with the metatype system. This is to enable
+ // QWidgetPrivate::create_sys to used delayed slot invokation in order
+ // to destroy WId objects during reparenting.
+ qRegisterMetaType<WId>("WId");
}
/*****************************************************************************
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 7dc3ae9..8da415f 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -1502,6 +1502,8 @@ void QWidgetPrivate::setWinId(WId id) // set widget identifier
mapper->remove(data.winid);
}
+ const WId oldWinId = data.winid;
+
data.winid = id;
#if defined(Q_WS_X11)
hd = id; // X11: hd == ident
@@ -1509,6 +1511,16 @@ void QWidgetPrivate::setWinId(WId id) // set widget identifier
if (mapper && id && !userDesktopWidget) {
mapper->insert(data.winid, q);
}
+
+ if(oldWinId != id) {
+ // Do not emit an event when the old winId is destroyed. This only
+ // happens (a) during widget destruction, and (b) immediately prior
+ // to creation of a new winId, for example as a result of re-parenting.
+ if(id != 0) {
+ QEvent e(QEvent::WinIdChange);
+ QCoreApplication::sendEvent(q, &e);
+ }
+ }
}
void QWidgetPrivate::createTLExtra()
@@ -2227,8 +2239,8 @@ QWidget *QWidget::find(WId id)
against. If Qt is using Carbon, the {WId} is actually an HIViewRef. If Qt
is using Cocoa, {WId} is a pointer to an NSView.
- \note We recommend that you do not store this value as it is likely to
- change at run-time.
+ This value may change at run-time. An event with type QEvent::WinIdChange
+ will be sent to the widget following a change in window system identifier.
\sa find()
*/
@@ -11998,3 +12010,10 @@ void QWidget::clearMask()
XRender extension is not supported on the X11 display, or if the
handle could not be created.
*/
+
+#ifdef Q_OS_SYMBIAN
+void QWidgetPrivate::_q_delayedDestroy(WId winId)
+{
+ delete winId;
+}
+#endif
diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h
index 3cc3093..e603a1a 100644
--- a/src/gui/kernel/qwidget.h
+++ b/src/gui/kernel/qwidget.h
@@ -773,6 +773,9 @@ private:
private:
Q_DISABLE_COPY(QWidget)
Q_PRIVATE_SLOT(d_func(), void _q_showIfNotHidden())
+#ifdef Q_OS_SYMBIAN
+ Q_PRIVATE_SLOT(d_func(), void _q_delayedDestroy(WId winId))
+#endif
QWidgetData *data;
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index a549740..f7c2712 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -296,7 +296,8 @@ public:
void setMask_sys(const QRegion &);
#ifdef Q_OS_SYMBIAN
void setSoftKeys_sys(const QList<QAction*> &softkeys);
- void activateSymbianWindow();
+ void activateSymbianWindow(WId wid = 0);
+ void _q_delayedDestroy(WId winId);
#endif
void raise_sys();
diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp
index b0d405a..8ce5001 100644
--- a/src/gui/kernel/qwidget_s60.cpp
+++ b/src/gui/kernel/qwidget_s60.cpp
@@ -56,6 +56,12 @@
#include <aknappui.h>
#endif
+// This is necessary in order to be able to perform delayed invokation on slots
+// which take arguments of type WId. One example is
+// QWidgetPrivate::_q_delayedDestroy, which is used to delay destruction of
+// CCoeControl objects until after the CONE event handler has finished running.
+Q_DECLARE_METATYPE(WId)
+
QT_BEGIN_NAMESPACE
extern bool qt_nograb();
@@ -318,8 +324,6 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de
bool desktop = (type == Qt::Desktop);
//bool tool = (type == Qt::Tool || type == Qt::Drawer);
- WId id = 0;
-
if (popup)
flags |= Qt::WindowStaysOnTopHint; // a popup stays on top
@@ -341,13 +345,10 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de
data.crect.setSize(QSize(width, height));
}
- CCoeControl *destroyw = 0;
+ CCoeControl *const destroyw = destroyOldWindow ? data.winid : 0;
createExtra();
if (window) {
- if (destroyOldWindow)
- destroyw = data.winid;
- id = window;
setWinId(window);
TRect tr = window->Rect();
data.crect.setRect(tr.iTl.iX, tr.iTl.iY, tr.Width(), tr.Height());
@@ -355,10 +356,15 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de
} else if (topLevel) {
if (!q->testAttribute(Qt::WA_Moved) && !q->testAttribute(Qt::WA_DontShowOnScreen))
data.crect.moveTopLeft(QPoint(clientRect.iTl.iX, clientRect.iTl.iY));
- QSymbianControl *control= q_check_ptr(new QSymbianControl(q));
- id = (WId)control;
- setWinId(id);
- QT_TRAP_THROWING(control->ConstructL(true,desktop));
+
+ QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) );
+ QT_TRAP_THROWING(control->ConstructL(true, desktop));
+
+ // Symbian windows are always created in an inactive state
+ // We perform this assignment for the case where the window is being re-created
+ // as aa result of a call to setParent_sys, on either this widget or one of its
+ // ancestors.
+ extra->activated = 0;
if (!desktop) {
TInt stackingFlags;
@@ -368,7 +374,7 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de
stackingFlags = ECoeStackFlagStandard;
}
control->MakeVisible(false);
- QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control, ECoeStackPriorityDefault, stackingFlags));
+ QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control.data(), ECoeStackPriorityDefault, stackingFlags));
// Avoid keyboard focus to a hidden window.
control->setFocusSafely(false);
@@ -391,11 +397,22 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de
int x, y, w, h;
data.crect.getRect(&x, &y, &w, &h);
control->SetRect(TRect(TPoint(x, y), TSize(w, h)));
+
+ // We wait until the control is fully constructed before calling setWinId, because
+ // this generates a WinIdChanged event.
+ setWinId(control.take());
+
} else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create native child widget
- QSymbianControl *control = new QSymbianControl(q);
- setWinId(control);
+
+ QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) );
QT_TRAP_THROWING(control->ConstructL(!parentWidget));
+ // Symbian windows are always created in an inactive state
+ // We perform this assignment for the case where the window is being re-created
+ // as aa result of a call to setParent_sys, on either this widget or one of its
+ // ancestors.
+ extra->activated = 0;
+
TInt stackingFlags;
if ((q->windowType() & Qt::Popup) == Qt::Popup) {
stackingFlags = ECoeStackFlagRefusesAllKeys | ECoeStackFlagRefusesFocus;
@@ -403,7 +420,7 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de
stackingFlags = ECoeStackFlagStandard;
}
control->MakeVisible(false);
- QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control, ECoeStackPriorityDefault, stackingFlags));
+ QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control.data(), ECoeStackPriorityDefault, stackingFlags));
// Avoid keyboard focus to a hidden window.
control->setFocusSafely(false);
@@ -418,12 +435,21 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de
| EPointerFilterMove | EPointerFilterDrag, 0);
if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
- activateSymbianWindow();
+ activateSymbianWindow(control.data());
+
+ // We wait until the control is fully constructed before calling setWinId, because
+ // this generates a WinIdChanged event.
+ setWinId(control.take());
}
if (destroyw) {
destroyw->ControlEnv()->AppUi()->RemoveFromStack(destroyw);
- CBase::Delete(destroyw);
+
+ // Delay deletion of the control in case this function is called in the
+ // context of a CONE event handler such as
+ // CCoeControl::ProcessPointerEventL
+ QMetaObject::invokeMethod(q, "_q_delayedDestroy",
+ Qt::QueuedConnection, Q_ARG(WId, destroyw));
}
if (q->testAttribute(Qt::WA_AcceptTouchEvents))
@@ -468,7 +494,7 @@ void QWidgetPrivate::show_sys()
invalidateBuffer(q->rect());
}
-void QWidgetPrivate::activateSymbianWindow()
+void QWidgetPrivate::activateSymbianWindow(WId wid)
{
Q_Q(QWidget);
@@ -476,8 +502,12 @@ void QWidgetPrivate::activateSymbianWindow()
Q_ASSERT(q->testAttribute(Qt::WA_Mapped));
Q_ASSERT(!extra->activated);
- WId id = q->internalWinId();
- QT_TRAP_THROWING(id->ActivateL());
+ if(!wid)
+ wid = q->internalWinId();
+
+ Q_ASSERT(wid);
+
+ QT_TRAP_THROWING(wid->ActivateL());
extra->activated = 1;
}
@@ -571,8 +601,14 @@ void QWidgetPrivate::reparentChildren()
w->d_func()->invalidateBuffer(w->rect());
WId parent = q->effectiveWinId();
WId child = w->effectiveWinId();
- if (parent != child)
- child->SetParent(parent);
+ if (parent != child) {
+ // Child widget is native. Because Symbian windows cannot be
+ // re-parented, we must re-create the window.
+ const WId window = 0;
+ const bool initializeWindow = false;
+ const bool destroyOldWindow = true;
+ w->d_func()->create_sys(window, initializeWindow, destroyOldWindow);
+ }
// ### TODO: We probably also need to update the component array here
w->d_func()->reparentChildren();
} else {