summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/phonon/mmf/videooutput.cpp24
-rw-r--r--src/3rdparty/phonon/mmf/videooutput.h1
-rw-r--r--src/3rdparty/phonon/mmf/videoplayer.cpp77
-rw-r--r--src/3rdparty/phonon/mmf/videoplayer.h10
-rw-r--r--src/gui/kernel/qapplication_s60.cpp20
-rw-r--r--src/gui/kernel/qwidget_s60.cpp152
6 files changed, 246 insertions, 38 deletions
diff --git a/src/3rdparty/phonon/mmf/videooutput.cpp b/src/3rdparty/phonon/mmf/videooutput.cpp
index 53178cb..c517c22 100644
--- a/src/3rdparty/phonon/mmf/videooutput.cpp
+++ b/src/3rdparty/phonon/mmf/videooutput.cpp
@@ -21,6 +21,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#include "videooutputobserver.h"
#include <QPaintEvent>
+#include <QPainter>
#include <QMoveEvent>
#include <QResizeEvent>
@@ -165,16 +166,13 @@ void MMF::VideoOutput::paintEvent(QPaintEvent* event)
TRACE("regions %d", event->region().numRects());
TRACE("type %d", event->type());
- QWidget::paintEvent(event);
-}
-
-QPaintEngine* MMF::VideoOutput::paintEngine() const
-{
- TRACE_CONTEXT(VideoOutput::sizeHint, EVideoApi);
-
- QPaintEngine* const engine = QWidget::paintEngine();
-
- TRACE_RETURN("0x%08x", engine);
+/*
+ QPainter painter;
+ painter.begin(this);
+ painter.setBrush(QColor(0, 0, 0, 255)); // opaque black
+ painter.drawRects(event->region().rects());
+ painter.end();
+*/
}
void MMF::VideoOutput::resizeEvent(QResizeEvent* event)
@@ -186,9 +184,8 @@ void MMF::VideoOutput::resizeEvent(QResizeEvent* event)
QWidget::resizeEvent(event);
- if (m_observer) {
+ if (m_observer)
m_observer->videoOutputRegionChanged();
- }
}
void MMF::VideoOutput::moveEvent(QMoveEvent* event)
@@ -200,9 +197,8 @@ void MMF::VideoOutput::moveEvent(QMoveEvent* event)
QWidget::moveEvent(event);
- if (m_observer) {
+ if (m_observer)
m_observer->videoOutputRegionChanged();
- }
}
#endif // PHONON_MMF_VIDEOOUTPUT_IS_QWIDGET
diff --git a/src/3rdparty/phonon/mmf/videooutput.h b/src/3rdparty/phonon/mmf/videooutput.h
index 0da6ea0..bcd9cb4 100644
--- a/src/3rdparty/phonon/mmf/videooutput.h
+++ b/src/3rdparty/phonon/mmf/videooutput.h
@@ -48,7 +48,6 @@ protected:
void paintEvent(QPaintEvent* event);
void resizeEvent(QResizeEvent* event);
void moveEvent(QMoveEvent* event);
- QPaintEngine* paintEngine() const;
#endif // PHONON_MMF_VIDEOOUTPUT_IS_QWIDGET
#ifdef PHONON_MMF_DEBUG_VIDEO_OUTPUT
diff --git a/src/3rdparty/phonon/mmf/videoplayer.cpp b/src/3rdparty/phonon/mmf/videoplayer.cpp
index f008edd..736d74f 100644
--- a/src/3rdparty/phonon/mmf/videoplayer.cpp
+++ b/src/3rdparty/phonon/mmf/videoplayer.cpp
@@ -40,6 +40,7 @@ MMF::VideoPlayer::VideoPlayer()
, m_screenDevice(NULL)
, m_window(NULL)
, m_totalTime(0)
+ , m_mmfOutputChangePending(false)
{
construct();
}
@@ -50,6 +51,7 @@ MMF::VideoPlayer::VideoPlayer(const AbstractPlayer& player)
, m_screenDevice(NULL)
, m_window(NULL)
, m_totalTime(0)
+ , m_mmfOutputChangePending(false)
{
construct();
}
@@ -72,6 +74,13 @@ void MMF::VideoPlayer::construct()
// 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
+ // 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 = CVideoPlayerUtility::NewL
(
@@ -106,6 +115,14 @@ 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();
}
@@ -222,6 +239,12 @@ void MMF::VideoPlayer::MvpuoPrepareComplete(TInt aError)
videoOutput().setFrameSize(m_frameSize);
+ // See comment in updateMmfOutput
+ if(m_mmfOutputChangePending) {
+ TRACE_0("MMF output change pending - pushing now");
+ updateMmfOutput();
+ }
+
emit totalTimeChanged(totalTime());
changeState(StoppedState);
} else {
@@ -288,12 +311,37 @@ void MMF::VideoPlayer::MvpuoEvent(const TMMFEvent &aEvent)
void MMF::VideoPlayer::videoOutputRegionChanged()
{
TRACE_CONTEXT(VideoPlayer::videoOutputRegionChanged, EVideoInternal);
- TRACE_ENTRY_0();
+ TRACE_ENTRY("state %d", state());
-#ifdef PHONON_MMF_DEBUG_VIDEO_OUTPUT
- videoOutput().dump();
-#endif
+ getNativeWindowSystemHandles();
+
+ // See comment in updateMmfOutput
+ if(state() == LoadingState)
+ m_mmfOutputChangePending = true;
+ else
+ updateMmfOutput();
+
+ TRACE_EXIT_0();
+}
+void MMF::VideoPlayer::updateMmfOutput()
+{
+ TRACE_CONTEXT(VideoPlayer::updateMmfOutput, EVideoInternal);
+ TRACE_ENTRY_0();
+
+ // 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
+ // MvpuoPrepareComplete, at which point the MMF controller has been
+ // loaded.
+
+ // 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.
+
getNativeWindowSystemHandles();
TRAPD(err,
@@ -309,7 +357,9 @@ void MMF::VideoPlayer::videoOutputRegionChanged()
TRACE("SetDisplayWindowL error %d", err);
setError(NormalError);
}
-
+
+ m_mmfOutputChangePending = false;
+
TRACE_EXIT_0();
}
@@ -389,11 +439,22 @@ void MMF::VideoPlayer::getNativeWindowSystemHandles()
// HACK: why isn't control->Rect updated following a call to
// updateGeometry on the parent widget?
m_windowRect = TRect(0, 100, 320, 250);
+ m_clipRect = m_windowRect;
#else
- m_windowRect = control->Rect();
-#endif
-
+ m_windowRect = TRect(
+ control->DrawableWindow()->AbsPosition(),
+ control->DrawableWindow()->Size());
+
+ //m_clipRect = control->Rect();
m_clipRect = m_windowRect;
+#endif
+
+ 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);
}
diff --git a/src/3rdparty/phonon/mmf/videoplayer.h b/src/3rdparty/phonon/mmf/videoplayer.h
index da373ab..887a26b 100644
--- a/src/3rdparty/phonon/mmf/videoplayer.h
+++ b/src/3rdparty/phonon/mmf/videoplayer.h
@@ -85,9 +85,10 @@ private:
// AbstractPlayer
virtual void videoOutputChanged();
-
+
void getNativeWindowSystemHandles();
-
+ void updateMmfOutput();
+
private:
CVideoPlayerUtility* m_player;
QScopedPointer<VideoOutput> m_dummyVideoOutput;
@@ -98,11 +99,14 @@ private:
RWindowBase* m_window;
TRect m_windowRect;
TRect m_clipRect;
-
+
QSize m_frameSize;
qint64 m_totalTime;
+ bool m_mmfOutputChangePending;
+
};
+
}
}
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index 44ac380..67b974e 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -316,10 +316,24 @@ QSymbianControl::QSymbianControl(QWidget *w)
void QSymbianControl::ConstructL(bool topLevel, bool desktop)
{
if (!desktop)
- {
- if (topLevel)
+ {
+ if (topLevel or !qwidget->parentWidget())
CreateWindowL(S60->windowGroup());
-
+ else
+ /**
+ * TODO: in order to avoid creating windows for all ancestors of
+ * this widget up to the root window, the parameter passed to
+ * CreateWindowL should be
+ * qwidget->parentWidget()->effectiveWinId(). However, if we do
+ * this, then we need to take care of re-parenting when a window
+ * is created for a widget between this one and the root window.
+ */
+ CreateWindowL(qwidget->parentWidget()->winId());
+
+ // Necessary in order to be able to track the activation status of
+ // the control's window
+ qwidget->d_func()->createTLExtra();
+
SetFocusing(true);
m_longTapDetector = QLongTapTimer::NewL(this);
}
diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp
index f8a5be5..a516266 100644
--- a/src/gui/kernel/qwidget_s60.cpp
+++ b/src/gui/kernel/qwidget_s60.cpp
@@ -150,9 +150,143 @@ void QWidgetPrivate::setSoftKeys_sys(const QList<QAction*> &softkeys)
#endif
}
-void QWidgetPrivate::setWSGeometry(bool /* dontShow */, const QRect & /* rect */)
-{
+void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &)
+{
+ // Note: based on x11 implementation
+
+ static const int XCOORD_MAX = 16383;
+ static const int WRECT_MAX = 16383;
+
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+
+ /*
+ There are up to four different coordinate systems here:
+ Qt coordinate system for this widget.
+ X coordinate system for this widget (relative to wrect).
+ Qt coordinate system for parent
+ X coordinate system for parent (relative to parent's wrect).
+ */
+
+ QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX);
+ QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX);
+ QRect wrect;
+ //xrect is the X geometry of my widget. (starts out in parent's Qt coord sys, and ends up in parent's X coord sys)
+ QRect xrect = data.crect;
+
+ const QWidget *const parent = q->parentWidget();
+ QRect parentWRect = parent->data->wrect;
+
+ if (parentWRect.isValid()) {
+ // parent is clipped, and we have to clip to the same limit as parent
+ if (!parentWRect.contains(xrect)) {
+ xrect &= parentWRect;
+ wrect = xrect;
+ //translate from parent's to my Qt coord sys
+ wrect.translate(-data.crect.topLeft());
+ }
+ //translate from parent's Qt coords to parent's X coords
+ xrect.translate(-parentWRect.topLeft());
+
+ } else {
+ // parent is not clipped, we may or may not have to clip
+
+ if (data.wrect.isValid() && QRect(QPoint(),data.crect.size()).contains(data.wrect)) {
+ // This is where the main optimization is: we are already
+ // clipped, and if our clip is still valid, we can just
+ // move our window, and do not need to move or clip
+ // children
+
+ QRect vrect = xrect & parent->rect();
+ vrect.translate(-data.crect.topLeft()); //the part of me that's visible through parent, in my Qt coords
+ if (data.wrect.contains(vrect)) {
+ xrect = data.wrect;
+ xrect.translate(data.crect.topLeft());
+ if (data.winid) {
+ data.winid->SetExtent(TPoint(xrect.x(), xrect.y()), TSize(xrect.width(), xrect.height()));
+ data.winid->DrawNow();
+ }
+ return;
+ }
+ }
+
+ if (!validRange.contains(xrect)) {
+ // we are too big, and must clip
+ xrect &=wrectRange;
+ wrect = xrect;
+ wrect.translate(-data.crect.topLeft());
+ //parent's X coord system is equal to parent's Qt coord
+ //sys, so we don't need to map xrect.
+ }
+
+ }
+
+ // unmap if we are outside the valid window system coord system
+ bool outsideRange = !xrect.isValid();
+ bool mapWindow = false;
+ if (q->testAttribute(Qt::WA_OutsideWSRange) != outsideRange) {
+ q->setAttribute(Qt::WA_OutsideWSRange, outsideRange);
+ if (outsideRange) {
+ if (data.winid)
+ data.winid->DrawableWindow()->SetVisible(EFalse);
+ q->setAttribute(Qt::WA_Mapped, false);
+ } else if (!q->isHidden()) {
+ mapWindow = true;
+ }
+ }
+ if (outsideRange)
+ return;
+
+ bool jump = (data.wrect != wrect);
+ data.wrect = wrect;
+
+
+ // and now recursively for all children...
+ // ### can be optimized
+ for (int i = 0; i < children.size(); ++i) {
+ QObject *object = children.at(i);
+ if (object->isWidgetType()) {
+ QWidget *w = static_cast<QWidget *>(object);
+ if (!w->isWindow() && w->testAttribute(Qt::WA_WState_Created))
+ w->d_func()->setWSGeometry(jump);
+ }
+ }
+
+ if (data.winid) {
+ // move ourselves to the new position and map (if necessary) after
+ // the movement. Rationale: moving unmapped windows is much faster
+ // than moving mapped windows
+ if (!parent->internalWinId())
+ xrect.translate(parent->mapTo(q->nativeParentWidget(), QPoint(0, 0)));
+ data.winid->SetExtent(TPoint(xrect.x(), xrect.y()), TSize(xrect.width(), xrect.height()));
+ if(!jump)
+ data.winid->DrawNow();
+ }
+
+ //to avoid flicker, we have to show children after the helper widget has moved
+ if (jump) {
+ for (int i = 0; i < children.size(); ++i) {
+ QObject *object = children.at(i);
+ if (object->isWidgetType()) {
+ QWidget *w = static_cast<QWidget *>(object);
+ if (!w->testAttribute(Qt::WA_OutsideWSRange) && !w->testAttribute(Qt::WA_Mapped) && !w->isHidden()) {
+ w->setAttribute(Qt::WA_Mapped);
+ if (w->internalWinId())
+ w->data->winid->DrawableWindow()->SetVisible(ETrue);
+ }
+ }
+ }
+ }
+
+ if (jump && data.winid)
+ data.winid->DrawNow(TRect(0, 0, wrect.width(), wrect.height()));
+
+ if (mapWindow and !dontShow) {
+ q->setAttribute(Qt::WA_Mapped);
+ if (q->internalWinId())
+ q->internalWinId()->DrawableWindow()->SetVisible(ETrue);
+ }
}
void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
@@ -358,9 +492,6 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de
}
QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control, ECoeStackPriorityDefault, stackingFlags));
- WId parentw = parentWidget->effectiveWinId();
- QT_TRAP_THROWING(control->SetContainerWindowL(*parentw));
-
q->setAttribute(Qt::WA_WState_Created);
int x, y, w, h;
data.crect.getRect(&x, &y, &w, &h);
@@ -390,7 +521,7 @@ void QWidgetPrivate::show_sys()
return;
}
- if (q->isWindow() && q->internalWinId()) {
+ if (q->internalWinId()) {
WId id = q->internalWinId();
if (!extra->topextra->activated) {
@@ -398,12 +529,15 @@ void QWidgetPrivate::show_sys()
extra->topextra->activated = 1;
}
id->MakeVisible(true);
- id->SetFocus(true);
+
+ if(q->isWindow())
+ id->SetFocus(true);
// Force setting of the icon after window is made visible,
// this is needed even WA_SetWindowIcon is not set, as in that case we need
// to reset to the application level window icon
- setWindowIcon_sys(true);
+ if(q->isWindow())
+ setWindowIcon_sys(true);
}
invalidateBuffer(q->rect());
@@ -415,7 +549,7 @@ void QWidgetPrivate::hide_sys()
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
deactivateWidgetCleanup();
WId id = q->internalWinId();
- if (q->isWindow() && id) {
+ if (id) {
if(id->IsFocused()) // Avoid unnecessary calls to FocusChanged()
id->SetFocus(false);
id->MakeVisible(false);