|
1 /* |
|
2 Copyright (C) 2007 Trolltech ASA |
|
3 Copyright (C) 2007 Staikos Computing Services Inc. |
|
4 |
|
5 This library is free software; you can redistribute it and/or |
|
6 modify it under the terms of the GNU Library General Public |
|
7 License as published by the Free Software Foundation; either |
|
8 version 2 of the License, or (at your option) any later version. |
|
9 |
|
10 This library is distributed in the hope that it will be useful, |
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 Library General Public License for more details. |
|
14 |
|
15 You should have received a copy of the GNU Library General Public License |
|
16 along with this library; see the file COPYING.LIB. If not, write to |
|
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
18 Boston, MA 02110-1301, USA. |
|
19 |
|
20 This class provides all functionality needed for loading images, style sheets and html |
|
21 pages from the web. It has a memory cache for these objects. |
|
22 */ |
|
23 #include "qwebframe.h" |
|
24 #include "qwebpage.h" |
|
25 #include "qwebpage_p.h" |
|
26 #include "qwebframe_p.h" |
|
27 |
|
28 #include "FocusController.h" |
|
29 #include "FrameLoaderClientQt.h" |
|
30 #include "Frame.h" |
|
31 #include "FrameTree.h" |
|
32 #include "FrameView.h" |
|
33 #include "Page.h" |
|
34 #include "ResourceRequest.h" |
|
35 #include "SelectionController.h" |
|
36 #include "PlatformScrollBar.h" |
|
37 |
|
38 #include "markup.h" |
|
39 #include "RenderTreeAsText.h" |
|
40 #include "Element.h" |
|
41 #include "Document.h" |
|
42 #include "DragData.h" |
|
43 #include "RenderObject.h" |
|
44 #include "GraphicsContext.h" |
|
45 #include "PlatformScrollBar.h" |
|
46 #include "PlatformMouseEvent.h" |
|
47 #include "PlatformWheelEvent.h" |
|
48 #include "GraphicsContext.h" |
|
49 #include "HitTestResult.h" |
|
50 |
|
51 #include "bindings/runtime.h" |
|
52 #include "bindings/runtime_root.h" |
|
53 #include "kjs_proxy.h" |
|
54 #include "kjs_window.h" |
|
55 #include "kjs_binding.h" |
|
56 #include "ExecState.h" |
|
57 #include "object.h" |
|
58 |
|
59 #include "wtf/HashMap.h" |
|
60 |
|
61 #include <qdebug.h> |
|
62 #include <qevent.h> |
|
63 #include <qpainter.h> |
|
64 |
|
65 using namespace WebCore; |
|
66 |
|
67 void QWebFramePrivate::init(QWebFrame *qframe, WebCore::Page *page, QWebFrameData *frameData) |
|
68 { |
|
69 q = qframe; |
|
70 |
|
71 frameLoaderClient = new FrameLoaderClientQt(); |
|
72 frame = new Frame(page, frameData->ownerElement, frameLoaderClient); |
|
73 frameLoaderClient->setFrame(qframe, frame.get()); |
|
74 |
|
75 frameView = new FrameView(frame.get()); |
|
76 frameView->deref(); |
|
77 frameView->setQWebFrame(qframe); |
|
78 if (!frameData->allowsScrolling) |
|
79 frameView->setScrollbarsMode(ScrollbarAlwaysOff); |
|
80 if (frameData->marginWidth != -1) |
|
81 frameView->setMarginWidth(frameData->marginWidth); |
|
82 if (frameData->marginHeight != -1) |
|
83 frameView->setMarginHeight(frameData->marginHeight); |
|
84 |
|
85 frame->setView(frameView.get()); |
|
86 frame->init(); |
|
87 eventHandler = frame->eventHandler(); |
|
88 } |
|
89 |
|
90 QWebFrame *QWebFramePrivate::parentFrame() |
|
91 { |
|
92 return qobject_cast<QWebFrame*>(q->parent()); |
|
93 } |
|
94 |
|
95 WebCore::PlatformScrollbar *QWebFramePrivate::horizontalScrollBar() const |
|
96 { |
|
97 Q_ASSERT(frameView); |
|
98 return frameView->horizontalScrollBar(); |
|
99 } |
|
100 |
|
101 WebCore::PlatformScrollbar *QWebFramePrivate::verticalScrollBar() const |
|
102 { |
|
103 Q_ASSERT(frameView); |
|
104 return frameView->verticalScrollBar(); |
|
105 } |
|
106 |
|
107 QWebFrame::QWebFrame(QWebPage *parent, QWebFrameData *frameData) |
|
108 : QObject(parent) |
|
109 , d(new QWebFramePrivate) |
|
110 { |
|
111 d->page = parent; |
|
112 d->init(this, parent->d->page, frameData); |
|
113 |
|
114 if (!frameData->url.isEmpty()) { |
|
115 ResourceRequest request(frameData->url, frameData->referrer); |
|
116 d->frame->loader()->load(request, frameData->name); |
|
117 } |
|
118 } |
|
119 |
|
120 QWebFrame::QWebFrame(QWebFrame *parent, QWebFrameData *frameData) |
|
121 : QObject(parent) |
|
122 , d(new QWebFramePrivate) |
|
123 { |
|
124 d->page = parent->d->page; |
|
125 d->init(this, parent->d->page->d->page, frameData); |
|
126 } |
|
127 |
|
128 QWebFrame::~QWebFrame() |
|
129 { |
|
130 Q_ASSERT(d->frame == 0); |
|
131 Q_ASSERT(d->frameView == 0); |
|
132 delete d; |
|
133 } |
|
134 |
|
135 void QWebFrame::addToJSWindowObject(const QByteArray &name, QObject *object) |
|
136 { |
|
137 KJS::JSLock lock; |
|
138 KJS::Window *window = KJS::Window::retrieveWindow(d->frame.get()); |
|
139 KJS::Bindings::RootObject *root = d->frame->bindingRootObject(); |
|
140 if (!window) { |
|
141 qDebug() << "Warning: couldn't get window object"; |
|
142 return; |
|
143 } |
|
144 |
|
145 KJS::JSObject *runtimeObject = |
|
146 KJS::Bindings::Instance::createRuntimeObject(KJS::Bindings::Instance::QtLanguage, |
|
147 object, root); |
|
148 |
|
149 window->put(window->interpreter()->globalExec(), KJS::Identifier(name.constData()), runtimeObject); |
|
150 } |
|
151 |
|
152 |
|
153 QString QWebFrame::markup() const |
|
154 { |
|
155 if (!d->frame->document()) |
|
156 return QString(); |
|
157 return createMarkup(d->frame->document()); |
|
158 } |
|
159 |
|
160 QString QWebFrame::innerText() const |
|
161 { |
|
162 if (d->frameView->layoutPending()) |
|
163 d->frameView->layout(); |
|
164 |
|
165 Element *documentElement = d->frame->document()->documentElement(); |
|
166 return documentElement->innerText(); |
|
167 } |
|
168 |
|
169 QString QWebFrame::renderTreeDump() const |
|
170 { |
|
171 if (d->frameView->layoutPending()) |
|
172 d->frameView->layout(); |
|
173 |
|
174 return externalRepresentation(d->frame->renderer()); |
|
175 } |
|
176 |
|
177 QString QWebFrame::title() const |
|
178 { |
|
179 if (d->frame->document()) |
|
180 return d->frame->document()->title(); |
|
181 else return QString(); |
|
182 } |
|
183 |
|
184 QString QWebFrame::name() const |
|
185 { |
|
186 return d->frame->tree()->name(); |
|
187 } |
|
188 |
|
189 QWebPage * QWebFrame::page() const |
|
190 { |
|
191 return d->page; |
|
192 } |
|
193 |
|
194 QString QWebFrame::selectedText() const |
|
195 { |
|
196 return d->frame->selectedText(); |
|
197 } |
|
198 |
|
199 QList<QWebFrame*> QWebFrame::childFrames() const |
|
200 { |
|
201 QList<QWebFrame*> rc; |
|
202 if (d->frame) { |
|
203 FrameTree *tree = d->frame->tree(); |
|
204 for (Frame *child = tree->firstChild(); child; child = child->tree()->nextSibling()) { |
|
205 FrameLoader *loader = child->loader(); |
|
206 FrameLoaderClientQt *client = static_cast<FrameLoaderClientQt*>(loader->client()); |
|
207 if (client) |
|
208 rc.append(client->webFrame()); |
|
209 } |
|
210 |
|
211 } |
|
212 return rc; |
|
213 } |
|
214 |
|
215 |
|
216 Qt::ScrollBarPolicy QWebFrame::verticalScrollBarPolicy() const |
|
217 { |
|
218 return (Qt::ScrollBarPolicy) d->frameView->vScrollbarMode(); |
|
219 } |
|
220 |
|
221 void QWebFrame::setVerticalScrollBarPolicy(Qt::ScrollBarPolicy policy) |
|
222 { |
|
223 Q_ASSERT(ScrollbarAuto == Qt::ScrollBarAsNeeded); |
|
224 Q_ASSERT(ScrollbarAlwaysOff == Qt::ScrollBarAlwaysOff); |
|
225 Q_ASSERT(ScrollbarAlwaysOn == Qt::ScrollBarAlwaysOn); |
|
226 d->frameView->setVScrollbarMode((ScrollbarMode)policy); |
|
227 } |
|
228 |
|
229 Qt::ScrollBarPolicy QWebFrame::horizontalScrollBarPolicy() const |
|
230 { |
|
231 return (Qt::ScrollBarPolicy) d->frameView->hScrollbarMode(); |
|
232 } |
|
233 |
|
234 void QWebFrame::setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy policy) |
|
235 { |
|
236 d->frameView->setHScrollbarMode((ScrollbarMode)policy); |
|
237 } |
|
238 |
|
239 void QWebFrame::render(QPainter *painter, const QRect &source) |
|
240 { |
|
241 if (!d->frameView || !d->frame->renderer()) |
|
242 return; |
|
243 |
|
244 layout(); |
|
245 |
|
246 GraphicsContext ctx(painter); |
|
247 d->frameView->paint(&ctx, source); |
|
248 } |
|
249 |
|
250 void QWebFrame::layout() |
|
251 { |
|
252 if (d->frameView->needsLayout()) { |
|
253 d->frameView->layout(); |
|
254 } |
|
255 |
|
256 foreach (QWebFrame *child, childFrames()) { |
|
257 child->layout(); |
|
258 } |
|
259 } |
|
260 |
|
261 QPoint QWebFrame::pos() const |
|
262 { |
|
263 Q_ASSERT(d->frameView); |
|
264 return d->frameView->frameGeometry().topLeft(); |
|
265 } |
|
266 |
|
267 QRect QWebFrame::geometry() const |
|
268 { |
|
269 Q_ASSERT(d->frameView); |
|
270 return d->frameView->frameGeometry(); |
|
271 } |
|
272 |
|
273 QString QWebFrame::evaluateJavaScript(const QString& scriptSource) |
|
274 { |
|
275 KJSProxy *proxy = d->frame->scriptProxy(); |
|
276 QString rc; |
|
277 if (proxy) { |
|
278 KJS::JSValue *v = proxy->evaluate(String(), 0, scriptSource); |
|
279 if (v) { |
|
280 rc = String(v->toString(proxy->interpreter()->globalExec())); |
|
281 } |
|
282 } |
|
283 return rc; |
|
284 } |
|
285 |
|
286 void QWebFrame::mouseMoveEvent(QMouseEvent *ev) |
|
287 { |
|
288 if (!d->frameView) |
|
289 return; |
|
290 |
|
291 d->eventHandler->handleMouseMoveEvent(PlatformMouseEvent(ev, 0)); |
|
292 const int xOffset = |
|
293 d->horizontalScrollBar() ? d->horizontalScrollBar()->value() : 0; |
|
294 const int yOffset = |
|
295 d->verticalScrollBar() ? d->verticalScrollBar()->value() : 0; |
|
296 IntPoint pt(ev->x() + xOffset, ev->y() + yOffset); |
|
297 WebCore::HitTestResult result = d->eventHandler->hitTestResultAtPoint(pt, false); |
|
298 WebCore::Element *link = result.URLElement(); |
|
299 if (link != d->lastHoverElement) { |
|
300 d->lastHoverElement = link; |
|
301 emit hoveringOverLink(result.absoluteLinkURL().prettyURL(), result.title()); |
|
302 } |
|
303 } |
|
304 |
|
305 void QWebFrame::mousePressEvent(QMouseEvent *ev) |
|
306 { |
|
307 if (!d->eventHandler) |
|
308 return; |
|
309 |
|
310 if (ev->button() == Qt::RightButton) |
|
311 d->eventHandler->sendContextMenuEvent(PlatformMouseEvent(ev, 1)); |
|
312 else |
|
313 d->eventHandler->handleMousePressEvent(PlatformMouseEvent(ev, 1)); |
|
314 |
|
315 //FIXME need to keep track of subframe focus for key events! |
|
316 d->page->setFocus(); |
|
317 } |
|
318 |
|
319 void QWebFrame::mouseDoubleClickEvent(QMouseEvent *ev) |
|
320 { |
|
321 if (!d->eventHandler) |
|
322 return; |
|
323 |
|
324 d->eventHandler->handleMousePressEvent(PlatformMouseEvent(ev, 2)); |
|
325 |
|
326 //FIXME need to keep track of subframe focus for key events! |
|
327 d->page->setFocus(); |
|
328 } |
|
329 |
|
330 void QWebFrame::mouseReleaseEvent(QMouseEvent *ev) |
|
331 { |
|
332 if (!d->frameView) |
|
333 return; |
|
334 |
|
335 d->eventHandler->handleMouseReleaseEvent(PlatformMouseEvent(ev, 0)); |
|
336 |
|
337 //FIXME need to keep track of subframe focus for key events! |
|
338 d->page->setFocus(); |
|
339 } |
|
340 |
|
341 void QWebFrame::wheelEvent(QWheelEvent *ev) |
|
342 { |
|
343 PlatformWheelEvent wkEvent(ev); |
|
344 bool accepted = false; |
|
345 if (d->eventHandler) |
|
346 accepted = d->eventHandler->handleWheelEvent(wkEvent); |
|
347 |
|
348 ev->setAccepted(accepted); |
|
349 |
|
350 //FIXME need to keep track of subframe focus for key events! |
|
351 d->page->setFocus(); |
|
352 } |
|
353 |