2 * Copyright (C) 2007 Holger Hans Peter Freyther
3 * Copyright (C) 2007 Christian Dywan <christian@twotoasts.de>
4 * Copyright (C) 2007 Xan Lopez <xan@gnome.org>
5 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of Apple, Inc. ("Apple") nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include "webkitgtkpage.h"
35 #include "webkitgtk-marshal.h"
36 #include "webkitgtkprivate.h"
38 #include "NotImplemented.h"
39 #include "ChromeClientGtk.h"
40 #include "ContextMenuClientGtk.h"
41 #include "DragClientGtk.h"
42 #include "EditorClientGtk.h"
43 #include "EventHandler.h"
44 #include "HitTestRequest.h"
45 #include "HitTestResult.h"
46 #include "GraphicsContext.h"
47 #include "InspectorClientGtk.h"
48 #include "FrameLoader.h"
49 #include "FrameView.h"
50 #include "PlatformKeyboardEvent.h"
51 #include "PlatformWheelEvent.h"
52 #include "SubstituteData.h"
54 #include <gdk/gdkkeysyms.h>
56 using namespace WebKit;
57 using namespace WebCore;
64 WINDOW_OBJECT_CLEARED,
66 LOAD_PROGRESS_CHANGED,
70 STATUS_BAR_TEXT_CHANGED,
80 static guint webkit_page_signals[LAST_SIGNAL] = { 0, };
82 G_DEFINE_TYPE(WebKitPage, webkit_page, GTK_TYPE_CONTAINER)
84 static gboolean webkit_page_expose_event(GtkWidget* widget, GdkEventExpose* event)
86 Frame* frame = core(getFrameFromPage(WEBKIT_PAGE(widget)));
88 gdk_region_get_clipbox(event->region, &clip);
89 cairo_t* cr = gdk_cairo_create(event->window);
90 GraphicsContext ctx(cr);
91 ctx.setGdkExposeEvent(event);
92 if (frame->renderer()) {
93 frame->view()->layoutIfNeededRecursive();
94 frame->view()->paint(&ctx, clip);
101 static gboolean webkit_page_key_event(GtkWidget* widget, GdkEventKey* event)
103 Frame* frame = core(getFrameFromPage(WEBKIT_PAGE(widget)));
104 PlatformKeyboardEvent keyboardEvent(event);
106 if (frame->eventHandler()->keyEvent(keyboardEvent))
109 if (event->type != GDK_KEY_PRESS)
112 FrameView* view = frame->view();
114 /* FIXME: at the very least we should be using the same code than the
115 Windows port here, but our ScrollView file diverges enough to make
116 that impossible. A short term solution would be to unify ScrollViewWin
117 and ScrollViewGtk. Long-term ScrollView and FrameView should be
118 unified and used everywhere for scrollbars */
120 switch (event->keyval) {
122 view->scrollBy(0, LINE_STEP);
125 view->scrollBy(0, -LINE_STEP);
128 view->scrollBy(LINE_STEP, 0);
131 view->scrollBy(-LINE_STEP, 0);
138 static gboolean webkit_page_button_event(GtkWidget* widget, GdkEventButton* event)
140 Frame* frame = core(getFrameFromPage(WEBKIT_PAGE(widget)));
142 if (event->type == GDK_BUTTON_RELEASE)
143 return frame->eventHandler()->handleMouseReleaseEvent(PlatformMouseEvent(event));
145 // FIXME: need to keep track of subframe focus for key events
146 gtk_widget_grab_focus(GTK_WIDGET(widget));
147 return frame->eventHandler()->handleMousePressEvent(PlatformMouseEvent(event));
150 static gboolean webkit_page_motion_event(GtkWidget* widget, GdkEventMotion* event)
152 Frame* frame = core(getFrameFromPage(WEBKIT_PAGE(widget)));
153 return frame->eventHandler()->mouseMoved(PlatformMouseEvent(event));
156 static gboolean webkit_page_scroll_event(GtkWidget* widget, GdkEventScroll* event)
158 Frame* frame = core(getFrameFromPage(WEBKIT_PAGE(widget)));
159 PlatformWheelEvent wheelEvent(event);
160 return frame->eventHandler()->handleWheelEvent(wheelEvent);
163 static void webkit_page_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
165 GTK_WIDGET_CLASS(webkit_page_parent_class)->size_allocate(widget,allocation);
167 Frame* frame = core(getFrameFromPage(WEBKIT_PAGE(widget)));
168 frame->view()->resize(allocation->width, allocation->height);
169 frame->forceLayout();
170 frame->view()->adjustViewSize();
171 frame->sendResizeEvent();
174 static void webkit_page_realize(GtkWidget* widget)
176 GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
178 GdkWindowAttr attributes;
179 attributes.window_type = GDK_WINDOW_CHILD;
180 attributes.x = widget->allocation.x;
181 attributes.y = widget->allocation.y;
182 attributes.width = widget->allocation.width;
183 attributes.height = widget->allocation.height;
184 attributes.wclass = GDK_INPUT_OUTPUT;
185 attributes.visual = gtk_widget_get_visual (widget);
186 attributes.colormap = gtk_widget_get_colormap (widget);
187 attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK
189 | GDK_BUTTON_PRESS_MASK
190 | GDK_BUTTON_RELEASE_MASK
191 | GDK_POINTER_MOTION_MASK
193 | GDK_KEY_RELEASE_MASK
194 | GDK_BUTTON_MOTION_MASK
195 | GDK_BUTTON1_MOTION_MASK
196 | GDK_BUTTON2_MOTION_MASK
197 | GDK_BUTTON3_MOTION_MASK;
199 gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
200 widget->window = gdk_window_new(gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
201 gdk_window_set_user_data(widget->window, widget);
204 static void webkit_page_set_scroll_adjustments(WebKitPage* page, GtkAdjustment* hadj, GtkAdjustment* vadj)
206 FrameView* view = core(getFrameFromPage(page))->view();
207 view->setGtkAdjustments(hadj, vadj);
210 static void webkit_page_container_add(GtkContainer* container, GtkWidget* widget)
212 WebKitPage* page = WEBKIT_PAGE(container);
213 WebKitPagePrivate* private_data = WEBKIT_PAGE_GET_PRIVATE(page);
215 private_data->children.add(widget);
216 if (GTK_WIDGET_REALIZED(container))
217 gtk_widget_set_parent_window(widget, GTK_WIDGET(page)->window);
218 gtk_widget_set_parent(widget, GTK_WIDGET(container));
221 static void webkit_page_container_remove(GtkContainer* container, GtkWidget* widget)
223 WebKitPagePrivate* private_data = WEBKIT_PAGE_GET_PRIVATE(WEBKIT_PAGE(container));
225 if (private_data->children.contains(widget)) {
226 gtk_widget_unparent(widget);
227 private_data->children.remove(widget);
231 static void webkit_page_container_forall(GtkContainer* container, gboolean, GtkCallback callback, gpointer callbackData)
233 WebKitPagePrivate* privateData = WEBKIT_PAGE_GET_PRIVATE(WEBKIT_PAGE(container));
235 HashSet<GtkWidget*> children = privateData->children;
236 HashSet<GtkWidget*>::const_iterator end = children.end();
237 for (HashSet<GtkWidget*>::const_iterator current = children.begin(); current != end; ++current)
238 (*callback)(*current, callbackData);
241 static WebKitPage* webkit_page_real_create_page(WebKitPage*)
247 static WebKitNavigationResponse webkit_page_real_navigation_requested(WebKitPage*, WebKitFrame* frame, WebKitNetworkRequest*)
250 return WEBKIT_NAVIGATION_RESPONSE_ACCEPT;
253 static void webkit_page_real_window_object_cleared(WebKitPage*, WebKitFrame*, JSGlobalContextRef context, JSObjectRef window_object)
258 static gchar* webkit_page_real_choose_file(WebKitPage*, WebKitFrame*, const gchar* old_name)
261 return g_strdup(old_name);
265 WEBKIT_SCRIPT_DIALOG_ALERT,
266 WEBKIT_SCRIPT_DIALOG_CONFIRM,
267 WEBKIT_SCRIPT_DIALOG_PROMPT
268 } WebKitScriptDialogType;
270 static gboolean webkit_page_script_dialog(WebKitPage* page, WebKitFrame* frame, const gchar* message, WebKitScriptDialogType type, const gchar* defaultValue, gchar** value)
272 GtkMessageType messageType;
273 GtkButtonsType buttons;
274 gint defaultResponse;
277 GtkWidget* entry = 0;
278 gboolean didConfirm = FALSE;
281 case WEBKIT_SCRIPT_DIALOG_ALERT:
282 messageType = GTK_MESSAGE_WARNING;
283 buttons = GTK_BUTTONS_CLOSE;
284 defaultResponse = GTK_RESPONSE_CLOSE;
286 case WEBKIT_SCRIPT_DIALOG_CONFIRM:
287 messageType = GTK_MESSAGE_QUESTION;
288 buttons = GTK_BUTTONS_YES_NO;
289 defaultResponse = GTK_RESPONSE_YES;
291 case WEBKIT_SCRIPT_DIALOG_PROMPT:
292 messageType = GTK_MESSAGE_QUESTION;
293 buttons = GTK_BUTTONS_OK_CANCEL;
294 defaultResponse = GTK_RESPONSE_OK;
297 g_warning("Unknown value for WebKitScriptDialogType.");
301 window = gtk_widget_get_toplevel(GTK_WIDGET(page));
302 dialog = gtk_message_dialog_new(GTK_WIDGET_TOPLEVEL(window) ? GTK_WINDOW(window) : 0, GTK_DIALOG_DESTROY_WITH_PARENT, messageType, buttons, "%s", message);
303 gchar* title = g_strconcat("JavaScript - ", webkit_frame_get_location(frame), NULL);
304 gtk_window_set_title(GTK_WINDOW(dialog), title);
307 if (type == WEBKIT_SCRIPT_DIALOG_PROMPT) {
308 entry = gtk_entry_new();
309 gtk_entry_set_text(GTK_ENTRY(entry), defaultValue);
310 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), entry);
311 gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
312 gtk_widget_show(entry);
315 gtk_dialog_set_default_response(GTK_DIALOG(dialog), defaultResponse);
316 gint response = gtk_dialog_run(GTK_DIALOG(dialog));
319 case GTK_RESPONSE_YES:
322 case GTK_RESPONSE_OK:
325 *value = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
329 case GTK_RESPONSE_NO:
330 case GTK_RESPONSE_CANCEL:
335 gtk_widget_destroy(GTK_WIDGET(dialog));
339 static gboolean webkit_page_real_script_alert(WebKitPage* page, WebKitFrame* frame, const gchar* message)
341 webkit_page_script_dialog(page, frame, message, WEBKIT_SCRIPT_DIALOG_ALERT, 0, 0);
345 static gboolean webkit_page_real_script_confirm(WebKitPage* page, WebKitFrame* frame, const gchar* message, gboolean* didConfirm)
347 *didConfirm = webkit_page_script_dialog(page, frame, message, WEBKIT_SCRIPT_DIALOG_CONFIRM, 0, 0);
351 static gboolean webkit_page_real_script_prompt(WebKitPage* page, WebKitFrame* frame, const gchar* message, const gchar* defaultValue, gchar** value)
353 if (!webkit_page_script_dialog(page, frame, message, WEBKIT_SCRIPT_DIALOG_PROMPT, defaultValue, value))
358 static gboolean webkit_page_real_console_message(WebKitPage* page, const gchar* message, unsigned int line, const gchar* sourceId)
360 g_print("console message: %s @%d: %s\n", sourceId, line, message);
364 static void webkit_page_finalize(GObject* object)
366 webkit_page_stop_loading(WEBKIT_PAGE(object));
368 WebKitPagePrivate* pageData = WEBKIT_PAGE_GET_PRIVATE(WEBKIT_PAGE(object));
369 delete pageData->page;
370 delete pageData->settings;
371 g_object_unref(pageData->mainFrame);
372 delete pageData->userAgent;
374 G_OBJECT_CLASS(webkit_page_parent_class)->finalize(object);
377 static void webkit_page_class_init(WebKitPageClass* pageClass)
379 g_type_class_add_private(pageClass, sizeof(WebKitPagePrivate));
385 webkit_page_signals[NAVIGATION_REQUESTED] = g_signal_new("navigation_requested",
386 G_TYPE_FROM_CLASS(pageClass),
387 (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
388 G_STRUCT_OFFSET (WebKitPageClass, navigation_requested),
391 webkit_marshal_INT__OBJECT_OBJECT,
397 * WebKitPage::window-object-cleared:
398 * @page: the object on which the signal is emitted
399 * @frame: the #WebKitFrame to which @window_object belongs
400 * @context: the #JSGlobalContextRef holding the global object and other
401 * execution state; equivalent to the return value of
402 * webkit_frame_get_global_context(@frame)
404 * @window_object: the #JSObjectRef representing the frame's JavaScript
407 * Emitted when the JavaScript window object in a #WebKitFrame has been
408 * cleared in preparation for a new load. This is the preferred place to
409 * set custom properties on the window object using the JavaScriptCore API.
411 webkit_page_signals[WINDOW_OBJECT_CLEARED] = g_signal_new("window_object_cleared",
412 G_TYPE_FROM_CLASS(pageClass),
413 (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
414 G_STRUCT_OFFSET (WebKitPageClass, window_object_cleared),
417 webkit_marshal_VOID__OBJECT_POINTER_POINTER,
424 * WebKitPage::load-started:
426 * @page: the object on which the signal is emitted
427 * @frame: the frame going to do the load
429 * When a #WebKitFrame begins to load this signal is emitted.
431 webkit_page_signals[LOAD_STARTED] = g_signal_new("load_started",
432 G_TYPE_FROM_CLASS(pageClass),
433 (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
437 g_cclosure_marshal_VOID__OBJECT,
442 * WebKitPage::load-progress-changed:
444 * @page: the #WebKitPage
445 * @progress: the global progress
447 webkit_page_signals[LOAD_PROGRESS_CHANGED] = g_signal_new("load_progress_changed",
448 G_TYPE_FROM_CLASS(pageClass),
449 (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
453 g_cclosure_marshal_VOID__INT,
457 webkit_page_signals[LOAD_FINISHED] = g_signal_new("load_finished",
458 G_TYPE_FROM_CLASS(pageClass),
459 (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
463 g_cclosure_marshal_VOID__OBJECT,
467 webkit_page_signals[TITLE_CHANGED] = g_signal_new("title_changed",
468 G_TYPE_FROM_CLASS(pageClass),
469 (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
473 webkit_marshal_VOID__STRING_STRING,
475 G_TYPE_STRING, G_TYPE_STRING);
477 webkit_page_signals[HOVERING_OVER_LINK] = g_signal_new("hovering_over_link",
478 G_TYPE_FROM_CLASS(pageClass),
479 (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
483 webkit_marshal_VOID__STRING_STRING,
488 webkit_page_signals[STATUS_BAR_TEXT_CHANGED] = g_signal_new("status_bar_text_changed",
489 G_TYPE_FROM_CLASS(pageClass),
490 (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
494 g_cclosure_marshal_VOID__STRING,
498 webkit_page_signals[ICOND_LOADED] = g_signal_new("icon_loaded",
499 G_TYPE_FROM_CLASS(pageClass),
500 (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
504 g_cclosure_marshal_VOID__VOID,
507 webkit_page_signals[SELECTION_CHANGED] = g_signal_new("selection_changed",
508 G_TYPE_FROM_CLASS(pageClass),
509 (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
513 g_cclosure_marshal_VOID__VOID,
517 * WebKitPage::console-message:
519 * @page: the object on which the signal is emitted
520 * @message: the message text
521 * @line: the line where the error occured
522 * @source_id: the source id
523 * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
525 * A JavaScript console message was created.
527 webkit_page_signals[CONSOLE_MESSAGE] = g_signal_new("console_message",
528 G_TYPE_FROM_CLASS(pageClass),
529 (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
530 G_STRUCT_OFFSET(WebKitPageClass, console_message),
531 g_signal_accumulator_true_handled,
533 webkit_marshal_BOOLEAN__STRING_INT_STRING,
535 G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING);
538 * WebKitPage::script-alert:
540 * @page: the object on which the signal is emitted
541 * @frame: the relevant frame
542 * @message: the message text
543 * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
545 * A JavaScript alert dialog was created.
547 webkit_page_signals[SCRIPT_ALERT] = g_signal_new("script-alert",
548 G_TYPE_FROM_CLASS(pageClass),
549 (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
550 G_STRUCT_OFFSET(WebKitPageClass, script_alert),
551 g_signal_accumulator_true_handled,
553 webkit_marshal_BOOLEAN__OBJECT_STRING,
555 G_TYPE_OBJECT, G_TYPE_STRING);
558 * WebKitPage::script-confirm:
560 * @page: the object on which the signal is emitted
561 * @frame: the relevant frame
562 * @message: the message text
563 * @confirmed: whether the dialog has been confirmed
564 * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
566 * A JavaScript confirm dialog was created, providing Yes and No buttons.
568 webkit_page_signals[SCRIPT_CONFIRM] = g_signal_new("script_confirm",
569 G_TYPE_FROM_CLASS(pageClass),
570 (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
571 G_STRUCT_OFFSET(WebKitPageClass, script_confirm),
572 g_signal_accumulator_true_handled,
574 webkit_marshal_BOOLEAN__OBJECT_STRING_BOOLEAN,
576 G_TYPE_OBJECT, G_TYPE_STRING, G_TYPE_BOOLEAN);
579 * WebKitPage::script-prompt:
581 * @page: the object on which the signal is emitted
582 * @frame: the relevant frame
583 * @message: the message text
584 * @default: the default value
585 * @text: To be filled with the return value or NULL if the dialog was cancelled.
586 * @return: TRUE to stop other handlers from being invoked for the event. FALSE to propagate the event further.
588 * A JavaScript prompt dialog was created, providing an entry to input text.
590 webkit_page_signals[SCRIPT_PROMPT] = g_signal_new("script_prompt",
591 G_TYPE_FROM_CLASS(pageClass),
592 (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
593 G_STRUCT_OFFSET(WebKitPageClass, script_prompt),
594 g_signal_accumulator_true_handled,
596 webkit_marshal_BOOLEAN__OBJECT_STRING_STRING_STRING,
598 G_TYPE_OBJECT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
602 * implementations of virtual methods
604 pageClass->create_page = webkit_page_real_create_page;
605 pageClass->navigation_requested = webkit_page_real_navigation_requested;
606 pageClass->window_object_cleared = webkit_page_real_window_object_cleared;
607 pageClass->choose_file = webkit_page_real_choose_file;
608 pageClass->script_alert = webkit_page_real_script_alert;
609 pageClass->script_confirm = webkit_page_real_script_confirm;
610 pageClass->script_prompt = webkit_page_real_script_prompt;
611 pageClass->console_message = webkit_page_real_console_message;
613 G_OBJECT_CLASS(pageClass)->finalize = webkit_page_finalize;
615 GtkWidgetClass* widgetClass = GTK_WIDGET_CLASS(pageClass);
616 widgetClass->realize = webkit_page_realize;
617 widgetClass->expose_event = webkit_page_expose_event;
618 widgetClass->key_press_event = webkit_page_key_event;
619 widgetClass->key_release_event = webkit_page_key_event;
620 widgetClass->button_press_event = webkit_page_button_event;
621 widgetClass->button_release_event = webkit_page_button_event;
622 widgetClass->motion_notify_event = webkit_page_motion_event;
623 widgetClass->scroll_event = webkit_page_scroll_event;
624 widgetClass->size_allocate = webkit_page_size_allocate;
626 GtkContainerClass* containerClass = GTK_CONTAINER_CLASS(pageClass);
627 containerClass->add = webkit_page_container_add;
628 containerClass->remove = webkit_page_container_remove;
629 containerClass->forall = webkit_page_container_forall;
632 * make us scrollable (e.g. addable to a GtkScrolledWindow)
634 pageClass->set_scroll_adjustments = webkit_page_set_scroll_adjustments;
635 GTK_WIDGET_CLASS(pageClass)->set_scroll_adjustments_signal = g_signal_new("set_scroll_adjustments",
636 G_TYPE_FROM_CLASS(pageClass),
637 (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
638 G_STRUCT_OFFSET(WebKitPageClass, set_scroll_adjustments),
640 webkit_marshal_VOID__OBJECT_OBJECT,
642 GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
645 static void webkit_page_init(WebKitPage* page)
647 WebKitPagePrivate* pageData = WEBKIT_PAGE_GET_PRIVATE(WEBKIT_PAGE(page));
648 pageData->page = new Page(new WebKit::ChromeClient(page), new WebKit::ContextMenuClient, new WebKit::EditorClient(page), new WebKit::DragClient, new WebKit::InspectorClient);
650 Settings* settings = pageData->page->settings();
651 settings->setLoadsImagesAutomatically(true);
652 settings->setMinimumFontSize(5);
653 settings->setMinimumLogicalFontSize(5);
654 settings->setShouldPrintBackgrounds(true);
655 settings->setJavaScriptEnabled(true);
656 settings->setDefaultFixedFontSize(14);
657 settings->setDefaultFontSize(14);
658 settings->setSerifFontFamily("Times New Roman");
659 settings->setSansSerifFontFamily("Arial");
660 settings->setFixedFontFamily("Courier New");
661 settings->setStandardFontFamily("Arial");
663 GTK_WIDGET_SET_FLAGS(page, GTK_CAN_FOCUS);
664 pageData->mainFrame = WEBKIT_FRAME(webkit_frame_new(page));
665 pageData->editable = false;
668 GtkWidget* webkit_page_new(void)
670 WebKitPage* page = WEBKIT_PAGE(g_object_new(WEBKIT_TYPE_PAGE, NULL));
672 return GTK_WIDGET(page);
675 void webkit_page_set_settings(WebKitPage* page, WebKitSettings* settings)
677 g_return_if_fail(WEBKIT_IS_PAGE(page));
678 g_return_if_fail(settings);
683 WebKitSettings* webkit_page_get_settings(WebKitPage* page)
685 g_return_val_if_fail(WEBKIT_IS_PAGE(page), NULL);
691 void webkit_page_go_backward(WebKitPage* page)
693 g_return_if_fail(WEBKIT_IS_PAGE(page));
695 WebKitPagePrivate* pageData = WEBKIT_PAGE_GET_PRIVATE(page);
696 WebKitFramePrivate* frameData = WEBKIT_FRAME_GET_PRIVATE(pageData->mainFrame);
697 frameData->frame->loader()->goBackOrForward(-1);
700 void webkit_page_go_forward(WebKitPage* page)
702 g_return_if_fail(WEBKIT_IS_PAGE(page));
704 WebKitPagePrivate* pageData = WEBKIT_PAGE_GET_PRIVATE(page);
705 WebKitFramePrivate* frameData = WEBKIT_FRAME_GET_PRIVATE(pageData->mainFrame);
706 frameData->frame->loader()->goBackOrForward(1);
709 gboolean webkit_page_can_go_backward(WebKitPage* page)
711 g_return_val_if_fail(WEBKIT_IS_PAGE(page), FALSE);
713 WebKitPagePrivate* pageData = WEBKIT_PAGE_GET_PRIVATE(page);
714 WebKitFramePrivate* frameData = WEBKIT_FRAME_GET_PRIVATE(pageData->mainFrame);
715 return frameData->frame->loader()->canGoBackOrForward(-1);
718 gboolean webkit_page_can_go_forward(WebKitPage* page)
720 g_return_val_if_fail(WEBKIT_IS_PAGE(page), FALSE);
722 WebKitPagePrivate* pageData = WEBKIT_PAGE_GET_PRIVATE(page);
723 WebKitFramePrivate* frameData = WEBKIT_FRAME_GET_PRIVATE(pageData->mainFrame);
724 return frameData->frame->loader()->canGoBackOrForward(1);
727 void webkit_page_open(WebKitPage* page, const gchar* uri)
729 g_return_if_fail(WEBKIT_IS_PAGE(page));
731 WebKitPagePrivate* pageData = WEBKIT_PAGE_GET_PRIVATE(page);
732 WebKitFramePrivate* frameData = WEBKIT_FRAME_GET_PRIVATE(pageData->mainFrame);
734 DeprecatedString string = DeprecatedString::fromUtf8(uri);
735 frameData->frame->loader()->load(ResourceRequest(KURL(string)));
738 void webkit_page_reload(WebKitPage* page)
740 g_return_if_fail(WEBKIT_IS_PAGE(page));
742 WebKitPagePrivate* pageData = WEBKIT_PAGE_GET_PRIVATE(page);
743 WebKitFramePrivate* frameData = WEBKIT_FRAME_GET_PRIVATE(pageData->mainFrame);
744 frameData->frame->loader()->reload();
747 void webkit_page_load_string(WebKitPage* page, const gchar* content, const gchar* contentMimeType, const gchar* contentEncoding, const gchar* baseUri)
749 g_return_if_fail(WEBKIT_IS_PAGE(page));
751 WebKitPagePrivate* pageData = WEBKIT_PAGE_GET_PRIVATE(page);
752 WebKitFramePrivate* frameData = WEBKIT_FRAME_GET_PRIVATE(pageData->mainFrame);
754 KURL url(DeprecatedString::fromUtf8(baseUri));
755 RefPtr<SharedBuffer> sharedBuffer = new SharedBuffer(strdup(content), strlen(content));
756 SubstituteData substituteData(sharedBuffer.release(), String(contentMimeType), String(contentEncoding), KURL("about:blank"), url);
758 frameData->frame->loader()->load(ResourceRequest(url), substituteData);
761 void webkit_page_load_html_string(WebKitPage* page, const gchar* content, const gchar* baseUrl)
763 g_return_if_fail(WEBKIT_IS_PAGE(page));
765 webkit_page_load_string(page, content, "text/html", "UTF-8", baseUrl);
768 void webkit_page_stop_loading(WebKitPage* page)
770 g_return_if_fail(WEBKIT_IS_PAGE(page));
772 WebKitPagePrivate* pageData = WEBKIT_PAGE_GET_PRIVATE(page);
773 WebKitFramePrivate* frameData = WEBKIT_FRAME_GET_PRIVATE(pageData->mainFrame);
775 if (FrameLoader* loader = frameData->frame->loader())
776 loader->stopAllLoaders();
779 WebKitFrame* webkit_page_get_main_frame(WebKitPage* page)
781 g_return_val_if_fail(WEBKIT_IS_PAGE(page), NULL);
783 WebKitPagePrivate* pageData = WEBKIT_PAGE_GET_PRIVATE(page);
784 return pageData->mainFrame;
787 void webkit_page_execute_script(WebKitPage* page, const gchar* script)
789 g_return_if_fail(WEBKIT_IS_PAGE(page));
790 g_return_if_fail(script);
792 WebKitPagePrivate* pageData = WEBKIT_PAGE_GET_PRIVATE(page);
793 WebKitFramePrivate* frameData = WEBKIT_FRAME_GET_PRIVATE(pageData->mainFrame);
795 if (FrameLoader* loader = frameData->frame->loader())
796 loader->executeScript(String::fromUTF8(script), true);
800 * webkit_page_get_editable:
801 * @page: a #WebKitPage
803 * Returns whether the user is allowed to edit the document.
805 * Returns %TRUE if @page allows the user to edit the HTML document, %FALSE if
806 * it doesn't. You can change @page's document programmatically regardless of
809 * Return value: a #gboolean indicating the editable state
811 gboolean webkit_page_get_editable(WebKitPage* page)
813 g_return_val_if_fail(WEBKIT_IS_PAGE(page), FALSE);
815 WebKitPagePrivate* pageData = WEBKIT_PAGE_GET_PRIVATE(page);
818 return pageData->editable;
822 * webkit_page_set_editable:
823 * @page: a #WebKitPage
824 * @flag: a #gboolean indicating the editable state
826 * Sets whether @page allows the user to edit its HTML document.
828 * If @flag is %TRUE, @page allows the user to edit the document. If @flag is
829 * %FALSE, an element in @page's document can only be edited if the
830 * CONTENTEDITABLE attribute has been set on the element or one of its parent
831 * elements. You can change @page's document programmatically regardless of
832 * this setting. By default a #WebKitPage is not editable.
834 * Normally, an HTML document is not editable unless the elements within the
835 * document are editable. This function provides a low-level way to make the
836 * contents of a #WebKitPage editable without altering the document or DOM
839 void webkit_page_set_editable(WebKitPage* page, gboolean flag)
841 g_return_if_fail(WEBKIT_IS_PAGE(page));
842 flag = flag != FALSE;
844 WebKitPagePrivate* pageData = WEBKIT_PAGE_GET_PRIVATE(page);
847 Frame* mainFrame = core(pageData->mainFrame);
848 g_return_if_fail(mainFrame);
850 // TODO: What happens when the frame is replaced?
851 if (flag == pageData->editable)
854 pageData->editable = flag;
857 mainFrame->applyEditingStyleToBodyElement();
858 // TODO: If the WebKitPage is made editable and the selection is empty, set it to something.
859 //if (!webkit_page_get_selected_dom_range(page))
860 // mainFrame->setSelectionFromNone();
862 mainFrame->removeEditingStyleFromBodyElement();