From: Steve Lamerton Date: Wed, 4 May 2011 18:24:30 +0000 (+0000) Subject: Set the correct svn properties on the new files. Correct a minor date typo. X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/61b98a2dac629cb5dbe1a6834ace6a33ba4eb103 Set the correct svn properties on the new files. Correct a minor date typo. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/SOC2011_WEBVIEW@67699 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/gtk/webview.h b/include/wx/gtk/webview.h index 88b53e892e..6d09870940 100644 --- a/include/wx/gtk/webview.h +++ b/include/wx/gtk/webview.h @@ -1,116 +1,116 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: include/gtk/wx/webview.h -// Purpose: GTK webkit backend for web view component -// Author: Robert Roebling, Marianne Gagnon -// Id: $Id$ -// Copyright: (c) 200 Marianne Gagnon, 1998 Robert Roebling -// Licence: wxWindows licence -///////////////////////////////////////////////////////////////////////////// - -#ifndef _WX_GTK_WEBKITCTRL_H_ -#define _WX_GTK_WEBKITCTRL_H_ - -#include "wx/setup.h" - -#if wxHAVE_WEB_BACKEND_GTK_WEBKIT - -#include "wx/webview.h" - -//----------------------------------------------------------------------------- -// wxWebViewGTKWebKit -//----------------------------------------------------------------------------- - -class WXDLLIMPEXP_CORE wxWebViewGTKWebKit : public wxWebView -{ -public: - wxWebViewGTKWebKit() { Init(); } - - wxWebViewGTKWebKit(wxWindow *parent, - wxWindowID id = wxID_ANY, - const wxString& url = wxWebViewDefaultURLStr, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, long style = 0, - const wxString& name = wxWebViewNameStr) - { - Init(); - - Create(parent, id, url, pos, size, style, name); - } - - virtual bool Create(wxWindow *parent, - wxWindowID id = wxID_ANY, - const wxString& url = wxWebViewDefaultURLStr, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, long style = 0, - const wxString& name = wxWebViewNameStr); - - virtual bool Enable( bool enable = true ); - - // implementation - // -------------- - - static wxVisualAttributes - GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL); - - // helper to allow access to protected member from GTK callback - void MoveWindow(int x, int y, int width, int height) - { - DoMoveWindow(x, y, width, height); - } - - void ZoomIn(); - void ZoomOut(); - void SetWebkitZoom(float level); - float GetWebkitZoom(); - - virtual void Stop(); - virtual void LoadUrl(const wxString& url); - virtual void GoBack(); - virtual void GoForward(); - virtual void Reload(wxWebViewReloadFlags flags = 0); - virtual bool CanGoBack(); - virtual bool CanGoForward(); - virtual wxString GetCurrentURL(); - virtual wxString GetCurrentTitle(); - virtual wxString GetPageSource(); - virtual void SetPage(const wxString& html, const wxString& baseUrl); - virtual void Print(); - virtual bool IsBusy(); - - void SetZoomType(wxWebViewZoomType); - wxWebViewZoomType GetZoomType() const; - bool CanSetZoomType(wxWebViewZoomType) const; - virtual wxWebViewZoom GetZoom(); - virtual void SetZoom(wxWebViewZoom); - - - - /** FIXME: hack to work around signals being received too early */ - bool m_ready; - - - /** TODO: check if this can be made private - * The native control has a getter to check for busy state, but except in - * very recent versions of webkit this getter doesn't say everything we need - * (namely it seems to stay indefinitely busy when loading is cancelled by - * user) - */ - bool m_busy; - -protected: - - virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const; - -private: - - // focus event handler: calls GTKUpdateBitmap() - void GTKOnFocus(wxFocusEvent& event); - - GtkWidget *web_view; - - // FIXME: try to get DECLARE_DYNAMIC_CLASS macros & stuff right - //DECLARE_DYNAMIC_CLASS(wxWebViewGTKWebKit) -}; - -#endif // if wxHAVE_WEB_BACKEND_GTK_WEBKIT - +///////////////////////////////////////////////////////////////////////////// +// Name: include/gtk/wx/webview.h +// Purpose: GTK webkit backend for web view component +// Author: Robert Roebling, Marianne Gagnon +// Id: $Id$ +// Copyright: (c) 2010 Marianne Gagnon, 1998 Robert Roebling +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_GTK_WEBKITCTRL_H_ +#define _WX_GTK_WEBKITCTRL_H_ + +#include "wx/setup.h" + +#if wxHAVE_WEB_BACKEND_GTK_WEBKIT + +#include "wx/webview.h" + +//----------------------------------------------------------------------------- +// wxWebViewGTKWebKit +//----------------------------------------------------------------------------- + +class WXDLLIMPEXP_CORE wxWebViewGTKWebKit : public wxWebView +{ +public: + wxWebViewGTKWebKit() { Init(); } + + wxWebViewGTKWebKit(wxWindow *parent, + wxWindowID id = wxID_ANY, + const wxString& url = wxWebViewDefaultURLStr, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, long style = 0, + const wxString& name = wxWebViewNameStr) + { + Init(); + + Create(parent, id, url, pos, size, style, name); + } + + virtual bool Create(wxWindow *parent, + wxWindowID id = wxID_ANY, + const wxString& url = wxWebViewDefaultURLStr, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, long style = 0, + const wxString& name = wxWebViewNameStr); + + virtual bool Enable( bool enable = true ); + + // implementation + // -------------- + + static wxVisualAttributes + GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL); + + // helper to allow access to protected member from GTK callback + void MoveWindow(int x, int y, int width, int height) + { + DoMoveWindow(x, y, width, height); + } + + void ZoomIn(); + void ZoomOut(); + void SetWebkitZoom(float level); + float GetWebkitZoom(); + + virtual void Stop(); + virtual void LoadUrl(const wxString& url); + virtual void GoBack(); + virtual void GoForward(); + virtual void Reload(wxWebViewReloadFlags flags = 0); + virtual bool CanGoBack(); + virtual bool CanGoForward(); + virtual wxString GetCurrentURL(); + virtual wxString GetCurrentTitle(); + virtual wxString GetPageSource(); + virtual void SetPage(const wxString& html, const wxString& baseUrl); + virtual void Print(); + virtual bool IsBusy(); + + void SetZoomType(wxWebViewZoomType); + wxWebViewZoomType GetZoomType() const; + bool CanSetZoomType(wxWebViewZoomType) const; + virtual wxWebViewZoom GetZoom(); + virtual void SetZoom(wxWebViewZoom); + + + + /** FIXME: hack to work around signals being received too early */ + bool m_ready; + + + /** TODO: check if this can be made private + * The native control has a getter to check for busy state, but except in + * very recent versions of webkit this getter doesn't say everything we need + * (namely it seems to stay indefinitely busy when loading is cancelled by + * user) + */ + bool m_busy; + +protected: + + virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const; + +private: + + // focus event handler: calls GTKUpdateBitmap() + void GTKOnFocus(wxFocusEvent& event); + + GtkWidget *web_view; + + // FIXME: try to get DECLARE_DYNAMIC_CLASS macros & stuff right + //DECLARE_DYNAMIC_CLASS(wxWebViewGTKWebKit) +}; + +#endif // if wxHAVE_WEB_BACKEND_GTK_WEBKIT + diff --git a/include/wx/msw/webviewie.h b/include/wx/msw/webviewie.h index 93f77d277a..0b94992877 100644 --- a/include/wx/msw/webviewie.h +++ b/include/wx/msw/webviewie.h @@ -1,126 +1,126 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: include/wx/msw/webviewie.h -// Purpose: wxMSW IE wxWebView backend -// Author: Marianne Gagnon -// Id: $Id$ -// Copyright: (c) 2010 Marianne Gagnon -// Licence: wxWindows licence -///////////////////////////////////////////////////////////////////////////// - -#ifndef wxWebViewIE_H -#define wxWebViewIE_H - -#include "wx/setup.h" - -#if wxHAVE_WEB_BACKEND_IE - -#include "wx/control.h" -#include "wx/webview.h" -#include "wx/msw/ole/automtn.h" -#include "wx/msw/ole/activex.h" - -// TODO: move this to wx/msw/chkconf.h -#if wxUSE_ACTIVEX != 1 -#error "wxUSE_ACTIVEX must be activated for this to work" -#endif - -#if wxUSE_OLE_AUTOMATION != 1 -#error "wxUSE_OLE_AUTOMATION must be activated for this to work" -#endif - -// FIXME: get those DLL export macros right... - -class wxWebViewIE : public wxWebView -{ -public: - - wxWebViewIE() {} - - wxWebViewIE(wxWindow* parent, - wxWindowID id, - const wxString& url = wxWebViewDefaultURLStr, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = 0, - const wxString& name = wxWebViewNameStr) - { - Create(parent, id, url, pos, size, style, name); - } - - bool Create(wxWindow* parent, - wxWindowID id, - const wxString& url = wxWebViewDefaultURLStr, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = 0, - const wxString& name = wxWebViewNameStr); - - virtual void LoadUrl(const wxString& url); - - virtual bool CanGoForward() { return m_canNavigateForward; } - virtual bool CanGoBack() { return m_canNavigateBack; } - virtual void GoBack(); - virtual void GoForward(); - virtual void Stop(); - virtual void Reload(wxWebViewReloadFlags flags=0); - - virtual wxString GetPageSource(); - - virtual bool IsBusy(); - virtual wxString GetCurrentURL(); - virtual wxString GetCurrentTitle(); - - virtual void SetZoomType(wxWebViewZoomType); - virtual wxWebViewZoomType GetZoomType() const; - virtual bool CanSetZoomType(wxWebViewZoomType) const; - - virtual void Print(); - - virtual void SetPage(const wxString& html, const wxString& baseUrl); - - virtual wxWebViewZoom GetZoom(); - virtual void SetZoom(wxWebViewZoom zoom); - - // ---- IE-specific methods - - // FIXME: I seem to be able to access remote webpages even in offline mode... - bool IsOfflineMode(); - void SetOfflineMode(bool offline); - - /** - * Get text zoom - * @return text zoom from 0 to 4 - */ - int GetIETextZoom(); - - /** - * @param level 0 to 4 - */ - void SetIETextZoom(int level); - - void SetIEOpticalZoom(float zoom); - float GetIEOpticalZoom(); - - void onActiveXEvent(wxActiveXEvent& evt); - void onEraseBg(wxEraseEvent& evt) {} - - DECLARE_EVENT_TABLE(); - -private: - wxActiveXContainer* m_container; - wxAutomationObject m_ie; - IWebBrowser2* m_webBrowser; - DWORD m_dwCookie; - bool m_canNavigateBack; - bool m_canNavigateForward; - - /** The "Busy" property of IWebBrowser2 does not always return busy when - * we'd want it to; this variable may be set to true in cases where the - * Busy property is false but should be true. - */ - bool m_isBusy; -}; - -#endif // wxHAVE_WEB_BACKEND_IE - -#endif // wxWebViewIE_H +///////////////////////////////////////////////////////////////////////////// +// Name: include/wx/msw/webviewie.h +// Purpose: wxMSW IE wxWebView backend +// Author: Marianne Gagnon +// Id: $Id$ +// Copyright: (c) 2010 Marianne Gagnon +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef wxWebViewIE_H +#define wxWebViewIE_H + +#include "wx/setup.h" + +#if wxHAVE_WEB_BACKEND_IE + +#include "wx/control.h" +#include "wx/webview.h" +#include "wx/msw/ole/automtn.h" +#include "wx/msw/ole/activex.h" + +// TODO: move this to wx/msw/chkconf.h +#if wxUSE_ACTIVEX != 1 +#error "wxUSE_ACTIVEX must be activated for this to work" +#endif + +#if wxUSE_OLE_AUTOMATION != 1 +#error "wxUSE_OLE_AUTOMATION must be activated for this to work" +#endif + +// FIXME: get those DLL export macros right... + +class wxWebViewIE : public wxWebView +{ +public: + + wxWebViewIE() {} + + wxWebViewIE(wxWindow* parent, + wxWindowID id, + const wxString& url = wxWebViewDefaultURLStr, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxString& name = wxWebViewNameStr) + { + Create(parent, id, url, pos, size, style, name); + } + + bool Create(wxWindow* parent, + wxWindowID id, + const wxString& url = wxWebViewDefaultURLStr, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxString& name = wxWebViewNameStr); + + virtual void LoadUrl(const wxString& url); + + virtual bool CanGoForward() { return m_canNavigateForward; } + virtual bool CanGoBack() { return m_canNavigateBack; } + virtual void GoBack(); + virtual void GoForward(); + virtual void Stop(); + virtual void Reload(wxWebViewReloadFlags flags=0); + + virtual wxString GetPageSource(); + + virtual bool IsBusy(); + virtual wxString GetCurrentURL(); + virtual wxString GetCurrentTitle(); + + virtual void SetZoomType(wxWebViewZoomType); + virtual wxWebViewZoomType GetZoomType() const; + virtual bool CanSetZoomType(wxWebViewZoomType) const; + + virtual void Print(); + + virtual void SetPage(const wxString& html, const wxString& baseUrl); + + virtual wxWebViewZoom GetZoom(); + virtual void SetZoom(wxWebViewZoom zoom); + + // ---- IE-specific methods + + // FIXME: I seem to be able to access remote webpages even in offline mode... + bool IsOfflineMode(); + void SetOfflineMode(bool offline); + + /** + * Get text zoom + * @return text zoom from 0 to 4 + */ + int GetIETextZoom(); + + /** + * @param level 0 to 4 + */ + void SetIETextZoom(int level); + + void SetIEOpticalZoom(float zoom); + float GetIEOpticalZoom(); + + void onActiveXEvent(wxActiveXEvent& evt); + void onEraseBg(wxEraseEvent& evt) {} + + DECLARE_EVENT_TABLE(); + +private: + wxActiveXContainer* m_container; + wxAutomationObject m_ie; + IWebBrowser2* m_webBrowser; + DWORD m_dwCookie; + bool m_canNavigateBack; + bool m_canNavigateForward; + + /** The "Busy" property of IWebBrowser2 does not always return busy when + * we'd want it to; this variable may be set to true in cases where the + * Busy property is false but should be true. + */ + bool m_isBusy; +}; + +#endif // wxHAVE_WEB_BACKEND_IE + +#endif // wxWebViewIE_H diff --git a/include/wx/osx/webview.h b/include/wx/osx/webview.h index 47a17e880f..2467442b8c 100644 --- a/include/wx/osx/webview.h +++ b/include/wx/osx/webview.h @@ -1,142 +1,142 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: include/wx/osx/webkit.h -// Purpose: wxOSXWebKitCtrl - embeddable web kit control, -// OS X implementation of web view component -// Author: Jethro Grassie / Kevin Ollivier / Marianne Gagnon -// Modified by: -// Created: 2004-4-16 -// RCS-ID: $Id$ -// Copyright: (c) Jethro Grassie / Kevin Ollivier / Marianne Gagnon -// Licence: wxWindows licence -///////////////////////////////////////////////////////////////////////////// - -#ifndef _WX_WEBKIT_H -#define _WX_WEBKIT_H - -#include "wx/setup.h" - -#if wxUSE_WEBKIT && (defined(__WXMAC__) || defined(__WXCOCOA__)) - -// TODO: define this in setup.h ? -#define wxHAVE_WEB_BACKEND_OSX_WEBKIT 1 - -#include "wx/control.h" -#include "wx/webview.h" - -// ---------------------------------------------------------------------------- -// Web Kit Control -// ---------------------------------------------------------------------------- - -class WXDLLIMPEXP_CORE wxOSXWebKitCtrl : public wxWebView -{ -public: - wxDECLARE_DYNAMIC_CLASS(wxOSXWebKitCtrl); - - wxOSXWebKitCtrl() {} - wxOSXWebKitCtrl(wxWindow *parent, - wxWindowID winID = wxID_ANY, - const wxString& strURL = wxWebViewDefaultURLStr, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, long style = 0, - const wxString& name = wxWebViewNameStr) - { - Create(parent, winID, strURL, pos, size, style, name); - } - bool Create(wxWindow *parent, - wxWindowID winID = wxID_ANY, - const wxString& strURL = wxWebViewDefaultURLStr, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, long style = 0, - const wxString& name = wxWebViewNameStr); - virtual ~wxOSXWebKitCtrl(); - - void InternalLoadURL(const wxString &url); - - virtual bool CanGoBack(); - virtual bool CanGoForward(); - virtual void GoBack(); - virtual void GoForward(); - virtual void Reload(wxWebViewReloadFlags flags = 0); - virtual void Stop(); - virtual wxString GetPageSource(); - virtual void SetPageTitle(const wxString& title) { m_pageTitle = title; } - virtual wxString GetPageTitle(){ return m_pageTitle; } - - virtual void SetPage(const wxString& html, const wxString& baseUrl); - - virtual void Print(); - - virtual void LoadUrl(const wxString& url); - virtual wxString GetCurrentURL(); - virtual wxString GetCurrentTitle(); - virtual wxWebViewZoom GetZoom(); - virtual void SetZoom(wxWebViewZoom zoom); - - virtual void SetZoomType(wxWebViewZoomType zoomType); - virtual wxWebViewZoomType GetZoomType() const; - virtual bool CanSetZoomType(wxWebViewZoomType type) const; - - virtual bool IsBusy() { return m_busy; } - - // ---- methods not from the parent (common) interface - wxString GetSelectedText(); - - wxString RunScript(const wxString& javascript); - - bool CanGetPageSource(); - - void SetScrollPos(int pos); - int GetScrollPos(); - - void MakeEditable(bool enable = true); - bool IsEditable(); - - wxString GetSelection(); - - bool CanIncreaseTextSize(); - void IncreaseTextSize(); - bool CanDecreaseTextSize(); - void DecreaseTextSize(); - - float GetWebkitZoom(); - void SetWebkitZoom(float zoom); - - // don't hide base class virtuals - virtual void SetScrollPos( int orient, int pos, bool refresh = true ) - { return wxControl::SetScrollPos(orient, pos, refresh); } - virtual int GetScrollPos( int orient ) const - { return wxControl::GetScrollPos(orient); } - - //we need to resize the webview when the control size changes - void OnSize(wxSizeEvent &event); - void OnMove(wxMoveEvent &event); - void OnMouseEvents(wxMouseEvent &event); - - bool m_busy; - -protected: - DECLARE_EVENT_TABLE() - void MacVisibilityChanged(); - -private: - wxWindow *m_parent; - wxWindowID m_windowID; - wxString m_pageTitle; - - struct objc_object *m_webView; - - // we may use this later to setup our own mouse events, - // so leave it in for now. - void* m_webKitCtrlEventHandler; - //It should be WebView*, but WebView is an Objective-C class - //TODO: look into using DECLARE_WXCOCOA_OBJC_CLASS rather than this. -}; - - -#else -// TODO: define this in setup.h ? -#define wxHAVE_WEB_BACKEND_OSX_WEBKIT 0 - -#endif // wxUSE_WEBKIT - -#endif // _WX_WEBKIT_H_ +///////////////////////////////////////////////////////////////////////////// +// Name: include/wx/osx/webkit.h +// Purpose: wxOSXWebKitCtrl - embeddable web kit control, +// OS X implementation of web view component +// Author: Jethro Grassie / Kevin Ollivier / Marianne Gagnon +// Modified by: +// Created: 2004-4-16 +// RCS-ID: $Id$ +// Copyright: (c) Jethro Grassie / Kevin Ollivier / Marianne Gagnon +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_WEBKIT_H +#define _WX_WEBKIT_H + +#include "wx/setup.h" + +#if wxUSE_WEBKIT && (defined(__WXMAC__) || defined(__WXCOCOA__)) + +// TODO: define this in setup.h ? +#define wxHAVE_WEB_BACKEND_OSX_WEBKIT 1 + +#include "wx/control.h" +#include "wx/webview.h" + +// ---------------------------------------------------------------------------- +// Web Kit Control +// ---------------------------------------------------------------------------- + +class WXDLLIMPEXP_CORE wxOSXWebKitCtrl : public wxWebView +{ +public: + wxDECLARE_DYNAMIC_CLASS(wxOSXWebKitCtrl); + + wxOSXWebKitCtrl() {} + wxOSXWebKitCtrl(wxWindow *parent, + wxWindowID winID = wxID_ANY, + const wxString& strURL = wxWebViewDefaultURLStr, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, long style = 0, + const wxString& name = wxWebViewNameStr) + { + Create(parent, winID, strURL, pos, size, style, name); + } + bool Create(wxWindow *parent, + wxWindowID winID = wxID_ANY, + const wxString& strURL = wxWebViewDefaultURLStr, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, long style = 0, + const wxString& name = wxWebViewNameStr); + virtual ~wxOSXWebKitCtrl(); + + void InternalLoadURL(const wxString &url); + + virtual bool CanGoBack(); + virtual bool CanGoForward(); + virtual void GoBack(); + virtual void GoForward(); + virtual void Reload(wxWebViewReloadFlags flags = 0); + virtual void Stop(); + virtual wxString GetPageSource(); + virtual void SetPageTitle(const wxString& title) { m_pageTitle = title; } + virtual wxString GetPageTitle(){ return m_pageTitle; } + + virtual void SetPage(const wxString& html, const wxString& baseUrl); + + virtual void Print(); + + virtual void LoadUrl(const wxString& url); + virtual wxString GetCurrentURL(); + virtual wxString GetCurrentTitle(); + virtual wxWebViewZoom GetZoom(); + virtual void SetZoom(wxWebViewZoom zoom); + + virtual void SetZoomType(wxWebViewZoomType zoomType); + virtual wxWebViewZoomType GetZoomType() const; + virtual bool CanSetZoomType(wxWebViewZoomType type) const; + + virtual bool IsBusy() { return m_busy; } + + // ---- methods not from the parent (common) interface + wxString GetSelectedText(); + + wxString RunScript(const wxString& javascript); + + bool CanGetPageSource(); + + void SetScrollPos(int pos); + int GetScrollPos(); + + void MakeEditable(bool enable = true); + bool IsEditable(); + + wxString GetSelection(); + + bool CanIncreaseTextSize(); + void IncreaseTextSize(); + bool CanDecreaseTextSize(); + void DecreaseTextSize(); + + float GetWebkitZoom(); + void SetWebkitZoom(float zoom); + + // don't hide base class virtuals + virtual void SetScrollPos( int orient, int pos, bool refresh = true ) + { return wxControl::SetScrollPos(orient, pos, refresh); } + virtual int GetScrollPos( int orient ) const + { return wxControl::GetScrollPos(orient); } + + //we need to resize the webview when the control size changes + void OnSize(wxSizeEvent &event); + void OnMove(wxMoveEvent &event); + void OnMouseEvents(wxMouseEvent &event); + + bool m_busy; + +protected: + DECLARE_EVENT_TABLE() + void MacVisibilityChanged(); + +private: + wxWindow *m_parent; + wxWindowID m_windowID; + wxString m_pageTitle; + + struct objc_object *m_webView; + + // we may use this later to setup our own mouse events, + // so leave it in for now. + void* m_webKitCtrlEventHandler; + //It should be WebView*, but WebView is an Objective-C class + //TODO: look into using DECLARE_WXCOCOA_OBJC_CLASS rather than this. +}; + + +#else +// TODO: define this in setup.h ? +#define wxHAVE_WEB_BACKEND_OSX_WEBKIT 0 + +#endif // wxUSE_WEBKIT + +#endif // _WX_WEBKIT_H_ diff --git a/include/wx/webview.h b/include/wx/webview.h index bd60cd82d7..9dbefdc9c6 100644 --- a/include/wx/webview.h +++ b/include/wx/webview.h @@ -1,429 +1,429 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: webview.h -// Purpose: Common interface and events for web view component -// Author: Marianne Gagnon -// Id: $Id$ -// Copyright: (c) 2010 Marianne Gagnon -// Licence: wxWindows licence -///////////////////////////////////////////////////////////////////////////// - -#ifndef _WX_WEB_VIEW_H_ -#define _WX_WEB_VIEW_H_ - -#include -#include -#include - -/** - * Zoom level in web view component - */ -enum wxWebViewZoom -{ - wxWEB_VIEW_ZOOM_TINY, - wxWEB_VIEW_ZOOM_SMALL, - wxWEB_VIEW_ZOOM_MEDIUM, - wxWEB_VIEW_ZOOM_LARGE, - wxWEB_VIEW_ZOOM_LARGEST -}; - -/** - * The type of zooming that the web view control can perform - */ -enum wxWebViewZoomType -{ - /** The entire layout scales when zooming, including images */ - wxWEB_VIEW_ZOOM_TYPE_LAYOUT, - /** Only the text changes in size when zooming, images and other layout - * elements retain their initial size */ - wxWEB_VIEW_ZOOM_TYPE_TEXT -}; - -/** Types of errors that can cause navigation to fail */ -enum wxWebNavigationError -{ - /** Connection error (timeout, etc.) */ - wxWEB_NAV_ERR_CONNECTION = 1, - /** Invalid certificate */ - wxWEB_NAV_ERR_CERTIFICATE = 2, - /** Authentication required */ - wxWEB_NAV_ERR_AUTH = 3, - /** Other security error */ - wxWEB_NAV_ERR_SECURITY = 4, - /** Requested resource not found */ - wxWEB_NAV_ERR_NOT_FOUND = 5, - /** Invalid request/parameters (e.g. bad URL, bad protocol, - * unsupported resource type) */ - wxWEB_NAV_ERR_REQUEST = 6, - /** The user cancelled (e.g. in a dialog) */ - wxWEB_NAV_ERR_USER_CANCELLED = 7, - /** Another (exotic) type of error that didn't fit in other categories*/ - wxWEB_NAV_ERR_OTHER = 8 -}; - -/** Type of refresh */ -enum wxWebViewReloadFlags -{ - /** Reload the current view without accessing the cache */ - wxWEB_VIEW_RELOAD_NO_CACHE = 1 -}; - - -/** - * List of available backends for wxWebView - */ -enum wxWebViewBackend -{ - /** Value that may be passed to wxWebView to let it pick an appropriate - * engine for the current platform*/ - wxWEB_VIEW_BACKEND_DEFAULT, - - /** The OSX-native WebKit web engine */ - wxWEB_VIEW_BACKEND_OSX_WEBKIT, - - /** The GTK port of the WebKit engine */ - wxWEB_VIEW_BACKEND_GTK_WEBKIT, - - /** Use Microsoft Internet Explorer as web engine */ - wxWEB_VIEW_BACKEND_IE -}; - -extern WXDLLIMPEXP_DATA_CORE(const char) wxWebViewNameStr[]; -extern WXDLLIMPEXP_DATA_CORE(const char) wxWebViewDefaultURLStr[]; - -/** - * @class wxWebView - * - * This control may be used to render web (HTML / CSS / javascript) documents. - * Capabilities of the HTML renderer will depend upon the backed. - * TODO: describe each backend and its capabilities here - * - * Note that errors are generally reported asynchronously though the - * wxEVT_COMMAND_WEB_VIEW_ERROR event described below. - * - * @beginEventEmissionTable{wxWebNavigationEvent} - * @event{EVT_BUTTON(id, func)} - * - * @event{EVT_WEB_VIEW_NAVIGATING(id, func)} - * Process a wxEVT_COMMAND_WEB_VIEW_NAVIGATING event, generated before trying - * to get a resource. This event may be vetoed to prevent navigating to this - * resource. Note that if the displayed HTML document has several frames, one - * such event will be generated per frame. - * - * @event{EVT_WEB_VIEW_NAVIGATED(id, func)} - * Process a wxEVT_COMMAND_WEB_VIEW_NAVIGATED event generated after it was - * confirmed that a resource would be requested. This event may not be vetoed. - * Note that if the displayed HTML document has several frames, one such event - * will be generated per frame. - * - * @event{EVT_WEB_VIEW_LOADED(id, func)} - * Process a wxEVT_COMMAND_WEB_VIEW_LOADED event generated when the document - * is fully loaded and displayed. - * - * @event{EVT_WEB_VIEW_ERRROR(id, func)} - * Process a wxEVT_COMMAND_WEB_VIEW_ERROR event generated when a navigation - * error occurs. - * The integer associated with this event will be a wxWebNavigationError item. - * The string associated with this event may contain a backend-specific more - * precise error message/code. - * - * @endEventTable - */ -class wxWebView : public wxControl -{ -public: - - /** - * Creation function for two-step creation. - */ - virtual bool Create(wxWindow* parent, - wxWindowID id, - const wxString& url, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name) = 0; - - /** - * Factory function to create a new wxWebView for two-step creation - * (you need to call wxWebView::Create on the returned object) - * @param backend which web engine to use as backend for wxWebView - * @return the created wxWebView, or NULL if the requested backend is - * not available - */ - static wxWebView* New(wxWebViewBackend backend = wxWEB_VIEW_BACKEND_DEFAULT); - - // TODO: clarify what styles can do, or remove this flag - /** - * Factory function to create a new wxWebView - * @param parent parent window to create this view in - * @param id ID of this control - * @param url URL to load by default in the web view - * @param pos position to create this control at - * (you may use wxDefaultPosition if you use sizers) - * @param size size to create this control with - * (you may use wxDefaultSize if you use sizers) - * @param backend which web engine to use as backend for wxWebView - * @return the created wxWebView, or NULL if the requested backend - * is not available - */ - static wxWebView* New(wxWindow* parent, - wxWindowID id, - const wxString& url = wxWebViewDefaultURLStr, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - wxWebViewBackend backend = wxWEB_VIEW_BACKEND_DEFAULT, - long style = 0, - const wxString& name = wxWebViewNameStr); - - - /** Get whether it is possible to navigate back in the history of - * visited pages - */ - virtual bool CanGoBack() = 0; - - /** Get whether it is possible to navigate forward in the history of - * visited pages - */ - virtual bool CanGoForward() = 0; - - /** Navigate back in the history of visited pages. - * Only valid if CanGoBack() returned true. - */ - virtual void GoBack() = 0; - - /** Navigate forwardin the history of visited pages. - * Only valid if CanGoForward() returned true. - */ - virtual void GoForward() = 0; - - /** - * Load a HTMl document (web page) from a URL - * @param url the URL where the HTML document to display can be found - * @note web engines generally report errors asynchronously, so if you wish - * to know whether loading the URL was successful, register to receive - * navigation error events - */ - virtual void LoadUrl(const wxString& url) = 0; - - /** - * Stop the current page loading process, if any. - * May trigger an error event of type wxWEB_NAV_ERR_USER_CANCELLED. - * TODO: make wxWEB_NAV_ERR_USER_CANCELLED errors uniform across ports. - */ - virtual void Stop() = 0; - - /** - * Reload the currently displayed URL. - * @param flags A bit array that may optionnally contain reload options - */ - virtual void Reload(wxWebViewReloadFlags flags=0) = 0; - - - /** - * Get the URL of the currently displayed document - */ - virtual wxString GetCurrentURL() = 0; - - /** - * Get the title of the current web page, or its URL/path if title is not - * available - */ - virtual wxString GetCurrentTitle() = 0; - - // TODO: handle choosing a frame when calling GetPageSource()? - /** - * Get the HTML source code of the currently displayed document - * @return the HTML source code, or an empty string if no page is currently - * shown - */ - virtual wxString GetPageSource() = 0; - - /** - * Get the zoom factor of the page - * @return How much the HTML document is zoomed (scaleed) - */ - virtual wxWebViewZoom GetZoom() = 0; - - /** - * Set the zoom factor of the page - * @param zoom How much to zoom (scale) the HTML document - */ - virtual void SetZoom(wxWebViewZoom zoom) = 0; - - /** - * Set how to interpret the zoom factor - * @param zoomType how the zoom factor should be interpreted by the - * HTML engine - * @note invoke canSetZoomType() first, some HTML renderers may not - * support all zoom types - */ - virtual void SetZoomType(wxWebViewZoomType zoomType) = 0; - - /** - * Get how the zoom factor is currently interpreted - * @return how the zoom factor is currently interpreted by the HTML engine - */ - virtual wxWebViewZoomType GetZoomType() const = 0; - - /** - * Retrieve whether the current HTML engine supports a type of zoom - * @param type the type of zoom to test - * @return whether this type of zoom is supported by this HTML engine - * (and thus can be set through setZoomType()) - */ - virtual bool CanSetZoomType(wxWebViewZoomType type) const = 0; - - // TODO: allow 'SetPage' to find files (e.g. images) from a virtual file - // system if possible - /** - * Set the displayed page source to the contents of the given string - * @param html the string that contains the HTML data to display - * @param baseUrl URL assigned to the HTML data, to be used to resolve - * relative paths, for instance - */ - virtual void SetPage(const wxString& html, const wxString& baseUrl) = 0; - - /** - * Set the displayed page source to the contents of the given stream - * @param html the stream to read HTML data from - * @param baseUrl URL assigned to the HTML data, to be used to resolve - * relative paths, for instance - */ - virtual void SetPage(wxInputStream& html, wxString baseUrl) - { - wxStringOutputStream stream; - stream.Write(html); - SetPage(stream.GetString(), baseUrl); - } - - // TODO: - // wxString GetSelection(); // maybe? - // void SetSelection(...); // maybe? - - // void MakeEditable(bool enable = true); // maybe? - // bool IsEditable(); // maybe? - - // void EnableJavascript(bool enabled); // maybe? - // wxString RunScript(const wxString& javascript); // maybe? - - // void SetScrollPos(int pos); // maybe? - // int GetScrollPos(); // maybe? - - // wxString GetStatusText(); // maybe? - // void SetStatusText(wxString text); // maybe? - // * status text changed event? - // * title changed event? - - // virtual bool IsOfflineMode() = 0; // maybe? - // virtual void SetOfflineMode(bool offline) = 0; // maybe? - - // TODO: offer API to control the opening of new frames - // (through as well as through javascript), OR - // provide a behavior consistent across ports. - // - OSX : I receive an event for new frames opened with HTML target, and - // currently block them all. - // - IE : The DISPID_NEWWINDOW2 event looks like it should work, but I - // receive way too many of them. A new IE instance opens. - // - GTK : All frame open requests are blocked. A slot exists that I could - // connect to to be notified if ever needed - - /** - * Opens a print dialog so that the user may print the currently - * displayed page. - */ - virtual void Print() = 0; - - /** - * Returns whether the web control is currently busy (e.g. loading a page) - */ - virtual bool IsBusy() = 0; -}; - -//class WXDLLIMPEXP_FWD_HTML wxWebNavigationEvent; - -// FIXME: get those WXDLLIMPEXP_HTML & DECLARE_DYNAMIC_CLASS right... -//wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_HTML, wxEVT_COMMAND_WEB_VIEW_NAVIGATE, -// wxWebNavigationEvent ); - - -// FIXME: get those WXDLLIMPEXP_HTML & DECLARE_DYNAMIC_CLASS right... -class wxWebNavigationEvent : public wxCommandEvent -{ -public: - wxWebNavigationEvent() {} - wxWebNavigationEvent(wxEventType type, int id, const wxString href, - const wxString target, bool canVeto) - : wxCommandEvent(type, id) - { - m_href = href; - m_target = target; - m_vetoed = false; - m_canVeto = canVeto; - } - - /** - * Get the URL being visited - */ - const wxString& GetHref() const { return m_href; } - - /** - * Get the target (frame or window) in which the URL that caused this event - * is viewed, or an empty string if not available. - */ - const wxString& GetTarget() const { return m_target; } - - // default copy ctor, assignment operator and dtor are ok - virtual wxEvent* Clone() const { return new wxWebNavigationEvent(*this); } - - /** Get whether this event may be vetoed (stopped/prevented). Only - * meaningful for events fired before navigation takes place. - */ - bool CanVeto() const { return m_canVeto; } - - /** Whether this event was vetoed (stopped/prevented). Only meaningful for - * events fired before navigation takes place. - */ - bool IsVetoed() const { return m_vetoed; } - - /** Veto (prevent/stop) this event. Only meaningful for events fired - * before navigation takes place. Only valid if CanVeto() returned true. - */ - void Veto() { wxASSERT(m_canVeto); m_vetoed = true; } - -private: - wxString m_href; - wxString m_target; - bool m_canVeto; - bool m_vetoed; - - wxDECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxWebNavigationEvent); -}; - -wxDECLARE_EVENT( wxEVT_COMMAND_WEB_VIEW_NAVIGATING, wxWebNavigationEvent ); -wxDECLARE_EVENT( wxEVT_COMMAND_WEB_VIEW_NAVIGATED, wxWebNavigationEvent ); -wxDECLARE_EVENT( wxEVT_COMMAND_WEB_VIEW_LOADED, wxWebNavigationEvent ); -wxDECLARE_EVENT( wxEVT_COMMAND_WEB_VIEW_ERROR, wxWebNavigationEvent ); - -typedef void (wxEvtHandler::*wxWebNavigationEventFunction) - (wxWebNavigationEvent&); - -#define wxWebNavigationEventHandler(func) \ - wxEVENT_HANDLER_CAST(wxWebNavigationEventFunction, func) - -#define EVT_WEB_VIEW_NAVIGATING(id, fn) \ - wx__DECLARE_EVT1(wxEVT_COMMAND_WEB_VIEW_NAVIGATING, id, - wxHtmlNavigatingEventHandler(fn)) - -#define EVT_WEB_VIEW_NAVIGATED(id, fn) \ - wx__DECLARE_EVT1(wxEVT_COMMAND_WEB_VIEW_NAVIGATED, id, - wxHtmlNavigatingEventHandler(fn)) - -#define EVT_WEB_VIEW_LOADED(id, fn) \ - wx__DECLARE_EVT1(wxEVT_COMMAND_WEB_VIEW_LOADED, id, - wxHtmlNavigatingEventHandler(fn)) - -#define EVT_WEB_VIEW_ERRROR(id, fn) \ - wx__DECLARE_EVT1(wxEVT_COMMAND_WEB_VIEW_ERROR, id, - wxHtmlNavigatingEventHandler(fn)) - -#endif +///////////////////////////////////////////////////////////////////////////// +// Name: webview.h +// Purpose: Common interface and events for web view component +// Author: Marianne Gagnon +// Id: $Id$ +// Copyright: (c) 2010 Marianne Gagnon +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_WEB_VIEW_H_ +#define _WX_WEB_VIEW_H_ + +#include +#include +#include + +/** + * Zoom level in web view component + */ +enum wxWebViewZoom +{ + wxWEB_VIEW_ZOOM_TINY, + wxWEB_VIEW_ZOOM_SMALL, + wxWEB_VIEW_ZOOM_MEDIUM, + wxWEB_VIEW_ZOOM_LARGE, + wxWEB_VIEW_ZOOM_LARGEST +}; + +/** + * The type of zooming that the web view control can perform + */ +enum wxWebViewZoomType +{ + /** The entire layout scales when zooming, including images */ + wxWEB_VIEW_ZOOM_TYPE_LAYOUT, + /** Only the text changes in size when zooming, images and other layout + * elements retain their initial size */ + wxWEB_VIEW_ZOOM_TYPE_TEXT +}; + +/** Types of errors that can cause navigation to fail */ +enum wxWebNavigationError +{ + /** Connection error (timeout, etc.) */ + wxWEB_NAV_ERR_CONNECTION = 1, + /** Invalid certificate */ + wxWEB_NAV_ERR_CERTIFICATE = 2, + /** Authentication required */ + wxWEB_NAV_ERR_AUTH = 3, + /** Other security error */ + wxWEB_NAV_ERR_SECURITY = 4, + /** Requested resource not found */ + wxWEB_NAV_ERR_NOT_FOUND = 5, + /** Invalid request/parameters (e.g. bad URL, bad protocol, + * unsupported resource type) */ + wxWEB_NAV_ERR_REQUEST = 6, + /** The user cancelled (e.g. in a dialog) */ + wxWEB_NAV_ERR_USER_CANCELLED = 7, + /** Another (exotic) type of error that didn't fit in other categories*/ + wxWEB_NAV_ERR_OTHER = 8 +}; + +/** Type of refresh */ +enum wxWebViewReloadFlags +{ + /** Reload the current view without accessing the cache */ + wxWEB_VIEW_RELOAD_NO_CACHE = 1 +}; + + +/** + * List of available backends for wxWebView + */ +enum wxWebViewBackend +{ + /** Value that may be passed to wxWebView to let it pick an appropriate + * engine for the current platform*/ + wxWEB_VIEW_BACKEND_DEFAULT, + + /** The OSX-native WebKit web engine */ + wxWEB_VIEW_BACKEND_OSX_WEBKIT, + + /** The GTK port of the WebKit engine */ + wxWEB_VIEW_BACKEND_GTK_WEBKIT, + + /** Use Microsoft Internet Explorer as web engine */ + wxWEB_VIEW_BACKEND_IE +}; + +extern WXDLLIMPEXP_DATA_CORE(const char) wxWebViewNameStr[]; +extern WXDLLIMPEXP_DATA_CORE(const char) wxWebViewDefaultURLStr[]; + +/** + * @class wxWebView + * + * This control may be used to render web (HTML / CSS / javascript) documents. + * Capabilities of the HTML renderer will depend upon the backed. + * TODO: describe each backend and its capabilities here + * + * Note that errors are generally reported asynchronously though the + * wxEVT_COMMAND_WEB_VIEW_ERROR event described below. + * + * @beginEventEmissionTable{wxWebNavigationEvent} + * @event{EVT_BUTTON(id, func)} + * + * @event{EVT_WEB_VIEW_NAVIGATING(id, func)} + * Process a wxEVT_COMMAND_WEB_VIEW_NAVIGATING event, generated before trying + * to get a resource. This event may be vetoed to prevent navigating to this + * resource. Note that if the displayed HTML document has several frames, one + * such event will be generated per frame. + * + * @event{EVT_WEB_VIEW_NAVIGATED(id, func)} + * Process a wxEVT_COMMAND_WEB_VIEW_NAVIGATED event generated after it was + * confirmed that a resource would be requested. This event may not be vetoed. + * Note that if the displayed HTML document has several frames, one such event + * will be generated per frame. + * + * @event{EVT_WEB_VIEW_LOADED(id, func)} + * Process a wxEVT_COMMAND_WEB_VIEW_LOADED event generated when the document + * is fully loaded and displayed. + * + * @event{EVT_WEB_VIEW_ERRROR(id, func)} + * Process a wxEVT_COMMAND_WEB_VIEW_ERROR event generated when a navigation + * error occurs. + * The integer associated with this event will be a wxWebNavigationError item. + * The string associated with this event may contain a backend-specific more + * precise error message/code. + * + * @endEventTable + */ +class wxWebView : public wxControl +{ +public: + + /** + * Creation function for two-step creation. + */ + virtual bool Create(wxWindow* parent, + wxWindowID id, + const wxString& url, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name) = 0; + + /** + * Factory function to create a new wxWebView for two-step creation + * (you need to call wxWebView::Create on the returned object) + * @param backend which web engine to use as backend for wxWebView + * @return the created wxWebView, or NULL if the requested backend is + * not available + */ + static wxWebView* New(wxWebViewBackend backend = wxWEB_VIEW_BACKEND_DEFAULT); + + // TODO: clarify what styles can do, or remove this flag + /** + * Factory function to create a new wxWebView + * @param parent parent window to create this view in + * @param id ID of this control + * @param url URL to load by default in the web view + * @param pos position to create this control at + * (you may use wxDefaultPosition if you use sizers) + * @param size size to create this control with + * (you may use wxDefaultSize if you use sizers) + * @param backend which web engine to use as backend for wxWebView + * @return the created wxWebView, or NULL if the requested backend + * is not available + */ + static wxWebView* New(wxWindow* parent, + wxWindowID id, + const wxString& url = wxWebViewDefaultURLStr, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + wxWebViewBackend backend = wxWEB_VIEW_BACKEND_DEFAULT, + long style = 0, + const wxString& name = wxWebViewNameStr); + + + /** Get whether it is possible to navigate back in the history of + * visited pages + */ + virtual bool CanGoBack() = 0; + + /** Get whether it is possible to navigate forward in the history of + * visited pages + */ + virtual bool CanGoForward() = 0; + + /** Navigate back in the history of visited pages. + * Only valid if CanGoBack() returned true. + */ + virtual void GoBack() = 0; + + /** Navigate forwardin the history of visited pages. + * Only valid if CanGoForward() returned true. + */ + virtual void GoForward() = 0; + + /** + * Load a HTMl document (web page) from a URL + * @param url the URL where the HTML document to display can be found + * @note web engines generally report errors asynchronously, so if you wish + * to know whether loading the URL was successful, register to receive + * navigation error events + */ + virtual void LoadUrl(const wxString& url) = 0; + + /** + * Stop the current page loading process, if any. + * May trigger an error event of type wxWEB_NAV_ERR_USER_CANCELLED. + * TODO: make wxWEB_NAV_ERR_USER_CANCELLED errors uniform across ports. + */ + virtual void Stop() = 0; + + /** + * Reload the currently displayed URL. + * @param flags A bit array that may optionnally contain reload options + */ + virtual void Reload(wxWebViewReloadFlags flags=0) = 0; + + + /** + * Get the URL of the currently displayed document + */ + virtual wxString GetCurrentURL() = 0; + + /** + * Get the title of the current web page, or its URL/path if title is not + * available + */ + virtual wxString GetCurrentTitle() = 0; + + // TODO: handle choosing a frame when calling GetPageSource()? + /** + * Get the HTML source code of the currently displayed document + * @return the HTML source code, or an empty string if no page is currently + * shown + */ + virtual wxString GetPageSource() = 0; + + /** + * Get the zoom factor of the page + * @return How much the HTML document is zoomed (scaleed) + */ + virtual wxWebViewZoom GetZoom() = 0; + + /** + * Set the zoom factor of the page + * @param zoom How much to zoom (scale) the HTML document + */ + virtual void SetZoom(wxWebViewZoom zoom) = 0; + + /** + * Set how to interpret the zoom factor + * @param zoomType how the zoom factor should be interpreted by the + * HTML engine + * @note invoke canSetZoomType() first, some HTML renderers may not + * support all zoom types + */ + virtual void SetZoomType(wxWebViewZoomType zoomType) = 0; + + /** + * Get how the zoom factor is currently interpreted + * @return how the zoom factor is currently interpreted by the HTML engine + */ + virtual wxWebViewZoomType GetZoomType() const = 0; + + /** + * Retrieve whether the current HTML engine supports a type of zoom + * @param type the type of zoom to test + * @return whether this type of zoom is supported by this HTML engine + * (and thus can be set through setZoomType()) + */ + virtual bool CanSetZoomType(wxWebViewZoomType type) const = 0; + + // TODO: allow 'SetPage' to find files (e.g. images) from a virtual file + // system if possible + /** + * Set the displayed page source to the contents of the given string + * @param html the string that contains the HTML data to display + * @param baseUrl URL assigned to the HTML data, to be used to resolve + * relative paths, for instance + */ + virtual void SetPage(const wxString& html, const wxString& baseUrl) = 0; + + /** + * Set the displayed page source to the contents of the given stream + * @param html the stream to read HTML data from + * @param baseUrl URL assigned to the HTML data, to be used to resolve + * relative paths, for instance + */ + virtual void SetPage(wxInputStream& html, wxString baseUrl) + { + wxStringOutputStream stream; + stream.Write(html); + SetPage(stream.GetString(), baseUrl); + } + + // TODO: + // wxString GetSelection(); // maybe? + // void SetSelection(...); // maybe? + + // void MakeEditable(bool enable = true); // maybe? + // bool IsEditable(); // maybe? + + // void EnableJavascript(bool enabled); // maybe? + // wxString RunScript(const wxString& javascript); // maybe? + + // void SetScrollPos(int pos); // maybe? + // int GetScrollPos(); // maybe? + + // wxString GetStatusText(); // maybe? + // void SetStatusText(wxString text); // maybe? + // * status text changed event? + // * title changed event? + + // virtual bool IsOfflineMode() = 0; // maybe? + // virtual void SetOfflineMode(bool offline) = 0; // maybe? + + // TODO: offer API to control the opening of new frames + // (through as well as through javascript), OR + // provide a behavior consistent across ports. + // - OSX : I receive an event for new frames opened with HTML target, and + // currently block them all. + // - IE : The DISPID_NEWWINDOW2 event looks like it should work, but I + // receive way too many of them. A new IE instance opens. + // - GTK : All frame open requests are blocked. A slot exists that I could + // connect to to be notified if ever needed + + /** + * Opens a print dialog so that the user may print the currently + * displayed page. + */ + virtual void Print() = 0; + + /** + * Returns whether the web control is currently busy (e.g. loading a page) + */ + virtual bool IsBusy() = 0; +}; + +//class WXDLLIMPEXP_FWD_HTML wxWebNavigationEvent; + +// FIXME: get those WXDLLIMPEXP_HTML & DECLARE_DYNAMIC_CLASS right... +//wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_HTML, wxEVT_COMMAND_WEB_VIEW_NAVIGATE, +// wxWebNavigationEvent ); + + +// FIXME: get those WXDLLIMPEXP_HTML & DECLARE_DYNAMIC_CLASS right... +class wxWebNavigationEvent : public wxCommandEvent +{ +public: + wxWebNavigationEvent() {} + wxWebNavigationEvent(wxEventType type, int id, const wxString href, + const wxString target, bool canVeto) + : wxCommandEvent(type, id) + { + m_href = href; + m_target = target; + m_vetoed = false; + m_canVeto = canVeto; + } + + /** + * Get the URL being visited + */ + const wxString& GetHref() const { return m_href; } + + /** + * Get the target (frame or window) in which the URL that caused this event + * is viewed, or an empty string if not available. + */ + const wxString& GetTarget() const { return m_target; } + + // default copy ctor, assignment operator and dtor are ok + virtual wxEvent* Clone() const { return new wxWebNavigationEvent(*this); } + + /** Get whether this event may be vetoed (stopped/prevented). Only + * meaningful for events fired before navigation takes place. + */ + bool CanVeto() const { return m_canVeto; } + + /** Whether this event was vetoed (stopped/prevented). Only meaningful for + * events fired before navigation takes place. + */ + bool IsVetoed() const { return m_vetoed; } + + /** Veto (prevent/stop) this event. Only meaningful for events fired + * before navigation takes place. Only valid if CanVeto() returned true. + */ + void Veto() { wxASSERT(m_canVeto); m_vetoed = true; } + +private: + wxString m_href; + wxString m_target; + bool m_canVeto; + bool m_vetoed; + + wxDECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxWebNavigationEvent); +}; + +wxDECLARE_EVENT( wxEVT_COMMAND_WEB_VIEW_NAVIGATING, wxWebNavigationEvent ); +wxDECLARE_EVENT( wxEVT_COMMAND_WEB_VIEW_NAVIGATED, wxWebNavigationEvent ); +wxDECLARE_EVENT( wxEVT_COMMAND_WEB_VIEW_LOADED, wxWebNavigationEvent ); +wxDECLARE_EVENT( wxEVT_COMMAND_WEB_VIEW_ERROR, wxWebNavigationEvent ); + +typedef void (wxEvtHandler::*wxWebNavigationEventFunction) + (wxWebNavigationEvent&); + +#define wxWebNavigationEventHandler(func) \ + wxEVENT_HANDLER_CAST(wxWebNavigationEventFunction, func) + +#define EVT_WEB_VIEW_NAVIGATING(id, fn) \ + wx__DECLARE_EVT1(wxEVT_COMMAND_WEB_VIEW_NAVIGATING, id, + wxHtmlNavigatingEventHandler(fn)) + +#define EVT_WEB_VIEW_NAVIGATED(id, fn) \ + wx__DECLARE_EVT1(wxEVT_COMMAND_WEB_VIEW_NAVIGATED, id, + wxHtmlNavigatingEventHandler(fn)) + +#define EVT_WEB_VIEW_LOADED(id, fn) \ + wx__DECLARE_EVT1(wxEVT_COMMAND_WEB_VIEW_LOADED, id, + wxHtmlNavigatingEventHandler(fn)) + +#define EVT_WEB_VIEW_ERRROR(id, fn) \ + wx__DECLARE_EVT1(wxEVT_COMMAND_WEB_VIEW_ERROR, id, + wxHtmlNavigatingEventHandler(fn)) + +#endif diff --git a/samples/web/web.cpp b/samples/web/web.cpp index befae13521..b5ad05da5e 100644 --- a/samples/web/web.cpp +++ b/samples/web/web.cpp @@ -1,640 +1,640 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: wxiepanel.cpp -// Purpose: wxBetterHTMLControl test -// Author: Marianne Gagnon -// Id: $Id$ -// Copyright: (c) 2010 Marianne Gagnon -// Licence: wxWindows licence -///////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include - -#if wxUSE_STC -#include -#else -#error "wxStyledTextControl is needed by this sample" -#endif - -#include "wx/webview.h" -#include "wxlogo.xpm" -#include "back.xpm" -#include "forward.xpm" -#include "stop.xpm" -#include "refresh.xpm" - -// -------------------------------------------------------------------------------------------------- -// SOURCE VIEW FRAME -// -------------------------------------------------------------------------------------------------- -enum -{ - MARGIN_LINE_NUMBERS, - //MARGIN_DIVIDER, - //MARGIN_FOLDING -}; - -class SourceViewDialog : public wxDialog -{ -public: - - void onClose(wxCloseEvent& evt) - { - EndModal( GetReturnCode() ); - } - - SourceViewDialog(wxWindow* parent, wxString source) : - wxDialog(parent, wxID_ANY, "Source Code", - wxDefaultPosition, wxSize(700,500), - wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) - { - wxStyledTextCtrl* text = new wxStyledTextCtrl(this, wxID_ANY); - - //text->SetLexer(wxSTC_LEX_HTML); - text->SetMarginWidth (MARGIN_LINE_NUMBERS, 50); - text->StyleSetForeground (wxSTC_STYLE_LINENUMBER, wxColour (75, 75, 75) ); - text->StyleSetBackground (wxSTC_STYLE_LINENUMBER, wxColour (220, 220, 220)); - text->SetMarginType (MARGIN_LINE_NUMBERS, wxSTC_MARGIN_NUMBER); - - text->SetWrapMode (wxSTC_WRAP_WORD); - - text->SetText(source); - - text->StyleClearAll(); - text->SetLexer(wxSTC_LEX_HTML); - text->StyleSetForeground (wxSTC_H_DOUBLESTRING, wxColour(255,0,0)); - text->StyleSetForeground (wxSTC_H_SINGLESTRING, wxColour(255,0,0)); - text->StyleSetForeground (wxSTC_H_ENTITY, wxColour(255,0,0)); - text->StyleSetForeground (wxSTC_H_TAG, wxColour(0,150,0)); - text->StyleSetForeground (wxSTC_H_TAGUNKNOWN, wxColour(0,150,0)); - text->StyleSetForeground (wxSTC_H_ATTRIBUTE, wxColour(0,0,150)); - text->StyleSetForeground (wxSTC_H_ATTRIBUTEUNKNOWN, wxColour(0,0,150)); - text->StyleSetForeground (wxSTC_H_COMMENT, wxColour(150,150,150)); - - - wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL); - sizer->Add(text, 1, wxEXPAND); - SetSizer(sizer); - - Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(SourceViewDialog::onClose), NULL, this); - } - - -}; - -// -------------------------------------------------------------------------------------------------- -// MAIN BROWSER CLASS -// -------------------------------------------------------------------------------------------------- -class wxMiniApp : public wxApp -{ - wxTextCtrl* url; - wxWebView* m_browser_ctrl; - wxFrame* frame; - - wxToolBarToolBase* back; - wxToolBarToolBase* forward; - wxToolBarToolBase* stop; - wxToolBarToolBase* reload; - wxToolBarToolBase* tools; - - wxMenu* toolsMenu; - wxMenuItem* tinySize; - wxMenuItem* smallSize; - wxMenuItem* mediumSize; - wxMenuItem* largeSize; - wxMenuItem* largestSize; - - //wxMenuItem* offlineMode; - //wxMenuItem* onlineMode; - - wxLogWindow* logging; - wxToolBar* m_toolbar; - - wxTimer* m_timer; - int m_animation_angle; - - wxPanel* m_notification_panel; - wxStaticText* m_notification_text; - -public: - // function called at the application initialization - virtual bool OnInit(); - - /** - * Implement timer to display the loading animation (OK, I admit this is totally irrelevant to - * the HTML control being demonstrated here, but it's fun ;) - */ - void onAnimationTimer(wxTimerEvent& evt) - { - m_animation_angle += 15; - if (m_animation_angle > 360) m_animation_angle -= 360; - - wxBitmap image(32, 32); - - { - wxMemoryDC dc; - dc.SelectObject(image); - dc.SetBackground(wxBrush(wxColour(255,0,255))); - dc.Clear(); - - if (m_animation_angle >= 0 && m_animation_angle <= 180) - { - dc.SetBrush(*wxYELLOW_BRUSH); - dc.SetPen(*wxYELLOW_PEN); - dc.DrawCircle(16 - int(sin(m_animation_angle*0.01745f /* convert to radians */)*14.0f), - 16 + int(cos(m_animation_angle*0.01745f /* convert to radians */)*14.0f), 3 ); - } - - dc.DrawBitmap(wxBitmap(wxlogo_xpm), 0, 0, true); - - if (m_animation_angle > 180) - { - dc.SetBrush(*wxYELLOW_BRUSH); - dc.SetPen(*wxYELLOW_PEN); - dc.DrawCircle(16 - int(sin(m_animation_angle*0.01745f /* convert to radians */)*14.0f), - 16 + int(cos(m_animation_angle*0.01745f /* convert to radians */)*14.0f), 3 ); - } - } - - image.SetMask(new wxMask(image, wxColour(255,0,255))); - m_toolbar->SetToolNormalBitmap(tools->GetId(), image); - } - - /** - * Method that retrieves the current state from the web control and updates the GUI - * the reflect this current state. - */ - void updateState() - { - m_toolbar->EnableTool( back->GetId(), m_browser_ctrl->CanGoBack() ); - m_toolbar->EnableTool( forward->GetId(), m_browser_ctrl->CanGoForward() ); - - if (m_browser_ctrl->IsBusy()) - { - //tools->SetLabel(_("Loading...")); - - if (m_timer == NULL) - { - m_timer = new wxTimer(this); - this->Connect(wxEVT_TIMER, wxTimerEventHandler(wxMiniApp::onAnimationTimer), NULL, this); - } - m_timer->Start(100); // start animation timer - - m_toolbar->EnableTool( stop->GetId(), true ); - } - else - { - if (m_timer != NULL) m_timer->Stop(); // stop animation timer - - //tools->SetLabel(_("Tools")); - m_toolbar->SetToolNormalBitmap(tools->GetId(), wxBitmap(wxlogo_xpm)); - m_toolbar->EnableTool( stop->GetId(), false ); - } - - frame->SetTitle( m_browser_ctrl->GetCurrentTitle() ); - url->SetValue( m_browser_ctrl->GetCurrentURL() ); - } - - /** - * Callback invoked when user entered an URL and pressed enter - */ - void onUrl(wxCommandEvent& evt) - { - if (m_notification_panel->IsShown()) - { - m_notification_panel->Hide(); - frame->Layout(); - } - - m_browser_ctrl->LoadUrl( url->GetValue() ); - updateState(); - } - - /** - * Callback invoked when user pressed the "back" button - */ - void onBack(wxCommandEvent& evt) - { - // First, hide notification panel if it was shown - if (m_notification_panel->IsShown()) - { - m_notification_panel->Hide(); - frame->Layout(); - } - - m_browser_ctrl->GoBack(); - updateState(); - } - - /** - * Callback invoked when user pressed the "forward" button - */ - void onForward(wxCommandEvent& evt) - { - // First, hide notification panel if it was shown - if (m_notification_panel->IsShown()) - { - m_notification_panel->Hide(); - frame->Layout(); - } - - m_browser_ctrl->GoForward(); - updateState(); - } - - /** - * Callback invoked when user pressed the "stop" button - */ - void onStop(wxCommandEvent& evt) - { - m_browser_ctrl->Stop(); - updateState(); - } - - /** - * Callback invoked when user pressed the "reload" button - */ - void onReload(wxCommandEvent& evt) - { - // First, hide notification panel if it was shown - if (m_notification_panel->IsShown()) - { - m_notification_panel->Hide(); - frame->Layout(); - } - - m_browser_ctrl->Reload(); - updateState(); - } - - /** - * Callback invoked when there is a request to load a new page (for instance - * when the user clicks a link) - */ - void onNavigationRequest(wxWebNavigationEvent& evt) - { - // First, hide notification panel if it was shown - if (m_notification_panel->IsShown()) - { - m_notification_panel->Hide(); - frame->Layout(); - } - - wxLogMessage("Navigation request to '" + evt.GetHref() + "' (target='" + - evt.GetTarget() + "')"); - - wxASSERT(m_browser_ctrl->IsBusy()); - - // Uncomment this to see how to block navigation requests - //int answer = wxMessageBox("Proceed with navigation to '" + evt.GetHref() + "'?", - // "Proceed with navigation?", wxYES_NO ); - //if (answer != wxYES) - //{ - // evt.Veto(); - //} - updateState(); - } - - /** - * Callback invoked when a navigation request was accepted - */ - void onNavigationComplete(wxWebNavigationEvent& evt) - { - wxLogMessage("Navigation complete; url='" + evt.GetHref() + "'"); - updateState(); - } - - /** - * Callback invoked when a page is finished loading - */ - void onDocumentLoaded(wxWebNavigationEvent& evt) - { - wxLogMessage("Document loaded; url='" + evt.GetHref() + "'"); - updateState(); - - m_browser_ctrl->GetZoom(); - } - - /** - * Invoked when user selects the "View Source" menu item - */ - void onViewSourceRequest(wxCommandEvent& evt) - { - SourceViewDialog dlg(frame, m_browser_ctrl->GetPageSource()); - dlg.Center(); - dlg.ShowModal(); - } - - /** - * Invoked when user selects the "Menu" item - */ - void onToolsClicked(wxCommandEvent& evt) - { - tinySize->Check(false); - smallSize->Check(false); - mediumSize->Check(false); - largeSize->Check(false); - largestSize->Check(false); - - wxWebViewZoom zoom = m_browser_ctrl->GetZoom(); - switch (zoom) - { - case wxWEB_VIEW_ZOOM_TINY: - tinySize->Check(); - break; - case wxWEB_VIEW_ZOOM_SMALL: - smallSize->Check(); - break; - case wxWEB_VIEW_ZOOM_MEDIUM: - mediumSize->Check(); - break; - case wxWEB_VIEW_ZOOM_LARGE: - largeSize->Check(); - break; - case wxWEB_VIEW_ZOOM_LARGEST: - largestSize->Check(); - break; - } - - // bool IsOfflineMode(); - // void SetOfflineMode(bool offline); - - //offlineMode->Check(false); - //onlineMode->Check(false); - //const bool offline = m_browser_ctrl->IsOfflineMode(); - //if (offline) offlineMode->Check(); - //else onlineMode->Check(); - - wxPoint position = frame->ScreenToClient( wxGetMousePosition() ); - frame->PopupMenu(toolsMenu, position.x, position.y); - } - - /** - * Invoked when user selects the zoom size in the menu - */ - void onSetZoom(wxCommandEvent& evt) - { - if (evt.GetId() == tinySize->GetId()) - { - m_browser_ctrl->SetZoom(wxWEB_VIEW_ZOOM_TINY); - } - else if (evt.GetId() == smallSize->GetId()) - { - m_browser_ctrl->SetZoom(wxWEB_VIEW_ZOOM_SMALL); - } - else if (evt.GetId() == mediumSize->GetId()) - { - m_browser_ctrl->SetZoom(wxWEB_VIEW_ZOOM_MEDIUM); - } - else if (evt.GetId() == largeSize->GetId()) - { - m_browser_ctrl->SetZoom(wxWEB_VIEW_ZOOM_LARGE); - } - else if (evt.GetId() == largestSize->GetId()) - { - m_browser_ctrl->SetZoom(wxWEB_VIEW_ZOOM_LARGEST); - } - else - { - wxASSERT(false); - } - } - - /* - void onChangeOnlineMode(wxCommandEvent& evt) - { - if (evt.GetId() == offlineMode->GetId()) - { - m_browser_ctrl->SetOfflineMode(true); - m_browser_ctrl->SetPage("

