/* This file is part of the KDE project. | |
Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). | |
This library is free software: you can redistribute it and/or modify | |
it under the terms of the GNU Lesser General Public License as published by | |
the Free Software Foundation, either version 2.1 or 3 of the License. | |
This library is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU Lesser General Public License for more details. | |
You should have received a copy of the GNU Lesser General Public License | |
along with this library. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
#include "ancestormovemonitor.h" | |
#include "utils.h" | |
#include "videooutput_dsa.h" | |
#include <QCoreApplication> | |
QT_BEGIN_NAMESPACE | |
using namespace Phonon::MMF; | |
/*! \class Phonon::MMF::AncestorMoveMonitor | |
\internal | |
\brief Class which installs a global event filter, and listens for move | |
events which may affect the absolute position of widgets registered with | |
the monitor | |
See QTBUG-4956 | |
*/ | |
/*! \class Phonon::MMF::VideoOutputObserver | |
\internal | |
*/ | |
//----------------------------------------------------------------------------- | |
// Constructor / destructor | |
//----------------------------------------------------------------------------- | |
AncestorMoveMonitor::AncestorMoveMonitor(QObject *parent) | |
: QObject(parent) | |
{ | |
QCoreApplication::instance()->installEventFilter(this); | |
} | |
AncestorMoveMonitor::~AncestorMoveMonitor() | |
{ | |
QCoreApplication::instance()->removeEventFilter(this); | |
} | |
//----------------------------------------------------------------------------- | |
// Public functions | |
//----------------------------------------------------------------------------- | |
void AncestorMoveMonitor::registerTarget(DsaVideoOutput *target) | |
{ | |
TRACE_CONTEXT(AncestorMoveMonitor::registerTarget, EVideoInternal); | |
TRACE_ENTRY("target 0x%08x", target); | |
// First un-register the target, in case this is being called as a result | |
// of re-parenting. This is not the most efficient way to update the | |
// target hash, but since this is not likely to be a frequent operation, | |
// simplicity is preferred over outright speed. In any case, re-parenting | |
// of the video widget leads to re-creation of native windows, which is | |
// likely to take far more processing than any implementation of this | |
// function. | |
unRegisterTarget(target); | |
QWidget *ancestor = target->parentWidget(); | |
while(ancestor) { | |
const Hash::iterator it = m_hash.find(ancestor); | |
if(m_hash.end() == it) { | |
TargetList targetList; | |
targetList.append(target); | |
m_hash.insert(ancestor, targetList); | |
} else { | |
TargetList& targetList = it.value(); | |
Q_ASSERT(targetList.indexOf(target) == -1); | |
targetList.append(target); | |
} | |
ancestor = ancestor->parentWidget(); | |
} | |
dump(); | |
TRACE_EXIT_0(); | |
} | |
void AncestorMoveMonitor::unRegisterTarget(DsaVideoOutput *target) | |
{ | |
TRACE_CONTEXT(AncestorMoveMonitor::unRegisterTarget, EVideoInternal); | |
TRACE_ENTRY("target 0x%08x", target); | |
Hash::iterator it = m_hash.begin(); | |
while(it != m_hash.end()) { | |
TargetList& targetList = it.value(); | |
const int index = targetList.indexOf(target); | |
if(index != -1) | |
targetList.removeAt(index); | |
if(targetList.count()) | |
++it; | |
else | |
it = m_hash.erase(it); | |
} | |
dump(); | |
TRACE_EXIT_0(); | |
} | |
bool AncestorMoveMonitor::eventFilter(QObject *watched, QEvent *event) | |
{ | |
TRACE_CONTEXT(AncestorMoveMonitor::eventFilter, EVideoInternal); | |
if(event->type() == QEvent::Move || event->type() == QEvent::ParentChange) { | |
//TRACE_ENTRY("watched 0x%08x event.type %d", watched, event->type()); | |
const Hash::const_iterator it = m_hash.find(watched); | |
if(it != m_hash.end()) { | |
const TargetList& targetList = it.value(); | |
DsaVideoOutput* target = 0; | |
foreach(target, targetList) { | |
switch (event->type()) { | |
case QEvent::Move: | |
// Notify the target that its ancestor has moved | |
target->ancestorMoved(); | |
break; | |
case QEvent::ParentChange: | |
// Update ancestor list for the target | |
registerTarget(target); | |
break; | |
default: | |
Q_ASSERT(false); | |
} | |
} | |
} | |
//TRACE_EXIT_0(); | |
} | |
// The event is never consumed by this filter | |
return false; | |
} | |
//----------------------------------------------------------------------------- | |
// Private functions | |
//----------------------------------------------------------------------------- | |
void AncestorMoveMonitor::dump() | |
{ | |
#ifndef QT_NO_DEBUG | |
TRACE_CONTEXT(AncestorMoveMonitor::dump, EVideoInternal); | |
for(Hash::const_iterator it = m_hash.begin(); | |
it != m_hash.end(); ++it) { | |
const QObject *ancestor = it.key(); | |
TRACE("ancestor 0x%08x", ancestor); | |
const TargetList& targetList = it.value(); | |
DsaVideoOutput* target = 0; | |
foreach(target, targetList) { | |
TRACE(" target 0x%08x", target); | |
} | |
} | |
#endif | |
} | |
QT_END_NAMESPACE | |