X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8290e3cd91a9ff5bd7aad1e51666518701193bb0..7c60222510bc5e197b12f153c4bf05db66cb0f4a:/src/osx/webview_webkit.mm diff --git a/src/osx/webview_webkit.mm b/src/osx/webview_webkit.mm index a6b0943d83..1609dfd59a 100644 --- a/src/osx/webview_webkit.mm +++ b/src/osx/webview_webkit.mm @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// // Name: src/osx/webview_webkit.mm -// Purpose: wxOSXWebKitCtrl - embeddable web kit control, +// Purpose: wxWebViewWebKit - embeddable web kit control, // OS X implementation of web view component // Author: Jethro Grassie / Kevin Ollivier / Marianne Gagnon // Modified by: @@ -14,6 +14,9 @@ #include "wx/osx/webview_webkit.h" +#if wxUSE_WEBVIEW && wxUSE_WEBVIEW_WEBKIT && (defined(__WXOSX_COCOA__) \ + || defined(__WXOSX_CARBON__)) + // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -21,35 +24,28 @@ #include "wx/wx.h" #endif -#if wxHAVE_WEB_BACKEND_OSX_WEBKIT - -#ifdef __WXCOCOA__ -#include "wx/cocoa/autorelease.h" -#else #include "wx/osx/private.h" +#include "wx/cocoa/string.h" +#include "wx/hashmap.h" +#include "wx/filesys.h" #include #include #include -#endif #include -// FIXME: find cleaner way to find the wxWidgets ID of a webview than this hack -#include -std::map wx_webviewctrls; - #define DEBUG_WEBKIT_SIZING 0 // ---------------------------------------------------------------------------- // macros // ---------------------------------------------------------------------------- -IMPLEMENT_DYNAMIC_CLASS(wxOSXWebKitCtrl, wxControl) +wxIMPLEMENT_DYNAMIC_CLASS(wxWebViewWebKit, wxWebView); -BEGIN_EVENT_TABLE(wxOSXWebKitCtrl, wxControl) +BEGIN_EVENT_TABLE(wxWebViewWebKit, wxControl) #if defined(__WXMAC__) && wxOSX_USE_CARBON - EVT_SIZE(wxOSXWebKitCtrl::OnSize) + EVT_SIZE(wxWebViewWebKit::OnSize) #endif END_EVENT_TABLE() @@ -97,7 +93,7 @@ static pascal OSStatus wxWebKitKeyEventHandler(EventHandlerCallRef handler, OSStatus result = eventNotHandledErr ; wxMacCarbonEvent cEvent( event ) ; - wxOSXWebKitCtrl* thisWindow = (wxOSXWebKitCtrl*) data ; + wxWebViewWebKit* thisWindow = (wxWebViewWebKit*) data ; wxWindow* focus = thisWindow ; unsigned char charCode ; @@ -107,7 +103,6 @@ static pascal OSStatus wxWebKitKeyEventHandler(EventHandlerCallRef handler, UInt32 keyCode ; UInt32 modifiers ; - Point point ; UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ; #if wxUSE_UNICODE @@ -139,13 +134,11 @@ static pascal OSStatus wxWebKitKeyEventHandler(EventHandlerCallRef handler, #endif GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL, - sizeof(char), NULL, &charCode ); + 1, NULL, &charCode ); GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode ); GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers ); - GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, NULL, - sizeof(Point), NULL, &point ); UInt32 message = (keyCode << 8) + charCode; switch ( GetEventKind( event ) ) @@ -159,7 +152,7 @@ static pascal OSStatus wxWebKitKeyEventHandler(EventHandlerCallRef handler, wxTheApp->MacSetCurrentEvent( event , handler ) ; if ( /* focus && */ wxTheApp->MacSendKeyDownEvent( - focus, message, modifiers, when, point.h, point.v, uniChar[0])) + focus, message, modifiers, when, uniChar[0])) { result = noErr ; } @@ -169,7 +162,7 @@ static pascal OSStatus wxWebKitKeyEventHandler(EventHandlerCallRef handler, case kEventRawKeyUp : if ( /* focus && */ wxTheApp->MacSendKeyUpEvent( - focus , message , modifiers , when , point.h , point.v , uniChar[0] ) ) + focus , message , modifiers , when , uniChar[0] ) ) { result = noErr ; } @@ -183,8 +176,6 @@ static pascal OSStatus wxWebKitKeyEventHandler(EventHandlerCallRef handler, event.m_controlDown = modifiers & controlKey; event.m_altDown = modifiers & optionKey; event.m_metaDown = modifiers & cmdKey; - event.m_x = point.h; - event.m_y = point.v; #if wxUSE_UNICODE event.m_uniChar = uniChar[0] ; @@ -229,14 +220,14 @@ static pascal OSStatus wxWebKitKeyEventHandler(EventHandlerCallRef handler, return result ; } -static pascal OSStatus wxOSXWebKitCtrlEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) +static pascal OSStatus wxWebViewWebKitEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) { OSStatus result = eventNotHandledErr ; wxMacCarbonEvent cEvent( event ) ; ControlRef controlRef ; - wxOSXWebKitCtrl* thisWindow = (wxOSXWebKitCtrl*) data ; + wxWebViewWebKit* thisWindow = (wxWebViewWebKit*) data ; wxNonOwnedWindow* tlw = NULL; if (thisWindow) tlw = thisWindow->MacGetTopLevelWindow(); @@ -297,74 +288,52 @@ static pascal OSStatus wxOSXWebKitCtrlEventHandler( EventHandlerCallRef handler return result ; } -DEFINE_ONE_SHOT_HANDLER_GETTER( wxOSXWebKitCtrlEventHandler ) +DEFINE_ONE_SHOT_HANDLER_GETTER( wxWebViewWebKitEventHandler ) #endif -//--------------------------------------------------------- -// helper functions for NSString<->wxString conversion -//--------------------------------------------------------- - -inline wxString wxStringWithNSString(NSString *nsstring) +@interface WebViewLoadDelegate : NSObject { -#if wxUSE_UNICODE - return wxString([nsstring UTF8String], wxConvUTF8); -#else - return wxString([nsstring lossyCString]); -#endif // wxUSE_UNICODE + wxWebViewWebKit* webKitWindow; } -inline NSString* wxNSStringWithWxString(const wxString &wxstring) -{ -#if wxUSE_UNICODE - return [NSString stringWithUTF8String: wxstring.mb_str(wxConvUTF8)]; -#else - return [NSString stringWithCString: wxstring.c_str() length:wxstring.Len()]; -#endif // wxUSE_UNICODE -} +- initWithWxWindow: (wxWebViewWebKit*)inWindow; -inline int wxNavTypeFromWebNavType(int type){ - if (type == WebNavigationTypeLinkClicked) - return wxWEBKIT_NAV_LINK_CLICKED; - - if (type == WebNavigationTypeFormSubmitted) - return wxWEBKIT_NAV_FORM_SUBMITTED; - - if (type == WebNavigationTypeBackForward) - return wxWEBKIT_NAV_BACK_NEXT; +@end - if (type == WebNavigationTypeReload) - return wxWEBKIT_NAV_RELOAD; +@interface WebViewPolicyDelegate : NSObject +{ + wxWebViewWebKit* webKitWindow; +} - if (type == WebNavigationTypeFormResubmitted) - return wxWEBKIT_NAV_FORM_RESUBMITTED; +- initWithWxWindow: (wxWebViewWebKit*)inWindow; - return wxWEBKIT_NAV_OTHER; -} +@end -@interface MyFrameLoadMonitor : NSObject +@interface WebViewUIDelegate : NSObject { - wxOSXWebKitCtrl* webKitWindow; + wxWebViewWebKit* webKitWindow; } -- initWithWxWindow: (wxOSXWebKitCtrl*)inWindow; +- initWithWxWindow: (wxWebViewWebKit*)inWindow; @end -@interface MyPolicyDelegate : NSObject -{ - wxOSXWebKitCtrl* webKitWindow; -} +//We use a hash to map scheme names to wxWebViewHandler +WX_DECLARE_STRING_HASH_MAP(wxSharedPtr, wxStringToWebHandlerMap); -- initWithWxWindow: (wxOSXWebKitCtrl*)inWindow; +static wxStringToWebHandlerMap g_stringHandlerMap; +@interface WebViewCustomProtocol : NSURLProtocol +{ +} @end // ---------------------------------------------------------------------------- // creation/destruction // ---------------------------------------------------------------------------- -bool wxOSXWebKitCtrl::Create(wxWindow *parent, +bool wxWebViewWebKit::Create(wxWindow *parent, wxWindowID winID, const wxString& strURL, const wxPoint& pos, @@ -372,126 +341,91 @@ bool wxOSXWebKitCtrl::Create(wxWindow *parent, const wxString& name) { m_busy = false; - //m_pageTitle = _("Untitled Page"); - //still needed for wxCocoa?? -/* - int width, height; - wxSize sizeInstance; - if (size.x == wxDefaultCoord || size.y == wxDefaultCoord) - { - m_parent->GetClientSize(&width, &height); - sizeInstance.x = width; - sizeInstance.y = height; - } - else - { - sizeInstance.x = size.x; - sizeInstance.y = size.y; - } -*/ - // now create and attach WebKit view... -#ifdef __WXCOCOA__ - wxControl::Create(parent, m_windowID, pos, sizeInstance, style, name); - SetSize(pos.x, pos.y, sizeInstance.x, sizeInstance.y); - - wxTopLevelWindowCocoa *topWin = wxDynamicCast(this, wxTopLevelWindowCocoa); - NSWindow* nsWin = topWin->GetNSWindow(); - NSRect rect; - rect.origin.x = pos.x; - rect.origin.y = pos.y; - rect.size.width = sizeInstance.x; - rect.size.height = sizeInstance.y; - m_webView = (WebView*)[[WebView alloc] initWithFrame:rect - frameName:@"webkitFrame" - groupName:@"webkitGroup"]; - SetNSView(m_webView); - [m_cocoaNSView release]; - - if(m_parent) m_parent->CocoaAddChild(this); - SetInitialFrameRect(pos,sizeInstance); -#else - m_macIsUserPane = false; + DontCreatePeer(); wxControl::Create(parent, winID, pos, size, style, wxDefaultValidator, name); #if wxOSX_USE_CARBON - m_peer = new wxMacControl(this); + wxMacControl* peer = new wxMacControl(this); WebInitForCarbon(); - HIWebViewCreate( m_peer->GetControlRefAddr() ); + HIWebViewCreate( peer->GetControlRefAddr() ); - m_webView = (WebView*) HIWebViewGetWebView( m_peer->GetControlRef() ); + m_webView = (WebView*) HIWebViewGetWebView( peer->GetControlRef() ); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 if ( UMAGetSystemVersion() >= 0x1030 ) - HIViewChangeFeatures( m_peer->GetControlRef() , kHIViewIsOpaque , 0 ) ; + HIViewChangeFeatures( peer->GetControlRef() , kHIViewIsOpaque , 0 ) ; #endif - InstallControlEventHandler(m_peer->GetControlRef(), - GetwxOSXWebKitCtrlEventHandlerUPP(), + InstallControlEventHandler(peer->GetControlRef(), + GetwxWebViewWebKitEventHandlerUPP(), GetEventTypeCount(eventList), eventList, this, (EventHandlerRef *)&m_webKitCtrlEventHandler); + SetPeer(peer); #else NSRect r = wxOSXGetFrameForControl( this, pos , size ) ; m_webView = [[WebView alloc] initWithFrame:r frameName:@"webkitFrame" groupName:@"webkitGroup"]; - m_peer = new wxWidgetCocoaImpl( this, m_webView ); + SetPeer(new wxWidgetCocoaImpl( this, m_webView )); #endif - wx_webviewctrls[m_webView] = this; - MacPostControlCreate(pos, size); #if wxOSX_USE_CARBON - HIViewSetVisible( m_peer->GetControlRef(), true ); + HIViewSetVisible( GetPeer()->GetControlRef(), true ); #endif [m_webView setHidden:false]; -#endif + // Register event listener interfaces - MyFrameLoadMonitor* myFrameLoadMonitor = - [[MyFrameLoadMonitor alloc] initWithWxWindow: this]; + WebViewLoadDelegate* loadDelegate = + [[WebViewLoadDelegate alloc] initWithWxWindow: this]; - [m_webView setFrameLoadDelegate:myFrameLoadMonitor]; + [m_webView setFrameLoadDelegate:loadDelegate]; // this is used to veto page loads, etc. - MyPolicyDelegate* myPolicyDelegate = - [[MyPolicyDelegate alloc] initWithWxWindow: this]; + WebViewPolicyDelegate* policyDelegate = + [[WebViewPolicyDelegate alloc] initWithWxWindow: this]; + + [m_webView setPolicyDelegate:policyDelegate]; - [m_webView setPolicyDelegate:myPolicyDelegate]; + WebViewUIDelegate* uiDelegate = + [[WebViewUIDelegate alloc] initWithWxWindow: this]; - InternalLoadURL(strURL); + [m_webView setUIDelegate:uiDelegate]; + + //Register our own class for custom scheme handling + [NSURLProtocol registerClass:[WebViewCustomProtocol class]]; + + LoadURL(strURL); return true; } -wxOSXWebKitCtrl::~wxOSXWebKitCtrl() +wxWebViewWebKit::~wxWebViewWebKit() { - MyFrameLoadMonitor* myFrameLoadMonitor = [m_webView frameLoadDelegate]; - MyPolicyDelegate* myPolicyDelegate = [m_webView policyDelegate]; + WebViewLoadDelegate* loadDelegate = [m_webView frameLoadDelegate]; + WebViewPolicyDelegate* policyDelegate = [m_webView policyDelegate]; + WebViewUIDelegate* uiDelegate = [m_webView UIDelegate]; [m_webView setFrameLoadDelegate: nil]; [m_webView setPolicyDelegate: nil]; + [m_webView setUIDelegate: nil]; + + if (loadDelegate) + [loadDelegate release]; - if (myFrameLoadMonitor) - [myFrameLoadMonitor release]; + if (policyDelegate) + [policyDelegate release]; - if (myPolicyDelegate) - [myPolicyDelegate release]; + if (uiDelegate) + [uiDelegate release]; } // ---------------------------------------------------------------------------- // public methods // ---------------------------------------------------------------------------- -void wxOSXWebKitCtrl::InternalLoadURL(const wxString &url) -{ - if( !m_webView ) - return; - - [[m_webView mainFrame] loadRequest:[NSURLRequest requestWithURL: - [NSURL URLWithString:wxNSStringWithWxString(url)]]]; -} - -bool wxOSXWebKitCtrl::CanGoBack() +bool wxWebViewWebKit::CanGoBack() const { if ( !m_webView ) return false; @@ -499,7 +433,7 @@ bool wxOSXWebKitCtrl::CanGoBack() return [m_webView canGoBack]; } -bool wxOSXWebKitCtrl::CanGoForward() +bool wxWebViewWebKit::CanGoForward() const { if ( !m_webView ) return false; @@ -507,34 +441,28 @@ bool wxOSXWebKitCtrl::CanGoForward() return [m_webView canGoForward]; } -void wxOSXWebKitCtrl::GoBack() +void wxWebViewWebKit::GoBack() { if ( !m_webView ) return; - bool result = [(WebView*)m_webView goBack]; - - // TODO: return result (if it also exists in other backends...) - //return result; + [(WebView*)m_webView goBack]; } -void wxOSXWebKitCtrl::GoForward() +void wxWebViewWebKit::GoForward() { if ( !m_webView ) return; - bool result = [(WebView*)m_webView goForward]; - - // TODO: return result (if it also exists in other backends...) - //return result; + [(WebView*)m_webView goForward]; } -void wxOSXWebKitCtrl::Reload(wxWebViewReloadFlags flags) +void wxWebViewWebKit::Reload(wxWebViewReloadFlags flags) { if ( !m_webView ) return; - if (flags & wxWEB_VIEW_RELOAD_NO_CACHE) + if (flags & wxWEBVIEW_RELOAD_NO_CACHE) { // TODO: test this indeed bypasses the cache [[m_webView preferences] setUsesPageCache:NO]; @@ -547,7 +475,7 @@ void wxOSXWebKitCtrl::Reload(wxWebViewReloadFlags flags) } } -void wxOSXWebKitCtrl::Stop() +void wxWebViewWebKit::Stop() { if ( !m_webView ) return; @@ -555,7 +483,7 @@ void wxOSXWebKitCtrl::Stop() [[m_webView mainFrame] stopLoading]; } -bool wxOSXWebKitCtrl::CanGetPageSource() +bool wxWebViewWebKit::CanGetPageSource() const { if ( !m_webView ) return false; @@ -564,7 +492,7 @@ bool wxOSXWebKitCtrl::CanGetPageSource() return ( [[dataSource representation] canProvideDocumentSource] ); } -wxString wxOSXWebKitCtrl::GetPageSource() +wxString wxWebViewWebKit::GetPageSource() const { if (CanGetPageSource()) @@ -587,16 +515,7 @@ wxString wxOSXWebKitCtrl::GetPageSource() return wxEmptyString; } -wxString wxOSXWebKitCtrl::GetSelection() -{ - if ( !m_webView ) - return wxEmptyString; - - NSString* selectedText = [[m_webView selectedDOMRange] toString]; - return wxStringWithNSString( selectedText ); -} - -bool wxOSXWebKitCtrl::CanIncreaseTextSize() +bool wxWebViewWebKit::CanIncreaseTextSize() const { if ( !m_webView ) return false; @@ -607,7 +526,7 @@ bool wxOSXWebKitCtrl::CanIncreaseTextSize() return false; } -void wxOSXWebKitCtrl::IncreaseTextSize() +void wxWebViewWebKit::IncreaseTextSize() { if ( !m_webView ) return; @@ -616,7 +535,7 @@ void wxOSXWebKitCtrl::IncreaseTextSize() [m_webView makeTextLarger:(WebView*)m_webView]; } -bool wxOSXWebKitCtrl::CanDecreaseTextSize() +bool wxWebViewWebKit::CanDecreaseTextSize() const { if ( !m_webView ) return false; @@ -627,7 +546,7 @@ bool wxOSXWebKitCtrl::CanDecreaseTextSize() return false; } -void wxOSXWebKitCtrl::DecreaseTextSize() +void wxWebViewWebKit::DecreaseTextSize() { if ( !m_webView ) return; @@ -636,7 +555,7 @@ void wxOSXWebKitCtrl::DecreaseTextSize() [m_webView makeTextSmaller:(WebView*)m_webView]; } -void wxOSXWebKitCtrl::Print() +void wxWebViewWebKit::Print() { // TODO: allow specifying the "show prompt" parameter in Print() ? @@ -652,7 +571,7 @@ void wxOSXWebKitCtrl::Print() { [op setShowsPrintPanel: showPrompt]; // in my tests, the progress bar always freezes and it stops the whole - // print operation. do not turn this to true unless there is a + // print operation. do not turn this to true unless there is a // workaround for the bug. [op setShowsProgressPanel: false]; } @@ -660,7 +579,7 @@ void wxOSXWebKitCtrl::Print() [op runOperation]; } -void wxOSXWebKitCtrl::MakeEditable(bool enable) +void wxWebViewWebKit::SetEditable(bool enable) { if ( !m_webView ) return; @@ -668,7 +587,7 @@ void wxOSXWebKitCtrl::MakeEditable(bool enable) [m_webView setEditable:enable ]; } -bool wxOSXWebKitCtrl::IsEditable() +bool wxWebViewWebKit::IsEditable() const { if ( !m_webView ) return false; @@ -676,29 +595,29 @@ bool wxOSXWebKitCtrl::IsEditable() return [m_webView isEditable]; } -void wxOSXWebKitCtrl::SetZoomType(wxWebViewZoomType zoomType) +void wxWebViewWebKit::SetZoomType(wxWebViewZoomType zoomType) { // there is only one supported zoom type at the moment so this setter // does nothing beyond checking sanity - wxASSERT(zoomType == wxWEB_VIEW_ZOOM_TYPE_TEXT); + wxASSERT(zoomType == wxWEBVIEW_ZOOM_TYPE_TEXT); } -wxWebViewZoomType wxOSXWebKitCtrl::GetZoomType() const +wxWebViewZoomType wxWebViewWebKit::GetZoomType() const { // for now that's the only one that is supported // FIXME: does the default zoom type change depending on webkit versions? :S // Then this will be wrong - return wxWEB_VIEW_ZOOM_TYPE_TEXT; + return wxWEBVIEW_ZOOM_TYPE_TEXT; } -bool wxOSXWebKitCtrl::CanSetZoomType(wxWebViewZoomType type) const +bool wxWebViewWebKit::CanSetZoomType(wxWebViewZoomType type) const { switch (type) { // for now that's the only one that is supported // TODO: I know recent versions of webkit support layout zoom too, // check if we can support it - case wxWEB_VIEW_ZOOM_TYPE_TEXT: + case wxWEBVIEW_ZOOM_TYPE_TEXT: return true; default: @@ -706,14 +625,14 @@ bool wxOSXWebKitCtrl::CanSetZoomType(wxWebViewZoomType type) const } } -int wxOSXWebKitCtrl::GetScrollPos() +int wxWebViewWebKit::GetScrollPos() { id result = [[m_webView windowScriptObject] evaluateWebScript:@"document.body.scrollTop"]; return [result intValue]; } -void wxOSXWebKitCtrl::SetScrollPos(int pos) +void wxWebViewWebKit::SetScrollPos(int pos) { if ( !m_webView ) return; @@ -724,7 +643,7 @@ void wxOSXWebKitCtrl::SetScrollPos(int pos) (NSString*)wxNSStringWithWxString( javascript )]; } -wxString wxOSXWebKitCtrl::GetSelectedText() +wxString wxWebViewWebKit::GetSelectedText() const { NSString* selection = [[m_webView selectedDOMRange] markupString]; if (!selection) return wxEmptyString; @@ -732,47 +651,18 @@ wxString wxOSXWebKitCtrl::GetSelectedText() return wxStringWithNSString(selection); } -wxString wxOSXWebKitCtrl::RunScript(const wxString& javascript) +void wxWebViewWebKit::RunScript(const wxString& javascript) { if ( !m_webView ) - return wxEmptyString; + return; - id result = [[m_webView windowScriptObject] evaluateWebScript: + [[m_webView windowScriptObject] evaluateWebScript: (NSString*)wxNSStringWithWxString( javascript )]; - - NSString* resultAsString; - NSString* className = NSStringFromClass([result class]); - - if ([className isEqualToString:@"NSCFNumber"]) - { - resultAsString = [NSString stringWithFormat:@"%@", result]; - } - else if ([className isEqualToString:@"NSCFString"]) - { - resultAsString = result; - } - else if ([className isEqualToString:@"NSCFBoolean"]) - { - if ([result boolValue]) - resultAsString = @"true"; - else - resultAsString = @"false"; - } - else if ([className isEqualToString:@"WebScriptObject"]) - { - resultAsString = [result stringRepresentation]; - } - else - { - return wxString(); - } - - return wxStringWithNSString( resultAsString ); } -void wxOSXWebKitCtrl::OnSize(wxSizeEvent &event) +void wxWebViewWebKit::OnSize(wxSizeEvent &event) { -#if defined(__WXMAC_) && wxOSX_USE_CARBON +#if defined(__WXMAC__) && wxOSX_USE_CARBON // This is a nasty hack because WebKit seems to lose its position when it is // embedded in a control that is not itself the content view for a TLW. // I put it in OnSize because these calcs are not perfect, and in fact are @@ -818,7 +708,7 @@ void wxOSXWebKitCtrl::OnSize(wxSizeEvent &event) // we want is the root view, because we need to make the y origin relative // to the very top of the window, not its contents, since we later flip // the y coordinate for Cocoa. - HIViewConvertRect (&rect, m_peer->GetControlRef(), + HIViewConvertRect (&rect, GetPeer()->GetControlRef(), HIViewGetRoot( (WindowRef) MacGetTopLevelWindowRef() )); @@ -849,9 +739,9 @@ void wxOSXWebKitCtrl::OnSize(wxSizeEvent &event) #endif } -void wxOSXWebKitCtrl::MacVisibilityChanged(){ +void wxWebViewWebKit::MacVisibilityChanged(){ #if defined(__WXMAC__) && wxOSX_USE_CARBON - bool isHidden = !IsControlVisible( m_peer->GetControlRef()); + bool isHidden = !IsControlVisible( GetPeer()->GetControlRef()); if (!isHidden) [(WebView*)m_webView display]; @@ -859,84 +749,85 @@ void wxOSXWebKitCtrl::MacVisibilityChanged(){ #endif } -void wxOSXWebKitCtrl::LoadUrl(const wxString& url) +void wxWebViewWebKit::LoadURL(const wxString& url) { - InternalLoadURL(url); + [[m_webView mainFrame] loadRequest:[NSURLRequest requestWithURL: + [NSURL URLWithString:wxNSStringWithWxString(url)]]]; } -wxString wxOSXWebKitCtrl::GetCurrentURL() +wxString wxWebViewWebKit::GetCurrentURL() const { return wxStringWithNSString([m_webView mainFrameURL]); } -wxString wxOSXWebKitCtrl::GetCurrentTitle() +wxString wxWebViewWebKit::GetCurrentTitle() const { - return GetPageTitle(); + return wxStringWithNSString([m_webView mainFrameTitle]); } -float wxOSXWebKitCtrl::GetWebkitZoom() +float wxWebViewWebKit::GetWebkitZoom() const { return [m_webView textSizeMultiplier]; } -void wxOSXWebKitCtrl::SetWebkitZoom(float zoom) +void wxWebViewWebKit::SetWebkitZoom(float zoom) { [m_webView setTextSizeMultiplier:zoom]; } -wxWebViewZoom wxOSXWebKitCtrl::GetZoom() +wxWebViewZoom wxWebViewWebKit::GetZoom() const { float zoom = GetWebkitZoom(); // arbitrary way to map float zoom to our common zoom enum if (zoom <= 0.55) { - return wxWEB_VIEW_ZOOM_TINY; + return wxWEBVIEW_ZOOM_TINY; } else if (zoom > 0.55 && zoom <= 0.85) { - return wxWEB_VIEW_ZOOM_SMALL; + return wxWEBVIEW_ZOOM_SMALL; } else if (zoom > 0.85 && zoom <= 1.15) { - return wxWEB_VIEW_ZOOM_MEDIUM; + return wxWEBVIEW_ZOOM_MEDIUM; } else if (zoom > 1.15 && zoom <= 1.45) { - return wxWEB_VIEW_ZOOM_LARGE; + return wxWEBVIEW_ZOOM_LARGE; } else if (zoom > 1.45) { - return wxWEB_VIEW_ZOOM_LARGEST; + return wxWEBVIEW_ZOOM_LARGEST; } // to shut up compilers, this can never be reached logically wxASSERT(false); - return wxWEB_VIEW_ZOOM_MEDIUM; + return wxWEBVIEW_ZOOM_MEDIUM; } -void wxOSXWebKitCtrl::SetZoom(wxWebViewZoom zoom) +void wxWebViewWebKit::SetZoom(wxWebViewZoom zoom) { // arbitrary way to map our common zoom enum to float zoom switch (zoom) { - case wxWEB_VIEW_ZOOM_TINY: + case wxWEBVIEW_ZOOM_TINY: SetWebkitZoom(0.4f); break; - case wxWEB_VIEW_ZOOM_SMALL: + case wxWEBVIEW_ZOOM_SMALL: SetWebkitZoom(0.7f); break; - case wxWEB_VIEW_ZOOM_MEDIUM: + case wxWEBVIEW_ZOOM_MEDIUM: SetWebkitZoom(1.0f); break; - case wxWEB_VIEW_ZOOM_LARGE: + case wxWEBVIEW_ZOOM_LARGE: SetWebkitZoom(1.3); break; - case wxWEB_VIEW_ZOOM_LARGEST: + case wxWEBVIEW_ZOOM_LARGEST: SetWebkitZoom(1.6); break; @@ -946,7 +837,7 @@ void wxOSXWebKitCtrl::SetZoom(wxWebViewZoom zoom) } -void wxOSXWebKitCtrl::SetPage(const wxString& src, const wxString& baseUrl) +void wxWebViewWebKit::DoSetPage(const wxString& src, const wxString& baseUrl) { if ( !m_webView ) return; @@ -956,6 +847,160 @@ void wxOSXWebKitCtrl::SetPage(const wxString& src, const wxString& baseUrl) wxNSStringWithWxString( baseUrl )]]; } +void wxWebViewWebKit::Cut() +{ + if ( !m_webView ) + return; + + [(WebView*)m_webView cut:m_webView]; +} + +void wxWebViewWebKit::Copy() +{ + if ( !m_webView ) + return; + + [(WebView*)m_webView copy:m_webView]; +} + +void wxWebViewWebKit::Paste() +{ + if ( !m_webView ) + return; + + [(WebView*)m_webView paste:m_webView]; +} + +void wxWebViewWebKit::DeleteSelection() +{ + if ( !m_webView ) + return; + + [(WebView*)m_webView deleteSelection]; +} + +bool wxWebViewWebKit::HasSelection() const +{ + DOMRange* range = [m_webView selectedDOMRange]; + if(!range) + { + return false; + } + else + { + return true; + } +} + +void wxWebViewWebKit::ClearSelection() +{ + //We use javascript as selection isn't exposed at the moment in webkit + RunScript("window.getSelection().removeAllRanges();"); +} + +void wxWebViewWebKit::SelectAll() +{ + RunScript("window.getSelection().selectAllChildren(document.body);"); +} + +wxString wxWebViewWebKit::GetSelectedSource() const +{ + wxString script = ("var range = window.getSelection().getRangeAt(0);" + "var element = document.createElement('div');" + "element.appendChild(range.cloneContents());" + "return element.innerHTML;"); + NSString *result = [m_webView stringByEvaluatingJavaScriptFromString: + wxNSStringWithWxString(script)]; + return wxStringWithNSString(result); +} + +wxString wxWebViewWebKit::GetPageText() const +{ + NSString *result = [m_webView stringByEvaluatingJavaScriptFromString: + @"document.body.textContent"]; + return wxStringWithNSString(result); +} + +void wxWebViewWebKit::EnableHistory(bool enable) +{ + if ( !m_webView ) + return; + + [m_webView setMaintainsBackForwardList:enable]; +} + +void wxWebViewWebKit::ClearHistory() +{ + [m_webView setMaintainsBackForwardList:NO]; + [m_webView setMaintainsBackForwardList:YES]; +} + +wxVector > wxWebViewWebKit::GetBackwardHistory() +{ + wxVector > backhist; + WebBackForwardList* history = [m_webView backForwardList]; + int count = [history backListCount]; + for(int i = -count; i < 0; i++) + { + WebHistoryItem* item = [history itemAtIndex:i]; + wxString url = wxStringWithNSString([item URLString]); + wxString title = wxStringWithNSString([item title]); + wxWebViewHistoryItem* wxitem = new wxWebViewHistoryItem(url, title); + wxitem->m_histItem = item; + wxSharedPtr itemptr(wxitem); + backhist.push_back(itemptr); + } + return backhist; +} + +wxVector > wxWebViewWebKit::GetForwardHistory() +{ + wxVector > forwardhist; + WebBackForwardList* history = [m_webView backForwardList]; + int count = [history forwardListCount]; + for(int i = 1; i <= count; i++) + { + WebHistoryItem* item = [history itemAtIndex:i]; + wxString url = wxStringWithNSString([item URLString]); + wxString title = wxStringWithNSString([item title]); + wxWebViewHistoryItem* wxitem = new wxWebViewHistoryItem(url, title); + wxitem->m_histItem = item; + wxSharedPtr itemptr(wxitem); + forwardhist.push_back(itemptr); + } + return forwardhist; +} + +void wxWebViewWebKit::LoadHistoryItem(wxSharedPtr item) +{ + [m_webView goToBackForwardItem:item->m_histItem]; +} + +bool wxWebViewWebKit::CanUndo() const +{ + return [[m_webView undoManager] canUndo]; +} + +bool wxWebViewWebKit::CanRedo() const +{ + return [[m_webView undoManager] canRedo]; +} + +void wxWebViewWebKit::Undo() +{ + [[m_webView undoManager] undo]; +} + +void wxWebViewWebKit::Redo() +{ + [[m_webView undoManager] redo]; +} + +void wxWebViewWebKit::RegisterHandler(wxSharedPtr handler) +{ + g_stringHandlerMap[handler->GetName()] = handler; +} + //------------------------------------------------------------ // Listener interfaces //------------------------------------------------------------ @@ -965,9 +1010,9 @@ void wxOSXWebKitCtrl::SetPage(const wxString& src, const wxString& baseUrl) // destroyed. Therefore, we must be careful to check both the existence // of the Carbon control and the event handler before firing events. -@implementation MyFrameLoadMonitor +@implementation WebViewLoadDelegate -- initWithWxWindow: (wxOSXWebKitCtrl*)inWindow +- initWithWxWindow: (wxWebViewWebKit*)inWindow { [super init]; webKitWindow = inWindow; // non retained @@ -977,50 +1022,47 @@ void wxOSXWebKitCtrl::SetPage(const wxString& src, const wxString& baseUrl) - (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame { - wxASSERT(wx_webviewctrls.find(sender) != wx_webviewctrls.end()); - wx_webviewctrls[sender]->m_busy = true; + webKitWindow->m_busy = true; } - (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame { - wxASSERT(wx_webviewctrls.find(sender) != wx_webviewctrls.end()); - wx_webviewctrls[sender]->m_busy = true; + webKitWindow->m_busy = true; if (webKitWindow && frame == [sender mainFrame]){ NSString *url = [[[[frame dataSource] request] URL] absoluteString]; wxString target = wxStringWithNSString([frame name]); - wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_NAVIGATED, - wx_webviewctrls[sender]->GetId(), - wxStringWithNSString( url ), - target, false); + wxWebViewEvent event(wxEVT_WEBVIEW_NAVIGATED, + webKitWindow->GetId(), + wxStringWithNSString( url ), + target); if (webKitWindow && webKitWindow->GetEventHandler()) - webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); + webKitWindow->GetEventHandler()->ProcessEvent(event); } } - (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame { - wxASSERT(wx_webviewctrls.find(sender) != wx_webviewctrls.end()); - wx_webviewctrls[sender]->m_busy = false; + webKitWindow->m_busy = false; if (webKitWindow && frame == [sender mainFrame]){ NSString *url = [[[[frame dataSource] request] URL] absoluteString]; wxString target = wxStringWithNSString([frame name]); - wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_LOADED, - wx_webviewctrls[sender]->GetId(), - wxStringWithNSString( url ), - target, false); + wxWebViewEvent event(wxEVT_WEBVIEW_LOADED, + webKitWindow->GetId(), + wxStringWithNSString( url ), + target); if (webKitWindow && webKitWindow->GetEventHandler()) - webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); + webKitWindow->GetEventHandler()->ProcessEvent(event); } } -wxString nsErrorToWxHtmlError(NSError* error, wxWebNavigationError* out) +wxString nsErrorToWxHtmlError(NSError* error, wxWebViewNavigationError* out) { - *out = wxWEB_NAV_ERR_OTHER; + *out = wxWEBVIEW_NAV_ERR_OTHER; if ([[error domain] isEqualToString:NSURLErrorDomain]) { @@ -1029,15 +1071,17 @@ wxString nsErrorToWxHtmlError(NSError* error, wxWebNavigationError* out) case NSURLErrorCannotFindHost: case NSURLErrorFileDoesNotExist: case NSURLErrorRedirectToNonExistentLocation: - *out = wxWEB_NAV_ERR_NOT_FOUND; + *out = wxWEBVIEW_NAV_ERR_NOT_FOUND; break; case NSURLErrorResourceUnavailable: case NSURLErrorHTTPTooManyRedirects: +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 case NSURLErrorDataLengthExceedsMaximum: +#endif case NSURLErrorBadURL: case NSURLErrorFileIsDirectory: - *out = wxWEB_NAV_ERR_REQUEST; + *out = wxWEBVIEW_NAV_ERR_REQUEST; break; case NSURLErrorTimedOut: @@ -1048,29 +1092,33 @@ wxString nsErrorToWxHtmlError(NSError* error, wxWebNavigationError* out) //case NSURLErrorInternationalRoamingOff: //case NSURLErrorCallIsActive: //case NSURLErrorDataNotAllowed: - *out = wxWEB_NAV_ERR_CONNECTION; + *out = wxWEBVIEW_NAV_ERR_CONNECTION; break; case NSURLErrorCancelled: case NSURLErrorUserCancelledAuthentication: - *out = wxWEB_NAV_ERR_USER_CANCELLED; + *out = wxWEBVIEW_NAV_ERR_USER_CANCELLED; break; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 case NSURLErrorCannotDecodeRawData: case NSURLErrorCannotDecodeContentData: - case NSURLErrorBadServerResponse: case NSURLErrorCannotParseResponse: - *out = wxWEB_NAV_ERR_REQUEST; +#endif + case NSURLErrorBadServerResponse: + *out = wxWEBVIEW_NAV_ERR_REQUEST; break; case NSURLErrorUserAuthenticationRequired: case NSURLErrorSecureConnectionFailed: +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 case NSURLErrorClientCertificateRequired: - *out = wxWEB_NAV_ERR_AUTH; +#endif + *out = wxWEBVIEW_NAV_ERR_AUTH; break; case NSURLErrorNoPermissionsToReadFile: - *out = wxWEB_NAV_ERR_SECURITY; + *out = wxWEBVIEW_NAV_ERR_SECURITY; break; case NSURLErrorServerCertificateHasBadDate: @@ -1078,7 +1126,7 @@ wxString nsErrorToWxHtmlError(NSError* error, wxWebNavigationError* out) case NSURLErrorServerCertificateHasUnknownRoot: case NSURLErrorServerCertificateNotYetValid: case NSURLErrorClientCertificateRejected: - *out = wxWEB_NAV_ERR_CERTIFICATE; + *out = wxWEBVIEW_NAV_ERR_CERTIFICATE; break; } } @@ -1095,24 +1143,23 @@ wxString nsErrorToWxHtmlError(NSError* error, wxWebNavigationError* out) - (void)webView:(WebView *)sender didFailLoadWithError:(NSError*) error forFrame:(WebFrame *)frame { - wxASSERT(wx_webviewctrls.find(sender) != wx_webviewctrls.end()); - wx_webviewctrls[sender]->m_busy = false; + webKitWindow->m_busy = false; if (webKitWindow && frame == [sender mainFrame]){ NSString *url = [[[[frame dataSource] request] URL] absoluteString]; - wxWebNavigationError type; + wxWebViewNavigationError type; wxString description = nsErrorToWxHtmlError(error, &type); - wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_ERROR, - wx_webviewctrls[sender]->GetId(), - wxStringWithNSString( url ), - wxEmptyString, false); - thisEvent.SetString(description); - thisEvent.SetInt(type); + wxWebViewEvent event(wxEVT_WEBVIEW_ERROR, + webKitWindow->GetId(), + wxStringWithNSString( url ), + wxEmptyString); + event.SetString(description); + event.SetInt(type); if (webKitWindow && webKitWindow->GetEventHandler()) { - webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); + webKitWindow->GetEventHandler()->ProcessEvent(event); } } } @@ -1121,40 +1168,45 @@ wxString nsErrorToWxHtmlError(NSError* error, wxWebNavigationError* out) didFailProvisionalLoadWithError:(NSError*)error forFrame:(WebFrame *)frame { - wxASSERT(wx_webviewctrls.find(sender) != wx_webviewctrls.end()); - wx_webviewctrls[sender]->m_busy = false; + webKitWindow->m_busy = false; if (webKitWindow && frame == [sender mainFrame]){ NSString *url = [[[[frame provisionalDataSource] request] URL] absoluteString]; - wxWebNavigationError type; + wxWebViewNavigationError type; wxString description = nsErrorToWxHtmlError(error, &type); - wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_ERROR, - wx_webviewctrls[sender]->GetId(), - wxStringWithNSString( url ), - wxEmptyString, false); - thisEvent.SetString(description); - thisEvent.SetInt(type); + wxWebViewEvent event(wxEVT_WEBVIEW_ERROR, + webKitWindow->GetId(), + wxStringWithNSString( url ), + wxEmptyString); + event.SetString(description); + event.SetInt(type); if (webKitWindow && webKitWindow->GetEventHandler()) - webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); + webKitWindow->GetEventHandler()->ProcessEvent(event); } } - (void)webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame { - if (webKitWindow && frame == [sender mainFrame]) - { - webKitWindow->SetPageTitle(wxStringWithNSString( title )); - } + wxString target = wxStringWithNSString([frame name]); + wxWebViewEvent event(wxEVT_WEBVIEW_TITLE_CHANGED, + webKitWindow->GetId(), + webKitWindow->GetCurrentURL(), + target); + + event.SetString(wxStringWithNSString(title)); + + if (webKitWindow && webKitWindow->GetEventHandler()) + webKitWindow->GetEventHandler()->ProcessEvent(event); } @end -@implementation MyPolicyDelegate +@implementation WebViewPolicyDelegate -- initWithWxWindow: (wxOSXWebKitCtrl*)inWindow +- initWithWxWindow: (wxWebViewWebKit*)inWindow { [super init]; webKitWindow = inWindow; // non retained @@ -1167,23 +1219,21 @@ wxString nsErrorToWxHtmlError(NSError* error, wxWebNavigationError* out) frame:(WebFrame *)frame decisionListener:(id)listener { - //wxUnusedVar(sender); wxUnusedVar(frame); - wxASSERT(wx_webviewctrls.find(sender) != wx_webviewctrls.end()); - wx_webviewctrls[sender]->m_busy = true; + webKitWindow->m_busy = true; NSString *url = [[request URL] absoluteString]; wxString target = wxStringWithNSString([frame name]); - wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_NAVIGATING, - wx_webviewctrls[sender]->GetId(), - wxStringWithNSString( url ), target, true); + wxWebViewEvent event(wxEVT_WEBVIEW_NAVIGATING, + webKitWindow->GetId(), + wxStringWithNSString( url ), target); if (webKitWindow && webKitWindow->GetEventHandler()) - webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); + webKitWindow->GetEventHandler()->ProcessEvent(event); - if (thisEvent.IsVetoed()) + if (!event.IsAllowed()) { - wx_webviewctrls[sender]->m_busy = false; + webKitWindow->m_busy = false; [listener ignore]; } else @@ -1192,17 +1242,131 @@ wxString nsErrorToWxHtmlError(NSError* error, wxWebNavigationError* out) } } -- (void)webView:(WebView *)sender +- (void)webView:(WebView *)sender decidePolicyForNewWindowAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request newFrameName:(NSString *)frameName decisionListener:(id < WebPolicyDecisionListener >)listener { - wxUnusedVar(sender); wxUnusedVar(actionInformation); + NSString *url = [[request URL] absoluteString]; + wxWebViewEvent event(wxEVT_WEBVIEW_NEWWINDOW, + webKitWindow->GetId(), + wxStringWithNSString( url ), ""); + + if (webKitWindow && webKitWindow->GetEventHandler()) + webKitWindow->GetEventHandler()->ProcessEvent(event); + [listener ignore]; } @end -#endif //wxHAVE_WEB_BACKEND_OSX_WEBKIT +@implementation WebViewCustomProtocol + ++ (BOOL)canInitWithRequest:(NSURLRequest *)request +{ + NSString *scheme = [[request URL] scheme]; + + wxStringToWebHandlerMap::const_iterator it; + for( it = g_stringHandlerMap.begin(); it != g_stringHandlerMap.end(); ++it ) + { + if(it->first.IsSameAs(wxStringWithNSString(scheme))) + { + return YES; + } + } + + return NO; +} + ++ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request +{ + //We don't do any processing here as the wxWebViewHandler classes do it + return request; +} + +- (void)startLoading +{ + NSURLRequest *request = [self request]; + NSString* path = [[request URL] absoluteString]; + + id client = [self client]; + + wxString wxpath = wxStringWithNSString(path); + wxString scheme = wxStringWithNSString([[request URL] scheme]); + wxFSFile* file = g_stringHandlerMap[scheme]->GetFile(wxpath); + + if (!file) + { + NSError *error = [[NSError alloc] initWithDomain:NSURLErrorDomain + code:NSURLErrorFileDoesNotExist + userInfo:nil]; + + [client URLProtocol:self didFailWithError:error]; + + return; + } + + size_t length = file->GetStream()->GetLength(); + + + NSURLResponse *response = [[NSURLResponse alloc] initWithURL:[request URL] + MIMEType:wxNSStringWithWxString(file->GetMimeType()) + expectedContentLength:length + textEncodingName:nil]; + + //Load the data, we malloc it so it is tidied up properly + void* buffer = malloc(length); + file->GetStream()->Read(buffer, length); + NSData *data = [[NSData alloc] initWithBytesNoCopy:buffer length:length]; + + //We do not support caching anything yet + [client URLProtocol:self didReceiveResponse:response + cacheStoragePolicy:NSURLCacheStorageNotAllowed]; + + //Set the data + [client URLProtocol:self didLoadData:data]; + + //Notify that we have finished + [client URLProtocolDidFinishLoading:self]; + + [response release]; +} + +- (void)stopLoading +{ + +} + +@end + + +@implementation WebViewUIDelegate + +- initWithWxWindow: (wxWebViewWebKit*)inWindow +{ + [super init]; + webKitWindow = inWindow; // non retained + return self; +} + +- (void)webView:(WebView *)sender printFrameView:(WebFrameView *)frameView +{ + wxUnusedVar(sender); + wxUnusedVar(frameView); + + webKitWindow->Print(); +} + +- (NSArray *)webView:(WebView *)sender contextMenuItemsForElement:(NSDictionary *)element + defaultMenuItems:(NSArray *) defaultMenuItems +{ + if(webKitWindow->IsContextMenuEnabled()) + return defaultMenuItems; + else + return nil; +} +@end + +#endif //wxUSE_WEBVIEW && wxUSE_WEBVIEW_WEBKIT