You are now in offline mode.

"); - } - else if (evt.GetId() == onlineMode->GetId()) - { - m_browser_ctrl->SetOfflineMode(false); - } - else - { - wxASSERT(false); - } - } - */ - - /** - * Callback invoked when a loading error occurs - */ - void onError(wxWebNavigationEvent& evt) - { - wxString errorCategory; - switch (evt.GetInt()) - { - case wxWEB_NAV_ERR_CONNECTION: - errorCategory = "wxWEB_NAV_ERR_CONNECTION"; - break; - - case wxWEB_NAV_ERR_CERTIFICATE: - errorCategory = "wxWEB_NAV_ERR_CERTIFICATE"; - break; - - case wxWEB_NAV_ERR_AUTH: - errorCategory = "wxWEB_NAV_ERR_AUTH"; - break; - - case wxWEB_NAV_ERR_SECURITY: - errorCategory = "wxWEB_NAV_ERR_SECURITY"; - break; - - case wxWEB_NAV_ERR_NOT_FOUND: - errorCategory = "wxWEB_NAV_ERR_NOT_FOUND"; - break; - - case wxWEB_NAV_ERR_REQUEST: - errorCategory = "wxWEB_NAV_ERR_REQUEST"; - break; - - case wxWEB_NAV_ERR_USER_CANCELLED: - errorCategory = "wxWEB_NAV_ERR_USER_CANCELLED"; - break; - - case wxWEB_NAV_ERR_OTHER: - errorCategory = "wxWEB_NAV_ERR_OTHER"; - break; - } - - wxLogMessage("Error; url='" + evt.GetHref() + "', error='" + errorCategory + "' (" + evt.GetString() + ")"); - - // show the notification panel - m_notification_text->SetLabel(_("An error occurred loading ") + evt.GetHref() + "\n" + - "'" + errorCategory + "' (" + evt.GetString() + ")"); - m_notification_panel->Layout(); - m_notification_panel->GetSizer()->SetSizeHints(m_notification_panel); - m_notification_panel->Show(); - frame->Layout(); - - updateState(); - } - - /** - * Invoked when user clicks "Hide" in the notification panel - */ - void onHideNotifBar(wxCommandEvent& evt) - { - m_notification_panel->Hide(); - frame->Layout(); - } - - void onClose(wxCloseEvent& evt) - { - frame->Destroy(); - } - - void onQuitMenu(wxCommandEvent& evt) - { - frame->Destroy(); - } - - /** - * Invoked when user selects "Print" from the menu - */ - void onPrint(wxCommandEvent& evt) - { - m_browser_ctrl->Print(); - } -}; - -IMPLEMENT_APP(wxMiniApp); - -bool wxMiniApp::OnInit() -{ - m_timer = NULL; - m_animation_angle = 0; - - frame = new wxFrame( NULL, -1, _("wxBetterHTMLControl Browser Example"), wxDefaultPosition, wxSize(800, 600) ); - - // wx has a default mechanism to expand the only control of a frame; but since this mechanism - // does not involve sizers, invoking ->Layout on the frame does not udpate the layout which is - // not good. - wxBoxSizer* expandSizer = new wxBoxSizer(wxHORIZONTAL); - wxPanel* mainpane = new wxPanel(frame, wxID_ANY); - expandSizer->Add(mainpane, 1, wxEXPAND); - frame->SetSizer(expandSizer); - - wxLog::SetLogLevel(wxLOG_Max); - logging = new wxLogWindow(frame, _("Logging")); - wxLog::SetLogLevel(wxLOG_Max); - - // ---- Create the Tools menu - toolsMenu = new wxMenu(); - wxMenuItem* print = toolsMenu->Append(wxID_ANY , _("Print")); - wxMenuItem* viewSource = toolsMenu->Append(wxID_ANY , _("View Source")); - toolsMenu->AppendSeparator(); - tinySize = toolsMenu->AppendCheckItem(wxID_ANY, _("Tiny")); - smallSize = toolsMenu->AppendCheckItem(wxID_ANY, _("Small")); - mediumSize = toolsMenu->AppendCheckItem(wxID_ANY, _("Medium")); - largeSize = toolsMenu->AppendCheckItem(wxID_ANY, _("Large")); - largestSize = toolsMenu->AppendCheckItem(wxID_ANY, _("Largest")); - //toolsMenu->AppendSeparator(); - //offlineMode = toolsMenu->AppendCheckItem(wxID_ANY, _("Offline Mode")); - //onlineMode = toolsMenu->AppendCheckItem(wxID_ANY, _("Online Mode")); - - // ---- Create the Toolbar - m_toolbar = frame->CreateToolBar(/*wxNO_BORDER |*/ wxTB_TEXT); - m_toolbar->SetToolBitmapSize(wxSize(32, 32)); - - back = m_toolbar->AddTool(wxID_ANY, _("Back"), wxBitmap(back_xpm)); - forward = m_toolbar->AddTool(wxID_ANY, _("Forward"), wxBitmap(forward_xpm)); - stop = m_toolbar->AddTool(wxID_ANY, _("Stop"), wxBitmap(stop_xpm)); - reload = m_toolbar->AddTool(wxID_ANY, _("Reload"), wxBitmap(refresh_xpm)); - - url = new wxTextCtrl(m_toolbar, wxID_ANY, wxT("http://www.google.com"), - wxDefaultPosition, wxSize(400, -1), wxTE_PROCESS_ENTER ); - m_toolbar->AddControl(url, _("URL")); - tools = m_toolbar->AddTool(wxID_ANY, _("Menu"), wxBitmap(wxlogo_xpm)); - //m_toolbar->SetDropdownMenu(tools->GetId(), toolsMenu); - - m_toolbar->Realize(); - - m_toolbar->Connect(back->GetId(), wxEVT_COMMAND_TOOL_CLICKED, - wxCommandEventHandler(wxMiniApp::onBack), NULL, this ); - m_toolbar->Connect(forward->GetId(), wxEVT_COMMAND_TOOL_CLICKED, - wxCommandEventHandler(wxMiniApp::onForward), NULL, this ); - m_toolbar->Connect(stop->GetId(), wxEVT_COMMAND_TOOL_CLICKED, - wxCommandEventHandler(wxMiniApp::onStop), NULL, this ); - m_toolbar->Connect(reload->GetId(), wxEVT_COMMAND_TOOL_CLICKED, - wxCommandEventHandler(wxMiniApp::onReload), NULL, this ); - m_toolbar->Connect(tools->GetId(), wxEVT_COMMAND_TOOL_CLICKED, - wxCommandEventHandler(wxMiniApp::onToolsClicked), NULL, this ); - - url->Connect(url->GetId(), wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(wxMiniApp::onUrl), NULL, this ); - - - frame->Connect(viewSource->GetId(), wxEVT_COMMAND_MENU_SELECTED, - wxCommandEventHandler(wxMiniApp::onViewSourceRequest), NULL, this ); - frame->Connect(print->GetId(), wxEVT_COMMAND_MENU_SELECTED, - wxCommandEventHandler(wxMiniApp::onPrint), NULL, this ); - - frame->Connect(tinySize->GetId(), wxEVT_COMMAND_MENU_SELECTED, - wxCommandEventHandler(wxMiniApp::onSetZoom), NULL, this ); - frame->Connect(smallSize->GetId(), wxEVT_COMMAND_MENU_SELECTED, - wxCommandEventHandler(wxMiniApp::onSetZoom), NULL, this ); - frame->Connect(mediumSize->GetId(), wxEVT_COMMAND_MENU_SELECTED, - wxCommandEventHandler(wxMiniApp::onSetZoom), NULL, this ); - frame->Connect(largeSize->GetId(), wxEVT_COMMAND_MENU_SELECTED, - wxCommandEventHandler(wxMiniApp::onSetZoom), NULL, this ); - frame->Connect(largestSize->GetId(), wxEVT_COMMAND_MENU_SELECTED, - wxCommandEventHandler(wxMiniApp::onSetZoom), NULL, this ); - - // ---- Create the web view - m_browser_ctrl = wxWebView::GetNew(mainpane, wxID_ANY); - - // ---- Create the notification panel - { - wxBoxSizer* notification_sizer = new wxBoxSizer(wxHORIZONTAL); - m_notification_panel = new wxPanel(mainpane, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SIMPLE); - m_notification_text = new wxStaticText(m_notification_panel, wxID_ANY, "[No message]"); - notification_sizer->Add( new wxStaticBitmap(m_notification_panel, wxID_ANY, - wxArtProvider::GetBitmap(wxART_WARNING, wxART_OTHER , wxSize(48, 48))), - 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 ); - notification_sizer->Add(m_notification_text, 1, wxEXPAND | wxALIGN_CENTER_VERTICAL | wxALL, 5); - wxButton* hideNotif = new wxButton(m_notification_panel, wxID_ANY, _("Hide")); - notification_sizer->Add(hideNotif, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); - m_notification_panel->SetSizer(notification_sizer); - m_notification_panel->SetBackgroundColour(wxColor(255,225,110)); - m_notification_panel->Hide(); - hideNotif->Connect(hideNotif->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, - wxCommandEventHandler(wxMiniApp::onHideNotifBar), NULL, this); - } - - wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL); - sizer->Add(m_notification_panel, 0, wxEXPAND | wxALL, 5); - sizer->Add(m_browser_ctrl, 1, wxEXPAND | wxALL, 5); - - mainpane->SetSizer(sizer); - frame->Layout(); - frame->Center(); - frame->Show(); - - m_browser_ctrl->Connect(m_browser_ctrl->GetId(), wxEVT_COMMAND_WEB_VIEW_NAVIGATING, - wxWebNavigationEventHandler(wxMiniApp::onNavigationRequest), NULL, this); - - m_browser_ctrl->Connect(m_browser_ctrl->GetId(), wxEVT_COMMAND_WEB_VIEW_NAVIGATED, - wxWebNavigationEventHandler(wxMiniApp::onNavigationComplete), NULL, this); - - m_browser_ctrl->Connect(m_browser_ctrl->GetId(), wxEVT_COMMAND_WEB_VIEW_LOADED, - wxWebNavigationEventHandler(wxMiniApp::onDocumentLoaded), NULL, this); - - m_browser_ctrl->Connect(m_browser_ctrl->GetId(), wxEVT_COMMAND_WEB_VIEW_ERROR, - wxWebNavigationEventHandler(wxMiniApp::onError), NULL, this); - - frame->Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(wxMiniApp::onClose), NULL, this); - Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(wxMiniApp::onQuitMenu), NULL, this); - - // You can test different zoom types (if supported by the backend) - // if (m_browser_ctrl->CanSetZoomType(wxWEB_VIEW_ZOOM_TYPE_LAYOUT)) - // m_browser_ctrl->SetZoomType(wxWEB_VIEW_ZOOM_TYPE_LAYOUT); - - SetTopWindow(frame); - frame->Layout(); - - return true; -} +///////////////////////////////////////////////////////////////////////////// +// Name: wxiepanel.cpp +// Purpose: wxBetterHTMLControl test +// Author: Marianne Gagnon +// Id: $Id$ +// Copyright: (c) 2010 Marianne Gagnon +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#if wxUSE_STC +#include +#else +#error "wxStyledTextControl is needed by this sample" +#endif + +#include "wx/webview.h" +#include "wxlogo.xpm" +#include "back.xpm" +#include "forward.xpm" +#include "stop.xpm" +#include "refresh.xpm" + +// -------------------------------------------------------------------------------------------------- +// SOURCE VIEW FRAME +// -------------------------------------------------------------------------------------------------- +enum +{ + MARGIN_LINE_NUMBERS, + //MARGIN_DIVIDER, + //MARGIN_FOLDING +}; + +class SourceViewDialog : public wxDialog +{ +public: + + void onClose(wxCloseEvent& evt) + { + EndModal( GetReturnCode() ); + } + + SourceViewDialog(wxWindow* parent, wxString source) : + wxDialog(parent, wxID_ANY, "Source Code", + wxDefaultPosition, wxSize(700,500), + wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) + { + wxStyledTextCtrl* text = new wxStyledTextCtrl(this, wxID_ANY); + + //text->SetLexer(wxSTC_LEX_HTML); + text->SetMarginWidth (MARGIN_LINE_NUMBERS, 50); + text->StyleSetForeground (wxSTC_STYLE_LINENUMBER, wxColour (75, 75, 75) ); + text->StyleSetBackground (wxSTC_STYLE_LINENUMBER, wxColour (220, 220, 220)); + text->SetMarginType (MARGIN_LINE_NUMBERS, wxSTC_MARGIN_NUMBER); + + text->SetWrapMode (wxSTC_WRAP_WORD); + + text->SetText(source); + + text->StyleClearAll(); + text->SetLexer(wxSTC_LEX_HTML); + text->StyleSetForeground (wxSTC_H_DOUBLESTRING, wxColour(255,0,0)); + text->StyleSetForeground (wxSTC_H_SINGLESTRING, wxColour(255,0,0)); + text->StyleSetForeground (wxSTC_H_ENTITY, wxColour(255,0,0)); + text->StyleSetForeground (wxSTC_H_TAG, wxColour(0,150,0)); + text->StyleSetForeground (wxSTC_H_TAGUNKNOWN, wxColour(0,150,0)); + text->StyleSetForeground (wxSTC_H_ATTRIBUTE, wxColour(0,0,150)); + text->StyleSetForeground (wxSTC_H_ATTRIBUTEUNKNOWN, wxColour(0,0,150)); + text->StyleSetForeground (wxSTC_H_COMMENT, wxColour(150,150,150)); + + + wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL); + sizer->Add(text, 1, wxEXPAND); + SetSizer(sizer); + + Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(SourceViewDialog::onClose), NULL, this); + } + + +}; + +// -------------------------------------------------------------------------------------------------- +// MAIN BROWSER CLASS +// -------------------------------------------------------------------------------------------------- +class wxMiniApp : public wxApp +{ + wxTextCtrl* url; + wxWebView* m_browser_ctrl; + wxFrame* frame; + + wxToolBarToolBase* back; + wxToolBarToolBase* forward; + wxToolBarToolBase* stop; + wxToolBarToolBase* reload; + wxToolBarToolBase* tools; + + wxMenu* toolsMenu; + wxMenuItem* tinySize; + wxMenuItem* smallSize; + wxMenuItem* mediumSize; + wxMenuItem* largeSize; + wxMenuItem* largestSize; + + //wxMenuItem* offlineMode; + //wxMenuItem* onlineMode; + + wxLogWindow* logging; + wxToolBar* m_toolbar; + + wxTimer* m_timer; + int m_animation_angle; + + wxPanel* m_notification_panel; + wxStaticText* m_notification_text; + +public: + // function called at the application initialization + virtual bool OnInit(); + + /** + * Implement timer to display the loading animation (OK, I admit this is totally irrelevant to + * the HTML control being demonstrated here, but it's fun ;) + */ + void onAnimationTimer(wxTimerEvent& evt) + { + m_animation_angle += 15; + if (m_animation_angle > 360) m_animation_angle -= 360; + + wxBitmap image(32, 32); + + { + wxMemoryDC dc; + dc.SelectObject(image); + dc.SetBackground(wxBrush(wxColour(255,0,255))); + dc.Clear(); + + if (m_animation_angle >= 0 && m_animation_angle <= 180) + { + dc.SetBrush(*wxYELLOW_BRUSH); + dc.SetPen(*wxYELLOW_PEN); + dc.DrawCircle(16 - int(sin(m_animation_angle*0.01745f /* convert to radians */)*14.0f), + 16 + int(cos(m_animation_angle*0.01745f /* convert to radians */)*14.0f), 3 ); + } + + dc.DrawBitmap(wxBitmap(wxlogo_xpm), 0, 0, true); + + if (m_animation_angle > 180) + { + dc.SetBrush(*wxYELLOW_BRUSH); + dc.SetPen(*wxYELLOW_PEN); + dc.DrawCircle(16 - int(sin(m_animation_angle*0.01745f /* convert to radians */)*14.0f), + 16 + int(cos(m_animation_angle*0.01745f /* convert to radians */)*14.0f), 3 ); + } + } + + image.SetMask(new wxMask(image, wxColour(255,0,255))); + m_toolbar->SetToolNormalBitmap(tools->GetId(), image); + } + + /** + * Method that retrieves the current state from the web control and updates the GUI + * the reflect this current state. + */ + void updateState() + { + m_toolbar->EnableTool( back->GetId(), m_browser_ctrl->CanGoBack() ); + m_toolbar->EnableTool( forward->GetId(), m_browser_ctrl->CanGoForward() ); + + if (m_browser_ctrl->IsBusy()) + { + //tools->SetLabel(_("Loading...")); + + if (m_timer == NULL) + { + m_timer = new wxTimer(this); + this->Connect(wxEVT_TIMER, wxTimerEventHandler(wxMiniApp::onAnimationTimer), NULL, this); + } + m_timer->Start(100); // start animation timer + + m_toolbar->EnableTool( stop->GetId(), true ); + } + else + { + if (m_timer != NULL) m_timer->Stop(); // stop animation timer + + //tools->SetLabel(_("Tools")); + m_toolbar->SetToolNormalBitmap(tools->GetId(), wxBitmap(wxlogo_xpm)); + m_toolbar->EnableTool( stop->GetId(), false ); + } + + frame->SetTitle( m_browser_ctrl->GetCurrentTitle() ); + url->SetValue( m_browser_ctrl->GetCurrentURL() ); + } + + /** + * Callback invoked when user entered an URL and pressed enter + */ + void onUrl(wxCommandEvent& evt) + { + if (m_notification_panel->IsShown()) + { + m_notification_panel->Hide(); + frame->Layout(); + } + + m_browser_ctrl->LoadUrl( url->GetValue() ); + updateState(); + } + + /** + * Callback invoked when user pressed the "back" button + */ + void onBack(wxCommandEvent& evt) + { + // First, hide notification panel if it was shown + if (m_notification_panel->IsShown()) + { + m_notification_panel->Hide(); + frame->Layout(); + } + + m_browser_ctrl->GoBack(); + updateState(); + } + + /** + * Callback invoked when user pressed the "forward" button + */ + void onForward(wxCommandEvent& evt) + { + // First, hide notification panel if it was shown + if (m_notification_panel->IsShown()) + { + m_notification_panel->Hide(); + frame->Layout(); + } + + m_browser_ctrl->GoForward(); + updateState(); + } + + /** + * Callback invoked when user pressed the "stop" button + */ + void onStop(wxCommandEvent& evt) + { + m_browser_ctrl->Stop(); + updateState(); + } + + /** + * Callback invoked when user pressed the "reload" button + */ + void onReload(wxCommandEvent& evt) + { + // First, hide notification panel if it was shown + if (m_notification_panel->IsShown()) + { + m_notification_panel->Hide(); + frame->Layout(); + } + + m_browser_ctrl->Reload(); + updateState(); + } + + /** + * Callback invoked when there is a request to load a new page (for instance + * when the user clicks a link) + */ + void onNavigationRequest(wxWebNavigationEvent& evt) + { + // First, hide notification panel if it was shown + if (m_notification_panel->IsShown()) + { + m_notification_panel->Hide(); + frame->Layout(); + } + + wxLogMessage("Navigation request to '" + evt.GetHref() + "' (target='" + + evt.GetTarget() + "')"); + + wxASSERT(m_browser_ctrl->IsBusy()); + + // Uncomment this to see how to block navigation requests + //int answer = wxMessageBox("Proceed with navigation to '" + evt.GetHref() + "'?", + // "Proceed with navigation?", wxYES_NO ); + //if (answer != wxYES) + //{ + // evt.Veto(); + //} + updateState(); + } + + /** + * Callback invoked when a navigation request was accepted + */ + void onNavigationComplete(wxWebNavigationEvent& evt) + { + wxLogMessage("Navigation complete; url='" + evt.GetHref() + "'"); + updateState(); + } + + /** + * Callback invoked when a page is finished loading + */ + void onDocumentLoaded(wxWebNavigationEvent& evt) + { + wxLogMessage("Document loaded; url='" + evt.GetHref() + "'"); + updateState(); + + m_browser_ctrl->GetZoom(); + } + + /** + * Invoked when user selects the "View Source" menu item + */ + void onViewSourceRequest(wxCommandEvent& evt) + { + SourceViewDialog dlg(frame, m_browser_ctrl->GetPageSource()); + dlg.Center(); + dlg.ShowModal(); + } + + /** + * Invoked when user selects the "Menu" item + */ + void onToolsClicked(wxCommandEvent& evt) + { + tinySize->Check(false); + smallSize->Check(false); + mediumSize->Check(false); + largeSize->Check(false); + largestSize->Check(false); + + wxWebViewZoom zoom = m_browser_ctrl->GetZoom(); + switch (zoom) + { + case wxWEB_VIEW_ZOOM_TINY: + tinySize->Check(); + break; + case wxWEB_VIEW_ZOOM_SMALL: + smallSize->Check(); + break; + case wxWEB_VIEW_ZOOM_MEDIUM: + mediumSize->Check(); + break; + case wxWEB_VIEW_ZOOM_LARGE: + largeSize->Check(); + break; + case wxWEB_VIEW_ZOOM_LARGEST: + largestSize->Check(); + break; + } + + // bool IsOfflineMode(); + // void SetOfflineMode(bool offline); + + //offlineMode->Check(false); + //onlineMode->Check(false); + //const bool offline = m_browser_ctrl->IsOfflineMode(); + //if (offline) offlineMode->Check(); + //else onlineMode->Check(); + + wxPoint position = frame->ScreenToClient( wxGetMousePosition() ); + frame->PopupMenu(toolsMenu, position.x, position.y); + } + + /** + * Invoked when user selects the zoom size in the menu + */ + void onSetZoom(wxCommandEvent& evt) + { + if (evt.GetId() == tinySize->GetId()) + { + m_browser_ctrl->SetZoom(wxWEB_VIEW_ZOOM_TINY); + } + else if (evt.GetId() == smallSize->GetId()) + { + m_browser_ctrl->SetZoom(wxWEB_VIEW_ZOOM_SMALL); + } + else if (evt.GetId() == mediumSize->GetId()) + { + m_browser_ctrl->SetZoom(wxWEB_VIEW_ZOOM_MEDIUM); + } + else if (evt.GetId() == largeSize->GetId()) + { + m_browser_ctrl->SetZoom(wxWEB_VIEW_ZOOM_LARGE); + } + else if (evt.GetId() == largestSize->GetId()) + { + m_browser_ctrl->SetZoom(wxWEB_VIEW_ZOOM_LARGEST); + } + else + { + wxASSERT(false); + } + } + + /* + void onChangeOnlineMode(wxCommandEvent& evt) + { + if (evt.GetId() == offlineMode->GetId()) + { + m_browser_ctrl->SetOfflineMode(true); + m_browser_ctrl->SetPage("

