2006-10-12 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
[WebKit-https.git] / WebCore / platform / gdk / FrameGdk.cpp
1 /*
2  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
3  * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com 
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
26  */
27
28 #include "config.h"
29 #include "FrameGdk.h"
30 #include "Element.h"
31 #include "RenderObject.h"
32 #include "RenderWidget.h"
33 #include "RenderLayer.h"
34 #include "Page.h"
35 #include "Document.h"
36 #include "DOMWindow.h"
37 #include "DOMImplementation.h"
38 #include "BrowserExtensionGdk.h"
39 #include "Document.h"
40 #include "Settings.h"
41 #include "Plugin.h"
42 #include "FramePrivate.h"
43 #include "GraphicsContext.h"
44 #include "HTMLDocument.h"
45 #include "ResourceLoader.h"
46 #include "ResourceLoaderInternal.h"
47 #include "PlatformMouseEvent.h"
48 #include "PlatformKeyboardEvent.h"
49 #include "PlatformWheelEvent.h"
50 #include "MouseEventWithHitTestResults.h"
51 #include "SelectionController.h"
52 #include "TypingCommand.h"
53 #include "SSLKeyGenerator.h"
54 #include "KeyboardCodes.h"
55 #include <gdk/gdk.h>
56
57
58 // This function loads resources from WebKit
59 // This does not belong here and I'm not sure where
60 // it should go
61 // I don't know what the plans or design is
62 // for none code resources
63 Vector<char> loadResourceIntoArray(const char* resourceName)
64 {
65     Vector<char> resource;
66     //if (strcmp(resourceName,"missingImage") == 0) {
67     //}
68     return resource;
69 }
70
71 namespace WebCore {
72
73 FrameGdkClientDefault::FrameGdkClientDefault()
74     : ResourceLoaderClient()
75     , m_frame(0)
76     , m_beginCalled(false)
77 {
78 }
79
80 FrameGdkClientDefault::~FrameGdkClientDefault()
81 {
82 }
83
84 void FrameGdkClientDefault::setFrame(const FrameGdk* frame)
85 {
86     m_frame = const_cast<FrameGdk*>(frame);
87 }
88
89 void FrameGdkClientDefault::openURL(const KURL& url)
90 {
91     m_frame->didOpenURL(url);
92     m_beginCalled = false;
93
94     RefPtr<ResourceLoader> loader = ResourceLoader::create(this, "GET", url);
95     loader->start(0);
96 }
97
98 void FrameGdkClientDefault::submitForm(const String& method, const KURL& url, const FormData* postData)
99 {
100     m_beginCalled = false;
101
102     RefPtr<ResourceLoader> loader = ResourceLoader::create(this, method, url, *postData);
103     loader->start(0);
104 }
105
106 void FrameGdkClientDefault::receivedResponse(ResourceLoader*, PlatformResponse)
107 {
108     // no-op
109 }
110
111 void FrameGdkClientDefault::receivedData(ResourceLoader* job, const char* data, int length)
112 {
113     if (!m_beginCalled) {
114         m_beginCalled = true;
115
116 #if 0  // FIXME: This is from Qt version, need to be removed or Gdk equivalent written
117         // Assign correct mimetype _before_ calling begin()!
118         ResourceLoaderInternal* d = job->getInternal();
119         if (d) {
120             ResourceRequest request(m_frame->resourceRequest());
121             request.m_responseMIMEType = d->m_mimetype;
122             m_frame->setResourceRequest(request);
123         }
124 #endif
125         m_frame->begin(job->url());
126     }
127
128     m_frame->write(data, length);
129 }
130
131 void FrameGdkClientDefault::receivedAllData(ResourceLoader* job, PlatformData data)
132 {
133     m_frame->end();
134     m_beginCalled = false;
135 }
136
137 static void doScroll(const RenderObject* r, float deltaX, float deltaY)
138 {
139     // FIXME: The scrolling done here should be done in the default handlers
140     // of the elements rather than here in the part.
141     if (!r)
142         return;
143
144     //broken since it calls scroll on scrollbars
145     //and we have none now
146     //r->scroll(direction, ScrollByWheel, multiplier);
147     if (!r->layer())
148         return;
149
150     int x = r->layer()->scrollXOffset() + deltaX;
151     int y = r->layer()->scrollYOffset() + deltaY;
152     r->layer()->scrollToOffset(x, y, true, true);
153 }
154
155 FrameGdk::FrameGdk(GdkDrawable* gdkdrawable)
156     : Frame(new Page, 0), m_drawable(gdkdrawable)
157 {
158     d->m_extension = new BrowserExtensionGdk(this);
159     Settings* settings = new Settings;
160     settings->setAutoLoadImages(true);
161     settings->setMinFontSize(5);
162     settings->setMinLogicalFontSize(5);
163     settings->setShouldPrintBackgrounds(true);
164
165     settings->setMediumFixedFontSize(14);
166     settings->setMediumFontSize(14);
167     settings->setSerifFontName("Times New Roman");
168     settings->setSansSerifFontName("Arial");
169     settings->setFixedFontName("Courier");
170     settings->setStdFontName("Arial");
171     setSettings(settings);
172     page()->setMainFrame(this);
173     FrameView* view = new FrameView(this);
174     setView(view);
175     IntRect geom = frameGeometry();
176     view->resize(geom.width(), geom.height());
177     view->ScrollView::setDrawable(gdkdrawable);
178
179     m_client = new FrameGdkClientDefault();
180     m_client->setFrame(this);
181 }
182
183 FrameGdk::FrameGdk(Page* page, Element* element)
184     : Frame(page,element)
185 {
186     d->m_extension = new BrowserExtensionGdk(this);
187     Settings* settings = new Settings;
188     settings->setAutoLoadImages(true);
189     setSettings(settings);
190     m_client = new FrameGdkClientDefault();
191     m_client->setFrame(this);
192 }
193
194 FrameGdk::~FrameGdk()
195 {
196     cancelAndClear();
197 }
198
199 bool FrameGdk::openURL(const KURL& url)
200 {
201     if (!m_client)
202         return false;
203
204     m_client->openURL(url);
205     return true;
206 }
207
208 void FrameGdk::submitForm(const ResourceRequest& request)
209 {
210     // FIXME: this is a hack inherited from FrameMac, and should be pushed into Frame
211     if (d->m_submittedFormURL == request.url())
212         return;
213
214     d->m_submittedFormURL = request.url();
215
216     if (m_client)
217         m_client->submitForm(request.doPost() ? "POST" : "GET", request.url(), &request.postData);
218     clearRecordedFormValues();
219 }
220
221 void FrameGdk::urlSelected(const ResourceRequest& request)
222 {
223     if (!m_client)
224         return;
225
226     m_client->openURL(request.url());
227 }
228
229 String FrameGdk::userAgent() const
230 {
231     return "Mozilla/5.0 (PC; U; Intel; Linux; en) AppleWebKit/420+ (KHTML, like Gecko)";
232 }
233
234 void FrameGdk::runJavaScriptAlert(String const& message)
235 {
236 }
237
238 bool FrameGdk::runJavaScriptConfirm(String const& message)
239 {
240     return true;
241 }
242
243 void FrameGdk::setTitle(const String &title)
244 {
245 }
246
247 void FrameGdk::handleGdkEvent(GdkEvent* event)
248 {
249     switch (event->type) {
250         case GDK_EXPOSE: {
251             GdkRectangle clip;
252             gdk_region_get_clipbox(event->expose.region, &clip);
253             gdk_window_begin_paint_region (event->any.window, event->expose.region);
254             cairo_t* cr = gdk_cairo_create (event->any.window);
255             GraphicsContext* ctx = new GraphicsContext(cr);
256             paint(ctx, IntRect(clip.x, clip.y, clip.width, clip.height));
257             delete ctx;
258             cairo_destroy(cr);
259             gdk_window_end_paint (event->any.window);
260             break;
261         }
262         case GDK_SCROLL: {
263             PlatformWheelEvent wheelEvent(event);
264             view()->handleWheelEvent(wheelEvent);
265             if (wheelEvent.isAccepted()) {
266                 return;
267             }
268             RenderObject::NodeInfo nodeInfo(true, true);
269             renderer()->layer()->hitTest(nodeInfo, wheelEvent.pos());
270             Node* node = nodeInfo.innerNode();
271             if (!node)
272                 return;
273             //Default to scrolling the page
274             //not sure why its null
275             //broke anyway when its not null
276             doScroll(renderer(), wheelEvent.deltaX(), wheelEvent.deltaY());
277             break;
278         }
279         case GDK_DRAG_ENTER:
280         case GDK_DRAG_LEAVE:
281         case GDK_DRAG_MOTION:
282         case GDK_DRAG_STATUS:
283         case GDK_DROP_START:
284         case GDK_DROP_FINISHED: {
285             //bool updateDragAndDrop(const PlatformMouseEvent&, Clipboard*);
286             //void cancelDragAndDrop(const PlatformMouseEvent&, Clipboard*);
287             //bool performDragAndDrop(const PlatformMouseEvent&, Clipboard*);
288             break;
289         }
290         case GDK_MOTION_NOTIFY:
291             view()->handleMouseMoveEvent(event);
292             break;
293         case GDK_BUTTON_PRESS:
294         case GDK_2BUTTON_PRESS:
295         case GDK_3BUTTON_PRESS:
296             view()->handleMousePressEvent(event);
297             break;
298         case GDK_BUTTON_RELEASE:
299             view()->handleMouseReleaseEvent(event);
300             break;
301         case GDK_KEY_PRESS:
302         case GDK_KEY_RELEASE: {
303             PlatformKeyboardEvent kevent(event);
304             bool handled = false;
305             if (!kevent.isKeyUp()) {
306                 Node* start = selectionController()->start().node();
307                 if (start && start->isContentEditable()) {
308                     switch(kevent.WindowsKeyCode()) {
309                         case VK_BACK:
310                             TypingCommand::deleteKeyPressed(document());
311                             break;
312                         case VK_DELETE:
313                             TypingCommand::forwardDeleteKeyPressed(document());
314                             break;
315                         case VK_LEFT:
316                             selectionController()->modify(SelectionController::MOVE, SelectionController::LEFT, CharacterGranularity);
317                             break;
318                         case VK_RIGHT:
319                             selectionController()->modify(SelectionController::MOVE, SelectionController::RIGHT, CharacterGranularity);
320                             break;
321                         case VK_UP:
322                             selectionController()->modify(SelectionController::MOVE, SelectionController::BACKWARD, ParagraphGranularity);
323                             break;
324                         case VK_DOWN:
325                             selectionController()->modify(SelectionController::MOVE, SelectionController::FORWARD, ParagraphGranularity);
326                             break;
327                         default:
328                             TypingCommand::insertText(document(), kevent.text(), false);
329
330                     }
331                     handled = true;
332                 }
333                 if (!handled) {
334                     switch (kevent.WindowsKeyCode()) {
335                         case VK_LEFT:
336                             doScroll(renderer(), true, -120);
337                             break;
338                         case VK_RIGHT:
339                             doScroll(renderer(), true, 120);
340                             break;
341                         case VK_UP:
342                             doScroll(renderer(), false, -120);
343                             break;
344                         case VK_PRIOR:
345                             //return SB_PAGEUP;
346                             break;
347                         case VK_NEXT:
348                             //return SB_PAGEDOWN;
349                             break;
350                         case VK_DOWN:
351                             doScroll(renderer(), false, 120);
352                             break;
353                         case VK_HOME:
354                             renderer()->layer()->scrollToOffset(0, 0, true, true);
355                             doScroll(renderer(), false, 120);
356                             break;
357                         case VK_END:
358                             renderer()->layer()->scrollToOffset(0,
359                                                                 renderer()->height(), true, true);
360                             break;
361                         case VK_SPACE:
362                             if (kevent.shiftKey())
363                                 doScroll(renderer(), false, -120);
364                             else
365                                 doScroll(renderer(), false, 120);
366                             break;
367                     }
368
369                 }
370             }
371         }
372         default:
373             break;
374     }
375 }
376
377 void FrameGdk::setFrameGeometry(const IntRect &r)
378 {
379     if (!m_drawable || !GDK_IS_WINDOW(m_drawable))
380         return;
381     GdkWindow* window = GDK_WINDOW(m_drawable);
382     gdk_window_move_resize(window, r.x(), r.y(), r.width(), r.height());
383 }
384
385 IntRect FrameGdk::frameGeometry() const
386 {
387     gint x, y, width, height, depth;
388     if (!m_drawable)
389         return IntRect();
390
391     if (!GDK_IS_WINDOW(m_drawable)) {
392         gdk_drawable_get_size(m_drawable, &width, &height);
393         return IntRect(0, 0, width, height);
394     }
395
396     GdkWindow* window = GDK_WINDOW(m_drawable);
397     gdk_window_get_geometry(window, &x, &y, &width, &height, &depth);
398     return IntRect(x, y, width, height);
399 }
400
401 bool FrameGdk::passWheelEventToChildWidget(Node* node)
402 {
403     if (!node)
404         return false;
405     RenderObject* renderer = node->renderer();
406     if (!renderer || !renderer->isWidget())
407         return false;
408     Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
409     if (!widget)
410         return false;
411     return true;
412 }
413
414 bool FrameGdk::passSubframeEventToSubframe(MouseEventWithHitTestResults& mev, Frame*)
415 {
416     if (mev.targetNode() == 0)
417         return true;
418     return false;
419 }
420
421 }