Reviewed by Rob Buis.
[WebKit-https.git] / WebKitQt / Api / qwebframe.cpp
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., 59 Temple Place - Suite 330,
18     Boston, MA 02111-1307, 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 "FrameLoaderClientQt.h"
29 #include "Frame.h"
30 #include "FrameTree.h"
31 #include "FrameView.h"
32 #include "GraphicsContext.h"
33 #include "HitTestResult.h"
34 #include "Page.h"
35 #include "PlatformMouseEvent.h"
36 #include "PlatformKeyboardEvent.h"
37 #include "PlatformWheelEvent.h"
38 #include "ResourceRequest.h"
39
40 #include "markup.h"
41 #include "RenderTreeAsText.h"
42 #include "Element.h"
43 #include "Document.h"
44 #include "DragData.h"
45 #include "RenderObject.h"
46
47 #include "bindings/runtime.h"
48 #include "bindings/runtime_root.h"
49 #include "ExecState.h"
50 #include "object.h"
51
52 #include "wtf/HashMap.h"
53
54 #include <qpainter.h>
55 #include <qevent.h>
56 #include <qscrollbar.h>
57 #include <qdebug.h>
58
59 using namespace WebCore;
60
61 void QWebFramePrivate::init(QWebFrame *qframe, WebCore::Page *page, QWebFrameData *frameData)
62 {
63     q = qframe;
64
65     q->setLineWidth(0);
66     q->setMidLineWidth(0);
67     q->setFrameShape(QFrame::NoFrame);
68     q->setMouseTracking(true);
69     q->setFocusPolicy(Qt::StrongFocus);
70     q->verticalScrollBar()->setSingleStep(20);
71     q->horizontalScrollBar()->setSingleStep(20);
72
73     frameLoaderClient = new FrameLoaderClientQt();
74     frame = new Frame(page, frameData->ownerElement, frameLoaderClient);
75     frameLoaderClient->setFrame(qframe, frame.get());
76
77     frameView = new FrameView(frame.get());
78     frameView->deref();
79     frameView->setScrollArea(qframe);
80     frameView->setAllowsScrolling(frameData->allowsScrolling);
81     frame->setView(frameView.get());
82     frame->init();
83     eventHandler = frame->eventHandler();
84 }
85
86 void QWebFramePrivate::_q_adjustScrollbars()
87 {
88     QAbstractSlider *hbar = q->horizontalScrollBar();
89     QAbstractSlider *vbar = q->verticalScrollBar();
90
91     const QSize viewportSize = q->viewport()->size();
92     QSize docSize = QSize(frameView->contentsWidth(), frameView->contentsHeight());
93
94     hbar->setRange(0, docSize.width() - viewportSize.width());
95     hbar->setPageStep(viewportSize.width());
96
97     vbar->setRange(0, docSize.height() - viewportSize.height());
98     vbar->setPageStep(viewportSize.height());
99 }
100
101 void QWebFramePrivate::_q_handleKeyEvent(QKeyEvent *ev, bool isKeyUp)
102 {
103     PlatformKeyboardEvent kevent(ev, isKeyUp);
104
105     if (!eventHandler)
106         return;
107
108     bool handled = eventHandler->keyEvent(kevent);
109
110     ev->setAccepted(handled);
111 }
112
113 QWebFrame::QWebFrame(QWebPage *parent, QWebFrameData *frameData)
114     : QAbstractScrollArea(parent)
115     , d(new QWebFramePrivate)
116 {
117     d->page = parent;
118     d->init(this, parent->d->page, frameData);
119
120     if (!frameData->url.isEmpty()) {
121         ResourceRequest request(frameData->url, frameData->referrer);
122         d->frame->loader()->load(request, frameData->name);
123     }
124 }
125
126
127 QWebFrame::QWebFrame(QWebFrame *parent, QWebFrameData *frameData)
128     : QAbstractScrollArea(parent->viewport())
129     , d(new QWebFramePrivate)
130 {
131     QPalette pal = palette();
132     pal.setBrush(QPalette::Background, Qt::white);
133     setPalette(pal);
134
135     d->page = parent->d->page;
136     d->init(this, parent->d->page->d->page, frameData);
137 }
138
139 QWebFrame::~QWebFrame()
140 {
141     Q_ASSERT(d->frame == 0);
142     Q_ASSERT(d->frameView == 0);
143     delete d;
144 }
145
146 void QWebFrame::addToJSWindowObject(const QByteArray &name, QObject *object)
147 {
148     KJS::Bindings::RootObject *root = d->frame->bindingRootObject();
149     KJS::ExecState *exec = root->interpreter()->globalExec();
150     KJS::JSObject *rootObject = root->interpreter()->globalObject();
151     KJS::JSObject *window = rootObject->get(exec, KJS::Identifier("window"))->getObject();
152     if (!window) {
153         qDebug() << "Warning: couldn't get window object";
154         return;
155     }
156
157     KJS::JSObject *testController =
158         KJS::Bindings::Instance::createRuntimeObject(KJS::Bindings::Instance::QtLanguage,
159                                                      object, root);
160
161     window->put(exec, KJS::Identifier(name.constData()), testController);
162 }
163
164
165 QString QWebFrame::markup() const
166 {
167     if (!d->frame->document())
168         return QString();
169     return createMarkup(d->frame->document());
170 }
171
172 QString QWebFrame::innerText() const
173 {
174     if (d->frameView->layoutPending())
175         d->frameView->layout();
176
177     Element *documentElement = d->frame->document()->documentElement();
178     return documentElement->innerText();
179 }
180
181 QString QWebFrame::renderTreeDump() const
182 {
183     if (d->frameView->layoutPending())
184         d->frameView->layout();
185
186     return externalRepresentation(d->frame->renderer());
187 }
188
189 QString QWebFrame::title() const
190 {
191     if (d->frame->document())
192         return d->frame->document()->title();
193     else return QString();
194 }
195
196 QWebPage * QWebFrame::page() const
197 {
198     return d->page;
199 }
200
201 QString QWebFrame::selectedText() const
202 {
203     return d->frame->selectedText();
204 }
205
206 void QWebFrame::resizeEvent(QResizeEvent *e)
207 {
208     QAbstractScrollArea::resizeEvent(e);
209     if (d->frame && d->frameView) {
210         d->frame->forceLayout();
211         d->frame->view()->adjustViewSize();
212     }
213     d->_q_adjustScrollbars();
214 }
215
216 QList<QWebFrame*> QWebFrame::childFrames() const
217 {
218     QList<QWebFrame*> rc;
219     if (d->frame) {
220         FrameTree *tree = d->frame->tree();
221         for (Frame *child = tree->firstChild(); child; child = child->tree()->nextSibling()) {
222             FrameLoader *loader = child->loader();
223             FrameLoaderClientQt *client = static_cast<FrameLoaderClientQt*>(loader->client());
224             if (client)
225                 rc.append(client->webFrame());
226         }
227
228     }
229     return rc;
230 }
231
232 void QWebFrame::paintEvent(QPaintEvent *ev)
233 {
234     if (!d->frameView || !d->frame->renderer())
235         return;
236
237 #ifdef QWEBKIT_TIME_RENDERING
238     QTime time;
239     time.start();
240 #endif
241     QRect clip = ev->rect();
242
243     if (d->frameView->needsLayout()) {
244         d->frameView->layout();
245     }
246     QPainter p(viewport());
247     GraphicsContext ctx(&p);
248
249     const int xOffset = horizontalScrollBar()->value();
250     const int yOffset = verticalScrollBar()->value();
251
252     ctx.translate(-xOffset, -yOffset);
253     clip.translate(xOffset, yOffset);
254
255     d->frame->paint(&ctx, clip);
256     p.end();
257
258 #ifdef    QWEBKIT_TIME_RENDERING
259     int elapsed = time.elapsed();
260     qDebug()<<"paint event on "<<clip<<", took to render =  "<<elapsed;
261 #endif
262 }
263
264 void QWebFrame::mouseMoveEvent(QMouseEvent *ev)
265 {
266     if (!d->frameView)
267         return;
268
269     d->frameView->handleMouseMoveEvent(PlatformMouseEvent(ev, 0));
270     const int xOffset = horizontalScrollBar()->value();
271     const int yOffset = verticalScrollBar()->value();
272     IntPoint pt(ev->x() + xOffset, ev->y() + yOffset);
273     WebCore::HitTestResult result = d->eventHandler->hitTestResultAtPoint(pt, false);
274     WebCore::Element *link = result.URLElement();
275     if (link != d->lastHoverElement) {
276         d->lastHoverElement = link;
277         emit hoveringOverLink(result.absoluteLinkURL().prettyURL(), result.title());
278     }
279 }
280
281 void QWebFrame::mousePressEvent(QMouseEvent *ev)
282 {
283     if (!d->eventHandler)
284         return;
285
286     d->eventHandler->handleMousePressEvent(PlatformMouseEvent(ev, 1));
287 }
288
289 void QWebFrame::mouseReleaseEvent(QMouseEvent *ev)
290 {
291     if (!d->frameView)
292         return;
293
294     d->frameView->handleMouseReleaseEvent(PlatformMouseEvent(ev, 0));
295 }
296
297 void QWebFrame::wheelEvent(QWheelEvent *e)
298 {
299     PlatformWheelEvent wkEvent(e);
300     bool accepted = false;
301     if (d->eventHandler)
302         accepted = d->eventHandler->handleWheelEvent(wkEvent);
303
304     e->setAccepted(accepted);
305     if (!accepted)
306         QAbstractScrollArea::wheelEvent(e);
307 }
308
309 void QWebFrame::keyPressEvent(QKeyEvent *ev)
310 {
311     d->_q_handleKeyEvent(ev, false);
312 }
313
314 void QWebFrame::keyReleaseEvent(QKeyEvent *ev)
315 {
316     d->_q_handleKeyEvent(ev, true);
317 }
318
319 /*!\reimp
320 */
321 void QWebFrame::scrollContentsBy(int dx, int dy)
322 {
323     viewport()->scroll(dx, dy);
324 }
325
326 #include "qwebframe.moc"