mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-17 20:50:42 +01:00
Merge revision 736 and revision 737 changes:
- Fix crashes/assertions when CefBrowserImpl is destroyed on a non-UI thread (issue #694). - Improve the handling of invalidation/painting for off-screen rendering (issue #695). git-svn-id: https://chromiumembedded.googlecode.com/svn/branches/963@738 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
parent
bcc07f0333
commit
b04a3cad07
@ -777,6 +777,9 @@ void CefBrowserImpl::UIT_DestroyBrowser() {
|
||||
dev_tools_agent_.reset();
|
||||
}
|
||||
|
||||
if (frame_objects_.size() > 0)
|
||||
frame_objects_.clear();
|
||||
|
||||
// Clean up anything associated with the WebViewHost widget.
|
||||
if (webviewhost_.get()) {
|
||||
if (webviewhost_->webwidget())
|
||||
@ -784,6 +787,13 @@ void CefBrowserImpl::UIT_DestroyBrowser() {
|
||||
webviewhost_.reset();
|
||||
}
|
||||
|
||||
delegate_.reset(NULL);
|
||||
popup_delegate_.reset(NULL);
|
||||
nav_controller_.reset(NULL);
|
||||
|
||||
if (paint_delegate_.get())
|
||||
paint_delegate_.reset(NULL);
|
||||
|
||||
// Remove the reference to the window handle.
|
||||
UIT_ClearMainWndHandle();
|
||||
|
||||
@ -795,11 +805,11 @@ void CefBrowserImpl::UIT_DestroyBrowser() {
|
||||
request_context_proxy_.release());
|
||||
}
|
||||
|
||||
// Remove the reference added in UIT_CreateBrowser().
|
||||
Release();
|
||||
|
||||
// Remove the browser from the list maintained by the context.
|
||||
_Context->RemoveBrowser(this);
|
||||
|
||||
// Remove the reference added in UIT_CreateBrowser().
|
||||
Release();
|
||||
}
|
||||
|
||||
void CefBrowserImpl::UIT_CloseBrowser() {
|
||||
|
@ -3,8 +3,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "browser_navigation_controller.h"
|
||||
#include "browser_impl.h"
|
||||
#include "libcef/browser_navigation_controller.h"
|
||||
#include "libcef/browser_impl.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "net/base/upload_data.h"
|
||||
@ -29,7 +29,7 @@ BrowserNavigationEntry::BrowserNavigationEntry(int page_id,
|
||||
method_(method),
|
||||
headers_(headers),
|
||||
target_frame_(target_frame) {
|
||||
if(!upload.isNull())
|
||||
if (!upload.isNull())
|
||||
upload_ = upload;
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ BrowserNavigationController::~BrowserNavigationController() {
|
||||
}
|
||||
|
||||
void BrowserNavigationController::Reset() {
|
||||
entries_.clear();
|
||||
entries_.reset();
|
||||
DiscardPendingEntry();
|
||||
|
||||
last_committed_entry_index_ = -1;
|
||||
@ -88,8 +88,8 @@ void BrowserNavigationController::GoToOffset(int offset) {
|
||||
}
|
||||
|
||||
void BrowserNavigationController::GoToIndex(int index) {
|
||||
DCHECK(index >= 0);
|
||||
DCHECK(index < static_cast<int>(entries_.size()));
|
||||
DCHECK_GE(index, 0);
|
||||
DCHECK_LT(index, static_cast<int>(entries_.size()));
|
||||
|
||||
DiscardPendingEntry();
|
||||
|
||||
@ -111,7 +111,8 @@ BrowserNavigationEntry* BrowserNavigationController::GetLastCommittedEntry()
|
||||
const {
|
||||
if (last_committed_entry_index_ == -1)
|
||||
return NULL;
|
||||
return entries_[last_committed_entry_index_].get();
|
||||
return const_cast<BrowserNavigationEntry*>(
|
||||
entries_[last_committed_entry_index_]);
|
||||
}
|
||||
|
||||
BrowserNavigationEntry* BrowserNavigationController::GetActiveEntry() const {
|
||||
@ -133,13 +134,14 @@ BrowserNavigationEntry* BrowserNavigationController::GetEntryAtIndex(
|
||||
if (index < 0 || index >= GetEntryCount())
|
||||
return NULL;
|
||||
|
||||
return entries_[index].get();
|
||||
return const_cast<BrowserNavigationEntry*>(entries_[index]);
|
||||
}
|
||||
|
||||
BrowserNavigationEntry* BrowserNavigationController::GetEntryWithPageID(
|
||||
int32 page_id) const {
|
||||
int index = GetEntryIndexWithPageID(page_id);
|
||||
return (index != -1) ? entries_[index].get() : NULL;
|
||||
return (index != -1) ?
|
||||
const_cast<BrowserNavigationEntry*>(entries_[index]) : NULL;
|
||||
}
|
||||
|
||||
void BrowserNavigationController::DidNavigateToEntry(
|
||||
@ -158,7 +160,7 @@ void BrowserNavigationController::DidNavigateToEntry(
|
||||
|
||||
int existing_entry_index = GetEntryIndexWithPageID(entry->GetPageID());
|
||||
BrowserNavigationEntry* existing_entry = (existing_entry_index != -1) ?
|
||||
entries_[existing_entry_index].get() : NULL;
|
||||
entries_[existing_entry_index] : NULL;
|
||||
if (!existing_entry) {
|
||||
// No existing entry, then simply ignore this navigation!
|
||||
DLOG(WARNING) << "ignoring navigation for page: " << entry->GetPageID();
|
||||
@ -191,7 +193,7 @@ void BrowserNavigationController::DidNavigateToEntry(
|
||||
}
|
||||
|
||||
void BrowserNavigationController::DiscardPendingEntry() {
|
||||
if (pending_entry_index_ == -1)
|
||||
if (pending_entry_index_ == -1 && pending_entry_)
|
||||
delete pending_entry_;
|
||||
pending_entry_ = NULL;
|
||||
pending_entry_index_ = -1;
|
||||
@ -204,19 +206,19 @@ void BrowserNavigationController::InsertEntry(BrowserNavigationEntry* entry) {
|
||||
if (settings.history_disabled) {
|
||||
// History is disabled. Remove any existing entries.
|
||||
if (entries_.size() > 0)
|
||||
entries_.clear();
|
||||
entries_.reset();
|
||||
} else {
|
||||
// Prune any entry which are in front of the current entry.
|
||||
int current_size = static_cast<int>(entries_.size());
|
||||
if (current_size > 0) {
|
||||
while (last_committed_entry_index_ < (current_size - 1)) {
|
||||
entries_.pop_back();
|
||||
entries_.erase(entries_.end() - 1);
|
||||
current_size--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
entries_.push_back(linked_ptr<BrowserNavigationEntry>(entry));
|
||||
entries_.push_back(entry);
|
||||
last_committed_entry_index_ = static_cast<int>(entries_.size()) - 1;
|
||||
UpdateMaxPageID();
|
||||
}
|
||||
@ -233,8 +235,8 @@ void BrowserNavigationController::NavigateToPendingEntry(bool reload,
|
||||
bool ignoreCache) {
|
||||
// For session history navigations only the pending_entry_index_ is set.
|
||||
if (!pending_entry_) {
|
||||
DCHECK(pending_entry_index_ != -1);
|
||||
pending_entry_ = entries_[pending_entry_index_].get();
|
||||
DCHECK_NE(pending_entry_index_, -1);
|
||||
pending_entry_ = entries_[pending_entry_index_];
|
||||
}
|
||||
|
||||
if (browser_->UIT_Navigate(*pending_entry_, reload, ignoreCache)) {
|
||||
|
@ -3,15 +3,16 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef _BROWSER_NAVIGATION_CONTROLLER_H
|
||||
#define _BROWSER_NAVIGATION_CONTROLLER_H
|
||||
#ifndef CEF_LIBCEF_BROWSER_NAVIGATION_CONTROLLER_H_
|
||||
#define CEF_LIBCEF_BROWSER_NAVIGATION_CONTROLLER_H_
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/memory/linked_ptr.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/memory/scoped_vector.h"
|
||||
#include "googleurl/src/gurl.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebHTTPBody.h"
|
||||
@ -24,7 +25,7 @@ class CefBrowserImpl;
|
||||
// Associated with browser-initated navigations to hold tracking data.
|
||||
class BrowserExtraData : public WebKit::WebDataSource::ExtraData {
|
||||
public:
|
||||
BrowserExtraData(int32 pending_page_id)
|
||||
explicit BrowserExtraData(int32 pending_page_id)
|
||||
: pending_page_id(pending_page_id),
|
||||
request_committed(false) {
|
||||
}
|
||||
@ -76,7 +77,7 @@ class BrowserNavigationEntry {
|
||||
const WebKit::WebHTTPBody& GetUploadData() const { return upload_; }
|
||||
const CefRequest::HeaderMap& GetHeaders() const { return headers_; }
|
||||
|
||||
private:
|
||||
private:
|
||||
// Describes the current page that the tab represents. This is not relevant
|
||||
// for all tab contents types.
|
||||
int32 page_id_;
|
||||
@ -97,7 +98,7 @@ private:
|
||||
// version as possible.
|
||||
class BrowserNavigationController {
|
||||
public:
|
||||
BrowserNavigationController(CefBrowserImpl* browser);
|
||||
explicit BrowserNavigationController(CefBrowserImpl* browser);
|
||||
~BrowserNavigationController();
|
||||
|
||||
void Reset();
|
||||
@ -186,8 +187,7 @@ class BrowserNavigationController {
|
||||
void UpdateMaxPageID();
|
||||
|
||||
// List of NavigationEntry for this tab
|
||||
typedef std::vector< linked_ptr<BrowserNavigationEntry> > NavigationEntryList;
|
||||
typedef NavigationEntryList::iterator NavigationEntryListIterator;
|
||||
typedef ScopedVector<BrowserNavigationEntry> NavigationEntryList;
|
||||
NavigationEntryList entries_;
|
||||
|
||||
// An entry we haven't gotten a response for yet. This will be discarded
|
||||
@ -208,5 +208,4 @@ class BrowserNavigationController {
|
||||
DISALLOW_EVIL_CONSTRUCTORS(BrowserNavigationController);
|
||||
};
|
||||
|
||||
#endif // _BROWSER_NAVIGATION_CONTROLLER_H
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_NAVIGATION_CONTROLLER_H_
|
||||
|
@ -1226,8 +1226,8 @@ void BrowserWebViewDelegate::UpdateSessionHistory(WebFrame* frame) {
|
||||
if (page_id_ == -1)
|
||||
return;
|
||||
|
||||
BrowserNavigationEntry* entry = static_cast<BrowserNavigationEntry*>(
|
||||
browser_->UIT_GetNavigationController()->GetEntryWithPageID(page_id_));
|
||||
BrowserNavigationEntry* entry =
|
||||
browser_->UIT_GetNavigationController()->GetEntryWithPageID(page_id_);
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
|
@ -1,16 +1,17 @@
|
||||
// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights
|
||||
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#include "dom_node_impl.h"
|
||||
#include "browser_impl.h"
|
||||
#include "cef_thread.h"
|
||||
#include "dom_document_impl.h"
|
||||
#include "dom_event_impl.h"
|
||||
#include "tracker.h"
|
||||
#include "libcef/dom_node_impl.h"
|
||||
#include "libcef/browser_impl.h"
|
||||
#include "libcef/cef_thread.h"
|
||||
#include "libcef/dom_document_impl.h"
|
||||
#include "libcef/dom_event_impl.h"
|
||||
#include "libcef/tracker.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/string_util.h"
|
||||
#include "base/threading/non_thread_safe.h"
|
||||
#include "base/utf_string_conversions.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebAttribute.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
|
||||
@ -38,31 +39,28 @@ using WebKit::WebNode;
|
||||
using WebKit::WebSelectElement;
|
||||
using WebKit::WebString;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
// Wrapper implementation for WebDOMEventListener.
|
||||
class CefDOMEventListenerWrapper : public WebDOMEventListener,
|
||||
public CefTrackObject
|
||||
{
|
||||
public:
|
||||
public CefTrackObject,
|
||||
public base::NonThreadSafe {
|
||||
public:
|
||||
CefDOMEventListenerWrapper(CefBrowserImpl* browser, WebFrame* frame,
|
||||
CefRefPtr<CefDOMEventListener> listener)
|
||||
: browser_(browser), frame_(frame), listener_(listener)
|
||||
{
|
||||
: browser_(browser),
|
||||
frame_(frame),
|
||||
listener_(listener) {
|
||||
// Cause this object to be deleted immediately before the frame is closed.
|
||||
browser->UIT_AddFrameObject(frame, this);
|
||||
}
|
||||
virtual ~CefDOMEventListenerWrapper()
|
||||
{
|
||||
REQUIRE_UIT();
|
||||
virtual ~CefDOMEventListenerWrapper() {
|
||||
}
|
||||
|
||||
virtual void handleEvent(const WebDOMEvent& event)
|
||||
{
|
||||
virtual void handleEvent(const WebDOMEvent& event) {
|
||||
CefRefPtr<CefDOMDocumentImpl> documentImpl;
|
||||
CefRefPtr<CefDOMEventImpl> eventImpl;
|
||||
|
||||
|
||||
if (!event.isNull()) {
|
||||
// Create CefDOMDocumentImpl and CefDOMEventImpl objects that are valid
|
||||
// only for the scope of this method.
|
||||
@ -72,32 +70,31 @@ public:
|
||||
eventImpl = new CefDOMEventImpl(documentImpl, event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
listener_->HandleEvent(eventImpl.get());
|
||||
|
||||
if(eventImpl.get())
|
||||
|
||||
if (eventImpl.get())
|
||||
eventImpl->Detach();
|
||||
if (documentImpl.get())
|
||||
documentImpl->Detach();
|
||||
}
|
||||
|
||||
protected:
|
||||
protected:
|
||||
CefBrowserImpl* browser_;
|
||||
WebFrame* frame_;
|
||||
CefRefPtr<CefDOMEventListener> listener_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
|
||||
CefDOMNodeImpl::CefDOMNodeImpl(CefRefPtr<CefDOMDocumentImpl> document,
|
||||
const WebKit::WebNode& node)
|
||||
: document_(document), node_(node)
|
||||
{
|
||||
: document_(document),
|
||||
node_(node) {
|
||||
}
|
||||
|
||||
CefDOMNodeImpl::~CefDOMNodeImpl()
|
||||
{
|
||||
CefDOMNodeImpl::~CefDOMNodeImpl() {
|
||||
REQUIRE_UIT();
|
||||
|
||||
if (document_.get() && !node_.isNull()) {
|
||||
@ -106,8 +103,7 @@ CefDOMNodeImpl::~CefDOMNodeImpl()
|
||||
}
|
||||
}
|
||||
|
||||
CefDOMNodeImpl::Type CefDOMNodeImpl::GetType()
|
||||
{
|
||||
CefDOMNodeImpl::Type CefDOMNodeImpl::GetType() {
|
||||
if (!VerifyContext())
|
||||
return DOM_NODE_TYPE_UNSUPPORTED;
|
||||
|
||||
@ -143,24 +139,21 @@ CefDOMNodeImpl::Type CefDOMNodeImpl::GetType()
|
||||
}
|
||||
}
|
||||
|
||||
bool CefDOMNodeImpl::IsText()
|
||||
{
|
||||
bool CefDOMNodeImpl::IsText() {
|
||||
if (!VerifyContext())
|
||||
return false;
|
||||
|
||||
return node_.isTextNode();
|
||||
}
|
||||
|
||||
bool CefDOMNodeImpl::IsElement()
|
||||
{
|
||||
bool CefDOMNodeImpl::IsElement() {
|
||||
if (!VerifyContext())
|
||||
return false;
|
||||
|
||||
return node_.isElementNode();
|
||||
}
|
||||
|
||||
bool CefDOMNodeImpl::IsFormControlElement()
|
||||
{
|
||||
bool CefDOMNodeImpl::IsFormControlElement() {
|
||||
if (!VerifyContext())
|
||||
return false;
|
||||
|
||||
@ -172,8 +165,7 @@ bool CefDOMNodeImpl::IsFormControlElement()
|
||||
return false;
|
||||
}
|
||||
|
||||
CefString CefDOMNodeImpl::GetFormControlElementType()
|
||||
{
|
||||
CefString CefDOMNodeImpl::GetFormControlElementType() {
|
||||
CefString str;
|
||||
if (!VerifyContext())
|
||||
return str;
|
||||
@ -193,8 +185,7 @@ CefString CefDOMNodeImpl::GetFormControlElementType()
|
||||
return str;
|
||||
}
|
||||
|
||||
bool CefDOMNodeImpl::IsSame(CefRefPtr<CefDOMNode> that)
|
||||
{
|
||||
bool CefDOMNodeImpl::IsSame(CefRefPtr<CefDOMNode> that) {
|
||||
if (!VerifyContext())
|
||||
return false;
|
||||
|
||||
@ -205,8 +196,7 @@ bool CefDOMNodeImpl::IsSame(CefRefPtr<CefDOMNode> that)
|
||||
return node_.equals(impl->node_);
|
||||
}
|
||||
|
||||
CefString CefDOMNodeImpl::GetName()
|
||||
{
|
||||
CefString CefDOMNodeImpl::GetName() {
|
||||
CefString str;
|
||||
if (!VerifyContext())
|
||||
return str;
|
||||
@ -218,8 +208,7 @@ CefString CefDOMNodeImpl::GetName()
|
||||
return str;
|
||||
}
|
||||
|
||||
CefString CefDOMNodeImpl::GetValue()
|
||||
{
|
||||
CefString CefDOMNodeImpl::GetValue() {
|
||||
CefString str;
|
||||
if (!VerifyContext())
|
||||
return str;
|
||||
@ -257,8 +246,7 @@ CefString CefDOMNodeImpl::GetValue()
|
||||
return str;
|
||||
}
|
||||
|
||||
bool CefDOMNodeImpl::SetValue(const CefString& value)
|
||||
{
|
||||
bool CefDOMNodeImpl::SetValue(const CefString& value) {
|
||||
if (!VerifyContext())
|
||||
return false;
|
||||
|
||||
@ -268,8 +256,7 @@ bool CefDOMNodeImpl::SetValue(const CefString& value)
|
||||
return node_.setNodeValue(string16(value));
|
||||
}
|
||||
|
||||
CefString CefDOMNodeImpl::GetAsMarkup()
|
||||
{
|
||||
CefString CefDOMNodeImpl::GetAsMarkup() {
|
||||
CefString str;
|
||||
if (!VerifyContext())
|
||||
return str;
|
||||
@ -281,56 +268,49 @@ CefString CefDOMNodeImpl::GetAsMarkup()
|
||||
return str;
|
||||
}
|
||||
|
||||
CefRefPtr<CefDOMDocument> CefDOMNodeImpl::GetDocument()
|
||||
{
|
||||
CefRefPtr<CefDOMDocument> CefDOMNodeImpl::GetDocument() {
|
||||
if (!VerifyContext())
|
||||
return NULL;
|
||||
|
||||
return document_.get();
|
||||
}
|
||||
|
||||
CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetParent()
|
||||
{
|
||||
CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetParent() {
|
||||
if (!VerifyContext())
|
||||
return NULL;
|
||||
|
||||
return document_->GetOrCreateNode(node_.parentNode());
|
||||
}
|
||||
|
||||
CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetPreviousSibling()
|
||||
{
|
||||
CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetPreviousSibling() {
|
||||
if (!VerifyContext())
|
||||
return NULL;
|
||||
|
||||
return document_->GetOrCreateNode(node_.previousSibling());
|
||||
}
|
||||
|
||||
CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetNextSibling()
|
||||
{
|
||||
CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetNextSibling() {
|
||||
if (!VerifyContext())
|
||||
return NULL;
|
||||
|
||||
return document_->GetOrCreateNode(node_.nextSibling());
|
||||
}
|
||||
|
||||
bool CefDOMNodeImpl::HasChildren()
|
||||
{
|
||||
bool CefDOMNodeImpl::HasChildren() {
|
||||
if (!VerifyContext())
|
||||
return false;
|
||||
|
||||
return node_.hasChildNodes();
|
||||
}
|
||||
|
||||
CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetFirstChild()
|
||||
{
|
||||
CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetFirstChild() {
|
||||
if (!VerifyContext())
|
||||
return NULL;
|
||||
|
||||
return document_->GetOrCreateNode(node_.firstChild());
|
||||
}
|
||||
|
||||
CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetLastChild()
|
||||
{
|
||||
CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetLastChild() {
|
||||
if (!VerifyContext())
|
||||
return NULL;
|
||||
|
||||
@ -339,8 +319,7 @@ CefRefPtr<CefDOMNode> CefDOMNodeImpl::GetLastChild()
|
||||
|
||||
void CefDOMNodeImpl::AddEventListener(const CefString& eventType,
|
||||
CefRefPtr<CefDOMEventListener> listener,
|
||||
bool useCapture)
|
||||
{
|
||||
bool useCapture) {
|
||||
if (!VerifyContext())
|
||||
return;
|
||||
|
||||
@ -350,8 +329,7 @@ void CefDOMNodeImpl::AddEventListener(const CefString& eventType,
|
||||
useCapture);
|
||||
}
|
||||
|
||||
CefString CefDOMNodeImpl::GetElementTagName()
|
||||
{
|
||||
CefString CefDOMNodeImpl::GetElementTagName() {
|
||||
CefString str;
|
||||
if (!VerifyContext())
|
||||
return str;
|
||||
@ -369,8 +347,7 @@ CefString CefDOMNodeImpl::GetElementTagName()
|
||||
return str;
|
||||
}
|
||||
|
||||
bool CefDOMNodeImpl::HasElementAttributes()
|
||||
{
|
||||
bool CefDOMNodeImpl::HasElementAttributes() {
|
||||
if (!VerifyContext())
|
||||
return false;
|
||||
|
||||
@ -383,8 +360,7 @@ bool CefDOMNodeImpl::HasElementAttributes()
|
||||
return (element.attributes().length() > 0);
|
||||
}
|
||||
|
||||
bool CefDOMNodeImpl::HasElementAttribute(const CefString& attrName)
|
||||
{
|
||||
bool CefDOMNodeImpl::HasElementAttribute(const CefString& attrName) {
|
||||
if (!VerifyContext())
|
||||
return false;
|
||||
|
||||
@ -397,8 +373,7 @@ bool CefDOMNodeImpl::HasElementAttribute(const CefString& attrName)
|
||||
return element.hasAttribute(string16(attrName));
|
||||
}
|
||||
|
||||
CefString CefDOMNodeImpl::GetElementAttribute(const CefString& attrName)
|
||||
{
|
||||
CefString CefDOMNodeImpl::GetElementAttribute(const CefString& attrName) {
|
||||
CefString str;
|
||||
if (!VerifyContext())
|
||||
return str;
|
||||
@ -416,8 +391,7 @@ CefString CefDOMNodeImpl::GetElementAttribute(const CefString& attrName)
|
||||
return str;
|
||||
}
|
||||
|
||||
void CefDOMNodeImpl::GetElementAttributes(AttributeMap& attrMap)
|
||||
{
|
||||
void CefDOMNodeImpl::GetElementAttributes(AttributeMap& attrMap) {
|
||||
if (!VerifyContext())
|
||||
return;
|
||||
|
||||
@ -449,8 +423,7 @@ void CefDOMNodeImpl::GetElementAttributes(AttributeMap& attrMap)
|
||||
}
|
||||
|
||||
bool CefDOMNodeImpl::SetElementAttribute(const CefString& attrName,
|
||||
const CefString& value)
|
||||
{
|
||||
const CefString& value) {
|
||||
if (!VerifyContext())
|
||||
return false;
|
||||
|
||||
@ -463,8 +436,7 @@ bool CefDOMNodeImpl::SetElementAttribute(const CefString& attrName,
|
||||
return element.setAttribute(string16(attrName), string16(value));
|
||||
}
|
||||
|
||||
CefString CefDOMNodeImpl::GetElementInnerText()
|
||||
{
|
||||
CefString CefDOMNodeImpl::GetElementInnerText() {
|
||||
CefString str;
|
||||
if (!VerifyContext())
|
||||
return str;
|
||||
@ -482,21 +454,19 @@ CefString CefDOMNodeImpl::GetElementInnerText()
|
||||
return str;
|
||||
}
|
||||
|
||||
void CefDOMNodeImpl::Detach()
|
||||
{
|
||||
void CefDOMNodeImpl::Detach() {
|
||||
document_ = NULL;
|
||||
node_.assign(WebNode());
|
||||
}
|
||||
|
||||
bool CefDOMNodeImpl::VerifyContext()
|
||||
{
|
||||
bool CefDOMNodeImpl::VerifyContext() {
|
||||
if (!document_.get()) {
|
||||
NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
if (!document_->VerifyContext())
|
||||
return false;
|
||||
if(node_.isNull()) {
|
||||
if (node_.isNull()) {
|
||||
NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "libcef/cef_thread.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/message_loop.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebWidget.h"
|
||||
@ -15,26 +16,18 @@ using WebKit::WebSize;
|
||||
|
||||
|
||||
void WebWidgetHost::ScheduleComposite() {
|
||||
if (has_invalidate_task_)
|
||||
if (invalidate_timer_.IsRunning())
|
||||
return;
|
||||
|
||||
has_invalidate_task_ = true;
|
||||
|
||||
// Try to paint at 60fps.
|
||||
static int64 kDesiredRate = 16;
|
||||
|
||||
base::TimeDelta delta = base::TimeTicks::Now() - paint_last_call_;
|
||||
int64 actualRate = delta.InMilliseconds();
|
||||
if (actualRate >= kDesiredRate) {
|
||||
// Can't keep up so run as fast as possible.
|
||||
MessageLoop::current()->PostTask(FROM_HERE,
|
||||
base::Bind(&WebWidgetHost::Invalidate, weak_factory_.GetWeakPtr()));
|
||||
} else {
|
||||
// Maintain the desired rate.
|
||||
MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
||||
base::Bind(&WebWidgetHost::Invalidate, weak_factory_.GetWeakPtr()),
|
||||
kDesiredRate - actualRate);
|
||||
}
|
||||
// Maintain the desired rate.
|
||||
invalidate_timer_.Start(
|
||||
FROM_HERE,
|
||||
base::TimeDelta::FromMilliseconds(kDesiredRate),
|
||||
this,
|
||||
&WebWidgetHost::Invalidate);
|
||||
}
|
||||
|
||||
void WebWidgetHost::ScheduleAnimation() {
|
||||
@ -105,9 +98,19 @@ gfx::PluginWindowHandle WebWidgetHost::GetWindowedPluginAt(int x, int y) {
|
||||
return gfx::kNullPluginWindow;
|
||||
}
|
||||
|
||||
void WebWidgetHost::SchedulePaintTimer() {
|
||||
if (layouting_ || paint_timer_.IsRunning())
|
||||
return;
|
||||
|
||||
paint_timer_.Start(
|
||||
FROM_HERE,
|
||||
base::TimeDelta::FromMilliseconds(0), // Fire immediately.
|
||||
this,
|
||||
&WebWidgetHost::DoPaint);
|
||||
}
|
||||
|
||||
void WebWidgetHost::DoPaint() {
|
||||
if (MessageLoop::current()->IsIdle()) {
|
||||
has_update_task_ = false;
|
||||
// Paint to the delegate.
|
||||
#if defined(OS_MACOSX)
|
||||
SkRegion region;
|
||||
@ -117,7 +120,6 @@ void WebWidgetHost::DoPaint() {
|
||||
#endif
|
||||
} else {
|
||||
// Try again later.
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE,
|
||||
base::Bind(&WebWidgetHost::DoPaint, weak_factory_.GetWeakPtr()));
|
||||
SchedulePaintTimer();
|
||||
}
|
||||
}
|
||||
|
@ -15,8 +15,8 @@
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/time.h"
|
||||
#include "base/timer.h"
|
||||
#include "skia/ext/platform_canvas.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h"
|
||||
@ -139,10 +139,6 @@ class WebWidgetHost {
|
||||
void MoveWindowedPlugin(const webkit::npapi::WebPluginGeometry& geometry);
|
||||
gfx::PluginWindowHandle GetWindowedPluginAt(int x, int y);
|
||||
|
||||
// If window rendering is disabled paint messages are generated after all
|
||||
// other pending messages have been processed.
|
||||
void DoPaint();
|
||||
|
||||
void set_popup(bool popup) { popup_ = popup; }
|
||||
bool popup() { return popup_; }
|
||||
|
||||
@ -151,6 +147,11 @@ class WebWidgetHost {
|
||||
protected:
|
||||
WebWidgetHost();
|
||||
|
||||
// If window rendering is disabled paint messages are generated after all
|
||||
// other pending messages have been processed.
|
||||
void SchedulePaintTimer();
|
||||
void DoPaint();
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Per-class wndproc. Returns true if the event should be swallowed.
|
||||
virtual bool WndProc(UINT message, WPARAM wparam, LPARAM lparam);
|
||||
@ -173,9 +174,8 @@ class WebWidgetHost {
|
||||
LRESULT OnImeEndComposition(UINT message, WPARAM wparam, LPARAM lparam,
|
||||
BOOL& handled);
|
||||
void OnInputLangChange(DWORD character_set, HKL input_language_id);
|
||||
void ImeUpdateTextInputState(WebKit::WebTextInputType type,
|
||||
const gfx::Rect& caret_rect);
|
||||
void UpdateInputMethod();
|
||||
void UpdateImeInputState();
|
||||
void ToggleImeTimer();
|
||||
#elif defined(OS_MACOSX)
|
||||
// These need to be called from a non-subclass, so they need to be public.
|
||||
public:
|
||||
@ -237,20 +237,18 @@ class WebWidgetHost {
|
||||
gfx::Rect paint_rect_;
|
||||
#endif
|
||||
|
||||
// True if an update task is pending when window rendering is disabled.
|
||||
bool has_update_task_;
|
||||
// Used to coalesce DidInvalidateRect() events into a single DoPaint() call.
|
||||
// Used when window rendering is disabled.
|
||||
base::OneShotTimer<WebWidgetHost> paint_timer_;
|
||||
|
||||
// True if an invalidate task is pending due to the Schedule*() methods.
|
||||
bool has_invalidate_task_;
|
||||
// Used to coalesce Schedule*() events into a single Invalidate() call.
|
||||
base::OneShotTimer<WebWidgetHost> invalidate_timer_;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// True if an update input method task is pending due to DidInvalidateRect().
|
||||
bool has_update_input_method_task_;
|
||||
// Used to call UpdateImeInputState() while IME is active.
|
||||
base::RepeatingTimer<WebWidgetHost> ime_timer_;
|
||||
#endif
|
||||
|
||||
// When the Paint() method last completed.
|
||||
base::TimeTicks paint_last_call_;
|
||||
|
||||
// Redraw rectangle requested by an explicit call to CefBrowser::Invalidate().
|
||||
gfx::Rect redraw_rect_;
|
||||
|
||||
@ -269,20 +267,16 @@ class WebWidgetHost {
|
||||
// Wrapper class for IME input.
|
||||
ui::ImeInput ime_input_;
|
||||
|
||||
// Represents whether or not this browser process is receiving status
|
||||
// messages about the focused edit control from a renderer process.
|
||||
// Represents whether or not this browser process is receiving status messages
|
||||
// about the focused edit control from a renderer process.
|
||||
bool ime_notification_;
|
||||
|
||||
// Represents whether or not the IME of a browser process is active.
|
||||
bool input_method_is_active_;
|
||||
|
||||
// Stores the current text input type received by ImeUpdateTextInputState()
|
||||
// method.
|
||||
// Stores the current text input type.
|
||||
WebKit::WebTextInputType text_input_type_;
|
||||
|
||||
// Stores the current caret bounds of input focus.
|
||||
WebKit::WebRect caret_bounds_;
|
||||
#endif
|
||||
#endif // OS_WIN
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
int mouse_modifiers_;
|
||||
@ -299,9 +293,6 @@ class WebWidgetHost {
|
||||
|
||||
bool painting_;
|
||||
bool layouting_;
|
||||
|
||||
private:
|
||||
base::WeakPtrFactory<WebWidgetHost> weak_factory_;
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_WEBWIDGET_HOST_H_
|
||||
|
@ -309,10 +309,7 @@ WebWidgetHost::WebWidgetHost()
|
||||
webwidget_(NULL),
|
||||
canvas_w_(0),
|
||||
canvas_h_(0),
|
||||
popup_(false),
|
||||
has_update_task_(false),
|
||||
has_invalidate_task_(false),
|
||||
ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
|
||||
popup_(false) {
|
||||
set_painting(false);
|
||||
}
|
||||
|
||||
@ -403,11 +400,6 @@ void WebWidgetHost::Paint() {
|
||||
cairo_destroy(cairo_drawable);
|
||||
|
||||
gdk_window_end_paint(window);
|
||||
|
||||
// Used with scheduled invalidation to maintain a consistent frame rate.
|
||||
paint_last_call_ = base::TimeTicks::Now();
|
||||
if (has_invalidate_task_)
|
||||
has_invalidate_task_ = false;
|
||||
}
|
||||
|
||||
void WebWidgetHost::SetTooltipText(const CefString& tooltip_text) {
|
||||
|
@ -82,12 +82,9 @@ WebWidgetHost::WebWidgetHost()
|
||||
canvas_w_(0),
|
||||
canvas_h_(0),
|
||||
popup_(false),
|
||||
has_update_task_(false),
|
||||
has_invalidate_task_(false),
|
||||
mouse_modifiers_(0),
|
||||
painting_(false),
|
||||
layouting_(false),
|
||||
ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
|
||||
layouting_(false) {
|
||||
set_painting(false);
|
||||
}
|
||||
|
||||
@ -100,24 +97,17 @@ void WebWidgetHost::DidInvalidateRect(const gfx::Rect& damaged_rect) {
|
||||
const gfx::Rect client_rect(width, height);
|
||||
|
||||
const gfx::Rect damaged_rect_in_client = client_rect.Intersect(damaged_rect);
|
||||
if (damaged_rect_in_client.IsEmpty())
|
||||
return;
|
||||
|
||||
if (!damaged_rect_in_client.IsEmpty()) {
|
||||
UpdatePaintRect(damaged_rect_in_client);
|
||||
UpdatePaintRect(damaged_rect_in_client);
|
||||
|
||||
if (view_) {
|
||||
NSRect cocoa_rect = NSRectFromCGRect(damaged_rect_in_client.ToCGRect());
|
||||
cocoa_rect.origin.y = client_rect.height() - NSMaxY(cocoa_rect);
|
||||
[view_ setNeedsDisplayInRect:cocoa_rect];
|
||||
} else {
|
||||
// Don't post a paint task if this invalidation occurred during layout or
|
||||
// if a paint task is already pending. Paint() will be called by
|
||||
// DoPaint().
|
||||
if (!layouting_ && !has_update_task_) {
|
||||
has_update_task_ = true;
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE,
|
||||
base::Bind(&WebWidgetHost::DoPaint, weak_factory_.GetWeakPtr()));
|
||||
}
|
||||
}
|
||||
if (view_) {
|
||||
NSRect cocoa_rect = NSRectFromCGRect(damaged_rect_in_client.ToCGRect());
|
||||
cocoa_rect.origin.y = client_rect.height() - NSMaxY(cocoa_rect);
|
||||
[view_ setNeedsDisplayInRect:cocoa_rect];
|
||||
} else {
|
||||
SchedulePaintTimer();
|
||||
}
|
||||
}
|
||||
|
||||
@ -309,6 +299,9 @@ void WebWidgetHost::Paint(SkRegion& update_rgn) {
|
||||
skia::DrawToNativeContext(canvas_.get(), context, x, y, ©_rect);
|
||||
}
|
||||
} else {
|
||||
if (damaged_rgn.isEmpty())
|
||||
return;
|
||||
|
||||
// Paint to the delegate.
|
||||
DCHECK(paint_delegate_);
|
||||
const SkBitmap& bitmap = canvas_->getDevice()->accessBitmap(false);
|
||||
@ -325,20 +318,14 @@ void WebWidgetHost::Paint(SkRegion& update_rgn) {
|
||||
|
||||
paint_delegate_->Paint(popup_, damaged_rects, pixels);
|
||||
}
|
||||
|
||||
// Used with scheduled invalidation to maintain a consistent frame rate.
|
||||
paint_last_call_ = base::TimeTicks::Now();
|
||||
if (has_invalidate_task_)
|
||||
has_invalidate_task_ = false;
|
||||
}
|
||||
|
||||
void WebWidgetHost::Invalidate() {
|
||||
if (view_) {
|
||||
[view_ setNeedsDisplay:YES];
|
||||
} else if (webwidget_) {
|
||||
WebSize size = webwidget_->size();
|
||||
InvalidateRect(gfx::Rect(0, 0, size.width, size.height));
|
||||
}
|
||||
if (!webwidget_)
|
||||
return;
|
||||
|
||||
WebSize size = webwidget_->size();
|
||||
InvalidateRect(gfx::Rect(0, 0, size.width, size.height));
|
||||
}
|
||||
|
||||
void WebWidgetHost::SetTooltipText(const CefString& tooltip_text) {
|
||||
@ -349,17 +336,7 @@ void WebWidgetHost::InvalidateRect(const gfx::Rect& rect) {
|
||||
if (rect.IsEmpty())
|
||||
return;
|
||||
|
||||
if (!view_) {
|
||||
// Don't post a paint task if this invalidation occurred during layout or if
|
||||
// a paint task is already pending. Paint() will be called by DoPaint().
|
||||
if (!layouting_ && !has_update_task_) {
|
||||
has_update_task_ = true;
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE,
|
||||
base::Bind(&WebWidgetHost::DoPaint, weak_factory_.GetWeakPtr()));
|
||||
}
|
||||
} else {
|
||||
NOTIMPLEMENTED();
|
||||
}
|
||||
DidInvalidateRect(rect);
|
||||
}
|
||||
|
||||
bool WebWidgetHost::GetImage(int width, int height, void* rgba_buffer) {
|
||||
|
@ -102,7 +102,6 @@ WebWidgetHost* WebWidgetHost::Create(HWND parent_view,
|
||||
0, 0, 0, 0,
|
||||
parent_view, NULL, GetModuleHandle(NULL),
|
||||
NULL);
|
||||
|
||||
ui::SetWindowUserData(host->view_, host);
|
||||
} else {
|
||||
host->paint_delegate_ = paint_delegate;
|
||||
@ -268,22 +267,21 @@ LRESULT CALLBACK WebWidgetHost::WndProc(HWND hwnd, UINT message, WPARAM wparam,
|
||||
}
|
||||
|
||||
void WebWidgetHost::DidInvalidateRect(const gfx::Rect& damaged_rect) {
|
||||
DLOG_IF(WARNING, painting_) << "unexpected invalidation while painting";
|
||||
int width, height;
|
||||
GetSize(width, height);
|
||||
const gfx::Rect client_rect(width, height);
|
||||
|
||||
// If this invalidate overlaps with a pending scroll then we have to downgrade
|
||||
// to invalidating the scroll rect.
|
||||
UpdatePaintRect(damaged_rect);
|
||||
InvalidateRect(damaged_rect);
|
||||
const gfx::Rect damaged_rect_in_client = client_rect.Intersect(damaged_rect);
|
||||
if (damaged_rect_in_client.IsEmpty())
|
||||
return;
|
||||
|
||||
if (!popup_ && view_ && webwidget_ && input_method_is_active_ &&
|
||||
!has_update_input_method_task_) {
|
||||
has_update_input_method_task_ = true;
|
||||
UpdatePaintRect(damaged_rect_in_client);
|
||||
|
||||
// Call UpdateInputMethod() approximately every 100ms.
|
||||
CefThread::PostDelayedTask(CefThread::UI, FROM_HERE,
|
||||
base::Bind(&WebWidgetHost::UpdateInputMethod,
|
||||
weak_factory_.GetWeakPtr()),
|
||||
100);
|
||||
if (view_) {
|
||||
RECT r = damaged_rect_in_client.ToRECT();
|
||||
::InvalidateRect(view_, &r, FALSE);
|
||||
} else {
|
||||
SchedulePaintTimer();
|
||||
}
|
||||
}
|
||||
|
||||
@ -314,7 +312,8 @@ void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
|
||||
|
||||
// Invalidate the scroll rect. It will be drawn from the canvas bitmap on the
|
||||
// next WM_PAINT call.
|
||||
InvalidateRect(clip_rect);
|
||||
RECT r = clip_rect.ToRECT();
|
||||
::InvalidateRect(view_, &r, FALSE);
|
||||
}
|
||||
|
||||
void WebWidgetHost::Invalidate() {
|
||||
@ -339,16 +338,11 @@ WebWidgetHost::WebWidgetHost()
|
||||
canvas_h_(0),
|
||||
popup_(false),
|
||||
track_mouse_leave_(false),
|
||||
has_update_task_(false),
|
||||
has_invalidate_task_(false),
|
||||
has_update_input_method_task_(false),
|
||||
tooltip_view_(NULL),
|
||||
tooltip_showing_(false),
|
||||
ime_notification_(false),
|
||||
input_method_is_active_(false),
|
||||
layouting_(false),
|
||||
text_input_type_(WebKit::WebTextInputTypeNone),
|
||||
ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
|
||||
text_input_type_(WebKit::WebTextInputTypeNone) {
|
||||
set_painting(false);
|
||||
}
|
||||
|
||||
@ -515,6 +509,9 @@ void WebWidgetHost::Paint() {
|
||||
// Draw children
|
||||
UpdateWindow(view_);
|
||||
} else {
|
||||
if (damaged_rgn.isEmpty())
|
||||
return;
|
||||
|
||||
// Paint to the delegate.
|
||||
DCHECK(paint_delegate_);
|
||||
const SkBitmap& bitmap = canvas_->getDevice()->accessBitmap(false);
|
||||
@ -531,30 +528,13 @@ void WebWidgetHost::Paint() {
|
||||
|
||||
paint_delegate_->Paint(popup_, damaged_rects, pixels);
|
||||
}
|
||||
|
||||
// Used with scheduled invalidation to maintain a consistent frame rate.
|
||||
paint_last_call_ = base::TimeTicks::Now();
|
||||
if (has_invalidate_task_)
|
||||
has_invalidate_task_ = false;
|
||||
}
|
||||
|
||||
void WebWidgetHost::InvalidateRect(const gfx::Rect& rect) {
|
||||
if (rect.IsEmpty())
|
||||
return;
|
||||
|
||||
if (view_) {
|
||||
// Let the window handle painting.
|
||||
RECT r = rect.ToRECT();
|
||||
::InvalidateRect(view_, &r, FALSE);
|
||||
} else {
|
||||
// Don't post a paint task if this invalidation occurred during layout or if
|
||||
// a paint task is already pending. Paint() will be called by DoPaint().
|
||||
if (!layouting_ && !has_update_task_) {
|
||||
has_update_task_ = true;
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE,
|
||||
base::Bind(&WebWidgetHost::DoPaint, weak_factory_.GetWeakPtr()));
|
||||
}
|
||||
}
|
||||
DidInvalidateRect(rect);
|
||||
}
|
||||
|
||||
bool WebWidgetHost::GetImage(int width, int height, void* buffer) {
|
||||
@ -947,26 +927,22 @@ LRESULT WebWidgetHost::OnImeSetContext(UINT message, WPARAM wparam,
|
||||
if (!webwidget_)
|
||||
return 0;
|
||||
|
||||
// We need status messages about the focused input control from a
|
||||
// renderer process when:
|
||||
// We need to start the IME timer when:
|
||||
// * the current input context has IMEs, and;
|
||||
// * an application is activated.
|
||||
// This seems to tell we should also check if the current input context has
|
||||
// IMEs before sending a request, however, this WM_IME_SETCONTEXT is
|
||||
// fortunately sent to an application only while the input context has IMEs.
|
||||
// Therefore, we just start/stop status messages according to the activation
|
||||
// This seems to indicate that we should also check if the current input
|
||||
// context has IMEs before starting the timer, however, this WM_IME_SETCONTEXT
|
||||
// is fortunately sent to an application only while the input context has
|
||||
// IMEs. Therefore, we just start/stop the timer according to the activation
|
||||
// status of this application without checks.
|
||||
bool activated = (wparam == TRUE);
|
||||
if (webwidget_) {
|
||||
input_method_is_active_ = activated;
|
||||
ime_notification_ = activated;
|
||||
}
|
||||
|
||||
ime_notification_ = (wparam == TRUE);
|
||||
if (ime_notification_)
|
||||
ime_input_.CreateImeWindow(view_);
|
||||
|
||||
ime_input_.CleanupComposition(view_);
|
||||
ime_input_.SetImeWindowStyle(view_, message, wparam, lparam, &handled);
|
||||
|
||||
ToggleImeTimer();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1000,7 +976,7 @@ LRESULT WebWidgetHost::OnImeComposition(UINT message, WPARAM wparam,
|
||||
ui_CompositionUnderline__WebKit_WebCompositionUnderline_diff);
|
||||
|
||||
// Retrieve the result string and its attributes of the ongoing composition
|
||||
// and send it to a renderer process.
|
||||
// and send to WebKit.
|
||||
ui::CompositionText composition;
|
||||
if (ime_input_.GetResult(view_, lparam, &composition.text)) {
|
||||
webwidget_->setComposition(composition.text,
|
||||
@ -1014,14 +990,12 @@ LRESULT WebWidgetHost::OnImeComposition(UINT message, WPARAM wparam,
|
||||
// by the start of another composition.
|
||||
}
|
||||
// Retrieve the composition string and its attributes of the ongoing
|
||||
// composition and send it to a renderer process.
|
||||
// composition and send to WebKit.
|
||||
if (ime_input_.GetComposition(view_, lparam, &composition)) {
|
||||
// TODO(suzhe): due to a bug of webkit, we can't use selection range with
|
||||
// composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
|
||||
composition.selection = ui::Range(composition.selection.end());
|
||||
|
||||
// TODO(suzhe): convert both renderer_host and renderer to use
|
||||
// ui::CompositionText.
|
||||
const std::vector<WebKit::WebCompositionUnderline>& underlines =
|
||||
reinterpret_cast<const std::vector<WebKit::WebCompositionUnderline>&>(
|
||||
composition.underlines);
|
||||
@ -1043,8 +1017,8 @@ LRESULT WebWidgetHost::OnImeEndComposition(UINT message, WPARAM wparam,
|
||||
if (ime_input_.is_composing()) {
|
||||
// A composition has been ended while there is an ongoing composition,
|
||||
// i.e. the ongoing composition has been canceled.
|
||||
// We need to reset the composition status both of the ImeInput object and
|
||||
// of the renderer process.
|
||||
// Reset the composition status of both of the ImeInput object and the
|
||||
// window.
|
||||
ime_input_.CancelIME(view_);
|
||||
ime_input_.ResetComposition(view_);
|
||||
}
|
||||
@ -1056,44 +1030,32 @@ LRESULT WebWidgetHost::OnImeEndComposition(UINT message, WPARAM wparam,
|
||||
|
||||
void WebWidgetHost::OnInputLangChange(DWORD character_set,
|
||||
HKL input_language_id) {
|
||||
if (!webwidget_)
|
||||
return;
|
||||
|
||||
// Send the given Locale ID to the ImeInput object and retrieves whether
|
||||
// or not the current input context has IMEs.
|
||||
// If the current input context has IMEs, a browser process has to send a
|
||||
// request to a renderer process that it needs status messages about
|
||||
// the focused edit control from the renderer process.
|
||||
// On the other hand, if the current input context does not have IMEs, the
|
||||
// browser process also has to send a request to the renderer process that
|
||||
// it does not need the status messages any longer.
|
||||
// To minimize the number of this notification request, we should check if
|
||||
// the browser process is actually retrieving the status messages (this
|
||||
// state is stored in ime_notification_) and send a request only if the
|
||||
// browser process has to update this status, its details are listed below:
|
||||
// * If a browser process is not retrieving the status messages,
|
||||
// (i.e. ime_notification_ == false),
|
||||
// send this request only if the input context does have IMEs,
|
||||
// (i.e. ime_status == true);
|
||||
// When it successfully sends the request, toggle its notification status,
|
||||
// (i.e.ime_notification_ = !ime_notification_ = true).
|
||||
// * If a browser process is retrieving the status messages
|
||||
// (i.e. ime_notification_ == true),
|
||||
// send this request only if the input context does not have IMEs,
|
||||
// (i.e. ime_status == false).
|
||||
// When it successfully sends the request, toggle its notification status,
|
||||
// (i.e.ime_notification_ = !ime_notification_ = false).
|
||||
// To analyze the above actions, we can optimize them into the ones
|
||||
// listed below:
|
||||
// 1 Sending a request only if ime_status_ != ime_notification_, and;
|
||||
// 2 Copying ime_status to ime_notification_ if it sends the request
|
||||
// successfully (because Action 1 shows ime_status = !ime_notification_.)
|
||||
// or not the current input context has IMEs. Toggle the timer based on
|
||||
// whether the current input context has IMEs.
|
||||
bool ime_status = ime_input_.SetInputLanguage();
|
||||
if (ime_status != ime_notification_ && webwidget_) {
|
||||
input_method_is_active_ = ime_status;
|
||||
if (ime_status != ime_notification_) {
|
||||
ime_notification_ = ime_status;
|
||||
ToggleImeTimer();
|
||||
}
|
||||
}
|
||||
|
||||
void WebWidgetHost::ImeUpdateTextInputState(WebKit::WebTextInputType type,
|
||||
const gfx::Rect& caret_rect) {
|
||||
void WebWidgetHost::UpdateImeInputState() {
|
||||
if (!webwidget_ || !ime_notification_) {
|
||||
ToggleImeTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
WebKit::WebTextInputType type = webwidget_->textInputType();
|
||||
WebKit::WebRect caret_bounds;
|
||||
|
||||
WebKit::WebRect startRect, endRect;
|
||||
if (webwidget_->selectionBounds(startRect, endRect))
|
||||
caret_bounds = endRect;
|
||||
|
||||
if (text_input_type_ != type) {
|
||||
text_input_type_ = type;
|
||||
if (type == WebKit::WebTextInputTypeText)
|
||||
@ -1102,31 +1064,24 @@ void WebWidgetHost::ImeUpdateTextInputState(WebKit::WebTextInputType type,
|
||||
ime_input_.DisableIME(view_);
|
||||
}
|
||||
|
||||
// Only update caret position if the input method is enabled.
|
||||
if (type == WebKit::WebTextInputTypeText)
|
||||
ime_input_.UpdateCaretRect(view_, caret_rect);
|
||||
}
|
||||
|
||||
void WebWidgetHost::UpdateInputMethod() {
|
||||
REQUIRE_UIT();
|
||||
|
||||
has_update_input_method_task_ = false;
|
||||
|
||||
if (!input_method_is_active_ || !webwidget_)
|
||||
return;
|
||||
|
||||
WebKit::WebTextInputType new_type = webwidget_->textInputType();
|
||||
WebKit::WebRect new_caret_bounds;
|
||||
|
||||
WebKit::WebRect startRect, endRect;
|
||||
if (webwidget_->selectionBounds(startRect, endRect))
|
||||
new_caret_bounds = endRect;
|
||||
|
||||
// Only sends text input type and caret bounds to the browser process if they
|
||||
// are changed.
|
||||
if (text_input_type_ != new_type || caret_bounds_ != new_caret_bounds) {
|
||||
text_input_type_ = new_type;
|
||||
caret_bounds_ = new_caret_bounds;
|
||||
ImeUpdateTextInputState(new_type, new_caret_bounds);
|
||||
// Only update caret position if the input method is enabled and the caret
|
||||
// position has changed.
|
||||
if (type == WebKit::WebTextInputTypeText && caret_bounds != caret_bounds_) {
|
||||
caret_bounds_ = caret_bounds;
|
||||
ime_input_.UpdateCaretRect(view_, caret_bounds);
|
||||
}
|
||||
}
|
||||
|
||||
void WebWidgetHost::ToggleImeTimer() {
|
||||
if (view_ && !popup_ && ime_notification_ && webwidget_) {
|
||||
if (!ime_timer_.IsRunning()) {
|
||||
ime_timer_.Start(
|
||||
FROM_HERE,
|
||||
base::TimeDelta::FromMilliseconds(200),
|
||||
this,
|
||||
&WebWidgetHost::UpdateImeInputState);
|
||||
}
|
||||
} else if (ime_timer_.IsRunning()) {
|
||||
ime_timer_.Stop();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user