You are now in offline mode.

"); + } + else if (evt.GetId() == onlineMode->GetId()) + { + m_browser_ctrl->SetOfflineMode(false); + } + else + { + wxASSERT(false); + } + } + */ + + /** + * Callback invoked when a loading error occurs + */ + void onError(wxWebNavigationEvent& evt) + { + wxString errorCategory; + switch (evt.GetInt()) + { + case wxWEB_NAV_ERR_CONNECTION: + errorCategory = "wxWEB_NAV_ERR_CONNECTION"; + break; + + case wxWEB_NAV_ERR_CERTIFICATE: + errorCategory = "wxWEB_NAV_ERR_CERTIFICATE"; + break; + + case wxWEB_NAV_ERR_AUTH: + errorCategory = "wxWEB_NAV_ERR_AUTH"; + break; + + case wxWEB_NAV_ERR_SECURITY: + errorCategory = "wxWEB_NAV_ERR_SECURITY"; + break; + + case wxWEB_NAV_ERR_NOT_FOUND: + errorCategory = "wxWEB_NAV_ERR_NOT_FOUND"; + break; + + case wxWEB_NAV_ERR_REQUEST: + errorCategory = "wxWEB_NAV_ERR_REQUEST"; + break; + + case wxWEB_NAV_ERR_USER_CANCELLED: + errorCategory = "wxWEB_NAV_ERR_USER_CANCELLED"; + break; + + case wxWEB_NAV_ERR_OTHER: + errorCategory = "wxWEB_NAV_ERR_OTHER"; + break; + } + + wxLogMessage("Error; url='" + evt.GetHref() + "', error='" + errorCategory + "' (" + evt.GetString() + ")"); + + // show the notification panel + m_notification_text->SetLabel(_("An error occurred loading ") + evt.GetHref() + "\n" + + "'" + errorCategory + "' (" + evt.GetString() + ")"); + m_notification_panel->Layout(); + m_notification_panel->GetSizer()->SetSizeHints(m_notification_panel); + m_notification_panel->Show(); + frame->Layout(); + + updateState(); + } + + /** + * Invoked when user clicks "Hide" in the notification panel + */ + void onHideNotifBar(wxCommandEvent& evt) + { + m_notification_panel->Hide(); + frame->Layout(); + } + + void onClose(wxCloseEvent& evt) + { + frame->Destroy(); + } + + void onQuitMenu(wxCommandEvent& evt) + { + frame->Destroy(); + } + + /** + * Invoked when user selects "Print" from the menu + */ + void onPrint(wxCommandEvent& evt) + { + m_browser_ctrl->Print(); + } +}; + +IMPLEMENT_APP(wxMiniApp); + +bool wxMiniApp::OnInit() +{ + m_timer = NULL; + m_animation_angle = 0; + + frame = new wxFrame( NULL, -1, _("wxBetterHTMLControl Browser Example"), wxDefaultPosition, wxSize(800, 600) ); + + // wx has a default mechanism to expand the only control of a frame; but since this mechanism + // does not involve sizers, invoking ->Layout on the frame does not udpate the layout which is + // not good. + wxBoxSizer* expandSizer = new wxBoxSizer(wxHORIZONTAL); + wxPanel* mainpane = new wxPanel(frame, wxID_ANY); + expandSizer->Add(mainpane, 1, wxEXPAND); + frame->SetSizer(expandSizer); + + wxLog::SetLogLevel(wxLOG_Max); + logging = new wxLogWindow(frame, _("Logging")); + wxLog::SetLogLevel(wxLOG_Max); + + // ---- Create the Tools menu + toolsMenu = new wxMenu(); + wxMenuItem* print = toolsMenu->Append(wxID_ANY , _("Print")); + wxMenuItem* viewSource = toolsMenu->Append(wxID_ANY , _("View Source")); + toolsMenu->AppendSeparator(); + tinySize = toolsMenu->AppendCheckItem(wxID_ANY, _("Tiny")); + smallSize = toolsMenu->AppendCheckItem(wxID_ANY, _("Small")); + mediumSize = toolsMenu->AppendCheckItem(wxID_ANY, _("Medium")); + largeSize = toolsMenu->AppendCheckItem(wxID_ANY, _("Large")); + largestSize = toolsMenu->AppendCheckItem(wxID_ANY, _("Largest")); + //toolsMenu->AppendSeparator(); + //offlineMode = toolsMenu->AppendCheckItem(wxID_ANY, _("Offline Mode")); + //onlineMode = toolsMenu->AppendCheckItem(wxID_ANY, _("Online Mode")); + + // ---- Create the Toolbar + m_toolbar = frame->CreateToolBar(/*wxNO_BORDER |*/ wxTB_TEXT); + m_toolbar->SetToolBitmapSize(wxSize(32, 32)); + + back = m_toolbar->AddTool(wxID_ANY, _("Back"), wxBitmap(back_xpm)); + forward = m_toolbar->AddTool(wxID_ANY, _("Forward"), wxBitmap(forward_xpm)); + stop = m_toolbar->AddTool(wxID_ANY, _("Stop"), wxBitmap(stop_xpm)); + reload = m_toolbar->AddTool(wxID_ANY, _("Reload"), wxBitmap(refresh_xpm)); + + url = new wxTextCtrl(m_toolbar, wxID_ANY, wxT("http://www.google.com"), + wxDefaultPosition, wxSize(400, -1), wxTE_PROCESS_ENTER ); + m_toolbar->AddControl(url, _("URL")); + tools = m_toolbar->AddTool(wxID_ANY, _("Menu"), wxBitmap(wxlogo_xpm)); + //m_toolbar->SetDropdownMenu(tools->GetId(), toolsMenu); + + m_toolbar->Realize(); + + m_toolbar->Connect(back->GetId(), wxEVT_COMMAND_TOOL_CLICKED, + wxCommandEventHandler(wxMiniApp::onBack), NULL, this ); + m_toolbar->Connect(forward->GetId(), wxEVT_COMMAND_TOOL_CLICKED, + wxCommandEventHandler(wxMiniApp::onForward), NULL, this ); + m_toolbar->Connect(stop->GetId(), wxEVT_COMMAND_TOOL_CLICKED, + wxCommandEventHandler(wxMiniApp::onStop), NULL, this ); + m_toolbar->Connect(reload->GetId(), wxEVT_COMMAND_TOOL_CLICKED, + wxCommandEventHandler(wxMiniApp::onReload), NULL, this ); + m_toolbar->Connect(tools->GetId(), wxEVT_COMMAND_TOOL_CLICKED, + wxCommandEventHandler(wxMiniApp::onToolsClicked), NULL, this ); + + url->Connect(url->GetId(), wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(wxMiniApp::onUrl), NULL, this ); + + + frame->Connect(viewSource->GetId(), wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(wxMiniApp::onViewSourceRequest), NULL, this ); + frame->Connect(print->GetId(), wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(wxMiniApp::onPrint), NULL, this ); + + frame->Connect(tinySize->GetId(), wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(wxMiniApp::onSetZoom), NULL, this ); + frame->Connect(smallSize->GetId(), wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(wxMiniApp::onSetZoom), NULL, this ); + frame->Connect(mediumSize->GetId(), wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(wxMiniApp::onSetZoom), NULL, this ); + frame->Connect(largeSize->GetId(), wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(wxMiniApp::onSetZoom), NULL, this ); + frame->Connect(largestSize->GetId(), wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler(wxMiniApp::onSetZoom), NULL, this ); + + // ---- Create the web view + m_browser_ctrl = wxWebView::GetNew(mainpane, wxID_ANY); + + // ---- Create the notification panel + { + wxBoxSizer* notification_sizer = new wxBoxSizer(wxHORIZONTAL); + m_notification_panel = new wxPanel(mainpane, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SIMPLE); + m_notification_text = new wxStaticText(m_notification_panel, wxID_ANY, "[No message]"); + notification_sizer->Add( new wxStaticBitmap(m_notification_panel, wxID_ANY, + wxArtProvider::GetBitmap(wxART_WARNING, wxART_OTHER , wxSize(48, 48))), + 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 ); + notification_sizer->Add(m_notification_text, 1, wxEXPAND | wxALIGN_CENTER_VERTICAL | wxALL, 5); + wxButton* hideNotif = new wxButton(m_notification_panel, wxID_ANY, _("Hide")); + notification_sizer->Add(hideNotif, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5); + m_notification_panel->SetSizer(notification_sizer); + m_notification_panel->SetBackgroundColour(wxColor(255,225,110)); + m_notification_panel->Hide(); + hideNotif->Connect(hideNotif->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, + wxCommandEventHandler(wxMiniApp::onHideNotifBar), NULL, this); + } + + wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL); + sizer->Add(m_notification_panel, 0, wxEXPAND | wxALL, 5); + sizer->Add(m_browser_ctrl, 1, wxEXPAND | wxALL, 5); + + mainpane->SetSizer(sizer); + frame->Layout(); + frame->Center(); + frame->Show(); + + m_browser_ctrl->Connect(m_browser_ctrl->GetId(), wxEVT_COMMAND_WEB_VIEW_NAVIGATING, + wxWebNavigationEventHandler(wxMiniApp::onNavigationRequest), NULL, this); + + m_browser_ctrl->Connect(m_browser_ctrl->GetId(), wxEVT_COMMAND_WEB_VIEW_NAVIGATED, + wxWebNavigationEventHandler(wxMiniApp::onNavigationComplete), NULL, this); + + m_browser_ctrl->Connect(m_browser_ctrl->GetId(), wxEVT_COMMAND_WEB_VIEW_LOADED, + wxWebNavigationEventHandler(wxMiniApp::onDocumentLoaded), NULL, this); + + m_browser_ctrl->Connect(m_browser_ctrl->GetId(), wxEVT_COMMAND_WEB_VIEW_ERROR, + wxWebNavigationEventHandler(wxMiniApp::onError), NULL, this); + + frame->Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(wxMiniApp::onClose), NULL, this); + Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(wxMiniApp::onQuitMenu), NULL, this); + + // You can test different zoom types (if supported by the backend) + // if (m_browser_ctrl->CanSetZoomType(wxWEB_VIEW_ZOOM_TYPE_LAYOUT)) + // m_browser_ctrl->SetZoomType(wxWEB_VIEW_ZOOM_TYPE_LAYOUT); + + SetTopWindow(frame); + frame->Layout(); + + return true; +} diff --git a/src/common/webview.cpp b/src/common/webview.cpp index 91ce54f048..6110186427 100644 --- a/src/common/webview.cpp +++ b/src/common/webview.cpp @@ -1,113 +1,113 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: webview.cpp -// Purpose: Common interface and events for web view component -// Author: Marianne Gagnon -// Id: $Id$ -// Copyright: (c) 2010 Marianne Gagnon -// Licence: wxWindows licence -///////////////////////////////////////////////////////////////////////////// - -#include "wx/webview.h" - -#include "wx/osx/webkit.h" -#include "wx/gtk/webkit.h" -#include "wx/msw/webkitie.h" - -extern WXDLLEXPORT_DATA(const char) wxWebViewNameStr[] = "wxWebView"; -extern WXDLLEXPORT_DATA(const char) wxWebViewDefaultURLStr[] = "about:blank"; - -IMPLEMENT_DYNAMIC_CLASS(wxWebNavigationEvent, wxCommandEvent) - -wxDEFINE_EVENT( wxEVT_COMMAND_WEB_VIEW_NAVIGATING, wxWebNavigationEvent ); -wxDEFINE_EVENT( wxEVT_COMMAND_WEB_VIEW_NAVIGATED, wxWebNavigationEvent ); -wxDEFINE_EVENT( wxEVT_COMMAND_WEB_VIEW_LOADED, wxWebNavigationEvent ); -wxDEFINE_EVENT( wxEVT_COMMAND_WEB_VIEW_ERROR, wxWebNavigationEvent ); - -// static -wxWebView* wxWebView::New(wxWebViewBackend backend) -{ - switch (backend) - { - #if wxHAVE_WEB_BACKEND_OSX_WEBKIT - case wxWEB_VIEW_BACKEND_OSX_WEBKIT: - return new wxOSXWebKitCtrl(); - #endif - - #if wxHAVE_WEB_BACKEND_GTK_WEBKIT - case wxWEB_VIEW_BACKEND_GTK_WEBKIT: - return new wxGtkWebKitCtrl(); - #endif - - #if wxHAVE_WEB_BACKEND_IE - case wxWEB_VIEW_BACKEND_IE: - return new wxIEPanel(); - #endif - - case wxWEB_VIEW_BACKEND_DEFAULT: - - #if wxHAVE_WEB_BACKEND_OSX_WEBKIT - return new wxOSXWebKitCtrl(); - #endif - - #if wxHAVE_WEB_BACKEND_GTK_WEBKIT - return new wxGtkWebKitCtrl(); - #endif - - #if wxHAVE_WEB_BACKEND_IE - return new wxIEPanel(); - #endif - - // fall-through intended - default: - return NULL; - } -} - -// static -wxWebView* wxWebView::New(wxWindow* parent, - wxWindowID id, - const wxString& url, - const wxPoint& pos, - const wxSize& size, - wxWebViewBackend backend, - long style, - const wxString& name) -{ - switch (backend) - { - #if wxHAVE_WEB_BACKEND_OSX_WEBKIT - case wxWEB_VIEW_BACKEND_OSX_WEBKIT: - return new wxOSXWebKitCtrl(parent, id, url, pos, size, style, - name); - #endif - - #if wxHAVE_WEB_BACKEND_GTK_WEBKIT - case wxWEB_VIEW_BACKEND_GTK_WEBKIT: - return new wxGtkWebKitCtrl(parent, id, url, pos, size, style, - name); - #endif - - #if wxHAVE_WEB_BACKEND_IE - case wxWEB_VIEW_BACKEND_IE: - return new wxIEPanel(parent, id, url, pos, size, style, name); - #endif - - case wxWEB_VIEW_BACKEND_DEFAULT: - - #if wxHAVE_WEB_BACKEND_OSX_WEBKIT - return new wxOSXWebKitCtrl(parent, id, url, pos, size, style, name); - #endif - - #if wxHAVE_WEB_BACKEND_GTK_WEBKIT - return new wxGtkWebKitCtrl(parent, id, url, pos, size, style, name); - #endif - - #if wxHAVE_WEB_BACKEND_IE - return new wxIEPanel(parent, id, url, pos, size, style, name); - #endif - - // fall-through intended - default: - return NULL; - } -} +///////////////////////////////////////////////////////////////////////////// +// Name: webview.cpp +// Purpose: Common interface and events for web view component +// Author: Marianne Gagnon +// Id: $Id$ +// Copyright: (c) 2010 Marianne Gagnon +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#include "wx/webview.h" + +#include "wx/osx/webkit.h" +#include "wx/gtk/webkit.h" +#include "wx/msw/webkitie.h" + +extern WXDLLEXPORT_DATA(const char) wxWebViewNameStr[] = "wxWebView"; +extern WXDLLEXPORT_DATA(const char) wxWebViewDefaultURLStr[] = "about:blank"; + +IMPLEMENT_DYNAMIC_CLASS(wxWebNavigationEvent, wxCommandEvent) + +wxDEFINE_EVENT( wxEVT_COMMAND_WEB_VIEW_NAVIGATING, wxWebNavigationEvent ); +wxDEFINE_EVENT( wxEVT_COMMAND_WEB_VIEW_NAVIGATED, wxWebNavigationEvent ); +wxDEFINE_EVENT( wxEVT_COMMAND_WEB_VIEW_LOADED, wxWebNavigationEvent ); +wxDEFINE_EVENT( wxEVT_COMMAND_WEB_VIEW_ERROR, wxWebNavigationEvent ); + +// static +wxWebView* wxWebView::New(wxWebViewBackend backend) +{ + switch (backend) + { + #if wxHAVE_WEB_BACKEND_OSX_WEBKIT + case wxWEB_VIEW_BACKEND_OSX_WEBKIT: + return new wxOSXWebKitCtrl(); + #endif + + #if wxHAVE_WEB_BACKEND_GTK_WEBKIT + case wxWEB_VIEW_BACKEND_GTK_WEBKIT: + return new wxGtkWebKitCtrl(); + #endif + + #if wxHAVE_WEB_BACKEND_IE + case wxWEB_VIEW_BACKEND_IE: + return new wxIEPanel(); + #endif + + case wxWEB_VIEW_BACKEND_DEFAULT: + + #if wxHAVE_WEB_BACKEND_OSX_WEBKIT + return new wxOSXWebKitCtrl(); + #endif + + #if wxHAVE_WEB_BACKEND_GTK_WEBKIT + return new wxGtkWebKitCtrl(); + #endif + + #if wxHAVE_WEB_BACKEND_IE + return new wxIEPanel(); + #endif + + // fall-through intended + default: + return NULL; + } +} + +// static +wxWebView* wxWebView::New(wxWindow* parent, + wxWindowID id, + const wxString& url, + const wxPoint& pos, + const wxSize& size, + wxWebViewBackend backend, + long style, + const wxString& name) +{ + switch (backend) + { + #if wxHAVE_WEB_BACKEND_OSX_WEBKIT + case wxWEB_VIEW_BACKEND_OSX_WEBKIT: + return new wxOSXWebKitCtrl(parent, id, url, pos, size, style, + name); + #endif + + #if wxHAVE_WEB_BACKEND_GTK_WEBKIT + case wxWEB_VIEW_BACKEND_GTK_WEBKIT: + return new wxGtkWebKitCtrl(parent, id, url, pos, size, style, + name); + #endif + + #if wxHAVE_WEB_BACKEND_IE + case wxWEB_VIEW_BACKEND_IE: + return new wxIEPanel(parent, id, url, pos, size, style, name); + #endif + + case wxWEB_VIEW_BACKEND_DEFAULT: + + #if wxHAVE_WEB_BACKEND_OSX_WEBKIT + return new wxOSXWebKitCtrl(parent, id, url, pos, size, style, name); + #endif + + #if wxHAVE_WEB_BACKEND_GTK_WEBKIT + return new wxGtkWebKitCtrl(parent, id, url, pos, size, style, name); + #endif + + #if wxHAVE_WEB_BACKEND_IE + return new wxIEPanel(parent, id, url, pos, size, style, name); + #endif + + // fall-through intended + default: + return NULL; + } +} diff --git a/src/gtk/webview.cpp b/src/gtk/webview.cpp index 2aac2708ff..915f86b70b 100644 --- a/src/gtk/webview.cpp +++ b/src/gtk/webview.cpp @@ -1,560 +1,560 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: src/gtk/webview.cpp -// Purpose: GTK WebKit backend for web view component -// Author: Marianne Gagnon, Robert Roebling -// Id: $Id$ -// Copyright: (c) 2010 Marianne Gagnon, 1998 Robert Roebling -// Licence: wxWindows licence -///////////////////////////////////////////////////////////////////////////// - -// For compilers that support precompilation, includes "wx.h". -#include "wx/wxprec.h" - - -#if wxHAVE_WEB_BACKEND_GTK_WEBKIT - -#include "wx/stockitem.h" -#include "wx/gtk/webview.h" -#include "wx/gtk/control.h" -#include "wx/gtk/private.h" -#include "webkit/webkit.h" - -// ---------------------------------------------------------------------------- -// GTK callbacks -// ---------------------------------------------------------------------------- - -extern "C" -{ - -static void -wxgtk_webkitctrl_load_status_callback(GtkWidget* widget, GParamSpec* arg1, - wxWebViewGTKWebKit *webKitCtrl) -{ - if (!webKitCtrl->m_ready) return; - - wxString url = webKitCtrl->GetCurrentURL(); - - WebKitLoadStatus status; - g_object_get(G_OBJECT(widget), "load-status", &status, NULL); - - wxString target; // TODO: get target (if possible) - - if (status == WEBKIT_LOAD_FINISHED) - { - webKitCtrl->m_busy = false; - wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_LOADED, - webKitCtrl->GetId(), - url, target, false); - - if (webKitCtrl && webKitCtrl->GetEventHandler()) - webKitCtrl->GetEventHandler()->ProcessEvent(thisEvent); - } - else if (status == WEBKIT_LOAD_COMMITTED) - { - webKitCtrl->m_busy = true; - wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_NAVIGATED, - webKitCtrl->GetId(), - url, target, false); - - if (webKitCtrl && webKitCtrl->GetEventHandler()) - webKitCtrl->GetEventHandler()->ProcessEvent(thisEvent); - } -} - -static WebKitNavigationResponse -wxgtk_webkitctrl_navigation_requ_callback(WebKitWebView *web_view, - WebKitWebFrame *frame, - WebKitNetworkRequest *request, - wxWebViewGTKWebKit *webKitCtrl) -{ - 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); - - if (webKitCtrl && webKitCtrl->GetEventHandler()) - webKitCtrl->GetEventHandler()->ProcessEvent(thisEvent); - - if (thisEvent.IsVetoed()) - { - webKitCtrl->m_busy = false; - return WEBKIT_NAVIGATION_RESPONSE_IGNORE; - } - else - { - return WEBKIT_NAVIGATION_RESPONSE_ACCEPT; - } -} - -static gboolean -wxgtk_webkitctrl_error (WebKitWebView *web_view, - WebKitWebFrame *web_frame, - gchar *uri, - gpointer web_error, - wxWebViewGTKWebKit* webKitWindow) -{ - webKitWindow->m_busy = false; - wxWebNavigationError type = wxWEB_NAV_ERR_OTHER; - - GError* error = (GError*)web_error; - wxString description(error->message, wxConvUTF8); - - if (strcmp(g_quark_to_string(error->domain), "soup_http_error_quark") == 0) - { - switch (error->code) - { - case SOUP_STATUS_CANCELLED: - type = wxWEB_NAV_ERR_USER_CANCELLED; - break; - - case SOUP_STATUS_CANT_RESOLVE: - case SOUP_STATUS_NOT_FOUND: - type = wxWEB_NAV_ERR_NOT_FOUND; - break; - - case SOUP_STATUS_CANT_RESOLVE_PROXY: - case SOUP_STATUS_CANT_CONNECT: - case SOUP_STATUS_CANT_CONNECT_PROXY: - case SOUP_STATUS_SSL_FAILED: - case SOUP_STATUS_IO_ERROR: - type = wxWEB_NAV_ERR_CONNECTION; - break; - - case SOUP_STATUS_MALFORMED: - //case SOUP_STATUS_TOO_MANY_REDIRECTS: - type = wxWEB_NAV_ERR_REQUEST; - break; - - //case SOUP_STATUS_NO_CONTENT: - //case SOUP_STATUS_RESET_CONTENT: - - case SOUP_STATUS_BAD_REQUEST: - type = wxWEB_NAV_ERR_REQUEST; - break; - - case SOUP_STATUS_UNAUTHORIZED: - case SOUP_STATUS_FORBIDDEN: - type = wxWEB_NAV_ERR_AUTH; - break; - - case SOUP_STATUS_METHOD_NOT_ALLOWED: - case SOUP_STATUS_NOT_ACCEPTABLE: - type = wxWEB_NAV_ERR_SECURITY; - break; - - case SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED: - type = wxWEB_NAV_ERR_AUTH; - break; - - case SOUP_STATUS_REQUEST_TIMEOUT: - type = wxWEB_NAV_ERR_CONNECTION; - break; - - //case SOUP_STATUS_PAYMENT_REQUIRED: - case SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE: - case SOUP_STATUS_REQUEST_URI_TOO_LONG: - case SOUP_STATUS_UNSUPPORTED_MEDIA_TYPE: - type = wxWEB_NAV_ERR_REQUEST; - break; - - case SOUP_STATUS_BAD_GATEWAY: - case SOUP_STATUS_SERVICE_UNAVAILABLE: - case SOUP_STATUS_GATEWAY_TIMEOUT: - type = wxWEB_NAV_ERR_CONNECTION; - break; - - case SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED: - type = wxWEB_NAV_ERR_REQUEST; - break; - //case SOUP_STATUS_INSUFFICIENT_STORAGE: - //case SOUP_STATUS_NOT_EXTENDED: - } - } - else if (strcmp(g_quark_to_string(error->domain), - "webkit-network-error-quark") == 0) - { - switch (error->code) - { - //WEBKIT_NETWORK_ERROR_FAILED: - //WEBKIT_NETWORK_ERROR_TRANSPORT: - - case WEBKIT_NETWORK_ERROR_UNKNOWN_PROTOCOL: - type = wxWEB_NAV_ERR_REQUEST; - break; - - case WEBKIT_NETWORK_ERROR_CANCELLED: - type = wxWEB_NAV_ERR_USER_CANCELLED; - break; - - case WEBKIT_NETWORK_ERROR_FILE_DOES_NOT_EXIST: - type = wxWEB_NAV_ERR_NOT_FOUND; - break; - } - } - else if (strcmp(g_quark_to_string(error->domain), - "webkit-policy-error-quark") == 0) - { - switch (error->code) - { - //case WEBKIT_POLICY_ERROR_FAILED: - //case WEBKIT_POLICY_ERROR_CANNOT_SHOW_MIME_TYPE: - //case WEBKIT_POLICY_ERROR_CANNOT_SHOW_URL: - //case WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE: - case WEBKIT_POLICY_ERROR_CANNOT_USE_RESTRICTED_PORT: - type = wxWEB_NAV_ERR_SECURITY; - break; - } - } - /* - webkit_plugin_error_quark - else - { - printf("Error domain %s\n", g_quark_to_string(error->domain)); - } - */ - - wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_ERROR, - webKitWindow->GetId(), - uri, - wxEmptyString, - false); - thisEvent.SetString(description); - thisEvent.SetInt(type); - - if (webKitWindow && webKitWindow->GetEventHandler()) - { - webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); - } - - return FALSE; -} - - -} // extern "C" - -//----------------------------------------------------------------------------- -// wxWebViewGTKWebKit -//----------------------------------------------------------------------------- - -//IMPLEMENT_DYNAMIC_CLASS(wxWebViewGTKWebKit, wxControl) - -bool wxWebViewGTKWebKit::Create(wxWindow *parent, - wxWindowID id, - const wxString &url, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name) -{ - m_ready = false; - m_busy = false; - - if (!PreCreation( parent, pos, size ) || - !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name )) - { - wxFAIL_MSG( wxT("wxWebViewGTKWebKit creation failed") ); - 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); - - g_signal_connect_after(web_view, "notify::load-status", - G_CALLBACK(wxgtk_webkitctrl_load_status_callback), - 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), - 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); - - m_parent->DoAddChild( this ); - - PostCreation(size); - - /* Open a webpage */ - webkit_web_view_load_uri (WEBKIT_WEB_VIEW (web_view), url); - - m_ready = true; - - return true; -} - -bool wxWebViewGTKWebKit::Enable( bool enable ) -{ - if (!wxControl::Enable(enable)) - return false; - - gtk_widget_set_sensitive(GTK_BIN(m_widget)->child, enable); - - //if (enable) - // GTKFixSensitivity(); - - return true; -} - -GdkWindow* -wxWebViewGTKWebKit::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const -{ - GdkWindow* window = gtk_widget_get_parent_window(m_widget); - return window; -} - -void wxWebViewGTKWebKit::ZoomIn() -{ - webkit_web_view_zoom_in (WEBKIT_WEB_VIEW(web_view)); -} - -void wxWebViewGTKWebKit::ZoomOut() -{ - webkit_web_view_zoom_out (WEBKIT_WEB_VIEW(web_view)); -} - -void wxWebViewGTKWebKit::SetWebkitZoom(float level) -{ - webkit_web_view_set_zoom_level (WEBKIT_WEB_VIEW(web_view), level); -} - -float wxWebViewGTKWebKit::GetWebkitZoom() -{ - return webkit_web_view_get_zoom_level (WEBKIT_WEB_VIEW(web_view)); -} - -void wxWebViewGTKWebKit::Stop() -{ - webkit_web_view_stop_loading (WEBKIT_WEB_VIEW(web_view)); -} - -void wxWebViewGTKWebKit::Reload(wxWebViewReloadFlags flags) -{ - if (flags & wxWEB_VIEW_RELOAD_NO_CACHE) - { - webkit_web_view_reload_bypass_cache (WEBKIT_WEB_VIEW(web_view)); - } - else - { - webkit_web_view_reload (WEBKIT_WEB_VIEW(web_view)); - } -} - -void wxWebViewGTKWebKit::LoadUrl(const wxString& url) -{ - webkit_web_view_open(WEBKIT_WEB_VIEW(web_view), wxGTK_CONV(loc)); -} - - -void wxWebViewGTKWebKit::GoBack() -{ - webkit_web_view_go_back (WEBKIT_WEB_VIEW(web_view)); -} - -void wxWebViewGTKWebKit::GoForward() -{ - webkit_web_view_go_forward (WEBKIT_WEB_VIEW(web_view)); -} - - -bool wxWebViewGTKWebKit::CanGoBack() -{ - return webkit_web_view_can_go_back (WEBKIT_WEB_VIEW(web_view)); -} - - -bool wxWebViewGTKWebKit::CanGoForward() -{ - return webkit_web_view_can_go_forward (WEBKIT_WEB_VIEW(web_view)); -} - - -wxString wxWebViewGTKWebKit::GetCurrentURL() -{ - // 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))); -} - - -wxString wxWebViewGTKWebKit::GetCurrentTitle() -{ - return wxString::FromUTF8(webkit_web_view_get_title( - WEBKIT_WEB_VIEW(web_view))); -} - - -wxString wxWebViewGTKWebKit::GetPageSource() -{ - WebKitWebFrame* frame = webkit_web_view_get_main_frame( - WEBKIT_WEB_VIEW(web_view)); - WebKitWebDataSource* src = webkit_web_frame_get_data_source (frame); - - // TODO: check encoding with - // const gchar* - // webkit_web_data_source_get_encoding(WebKitWebDataSource *data_source); - return wxString(webkit_web_data_source_get_data (src)->str, wxConvUTF8); -} - - -wxWebViewZoom wxWebViewGTKWebKit::GetZoom() -{ - float zoom = GetWebkitZoom(); - - // arbitrary way to map float zoom to our common zoom enum - if (zoom <= 0.65) - { - return wxWEB_VIEW_ZOOM_TINY; - } - else if (zoom > 0.65 && zoom <= 0.90) - { - return wxWEB_VIEW_ZOOM_SMALL; - } - else if (zoom > 0.90 && zoom <= 1.15) - { - return wxWEB_VIEW_ZOOM_MEDIUM; - } - else if (zoom > 1.15 && zoom <= 1.45) - { - return wxWEB_VIEW_ZOOM_LARGE; - } - else if (zoom > 1.45) - { - return wxWEB_VIEW_ZOOM_LARGEST; - } - - // to shut up compilers, this can never be reached logically - wxASSERT(false); - return wxWEB_VIEW_ZOOM_MEDIUM; -} - - -void wxWebViewGTKWebKit::SetZoom(wxWebViewZoom zoom) -{ - // arbitrary way to map our common zoom enum to float zoom - switch (zoom) - { - case wxWEB_VIEW_ZOOM_TINY: - SetWebkitZoom(0.6f); - break; - - case wxWEB_VIEW_ZOOM_SMALL: - SetWebkitZoom(0.8f); - break; - - case wxWEB_VIEW_ZOOM_MEDIUM: - SetWebkitZoom(1.0f); - break; - - case wxWEB_VIEW_ZOOM_LARGE: - SetWebkitZoom(1.3); - break; - - case wxWEB_VIEW_ZOOM_LARGEST: - SetWebkitZoom(1.6); - break; - - default: - wxASSERT(false); - } -} - -void wxWebViewGTKWebKit::SetZoomType(wxWebViewZoomType type) -{ - webkit_web_view_set_full_content_zoom(WEBKIT_WEB_VIEW(web_view), - (type == wxWEB_VIEW_ZOOM_TYPE_LAYOUT ? - TRUE : FALSE)); -} - -wxWebViewZoomType wxWebViewGTKWebKit::GetZoomType() const -{ - gboolean fczoom = webkit_web_view_get_full_content_zoom( - WEBKIT_WEB_VIEW(web_view)); - - if (fczoom) return wxWEB_VIEW_ZOOM_TYPE_LAYOUT; - else return wxWEB_VIEW_ZOOM_TYPE_TEXT; -} - -bool wxWebViewGTKWebKit::CanSetZoomType(wxWebViewZoomType) const -{ - // this port supports all zoom types - return true; -} - -void wxWebViewGTKWebKit::SetPage(const wxString& html, const wxString& baseUri) -{ - webkit_web_view_load_string (WEBKIT_WEB_VIEW(web_view), - html.mb_str(wxConvUTF8), - "text/html", - "UTF-8", - baseUri.mb_str(wxConvUTF8)); -} - -void wxWebViewGTKWebKit::Print() -{ - WebKitWebFrame* frame = webkit_web_view_get_main_frame( - WEBKIT_WEB_VIEW(web_view)); - webkit_web_frame_print (frame); - - // GtkPrintOperationResult webkit_web_frame_print_full - // (WebKitWebFrame *frame, - // GtkPrintOperation *operation, - // GtkPrintOperationAction action, - // GError **error); - -} - - -bool wxWebViewGTKWebKit::IsBusy() -{ - return m_busy; - - // This code looks nice but returns true after a page was cancelled - /* - WebKitLoadStatus status = webkit_web_view_get_load_status - (WEBKIT_WEB_VIEW(web_view)); - - -#if WEBKIT_CHECK_VERSION(1,1,16) - // WEBKIT_LOAD_FAILED is new in webkit 1.1.16 - if (status == WEBKIT_LOAD_FAILED) - { - return false; - } -#endif - if (status == WEBKIT_LOAD_FINISHED) - { - return false; - } - - return true; - */ -} - -// static -wxVisualAttributes -wxWebViewGTKWebKit::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant)) -{ - return GetDefaultAttributesFromGTKWidget(webkit_web_view_new); -} - - -#endif // wxHAVE_WEB_BACKEND_GTK_WEBKIT +///////////////////////////////////////////////////////////////////////////// +// Name: src/gtk/webview.cpp +// Purpose: GTK WebKit backend for web view component +// Author: Marianne Gagnon, Robert Roebling +// Id: $Id$ +// Copyright: (c) 2010 Marianne Gagnon, 1998 Robert Roebling +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + + +#if wxHAVE_WEB_BACKEND_GTK_WEBKIT + +#include "wx/stockitem.h" +#include "wx/gtk/webview.h" +#include "wx/gtk/control.h" +#include "wx/gtk/private.h" +#include "webkit/webkit.h" + +// ---------------------------------------------------------------------------- +// GTK callbacks +// ---------------------------------------------------------------------------- + +extern "C" +{ + +static void +wxgtk_webkitctrl_load_status_callback(GtkWidget* widget, GParamSpec* arg1, + wxWebViewGTKWebKit *webKitCtrl) +{ + if (!webKitCtrl->m_ready) return; + + wxString url = webKitCtrl->GetCurrentURL(); + + WebKitLoadStatus status; + g_object_get(G_OBJECT(widget), "load-status", &status, NULL); + + wxString target; // TODO: get target (if possible) + + if (status == WEBKIT_LOAD_FINISHED) + { + webKitCtrl->m_busy = false; + wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_LOADED, + webKitCtrl->GetId(), + url, target, false); + + if (webKitCtrl && webKitCtrl->GetEventHandler()) + webKitCtrl->GetEventHandler()->ProcessEvent(thisEvent); + } + else if (status == WEBKIT_LOAD_COMMITTED) + { + webKitCtrl->m_busy = true; + wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_NAVIGATED, + webKitCtrl->GetId(), + url, target, false); + + if (webKitCtrl && webKitCtrl->GetEventHandler()) + webKitCtrl->GetEventHandler()->ProcessEvent(thisEvent); + } +} + +static WebKitNavigationResponse +wxgtk_webkitctrl_navigation_requ_callback(WebKitWebView *web_view, + WebKitWebFrame *frame, + WebKitNetworkRequest *request, + wxWebViewGTKWebKit *webKitCtrl) +{ + 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); + + if (webKitCtrl && webKitCtrl->GetEventHandler()) + webKitCtrl->GetEventHandler()->ProcessEvent(thisEvent); + + if (thisEvent.IsVetoed()) + { + webKitCtrl->m_busy = false; + return WEBKIT_NAVIGATION_RESPONSE_IGNORE; + } + else + { + return WEBKIT_NAVIGATION_RESPONSE_ACCEPT; + } +} + +static gboolean +wxgtk_webkitctrl_error (WebKitWebView *web_view, + WebKitWebFrame *web_frame, + gchar *uri, + gpointer web_error, + wxWebViewGTKWebKit* webKitWindow) +{ + webKitWindow->m_busy = false; + wxWebNavigationError type = wxWEB_NAV_ERR_OTHER; + + GError* error = (GError*)web_error; + wxString description(error->message, wxConvUTF8); + + if (strcmp(g_quark_to_string(error->domain), "soup_http_error_quark") == 0) + { + switch (error->code) + { + case SOUP_STATUS_CANCELLED: + type = wxWEB_NAV_ERR_USER_CANCELLED; + break; + + case SOUP_STATUS_CANT_RESOLVE: + case SOUP_STATUS_NOT_FOUND: + type = wxWEB_NAV_ERR_NOT_FOUND; + break; + + case SOUP_STATUS_CANT_RESOLVE_PROXY: + case SOUP_STATUS_CANT_CONNECT: + case SOUP_STATUS_CANT_CONNECT_PROXY: + case SOUP_STATUS_SSL_FAILED: + case SOUP_STATUS_IO_ERROR: + type = wxWEB_NAV_ERR_CONNECTION; + break; + + case SOUP_STATUS_MALFORMED: + //case SOUP_STATUS_TOO_MANY_REDIRECTS: + type = wxWEB_NAV_ERR_REQUEST; + break; + + //case SOUP_STATUS_NO_CONTENT: + //case SOUP_STATUS_RESET_CONTENT: + + case SOUP_STATUS_BAD_REQUEST: + type = wxWEB_NAV_ERR_REQUEST; + break; + + case SOUP_STATUS_UNAUTHORIZED: + case SOUP_STATUS_FORBIDDEN: + type = wxWEB_NAV_ERR_AUTH; + break; + + case SOUP_STATUS_METHOD_NOT_ALLOWED: + case SOUP_STATUS_NOT_ACCEPTABLE: + type = wxWEB_NAV_ERR_SECURITY; + break; + + case SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED: + type = wxWEB_NAV_ERR_AUTH; + break; + + case SOUP_STATUS_REQUEST_TIMEOUT: + type = wxWEB_NAV_ERR_CONNECTION; + break; + + //case SOUP_STATUS_PAYMENT_REQUIRED: + case SOUP_STATUS_REQUEST_ENTITY_TOO_LARGE: + case SOUP_STATUS_REQUEST_URI_TOO_LONG: + case SOUP_STATUS_UNSUPPORTED_MEDIA_TYPE: + type = wxWEB_NAV_ERR_REQUEST; + break; + + case SOUP_STATUS_BAD_GATEWAY: + case SOUP_STATUS_SERVICE_UNAVAILABLE: + case SOUP_STATUS_GATEWAY_TIMEOUT: + type = wxWEB_NAV_ERR_CONNECTION; + break; + + case SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED: + type = wxWEB_NAV_ERR_REQUEST; + break; + //case SOUP_STATUS_INSUFFICIENT_STORAGE: + //case SOUP_STATUS_NOT_EXTENDED: + } + } + else if (strcmp(g_quark_to_string(error->domain), + "webkit-network-error-quark") == 0) + { + switch (error->code) + { + //WEBKIT_NETWORK_ERROR_FAILED: + //WEBKIT_NETWORK_ERROR_TRANSPORT: + + case WEBKIT_NETWORK_ERROR_UNKNOWN_PROTOCOL: + type = wxWEB_NAV_ERR_REQUEST; + break; + + case WEBKIT_NETWORK_ERROR_CANCELLED: + type = wxWEB_NAV_ERR_USER_CANCELLED; + break; + + case WEBKIT_NETWORK_ERROR_FILE_DOES_NOT_EXIST: + type = wxWEB_NAV_ERR_NOT_FOUND; + break; + } + } + else if (strcmp(g_quark_to_string(error->domain), + "webkit-policy-error-quark") == 0) + { + switch (error->code) + { + //case WEBKIT_POLICY_ERROR_FAILED: + //case WEBKIT_POLICY_ERROR_CANNOT_SHOW_MIME_TYPE: + //case WEBKIT_POLICY_ERROR_CANNOT_SHOW_URL: + //case WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE: + case WEBKIT_POLICY_ERROR_CANNOT_USE_RESTRICTED_PORT: + type = wxWEB_NAV_ERR_SECURITY; + break; + } + } + /* + webkit_plugin_error_quark + else + { + printf("Error domain %s\n", g_quark_to_string(error->domain)); + } + */ + + wxWebNavigationEvent thisEvent(wxEVT_COMMAND_WEB_VIEW_ERROR, + webKitWindow->GetId(), + uri, + wxEmptyString, + false); + thisEvent.SetString(description); + thisEvent.SetInt(type); + + if (webKitWindow && webKitWindow->GetEventHandler()) + { + webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); + } + + return FALSE; +} + + +} // extern "C" + +//----------------------------------------------------------------------------- +// wxWebViewGTKWebKit +//----------------------------------------------------------------------------- + +//IMPLEMENT_DYNAMIC_CLASS(wxWebViewGTKWebKit, wxControl) + +bool wxWebViewGTKWebKit::Create(wxWindow *parent, + wxWindowID id, + const wxString &url, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name) +{ + m_ready = false; + m_busy = false; + + if (!PreCreation( parent, pos, size ) || + !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name )) + { + wxFAIL_MSG( wxT("wxWebViewGTKWebKit creation failed") ); + 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); + + g_signal_connect_after(web_view, "notify::load-status", + G_CALLBACK(wxgtk_webkitctrl_load_status_callback), + 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), + 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); + + m_parent->DoAddChild( this ); + + PostCreation(size); + + /* Open a webpage */ + webkit_web_view_load_uri (WEBKIT_WEB_VIEW (web_view), url); + + m_ready = true; + + return true; +} + +bool wxWebViewGTKWebKit::Enable( bool enable ) +{ + if (!wxControl::Enable(enable)) + return false; + + gtk_widget_set_sensitive(GTK_BIN(m_widget)->child, enable); + + //if (enable) + // GTKFixSensitivity(); + + return true; +} + +GdkWindow* +wxWebViewGTKWebKit::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const +{ + GdkWindow* window = gtk_widget_get_parent_window(m_widget); + return window; +} + +void wxWebViewGTKWebKit::ZoomIn() +{ + webkit_web_view_zoom_in (WEBKIT_WEB_VIEW(web_view)); +} + +void wxWebViewGTKWebKit::ZoomOut() +{ + webkit_web_view_zoom_out (WEBKIT_WEB_VIEW(web_view)); +} + +void wxWebViewGTKWebKit::SetWebkitZoom(float level) +{ + webkit_web_view_set_zoom_level (WEBKIT_WEB_VIEW(web_view), level); +} + +float wxWebViewGTKWebKit::GetWebkitZoom() +{ + return webkit_web_view_get_zoom_level (WEBKIT_WEB_VIEW(web_view)); +} + +void wxWebViewGTKWebKit::Stop() +{ + webkit_web_view_stop_loading (WEBKIT_WEB_VIEW(web_view)); +} + +void wxWebViewGTKWebKit::Reload(wxWebViewReloadFlags flags) +{ + if (flags & wxWEB_VIEW_RELOAD_NO_CACHE) + { + webkit_web_view_reload_bypass_cache (WEBKIT_WEB_VIEW(web_view)); + } + else + { + webkit_web_view_reload (WEBKIT_WEB_VIEW(web_view)); + } +} + +void wxWebViewGTKWebKit::LoadUrl(const wxString& url) +{ + webkit_web_view_open(WEBKIT_WEB_VIEW(web_view), wxGTK_CONV(loc)); +} + + +void wxWebViewGTKWebKit::GoBack() +{ + webkit_web_view_go_back (WEBKIT_WEB_VIEW(web_view)); +} + +void wxWebViewGTKWebKit::GoForward() +{ + webkit_web_view_go_forward (WEBKIT_WEB_VIEW(web_view)); +} + + +bool wxWebViewGTKWebKit::CanGoBack() +{ + return webkit_web_view_can_go_back (WEBKIT_WEB_VIEW(web_view)); +} + + +bool wxWebViewGTKWebKit::CanGoForward() +{ + return webkit_web_view_can_go_forward (WEBKIT_WEB_VIEW(web_view)); +} + + +wxString wxWebViewGTKWebKit::GetCurrentURL() +{ + // 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))); +} + + +wxString wxWebViewGTKWebKit::GetCurrentTitle() +{ + return wxString::FromUTF8(webkit_web_view_get_title( + WEBKIT_WEB_VIEW(web_view))); +} + + +wxString wxWebViewGTKWebKit::GetPageSource() +{ + WebKitWebFrame* frame = webkit_web_view_get_main_frame( + WEBKIT_WEB_VIEW(web_view)); + WebKitWebDataSource* src = webkit_web_frame_get_data_source (frame); + + // TODO: check encoding with + // const gchar* + // webkit_web_data_source_get_encoding(WebKitWebDataSource *data_source); + return wxString(webkit_web_data_source_get_data (src)->str, wxConvUTF8); +} + + +wxWebViewZoom wxWebViewGTKWebKit::GetZoom() +{ + float zoom = GetWebkitZoom(); + + // arbitrary way to map float zoom to our common zoom enum + if (zoom <= 0.65) + { + return wxWEB_VIEW_ZOOM_TINY; + } + else if (zoom > 0.65 && zoom <= 0.90) + { + return wxWEB_VIEW_ZOOM_SMALL; + } + else if (zoom > 0.90 && zoom <= 1.15) + { + return wxWEB_VIEW_ZOOM_MEDIUM; + } + else if (zoom > 1.15 && zoom <= 1.45) + { + return wxWEB_VIEW_ZOOM_LARGE; + } + else if (zoom > 1.45) + { + return wxWEB_VIEW_ZOOM_LARGEST; + } + + // to shut up compilers, this can never be reached logically + wxASSERT(false); + return wxWEB_VIEW_ZOOM_MEDIUM; +} + + +void wxWebViewGTKWebKit::SetZoom(wxWebViewZoom zoom) +{ + // arbitrary way to map our common zoom enum to float zoom + switch (zoom) + { + case wxWEB_VIEW_ZOOM_TINY: + SetWebkitZoom(0.6f); + break; + + case wxWEB_VIEW_ZOOM_SMALL: + SetWebkitZoom(0.8f); + break; + + case wxWEB_VIEW_ZOOM_MEDIUM: + SetWebkitZoom(1.0f); + break; + + case wxWEB_VIEW_ZOOM_LARGE: + SetWebkitZoom(1.3); + break; + + case wxWEB_VIEW_ZOOM_LARGEST: + SetWebkitZoom(1.6); + break; + + default: + wxASSERT(false); + } +} + +void wxWebViewGTKWebKit::SetZoomType(wxWebViewZoomType type) +{ + webkit_web_view_set_full_content_zoom(WEBKIT_WEB_VIEW(web_view), + (type == wxWEB_VIEW_ZOOM_TYPE_LAYOUT ? + TRUE : FALSE)); +} + +wxWebViewZoomType wxWebViewGTKWebKit::GetZoomType() const +{ + gboolean fczoom = webkit_web_view_get_full_content_zoom( + WEBKIT_WEB_VIEW(web_view)); + + if (fczoom) return wxWEB_VIEW_ZOOM_TYPE_LAYOUT; + else return wxWEB_VIEW_ZOOM_TYPE_TEXT; +} + +bool wxWebViewGTKWebKit::CanSetZoomType(wxWebViewZoomType) const +{ + // this port supports all zoom types + return true; +} + +void wxWebViewGTKWebKit::SetPage(const wxString& html, const wxString& baseUri) +{ + webkit_web_view_load_string (WEBKIT_WEB_VIEW(web_view), + html.mb_str(wxConvUTF8), + "text/html", + "UTF-8", + baseUri.mb_str(wxConvUTF8)); +} + +void wxWebViewGTKWebKit::Print() +{ + WebKitWebFrame* frame = webkit_web_view_get_main_frame( + WEBKIT_WEB_VIEW(web_view)); + webkit_web_frame_print (frame); + + // GtkPrintOperationResult webkit_web_frame_print_full + // (WebKitWebFrame *frame, + // GtkPrintOperation *operation, + // GtkPrintOperationAction action, + // GError **error); + +} + + +bool wxWebViewGTKWebKit::IsBusy() +{ + return m_busy; + + // This code looks nice but returns true after a page was cancelled + /* + WebKitLoadStatus status = webkit_web_view_get_load_status + (WEBKIT_WEB_VIEW(web_view)); + + +#if WEBKIT_CHECK_VERSION(1,1,16) + // WEBKIT_LOAD_FAILED is new in webkit 1.1.16 + if (status == WEBKIT_LOAD_FAILED) + { + return false; + } +#endif + if (status == WEBKIT_LOAD_FINISHED) + { + return false; + } + + return true; + */ +} + +// static +wxVisualAttributes +wxWebViewGTKWebKit::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant)) +{ + return GetDefaultAttributesFromGTKWidget(webkit_web_view_new); +} + + +#endif // wxHAVE_WEB_BACKEND_GTK_WEBKIT diff --git a/src/msw/webviewie.cpp b/src/msw/webviewie.cpp index e6f1246ce3..fe302da0fc 100644 --- a/src/msw/webviewie.cpp +++ b/src/msw/webviewie.cpp @@ -1,667 +1,667 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: src/msw/webviewie.cpp -// Purpose: wxMSW wxWebViewIE class implementation for web view component -// Author: Marianne Gagnon -// Id: $Id$ -// Copyright: (c) 2010 Marianne Gagnon -// Licence: wxWindows licence -///////////////////////////////////////////////////////////////////////////// - -#include "wx/msw/webview.h" - -#if wxHAVE_WEB_BACKEND_IE - -#include -#include -#include -#include -#include - -// FIXME: Seems like MINGW does not have these, how to handle cleanly? -#define DISPID_COMMANDSTATECHANGE 105 -typedef enum CommandStateChangeConstants { - CSC_UPDATECOMMANDS = (int) 0xFFFFFFFF, - CSC_NAVIGATEFORWARD = 0x1, - CSC_NAVIGATEBACK = 0x2 -} CommandStateChangeConstants; - - -// FIXME: Seems like MINGW does not have these, how to handle cleanly? -#define DISPID_NAVIGATECOMPLETE2 252 -#define DISPID_NAVIGATEERROR 271 -#define OLECMDID_OPTICAL_ZOOM 63 -#define INET_E_ERROR_FIRST 0x800C0002L -#define INET_E_INVALID_URL 0x800C0002L -#define INET_E_NO_SESSION 0x800C0003L -#define INET_E_CANNOT_CONNECT 0x800C0004L -#define INET_E_RESOURCE_NOT_FOUND 0x800C0005L -#define INET_E_OBJECT_NOT_FOUND 0x800C0006L -#define INET_E_DATA_NOT_AVAILABLE 0x800C0007L -#define INET_E_DOWNLOAD_FAILURE 0x800C0008L -#define INET_E_AUTHENTICATION_REQUIRED 0x800C0009L -#define INET_E_NO_VALID_MEDIA 0x800C000AL -#define INET_E_CONNECTION_TIMEOUT 0x800C000BL -#define INET_E_INVALID_REQUEST 0x800C000CL -#define INET_E_UNKNOWN_PROTOCOL 0x800C000DL -#define INET_E_SECURITY_PROBLEM 0x800C000EL -#define INET_E_CANNOT_LOAD_DATA 0x800C000FL -#define INET_E_CANNOT_INSTANTIATE_OBJECT 0x800C0010L -#define INET_E_QUERYOPTION_UNKNOWN 0x800C0013L -#define INET_E_REDIRECT_FAILED 0x800C0014L -#define INET_E_REDIRECT_TO_DIR 0x800C0015L -#define INET_E_CANNOT_LOCK_REQUEST 0x800C0016L -#define INET_E_USE_EXTEND_BINDING 0x800C0017L -#define INET_E_TERMINATED_BIND 0x800C0018L -#define INET_E_INVALID_CERTIFICATE 0x800C0019L -#define INET_E_CODE_DOWNLOAD_DECLINED 0x800C0100L -#define INET_E_RESULT_DISPATCHED 0x800C0200L -#define INET_E_CANNOT_REPLACE_SFP_FILE 0x800C0300L -#define INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY 0x800C0500L -#define INET_E_CODE_INSTALL_SUPPRESSED 0x800C0400L - -#define REFRESH_COMPLETELY 3 - -BEGIN_EVENT_TABLE(wxWebViewIE, wxControl) -EVT_ACTIVEX(wxID_ANY, wxWebViewIE::onActiveXEvent) -EVT_ERASE_BACKGROUND(wxWebViewIE::onEraseBg) -END_EVENT_TABLE() - -bool wxWebViewIE::Create(wxWindow* parent, - wxWindowID id, - const wxString& url, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name) -{ - if (!wxControl::Create(parent, id, pos, size, style, - wxDefaultValidator, name)) - { - return false; - } - - m_webBrowser = NULL; - m_canNavigateBack = false; - m_canNavigateForward = false; - m_isBusy = false; - - if (::CoCreateInstance(CLSID_WebBrowser, NULL, - CLSCTX_INPROC_SERVER, // CLSCTX_INPROC, - IID_IWebBrowser2 , (void**)&m_webBrowser) != 0) - { - wxLogError("Failed to initialize IE, CoCreateInstance returned an error"); - return false; - } - - m_ie.SetDispatchPtr(m_webBrowser); // wxAutomationObject will release itself - - m_webBrowser->put_RegisterAsBrowser(VARIANT_TRUE); - m_webBrowser->put_RegisterAsDropTarget(VARIANT_TRUE); - //m_webBrowser->put_Silent(VARIANT_FALSE); - - m_container = new wxActiveXContainer(this, IID_IWebBrowser2, m_webBrowser); - - SetBackgroundStyle(wxBG_STYLE_PAINT); - SetDoubleBuffered(true); - return true; -} - - -void wxWebViewIE::LoadUrl(const wxString& url) -{ - wxVariant out = m_ie.CallMethod("Navigate", (BSTR) url.wc_str(), - NULL, NULL, NULL, NULL); - - // FIXME: why is out value null?? - //(HRESULT)(out.GetLong()) == S_OK; -} - -void wxWebViewIE::SetPage(const wxString& html, const wxString& baseUrl) -{ - LoadUrl("about:blank"); - - // Let the wx events generated for navigation events be processed, so - // that the underlying IE component completes its Document object. - // FIXME: calling wxYield is not elegant nor very reliable probably - wxYield(); - - wxVariant documentVariant = m_ie.GetProperty("Document"); - void* documentPtr = documentVariant.GetVoidPtr(); - - wxASSERT (documentPtr != NULL); - - // TODO: consider the "baseUrl" parameter if possible - // TODO: consider encoding - BSTR bstr = SysAllocString(html.wc_str()); - - // Creates a new one-dimensional array - SAFEARRAY *psaStrings = SafeArrayCreateVector(VT_VARIANT, 0, 1); - if (psaStrings != NULL) - { - VARIANT *param; - HRESULT hr = SafeArrayAccessData(psaStrings, (LPVOID*)¶m); - param->vt = VT_BSTR; - param->bstrVal = bstr; - - hr = SafeArrayUnaccessData(psaStrings); - - IHTMLDocument2* document = (IHTMLDocument2*)documentPtr; - document->write(psaStrings); - - // SafeArrayDestroy calls SysFreeString for each BSTR - SafeArrayDestroy(psaStrings); - } - else - { - wxLogError("wxWebViewIE::SetPage() : psaStrings is NULL"); - } - -} - -wxString wxWebViewIE::GetPageSource() -{ - wxVariant documentVariant = m_ie.GetProperty("Document"); - void* documentPtr = documentVariant.GetVoidPtr(); - - if (documentPtr == NULL) - { - return wxEmptyString; - } - - IHTMLDocument2* document = (IHTMLDocument2*)documentPtr; - - IHTMLElement *bodyTag = NULL; - IHTMLElement *htmlTag = NULL; - document->get_body(&bodyTag); - wxASSERT(bodyTag != NULL); - - document->Release(); - bodyTag->get_parentElement(&htmlTag); - wxASSERT(htmlTag != NULL); - - BSTR bstr; - htmlTag->get_outerHTML(&bstr); - - bodyTag->Release(); - htmlTag->Release(); - - //wxMessageBox(wxString(bstr)); - - // TODO: check encoding - return wxString(bstr); -} - -// FIXME? retrieve OLECMDID_GETZOOMRANGE instead of hardcoding range 0-4 -wxWebViewZoom wxWebViewIE::GetZoom() -{ - const int zoom = GetIETextZoom(); - - switch (zoom) - { - case 0: - return wxWEB_VIEW_ZOOM_TINY; - break; - case 1: - return wxWEB_VIEW_ZOOM_SMALL; - break; - case 2: - return wxWEB_VIEW_ZOOM_MEDIUM; - break; - case 3: - return wxWEB_VIEW_ZOOM_LARGE; - break; - case 4: - return wxWEB_VIEW_ZOOM_LARGEST; - break; - default: - wxASSERT(false); - return wxWEB_VIEW_ZOOM_MEDIUM; - } -} -void wxWebViewIE::SetZoom(wxWebViewZoom zoom) -{ - // I know I could cast from enum to int since wxWebViewZoom happens to - // match with IE's zoom levels, but I don't like doing that, what if enum - // values change... - switch (zoom) - { - case wxWEB_VIEW_ZOOM_TINY: - SetIETextZoom(0); - break; - case wxWEB_VIEW_ZOOM_SMALL: - SetIETextZoom(1); - break; - case wxWEB_VIEW_ZOOM_MEDIUM: - SetIETextZoom(2); - break; - case wxWEB_VIEW_ZOOM_LARGE: - SetIETextZoom(3); - break; - case wxWEB_VIEW_ZOOM_LARGEST: - SetIETextZoom(4); - break; - default: - wxASSERT(false); - } -} - -void wxWebViewIE::SetIETextZoom(int level) -{ - VARIANT zoomVariant; - VariantInit (&zoomVariant); - V_VT(&zoomVariant) = VT_I4; - V_I4(&zoomVariant) = level; - - HRESULT result = m_webBrowser->ExecWB(OLECMDID_ZOOM, - OLECMDEXECOPT_DONTPROMPTUSER, - &zoomVariant, NULL); - wxASSERT (result == S_OK); - - VariantClear (&zoomVariant); -} - -int wxWebViewIE::GetIETextZoom() -{ - VARIANT zoomVariant; - VariantInit (&zoomVariant); - V_VT(&zoomVariant) = VT_I4; - V_I4(&zoomVariant) = 4; - - HRESULT result = m_webBrowser->ExecWB(OLECMDID_ZOOM, - OLECMDEXECOPT_DONTPROMPTUSER, - NULL, &zoomVariant); - wxASSERT (result == S_OK); - - int zoom = V_I4(&zoomVariant); - // wxMessageBox(wxString::Format("Zoom : %i", zoom)); - VariantClear (&zoomVariant); - - return zoom; -} - -void wxWebViewIE::SetIEOpticalZoom(float zoom) -{ - // TODO: add support for optical zoom (IE7+ only) - - // TODO: get range from OLECMDID_OPTICAL_GETZOOMRANGE instead of hardcoding? - wxASSERT(zoom >= 10.0f); - wxASSERT(zoom <= 1000.0f); - - VARIANT zoomVariant; - VariantInit (&zoomVariant); - V_VT(&zoomVariant) = VT_I4; - V_I4(&zoomVariant) = (zoom * 100.0f); - - HRESULT result = m_webBrowser->ExecWB((OLECMDID)OLECMDID_OPTICAL_ZOOM, - OLECMDEXECOPT_DODEFAULT, - &zoomVariant, - NULL); - wxASSERT (result == S_OK); -} - -float wxWebViewIE::GetIEOpticalZoom() -{ - // TODO: add support for optical zoom (IE7+ only) - - VARIANT zoomVariant; - VariantInit (&zoomVariant); - V_VT(&zoomVariant) = VT_I4; - V_I4(&zoomVariant) = -1; - - HRESULT result = m_webBrowser->ExecWB((OLECMDID)OLECMDID_OPTICAL_ZOOM, - OLECMDEXECOPT_DODEFAULT, NULL, - &zoomVariant); - wxASSERT (result == S_OK); - - const int zoom = V_I4(&zoomVariant); - VariantClear (&zoomVariant); - - return zoom / 100.0f; -} - -void wxWebViewIE::SetZoomType(wxWebViewZoomType) -{ - // TODO: add support for optical zoom (IE7+ only) - wxASSERT(false); -} - -wxWebViewZoomType wxWebViewIE::GetZoomType() const -{ - // TODO: add support for optical zoom (IE7+ only) - return wxWEB_VIEW_ZOOM_TYPE_TEXT; -} - -bool wxWebViewIE::CanSetZoomType(wxWebViewZoomType) const -{ - // both are supported - // TODO: IE6 only supports text zoom, check if it's IE6 first - return true; -} - -void wxWebViewIE::Print() -{ - m_webBrowser->ExecWB(OLECMDID_PRINTPREVIEW, - OLECMDEXECOPT_DODEFAULT, NULL, NULL); -} - -void wxWebViewIE::GoBack() -{ - wxVariant out = m_ie.CallMethod("GoBack"); - - // FIXME: why is out value null?? - //return (HRESULT)(out.GetLong()) == S_OK; -} - -void wxWebViewIE::GoForward() -{ - wxVariant out = m_ie.CallMethod("GoForward"); - - // FIXME: why is out value null?? - //return (HRESULT)(out.GetLong()) == S_OK; -} - -void wxWebViewIE::Stop() -{ - wxVariant out = m_ie.CallMethod("Stop"); - - // FIXME: why is out value null?? - //return (HRESULT)(out.GetLong()) == S_OK; -} - - -void wxWebViewIE::Reload(wxWebViewReloadFlags flags) -{ - wxVariant out; - - if (flags & wxWEB_VIEW_RELOAD_NO_CACHE) - { - VARIANTARG level; - level.vt = VT_I2; - level.iVal = 3; - out = m_ie.CallMethod("Refresh2", &level); - } - else - { - out = m_ie.CallMethod("Refresh"); - } - - if (out.GetType() != "null") - { - wxMessageBox("Non-null return message : " + out.GetType()); - } -} - -bool wxWebViewIE::IsOfflineMode() -{ - wxVariant out = m_ie.GetProperty("Offline"); - - wxASSERT(out.GetType() == "bool"); - - return out.GetBool(); -} - -void wxWebViewIE::SetOfflineMode(bool offline) -{ - // FIXME: the wxWidgets docs do not really document what the return - // parameter of PutProperty is - const bool success = m_ie.PutProperty("Offline", (offline ? - VARIANT_TRUE : - VARIANT_FALSE)); - wxASSERT(success); -} - -bool wxWebViewIE::IsBusy() -{ - if (m_isBusy) return true; - - wxVariant out = m_ie.GetProperty("Busy"); - - wxASSERT(out.GetType() == "bool"); - - return out.GetBool(); -} - -wxString wxWebViewIE::GetCurrentURL() -{ - wxVariant out = m_ie.GetProperty("LocationURL"); - - wxASSERT(out.GetType() == "string"); - return out.GetString(); -} - -wxString wxWebViewIE::GetCurrentTitle() -{ - wxVariant out = m_ie.GetProperty("LocationName"); - - wxASSERT(out.GetType() == "string"); - return out.GetString(); -} - -void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt) -{ - if (m_webBrowser == NULL) return; - - switch (evt.GetDispatchId()) - { - case DISPID_BEFORENAVIGATE2: - { - m_isBusy = true; - - wxString url = evt[1].GetString(); - wxString target = evt[3].GetString(); - - wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATING, - GetId(), url, target, true); - event.SetEventObject(this); - HandleWindowEvent(event); - - if (event.IsVetoed()) - { - wxActiveXEventNativeMSW* nativeParams = - evt.GetNativeParameters(); - *V_BOOLREF(&nativeParams->pDispParams->rgvarg[0]) = VARIANT_TRUE; - } - - // at this point, either the navigation event has been cancelled - // and we're not busy, either it was accepted and IWebBrowser2's - // Busy property will be true; so we don't need our override - // flag anymore. - m_isBusy = false; - - break; - } - - case DISPID_NAVIGATECOMPLETE2: - { - wxString url = evt[1].GetString(); - // TODO: set target parameter if possible - wxString target = wxEmptyString; - wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATED, - GetId(), url, target, false); - event.SetEventObject(this); - HandleWindowEvent(event); - break; - } - - case DISPID_PROGRESSCHANGE: - { - // download progress - break; - } - - case DISPID_DOCUMENTCOMPLETE: - { - wxString url = evt[1].GetString(); - // TODO: set target parameter if possible - wxString target = wxEmptyString; - wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_LOADED, GetId(), - url, target, false); - event.SetEventObject(this); - HandleWindowEvent(event); - break; - } - - case DISPID_STATUSTEXTCHANGE: - { - break; - } - - case DISPID_TITLECHANGE: - { - break; - } - - case DISPID_NAVIGATEERROR: - { - wxWebNavigationError errorType = wxWEB_NAV_ERR_OTHER; - wxString errorCode = "?"; - switch (evt[3].GetLong()) - { - case INET_E_INVALID_URL: // (0x800C0002L or -2146697214) - errorCode = "INET_E_INVALID_URL"; - errorType = wxWEB_NAV_ERR_REQUEST; - break; - case INET_E_NO_SESSION: // (0x800C0003L or -2146697213) - errorCode = "INET_E_NO_SESSION"; - errorType = wxWEB_NAV_ERR_CONNECTION; - break; - case INET_E_CANNOT_CONNECT: // (0x800C0004L or -2146697212) - errorCode = "INET_E_CANNOT_CONNECT"; - errorType = wxWEB_NAV_ERR_CONNECTION; - break; - case INET_E_RESOURCE_NOT_FOUND: // (0x800C0005L or -2146697211) - errorCode = "INET_E_RESOURCE_NOT_FOUND"; - errorType = wxWEB_NAV_ERR_NOT_FOUND; - break; - case INET_E_OBJECT_NOT_FOUND: // (0x800C0006L or -2146697210) - errorCode = "INET_E_OBJECT_NOT_FOUND"; - errorType = wxWEB_NAV_ERR_NOT_FOUND; - break; - case INET_E_DATA_NOT_AVAILABLE: // (0x800C0007L or -2146697209) - errorCode = "INET_E_DATA_NOT_AVAILABLE"; - errorType = wxWEB_NAV_ERR_NOT_FOUND; - break; - case INET_E_DOWNLOAD_FAILURE: // (0x800C0008L or -2146697208) - errorCode = "INET_E_DOWNLOAD_FAILURE"; - errorType = wxWEB_NAV_ERR_CONNECTION; - break; - case INET_E_AUTHENTICATION_REQUIRED: // (0x800C0009L or -2146697207) - errorCode = "INET_E_AUTHENTICATION_REQUIRED"; - errorType = wxWEB_NAV_ERR_AUTH; - break; - case INET_E_NO_VALID_MEDIA: // (0x800C000AL or -2146697206) - errorCode = "INET_E_NO_VALID_MEDIA"; - errorType = wxWEB_NAV_ERR_REQUEST; - break; - case INET_E_CONNECTION_TIMEOUT: // (0x800C000BL or -2146697205) - errorCode = "INET_E_CONNECTION_TIMEOUT"; - errorType = wxWEB_NAV_ERR_CONNECTION; - break; - case INET_E_INVALID_REQUEST: // (0x800C000CL or -2146697204) - errorCode = "INET_E_INVALID_REQUEST"; - errorType = wxWEB_NAV_ERR_REQUEST; - break; - case INET_E_UNKNOWN_PROTOCOL: // (0x800C000DL or -2146697203) - errorCode = "INET_E_UNKNOWN_PROTOCOL"; - errorType = wxWEB_NAV_ERR_REQUEST; - break; - case INET_E_SECURITY_PROBLEM: // (0x800C000EL or -2146697202) - errorCode = "INET_E_SECURITY_PROBLEM"; - errorType = wxWEB_NAV_ERR_SECURITY; - break; - case INET_E_CANNOT_LOAD_DATA: // (0x800C000FL or -2146697201) - errorCode = "INET_E_CANNOT_LOAD_DATA"; - errorType = wxWEB_NAV_ERR_OTHER; - break; - case INET_E_CANNOT_INSTANTIATE_OBJECT: - // CoCreateInstance will return an error code if this happens, - // we'll handle this above. - return; - break; - case INET_E_REDIRECT_FAILED: // (0x800C0014L or -2146697196) - errorCode = "INET_E_REDIRECT_FAILED"; - errorType = wxWEB_NAV_ERR_OTHER; - break; - case INET_E_REDIRECT_TO_DIR: // (0x800C0015L or -2146697195) - errorCode = "INET_E_REDIRECT_TO_DIR"; - errorType = wxWEB_NAV_ERR_REQUEST; - break; - case INET_E_CANNOT_LOCK_REQUEST: // (0x800C0016L or -2146697194) - errorCode = "INET_E_CANNOT_LOCK_REQUEST"; - errorType = wxWEB_NAV_ERR_OTHER; - break; - case INET_E_USE_EXTEND_BINDING: // (0x800C0017L or -2146697193) - errorCode = "INET_E_USE_EXTEND_BINDING"; - errorType = wxWEB_NAV_ERR_OTHER; - break; - case INET_E_TERMINATED_BIND: // (0x800C0018L or -2146697192) - errorCode = "INET_E_TERMINATED_BIND"; - errorType = wxWEB_NAV_ERR_OTHER; - break; - case INET_E_INVALID_CERTIFICATE: // (0x800C0019L or -2146697191) - errorCode = "INET_E_INVALID_CERTIFICATE"; - errorType = wxWEB_NAV_ERR_CERTIFICATE; - break; - case INET_E_CODE_DOWNLOAD_DECLINED: // (0x800C0100L or -2146696960) - errorCode = "INET_E_CODE_DOWNLOAD_DECLINED"; - errorType = wxWEB_NAV_ERR_USER_CANCELLED; - break; - case INET_E_RESULT_DISPATCHED: // (0x800C0200L or -2146696704) - // cancel request cancelled... - errorCode = "INET_E_RESULT_DISPATCHED"; - errorType = wxWEB_NAV_ERR_OTHER; - break; - case INET_E_CANNOT_REPLACE_SFP_FILE: // (0x800C0300L or -2146696448) - errorCode = "INET_E_CANNOT_REPLACE_SFP_FILE"; - errorType = wxWEB_NAV_ERR_SECURITY; - break; - case INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY: - errorCode = "INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY"; - errorType = wxWEB_NAV_ERR_SECURITY; - break; - case INET_E_CODE_INSTALL_SUPPRESSED: - errorCode = "INET_E_CODE_INSTALL_SUPPRESSED"; - errorType = wxWEB_NAV_ERR_SECURITY; - break; - } - - wxString url = evt[1].GetString(); - wxString target = evt[2].GetString(); - wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_ERROR, GetId(), - url, target, false); - event.SetEventObject(this); - event.SetInt(errorType); - event.SetString(errorCode); - HandleWindowEvent(event); - break; - } - - case DISPID_COMMANDSTATECHANGE: - { - long commandId = evt[0].GetLong(); - bool enable = evt[1].GetBool(); - if (commandId == CSC_NAVIGATEBACK) - { - m_canNavigateBack = enable; - } - else if (commandId == CSC_NAVIGATEFORWARD) - { - m_canNavigateForward = enable; - } - } - - /* - case DISPID_NEWWINDOW2: - //case DISPID_NEWWINDOW3: - { - wxLogMessage("DISPID_NEWWINDOW2\n"); - wxActiveXEventNativeMSW* nativeParams = evt.GetNativeParameters(); - // Cancel the attempt to open a new window - *V_BOOLREF(&nativeParams->pDispParams->rgvarg[0]) = VARIANT_TRUE; - }*/ - } - - evt.Skip(); -} - -#endif +///////////////////////////////////////////////////////////////////////////// +// Name: src/msw/webviewie.cpp +// Purpose: wxMSW wxWebViewIE class implementation for web view component +// Author: Marianne Gagnon +// Id: $Id$ +// Copyright: (c) 2010 Marianne Gagnon +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#include "wx/msw/webview.h" + +#if wxHAVE_WEB_BACKEND_IE + +#include +#include +#include +#include +#include + +// FIXME: Seems like MINGW does not have these, how to handle cleanly? +#define DISPID_COMMANDSTATECHANGE 105 +typedef enum CommandStateChangeConstants { + CSC_UPDATECOMMANDS = (int) 0xFFFFFFFF, + CSC_NAVIGATEFORWARD = 0x1, + CSC_NAVIGATEBACK = 0x2 +} CommandStateChangeConstants; + + +// FIXME: Seems like MINGW does not have these, how to handle cleanly? +#define DISPID_NAVIGATECOMPLETE2 252 +#define DISPID_NAVIGATEERROR 271 +#define OLECMDID_OPTICAL_ZOOM 63 +#define INET_E_ERROR_FIRST 0x800C0002L +#define INET_E_INVALID_URL 0x800C0002L +#define INET_E_NO_SESSION 0x800C0003L +#define INET_E_CANNOT_CONNECT 0x800C0004L +#define INET_E_RESOURCE_NOT_FOUND 0x800C0005L +#define INET_E_OBJECT_NOT_FOUND 0x800C0006L +#define INET_E_DATA_NOT_AVAILABLE 0x800C0007L +#define INET_E_DOWNLOAD_FAILURE 0x800C0008L +#define INET_E_AUTHENTICATION_REQUIRED 0x800C0009L +#define INET_E_NO_VALID_MEDIA 0x800C000AL +#define INET_E_CONNECTION_TIMEOUT 0x800C000BL +#define INET_E_INVALID_REQUEST 0x800C000CL +#define INET_E_UNKNOWN_PROTOCOL 0x800C000DL +#define INET_E_SECURITY_PROBLEM 0x800C000EL +#define INET_E_CANNOT_LOAD_DATA 0x800C000FL +#define INET_E_CANNOT_INSTANTIATE_OBJECT 0x800C0010L +#define INET_E_QUERYOPTION_UNKNOWN 0x800C0013L +#define INET_E_REDIRECT_FAILED 0x800C0014L +#define INET_E_REDIRECT_TO_DIR 0x800C0015L +#define INET_E_CANNOT_LOCK_REQUEST 0x800C0016L +#define INET_E_USE_EXTEND_BINDING 0x800C0017L +#define INET_E_TERMINATED_BIND 0x800C0018L +#define INET_E_INVALID_CERTIFICATE 0x800C0019L +#define INET_E_CODE_DOWNLOAD_DECLINED 0x800C0100L +#define INET_E_RESULT_DISPATCHED 0x800C0200L +#define INET_E_CANNOT_REPLACE_SFP_FILE 0x800C0300L +#define INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY 0x800C0500L +#define INET_E_CODE_INSTALL_SUPPRESSED 0x800C0400L + +#define REFRESH_COMPLETELY 3 + +BEGIN_EVENT_TABLE(wxWebViewIE, wxControl) +EVT_ACTIVEX(wxID_ANY, wxWebViewIE::onActiveXEvent) +EVT_ERASE_BACKGROUND(wxWebViewIE::onEraseBg) +END_EVENT_TABLE() + +bool wxWebViewIE::Create(wxWindow* parent, + wxWindowID id, + const wxString& url, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name) +{ + if (!wxControl::Create(parent, id, pos, size, style, + wxDefaultValidator, name)) + { + return false; + } + + m_webBrowser = NULL; + m_canNavigateBack = false; + m_canNavigateForward = false; + m_isBusy = false; + + if (::CoCreateInstance(CLSID_WebBrowser, NULL, + CLSCTX_INPROC_SERVER, // CLSCTX_INPROC, + IID_IWebBrowser2 , (void**)&m_webBrowser) != 0) + { + wxLogError("Failed to initialize IE, CoCreateInstance returned an error"); + return false; + } + + m_ie.SetDispatchPtr(m_webBrowser); // wxAutomationObject will release itself + + m_webBrowser->put_RegisterAsBrowser(VARIANT_TRUE); + m_webBrowser->put_RegisterAsDropTarget(VARIANT_TRUE); + //m_webBrowser->put_Silent(VARIANT_FALSE); + + m_container = new wxActiveXContainer(this, IID_IWebBrowser2, m_webBrowser); + + SetBackgroundStyle(wxBG_STYLE_PAINT); + SetDoubleBuffered(true); + return true; +} + + +void wxWebViewIE::LoadUrl(const wxString& url) +{ + wxVariant out = m_ie.CallMethod("Navigate", (BSTR) url.wc_str(), + NULL, NULL, NULL, NULL); + + // FIXME: why is out value null?? + //(HRESULT)(out.GetLong()) == S_OK; +} + +void wxWebViewIE::SetPage(const wxString& html, const wxString& baseUrl) +{ + LoadUrl("about:blank"); + + // Let the wx events generated for navigation events be processed, so + // that the underlying IE component completes its Document object. + // FIXME: calling wxYield is not elegant nor very reliable probably + wxYield(); + + wxVariant documentVariant = m_ie.GetProperty("Document"); + void* documentPtr = documentVariant.GetVoidPtr(); + + wxASSERT (documentPtr != NULL); + + // TODO: consider the "baseUrl" parameter if possible + // TODO: consider encoding + BSTR bstr = SysAllocString(html.wc_str()); + + // Creates a new one-dimensional array + SAFEARRAY *psaStrings = SafeArrayCreateVector(VT_VARIANT, 0, 1); + if (psaStrings != NULL) + { + VARIANT *param; + HRESULT hr = SafeArrayAccessData(psaStrings, (LPVOID*)¶m); + param->vt = VT_BSTR; + param->bstrVal = bstr; + + hr = SafeArrayUnaccessData(psaStrings); + + IHTMLDocument2* document = (IHTMLDocument2*)documentPtr; + document->write(psaStrings); + + // SafeArrayDestroy calls SysFreeString for each BSTR + SafeArrayDestroy(psaStrings); + } + else + { + wxLogError("wxWebViewIE::SetPage() : psaStrings is NULL"); + } + +} + +wxString wxWebViewIE::GetPageSource() +{ + wxVariant documentVariant = m_ie.GetProperty("Document"); + void* documentPtr = documentVariant.GetVoidPtr(); + + if (documentPtr == NULL) + { + return wxEmptyString; + } + + IHTMLDocument2* document = (IHTMLDocument2*)documentPtr; + + IHTMLElement *bodyTag = NULL; + IHTMLElement *htmlTag = NULL; + document->get_body(&bodyTag); + wxASSERT(bodyTag != NULL); + + document->Release(); + bodyTag->get_parentElement(&htmlTag); + wxASSERT(htmlTag != NULL); + + BSTR bstr; + htmlTag->get_outerHTML(&bstr); + + bodyTag->Release(); + htmlTag->Release(); + + //wxMessageBox(wxString(bstr)); + + // TODO: check encoding + return wxString(bstr); +} + +// FIXME? retrieve OLECMDID_GETZOOMRANGE instead of hardcoding range 0-4 +wxWebViewZoom wxWebViewIE::GetZoom() +{ + const int zoom = GetIETextZoom(); + + switch (zoom) + { + case 0: + return wxWEB_VIEW_ZOOM_TINY; + break; + case 1: + return wxWEB_VIEW_ZOOM_SMALL; + break; + case 2: + return wxWEB_VIEW_ZOOM_MEDIUM; + break; + case 3: + return wxWEB_VIEW_ZOOM_LARGE; + break; + case 4: + return wxWEB_VIEW_ZOOM_LARGEST; + break; + default: + wxASSERT(false); + return wxWEB_VIEW_ZOOM_MEDIUM; + } +} +void wxWebViewIE::SetZoom(wxWebViewZoom zoom) +{ + // I know I could cast from enum to int since wxWebViewZoom happens to + // match with IE's zoom levels, but I don't like doing that, what if enum + // values change... + switch (zoom) + { + case wxWEB_VIEW_ZOOM_TINY: + SetIETextZoom(0); + break; + case wxWEB_VIEW_ZOOM_SMALL: + SetIETextZoom(1); + break; + case wxWEB_VIEW_ZOOM_MEDIUM: + SetIETextZoom(2); + break; + case wxWEB_VIEW_ZOOM_LARGE: + SetIETextZoom(3); + break; + case wxWEB_VIEW_ZOOM_LARGEST: + SetIETextZoom(4); + break; + default: + wxASSERT(false); + } +} + +void wxWebViewIE::SetIETextZoom(int level) +{ + VARIANT zoomVariant; + VariantInit (&zoomVariant); + V_VT(&zoomVariant) = VT_I4; + V_I4(&zoomVariant) = level; + + HRESULT result = m_webBrowser->ExecWB(OLECMDID_ZOOM, + OLECMDEXECOPT_DONTPROMPTUSER, + &zoomVariant, NULL); + wxASSERT (result == S_OK); + + VariantClear (&zoomVariant); +} + +int wxWebViewIE::GetIETextZoom() +{ + VARIANT zoomVariant; + VariantInit (&zoomVariant); + V_VT(&zoomVariant) = VT_I4; + V_I4(&zoomVariant) = 4; + + HRESULT result = m_webBrowser->ExecWB(OLECMDID_ZOOM, + OLECMDEXECOPT_DONTPROMPTUSER, + NULL, &zoomVariant); + wxASSERT (result == S_OK); + + int zoom = V_I4(&zoomVariant); + // wxMessageBox(wxString::Format("Zoom : %i", zoom)); + VariantClear (&zoomVariant); + + return zoom; +} + +void wxWebViewIE::SetIEOpticalZoom(float zoom) +{ + // TODO: add support for optical zoom (IE7+ only) + + // TODO: get range from OLECMDID_OPTICAL_GETZOOMRANGE instead of hardcoding? + wxASSERT(zoom >= 10.0f); + wxASSERT(zoom <= 1000.0f); + + VARIANT zoomVariant; + VariantInit (&zoomVariant); + V_VT(&zoomVariant) = VT_I4; + V_I4(&zoomVariant) = (zoom * 100.0f); + + HRESULT result = m_webBrowser->ExecWB((OLECMDID)OLECMDID_OPTICAL_ZOOM, + OLECMDEXECOPT_DODEFAULT, + &zoomVariant, + NULL); + wxASSERT (result == S_OK); +} + +float wxWebViewIE::GetIEOpticalZoom() +{ + // TODO: add support for optical zoom (IE7+ only) + + VARIANT zoomVariant; + VariantInit (&zoomVariant); + V_VT(&zoomVariant) = VT_I4; + V_I4(&zoomVariant) = -1; + + HRESULT result = m_webBrowser->ExecWB((OLECMDID)OLECMDID_OPTICAL_ZOOM, + OLECMDEXECOPT_DODEFAULT, NULL, + &zoomVariant); + wxASSERT (result == S_OK); + + const int zoom = V_I4(&zoomVariant); + VariantClear (&zoomVariant); + + return zoom / 100.0f; +} + +void wxWebViewIE::SetZoomType(wxWebViewZoomType) +{ + // TODO: add support for optical zoom (IE7+ only) + wxASSERT(false); +} + +wxWebViewZoomType wxWebViewIE::GetZoomType() const +{ + // TODO: add support for optical zoom (IE7+ only) + return wxWEB_VIEW_ZOOM_TYPE_TEXT; +} + +bool wxWebViewIE::CanSetZoomType(wxWebViewZoomType) const +{ + // both are supported + // TODO: IE6 only supports text zoom, check if it's IE6 first + return true; +} + +void wxWebViewIE::Print() +{ + m_webBrowser->ExecWB(OLECMDID_PRINTPREVIEW, + OLECMDEXECOPT_DODEFAULT, NULL, NULL); +} + +void wxWebViewIE::GoBack() +{ + wxVariant out = m_ie.CallMethod("GoBack"); + + // FIXME: why is out value null?? + //return (HRESULT)(out.GetLong()) == S_OK; +} + +void wxWebViewIE::GoForward() +{ + wxVariant out = m_ie.CallMethod("GoForward"); + + // FIXME: why is out value null?? + //return (HRESULT)(out.GetLong()) == S_OK; +} + +void wxWebViewIE::Stop() +{ + wxVariant out = m_ie.CallMethod("Stop"); + + // FIXME: why is out value null?? + //return (HRESULT)(out.GetLong()) == S_OK; +} + + +void wxWebViewIE::Reload(wxWebViewReloadFlags flags) +{ + wxVariant out; + + if (flags & wxWEB_VIEW_RELOAD_NO_CACHE) + { + VARIANTARG level; + level.vt = VT_I2; + level.iVal = 3; + out = m_ie.CallMethod("Refresh2", &level); + } + else + { + out = m_ie.CallMethod("Refresh"); + } + + if (out.GetType() != "null") + { + wxMessageBox("Non-null return message : " + out.GetType()); + } +} + +bool wxWebViewIE::IsOfflineMode() +{ + wxVariant out = m_ie.GetProperty("Offline"); + + wxASSERT(out.GetType() == "bool"); + + return out.GetBool(); +} + +void wxWebViewIE::SetOfflineMode(bool offline) +{ + // FIXME: the wxWidgets docs do not really document what the return + // parameter of PutProperty is + const bool success = m_ie.PutProperty("Offline", (offline ? + VARIANT_TRUE : + VARIANT_FALSE)); + wxASSERT(success); +} + +bool wxWebViewIE::IsBusy() +{ + if (m_isBusy) return true; + + wxVariant out = m_ie.GetProperty("Busy"); + + wxASSERT(out.GetType() == "bool"); + + return out.GetBool(); +} + +wxString wxWebViewIE::GetCurrentURL() +{ + wxVariant out = m_ie.GetProperty("LocationURL"); + + wxASSERT(out.GetType() == "string"); + return out.GetString(); +} + +wxString wxWebViewIE::GetCurrentTitle() +{ + wxVariant out = m_ie.GetProperty("LocationName"); + + wxASSERT(out.GetType() == "string"); + return out.GetString(); +} + +void wxWebViewIE::onActiveXEvent(wxActiveXEvent& evt) +{ + if (m_webBrowser == NULL) return; + + switch (evt.GetDispatchId()) + { + case DISPID_BEFORENAVIGATE2: + { + m_isBusy = true; + + wxString url = evt[1].GetString(); + wxString target = evt[3].GetString(); + + wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATING, + GetId(), url, target, true); + event.SetEventObject(this); + HandleWindowEvent(event); + + if (event.IsVetoed()) + { + wxActiveXEventNativeMSW* nativeParams = + evt.GetNativeParameters(); + *V_BOOLREF(&nativeParams->pDispParams->rgvarg[0]) = VARIANT_TRUE; + } + + // at this point, either the navigation event has been cancelled + // and we're not busy, either it was accepted and IWebBrowser2's + // Busy property will be true; so we don't need our override + // flag anymore. + m_isBusy = false; + + break; + } + + case DISPID_NAVIGATECOMPLETE2: + { + wxString url = evt[1].GetString(); + // TODO: set target parameter if possible + wxString target = wxEmptyString; + wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_NAVIGATED, + GetId(), url, target, false); + event.SetEventObject(this); + HandleWindowEvent(event); + break; + } + + case DISPID_PROGRESSCHANGE: + { + // download progress + break; + } + + case DISPID_DOCUMENTCOMPLETE: + { + wxString url = evt[1].GetString(); + // TODO: set target parameter if possible + wxString target = wxEmptyString; + wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_LOADED, GetId(), + url, target, false); + event.SetEventObject(this); + HandleWindowEvent(event); + break; + } + + case DISPID_STATUSTEXTCHANGE: + { + break; + } + + case DISPID_TITLECHANGE: + { + break; + } + + case DISPID_NAVIGATEERROR: + { + wxWebNavigationError errorType = wxWEB_NAV_ERR_OTHER; + wxString errorCode = "?"; + switch (evt[3].GetLong()) + { + case INET_E_INVALID_URL: // (0x800C0002L or -2146697214) + errorCode = "INET_E_INVALID_URL"; + errorType = wxWEB_NAV_ERR_REQUEST; + break; + case INET_E_NO_SESSION: // (0x800C0003L or -2146697213) + errorCode = "INET_E_NO_SESSION"; + errorType = wxWEB_NAV_ERR_CONNECTION; + break; + case INET_E_CANNOT_CONNECT: // (0x800C0004L or -2146697212) + errorCode = "INET_E_CANNOT_CONNECT"; + errorType = wxWEB_NAV_ERR_CONNECTION; + break; + case INET_E_RESOURCE_NOT_FOUND: // (0x800C0005L or -2146697211) + errorCode = "INET_E_RESOURCE_NOT_FOUND"; + errorType = wxWEB_NAV_ERR_NOT_FOUND; + break; + case INET_E_OBJECT_NOT_FOUND: // (0x800C0006L or -2146697210) + errorCode = "INET_E_OBJECT_NOT_FOUND"; + errorType = wxWEB_NAV_ERR_NOT_FOUND; + break; + case INET_E_DATA_NOT_AVAILABLE: // (0x800C0007L or -2146697209) + errorCode = "INET_E_DATA_NOT_AVAILABLE"; + errorType = wxWEB_NAV_ERR_NOT_FOUND; + break; + case INET_E_DOWNLOAD_FAILURE: // (0x800C0008L or -2146697208) + errorCode = "INET_E_DOWNLOAD_FAILURE"; + errorType = wxWEB_NAV_ERR_CONNECTION; + break; + case INET_E_AUTHENTICATION_REQUIRED: // (0x800C0009L or -2146697207) + errorCode = "INET_E_AUTHENTICATION_REQUIRED"; + errorType = wxWEB_NAV_ERR_AUTH; + break; + case INET_E_NO_VALID_MEDIA: // (0x800C000AL or -2146697206) + errorCode = "INET_E_NO_VALID_MEDIA"; + errorType = wxWEB_NAV_ERR_REQUEST; + break; + case INET_E_CONNECTION_TIMEOUT: // (0x800C000BL or -2146697205) + errorCode = "INET_E_CONNECTION_TIMEOUT"; + errorType = wxWEB_NAV_ERR_CONNECTION; + break; + case INET_E_INVALID_REQUEST: // (0x800C000CL or -2146697204) + errorCode = "INET_E_INVALID_REQUEST"; + errorType = wxWEB_NAV_ERR_REQUEST; + break; + case INET_E_UNKNOWN_PROTOCOL: // (0x800C000DL or -2146697203) + errorCode = "INET_E_UNKNOWN_PROTOCOL"; + errorType = wxWEB_NAV_ERR_REQUEST; + break; + case INET_E_SECURITY_PROBLEM: // (0x800C000EL or -2146697202) + errorCode = "INET_E_SECURITY_PROBLEM"; + errorType = wxWEB_NAV_ERR_SECURITY; + break; + case INET_E_CANNOT_LOAD_DATA: // (0x800C000FL or -2146697201) + errorCode = "INET_E_CANNOT_LOAD_DATA"; + errorType = wxWEB_NAV_ERR_OTHER; + break; + case INET_E_CANNOT_INSTANTIATE_OBJECT: + // CoCreateInstance will return an error code if this happens, + // we'll handle this above. + return; + break; + case INET_E_REDIRECT_FAILED: // (0x800C0014L or -2146697196) + errorCode = "INET_E_REDIRECT_FAILED"; + errorType = wxWEB_NAV_ERR_OTHER; + break; + case INET_E_REDIRECT_TO_DIR: // (0x800C0015L or -2146697195) + errorCode = "INET_E_REDIRECT_TO_DIR"; + errorType = wxWEB_NAV_ERR_REQUEST; + break; + case INET_E_CANNOT_LOCK_REQUEST: // (0x800C0016L or -2146697194) + errorCode = "INET_E_CANNOT_LOCK_REQUEST"; + errorType = wxWEB_NAV_ERR_OTHER; + break; + case INET_E_USE_EXTEND_BINDING: // (0x800C0017L or -2146697193) + errorCode = "INET_E_USE_EXTEND_BINDING"; + errorType = wxWEB_NAV_ERR_OTHER; + break; + case INET_E_TERMINATED_BIND: // (0x800C0018L or -2146697192) + errorCode = "INET_E_TERMINATED_BIND"; + errorType = wxWEB_NAV_ERR_OTHER; + break; + case INET_E_INVALID_CERTIFICATE: // (0x800C0019L or -2146697191) + errorCode = "INET_E_INVALID_CERTIFICATE"; + errorType = wxWEB_NAV_ERR_CERTIFICATE; + break; + case INET_E_CODE_DOWNLOAD_DECLINED: // (0x800C0100L or -2146696960) + errorCode = "INET_E_CODE_DOWNLOAD_DECLINED"; + errorType = wxWEB_NAV_ERR_USER_CANCELLED; + break; + case INET_E_RESULT_DISPATCHED: // (0x800C0200L or -2146696704) + // cancel request cancelled... + errorCode = "INET_E_RESULT_DISPATCHED"; + errorType = wxWEB_NAV_ERR_OTHER; + break; + case INET_E_CANNOT_REPLACE_SFP_FILE: // (0x800C0300L or -2146696448) + errorCode = "INET_E_CANNOT_REPLACE_SFP_FILE"; + errorType = wxWEB_NAV_ERR_SECURITY; + break; + case INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY: + errorCode = "INET_E_CODE_INSTALL_BLOCKED_BY_HASH_POLICY"; + errorType = wxWEB_NAV_ERR_SECURITY; + break; + case INET_E_CODE_INSTALL_SUPPRESSED: + errorCode = "INET_E_CODE_INSTALL_SUPPRESSED"; + errorType = wxWEB_NAV_ERR_SECURITY; + break; + } + + wxString url = evt[1].GetString(); + wxString target = evt[2].GetString(); + wxWebNavigationEvent event(wxEVT_COMMAND_WEB_VIEW_ERROR, GetId(), + url, target, false); + event.SetEventObject(this); + event.SetInt(errorType); + event.SetString(errorCode); + HandleWindowEvent(event); + break; + } + + case DISPID_COMMANDSTATECHANGE: + { + long commandId = evt[0].GetLong(); + bool enable = evt[1].GetBool(); + if (commandId == CSC_NAVIGATEBACK) + { + m_canNavigateBack = enable; + } + else if (commandId == CSC_NAVIGATEFORWARD) + { + m_canNavigateForward = enable; + } + } + + /* + case DISPID_NEWWINDOW2: + //case DISPID_NEWWINDOW3: + { + wxLogMessage("DISPID_NEWWINDOW2\n"); + wxActiveXEventNativeMSW* nativeParams = evt.GetNativeParameters(); + // Cancel the attempt to open a new window + *V_BOOLREF(&nativeParams->pDispParams->rgvarg[0]) = VARIANT_TRUE; + }*/ + } + + evt.Skip(); +} + +#endif diff --git a/src/osx/webview.mm b/src/osx/webview.mm index 83b13363b8..15b855297d 100644 --- a/src/osx/webview.mm +++ b/src/osx/webview.mm @@ -1,1208 +1,1208 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: src/osx/webkit.mm -// Purpose: wxOSXWebKitCtrl - embeddable web kit control, -// OS X implementation of web view component -// Author: Jethro Grassie / Kevin Ollivier / Marianne Gagnon -// Modified by: -// Created: 2004-4-16 -// RCS-ID: $Id: webkit.mm 64943 2010-07-13 13:29:58Z VZ $ -// Copyright: (c) Jethro Grassie / Kevin Ollivier / Marianne Gagnon -// Licence: wxWindows licence -///////////////////////////////////////////////////////////////////////////// - -// http://developer.apple.com/mac/library/documentation/Cocoa/Reference/WebKit/Classes/WebView_Class/Reference/Reference.html - -#include "wx/osx/webview.h" - -// For compilers that support precompilation, includes "wx.h". -#include "wx/wxprec.h" - -#ifndef WX_PRECOMP - #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 -#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) - -BEGIN_EVENT_TABLE(wxOSXWebKitCtrl, wxControl) -#if defined(__WXMAC__) && wxOSX_USE_CARBON - EVT_SIZE(wxOSXWebKitCtrl::OnSize) -#endif -END_EVENT_TABLE() - -#if defined(__WXOSX__) && wxOSX_USE_CARBON - -// ---------------------------------------------------------------------------- -// Carbon Events handlers -// ---------------------------------------------------------------------------- - -// prototype for function in src/osx/carbon/nonownedwnd.cpp -void SetupMouseEvent( wxMouseEvent &wxevent , wxMacCarbonEvent &cEvent ); - -static const EventTypeSpec eventList[] = -{ - //{ kEventClassControl, kEventControlTrack } , - { kEventClassMouse, kEventMouseUp }, - { kEventClassMouse, kEventMouseDown }, - { kEventClassMouse, kEventMouseMoved }, - { kEventClassMouse, kEventMouseDragged }, - - { kEventClassKeyboard, kEventRawKeyDown } , - { kEventClassKeyboard, kEventRawKeyRepeat } , - { kEventClassKeyboard, kEventRawKeyUp } , - { kEventClassKeyboard, kEventRawKeyModifiersChanged } , - - { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } , - { kEventClassTextInput, kEventTextInputUpdateActiveInputArea } , - -#if DEBUG_WEBKIT_SIZING == 1 - { kEventClassControl, kEventControlBoundsChanged } , -#endif -}; - -// mix this in from window.cpp -pascal OSStatus wxMacUnicodeTextEventHandler(EventHandlerCallRef handler, - EventRef event, void *data) ; - -// NOTE: This is mostly taken from KeyboardEventHandler in toplevel.cpp, but -// that expects the data pointer is a top-level window, so I needed to change -// that in this case. However, once 2.8 is out, we should factor out the common -// logic among the two functions and merge them. -static pascal OSStatus wxWebKitKeyEventHandler(EventHandlerCallRef handler, - EventRef event, void *data) -{ - OSStatus result = eventNotHandledErr ; - wxMacCarbonEvent cEvent( event ) ; - - wxOSXWebKitCtrl* thisWindow = (wxOSXWebKitCtrl*) data ; - wxWindow* focus = thisWindow ; - - unsigned char charCode ; - wxChar uniChar[2] ; - uniChar[0] = 0; - uniChar[1] = 0; - - UInt32 keyCode ; - UInt32 modifiers ; - Point point ; - UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ; - -#if wxUSE_UNICODE - ByteCount dataSize = 0 ; - if ( GetEventParameter(event, kEventParamKeyUnicodes, typeUnicodeText, - NULL, 0 , &dataSize, NULL ) == noErr) - { - UniChar buf[2] ; - int numChars = dataSize / sizeof( UniChar) + 1; - - UniChar* charBuf = buf ; - - if ( numChars * 2 > 4 ) - charBuf = new UniChar[ numChars ] ; - GetEventParameter(event, kEventParamKeyUnicodes, typeUnicodeText, NULL, - dataSize , NULL , charBuf) ; - charBuf[ numChars - 1 ] = 0; - -#if SIZEOF_WCHAR_T == 2 - uniChar = charBuf[0] ; -#else - wxMBConvUTF16 converter ; - converter.MB2WC( uniChar , (const char*)charBuf , 2 ) ; -#endif - - if ( numChars * 2 > 4 ) - delete[] charBuf ; - } -#endif - - GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL, - sizeof(char), 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 ) ) - { - case kEventRawKeyRepeat : - case kEventRawKeyDown : - { - WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ; - WXEVENTHANDLERCALLREF formerHandler = - wxTheApp->MacGetCurrentEventHandlerCallRef() ; - - wxTheApp->MacSetCurrentEvent( event , handler ) ; - if ( /* focus && */ wxTheApp->MacSendKeyDownEvent( - focus, message, modifiers, when, point.h, point.v, uniChar[0])) - { - result = noErr ; - } - wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ; - } - break ; - - case kEventRawKeyUp : - if ( /* focus && */ wxTheApp->MacSendKeyUpEvent( - focus , message , modifiers , when , point.h , point.v , uniChar[0] ) ) - { - result = noErr ; - } - break ; - - case kEventRawKeyModifiersChanged : - { - wxKeyEvent event(wxEVT_KEY_DOWN); - - event.m_shiftDown = modifiers & shiftKey; - 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] ; -#endif - - event.SetTimestamp(when); - event.SetEventObject(focus); - - if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & controlKey ) - { - event.m_keyCode = WXK_CONTROL ; - event.SetEventType( ( modifiers & controlKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ; - focus->GetEventHandler()->ProcessEvent( event ) ; - } - if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & shiftKey ) - { - event.m_keyCode = WXK_SHIFT ; - event.SetEventType( ( modifiers & shiftKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ; - focus->GetEventHandler()->ProcessEvent( event ) ; - } - if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & optionKey ) - { - event.m_keyCode = WXK_ALT ; - event.SetEventType( ( modifiers & optionKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ; - focus->GetEventHandler()->ProcessEvent( event ) ; - } - if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & cmdKey ) - { - event.m_keyCode = WXK_COMMAND ; - event.SetEventType( ( modifiers & cmdKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ; - focus->GetEventHandler()->ProcessEvent( event ) ; - } - - wxApp::s_lastModifiers = modifiers ; - } - break ; - - default: - break; - } - - return result ; -} - -static pascal OSStatus wxOSXWebKitCtrlEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) -{ - OSStatus result = eventNotHandledErr ; - - wxMacCarbonEvent cEvent( event ) ; - - ControlRef controlRef ; - wxOSXWebKitCtrl* thisWindow = (wxOSXWebKitCtrl*) data ; - wxNonOwnedWindow* tlw = NULL; - if (thisWindow) - tlw = thisWindow->MacGetTopLevelWindow(); - - cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ; - - wxWindow* currentMouseWindow = thisWindow ; - - if ( wxApp::s_captureWindow ) - currentMouseWindow = wxApp::s_captureWindow; - - switch ( GetEventClass( event ) ) - { - case kEventClassKeyboard: - { - result = wxWebKitKeyEventHandler(handler, event, data); - break; - } - - case kEventClassTextInput: - { - result = wxMacUnicodeTextEventHandler(handler, event, data); - break; - } - - case kEventClassMouse: - { - switch ( GetEventKind( event ) ) - { - case kEventMouseDragged : - case kEventMouseMoved : - case kEventMouseDown : - case kEventMouseUp : - { - wxMouseEvent wxevent(wxEVT_LEFT_DOWN); - SetupMouseEvent( wxevent , cEvent ) ; - - currentMouseWindow->ScreenToClient( &wxevent.m_x , &wxevent.m_y ) ; - wxevent.SetEventObject( currentMouseWindow ) ; - wxevent.SetId( currentMouseWindow->GetId() ) ; - - if ( currentMouseWindow->GetEventHandler()->ProcessEvent(wxevent) ) - { - result = noErr; - } - - break; // this should enable WebKit to fire mouse dragged and mouse up events... - } - default : - break ; - } - } - default: - break; - } - - result = CallNextEventHandler(handler, event); - return result ; -} - -DEFINE_ONE_SHOT_HANDLER_GETTER( wxOSXWebKitCtrlEventHandler ) - -#endif - -//--------------------------------------------------------- -// helper functions for NSString<->wxString conversion -//--------------------------------------------------------- - -inline wxString wxStringWithNSString(NSString *nsstring) -{ -#if wxUSE_UNICODE - return wxString([nsstring UTF8String], wxConvUTF8); -#else - return wxString([nsstring lossyCString]); -#endif // wxUSE_UNICODE -} - -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 -} - -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; - - if (type == WebNavigationTypeReload) - return wxWEBKIT_NAV_RELOAD; - - if (type == WebNavigationTypeFormResubmitted) - return wxWEBKIT_NAV_FORM_RESUBMITTED; - - return wxWEBKIT_NAV_OTHER; -} - -@interface MyFrameLoadMonitor : NSObject -{ - wxOSXWebKitCtrl* webKitWindow; -} - -- initWithWxWindow: (wxOSXWebKitCtrl*)inWindow; - -@end - -@interface MyPolicyDelegate : NSObject -{ - wxOSXWebKitCtrl* webKitWindow; -} - -- initWithWxWindow: (wxOSXWebKitCtrl*)inWindow; - -@end - -// ---------------------------------------------------------------------------- -// creation/destruction -// ---------------------------------------------------------------------------- - -bool wxOSXWebKitCtrl::Create(wxWindow *parent, - wxWindowID winID, - const wxString& strURL, - const wxPoint& pos, - const wxSize& size, long style, - 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; - wxControl::Create(parent, winID, pos, size, style, wxDefaultValidator, name); - -#if wxOSX_USE_CARBON - m_peer = new wxMacControl(this); - WebInitForCarbon(); - HIWebViewCreate( m_peer->GetControlRefAddr() ); - - m_webView = (WebView*) HIWebViewGetWebView( m_peer->GetControlRef() ); - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 - if ( UMAGetSystemVersion() >= 0x1030 ) - HIViewChangeFeatures( m_peer->GetControlRef() , kHIViewIsOpaque , 0 ) ; -#endif - InstallControlEventHandler(m_peer->GetControlRef(), - GetwxOSXWebKitCtrlEventHandlerUPP(), - GetEventTypeCount(eventList), eventList, this, - (EventHandlerRef *)&m_webKitCtrlEventHandler); -#else - NSRect r = wxOSXGetFrameForControl( this, pos , size ) ; - m_webView = [[WebView alloc] initWithFrame:r - frameName:@"webkitFrame" - groupName:@"webkitGroup"]; - m_peer = new wxWidgetCocoaImpl( this, m_webView ); -#endif - - wx_webviewctrls[m_webView] = this; - - MacPostControlCreate(pos, size); - -#if wxOSX_USE_CARBON - HIViewSetVisible( m_peer->GetControlRef(), true ); -#endif - [m_webView setHidden:false]; - -#endif - - // Register event listener interfaces - MyFrameLoadMonitor* myFrameLoadMonitor = - [[MyFrameLoadMonitor alloc] initWithWxWindow: this]; - - [m_webView setFrameLoadDelegate:myFrameLoadMonitor]; - - // this is used to veto page loads, etc. - MyPolicyDelegate* myPolicyDelegate = - [[MyPolicyDelegate alloc] initWithWxWindow: this]; - - [m_webView setPolicyDelegate:myPolicyDelegate]; - - InternalLoadURL(strURL); - return true; -} - -wxOSXWebKitCtrl::~wxOSXWebKitCtrl() -{ - MyFrameLoadMonitor* myFrameLoadMonitor = [m_webView frameLoadDelegate]; - MyPolicyDelegate* myPolicyDelegate = [m_webView policyDelegate]; - [m_webView setFrameLoadDelegate: nil]; - [m_webView setPolicyDelegate: nil]; - - if (myFrameLoadMonitor) - [myFrameLoadMonitor release]; - - if (myPolicyDelegate) - [myPolicyDelegate 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() -{ - if ( !m_webView ) - return false; - - return [m_webView canGoBack]; -} - -bool wxOSXWebKitCtrl::CanGoForward() -{ - if ( !m_webView ) - return false; - - return [m_webView canGoForward]; -} - -void wxOSXWebKitCtrl::GoBack() -{ - if ( !m_webView ) - return; - - bool result = [(WebView*)m_webView goBack]; - - // TODO: return result (if it also exists in other backends...) - //return result; -} - -void wxOSXWebKitCtrl::GoForward() -{ - if ( !m_webView ) - return; - - bool result = [(WebView*)m_webView goForward]; - - // TODO: return result (if it also exists in other backends...) - //return result; -} - -void wxOSXWebKitCtrl::Reload(wxWebViewReloadFlags flags) -{ - if ( !m_webView ) - return; - - if (flags & wxWEB_VIEW_RELOAD_NO_CACHE) - { - // TODO: test this indeed bypasses the cache - [[m_webView preferences] setUsesPageCache:NO]; - [[m_webView mainFrame] reload]; - [[m_webView preferences] setUsesPageCache:YES]; - } - else - { - [[m_webView mainFrame] reload]; - } -} - -void wxOSXWebKitCtrl::Stop() -{ - if ( !m_webView ) - return; - - [[m_webView mainFrame] stopLoading]; -} - -bool wxOSXWebKitCtrl::CanGetPageSource() -{ - if ( !m_webView ) - return false; - - WebDataSource* dataSource = [[m_webView mainFrame] dataSource]; - return ( [[dataSource representation] canProvideDocumentSource] ); -} - -wxString wxOSXWebKitCtrl::GetPageSource() -{ - - if (CanGetPageSource()) - { - WebDataSource* dataSource = [[m_webView mainFrame] dataSource]; - wxASSERT (dataSource != nil); - - id representation = [dataSource representation]; - wxASSERT (representation != nil); - - NSString* source = [representation documentSource]; - if (source == nil) - { - return wxEmptyString; - } - - return wxStringWithNSString( source ); - } - - return wxEmptyString; -} - -wxString wxOSXWebKitCtrl::GetSelection() -{ - if ( !m_webView ) - return wxEmptyString; - - NSString* selectedText = [[m_webView selectedDOMRange] toString]; - return wxStringWithNSString( selectedText ); -} - -bool wxOSXWebKitCtrl::CanIncreaseTextSize() -{ - if ( !m_webView ) - return false; - - if ([m_webView canMakeTextLarger]) - return true; - else - return false; -} - -void wxOSXWebKitCtrl::IncreaseTextSize() -{ - if ( !m_webView ) - return; - - if (CanIncreaseTextSize()) - [m_webView makeTextLarger:(WebView*)m_webView]; -} - -bool wxOSXWebKitCtrl::CanDecreaseTextSize() -{ - if ( !m_webView ) - return false; - - if ([m_webView canMakeTextSmaller]) - return true; - else - return false; -} - -void wxOSXWebKitCtrl::DecreaseTextSize() -{ - if ( !m_webView ) - return; - - if (CanDecreaseTextSize()) - [m_webView makeTextSmaller:(WebView*)m_webView]; -} - -void wxOSXWebKitCtrl::Print() -{ - - // TODO: allow specifying the "show prompt" parameter in Print() ? - bool showPrompt = true; - - if ( !m_webView ) - return; - - id view = [[[m_webView mainFrame] frameView] documentView]; - NSPrintOperation *op = [NSPrintOperation printOperationWithView:view - printInfo: [NSPrintInfo sharedPrintInfo]]; - if (showPrompt) - { - [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 - // workaround for the bug. - [op setShowsProgressPanel: false]; - } - // Print it. - [op runOperation]; -} - -void wxOSXWebKitCtrl::MakeEditable(bool enable) -{ - if ( !m_webView ) - return; - - [m_webView setEditable:enable ]; -} - -bool wxOSXWebKitCtrl::IsEditable() -{ - if ( !m_webView ) - return false; - - return [m_webView isEditable]; -} - -void wxOSXWebKitCtrl::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); -} - -wxWebViewZoomType wxOSXWebKitCtrl::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; -} - -bool wxOSXWebKitCtrl::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: - return true; - - default: - return false; - } -} - -int wxOSXWebKitCtrl::GetScrollPos() -{ - id result = [[m_webView windowScriptObject] - evaluateWebScript:@"document.body.scrollTop"]; - return [result intValue]; -} - -void wxOSXWebKitCtrl::SetScrollPos(int pos) -{ - if ( !m_webView ) - return; - - wxString javascript; - javascript.Printf(wxT("document.body.scrollTop = %d;"), pos); - [[m_webView windowScriptObject] evaluateWebScript: - (NSString*)wxNSStringWithWxString( javascript )]; -} - -wxString wxOSXWebKitCtrl::GetSelectedText() -{ - NSString* selection = [[m_webView selectedDOMRange] markupString]; - if (!selection) return wxEmptyString; - - return wxStringWithNSString(selection); -} - -wxString wxOSXWebKitCtrl::RunScript(const wxString& javascript) -{ - if ( !m_webView ) - return wxEmptyString; - - id result = [[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) -{ -#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 - // basically guesses based on reverse engineering, so it's best to give - // people the option of overriding OnSize with their own calcs if need be. - // I also left some test debugging print statements as a convenience if - // a(nother) problem crops up. - - wxWindow* tlw = MacGetTopLevelWindow(); - - NSRect frame = [(WebView*)m_webView frame]; - NSRect bounds = [(WebView*)m_webView bounds]; - -#if DEBUG_WEBKIT_SIZING - fprintf(stderr,"Carbon window x=%d, y=%d, width=%d, height=%d\n", - GetPosition().x, GetPosition().y, GetSize().x, GetSize().y); - fprintf(stderr, "Cocoa window frame x=%G, y=%G, width=%G, height=%G\n", - frame.origin.x, frame.origin.y, - frame.size.width, frame.size.height); - fprintf(stderr, "Cocoa window bounds x=%G, y=%G, width=%G, height=%G\n", - bounds.origin.x, bounds.origin.y, - bounds.size.width, bounds.size.height); -#endif - - // This must be the case that Apple tested with, because well, in this one case - // we don't need to do anything! It just works. ;) - if (GetParent() == tlw) return; - - // since we no longer use parent coordinates, we always want 0,0. - int x = 0; - int y = 0; - - HIRect rect; - rect.origin.x = x; - rect.origin.y = y; - -#if DEBUG_WEBKIT_SIZING - printf("Before conversion, origin is: x = %d, y = %d\n", x, y); -#endif - - // NB: In most cases, when calling HIViewConvertRect, what people want is to - // use GetRootControl(), and this tripped me up at first. But in fact, what - // 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(), - HIViewGetRoot( - (WindowRef) MacGetTopLevelWindowRef() - )); - - x = (int)rect.origin.x; - y = (int)rect.origin.y; - -#if DEBUG_WEBKIT_SIZING - printf("Moving Cocoa frame origin to: x = %d, y = %d\n", x, y); -#endif - - if (tlw){ - //flip the y coordinate to convert to Cocoa coordinates - y = tlw->GetSize().y - ((GetSize().y) + y); - } - -#if DEBUG_WEBKIT_SIZING - printf("y = %d after flipping value\n", y); -#endif - - frame.origin.x = x; - frame.origin.y = y; - [(WebView*)m_webView setFrame:frame]; - - if (IsShown()) - [(WebView*)m_webView display]; - event.Skip(); -#endif -} - -void wxOSXWebKitCtrl::MacVisibilityChanged(){ -#if defined(__WXMAC__) && wxOSX_USE_CARBON - bool isHidden = !IsControlVisible( m_peer->GetControlRef()); - if (!isHidden) - [(WebView*)m_webView display]; - - [m_webView setHidden:isHidden]; -#endif -} - -void wxOSXWebKitCtrl::LoadUrl(const wxString& url) -{ - InternalLoadURL(url); -} - -wxString wxOSXWebKitCtrl::GetCurrentURL() -{ - return wxStringWithNSString([m_webView mainFrameURL]); -} - -wxString wxOSXWebKitCtrl::GetCurrentTitle() -{ - return GetPageTitle(); -} - -float wxOSXWebKitCtrl::GetWebkitZoom() -{ - return [m_webView textSizeMultiplier]; -} - -void wxOSXWebKitCtrl::SetWebkitZoom(float zoom) -{ - [m_webView setTextSizeMultiplier:zoom]; -} - -wxWebViewZoom wxOSXWebKitCtrl::GetZoom() -{ - float zoom = GetWebkitZoom(); - - // arbitrary way to map float zoom to our common zoom enum - if (zoom <= 0.55) - { - return wxWEB_VIEW_ZOOM_TINY; - } - else if (zoom > 0.55 && zoom <= 0.85) - { - return wxWEB_VIEW_ZOOM_SMALL; - } - else if (zoom > 0.85 && zoom <= 1.15) - { - return wxWEB_VIEW_ZOOM_MEDIUM; - } - else if (zoom > 1.15 && zoom <= 1.45) - { - return wxWEB_VIEW_ZOOM_LARGE; - } - else if (zoom > 1.45) - { - return wxWEB_VIEW_ZOOM_LARGEST; - } - - // to shut up compilers, this can never be reached logically - wxASSERT(false); - return wxWEB_VIEW_ZOOM_MEDIUM; -} - -void wxOSXWebKitCtrl::SetZoom(wxWebViewZoom zoom) -{ - // arbitrary way to map our common zoom enum to float zoom - switch (zoom) - { - case wxWEB_VIEW_ZOOM_TINY: - SetWebkitZoom(0.4f); - break; - - case wxWEB_VIEW_ZOOM_SMALL: - SetWebkitZoom(0.7f); - break; - - case wxWEB_VIEW_ZOOM_MEDIUM: - SetWebkitZoom(1.0f); - break; - - case wxWEB_VIEW_ZOOM_LARGE: - SetWebkitZoom(1.3); - break; - - case wxWEB_VIEW_ZOOM_LARGEST: - SetWebkitZoom(1.6); - break; - - default: - wxASSERT(false); - } - -} - -void wxOSXWebKitCtrl::SetPage(const wxString& src, const wxString& baseUrl) -{ - if ( !m_webView ) - return; - - [[m_webView mainFrame] loadHTMLString:(NSString*)wxNSStringWithWxString(src) - baseURL:[NSURL URLWithString: - wxNSStringWithWxString( baseUrl )]]; -} - -//------------------------------------------------------------ -// Listener interfaces -//------------------------------------------------------------ - -// NB: I'm still tracking this down, but it appears the Cocoa window -// still has these events fired on it while the Carbon control is being -// destroyed. Therefore, we must be careful to check both the existence -// of the Carbon control and the event handler before firing events. - -@implementation MyFrameLoadMonitor - -- initWithWxWindow: (wxOSXWebKitCtrl*)inWindow -{ - [super init]; - webKitWindow = inWindow; // non retained - return self; -} - -- (void)webView:(WebView *)sender - didStartProvisionalLoadForFrame:(WebFrame *)frame -{ - wxASSERT(wx_webviewctrls.find(sender) != wx_webviewctrls.end()); - wx_webviewctrls[sender]->m_busy = true; -} - -- (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame -{ - wxASSERT(wx_webviewctrls.find(sender) != wx_webviewctrls.end()); - wx_webviewctrls[sender]->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); - - if (webKitWindow && webKitWindow->GetEventHandler()) - webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); - } -} - -- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame -{ - wxASSERT(wx_webviewctrls.find(sender) != wx_webviewctrls.end()); - wx_webviewctrls[sender]->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); - - if (webKitWindow && webKitWindow->GetEventHandler()) - webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); - } -} - -wxString nsErrorToWxHtmlError(NSError* error, wxWebNavigationError* out) -{ - *out = wxWEB_NAV_ERR_OTHER; - - if ([[error domain] isEqualToString:NSURLErrorDomain]) - { - switch ([error code]) - { - case NSURLErrorCannotFindHost: - case NSURLErrorFileDoesNotExist: - case NSURLErrorRedirectToNonExistentLocation: - *out = wxWEB_NAV_ERR_NOT_FOUND; - break; - - case NSURLErrorResourceUnavailable: - case NSURLErrorHTTPTooManyRedirects: - case NSURLErrorDataLengthExceedsMaximum: - case NSURLErrorBadURL: - case NSURLErrorFileIsDirectory: - *out = wxWEB_NAV_ERR_REQUEST; - break; - - case NSURLErrorTimedOut: - case NSURLErrorDNSLookupFailed: - case NSURLErrorNetworkConnectionLost: - case NSURLErrorCannotConnectToHost: - case NSURLErrorNotConnectedToInternet: - //case NSURLErrorInternationalRoamingOff: - //case NSURLErrorCallIsActive: - //case NSURLErrorDataNotAllowed: - *out = wxWEB_NAV_ERR_CONNECTION; - break; - - case NSURLErrorCancelled: - case NSURLErrorUserCancelledAuthentication: - *out = wxWEB_NAV_ERR_USER_CANCELLED; - break; - - case NSURLErrorCannotDecodeRawData: - case NSURLErrorCannotDecodeContentData: - case NSURLErrorBadServerResponse: - case NSURLErrorCannotParseResponse: - *out = wxWEB_NAV_ERR_REQUEST; - break; - - case NSURLErrorUserAuthenticationRequired: - case NSURLErrorSecureConnectionFailed: - case NSURLErrorClientCertificateRequired: - *out = wxWEB_NAV_ERR_AUTH; - break; - - case NSURLErrorNoPermissionsToReadFile: - *out = wxWEB_NAV_ERR_SECURITY; - break; - - case NSURLErrorServerCertificateHasBadDate: - case NSURLErrorServerCertificateUntrusted: - case NSURLErrorServerCertificateHasUnknownRoot: - case NSURLErrorServerCertificateNotYetValid: - case NSURLErrorClientCertificateRejected: - *out = wxWEB_NAV_ERR_CERTIFICATE; - break; - } - } - - wxString message = wxStringWithNSString([error localizedDescription]); - NSString* detail = [error localizedFailureReason]; - if (detail != NULL) - { - message = message + " (" + wxStringWithNSString(detail) + ")"; - } - return message; -} - -- (void)webView:(WebView *)sender didFailLoadWithError:(NSError*) error - forFrame:(WebFrame *)frame -{ - wxASSERT(wx_webviewctrls.find(sender) != wx_webviewctrls.end()); - wx_webviewctrls[sender]->m_busy = false; - - if (webKitWindow && frame == [sender mainFrame]){ - NSString *url = [[[[frame dataSource] request] URL] absoluteString]; - - wxWebNavigationError 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); - - if (webKitWindow && webKitWindow->GetEventHandler()) - { - webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); - } - } -} - -- (void)webView:(WebView *)sender - didFailProvisionalLoadWithError:(NSError*)error - forFrame:(WebFrame *)frame -{ - wxASSERT(wx_webviewctrls.find(sender) != wx_webviewctrls.end()); - wx_webviewctrls[sender]->m_busy = false; - - if (webKitWindow && frame == [sender mainFrame]){ - NSString *url = [[[[frame provisionalDataSource] request] URL] - absoluteString]; - - wxWebNavigationError 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); - - if (webKitWindow && webKitWindow->GetEventHandler()) - webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); - } -} - -- (void)webView:(WebView *)sender didReceiveTitle:(NSString *)title - forFrame:(WebFrame *)frame -{ - if (webKitWindow && frame == [sender mainFrame]) - { - webKitWindow->SetPageTitle(wxStringWithNSString( title )); - } -} -@end - -@implementation MyPolicyDelegate - -- initWithWxWindow: (wxOSXWebKitCtrl*)inWindow -{ - [super init]; - webKitWindow = inWindow; // non retained - return self; -} - -- (void)webView:(WebView *)sender - decidePolicyForNavigationAction:(NSDictionary *)actionInformation - request:(NSURLRequest *)request - frame:(WebFrame *)frame - decisionListener:(id)listener -{ - //wxUnusedVar(sender); - wxUnusedVar(frame); - - wxASSERT(wx_webviewctrls.find(sender) != wx_webviewctrls.end()); - wx_webviewctrls[sender]->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); - - if (webKitWindow && webKitWindow->GetEventHandler()) - webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); - - if (thisEvent.IsVetoed()) - { - wx_webviewctrls[sender]->m_busy = false; - [listener ignore]; - } - else - { - [listener use]; - } -} - -- (void)webView:(WebView *)sender - decidePolicyForNewWindowAction:(NSDictionary *)actionInformation - request:(NSURLRequest *)request - newFrameName:(NSString *)frameName - decisionListener:(id < WebPolicyDecisionListener >)listener -{ - wxUnusedVar(sender); - wxUnusedVar(actionInformation); - - [listener ignore]; -} -@end - -#endif //wxHAVE_WEB_BACKEND_OSX_WEBKIT +///////////////////////////////////////////////////////////////////////////// +// Name: src/osx/webkit.mm +// Purpose: wxOSXWebKitCtrl - embeddable web kit control, +// OS X implementation of web view component +// Author: Jethro Grassie / Kevin Ollivier / Marianne Gagnon +// Modified by: +// Created: 2004-4-16 +// RCS-ID: $Id$ +// Copyright: (c) Jethro Grassie / Kevin Ollivier / Marianne Gagnon +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +// http://developer.apple.com/mac/library/documentation/Cocoa/Reference/WebKit/Classes/WebView_Class/Reference/Reference.html + +#include "wx/osx/webview.h" + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifndef WX_PRECOMP + #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 +#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) + +BEGIN_EVENT_TABLE(wxOSXWebKitCtrl, wxControl) +#if defined(__WXMAC__) && wxOSX_USE_CARBON + EVT_SIZE(wxOSXWebKitCtrl::OnSize) +#endif +END_EVENT_TABLE() + +#if defined(__WXOSX__) && wxOSX_USE_CARBON + +// ---------------------------------------------------------------------------- +// Carbon Events handlers +// ---------------------------------------------------------------------------- + +// prototype for function in src/osx/carbon/nonownedwnd.cpp +void SetupMouseEvent( wxMouseEvent &wxevent , wxMacCarbonEvent &cEvent ); + +static const EventTypeSpec eventList[] = +{ + //{ kEventClassControl, kEventControlTrack } , + { kEventClassMouse, kEventMouseUp }, + { kEventClassMouse, kEventMouseDown }, + { kEventClassMouse, kEventMouseMoved }, + { kEventClassMouse, kEventMouseDragged }, + + { kEventClassKeyboard, kEventRawKeyDown } , + { kEventClassKeyboard, kEventRawKeyRepeat } , + { kEventClassKeyboard, kEventRawKeyUp } , + { kEventClassKeyboard, kEventRawKeyModifiersChanged } , + + { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } , + { kEventClassTextInput, kEventTextInputUpdateActiveInputArea } , + +#if DEBUG_WEBKIT_SIZING == 1 + { kEventClassControl, kEventControlBoundsChanged } , +#endif +}; + +// mix this in from window.cpp +pascal OSStatus wxMacUnicodeTextEventHandler(EventHandlerCallRef handler, + EventRef event, void *data) ; + +// NOTE: This is mostly taken from KeyboardEventHandler in toplevel.cpp, but +// that expects the data pointer is a top-level window, so I needed to change +// that in this case. However, once 2.8 is out, we should factor out the common +// logic among the two functions and merge them. +static pascal OSStatus wxWebKitKeyEventHandler(EventHandlerCallRef handler, + EventRef event, void *data) +{ + OSStatus result = eventNotHandledErr ; + wxMacCarbonEvent cEvent( event ) ; + + wxOSXWebKitCtrl* thisWindow = (wxOSXWebKitCtrl*) data ; + wxWindow* focus = thisWindow ; + + unsigned char charCode ; + wxChar uniChar[2] ; + uniChar[0] = 0; + uniChar[1] = 0; + + UInt32 keyCode ; + UInt32 modifiers ; + Point point ; + UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ; + +#if wxUSE_UNICODE + ByteCount dataSize = 0 ; + if ( GetEventParameter(event, kEventParamKeyUnicodes, typeUnicodeText, + NULL, 0 , &dataSize, NULL ) == noErr) + { + UniChar buf[2] ; + int numChars = dataSize / sizeof( UniChar) + 1; + + UniChar* charBuf = buf ; + + if ( numChars * 2 > 4 ) + charBuf = new UniChar[ numChars ] ; + GetEventParameter(event, kEventParamKeyUnicodes, typeUnicodeText, NULL, + dataSize , NULL , charBuf) ; + charBuf[ numChars - 1 ] = 0; + +#if SIZEOF_WCHAR_T == 2 + uniChar = charBuf[0] ; +#else + wxMBConvUTF16 converter ; + converter.MB2WC( uniChar , (const char*)charBuf , 2 ) ; +#endif + + if ( numChars * 2 > 4 ) + delete[] charBuf ; + } +#endif + + GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL, + sizeof(char), 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 ) ) + { + case kEventRawKeyRepeat : + case kEventRawKeyDown : + { + WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ; + WXEVENTHANDLERCALLREF formerHandler = + wxTheApp->MacGetCurrentEventHandlerCallRef() ; + + wxTheApp->MacSetCurrentEvent( event , handler ) ; + if ( /* focus && */ wxTheApp->MacSendKeyDownEvent( + focus, message, modifiers, when, point.h, point.v, uniChar[0])) + { + result = noErr ; + } + wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ; + } + break ; + + case kEventRawKeyUp : + if ( /* focus && */ wxTheApp->MacSendKeyUpEvent( + focus , message , modifiers , when , point.h , point.v , uniChar[0] ) ) + { + result = noErr ; + } + break ; + + case kEventRawKeyModifiersChanged : + { + wxKeyEvent event(wxEVT_KEY_DOWN); + + event.m_shiftDown = modifiers & shiftKey; + 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] ; +#endif + + event.SetTimestamp(when); + event.SetEventObject(focus); + + if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & controlKey ) + { + event.m_keyCode = WXK_CONTROL ; + event.SetEventType( ( modifiers & controlKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ; + focus->GetEventHandler()->ProcessEvent( event ) ; + } + if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & shiftKey ) + { + event.m_keyCode = WXK_SHIFT ; + event.SetEventType( ( modifiers & shiftKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ; + focus->GetEventHandler()->ProcessEvent( event ) ; + } + if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & optionKey ) + { + event.m_keyCode = WXK_ALT ; + event.SetEventType( ( modifiers & optionKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ; + focus->GetEventHandler()->ProcessEvent( event ) ; + } + if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & cmdKey ) + { + event.m_keyCode = WXK_COMMAND ; + event.SetEventType( ( modifiers & cmdKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ; + focus->GetEventHandler()->ProcessEvent( event ) ; + } + + wxApp::s_lastModifiers = modifiers ; + } + break ; + + default: + break; + } + + return result ; +} + +static pascal OSStatus wxOSXWebKitCtrlEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) +{ + OSStatus result = eventNotHandledErr ; + + wxMacCarbonEvent cEvent( event ) ; + + ControlRef controlRef ; + wxOSXWebKitCtrl* thisWindow = (wxOSXWebKitCtrl*) data ; + wxNonOwnedWindow* tlw = NULL; + if (thisWindow) + tlw = thisWindow->MacGetTopLevelWindow(); + + cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ; + + wxWindow* currentMouseWindow = thisWindow ; + + if ( wxApp::s_captureWindow ) + currentMouseWindow = wxApp::s_captureWindow; + + switch ( GetEventClass( event ) ) + { + case kEventClassKeyboard: + { + result = wxWebKitKeyEventHandler(handler, event, data); + break; + } + + case kEventClassTextInput: + { + result = wxMacUnicodeTextEventHandler(handler, event, data); + break; + } + + case kEventClassMouse: + { + switch ( GetEventKind( event ) ) + { + case kEventMouseDragged : + case kEventMouseMoved : + case kEventMouseDown : + case kEventMouseUp : + { + wxMouseEvent wxevent(wxEVT_LEFT_DOWN); + SetupMouseEvent( wxevent , cEvent ) ; + + currentMouseWindow->ScreenToClient( &wxevent.m_x , &wxevent.m_y ) ; + wxevent.SetEventObject( currentMouseWindow ) ; + wxevent.SetId( currentMouseWindow->GetId() ) ; + + if ( currentMouseWindow->GetEventHandler()->ProcessEvent(wxevent) ) + { + result = noErr; + } + + break; // this should enable WebKit to fire mouse dragged and mouse up events... + } + default : + break ; + } + } + default: + break; + } + + result = CallNextEventHandler(handler, event); + return result ; +} + +DEFINE_ONE_SHOT_HANDLER_GETTER( wxOSXWebKitCtrlEventHandler ) + +#endif + +//--------------------------------------------------------- +// helper functions for NSString<->wxString conversion +//--------------------------------------------------------- + +inline wxString wxStringWithNSString(NSString *nsstring) +{ +#if wxUSE_UNICODE + return wxString([nsstring UTF8String], wxConvUTF8); +#else + return wxString([nsstring lossyCString]); +#endif // wxUSE_UNICODE +} + +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 +} + +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; + + if (type == WebNavigationTypeReload) + return wxWEBKIT_NAV_RELOAD; + + if (type == WebNavigationTypeFormResubmitted) + return wxWEBKIT_NAV_FORM_RESUBMITTED; + + return wxWEBKIT_NAV_OTHER; +} + +@interface MyFrameLoadMonitor : NSObject +{ + wxOSXWebKitCtrl* webKitWindow; +} + +- initWithWxWindow: (wxOSXWebKitCtrl*)inWindow; + +@end + +@interface MyPolicyDelegate : NSObject +{ + wxOSXWebKitCtrl* webKitWindow; +} + +- initWithWxWindow: (wxOSXWebKitCtrl*)inWindow; + +@end + +// ---------------------------------------------------------------------------- +// creation/destruction +// ---------------------------------------------------------------------------- + +bool wxOSXWebKitCtrl::Create(wxWindow *parent, + wxWindowID winID, + const wxString& strURL, + const wxPoint& pos, + const wxSize& size, long style, + 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; + wxControl::Create(parent, winID, pos, size, style, wxDefaultValidator, name); + +#if wxOSX_USE_CARBON + m_peer = new wxMacControl(this); + WebInitForCarbon(); + HIWebViewCreate( m_peer->GetControlRefAddr() ); + + m_webView = (WebView*) HIWebViewGetWebView( m_peer->GetControlRef() ); + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 + if ( UMAGetSystemVersion() >= 0x1030 ) + HIViewChangeFeatures( m_peer->GetControlRef() , kHIViewIsOpaque , 0 ) ; +#endif + InstallControlEventHandler(m_peer->GetControlRef(), + GetwxOSXWebKitCtrlEventHandlerUPP(), + GetEventTypeCount(eventList), eventList, this, + (EventHandlerRef *)&m_webKitCtrlEventHandler); +#else + NSRect r = wxOSXGetFrameForControl( this, pos , size ) ; + m_webView = [[WebView alloc] initWithFrame:r + frameName:@"webkitFrame" + groupName:@"webkitGroup"]; + m_peer = new wxWidgetCocoaImpl( this, m_webView ); +#endif + + wx_webviewctrls[m_webView] = this; + + MacPostControlCreate(pos, size); + +#if wxOSX_USE_CARBON + HIViewSetVisible( m_peer->GetControlRef(), true ); +#endif + [m_webView setHidden:false]; + +#endif + + // Register event listener interfaces + MyFrameLoadMonitor* myFrameLoadMonitor = + [[MyFrameLoadMonitor alloc] initWithWxWindow: this]; + + [m_webView setFrameLoadDelegate:myFrameLoadMonitor]; + + // this is used to veto page loads, etc. + MyPolicyDelegate* myPolicyDelegate = + [[MyPolicyDelegate alloc] initWithWxWindow: this]; + + [m_webView setPolicyDelegate:myPolicyDelegate]; + + InternalLoadURL(strURL); + return true; +} + +wxOSXWebKitCtrl::~wxOSXWebKitCtrl() +{ + MyFrameLoadMonitor* myFrameLoadMonitor = [m_webView frameLoadDelegate]; + MyPolicyDelegate* myPolicyDelegate = [m_webView policyDelegate]; + [m_webView setFrameLoadDelegate: nil]; + [m_webView setPolicyDelegate: nil]; + + if (myFrameLoadMonitor) + [myFrameLoadMonitor release]; + + if (myPolicyDelegate) + [myPolicyDelegate 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() +{ + if ( !m_webView ) + return false; + + return [m_webView canGoBack]; +} + +bool wxOSXWebKitCtrl::CanGoForward() +{ + if ( !m_webView ) + return false; + + return [m_webView canGoForward]; +} + +void wxOSXWebKitCtrl::GoBack() +{ + if ( !m_webView ) + return; + + bool result = [(WebView*)m_webView goBack]; + + // TODO: return result (if it also exists in other backends...) + //return result; +} + +void wxOSXWebKitCtrl::GoForward() +{ + if ( !m_webView ) + return; + + bool result = [(WebView*)m_webView goForward]; + + // TODO: return result (if it also exists in other backends...) + //return result; +} + +void wxOSXWebKitCtrl::Reload(wxWebViewReloadFlags flags) +{ + if ( !m_webView ) + return; + + if (flags & wxWEB_VIEW_RELOAD_NO_CACHE) + { + // TODO: test this indeed bypasses the cache + [[m_webView preferences] setUsesPageCache:NO]; + [[m_webView mainFrame] reload]; + [[m_webView preferences] setUsesPageCache:YES]; + } + else + { + [[m_webView mainFrame] reload]; + } +} + +void wxOSXWebKitCtrl::Stop() +{ + if ( !m_webView ) + return; + + [[m_webView mainFrame] stopLoading]; +} + +bool wxOSXWebKitCtrl::CanGetPageSource() +{ + if ( !m_webView ) + return false; + + WebDataSource* dataSource = [[m_webView mainFrame] dataSource]; + return ( [[dataSource representation] canProvideDocumentSource] ); +} + +wxString wxOSXWebKitCtrl::GetPageSource() +{ + + if (CanGetPageSource()) + { + WebDataSource* dataSource = [[m_webView mainFrame] dataSource]; + wxASSERT (dataSource != nil); + + id representation = [dataSource representation]; + wxASSERT (representation != nil); + + NSString* source = [representation documentSource]; + if (source == nil) + { + return wxEmptyString; + } + + return wxStringWithNSString( source ); + } + + return wxEmptyString; +} + +wxString wxOSXWebKitCtrl::GetSelection() +{ + if ( !m_webView ) + return wxEmptyString; + + NSString* selectedText = [[m_webView selectedDOMRange] toString]; + return wxStringWithNSString( selectedText ); +} + +bool wxOSXWebKitCtrl::CanIncreaseTextSize() +{ + if ( !m_webView ) + return false; + + if ([m_webView canMakeTextLarger]) + return true; + else + return false; +} + +void wxOSXWebKitCtrl::IncreaseTextSize() +{ + if ( !m_webView ) + return; + + if (CanIncreaseTextSize()) + [m_webView makeTextLarger:(WebView*)m_webView]; +} + +bool wxOSXWebKitCtrl::CanDecreaseTextSize() +{ + if ( !m_webView ) + return false; + + if ([m_webView canMakeTextSmaller]) + return true; + else + return false; +} + +void wxOSXWebKitCtrl::DecreaseTextSize() +{ + if ( !m_webView ) + return; + + if (CanDecreaseTextSize()) + [m_webView makeTextSmaller:(WebView*)m_webView]; +} + +void wxOSXWebKitCtrl::Print() +{ + + // TODO: allow specifying the "show prompt" parameter in Print() ? + bool showPrompt = true; + + if ( !m_webView ) + return; + + id view = [[[m_webView mainFrame] frameView] documentView]; + NSPrintOperation *op = [NSPrintOperation printOperationWithView:view + printInfo: [NSPrintInfo sharedPrintInfo]]; + if (showPrompt) + { + [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 + // workaround for the bug. + [op setShowsProgressPanel: false]; + } + // Print it. + [op runOperation]; +} + +void wxOSXWebKitCtrl::MakeEditable(bool enable) +{ + if ( !m_webView ) + return; + + [m_webView setEditable:enable ]; +} + +bool wxOSXWebKitCtrl::IsEditable() +{ + if ( !m_webView ) + return false; + + return [m_webView isEditable]; +} + +void wxOSXWebKitCtrl::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); +} + +wxWebViewZoomType wxOSXWebKitCtrl::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; +} + +bool wxOSXWebKitCtrl::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: + return true; + + default: + return false; + } +} + +int wxOSXWebKitCtrl::GetScrollPos() +{ + id result = [[m_webView windowScriptObject] + evaluateWebScript:@"document.body.scrollTop"]; + return [result intValue]; +} + +void wxOSXWebKitCtrl::SetScrollPos(int pos) +{ + if ( !m_webView ) + return; + + wxString javascript; + javascript.Printf(wxT("document.body.scrollTop = %d;"), pos); + [[m_webView windowScriptObject] evaluateWebScript: + (NSString*)wxNSStringWithWxString( javascript )]; +} + +wxString wxOSXWebKitCtrl::GetSelectedText() +{ + NSString* selection = [[m_webView selectedDOMRange] markupString]; + if (!selection) return wxEmptyString; + + return wxStringWithNSString(selection); +} + +wxString wxOSXWebKitCtrl::RunScript(const wxString& javascript) +{ + if ( !m_webView ) + return wxEmptyString; + + id result = [[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) +{ +#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 + // basically guesses based on reverse engineering, so it's best to give + // people the option of overriding OnSize with their own calcs if need be. + // I also left some test debugging print statements as a convenience if + // a(nother) problem crops up. + + wxWindow* tlw = MacGetTopLevelWindow(); + + NSRect frame = [(WebView*)m_webView frame]; + NSRect bounds = [(WebView*)m_webView bounds]; + +#if DEBUG_WEBKIT_SIZING + fprintf(stderr,"Carbon window x=%d, y=%d, width=%d, height=%d\n", + GetPosition().x, GetPosition().y, GetSize().x, GetSize().y); + fprintf(stderr, "Cocoa window frame x=%G, y=%G, width=%G, height=%G\n", + frame.origin.x, frame.origin.y, + frame.size.width, frame.size.height); + fprintf(stderr, "Cocoa window bounds x=%G, y=%G, width=%G, height=%G\n", + bounds.origin.x, bounds.origin.y, + bounds.size.width, bounds.size.height); +#endif + + // This must be the case that Apple tested with, because well, in this one case + // we don't need to do anything! It just works. ;) + if (GetParent() == tlw) return; + + // since we no longer use parent coordinates, we always want 0,0. + int x = 0; + int y = 0; + + HIRect rect; + rect.origin.x = x; + rect.origin.y = y; + +#if DEBUG_WEBKIT_SIZING + printf("Before conversion, origin is: x = %d, y = %d\n", x, y); +#endif + + // NB: In most cases, when calling HIViewConvertRect, what people want is to + // use GetRootControl(), and this tripped me up at first. But in fact, what + // 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(), + HIViewGetRoot( + (WindowRef) MacGetTopLevelWindowRef() + )); + + x = (int)rect.origin.x; + y = (int)rect.origin.y; + +#if DEBUG_WEBKIT_SIZING + printf("Moving Cocoa frame origin to: x = %d, y = %d\n", x, y); +#endif + + if (tlw){ + //flip the y coordinate to convert to Cocoa coordinates + y = tlw->GetSize().y - ((GetSize().y) + y); + } + +#if DEBUG_WEBKIT_SIZING + printf("y = %d after flipping value\n", y); +#endif + + frame.origin.x = x; + frame.origin.y = y; + [(WebView*)m_webView setFrame:frame]; + + if (IsShown()) + [(WebView*)m_webView display]; + event.Skip(); +#endif +} + +void wxOSXWebKitCtrl::MacVisibilityChanged(){ +#if defined(__WXMAC__) && wxOSX_USE_CARBON + bool isHidden = !IsControlVisible( m_peer->GetControlRef()); + if (!isHidden) + [(WebView*)m_webView display]; + + [m_webView setHidden:isHidden]; +#endif +} + +void wxOSXWebKitCtrl::LoadUrl(const wxString& url) +{ + InternalLoadURL(url); +} + +wxString wxOSXWebKitCtrl::GetCurrentURL() +{ + return wxStringWithNSString([m_webView mainFrameURL]); +} + +wxString wxOSXWebKitCtrl::GetCurrentTitle() +{ + return GetPageTitle(); +} + +float wxOSXWebKitCtrl::GetWebkitZoom() +{ + return [m_webView textSizeMultiplier]; +} + +void wxOSXWebKitCtrl::SetWebkitZoom(float zoom) +{ + [m_webView setTextSizeMultiplier:zoom]; +} + +wxWebViewZoom wxOSXWebKitCtrl::GetZoom() +{ + float zoom = GetWebkitZoom(); + + // arbitrary way to map float zoom to our common zoom enum + if (zoom <= 0.55) + { + return wxWEB_VIEW_ZOOM_TINY; + } + else if (zoom > 0.55 && zoom <= 0.85) + { + return wxWEB_VIEW_ZOOM_SMALL; + } + else if (zoom > 0.85 && zoom <= 1.15) + { + return wxWEB_VIEW_ZOOM_MEDIUM; + } + else if (zoom > 1.15 && zoom <= 1.45) + { + return wxWEB_VIEW_ZOOM_LARGE; + } + else if (zoom > 1.45) + { + return wxWEB_VIEW_ZOOM_LARGEST; + } + + // to shut up compilers, this can never be reached logically + wxASSERT(false); + return wxWEB_VIEW_ZOOM_MEDIUM; +} + +void wxOSXWebKitCtrl::SetZoom(wxWebViewZoom zoom) +{ + // arbitrary way to map our common zoom enum to float zoom + switch (zoom) + { + case wxWEB_VIEW_ZOOM_TINY: + SetWebkitZoom(0.4f); + break; + + case wxWEB_VIEW_ZOOM_SMALL: + SetWebkitZoom(0.7f); + break; + + case wxWEB_VIEW_ZOOM_MEDIUM: + SetWebkitZoom(1.0f); + break; + + case wxWEB_VIEW_ZOOM_LARGE: + SetWebkitZoom(1.3); + break; + + case wxWEB_VIEW_ZOOM_LARGEST: + SetWebkitZoom(1.6); + break; + + default: + wxASSERT(false); + } + +} + +void wxOSXWebKitCtrl::SetPage(const wxString& src, const wxString& baseUrl) +{ + if ( !m_webView ) + return; + + [[m_webView mainFrame] loadHTMLString:(NSString*)wxNSStringWithWxString(src) + baseURL:[NSURL URLWithString: + wxNSStringWithWxString( baseUrl )]]; +} + +//------------------------------------------------------------ +// Listener interfaces +//------------------------------------------------------------ + +// NB: I'm still tracking this down, but it appears the Cocoa window +// still has these events fired on it while the Carbon control is being +// destroyed. Therefore, we must be careful to check both the existence +// of the Carbon control and the event handler before firing events. + +@implementation MyFrameLoadMonitor + +- initWithWxWindow: (wxOSXWebKitCtrl*)inWindow +{ + [super init]; + webKitWindow = inWindow; // non retained + return self; +} + +- (void)webView:(WebView *)sender + didStartProvisionalLoadForFrame:(WebFrame *)frame +{ + wxASSERT(wx_webviewctrls.find(sender) != wx_webviewctrls.end()); + wx_webviewctrls[sender]->m_busy = true; +} + +- (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame +{ + wxASSERT(wx_webviewctrls.find(sender) != wx_webviewctrls.end()); + wx_webviewctrls[sender]->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); + + if (webKitWindow && webKitWindow->GetEventHandler()) + webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); + } +} + +- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame +{ + wxASSERT(wx_webviewctrls.find(sender) != wx_webviewctrls.end()); + wx_webviewctrls[sender]->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); + + if (webKitWindow && webKitWindow->GetEventHandler()) + webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); + } +} + +wxString nsErrorToWxHtmlError(NSError* error, wxWebNavigationError* out) +{ + *out = wxWEB_NAV_ERR_OTHER; + + if ([[error domain] isEqualToString:NSURLErrorDomain]) + { + switch ([error code]) + { + case NSURLErrorCannotFindHost: + case NSURLErrorFileDoesNotExist: + case NSURLErrorRedirectToNonExistentLocation: + *out = wxWEB_NAV_ERR_NOT_FOUND; + break; + + case NSURLErrorResourceUnavailable: + case NSURLErrorHTTPTooManyRedirects: + case NSURLErrorDataLengthExceedsMaximum: + case NSURLErrorBadURL: + case NSURLErrorFileIsDirectory: + *out = wxWEB_NAV_ERR_REQUEST; + break; + + case NSURLErrorTimedOut: + case NSURLErrorDNSLookupFailed: + case NSURLErrorNetworkConnectionLost: + case NSURLErrorCannotConnectToHost: + case NSURLErrorNotConnectedToInternet: + //case NSURLErrorInternationalRoamingOff: + //case NSURLErrorCallIsActive: + //case NSURLErrorDataNotAllowed: + *out = wxWEB_NAV_ERR_CONNECTION; + break; + + case NSURLErrorCancelled: + case NSURLErrorUserCancelledAuthentication: + *out = wxWEB_NAV_ERR_USER_CANCELLED; + break; + + case NSURLErrorCannotDecodeRawData: + case NSURLErrorCannotDecodeContentData: + case NSURLErrorBadServerResponse: + case NSURLErrorCannotParseResponse: + *out = wxWEB_NAV_ERR_REQUEST; + break; + + case NSURLErrorUserAuthenticationRequired: + case NSURLErrorSecureConnectionFailed: + case NSURLErrorClientCertificateRequired: + *out = wxWEB_NAV_ERR_AUTH; + break; + + case NSURLErrorNoPermissionsToReadFile: + *out = wxWEB_NAV_ERR_SECURITY; + break; + + case NSURLErrorServerCertificateHasBadDate: + case NSURLErrorServerCertificateUntrusted: + case NSURLErrorServerCertificateHasUnknownRoot: + case NSURLErrorServerCertificateNotYetValid: + case NSURLErrorClientCertificateRejected: + *out = wxWEB_NAV_ERR_CERTIFICATE; + break; + } + } + + wxString message = wxStringWithNSString([error localizedDescription]); + NSString* detail = [error localizedFailureReason]; + if (detail != NULL) + { + message = message + " (" + wxStringWithNSString(detail) + ")"; + } + return message; +} + +- (void)webView:(WebView *)sender didFailLoadWithError:(NSError*) error + forFrame:(WebFrame *)frame +{ + wxASSERT(wx_webviewctrls.find(sender) != wx_webviewctrls.end()); + wx_webviewctrls[sender]->m_busy = false; + + if (webKitWindow && frame == [sender mainFrame]){ + NSString *url = [[[[frame dataSource] request] URL] absoluteString]; + + wxWebNavigationError 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); + + if (webKitWindow && webKitWindow->GetEventHandler()) + { + webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); + } + } +} + +- (void)webView:(WebView *)sender + didFailProvisionalLoadWithError:(NSError*)error + forFrame:(WebFrame *)frame +{ + wxASSERT(wx_webviewctrls.find(sender) != wx_webviewctrls.end()); + wx_webviewctrls[sender]->m_busy = false; + + if (webKitWindow && frame == [sender mainFrame]){ + NSString *url = [[[[frame provisionalDataSource] request] URL] + absoluteString]; + + wxWebNavigationError 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); + + if (webKitWindow && webKitWindow->GetEventHandler()) + webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); + } +} + +- (void)webView:(WebView *)sender didReceiveTitle:(NSString *)title + forFrame:(WebFrame *)frame +{ + if (webKitWindow && frame == [sender mainFrame]) + { + webKitWindow->SetPageTitle(wxStringWithNSString( title )); + } +} +@end + +@implementation MyPolicyDelegate + +- initWithWxWindow: (wxOSXWebKitCtrl*)inWindow +{ + [super init]; + webKitWindow = inWindow; // non retained + return self; +} + +- (void)webView:(WebView *)sender + decidePolicyForNavigationAction:(NSDictionary *)actionInformation + request:(NSURLRequest *)request + frame:(WebFrame *)frame + decisionListener:(id)listener +{ + //wxUnusedVar(sender); + wxUnusedVar(frame); + + wxASSERT(wx_webviewctrls.find(sender) != wx_webviewctrls.end()); + wx_webviewctrls[sender]->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); + + if (webKitWindow && webKitWindow->GetEventHandler()) + webKitWindow->GetEventHandler()->ProcessEvent(thisEvent); + + if (thisEvent.IsVetoed()) + { + wx_webviewctrls[sender]->m_busy = false; + [listener ignore]; + } + else + { + [listener use]; + } +} + +- (void)webView:(WebView *)sender + decidePolicyForNewWindowAction:(NSDictionary *)actionInformation + request:(NSURLRequest *)request + newFrameName:(NSString *)frameName + decisionListener:(id < WebPolicyDecisionListener >)listener +{ + wxUnusedVar(sender); + wxUnusedVar(actionInformation); + + [listener ignore]; +} +@end + +#endif //wxHAVE_WEB_BACKEND_OSX_WEBKIT