|
1 /* |
|
2 Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) |
|
3 |
|
4 This library is free software; you can redistribute it and/or |
|
5 modify it under the terms of the GNU Library General Public |
|
6 License as published by the Free Software Foundation; either |
|
7 version 2 of the License, or (at your option) any later version. |
|
8 |
|
9 This library is distributed in the hope that it will be useful, |
|
10 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 Library General Public License for more details. |
|
13 |
|
14 You should have received a copy of the GNU Library General Public License |
|
15 along with this library; see the file COPYING.LIB. If not, write to |
|
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
17 Boston, MA 02110-1301, USA. |
|
18 */ |
|
19 |
|
20 #include "config.h" |
|
21 #include "PluginContainerQt.h" |
|
22 |
|
23 #include "FocusController.h" |
|
24 #include "Frame.h" |
|
25 #include "FrameView.h" |
|
26 #include "Page.h" |
|
27 #include "PlatformKeyboardEvent.h" |
|
28 #include "PlatformWheelEvent.h" |
|
29 #include "PluginView.h" |
|
30 #include <QApplication> |
|
31 #include <QX11Info> |
|
32 |
|
33 using namespace WebCore; |
|
34 |
|
35 PluginClientWrapper::PluginClientWrapper(QWidget* parent, WId client) |
|
36 : QWidget(0, Qt::Popup) |
|
37 { |
|
38 // create a QWidget that adopts the plugin window id, do not give it |
|
39 // a parent so that we don't end up handling events supposed to be |
|
40 // handled by the QX11EmbedContainer. |
|
41 |
|
42 // without the parent this will be considered a toplevel widget, |
|
43 // and thus make Qt not quit the event loop after the last window |
|
44 // has been closed. In order to work around this, we set the window |
|
45 // type to Qt::Popup. |
|
46 |
|
47 create(client, false, true); |
|
48 m_parent = parent; |
|
49 } |
|
50 |
|
51 PluginClientWrapper::~PluginClientWrapper() |
|
52 { |
|
53 destroy(false, false); |
|
54 } |
|
55 |
|
56 bool PluginClientWrapper::x11Event(XEvent* event) |
|
57 { |
|
58 // modify the event window id and insert it into the Qt event system. |
|
59 event->xany.window = m_parent->parentWidget()->winId(); |
|
60 static_cast<QApplication*>(QApplication::instance())->x11ProcessEvent(event); |
|
61 return true; |
|
62 } |
|
63 |
|
64 PluginContainerQt::PluginContainerQt(PluginView* view, QWidget* parent) |
|
65 : QX11EmbedContainer(parent) |
|
66 , m_pluginView(view) |
|
67 , m_clientWrapper(0) |
|
68 { |
|
69 connect(this, SIGNAL(clientClosed()), this, SLOT(on_clientClosed())); |
|
70 connect(this, SIGNAL(clientIsEmbedded()), this, SLOT(on_clientIsEmbedded())); |
|
71 } |
|
72 |
|
73 PluginContainerQt::~PluginContainerQt() |
|
74 { |
|
75 delete m_clientWrapper; |
|
76 m_pluginView->setPlatformPluginWidget(0); |
|
77 } |
|
78 |
|
79 void PluginContainerQt::on_clientClosed() |
|
80 { |
|
81 delete m_clientWrapper; |
|
82 m_clientWrapper = 0; |
|
83 } |
|
84 |
|
85 void PluginContainerQt::on_clientIsEmbedded() |
|
86 { |
|
87 delete m_clientWrapper; |
|
88 m_clientWrapper = 0; |
|
89 |
|
90 // Only create a QWidget wrapper for the plugin in the case it isn't in the |
|
91 // Qt window mapper, and thus receiving events from the Qt event system. |
|
92 // This way the PluginClientWrapper receives the scroll events and passes |
|
93 // them to the parent. NOTICE: Native Qt based plugins running in process, |
|
94 // will already be in the window mapper, and thus creating a wrapper, stops |
|
95 // them from getting events from Qt, as they are redirected to the wrapper. |
|
96 if (!QWidget::find(clientWinId())) |
|
97 m_clientWrapper = new PluginClientWrapper(this, clientWinId()); |
|
98 } |
|
99 |
|
100 void PluginContainerQt::redirectWheelEventsToParent(bool enable) |
|
101 { |
|
102 // steal wheel events from the plugin as we want to handle it. When doing this |
|
103 // all button 4, 5, 6, and 7, ButtonPress and ButtonRelease events are passed |
|
104 // to the x11Event handler of the PluginClientWrapper, which then changes the |
|
105 // window id of the event to the parent of PluginContainer and puts the event |
|
106 // back into the Qt event loop, so that we will actually scroll the parent |
|
107 // frame. |
|
108 for (int buttonNo = 4; buttonNo < 8; buttonNo++) { |
|
109 if (enable) |
|
110 XGrabButton(x11Info().display(), buttonNo, AnyModifier, clientWinId(), |
|
111 false, ButtonPressMask, GrabModeAsync, GrabModeAsync, 0L, 0L); |
|
112 else |
|
113 XUngrabButton(x11Info().display(), buttonNo, AnyModifier, clientWinId()); |
|
114 } |
|
115 } |
|
116 |
|
117 bool PluginContainerQt::x11Event(XEvent* event) |
|
118 { |
|
119 switch (event->type) { |
|
120 case EnterNotify: |
|
121 // if the plugin window doesn't have focus we do not want to send wheel |
|
122 // events to it, but to the parent frame, so let's redirect here. |
|
123 redirectWheelEventsToParent(!hasFocus()); |
|
124 break; |
|
125 case LeaveNotify: |
|
126 // it is always safe to ungrab wheel events when the mouse leaves the |
|
127 // plugin window. |
|
128 redirectWheelEventsToParent(false); |
|
129 break; |
|
130 } |
|
131 |
|
132 return QX11EmbedContainer::x11Event(event); |
|
133 } |
|
134 |
|
135 void PluginContainerQt::focusInEvent(QFocusEvent* event) |
|
136 { |
|
137 // we got focus, stop redirecting the wheel events |
|
138 redirectWheelEventsToParent(false); |
|
139 |
|
140 if (Page* page = m_pluginView->parentFrame()->page()) |
|
141 page->focusController()->setActive(true); |
|
142 |
|
143 m_pluginView->focusPluginElement(); |
|
144 } |
|
145 |
|
146 void PluginContainerQt::focusOutEvent(QFocusEvent*) |
|
147 { |
|
148 if (Page* page = m_pluginView->parentFrame()->page()) |
|
149 page->focusController()->setActive(false); |
|
150 } |