X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b5374b5cfa33cca0053761178fedcba1ddc7a5d9..14722c43c30918cd8fbba956b50ac3426d2fe339:/src/gtk/webview_webkit.cpp?ds=inline diff --git a/src/gtk/webview_webkit.cpp b/src/gtk/webview_webkit.cpp index b838f79d9d..278f445f59 100644 --- a/src/gtk/webview_webkit.cpp +++ b/src/gtk/webview_webkit.cpp @@ -10,13 +10,15 @@ // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" -#if wxUSE_WEBVIEW_WEBKIT +#if wxUSE_WEBVIEW && wxUSE_WEBVIEW_WEBKIT #include "wx/stockitem.h" #include "wx/gtk/webview_webkit.h" #include "wx/gtk/control.h" #include "wx/gtk/private.h" -#include "webkit/webkit.h" +#include "wx/filesys.h" +#include "wx/base64.h" +#include // ---------------------------------------------------------------------------- // GTK callbacks @@ -26,10 +28,14 @@ extern "C" { static void -wxgtk_webkitctrl_load_status_callback(GtkWidget* widget, GParamSpec* arg1, - wxWebViewWebKit *webKitCtrl) +wxgtk_webview_webkit_load_status(GtkWidget* widget, + GParamSpec*, + wxWebViewWebKit *webKitCtrl) { - if (!webKitCtrl->m_ready) return; + // We can be called from webkit_web_view_dispose() during the window + // destruction, don't use half-destroyed object in this case. + if ( webKitCtrl->IsBeingDeleted() ) + return; wxString url = webKitCtrl->GetCurrentURL(); @@ -40,66 +46,120 @@ wxgtk_webkitctrl_load_status_callback(GtkWidget* widget, GParamSpec* arg1, if (status == WEBKIT_LOAD_FINISHED) { + WebKitWebBackForwardList* hist = webkit_web_view_get_back_forward_list(WEBKIT_WEB_VIEW(widget)); + WebKitWebHistoryItem* item = webkit_web_back_forward_list_get_current_item(hist); + //We have to check if we are actually storing history + //If the item isn't added we add it ourselves, it isn't added otherwise + //with a custom scheme. + if(WEBKIT_IS_WEB_HISTORY_ITEM(item) && webkit_web_history_item_get_uri(item) != url) + { + WebKitWebHistoryItem* + newitem = webkit_web_history_item_new_with_data + ( + url.utf8_str(), + webKitCtrl->GetCurrentTitle().utf8_str() + ); + webkit_web_back_forward_list_add_item(hist, newitem); + } + webKitCtrl->m_busy = false; - wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_LOADED, - webKitCtrl->GetId(), - url, target, false); + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_LOADED, + webKitCtrl->GetId(), + url, target); if (webKitCtrl && webKitCtrl->GetEventHandler()) - webKitCtrl->GetEventHandler()->ProcessEvent(thisEvent); + webKitCtrl->GetEventHandler()->ProcessEvent(event); } else if (status == WEBKIT_LOAD_COMMITTED) { webKitCtrl->m_busy = true; - wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_NAVIGATED, - webKitCtrl->GetId(), - url, target, false); + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATED, + webKitCtrl->GetId(), + url, target); if (webKitCtrl && webKitCtrl->GetEventHandler()) - webKitCtrl->GetEventHandler()->ProcessEvent(thisEvent); + webKitCtrl->GetEventHandler()->ProcessEvent(event); } } -static WebKitNavigationResponse -wxgtk_webkitctrl_navigation_requ_callback(WebKitWebView *web_view, - WebKitWebFrame *frame, - WebKitNetworkRequest *request, - wxWebViewWebKit *webKitCtrl) +static gboolean +wxgtk_webview_webkit_navigation(WebKitWebView *, + WebKitWebFrame *frame, + WebKitNetworkRequest *request, + WebKitWebNavigationAction *, + WebKitWebPolicyDecision *policy_decision, + wxWebViewWebKit *webKitCtrl) { + if(webKitCtrl->m_guard) + { + webKitCtrl->m_guard = false; + //We set this to make sure that we don't try to load the page again from + //the resource request callback + webKitCtrl->m_vfsurl = webkit_network_request_get_uri(request); + webkit_web_policy_decision_use(policy_decision); + return FALSE; + } + webKitCtrl->m_busy = true; const gchar* uri = webkit_network_request_get_uri(request); wxString target = webkit_web_frame_get_name (frame); - wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_NAVIGATING, - webKitCtrl->GetId(), - wxString( uri, wxConvUTF8 ), - target, - true); + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATING, + webKitCtrl->GetId(), + wxString( uri, wxConvUTF8 ), + target); if (webKitCtrl && webKitCtrl->GetEventHandler()) - webKitCtrl->GetEventHandler()->ProcessEvent(thisEvent); + webKitCtrl->GetEventHandler()->ProcessEvent(event); - if (thisEvent.IsVetoed()) + if (!event.IsAllowed()) { webKitCtrl->m_busy = false; - return WEBKIT_NAVIGATION_RESPONSE_IGNORE; + webkit_web_policy_decision_ignore(policy_decision); + return TRUE; } else { - return WEBKIT_NAVIGATION_RESPONSE_ACCEPT; + wxString wxuri = uri; + wxSharedPtr handler; + wxVector > hanlders = webKitCtrl->GetHandlers(); + //We are not vetoed so see if we match one of the additional handlers + for(wxVector >::iterator it = hanlders.begin(); + it != hanlders.end(); ++it) + { + if(wxuri.substr(0, (*it)->GetName().length()) == (*it)->GetName()) + { + handler = (*it); + } + } + //If we found a handler we can then use it to load the file directly + //ourselves + if(handler) + { + webKitCtrl->m_guard = true; + wxFSFile* file = handler->GetFile(wxuri); + if(file) + { + webKitCtrl->SetPage(*file->GetStream(), wxuri); + } + //We need to throw some sort of error here if file is NULL + webkit_web_policy_decision_ignore(policy_decision); + return TRUE; + } + return FALSE; } } static gboolean -wxgtk_webkitctrl_error (WebKitWebView *web_view, - WebKitWebFrame *web_frame, - gchar *uri, - gpointer web_error, - wxWebViewWebKit* webKitWindow) +wxgtk_webview_webkit_error(WebKitWebView*, + WebKitWebFrame*, + gchar *uri, + gpointer web_error, + wxWebViewWebKit* webKitWindow) { webKitWindow->m_busy = false; - wxWebNavigationError type = wxWEB_NAV_ERR_OTHER; + wxWebViewNavigationError type = wxWEB_NAV_ERR_OTHER; GError* error = (GError*)web_error; wxString description(error->message, wxConvUTF8); @@ -218,22 +278,109 @@ wxgtk_webkitctrl_error (WebKitWebView *web_view, } */ - wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_ERROR, - webKitWindow->GetId(), - uri, - wxEmptyString, - false); - thisEvent.SetString(description); - thisEvent.SetInt(type); + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_ERROR, + webKitWindow->GetId(), + uri, ""); + event.SetString(description); + event.SetInt(type); if (webKitWindow && webKitWindow->GetEventHandler()) { - webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); + webKitWindow->GetEventHandler()->ProcessEvent(event); } return FALSE; } +static gboolean +wxgtk_webview_webkit_new_window(WebKitWebView*, + WebKitWebFrame *frame, + WebKitNetworkRequest *request, + WebKitWebNavigationAction*, + WebKitWebPolicyDecision *policy_decision, + wxWebViewWebKit *webKitCtrl) +{ + const gchar* uri = webkit_network_request_get_uri(request); + + wxString target = webkit_web_frame_get_name (frame); + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_NEWWINDOW, + webKitCtrl->GetId(), + wxString( uri, wxConvUTF8 ), + target); + + if (webKitCtrl && webKitCtrl->GetEventHandler()) + webKitCtrl->GetEventHandler()->ProcessEvent(event); + + //We always want the user to handle this themselves + webkit_web_policy_decision_ignore(policy_decision); + return TRUE; +} + +static void +wxgtk_webview_webkit_title_changed(WebKitWebView*, + WebKitWebFrame*, + gchar *title, + wxWebViewWebKit *webKitCtrl) +{ + wxWebViewEvent event(wxEVT_COMMAND_WEB_VIEW_TITLE_CHANGED, + webKitCtrl->GetId(), + webKitCtrl->GetCurrentURL(), + ""); + event.SetString(wxString(title, wxConvUTF8)); + + if (webKitCtrl && webKitCtrl->GetEventHandler()) + webKitCtrl->GetEventHandler()->ProcessEvent(event); + +} + +static void +wxgtk_webview_webkit_resource_req(WebKitWebView *, + WebKitWebFrame *, + WebKitWebResource *, + WebKitNetworkRequest *request, + WebKitNetworkResponse *, + wxWebViewWebKit *webKitCtrl) +{ + wxString uri = webkit_network_request_get_uri(request); + + wxSharedPtr handler; + wxVector > hanlders = webKitCtrl->GetHandlers(); + + //We are not vetoed so see if we match one of the additional handlers + for(wxVector >::iterator it = hanlders.begin(); + it != hanlders.end(); ++it) + { + if(uri.substr(0, (*it)->GetName().length()) == (*it)->GetName()) + { + handler = (*it); + } + } + //If we found a handler we can then use it to load the file directly + //ourselves + if(handler) + { + //If it is requsting the page itself then return as we have already + //loaded it from the archive + if(webKitCtrl->m_vfsurl == uri) + return; + + wxFSFile* file = handler->GetFile(uri); + if(file) + { + //We load the data into a data url to save it being written out again + size_t size = file->GetStream()->GetLength(); + char *buffer = new char[size]; + file->GetStream()->Read(buffer, size); + wxString data = wxBase64Encode(buffer, size); + delete[] buffer; + wxString mime = file->GetMimeType(); + wxString path = "data:" + mime + ";base64," + data; + //Then we can redirect the call + webkit_network_request_set_uri(request, path.utf8_str()); + } + + } +} } // extern "C" @@ -241,7 +388,7 @@ wxgtk_webkitctrl_error (WebKitWebView *web_view, // wxWebViewWebKit //----------------------------------------------------------------------------- -//IMPLEMENT_DYNAMIC_CLASS(wxWebViewWebKit, wxControl) +wxIMPLEMENT_DYNAMIC_CLASS(wxWebViewWebKit, wxWebView); bool wxWebViewWebKit::Create(wxWindow *parent, wxWindowID id, @@ -251,8 +398,13 @@ bool wxWebViewWebKit::Create(wxWindow *parent, long style, const wxString& name) { - m_ready = false; m_busy = false; + m_guard = false; + FindClear(); + + // We currently unconditionally impose scrolling in both directions as it's + // necessary to show arbitrary pages. + style |= wxHSCROLL | wxVSCROLL; if (!PreCreation( parent, pos, size ) || !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name )) @@ -261,50 +413,61 @@ bool wxWebViewWebKit::Create(wxWindow *parent, return false; } - GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL); - web_view = webkit_web_view_new (); - g_object_ref(web_view); // TODO: check memory management - - m_widget = scrolled_window; - g_object_ref(m_widget); // TODO: check memory management - - /* Place the WebKitWebView in the GtkScrolledWindow */ - gtk_container_add (GTK_CONTAINER (scrolled_window), web_view); - gtk_widget_show(m_widget); - gtk_widget_show(web_view); + m_web_view = WEBKIT_WEB_VIEW(webkit_web_view_new()); + GTKCreateScrolledWindowWith(GTK_WIDGET(m_web_view)); + g_object_ref(m_widget); - g_signal_connect_after(web_view, "notify::load-status", - G_CALLBACK(wxgtk_webkitctrl_load_status_callback), + g_signal_connect_after(m_web_view, "navigation-policy-decision-requested", + G_CALLBACK(wxgtk_webview_webkit_navigation), this); - g_signal_connect_after(web_view, "navigation-requested", - G_CALLBACK(wxgtk_webkitctrl_navigation_requ_callback), - this); - g_signal_connect_after(web_view, "load-error", - G_CALLBACK(wxgtk_webkitctrl_error), + g_signal_connect_after(m_web_view, "load-error", + G_CALLBACK(wxgtk_webview_webkit_error), this); - // this signal can be added if we care about new frames open requests - //g_signal_connect_after(web_view, "new-window-policy-decision-requested", - // G_CALLBACK(...), this); + g_signal_connect_after(m_web_view, "new-window-policy-decision-requested", + G_CALLBACK(wxgtk_webview_webkit_new_window), this); + + g_signal_connect_after(m_web_view, "title-changed", + G_CALLBACK(wxgtk_webview_webkit_title_changed), this); + + g_signal_connect_after(m_web_view, "resource-request-starting", + G_CALLBACK(wxgtk_webview_webkit_resource_req), this); m_parent->DoAddChild( this ); PostCreation(size); /* Open a webpage */ - webkit_web_view_load_uri (WEBKIT_WEB_VIEW (web_view), url); + webkit_web_view_load_uri(m_web_view, url.utf8_str()); - m_ready = true; + //Get the initial history limit so we can enable and disable it later + WebKitWebBackForwardList* history; + history = webkit_web_view_get_back_forward_list(m_web_view); + m_historyLimit = webkit_web_back_forward_list_get_limit(history); + + // last to avoid getting signal too early + g_signal_connect_after(m_web_view, "notify::load-status", + G_CALLBACK(wxgtk_webview_webkit_load_status), + this); return true; } +wxWebViewWebKit::~wxWebViewWebKit() +{ + // The main goal here is to set m_isBeingDeleted to true to avoid the use + // of this -- already half-destroyed -- object from WebKit callbacks, but + // just setting it would prevent wxWindowDestroyEvent from being sent, so + // send it now instead. + SendDestroyEvent(); +} + bool wxWebViewWebKit::Enable( bool enable ) { if (!wxControl::Enable(enable)) return false; - gtk_widget_set_sensitive(GTK_BIN(m_widget)->child, enable); + gtk_widget_set_sensitive(gtk_bin_get_child(GTK_BIN(m_widget)), enable); //if (enable) // GTKFixSensitivity(); @@ -321,90 +484,208 @@ wxWebViewWebKit::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const void wxWebViewWebKit::ZoomIn() { - webkit_web_view_zoom_in (WEBKIT_WEB_VIEW(web_view)); + webkit_web_view_zoom_in(m_web_view); } void wxWebViewWebKit::ZoomOut() { - webkit_web_view_zoom_out (WEBKIT_WEB_VIEW(web_view)); + webkit_web_view_zoom_out(m_web_view); } void wxWebViewWebKit::SetWebkitZoom(float level) { - webkit_web_view_set_zoom_level (WEBKIT_WEB_VIEW(web_view), level); + webkit_web_view_set_zoom_level(m_web_view, level); } -float wxWebViewWebKit::GetWebkitZoom() +float wxWebViewWebKit::GetWebkitZoom() const { - return webkit_web_view_get_zoom_level (WEBKIT_WEB_VIEW(web_view)); + return webkit_web_view_get_zoom_level(m_web_view); } void wxWebViewWebKit::Stop() { - webkit_web_view_stop_loading (WEBKIT_WEB_VIEW(web_view)); + webkit_web_view_stop_loading(m_web_view); } void wxWebViewWebKit::Reload(wxWebViewReloadFlags flags) { if (flags & wxWEB_VIEW_RELOAD_NO_CACHE) { - webkit_web_view_reload_bypass_cache (WEBKIT_WEB_VIEW(web_view)); + webkit_web_view_reload_bypass_cache(m_web_view); } else { - webkit_web_view_reload (WEBKIT_WEB_VIEW(web_view)); + webkit_web_view_reload(m_web_view); } } -void wxWebViewWebKit::LoadUrl(const wxString& url) +void wxWebViewWebKit::LoadURL(const wxString& url) { - webkit_web_view_load_uri(WEBKIT_WEB_VIEW(web_view), wxGTK_CONV(url)); + webkit_web_view_load_uri(m_web_view, wxGTK_CONV(url)); } void wxWebViewWebKit::GoBack() { - webkit_web_view_go_back (WEBKIT_WEB_VIEW(web_view)); + webkit_web_view_go_back(m_web_view); } void wxWebViewWebKit::GoForward() { - webkit_web_view_go_forward (WEBKIT_WEB_VIEW(web_view)); + webkit_web_view_go_forward(m_web_view); } -bool wxWebViewWebKit::CanGoBack() +bool wxWebViewWebKit::CanGoBack() const { - return webkit_web_view_can_go_back (WEBKIT_WEB_VIEW(web_view)); + return webkit_web_view_can_go_back(m_web_view); } -bool wxWebViewWebKit::CanGoForward() +bool wxWebViewWebKit::CanGoForward() const { - return webkit_web_view_can_go_forward (WEBKIT_WEB_VIEW(web_view)); + return webkit_web_view_can_go_forward(m_web_view); } +void wxWebViewWebKit::ClearHistory() +{ + WebKitWebBackForwardList* history; + history = webkit_web_view_get_back_forward_list(m_web_view); + webkit_web_back_forward_list_clear(history); +} -wxString wxWebViewWebKit::GetCurrentURL() +void wxWebViewWebKit::EnableHistory(bool enable) +{ + WebKitWebBackForwardList* history; + history = webkit_web_view_get_back_forward_list(m_web_view); + if(enable) + { + webkit_web_back_forward_list_set_limit(history, m_historyLimit); + } + else + { + webkit_web_back_forward_list_set_limit(history, 0); + } +} + +wxVector > wxWebViewWebKit::GetBackwardHistory() +{ + wxVector > backhist; + WebKitWebBackForwardList* history; + history = webkit_web_view_get_back_forward_list(m_web_view); + GList* list = webkit_web_back_forward_list_get_back_list_with_limit(history, + m_historyLimit); + //We need to iterate in reverse to get the order we desire + for(int i = g_list_length(list) - 1; i >= 0 ; i--) + { + WebKitWebHistoryItem* gtkitem = (WebKitWebHistoryItem*)g_list_nth_data(list, i); + wxWebViewHistoryItem* wxitem = new wxWebViewHistoryItem( + webkit_web_history_item_get_uri(gtkitem), + webkit_web_history_item_get_title(gtkitem)); + wxitem->m_histItem = gtkitem; + wxSharedPtr item(wxitem); + backhist.push_back(item); + } + return backhist; +} + +wxVector > wxWebViewWebKit::GetForwardHistory() +{ + wxVector > forwardhist; + WebKitWebBackForwardList* history; + history = webkit_web_view_get_back_forward_list(m_web_view); + GList* list = webkit_web_back_forward_list_get_forward_list_with_limit(history, + m_historyLimit); + for(guint i = 0; i < g_list_length(list); i++) + { + WebKitWebHistoryItem* gtkitem = (WebKitWebHistoryItem*)g_list_nth_data(list, i); + wxWebViewHistoryItem* wxitem = new wxWebViewHistoryItem( + webkit_web_history_item_get_uri(gtkitem), + webkit_web_history_item_get_title(gtkitem)); + wxitem->m_histItem = gtkitem; + wxSharedPtr item(wxitem); + forwardhist.push_back(item); + } + return forwardhist; +} + +void wxWebViewWebKit::LoadHistoryItem(wxSharedPtr item) +{ + WebKitWebHistoryItem* gtkitem = (WebKitWebHistoryItem*)item->m_histItem; + if(gtkitem) + { + webkit_web_view_go_to_back_forward_item(m_web_view, + WEBKIT_WEB_HISTORY_ITEM(gtkitem)); + } +} + +bool wxWebViewWebKit::CanCut() const +{ + return webkit_web_view_can_cut_clipboard(m_web_view); +} + +bool wxWebViewWebKit::CanCopy() const +{ + return webkit_web_view_can_copy_clipboard(m_web_view); +} + +bool wxWebViewWebKit::CanPaste() const +{ + return webkit_web_view_can_paste_clipboard(m_web_view); +} + +void wxWebViewWebKit::Cut() +{ + webkit_web_view_cut_clipboard(m_web_view); +} + +void wxWebViewWebKit::Copy() +{ + webkit_web_view_copy_clipboard(m_web_view); +} + +void wxWebViewWebKit::Paste() +{ + webkit_web_view_paste_clipboard(m_web_view); +} + +bool wxWebViewWebKit::CanUndo() const +{ + return webkit_web_view_can_undo(m_web_view); +} + +bool wxWebViewWebKit::CanRedo() const +{ + return webkit_web_view_can_redo(m_web_view); +} + +void wxWebViewWebKit::Undo() +{ + webkit_web_view_undo(m_web_view); +} + +void wxWebViewWebKit::Redo() +{ + webkit_web_view_redo(m_web_view); +} + +wxString wxWebViewWebKit::GetCurrentURL() const { // FIXME: check which encoding the web kit control uses instead of // assuming UTF8 (here and elsewhere too) - return wxString::FromUTF8(webkit_web_view_get_uri( - WEBKIT_WEB_VIEW(web_view))); + return wxString::FromUTF8(webkit_web_view_get_uri(m_web_view)); } -wxString wxWebViewWebKit::GetCurrentTitle() +wxString wxWebViewWebKit::GetCurrentTitle() const { - return wxString::FromUTF8(webkit_web_view_get_title( - WEBKIT_WEB_VIEW(web_view))); + return wxString::FromUTF8(webkit_web_view_get_title(m_web_view)); } -wxString wxWebViewWebKit::GetPageSource() +wxString wxWebViewWebKit::GetPageSource() const { - WebKitWebFrame* frame = webkit_web_view_get_main_frame( - WEBKIT_WEB_VIEW(web_view)); + WebKitWebFrame* frame = webkit_web_view_get_main_frame(m_web_view); WebKitWebDataSource* src = webkit_web_frame_get_data_source (frame); // TODO: check encoding with @@ -414,7 +695,7 @@ wxString wxWebViewWebKit::GetPageSource() } -wxWebViewZoom wxWebViewWebKit::GetZoom() +wxWebViewZoom wxWebViewWebKit::GetZoom() const { float zoom = GetWebkitZoom(); @@ -478,15 +759,14 @@ void wxWebViewWebKit::SetZoom(wxWebViewZoom zoom) void wxWebViewWebKit::SetZoomType(wxWebViewZoomType type) { - webkit_web_view_set_full_content_zoom(WEBKIT_WEB_VIEW(web_view), + webkit_web_view_set_full_content_zoom(m_web_view, (type == wxWEB_VIEW_ZOOM_TYPE_LAYOUT ? TRUE : FALSE)); } wxWebViewZoomType wxWebViewWebKit::GetZoomType() const { - gboolean fczoom = webkit_web_view_get_full_content_zoom( - WEBKIT_WEB_VIEW(web_view)); + gboolean fczoom = webkit_web_view_get_full_content_zoom(m_web_view); if (fczoom) return wxWEB_VIEW_ZOOM_TYPE_LAYOUT; else return wxWEB_VIEW_ZOOM_TYPE_TEXT; @@ -498,9 +778,9 @@ bool wxWebViewWebKit::CanSetZoomType(wxWebViewZoomType) const return true; } -void wxWebViewWebKit::SetPage(const wxString& html, const wxString& baseUri) +void wxWebViewWebKit::DoSetPage(const wxString& html, const wxString& baseUri) { - webkit_web_view_load_string (WEBKIT_WEB_VIEW(web_view), + webkit_web_view_load_string (m_web_view, html.mb_str(wxConvUTF8), "text/html", "UTF-8", @@ -509,8 +789,7 @@ void wxWebViewWebKit::SetPage(const wxString& html, const wxString& baseUri) void wxWebViewWebKit::Print() { - WebKitWebFrame* frame = webkit_web_view_get_main_frame( - WEBKIT_WEB_VIEW(web_view)); + WebKitWebFrame* frame = webkit_web_view_get_main_frame(m_web_view); webkit_web_frame_print (frame); // GtkPrintOperationResult webkit_web_frame_print_full @@ -522,7 +801,7 @@ void wxWebViewWebKit::Print() } -bool wxWebViewWebKit::IsBusy() +bool wxWebViewWebKit::IsBusy() const { return m_busy; @@ -548,6 +827,181 @@ bool wxWebViewWebKit::IsBusy() */ } +void wxWebViewWebKit::SetEditable(bool enable) +{ + webkit_web_view_set_editable(m_web_view, enable); +} + +bool wxWebViewWebKit::IsEditable() const +{ + return webkit_web_view_get_editable(m_web_view); +} + +void wxWebViewWebKit::DeleteSelection() +{ + webkit_web_view_delete_selection(m_web_view); +} + +bool wxWebViewWebKit::HasSelection() const +{ + return webkit_web_view_has_selection(m_web_view); +} + +void wxWebViewWebKit::SelectAll() +{ + webkit_web_view_select_all(m_web_view); +} + +wxString wxWebViewWebKit::GetSelectedText() const +{ + WebKitDOMDocument* doc; + WebKitDOMDOMWindow* win; + WebKitDOMDOMSelection* sel; + WebKitDOMRange* range; + + doc = webkit_web_view_get_dom_document(m_web_view); + win = webkit_dom_document_get_default_view(WEBKIT_DOM_DOCUMENT(doc)); + sel = webkit_dom_dom_window_get_selection(WEBKIT_DOM_DOM_WINDOW(win)); + range = webkit_dom_dom_selection_get_range_at(WEBKIT_DOM_DOM_SELECTION(sel), + 0, NULL); + return wxString(webkit_dom_range_get_text(WEBKIT_DOM_RANGE(range)), + wxConvUTF8); +} + +wxString wxWebViewWebKit::GetSelectedSource() const +{ + WebKitDOMDocument* doc; + WebKitDOMDOMWindow* win; + WebKitDOMDOMSelection* sel; + WebKitDOMRange* range; + WebKitDOMElement* div; + WebKitDOMDocumentFragment* clone; + WebKitDOMHTMLElement* html; + + doc = webkit_web_view_get_dom_document(m_web_view); + win = webkit_dom_document_get_default_view(WEBKIT_DOM_DOCUMENT(doc)); + sel = webkit_dom_dom_window_get_selection(WEBKIT_DOM_DOM_WINDOW(win)); + range = webkit_dom_dom_selection_get_range_at(WEBKIT_DOM_DOM_SELECTION(sel), + 0, NULL); + div = webkit_dom_document_create_element(WEBKIT_DOM_DOCUMENT(doc), "div", NULL); + + clone = webkit_dom_range_clone_contents(WEBKIT_DOM_RANGE(range), NULL); + webkit_dom_node_append_child(&div->parent_instance, &clone->parent_instance, NULL); + html = (WebKitDOMHTMLElement*)div; + + return wxString(webkit_dom_html_element_get_inner_html(WEBKIT_DOM_HTML_ELEMENT(html)), + wxConvUTF8); +} + +void wxWebViewWebKit::ClearSelection() +{ + WebKitDOMDocument* doc; + WebKitDOMDOMWindow* win; + WebKitDOMDOMSelection* sel; + + doc = webkit_web_view_get_dom_document(m_web_view); + win = webkit_dom_document_get_default_view(WEBKIT_DOM_DOCUMENT(doc)); + sel = webkit_dom_dom_window_get_selection(WEBKIT_DOM_DOM_WINDOW(win)); + webkit_dom_dom_selection_remove_all_ranges(WEBKIT_DOM_DOM_SELECTION(sel)); + +} + +wxString wxWebViewWebKit::GetPageText() const +{ + WebKitDOMDocument* doc; + WebKitDOMHTMLElement* body; + + doc = webkit_web_view_get_dom_document(m_web_view); + body = webkit_dom_document_get_body(WEBKIT_DOM_DOCUMENT(doc)); + return wxString(webkit_dom_html_element_get_inner_text(WEBKIT_DOM_HTML_ELEMENT(body)), + wxConvUTF8); +} + +void wxWebViewWebKit::RunScript(const wxString& javascript) +{ + webkit_web_view_execute_script(m_web_view, + javascript.mb_str(wxConvUTF8)); +} + +void wxWebViewWebKit::RegisterHandler(wxSharedPtr handler) +{ + m_handlerList.push_back(handler); +} + +long wxWebViewWebKit::Find(const wxString& text, int flags) +{ + bool newSearch = false; + if(text != m_findText || + (flags & wxWEB_VIEW_FIND_MATCH_CASE) != (m_findFlags & wxWEB_VIEW_FIND_MATCH_CASE)) + { + newSearch = true; + //If it is a new search we need to clear existing highlights + webkit_web_view_unmark_text_matches(m_web_view); + webkit_web_view_set_highlight_text_matches(m_web_view, false); + } + + m_findFlags = flags; + m_findText = text; + + //If the search string is empty then we clear any selection and highlight + if(text == "") + { + webkit_web_view_unmark_text_matches(m_web_view); + webkit_web_view_set_highlight_text_matches(m_web_view, false); + ClearSelection(); + return wxNOT_FOUND; + } + + bool wrap = false, matchCase = false, forward = true; + if(flags & wxWEB_VIEW_FIND_WRAP) + wrap = true; + if(flags & wxWEB_VIEW_FIND_MATCH_CASE) + matchCase = true; + if(flags & wxWEB_VIEW_FIND_BACKWARDS) + forward = false; + + if(newSearch) + { + //Initially we mark the matches to know how many we have + m_findCount = webkit_web_view_mark_text_matches(m_web_view, wxGTK_CONV(text), matchCase, 0); + //In this case we return early to match IE behaviour + m_findPosition = -1; + return m_findCount; + } + else + { + if(forward) + m_findPosition++; + else + m_findPosition--; + if(m_findPosition < 0) + m_findPosition += m_findCount; + if(m_findPosition > m_findCount) + m_findPosition -= m_findCount; + } + + //Highlight them if needed + bool highlight = flags & wxWEB_VIEW_FIND_HIGHLIGHT_RESULT ? true : false; + webkit_web_view_set_highlight_text_matches(m_web_view, highlight); + + if(!webkit_web_view_search_text(m_web_view, wxGTK_CONV(text), matchCase, forward, wrap)) + { + m_findPosition = -1; + ClearSelection(); + return wxNOT_FOUND; + } + wxLogMessage(wxString::Format("Returning %d", m_findPosition)); + return newSearch ? m_findCount : m_findPosition; +} + +void wxWebViewWebKit::FindClear() +{ + m_findCount = 0; + m_findFlags = 0; + m_findText = ""; + m_findPosition = -1; +} + // static wxVisualAttributes wxWebViewWebKit::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant)) @@ -556,4 +1010,4 @@ wxWebViewWebKit::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant)) } -#endif // wxHAVE_WEB_BACKEND_GTK_WEBKIT +#endif // wxUSE_WEBVIEW && wxUSE_WEBVIEW_WEBKIT