From 9c6dcab73ab872e0293629646901cc587c946c9e Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Fri, 14 Oct 2011 12:40:40 +0000 Subject: [PATCH] - Add CefFocusHandler::OnFocusedNodeChanged() notification (issue #379). - Add CefDOMNode::IsFormControlElement() and CefDOMNode::GetFormControlElementType() methods (issue #379). - Add space bar handling example to cefclient. git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@318 5089003a-bbd8-11dd-ad1f-f1f9622dbc98 --- include/cef.h | 34 +++++++++++++++++--- include/cef_capi.h | 39 +++++++++++++++++++---- libcef/browser_webview_delegate.cc | 25 +++++++++++++++ libcef/browser_webview_delegate.h | 1 + libcef/dom_node_impl.cc | 34 ++++++++++++++++++++ libcef/dom_node_impl.h | 2 ++ libcef_dll/cpptoc/cpptoc.h | 5 +++ libcef_dll/cpptoc/domnode_cpptoc.cc | 23 +++++++++++++ libcef_dll/cpptoc/focus_handler_cpptoc.cc | 19 +++++++++++ libcef_dll/ctocpp/ctocpp.h | 5 +++ libcef_dll/ctocpp/domnode_ctocpp.cc | 20 ++++++++++++ libcef_dll/ctocpp/domnode_ctocpp.h | 2 ++ libcef_dll/ctocpp/focus_handler_ctocpp.cc | 13 ++++++++ libcef_dll/ctocpp/focus_handler_ctocpp.h | 2 ++ tests/cefclient/client_handler.cpp | 34 +++++++++++++++++++- tests/cefclient/client_handler.h | 21 ++++++++++++ 16 files changed, 267 insertions(+), 12 deletions(-) diff --git a/include/cef.h b/include/cef.h index f414621df..30d1cc4eb 100644 --- a/include/cef.h +++ b/include/cef.h @@ -1331,6 +1331,19 @@ public: /*--cef()--*/ virtual bool OnSetFocus(CefRefPtr browser, FocusSource source) { return false; } + + /// + // Called when a new node in the the browser gets focus. The |node| value may + // be empty if no specific node has gained focus. The node object passed to + // this method represents a snapshot of the DOM at the time this method is + // executed. DOM objects are only valid for the scope of this method. Do not + // keep references to or attempt to access any DOM objects outside the scope + // of this method. + /// + /*--cef()--*/ + virtual void OnFocusedNodeChanged(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr node) {} }; @@ -1345,10 +1358,11 @@ public: typedef cef_handler_keyevent_type_t KeyEventType; /// - // Called when the browser component receives a keyboard event. |type| is the - // type of keyboard event, |code| is the windows scan-code for the event, - // |modifiers| is a set of bit-flags describing any pressed modifier keys and - // |isSystemKey| is true if Windows considers this a 'system key' message (see + // Called when the browser component receives a keyboard event that has not + // been intercepted via JavaScript. |type| is the type of keyboard event, + // |code| is the windows scan-code for the event, |modifiers| is a set of bit- + // flags describing any pressed modifier keys and |isSystemKey| is true if + // Windows considers this a 'system key' message (see // http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx). Return // true if the keyboard event was handled or false to allow the browser // component to handle the event. @@ -3267,6 +3281,18 @@ public: /*--cef()--*/ virtual bool IsElement() =0; + /// + // Returns true if this is a form control element node. + /// + /*--cef()--*/ + virtual bool IsFormControlElement() =0; + + /// + // Returns the type of this form control element node. + /// + /*--cef()--*/ + virtual CefString GetFormControlElementType() =0; + /// // Returns true if this object is pointing to the same handle as |that| // object. diff --git a/include/cef_capi.h b/include/cef_capi.h index b4916b754..a44b4a712 100644 --- a/include/cef_capi.h +++ b/include/cef_capi.h @@ -1138,6 +1138,18 @@ typedef struct _cef_focus_handler_t int (CEF_CALLBACK *on_set_focus)(struct _cef_focus_handler_t* self, struct _cef_browser_t* browser, enum cef_handler_focus_source_t source); + /// + // Called when a new node in the the browser gets focus. The |node| value may + // be NULL if no specific node has gained focus. The node object passed to + // this function represents a snapshot of the DOM at the time this function is + // executed. DOM objects are only valid for the scope of this function. Do not + // keep references to or attempt to access any DOM objects outside the scope + // of this function. + /// + void (CEF_CALLBACK *on_focused_node_changed)( + struct _cef_focus_handler_t* self, struct _cef_browser_t* browser, + struct _cef_frame_t* frame, struct _cef_domnode_t* node); + } cef_focus_handler_t; @@ -1151,13 +1163,14 @@ typedef struct _cef_keyboard_handler_t cef_base_t base; /// - // Called when the browser component receives a keyboard event. |type| is the - // type of keyboard event, |code| is the windows scan-code for the event, - // |modifiers| is a set of bit-flags describing any pressed modifier keys and - // |isSystemKey| is true (1) if Windows considers this a 'system key' message - // (see http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx). Return - // true (1) if the keyboard event was handled or false (0) to allow the - // browser component to handle the event. + // Called when the browser component receives a keyboard event that has not + // been intercepted via JavaScript. |type| is the type of keyboard event, + // |code| is the windows scan-code for the event, |modifiers| is a set of bit- + // flags describing any pressed modifier keys and |isSystemKey| is true (1) if + // Windows considers this a 'system key' message (see + // http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx). Return true + // (1) if the keyboard event was handled or false (0) to allow the browser + // component to handle the event. /// int (CEF_CALLBACK *on_key_event)(struct _cef_keyboard_handler_t* self, struct _cef_browser_t* browser, enum cef_handler_keyevent_type_t type, @@ -3045,6 +3058,18 @@ typedef struct _cef_domnode_t /// int (CEF_CALLBACK *is_element)(struct _cef_domnode_t* self); + /// + // Returns true (1) if this is a form control element node. + /// + int (CEF_CALLBACK *is_form_control_element)(struct _cef_domnode_t* self); + + /// + // Returns the type of this form control element node. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_form_control_element_type)( + struct _cef_domnode_t* self); + /// // Returns true (1) if this object is pointing to the same handle as |that| // object. diff --git a/libcef/browser_webview_delegate.cc b/libcef/browser_webview_delegate.cc index 79b3f707d..843f74993 100644 --- a/libcef/browser_webview_delegate.cc +++ b/libcef/browser_webview_delegate.cc @@ -17,6 +17,7 @@ #include "browser_webstoragenamespace_impl.h" #include "browser_zoom_map.h" #include "cef_context.h" +#include "dom_document_impl.h" #include "request_impl.h" #include "v8_impl.h" @@ -462,6 +463,30 @@ void BrowserWebViewDelegate::focusPrevious() { } } +void BrowserWebViewDelegate::focusedNodeChanged(const WebKit::WebNode& node) { + CefRefPtr client = browser_->GetClient(); + if (client.get()) { + CefRefPtr handler = client->GetFocusHandler(); + if (handler.get()) { + if (node.isNull()) { + handler->OnFocusedNodeChanged(browser_, browser_->GetFocusedFrame(), + NULL); + } else { + const WebKit::WebDocument& document = node.document(); + if (!document.isNull()) { + WebKit::WebFrame* frame = document.frame(); + CefRefPtr documentImpl = + new CefDOMDocumentImpl(browser_, frame); + handler->OnFocusedNodeChanged(browser_, + browser_->UIT_GetCefFrame(frame), + documentImpl->GetOrCreateNode(node)); + documentImpl->Detach(); + } + } + } + } +} + void BrowserWebViewDelegate::navigateBackForwardSoon(int offset) { browser_->UIT_GetNavigationController()->GoToOffset(offset); } diff --git a/libcef/browser_webview_delegate.h b/libcef/browser_webview_delegate.h index 2fa9d9863..0736bfad0 100644 --- a/libcef/browser_webview_delegate.h +++ b/libcef/browser_webview_delegate.h @@ -112,6 +112,7 @@ class BrowserWebViewDelegate : public WebKit::WebViewClient, virtual bool acceptsLoadDrops() OVERRIDE { return true; } virtual void focusNext() OVERRIDE; virtual void focusPrevious() OVERRIDE; + virtual void focusedNodeChanged(const WebKit::WebNode& node) OVERRIDE; virtual void navigateBackForwardSoon(int offset) OVERRIDE; virtual int historyBackListCount() OVERRIDE; virtual int historyForwardListCount() OVERRIDE; diff --git a/libcef/dom_node_impl.cc b/libcef/dom_node_impl.cc index 8f5d7224b..d101c1abf 100644 --- a/libcef/dom_node_impl.cc +++ b/libcef/dom_node_impl.cc @@ -159,6 +159,40 @@ bool CefDOMNodeImpl::IsElement() return node_.isElementNode(); } +bool CefDOMNodeImpl::IsFormControlElement() +{ + if (!VerifyContext()) + return false; + + if (node_.isElementNode()) { + const WebElement& element = node_.toConst(); + return element.isFormControlElement(); + } + + return false; +} + +CefString CefDOMNodeImpl::GetFormControlElementType() +{ + CefString str; + if (!VerifyContext()) + return str; + + if (node_.isElementNode()) { + const WebElement& element = node_.toConst(); + if (element.isFormControlElement()) { + // Retrieve the type from the form control element. + const WebFormControlElement& formElement = + node_.toConst(); + + const string16& form_control_type = formElement.formControlType(); + str = form_control_type; + } + } + + return str; +} + bool CefDOMNodeImpl::IsSame(CefRefPtr that) { if (!VerifyContext()) diff --git a/libcef/dom_node_impl.h b/libcef/dom_node_impl.h index 8c74e8d4c..a430c9a6a 100644 --- a/libcef/dom_node_impl.h +++ b/libcef/dom_node_impl.h @@ -20,6 +20,8 @@ public: virtual Type GetType() OVERRIDE; virtual bool IsText() OVERRIDE; virtual bool IsElement() OVERRIDE; + virtual bool IsFormControlElement() OVERRIDE; + virtual CefString GetFormControlElementType() OVERRIDE; virtual bool IsSame(CefRefPtr that) OVERRIDE; virtual CefString GetName() OVERRIDE; virtual CefString GetValue() OVERRIDE; diff --git a/libcef_dll/cpptoc/cpptoc.h b/libcef_dll/cpptoc/cpptoc.h index bbfc431e7..157684e53 100644 --- a/libcef_dll/cpptoc/cpptoc.h +++ b/libcef_dll/cpptoc/cpptoc.h @@ -40,6 +40,9 @@ public: // instance to the other side. static StructName* Wrap(CefRefPtr c) { + if (!c.get()) + return NULL; + // Wrap our object with the CefCppToC class. ClassName* wrapper = new ClassName(c); // Add a reference to our wrapper object that will be released once our @@ -53,6 +56,8 @@ public: // our wrapper structure back from the other side. static CefRefPtr Unwrap(StructName* s) { + DCHECK(s); + // Cast our structure to the wrapper structure type. Struct* wrapperStruct = reinterpret_cast(s); // Add the underlying object instance to a smart pointer. diff --git a/libcef_dll/cpptoc/domnode_cpptoc.cc b/libcef_dll/cpptoc/domnode_cpptoc.cc index f9fbc6a0e..6e502af35 100644 --- a/libcef_dll/cpptoc/domnode_cpptoc.cc +++ b/libcef_dll/cpptoc/domnode_cpptoc.cc @@ -46,6 +46,26 @@ int CEF_CALLBACK domnode_is_element(struct _cef_domnode_t* self) return CefDOMNodeCppToC::Get(self)->IsElement(); } +int CEF_CALLBACK domnode_is_form_control_element(struct _cef_domnode_t* self) +{ + DCHECK(self); + if (!self) + return 0; + + return CefDOMNodeCppToC::Get(self)->IsFormControlElement(); +} + +cef_string_userfree_t CEF_CALLBACK domnode_get_form_control_element_type( + struct _cef_domnode_t* self) +{ + DCHECK(self); + if (!self) + return NULL; + + CefString str = CefDOMNodeCppToC::Get(self)->GetFormControlElementType(); + return str.DetachToUserFree(); +} + int CEF_CALLBACK domnode_is_same(struct _cef_domnode_t* self, struct _cef_domnode_t* that) { @@ -292,6 +312,9 @@ CefDOMNodeCppToC::CefDOMNodeCppToC(CefDOMNode* cls) struct_.struct_.get_type = domnode_get_type; struct_.struct_.is_text = domnode_is_text; struct_.struct_.is_element = domnode_is_element; + struct_.struct_.is_form_control_element = domnode_is_form_control_element; + struct_.struct_.get_form_control_element_type = + domnode_get_form_control_element_type; struct_.struct_.is_same = domnode_is_same; struct_.struct_.get_name = domnode_get_name; struct_.struct_.get_value = domnode_get_value; diff --git a/libcef_dll/cpptoc/focus_handler_cpptoc.cc b/libcef_dll/cpptoc/focus_handler_cpptoc.cc index e3c2bf32b..55799aea3 100644 --- a/libcef_dll/cpptoc/focus_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/focus_handler_cpptoc.cc @@ -12,6 +12,8 @@ #include "libcef_dll/cpptoc/focus_handler_cpptoc.h" #include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/domnode_ctocpp.h" +#include "libcef_dll/ctocpp/frame_ctocpp.h" // MEMBER FUNCTIONS - Body may be edited by hand. @@ -40,6 +42,21 @@ int CEF_CALLBACK focus_handler_on_set_focus(struct _cef_focus_handler_t* self, CefBrowserCToCpp::Wrap(browser), source); } +void CEF_CALLBACK focus_handler_on_focused_node_changed( + struct _cef_focus_handler_t* self, cef_browser_t* browser, + cef_frame_t* frame, struct _cef_domnode_t* node) +{ + DCHECK(self); + DCHECK(browser); + DCHECK(frame); + if (!self || !browser || !frame) + return; + + return CefFocusHandlerCppToC::Get(self)->OnFocusedNodeChanged( + CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame), + CefDOMNodeCToCpp::Wrap(node)); +} + // CONSTRUCTOR - Do not edit by hand. @@ -49,6 +66,8 @@ CefFocusHandlerCppToC::CefFocusHandlerCppToC(CefFocusHandler* cls) { struct_.struct_.on_take_focus = focus_handler_on_take_focus; struct_.struct_.on_set_focus = focus_handler_on_set_focus; + struct_.struct_.on_focused_node_changed = + focus_handler_on_focused_node_changed; } #ifndef NDEBUG diff --git a/libcef_dll/ctocpp/ctocpp.h b/libcef_dll/ctocpp/ctocpp.h index 4b8348c44..9d275c356 100644 --- a/libcef_dll/ctocpp/ctocpp.h +++ b/libcef_dll/ctocpp/ctocpp.h @@ -21,6 +21,9 @@ public: // received from the other side. static CefRefPtr Wrap(StructName* s) { + if (!s) + return NULL; + // Wrap their structure with the CefCToCpp object. ClassName* wrapper = new ClassName(s); // Put the wrapper object in a smart pointer. @@ -36,6 +39,8 @@ public: // instance for return back to the other side. static StructName* Unwrap(CefRefPtr c) { + DCHECK(c.get()); + // Cast the object to our wrapper class type. ClassName* wrapper = static_cast(c.get()); // Add a reference to the CefCppToC wrapper object on the other side that diff --git a/libcef_dll/ctocpp/domnode_ctocpp.cc b/libcef_dll/ctocpp/domnode_ctocpp.cc index 0790cc775..db8a84295 100644 --- a/libcef_dll/ctocpp/domnode_ctocpp.cc +++ b/libcef_dll/ctocpp/domnode_ctocpp.cc @@ -42,6 +42,26 @@ bool CefDOMNodeCToCpp::IsElement() return struct_->is_element(struct_) ? true : false; } +bool CefDOMNodeCToCpp::IsFormControlElement() +{ + if (CEF_MEMBER_MISSING(struct_, is_form_control_element)) + return false; + + return struct_->is_form_control_element(struct_) ? true : false; +} + +CefString CefDOMNodeCToCpp::GetFormControlElementType() +{ + CefString str; + if (CEF_MEMBER_MISSING(struct_, get_form_control_element_type)) + return str; + + cef_string_userfree_t strPtr = + struct_->get_form_control_element_type(struct_); + str.AttachToUserFree(strPtr); + return str; +} + bool CefDOMNodeCToCpp::IsSame(CefRefPtr that) { if (CEF_MEMBER_MISSING(struct_, is_same)) diff --git a/libcef_dll/ctocpp/domnode_ctocpp.h b/libcef_dll/ctocpp/domnode_ctocpp.h index 181e9ac1e..693dc0b54 100644 --- a/libcef_dll/ctocpp/domnode_ctocpp.h +++ b/libcef_dll/ctocpp/domnode_ctocpp.h @@ -34,6 +34,8 @@ public: virtual Type GetType() OVERRIDE; virtual bool IsText() OVERRIDE; virtual bool IsElement() OVERRIDE; + virtual bool IsFormControlElement() OVERRIDE; + virtual CefString GetFormControlElementType() OVERRIDE; virtual bool IsSame(CefRefPtr that) OVERRIDE; virtual CefString GetName() OVERRIDE; virtual CefString GetValue() OVERRIDE; diff --git a/libcef_dll/ctocpp/focus_handler_ctocpp.cc b/libcef_dll/ctocpp/focus_handler_ctocpp.cc index edc70e1cb..40d40b9cc 100644 --- a/libcef_dll/ctocpp/focus_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/focus_handler_ctocpp.cc @@ -11,6 +11,8 @@ // #include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/domnode_cpptoc.h" +#include "libcef_dll/cpptoc/frame_cpptoc.h" #include "libcef_dll/ctocpp/focus_handler_ctocpp.h" @@ -35,6 +37,17 @@ bool CefFocusHandlerCToCpp::OnSetFocus(CefRefPtr browser, source) ? true : false; } +void CefFocusHandlerCToCpp::OnFocusedNodeChanged(CefRefPtr browser, + CefRefPtr frame, CefRefPtr node) +{ + if (CEF_MEMBER_MISSING(struct_, on_focused_node_changed)) + return; + + struct_->on_focused_node_changed(struct_, + CefBrowserCppToC::Wrap(browser), CefFrameCppToC::Wrap(frame), + CefDOMNodeCppToC::Wrap(node)); +} + #ifndef NDEBUG template<> long CefCToCpp browser, bool next) OVERRIDE; virtual bool OnSetFocus(CefRefPtr browser, FocusSource source) OVERRIDE; + virtual void OnFocusedNodeChanged(CefRefPtr browser, + CefRefPtr frame, CefRefPtr node) OVERRIDE; }; #endif // BUILDING_CEF_SHARED diff --git a/tests/cefclient/client_handler.cpp b/tests/cefclient/client_handler.cpp index bf0b3012a..29edffa3e 100644 --- a/tests/cefclient/client_handler.cpp +++ b/tests/cefclient/client_handler.cpp @@ -20,7 +20,8 @@ ClientHandler::ClientHandler() m_BackHwnd(NULL), m_ForwardHwnd(NULL), m_StopHwnd(NULL), - m_ReloadHwnd(NULL) + m_ReloadHwnd(NULL), + m_bFormElementHasFocus(false) { } @@ -201,6 +202,37 @@ bool ClientHandler::OnConsoleMessage(CefRefPtr browser, return false; } +void ClientHandler::OnFocusedNodeChanged(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr node) +{ + REQUIRE_UI_THREAD(); + + // Set to true if a form element has focus. + m_bFormElementHasFocus = (node.get() && node->IsFormControlElement()); +} + +bool ClientHandler::OnKeyEvent(CefRefPtr browser, + KeyEventType type, + int code, + int modifiers, + bool isSystemKey) +{ + REQUIRE_UI_THREAD(); + + if (!m_bFormElementHasFocus && code == 0x20) { + // Special handling for the space character if a form element does not have + // focus. + if (type == KEYEVENT_RAWKEYDOWN) { + browser->GetMainFrame()->ExecuteJavaScript( + "alert('You pressed the space bar!');", "", 0); + } + return true; + } + + return false; +} + bool ClientHandler::GetPrintHeaderFooter(CefRefPtr browser, CefRefPtr frame, const CefPrintInfo& printInfo, diff --git a/tests/cefclient/client_handler.h b/tests/cefclient/client_handler.h index e1fd49168..5834b8850 100644 --- a/tests/cefclient/client_handler.h +++ b/tests/cefclient/client_handler.h @@ -21,6 +21,8 @@ class ClientHandler : public CefClient, public CefLoadHandler, public CefRequestHandler, public CefDisplayHandler, + public CefFocusHandler, + public CefKeyboardHandler, public CefPrintHandler, public CefJSBindingHandler, public CefDragHandler, @@ -39,6 +41,10 @@ public: { return this; } virtual CefRefPtr GetDisplayHandler() OVERRIDE { return this; } + virtual CefRefPtr GetFocusHandler() OVERRIDE + { return this; } + virtual CefRefPtr GetKeyboardHandler() OVERRIDE + { return this; } virtual CefRefPtr GetPrintHandler() OVERRIDE { return this; } virtual CefRefPtr GetJSBindingHandler() OVERRIDE @@ -97,6 +103,18 @@ public: const CefString& source, int line) OVERRIDE; + // CefFocusHandler methods. + virtual void OnFocusedNodeChanged(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr node) OVERRIDE; + + // CefKeyboardHandler methods. + virtual bool OnKeyEvent(CefRefPtr browser, + KeyEventType type, + int code, + int modifiers, + bool isSystemKey) OVERRIDE; + // CefPrintHandler methods. virtual bool GetPrintHeaderFooter(CefRefPtr browser, CefRefPtr frame, @@ -192,6 +210,9 @@ protected: typedef std::map > DOMVisitorMap; DOMVisitorMap m_DOMVisitors; + // True if a form element currently has focus + bool m_bFormElementHasFocus; + // Include the default reference counting implementation. IMPLEMENT_REFCOUNTING(ClientHandler); // Include the default locking implementation.