Don't eagerly set wxKeyEvent position fields.
[wxWidgets.git] / src / gtk / webview_webkit.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/webview_webkit.cpp
3 // Purpose: GTK WebKit backend for web view component
4 // Author: Marianne Gagnon, Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 2010 Marianne Gagnon, 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 // For compilers that support precompilation, includes "wx.h".
11 #include "wx/wxprec.h"
12
13 #if wxUSE_WEBVIEW && wxUSE_WEBVIEW_WEBKIT
14
15 #include "wx/stockitem.h"
16 #include "wx/gtk/webview_webkit.h"
17 #include "wx/gtk/control.h"
18 #include "wx/gtk/private.h"
19 #include "wx/filesys.h"
20 #include "wx/base64.h"
21 #include <webkit/webkit.h>
22
23 // ----------------------------------------------------------------------------
24 // GTK callbacks
25 // ----------------------------------------------------------------------------
26
27 extern "C"
28 {
29
30 static void
31 wxgtk_webview_webkit_load_status(GtkWidget* widget,
32 GParamSpec*,
33 wxWebViewWebKit *webKitCtrl)
34 {
35 // We can be called from webkit_web_view_dispose() during the window
36 // destruction, don't use half-destroyed object in this case.
37 if ( webKitCtrl->IsBeingDeleted() )
38 return;
39
40 wxString url = webKitCtrl->GetCurrentURL();
41
42 WebKitLoadStatus status;
43 g_object_get(G_OBJECT(widget), "load-status", &status, NULL);
44
45 wxString target; // TODO: get target (if possible)
46
47 if (status == WEBKIT_LOAD_FINISHED)
48 {
49 WebKitWebBackForwardList* hist = webkit_web_view_get_back_forward_list(WEBKIT_WEB_VIEW(widget));
50 WebKitWebHistoryItem* item = webkit_web_back_forward_list_get_current_item(hist);
51 //We have to check if we are actually storing history
52 //If the item isn't added we add it ourselves, it isn't added otherwise
53 //with a custom scheme.
54 if(WEBKIT_IS_WEB_HISTORY_ITEM(item) && webkit_web_history_item_get_uri(item) != url)
55 {
56 WebKitWebHistoryItem*
57 newitem = webkit_web_history_item_new_with_data
58 (
59 url.utf8_str(),
60 webKitCtrl->GetCurrentTitle().utf8_str()
61 );
62 webkit_web_back_forward_list_add_item(hist, newitem);
63 }
64
65 webKitCtrl->m_busy = false;
66 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_LOADED,
67 webKitCtrl->GetId(),
68 url, target);
69
70 if (webKitCtrl && webKitCtrl->GetEventHandler())
71 webKitCtrl->GetEventHandler()->ProcessEvent(event);
72 }
73 else if (status == WEBKIT_LOAD_COMMITTED)
74 {
75 webKitCtrl->m_busy = true;
76 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATED,
77 webKitCtrl->GetId(),
78 url, target);
79
80 if (webKitCtrl && webKitCtrl->GetEventHandler())
81 webKitCtrl->GetEventHandler()->ProcessEvent(event);
82 }
83 }
84
85 static gboolean
86 wxgtk_webview_webkit_navigation(WebKitWebView *,
87 WebKitWebFrame *frame,
88 WebKitNetworkRequest *request,
89 WebKitWebNavigationAction *,
90 WebKitWebPolicyDecision *policy_decision,
91 wxWebViewWebKit *webKitCtrl)
92 {
93 if(webKitCtrl->m_guard)
94 {
95 webKitCtrl->m_guard = false;
96 //We set this to make sure that we don't try to load the page again from
97 //the resource request callback
98 webKitCtrl->m_vfsurl = webkit_network_request_get_uri(request);
99 webkit_web_policy_decision_use(policy_decision);
100 return FALSE;
101 }
102
103 webKitCtrl->m_busy = true;
104
105 const gchar* uri = webkit_network_request_get_uri(request);
106
107 wxString target = webkit_web_frame_get_name (frame);
108 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATING,
109 webKitCtrl->GetId(),
110 wxString( uri, wxConvUTF8 ),
111 target);
112
113 if (webKitCtrl && webKitCtrl->GetEventHandler())
114 webKitCtrl->GetEventHandler()->ProcessEvent(event);
115
116 if (!event.IsAllowed())
117 {
118 webKitCtrl->m_busy = false;
119 webkit_web_policy_decision_ignore(policy_decision);
120 return TRUE;
121 }
122 else
123 {
124 wxString wxuri = uri;
125 wxSharedPtr<wxWebViewHandler> handler;
126 wxVector<wxSharedPtr<wxWebViewHandler> > hanlders = webKitCtrl->GetHandlers();
127 //We are not vetoed so see if we match one of the additional handlers
128 for(wxVector<wxSharedPtr<wxWebViewHandler> >::iterator it = hanlders.begin();
129 it != hanlders.end(); ++it)
130 {
131 if(wxuri.substr(0, (*it)->GetName().length()) == (*it)->GetName())
132 {
133 handler = (*it);
134 }
135 }
136 //If we found a handler we can then use it to load the file directly
137 //ourselves
138 if(handler)
139 {
140 webKitCtrl->m_guard = true;
141 wxFSFile* file = handler->GetFile(wxuri);
142 if(file)
143 {
144 webKitCtrl->SetPage(*file->GetStream(), wxuri);
145 }
146 //We need to throw some sort of error here if file is NULL
147 webkit_web_policy_decision_ignore(policy_decision);
148 return TRUE;
149 }
150 return FALSE;
151 }
152 }
153
154 static gboolean
155 wxgtk_webview_webkit_error(WebKitWebView*,
156 WebKitWebFrame*,
157 gchar *uri,
158 gpointer web_error,
159 wxWebViewWebKit* webKitWindow)
160 {
161 webKitWindow->m_busy = false;
162 wxWebViewNavigationError type = wxWEB_NAV_ERR_OTHER;
163
164 GError* error = (GError*)web_error;
165 wxString description(error->message, wxConvUTF8);
166
167 if (strcmp(g_quark_to_string(error->domain), "soup_http_error_quark") == 0)
168 {
169 switch (error->code)
170 {
171 case SOUP_STATUS_CANCELLED:
172 type = wxWEB_NAV_ERR_USER_CANCELLED;
173 break;
174
175 case SOUP_STATUS_CANT_RESOLVE:
176 case SOUP_STATUS_NOT_FOUND:
177 type = wxWEB_NAV_ERR_NOT_FOUND;
178 break;
179
180 case SOUP_STATUS_CANT_RESOLVE_PROXY:
181 case SOUP_STATUS_CANT_CONNECT:
182 case SOUP_STATUS_CANT_CONNECT_PROXY:
183 case SOUP_STATUS_SSL_FAILED:
184 case SOUP_STATUS_IO_ERROR:
185 type = wxWEB_NAV_ERR_CONNECTION;
186 break;
187
188 case SOUP_STATUS_MALFORMED:
189 //case SOUP_STATUS_TOO_MANY_REDIRECTS:
190 type = wxWEB_NAV_ERR_REQUEST;
191 break;
192
193 //case SOUP_STATUS_NO_CONTENT:
194 //case SOUP_STATUS_RESET_CONTENT:
195
196 case SOUP_STATUS_BAD_REQUEST:
197 type = wxWEB_NAV_ERR_REQUEST;
198 break;
199
200 case SOUP_STATUS_UNAUTHORIZED:
201 case SOUP_STATUS_FORBIDDEN:
202 type = wxWEB_NAV_ERR_AUTH;
203 break;
204
205 case SOUP_STATUS_METHOD_NOT_ALLOWED:
206 case SOUP_STATUS_NOT_ACCEPTABLE:
207 type = wxWEB_NAV_ERR_SECURITY;
208 break;
209
210 case SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED:
211 type = wxWEB_NAV_ERR_AUTH;
212 break;
213
214 case SOUP_STATUS_REQUEST_TIMEOUT:
215 type = wxWEB_NAV_ERR_CONNECTION;
216 break;
217
218 //case SOUP_STATUS_PAYMENT_REQUIRED:
219 case SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE:
220 case SOUP_STATUS_REQUEST_URI_TOO_LONG:
221 case SOUP_STATUS_UNSUPPORTED_MEDIA_TYPE:
222 type = wxWEB_NAV_ERR_REQUEST;
223 break;
224
225 case SOUP_STATUS_BAD_GATEWAY:
226 case SOUP_STATUS_SERVICE_UNAVAILABLE:
227 case SOUP_STATUS_GATEWAY_TIMEOUT:
228 type = wxWEB_NAV_ERR_CONNECTION;
229 break;
230
231 case SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED:
232 type = wxWEB_NAV_ERR_REQUEST;
233 break;
234 //case SOUP_STATUS_INSUFFICIENT_STORAGE:
235 //case SOUP_STATUS_NOT_EXTENDED:
236 }
237 }
238 else if (strcmp(g_quark_to_string(error->domain),
239 "webkit-network-error-quark") == 0)
240 {
241 switch (error->code)
242 {
243 //WEBKIT_NETWORK_ERROR_FAILED:
244 //WEBKIT_NETWORK_ERROR_TRANSPORT:
245
246 case WEBKIT_NETWORK_ERROR_UNKNOWN_PROTOCOL:
247 type = wxWEB_NAV_ERR_REQUEST;
248 break;
249
250 case WEBKIT_NETWORK_ERROR_CANCELLED:
251 type = wxWEB_NAV_ERR_USER_CANCELLED;
252 break;
253
254 case WEBKIT_NETWORK_ERROR_FILE_DOES_NOT_EXIST:
255 type = wxWEB_NAV_ERR_NOT_FOUND;
256 break;
257 }
258 }
259 else if (strcmp(g_quark_to_string(error->domain),
260 "webkit-policy-error-quark") == 0)
261 {
262 switch (error->code)
263 {
264 //case WEBKIT_POLICY_ERROR_FAILED:
265 //case WEBKIT_POLICY_ERROR_CANNOT_SHOW_MIME_TYPE:
266 //case WEBKIT_POLICY_ERROR_CANNOT_SHOW_URL:
267 //case WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE:
268 case WEBKIT_POLICY_ERROR_CANNOT_USE_RESTRICTED_PORT:
269 type = wxWEB_NAV_ERR_SECURITY;
270 break;
271 }
272 }
273 /*
274 webkit_plugin_error_quark
275 else
276 {
277 printf("Error domain %s\n", g_quark_to_string(error->domain));
278 }
279 */
280
281 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_ERROR,
282 webKitWindow->GetId(),
283 uri, "");
284 event.SetString(description);
285 event.SetInt(type);
286
287 if (webKitWindow && webKitWindow->GetEventHandler())
288 {
289 webKitWindow->GetEventHandler()->ProcessEvent(event);
290 }
291
292 return FALSE;
293 }
294
295 static gboolean
296 wxgtk_webview_webkit_new_window(WebKitWebView*,
297 WebKitWebFrame *frame,
298 WebKitNetworkRequest *request,
299 WebKitWebNavigationAction*,
300 WebKitWebPolicyDecision *policy_decision,
301 wxWebViewWebKit *webKitCtrl)
302 {
303 const gchar* uri = webkit_network_request_get_uri(request);
304
305 wxString target = webkit_web_frame_get_name (frame);
306 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NEWWINDOW,
307 webKitCtrl->GetId(),
308 wxString( uri, wxConvUTF8 ),
309 target);
310
311 if (webKitCtrl && webKitCtrl->GetEventHandler())
312 webKitCtrl->GetEventHandler()->ProcessEvent(event);
313
314 //We always want the user to handle this themselves
315 webkit_web_policy_decision_ignore(policy_decision);
316 return TRUE;
317 }
318
319 static void
320 wxgtk_webview_webkit_title_changed(WebKitWebView*,
321 WebKitWebFrame*,
322 gchar *title,
323 wxWebViewWebKit *webKitCtrl)
324 {
325 wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_TITLE_CHANGED,
326 webKitCtrl->GetId(),
327 webKitCtrl->GetCurrentURL(),
328 "");
329 event.SetString(wxString(title, wxConvUTF8));
330
331 if (webKitCtrl && webKitCtrl->GetEventHandler())
332 webKitCtrl->GetEventHandler()->ProcessEvent(event);
333
334 }
335
336 static void
337 wxgtk_webview_webkit_resource_req(WebKitWebView *,
338 WebKitWebFrame *,
339 WebKitWebResource *,
340 WebKitNetworkRequest *request,
341 WebKitNetworkResponse *,
342 wxWebViewWebKit *webKitCtrl)
343 {
344 wxString uri = webkit_network_request_get_uri(request);
345
346 wxSharedPtr<wxWebViewHandler> handler;
347 wxVector<wxSharedPtr<wxWebViewHandler> > hanlders = webKitCtrl->GetHandlers();
348
349 //We are not vetoed so see if we match one of the additional handlers
350 for(wxVector<wxSharedPtr<wxWebViewHandler> >::iterator it = hanlders.begin();
351 it != hanlders.end(); ++it)
352 {
353 if(uri.substr(0, (*it)->GetName().length()) == (*it)->GetName())
354 {
355 handler = (*it);
356 }
357 }
358 //If we found a handler we can then use it to load the file directly
359 //ourselves
360 if(handler)
361 {
362 //If it is requsting the page itself then return as we have already
363 //loaded it from the archive
364 if(webKitCtrl->m_vfsurl == uri)
365 return;
366
367 wxFSFile* file = handler->GetFile(uri);
368 if(file)
369 {
370 //We load the data into a data url to save it being written out again
371 size_t size = file->GetStream()->GetLength();
372 char *buffer = new char[size];
373 file->GetStream()->Read(buffer, size);
374 wxString data = wxBase64Encode(buffer, size);
375 delete[] buffer;
376 wxString mime = file->GetMimeType();
377 wxString path = "data:" + mime + ";base64," + data;
378 //Then we can redirect the call
379 webkit_network_request_set_uri(request, path.utf8_str());
380 }
381
382 }
383 }
384
385 } // extern "C"
386
387 //-----------------------------------------------------------------------------
388 // wxWebViewWebKit
389 //-----------------------------------------------------------------------------
390
391 wxIMPLEMENT_DYNAMIC_CLASS(wxWebViewWebKit, wxWebView);
392
393 bool wxWebViewWebKit::Create(wxWindow *parent,
394 wxWindowID id,
395 const wxString &url,
396 const wxPoint& pos,
397 const wxSize& size,
398 long style,
399 const wxString& name)
400 {
401 m_busy = false;
402 m_guard = false;
403
404 // We currently unconditionally impose scrolling in both directions as it's
405 // necessary to show arbitrary pages.
406 style |= wxHSCROLL | wxVSCROLL;
407
408 if (!PreCreation( parent, pos, size ) ||
409 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
410 {
411 wxFAIL_MSG( wxT("wxWebViewWebKit creation failed") );
412 return false;
413 }
414
415 m_web_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
416 GTKCreateScrolledWindowWith(GTK_WIDGET(m_web_view));
417 g_object_ref(m_widget);
418
419 g_signal_connect_after(m_web_view, "navigation-policy-decision-requested",
420 G_CALLBACK(wxgtk_webview_webkit_navigation),
421 this);
422 g_signal_connect_after(m_web_view, "load-error",
423 G_CALLBACK(wxgtk_webview_webkit_error),
424 this);
425
426 g_signal_connect_after(m_web_view, "new-window-policy-decision-requested",
427 G_CALLBACK(wxgtk_webview_webkit_new_window), this);
428
429 g_signal_connect_after(m_web_view, "title-changed",
430 G_CALLBACK(wxgtk_webview_webkit_title_changed), this);
431
432 g_signal_connect_after(m_web_view, "resource-request-starting",
433 G_CALLBACK(wxgtk_webview_webkit_resource_req), this);
434
435 m_parent->DoAddChild( this );
436
437 PostCreation(size);
438
439 /* Open a webpage */
440 webkit_web_view_load_uri(m_web_view, url.utf8_str());
441
442 //Get the initial history limit so we can enable and disable it later
443 WebKitWebBackForwardList* history;
444 history = webkit_web_view_get_back_forward_list(m_web_view);
445 m_historyLimit = webkit_web_back_forward_list_get_limit(history);
446
447 // last to avoid getting signal too early
448 g_signal_connect_after(m_web_view, "notify::load-status",
449 G_CALLBACK(wxgtk_webview_webkit_load_status),
450 this);
451
452 return true;
453 }
454
455 wxWebViewWebKit::~wxWebViewWebKit()
456 {
457 // The main goal here is to set m_isBeingDeleted to true to avoid the use
458 // of this -- already half-destroyed -- object from WebKit callbacks, but
459 // just setting it would prevent wxWindowDestroyEvent from being sent, so
460 // send it now instead.
461 SendDestroyEvent();
462 }
463
464 bool wxWebViewWebKit::Enable( bool enable )
465 {
466 if (!wxControl::Enable(enable))
467 return false;
468
469 gtk_widget_set_sensitive(gtk_bin_get_child(GTK_BIN(m_widget)), enable);
470
471 //if (enable)
472 // GTKFixSensitivity();
473
474 return true;
475 }
476
477 GdkWindow*
478 wxWebViewWebKit::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
479 {
480 GdkWindow* window = gtk_widget_get_parent_window(m_widget);
481 return window;
482 }
483
484 void wxWebViewWebKit::ZoomIn()
485 {
486 webkit_web_view_zoom_in(m_web_view);
487 }
488
489 void wxWebViewWebKit::ZoomOut()
490 {
491 webkit_web_view_zoom_out(m_web_view);
492 }
493
494 void wxWebViewWebKit::SetWebkitZoom(float level)
495 {
496 webkit_web_view_set_zoom_level(m_web_view, level);
497 }
498
499 float wxWebViewWebKit::GetWebkitZoom() const
500 {
501 return webkit_web_view_get_zoom_level(m_web_view);
502 }
503
504 void wxWebViewWebKit::Stop()
505 {
506 webkit_web_view_stop_loading(m_web_view);
507 }
508
509 void wxWebViewWebKit::Reload(wxWebViewReloadFlags flags)
510 {
511 if (flags & wxWEB_VIEW_RELOAD_NO_CACHE)
512 {
513 webkit_web_view_reload_bypass_cache(m_web_view);
514 }
515 else
516 {
517 webkit_web_view_reload(m_web_view);
518 }
519 }
520
521 void wxWebViewWebKit::LoadURL(const wxString& url)
522 {
523 webkit_web_view_load_uri(m_web_view, wxGTK_CONV(url));
524 }
525
526
527 void wxWebViewWebKit::GoBack()
528 {
529 webkit_web_view_go_back(m_web_view);
530 }
531
532 void wxWebViewWebKit::GoForward()
533 {
534 webkit_web_view_go_forward(m_web_view);
535 }
536
537
538 bool wxWebViewWebKit::CanGoBack() const
539 {
540 return webkit_web_view_can_go_back(m_web_view);
541 }
542
543
544 bool wxWebViewWebKit::CanGoForward() const
545 {
546 return webkit_web_view_can_go_forward(m_web_view);
547 }
548
549 void wxWebViewWebKit::ClearHistory()
550 {
551 WebKitWebBackForwardList* history;
552 history = webkit_web_view_get_back_forward_list(m_web_view);
553 webkit_web_back_forward_list_clear(history);
554 }
555
556 void wxWebViewWebKit::EnableHistory(bool enable)
557 {
558 WebKitWebBackForwardList* history;
559 history = webkit_web_view_get_back_forward_list(m_web_view);
560 if(enable)
561 {
562 webkit_web_back_forward_list_set_limit(history, m_historyLimit);
563 }
564 else
565 {
566 webkit_web_back_forward_list_set_limit(history, 0);
567 }
568 }
569
570 wxVector<wxSharedPtr<wxWebViewHistoryItem> > wxWebViewWebKit::GetBackwardHistory()
571 {
572 wxVector<wxSharedPtr<wxWebViewHistoryItem> > backhist;
573 WebKitWebBackForwardList* history;
574 history = webkit_web_view_get_back_forward_list(m_web_view);
575 GList* list = webkit_web_back_forward_list_get_back_list_with_limit(history,
576 m_historyLimit);
577 //We need to iterate in reverse to get the order we desire
578 for(int i = g_list_length(list) - 1; i >= 0 ; i--)
579 {
580 WebKitWebHistoryItem* gtkitem = (WebKitWebHistoryItem*)g_list_nth_data(list, i);
581 wxWebViewHistoryItem* wxitem = new wxWebViewHistoryItem(
582 webkit_web_history_item_get_uri(gtkitem),
583 webkit_web_history_item_get_title(gtkitem));
584 wxitem->m_histItem = gtkitem;
585 wxSharedPtr<wxWebViewHistoryItem> item(wxitem);
586 backhist.push_back(item);
587 }
588 return backhist;
589 }
590
591 wxVector<wxSharedPtr<wxWebViewHistoryItem> > wxWebViewWebKit::GetForwardHistory()
592 {
593 wxVector<wxSharedPtr<wxWebViewHistoryItem> > forwardhist;
594 WebKitWebBackForwardList* history;
595 history = webkit_web_view_get_back_forward_list(m_web_view);
596 GList* list = webkit_web_back_forward_list_get_forward_list_with_limit(history,
597 m_historyLimit);
598 for(guint i = 0; i < g_list_length(list); i++)
599 {
600 WebKitWebHistoryItem* gtkitem = (WebKitWebHistoryItem*)g_list_nth_data(list, i);
601 wxWebViewHistoryItem* wxitem = new wxWebViewHistoryItem(
602 webkit_web_history_item_get_uri(gtkitem),
603 webkit_web_history_item_get_title(gtkitem));
604 wxitem->m_histItem = gtkitem;
605 wxSharedPtr<wxWebViewHistoryItem> item(wxitem);
606 forwardhist.push_back(item);
607 }
608 return forwardhist;
609 }
610
611 void wxWebViewWebKit::LoadHistoryItem(wxSharedPtr<wxWebViewHistoryItem> item)
612 {
613 WebKitWebHistoryItem* gtkitem = (WebKitWebHistoryItem*)item->m_histItem;
614 if(gtkitem)
615 {
616 webkit_web_view_go_to_back_forward_item(m_web_view,
617 WEBKIT_WEB_HISTORY_ITEM(gtkitem));
618 }
619 }
620
621 bool wxWebViewWebKit::CanCut() const
622 {
623 return webkit_web_view_can_cut_clipboard(m_web_view);
624 }
625
626 bool wxWebViewWebKit::CanCopy() const
627 {
628 return webkit_web_view_can_copy_clipboard(m_web_view);
629 }
630
631 bool wxWebViewWebKit::CanPaste() const
632 {
633 return webkit_web_view_can_paste_clipboard(m_web_view);
634 }
635
636 void wxWebViewWebKit::Cut()
637 {
638 webkit_web_view_cut_clipboard(m_web_view);
639 }
640
641 void wxWebViewWebKit::Copy()
642 {
643 webkit_web_view_copy_clipboard(m_web_view);
644 }
645
646 void wxWebViewWebKit::Paste()
647 {
648 webkit_web_view_paste_clipboard(m_web_view);
649 }
650
651 bool wxWebViewWebKit::CanUndo() const
652 {
653 return webkit_web_view_can_undo(m_web_view);
654 }
655
656 bool wxWebViewWebKit::CanRedo() const
657 {
658 return webkit_web_view_can_redo(m_web_view);
659 }
660
661 void wxWebViewWebKit::Undo()
662 {
663 webkit_web_view_undo(m_web_view);
664 }
665
666 void wxWebViewWebKit::Redo()
667 {
668 webkit_web_view_redo(m_web_view);
669 }
670
671 wxString wxWebViewWebKit::GetCurrentURL() const
672 {
673 // FIXME: check which encoding the web kit control uses instead of
674 // assuming UTF8 (here and elsewhere too)
675 return wxString::FromUTF8(webkit_web_view_get_uri(m_web_view));
676 }
677
678
679 wxString wxWebViewWebKit::GetCurrentTitle() const
680 {
681 return wxString::FromUTF8(webkit_web_view_get_title(m_web_view));
682 }
683
684
685 wxString wxWebViewWebKit::GetPageSource() const
686 {
687 WebKitWebFrame* frame = webkit_web_view_get_main_frame(m_web_view);
688 WebKitWebDataSource* src = webkit_web_frame_get_data_source (frame);
689
690 // TODO: check encoding with
691 // const gchar*
692 // webkit_web_data_source_get_encoding(WebKitWebDataSource *data_source);
693 return wxString(webkit_web_data_source_get_data (src)->str, wxConvUTF8);
694 }
695
696
697 wxWebViewZoom wxWebViewWebKit::GetZoom() const
698 {
699 float zoom = GetWebkitZoom();
700
701 // arbitrary way to map float zoom to our common zoom enum
702 if (zoom <= 0.65)
703 {
704 return wxWEB_VIEW_ZOOM_TINY;
705 }
706 else if (zoom > 0.65 && zoom <= 0.90)
707 {
708 return wxWEB_VIEW_ZOOM_SMALL;
709 }
710 else if (zoom > 0.90 && zoom <= 1.15)
711 {
712 return wxWEB_VIEW_ZOOM_MEDIUM;
713 }
714 else if (zoom > 1.15 && zoom <= 1.45)
715 {
716 return wxWEB_VIEW_ZOOM_LARGE;
717 }
718 else if (zoom > 1.45)
719 {
720 return wxWEB_VIEW_ZOOM_LARGEST;
721 }
722
723 // to shut up compilers, this can never be reached logically
724 wxASSERT(false);
725 return wxWEB_VIEW_ZOOM_MEDIUM;
726 }
727
728
729 void wxWebViewWebKit::SetZoom(wxWebViewZoom zoom)
730 {
731 // arbitrary way to map our common zoom enum to float zoom
732 switch (zoom)
733 {
734 case wxWEB_VIEW_ZOOM_TINY:
735 SetWebkitZoom(0.6f);
736 break;
737
738 case wxWEB_VIEW_ZOOM_SMALL:
739 SetWebkitZoom(0.8f);
740 break;
741
742 case wxWEB_VIEW_ZOOM_MEDIUM:
743 SetWebkitZoom(1.0f);
744 break;
745
746 case wxWEB_VIEW_ZOOM_LARGE:
747 SetWebkitZoom(1.3);
748 break;
749
750 case wxWEB_VIEW_ZOOM_LARGEST:
751 SetWebkitZoom(1.6);
752 break;
753
754 default:
755 wxASSERT(false);
756 }
757 }
758
759 void wxWebViewWebKit::SetZoomType(wxWebViewZoomType type)
760 {
761 webkit_web_view_set_full_content_zoom(m_web_view,
762 (type == wxWEB_VIEW_ZOOM_TYPE_LAYOUT ?
763 TRUE : FALSE));
764 }
765
766 wxWebViewZoomType wxWebViewWebKit::GetZoomType() const
767 {
768 gboolean fczoom = webkit_web_view_get_full_content_zoom(m_web_view);
769
770 if (fczoom) return wxWEB_VIEW_ZOOM_TYPE_LAYOUT;
771 else return wxWEB_VIEW_ZOOM_TYPE_TEXT;
772 }
773
774 bool wxWebViewWebKit::CanSetZoomType(wxWebViewZoomType) const
775 {
776 // this port supports all zoom types
777 return true;
778 }
779
780 void wxWebViewWebKit::DoSetPage(const wxString& html, const wxString& baseUri)
781 {
782 webkit_web_view_load_string (m_web_view,
783 html.mb_str(wxConvUTF8),
784 "text/html",
785 "UTF-8",
786 baseUri.mb_str(wxConvUTF8));
787 }
788
789 void wxWebViewWebKit::Print()
790 {
791 WebKitWebFrame* frame = webkit_web_view_get_main_frame(m_web_view);
792 webkit_web_frame_print (frame);
793
794 // GtkPrintOperationResult webkit_web_frame_print_full
795 // (WebKitWebFrame *frame,
796 // GtkPrintOperation *operation,
797 // GtkPrintOperationAction action,
798 // GError **error);
799
800 }
801
802
803 bool wxWebViewWebKit::IsBusy() const
804 {
805 return m_busy;
806
807 // This code looks nice but returns true after a page was cancelled
808 /*
809 WebKitLoadStatus status = webkit_web_view_get_load_status
810 (WEBKIT_WEB_VIEW(web_view));
811
812
813 #if WEBKIT_CHECK_VERSION(1,1,16)
814 // WEBKIT_LOAD_FAILED is new in webkit 1.1.16
815 if (status == WEBKIT_LOAD_FAILED)
816 {
817 return false;
818 }
819 #endif
820 if (status == WEBKIT_LOAD_FINISHED)
821 {
822 return false;
823 }
824
825 return true;
826 */
827 }
828
829 void wxWebViewWebKit::SetEditable(bool enable)
830 {
831 webkit_web_view_set_editable(m_web_view, enable);
832 }
833
834 bool wxWebViewWebKit::IsEditable() const
835 {
836 return webkit_web_view_get_editable(m_web_view);
837 }
838
839 void wxWebViewWebKit::DeleteSelection()
840 {
841 webkit_web_view_delete_selection(m_web_view);
842 }
843
844 bool wxWebViewWebKit::HasSelection() const
845 {
846 return webkit_web_view_has_selection(m_web_view);
847 }
848
849 void wxWebViewWebKit::SelectAll()
850 {
851 webkit_web_view_select_all(m_web_view);
852 }
853
854 wxString wxWebViewWebKit::GetSelectedText() const
855 {
856 WebKitDOMDocument* doc;
857 WebKitDOMDOMWindow* win;
858 WebKitDOMDOMSelection* sel;
859 WebKitDOMRange* range;
860
861 doc = webkit_web_view_get_dom_document(m_web_view);
862 win = webkit_dom_document_get_default_view(WEBKIT_DOM_DOCUMENT(doc));
863 sel = webkit_dom_dom_window_get_selection(WEBKIT_DOM_DOM_WINDOW(win));
864 range = webkit_dom_dom_selection_get_range_at(WEBKIT_DOM_DOM_SELECTION(sel),
865 0, NULL);
866 return wxString(webkit_dom_range_get_text(WEBKIT_DOM_RANGE(range)),
867 wxConvUTF8);
868 }
869
870 wxString wxWebViewWebKit::GetSelectedSource() const
871 {
872 WebKitDOMDocument* doc;
873 WebKitDOMDOMWindow* win;
874 WebKitDOMDOMSelection* sel;
875 WebKitDOMRange* range;
876 WebKitDOMElement* div;
877 WebKitDOMDocumentFragment* clone;
878 WebKitDOMHTMLElement* html;
879
880 doc = webkit_web_view_get_dom_document(m_web_view);
881 win = webkit_dom_document_get_default_view(WEBKIT_DOM_DOCUMENT(doc));
882 sel = webkit_dom_dom_window_get_selection(WEBKIT_DOM_DOM_WINDOW(win));
883 range = webkit_dom_dom_selection_get_range_at(WEBKIT_DOM_DOM_SELECTION(sel),
884 0, NULL);
885 div = webkit_dom_document_create_element(WEBKIT_DOM_DOCUMENT(doc), "div", NULL);
886
887 clone = webkit_dom_range_clone_contents(WEBKIT_DOM_RANGE(range), NULL);
888 webkit_dom_node_append_child(&div->parent_instance, &clone->parent_instance, NULL);
889 html = (WebKitDOMHTMLElement*)div;
890
891 return wxString(webkit_dom_html_element_get_inner_html(WEBKIT_DOM_HTML_ELEMENT(html)),
892 wxConvUTF8);
893 }
894
895 void wxWebViewWebKit::ClearSelection()
896 {
897 WebKitDOMDocument* doc;
898 WebKitDOMDOMWindow* win;
899 WebKitDOMDOMSelection* sel;
900
901 doc = webkit_web_view_get_dom_document(m_web_view);
902 win = webkit_dom_document_get_default_view(WEBKIT_DOM_DOCUMENT(doc));
903 sel = webkit_dom_dom_window_get_selection(WEBKIT_DOM_DOM_WINDOW(win));
904 webkit_dom_dom_selection_remove_all_ranges(WEBKIT_DOM_DOM_SELECTION(sel));
905
906 }
907
908 wxString wxWebViewWebKit::GetPageText() const
909 {
910 WebKitDOMDocument* doc;
911 WebKitDOMHTMLElement* body;
912
913 doc = webkit_web_view_get_dom_document(m_web_view);
914 body = webkit_dom_document_get_body(WEBKIT_DOM_DOCUMENT(doc));
915 return wxString(webkit_dom_html_element_get_inner_text(WEBKIT_DOM_HTML_ELEMENT(body)),
916 wxConvUTF8);
917 }
918
919 void wxWebViewWebKit::RunScript(const wxString& javascript)
920 {
921 webkit_web_view_execute_script(m_web_view,
922 javascript.mb_str(wxConvUTF8));
923 }
924
925 void wxWebViewWebKit::RegisterHandler(wxSharedPtr<wxWebViewHandler> handler)
926 {
927 m_handlerList.push_back(handler);
928 }
929
930 // static
931 wxVisualAttributes
932 wxWebViewWebKit::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
933 {
934 return GetDefaultAttributesFromGTKWidget(webkit_web_view_new);
935 }
936
937
938 #endif // wxUSE_WEBVIEW && wxUSE_WEBVIEW_WEBKIT