diff -r 000000000000 -r 4f2f89ce4247 WebCore/plugins/qt/PluginContainerQt.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebCore/plugins/qt/PluginContainerQt.cpp Fri Sep 17 09:02:29 2010 +0300 @@ -0,0 +1,150 @@ +/* + 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 Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "PluginContainerQt.h" + +#include "FocusController.h" +#include "Frame.h" +#include "FrameView.h" +#include "Page.h" +#include "PlatformKeyboardEvent.h" +#include "PlatformWheelEvent.h" +#include "PluginView.h" +#include +#include + +using namespace WebCore; + +PluginClientWrapper::PluginClientWrapper(QWidget* parent, WId client) + : QWidget(0, Qt::Popup) +{ + // create a QWidget that adopts the plugin window id, do not give it + // a parent so that we don't end up handling events supposed to be + // handled by the QX11EmbedContainer. + + // without the parent this will be considered a toplevel widget, + // and thus make Qt not quit the event loop after the last window + // has been closed. In order to work around this, we set the window + // type to Qt::Popup. + + create(client, false, true); + m_parent = parent; +} + +PluginClientWrapper::~PluginClientWrapper() +{ + destroy(false, false); +} + +bool PluginClientWrapper::x11Event(XEvent* event) +{ + // modify the event window id and insert it into the Qt event system. + event->xany.window = m_parent->parentWidget()->winId(); + static_cast(QApplication::instance())->x11ProcessEvent(event); + return true; +} + +PluginContainerQt::PluginContainerQt(PluginView* view, QWidget* parent) + : QX11EmbedContainer(parent) + , m_pluginView(view) + , m_clientWrapper(0) +{ + connect(this, SIGNAL(clientClosed()), this, SLOT(on_clientClosed())); + connect(this, SIGNAL(clientIsEmbedded()), this, SLOT(on_clientIsEmbedded())); +} + +PluginContainerQt::~PluginContainerQt() +{ + delete m_clientWrapper; + m_pluginView->setPlatformPluginWidget(0); +} + +void PluginContainerQt::on_clientClosed() +{ + delete m_clientWrapper; + m_clientWrapper = 0; +} + +void PluginContainerQt::on_clientIsEmbedded() +{ + delete m_clientWrapper; + m_clientWrapper = 0; + + // Only create a QWidget wrapper for the plugin in the case it isn't in the + // Qt window mapper, and thus receiving events from the Qt event system. + // This way the PluginClientWrapper receives the scroll events and passes + // them to the parent. NOTICE: Native Qt based plugins running in process, + // will already be in the window mapper, and thus creating a wrapper, stops + // them from getting events from Qt, as they are redirected to the wrapper. + if (!QWidget::find(clientWinId())) + m_clientWrapper = new PluginClientWrapper(this, clientWinId()); +} + +void PluginContainerQt::redirectWheelEventsToParent(bool enable) +{ + // steal wheel events from the plugin as we want to handle it. When doing this + // all button 4, 5, 6, and 7, ButtonPress and ButtonRelease events are passed + // to the x11Event handler of the PluginClientWrapper, which then changes the + // window id of the event to the parent of PluginContainer and puts the event + // back into the Qt event loop, so that we will actually scroll the parent + // frame. + for (int buttonNo = 4; buttonNo < 8; buttonNo++) { + if (enable) + XGrabButton(x11Info().display(), buttonNo, AnyModifier, clientWinId(), + false, ButtonPressMask, GrabModeAsync, GrabModeAsync, 0L, 0L); + else + XUngrabButton(x11Info().display(), buttonNo, AnyModifier, clientWinId()); + } +} + +bool PluginContainerQt::x11Event(XEvent* event) +{ + switch (event->type) { + case EnterNotify: + // if the plugin window doesn't have focus we do not want to send wheel + // events to it, but to the parent frame, so let's redirect here. + redirectWheelEventsToParent(!hasFocus()); + break; + case LeaveNotify: + // it is always safe to ungrab wheel events when the mouse leaves the + // plugin window. + redirectWheelEventsToParent(false); + break; + } + + return QX11EmbedContainer::x11Event(event); +} + +void PluginContainerQt::focusInEvent(QFocusEvent* event) +{ + // we got focus, stop redirecting the wheel events + redirectWheelEventsToParent(false); + + if (Page* page = m_pluginView->parentFrame()->page()) + page->focusController()->setActive(true); + + m_pluginView->focusPluginElement(); +} + +void PluginContainerQt::focusOutEvent(QFocusEvent*) +{ + if (Page* page = m_pluginView->parentFrame()->page()) + page->focusController()->setActive(false); +}