- Add find in page support.

- Fix loading of resources from libcef.dll (Issue 76).
- Fix leak of CefMessageLoopForUI object when not in multi threaded message loop mode.

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@88 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt
2010-07-19 22:19:30 +00:00
parent ba08f77938
commit 0e29c2e840
23 changed files with 549 additions and 99 deletions

View File

@ -242,6 +242,50 @@ protected:
}; };
// Class representing a rectangle.
class CefRect : public cef_rect_t
{
public:
CefRect()
{
x = y = width = height = 0;
}
CefRect(int x, int y, int width, int height)
{
set(x, y, width, height);
}
CefRect(const cef_rect_t& r)
{
set(r.x, r.y, r.width, r.height);
}
CefRect& operator=(const cef_rect_t& r)
{
x = r.x;
y = r.y;
width = r.width;
height = r.height;
return *this;
}
bool isEmpty() const { return width <= 0 || height <= 0; }
void set(int x, int y, int width, int height)
{
this->x = x, this->y = y, this->width = width, this->height = height;
}
};
inline bool operator==(const CefRect& a, const CefRect& b)
{
return a.x == b.x && a.y == b.y && a.width == b.width && a.height == b.height;
}
inline bool operator!=(const CefRect& a, const CefRect& b)
{
return !(a == b);
}
// Class used to represent a browser window. All methods exposed by this class // Class used to represent a browser window. All methods exposed by this class
// should be thread safe. // should be thread safe.
/*--cef(source=library)--*/ /*--cef(source=library)--*/
@ -319,6 +363,19 @@ public:
// Returns the names of all existing frames. // Returns the names of all existing frames.
/*--cef()--*/ /*--cef()--*/
virtual void GetFrameNames(std::vector<std::wstring>& names) =0; virtual void GetFrameNames(std::vector<std::wstring>& names) =0;
// Search for |searchText|. |identifier| can be used to have multiple searches
// running simultaniously. |forward| indicates whether to search forward or
// backward within the page. |matchCase| indicates whether the search should
// be case-sensitive. |findNext| indicates whether this is the first request
// or a follow-up.
/*--cef()--*/
virtual void Find(int identifier, const std::wstring& searchText,
bool forward, bool matchCase, bool findNext) =0;
// Cancel all searches that are currently going on.
/*--cef()--*/
virtual void StopFinding(bool clearSelection) =0;
}; };
@ -637,6 +694,18 @@ public:
virtual RetVal HandleConsoleMessage(CefRefPtr<CefBrowser> browser, virtual RetVal HandleConsoleMessage(CefRefPtr<CefBrowser> browser,
const std::wstring& message, const std::wstring& message,
const std::wstring& source, int line) =0; const std::wstring& source, int line) =0;
// Called to report find results returned by CefBrowser::Find(). |identifer|
// is the identifier passed to CefBrowser::Find(), |count| is the number of
// matches currently identified, |selectionRect| is the location of where the
// match was found (in window coordinates), |activeMatchOrdinal| is the
// current position in the search results, and |finalUpdate| is true if this
// is the last find notification. The return value is currently ignored.
/*--cef()--*/
virtual RetVal HandleFindResult(CefRefPtr<CefBrowser> browser,
int identifier, int count,
const CefRect& selectionRect,
int activeMatchOrdinal, bool finalUpdate) =0;
}; };

View File

@ -213,6 +213,18 @@ typedef struct _cef_browser_t
void (CEF_CALLBACK *get_frame_names)(struct _cef_browser_t* self, void (CEF_CALLBACK *get_frame_names)(struct _cef_browser_t* self,
cef_string_list_t names); cef_string_list_t names);
// Search for |searchText|. |identifier| can be used to have multiple searches
// running simultaniously. |forward| indicates whether to search forward or
// backward within the page. |matchCase| indicates whether the search should
// be case-sensitive. |findNext| indicates whether this is the first request
// or a follow-up.
void (CEF_CALLBACK *find)(struct _cef_browser_t* self, int identifier,
const wchar_t* searchText, int forward, int matchCase, int findNext);
// Cancel all searches that are currently going on.
void (CEF_CALLBACK *stop_finding)(struct _cef_browser_t* self,
int clearSelection);
} cef_browser_t; } cef_browser_t;
@ -495,6 +507,18 @@ typedef struct _cef_handler_t
struct _cef_handler_t* self, struct _cef_browser_t* browser, struct _cef_handler_t* self, struct _cef_browser_t* browser,
const wchar_t* message, const wchar_t* source, int line); const wchar_t* message, const wchar_t* source, int line);
// Called to report find results returned by cef_browser_t::find().
// |identifer| is the identifier passed to cef_browser_t::find(), |count| is
// the number of matches currently identified, |selectionRect| is the location
// of where the match was found (in window coordinates), |activeMatchOrdinal|
// is the current position in the search results, and |finalUpdate| is true
// (1) if this is the last find notification. The return value is currently
// ignored.
enum cef_retval_t (CEF_CALLBACK *handle_find_result)(
struct _cef_handler_t* self, struct _cef_browser_t* browser,
int identifier, int count, const cef_rect_t* selectionRect,
int activeMatchOrdinal, int finalUpdate);
} cef_handler_t; } cef_handler_t;

View File

@ -220,6 +220,15 @@ enum cef_handler_keyevent_modifiers_t
KEY_META = 1 << 3 KEY_META = 1 << 3
}; };
// Structure representing a rectangle.
typedef struct _cef_rect_t
{
int x;
int y;
int width;
int height;
} cef_rect_t;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -9,17 +9,29 @@
#include "request_impl.h" #include "request_impl.h"
#include "base/utf_string_conversions.h" #include "base/utf_string_conversions.h"
#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" #include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/WebKit/chromium/public/WebHTTPBody.h" #include "third_party/WebKit/WebKit/chromium/public/WebHTTPBody.h"
#include "third_party/WebKit/WebKit/chromium/public/WebPlugin.h"
#include "third_party/WebKit/WebKit/chromium/public/WebPluginDocument.h"
#include "third_party/WebKit/WebKit/chromium/public/WebRange.h"
#include "third_party/WebKit/WebKit/chromium/public/WebRect.h"
#include "third_party/WebKit/WebKit/chromium/public/WebScriptSource.h" #include "third_party/WebKit/WebKit/chromium/public/WebScriptSource.h"
#include "third_party/WebKit/WebKit/chromium/public/WebString.h" #include "third_party/WebKit/WebKit/chromium/public/WebString.h"
#include "third_party/WebKit/WebKit/chromium/public/WebURL.h" #include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
#include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h" #include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h"
#include "third_party/WebKit/WebKit/chromium/public/WebView.h" #include "third_party/WebKit/WebKit/chromium/public/WebView.h"
#include "webkit/glue/glue_serialize.h" #include "webkit/glue/glue_serialize.h"
#include "webkit/glue/plugins/webplugin_delegate.h"
#include "webkit/glue/plugins/webplugin_impl.h"
using WebKit::WebDocument;
using WebKit::WebFrame; using WebKit::WebFrame;
using WebKit::WebHTTPBody; using WebKit::WebHTTPBody;
using WebKit::WebPlugin;
using WebKit::WebPluginDocument;
using WebKit::WebRange;
using WebKit::WebRect;
using WebKit::WebScriptSource; using WebKit::WebScriptSource;
using WebKit::WebString; using WebKit::WebString;
using WebKit::WebURL; using WebKit::WebURL;
@ -121,6 +133,26 @@ void CefBrowserImpl::GetFrameNames(std::vector<std::wstring>& names)
} while (it != main_frame); } while (it != main_frame);
} }
void CefBrowserImpl::Find(int identifier, const std::wstring& searchText,
bool forward, bool matchCase, bool findNext)
{
WebKit::WebFindOptions options;
options.forward = forward;
options.matchCase = matchCase;
options.findNext = findNext;
// Execute the request on the UI thread.
PostTask(FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_Find, identifier, searchText, options));
}
void CefBrowserImpl::StopFinding(bool clearSelection)
{
// Execute the request on the UI thread.
PostTask(FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_StopFinding, clearSelection));
}
CefRefPtr<CefFrame> CefBrowserImpl::GetCefFrame(WebFrame* frame) CefRefPtr<CefFrame> CefBrowserImpl::GetCefFrame(WebFrame* frame)
{ {
CefRefPtr<CefFrame> cef_frame; CefRefPtr<CefFrame> cef_frame;
@ -676,6 +708,169 @@ void CefBrowserImpl::UIT_HandleAction(CefHandler::MenuId menuId,
frame->Release(); frame->Release();
} }
void CefBrowserImpl::UIT_Find(int identifier, const std::wstring& search_text,
const WebKit::WebFindOptions& options)
{
WebFrame* main_frame = GetWebView()->mainFrame();
if (main_frame->document().isPluginDocument()) {
WebPlugin* plugin = main_frame->document().to<WebPluginDocument>().plugin();
webkit_glue::WebPluginDelegate* delegate =
static_cast<webkit_glue::WebPluginImpl*>(plugin)->delegate();
if (options.findNext) {
// Just navigate back/forward.
delegate->SelectFindResult(options.forward);
} else {
if (delegate->SupportsFind()) {
delegate->StartFind(UTF16ToUTF8(search_text),
options.matchCase,
identifier);
} else {
// No find results.
UIT_NotifyFindStatus(identifier, 0, gfx::Rect(), 0, true);
}
}
return;
}
WebFrame* frame_after_main = main_frame->traverseNext(true);
WebFrame* focused_frame = GetWebView()->focusedFrame();
WebFrame* search_frame = focused_frame; // start searching focused frame.
bool multi_frame = (frame_after_main != main_frame);
// If we have multiple frames, we don't want to wrap the search within the
// frame, so we check here if we only have main_frame in the chain.
bool wrap_within_frame = !multi_frame;
WebRect selection_rect;
bool result = false;
// If something is selected when we start searching it means we cannot just
// increment the current match ordinal; we need to re-generate it.
WebRange current_selection = focused_frame->selectionRange();
do {
result = search_frame->find(
identifier, search_text, options, wrap_within_frame, &selection_rect);
if (!result) {
// don't leave text selected as you move to the next frame.
search_frame->executeCommand(WebString::fromUTF8("Unselect"));
// Find the next frame, but skip the invisible ones.
do {
// What is the next frame to search? (we might be going backwards). Note
// that we specify wrap=true so that search_frame never becomes NULL.
search_frame = options.forward ?
search_frame->traverseNext(true) :
search_frame->traversePrevious(true);
} while (!search_frame->hasVisibleContent() &&
search_frame != focused_frame);
// Make sure selection doesn't affect the search operation in new frame.
search_frame->executeCommand(WebString::fromUTF8("Unselect"));
// If we have multiple frames and we have wrapped back around to the
// focused frame, we need to search it once more allowing wrap within
// the frame, otherwise it will report 'no match' if the focused frame has
// reported matches, but no frames after the focused_frame contain a
// match for the search word(s).
if (multi_frame && search_frame == focused_frame) {
result = search_frame->find(
identifier, search_text, options, true, // Force wrapping.
&selection_rect);
}
}
GetWebView()->setFocusedFrame(search_frame);
} while (!result && search_frame != focused_frame);
if (options.findNext && current_selection.isNull()) {
// Force the main_frame to report the actual count.
main_frame->increaseMatchCount(0, identifier);
} else {
// If nothing is found, set result to "0 of 0", otherwise, set it to
// "-1 of 1" to indicate that we found at least one item, but we don't know
// yet what is active.
int ordinal = result ? -1 : 0; // -1 here means, we might know more later.
int match_count = result ? 1 : 0; // 1 here means possibly more coming.
// If we find no matches then this will be our last status update.
// Otherwise the scoping effort will send more results.
bool final_status_update = !result;
// Send the search result.
UIT_NotifyFindStatus(identifier, match_count, selection_rect, ordinal,
final_status_update);
// Scoping effort begins, starting with the mainframe.
search_frame = main_frame;
main_frame->resetMatchCount();
do {
// Cancel all old scoping requests before starting a new one.
search_frame->cancelPendingScopingEffort();
// We don't start another scoping effort unless at least one match has
// been found.
if (result) {
// Start new scoping request. If the scoping function determines that it
// needs to scope, it will defer until later.
search_frame->scopeStringMatches(identifier,
search_text,
options,
true); // reset the tickmarks
}
// Iterate to the next frame. The frame will not necessarily scope, for
// example if it is not visible.
search_frame = search_frame->traverseNext(true);
} while (search_frame != main_frame);
}
}
void CefBrowserImpl::UIT_StopFinding(bool clear_selection)
{
WebView* view = GetWebView();
if (!view)
return;
WebDocument doc = view->mainFrame()->document();
if (doc.isPluginDocument()) {
WebPlugin* plugin = view->mainFrame()->document().
to<WebPluginDocument>().plugin();
webkit_glue::WebPluginDelegate* delegate =
static_cast<webkit_glue::WebPluginImpl*>(plugin)->delegate();
delegate->StopFind();
return;
}
if (clear_selection)
view->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect"));
WebFrame* frame = view->mainFrame();
while (frame) {
frame->stopFinding(clear_selection);
frame = frame->traverseNext(false);
}
}
void CefBrowserImpl::UIT_NotifyFindStatus(int identifier, int count,
const WebKit::WebRect& selection_rect,
int active_match_ordinal,
bool final_update)
{
if(handler_.get())
{
CefRect rect(selection_rect.x, selection_rect.y, selection_rect.width,
selection_rect.height);
handler_->HandleFindResult(this, identifier, count, rect,
active_match_ordinal, final_update);
}
}
// CefFrameImpl // CefFrameImpl

View File

@ -16,6 +16,8 @@
#include "printing/win_printing_context.h" #include "printing/win_printing_context.h"
#endif #endif
#include "third_party/WebKit/WebKit/chromium/public/WebFindOptions.h"
namespace WebKit { namespace WebKit {
class WebView; class WebView;
} }
@ -52,7 +54,10 @@ public:
virtual CefRefPtr<CefFrame> GetFocusedFrame(); virtual CefRefPtr<CefFrame> GetFocusedFrame();
virtual CefRefPtr<CefFrame> GetFrame(const std::wstring& name); virtual CefRefPtr<CefFrame> GetFrame(const std::wstring& name);
virtual void GetFrameNames(std::vector<std::wstring>& names); virtual void GetFrameNames(std::vector<std::wstring>& names);
virtual void Find(int identifier, const std::wstring& searchText,
bool forward, bool matchCase, bool findNext);
virtual void StopFinding(bool clearSelection);
// CefFrames are light-weight objects managed by the browser and loosely // CefFrames are light-weight objects managed by the browser and loosely
// coupled to a WebFrame object by name. If a CefFrame object does not // coupled to a WebFrame object by name. If a CefFrame object does not
// already exist for the specified WebFrame one will be created. There is no // already exist for the specified WebFrame one will be created. There is no
@ -91,7 +96,7 @@ public:
const std::wstring& jsCode, const std::wstring& jsCode,
const std::wstring& scriptUrl, const std::wstring& scriptUrl,
int startLine); int startLine);
virtual std::wstring GetURL(CefRefPtr<CefFrame> frame); std::wstring GetURL(CefRefPtr<CefFrame> frame);
WebKit::WebView* GetWebView() const { WebKit::WebView* GetWebView() const {
return webviewhost_.get() ? webviewhost_->webview() : NULL; return webviewhost_.get() ? webviewhost_->webview() : NULL;
@ -212,6 +217,13 @@ public:
void UIT_SetUniqueID(int id) { unique_id_ = id; } void UIT_SetUniqueID(int id) { unique_id_ = id; }
int UIT_GetUniqueID() { return unique_id_; } int UIT_GetUniqueID() { return unique_id_; }
void UIT_Find(int identifier, const std::wstring& search_text,
const WebKit::WebFindOptions& options);
void UIT_StopFinding(bool clear_selection);
void UIT_NotifyFindStatus(int identifier, int count,
const WebKit::WebRect& selection_rect,
int active_match_ordinal, bool final_update);
static bool ImplementsThreadSafeReferenceCounting() { return true; } static bool ImplementsThreadSafeReferenceCounting() { return true; }
protected: protected:

View File

@ -54,93 +54,14 @@ base::StringPiece GetRawDataResource(HMODULE module, int resource_id) {
} }
base::StringPiece NetResourceProvider(int key) { base::StringPiece NetResourceProvider(int key) {
return GetRawDataResource(::GetModuleHandle(NULL), key); HMODULE hModule = ::GetModuleHandle(L"libcef.dll");
if(!hModule)
hModule = ::GetModuleHandle(NULL);
return GetRawDataResource(hModule, key);
} }
base::StringPiece GetDataResource(int resource_id) { base::StringPiece GetDataResource(int resource_id) {
switch (resource_id) { return NetResourceProvider(resource_id);
case IDR_BROKENIMAGE: {
// Use webkit's broken image icon (16x16)
static unsigned char broken_image_data[] = {
0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x10, 0x00, 0x10, 0x00, 0xD5, 0x00,
0x00, 0x20, 0x68, 0xB0, 0x70, 0x98, 0xC0, 0x28, 0x78, 0xB8, 0x20, 0x70,
0xB8, 0x88, 0xB8, 0xD8, 0x78, 0x98, 0xC8, 0x28, 0x80, 0xC0, 0xF8, 0xF8,
0xF8, 0xF0, 0xF0, 0xF8, 0xE0, 0xE8, 0xF0, 0xD0, 0xE0, 0xF0, 0xB8, 0xD0,
0xE8, 0xC0, 0xD8, 0xE8, 0x98, 0xC0, 0xE0, 0x68, 0x90, 0xC0, 0x70, 0x90,
0xC0, 0x30, 0x80, 0xC0, 0x28, 0x88, 0xC0, 0x30, 0x78, 0xB8, 0x88, 0xB8,
0xE0, 0x78, 0xA0, 0xC8, 0x20, 0x70, 0xB0, 0x90, 0xA8, 0xD0, 0x88, 0xA8,
0xD0, 0x70, 0x98, 0xC8, 0x90, 0xB0, 0xD0, 0x80, 0xA0, 0xC8, 0x28, 0x88,
0xC8, 0x20, 0x78, 0xB8, 0x40, 0x90, 0xC8, 0x50, 0x98, 0xC8, 0x28, 0x78,
0xC0, 0x50, 0x90, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x06,
0x8F, 0xC0, 0x8C, 0x70, 0x48, 0x2C, 0x66, 0x2C, 0x87, 0xA4, 0x72, 0xB9,
0xB4, 0x20, 0x37, 0xD0, 0xA8, 0x14, 0x7A, 0xB0, 0x5C, 0x0E, 0x51, 0x83,
0x76, 0x1B, 0x3D, 0x5C, 0xAE, 0x91, 0x88, 0x76, 0x32, 0x59, 0x34, 0x3A,
0x86, 0xB0, 0x57, 0x73, 0xD8, 0x12, 0x12, 0x86, 0xCE, 0x21, 0xF1, 0xD1,
0x1E, 0x34, 0xEC, 0xAD, 0x87, 0x20, 0x80, 0x1C, 0x10, 0x02, 0x76, 0x78,
0x6D, 0x06, 0x1F, 0x02, 0x87, 0x0D, 0x0C, 0x20, 0x1C, 0x82, 0x14, 0x07,
0x87, 0x87, 0x1C, 0x20, 0x04, 0x1C, 0x95, 0x87, 0x07, 0x14, 0x05, 0x07,
0x95, 0x95, 0x03, 0x12, 0x12, 0x03, 0x9C, 0x1C, 0x07, 0x05, 0x18, 0x07,
0x03, 0xA8, 0x03, 0x15, 0x0A, 0x0A, 0x15, 0xA9, 0x03, 0x07, 0x18, 0x01,
0xA7, 0xA9, 0xAB, 0xAD, 0xAF, 0x07, 0x01, 0x0F, 0x07, 0x15, 0xBD, 0x15,
0x00, 0xC0, 0x00, 0xBE, 0x15, 0x07, 0x0F, 0x0E, 0xBC, 0xC3, 0xC9, 0xBD,
0x07, 0x0E, 0xC7, 0x4C, 0xCF, 0x49, 0xCD, 0xD2, 0xD3, 0xD4, 0xD2, 0x41,
0x00, 0x3B
};
return base::StringPiece(reinterpret_cast<char*>(broken_image_data),
static_cast<base::StringPiece::size_type>(
sizeof(broken_image_data) / sizeof(unsigned char)));
}
case IDR_TEXTAREA_RESIZER: {
// Use webkit's text area resizer image.
static unsigned char area_resizer_data[] = {
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08,
0x08, 0x06, 0x00, 0x00, 0x00, 0xC4, 0x0F, 0xBE, 0x8B, 0x00, 0x00, 0x00,
0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0B, 0x13, 0x00, 0x00, 0x0B,
0x13, 0x01, 0x00, 0x9A, 0x9C, 0x18, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41,
0x4D, 0x41, 0x00, 0x00, 0xB1, 0x8E, 0x7C, 0xFB, 0x51, 0x93, 0x00, 0x00,
0x00, 0x20, 0x63, 0x48, 0x52, 0x4D, 0x00, 0x00, 0x7A, 0x25, 0x00, 0x00,
0x80, 0x83, 0x00, 0x00, 0xF9, 0xFF, 0x00, 0x00, 0x80, 0xE9, 0x00, 0x00,
0x75, 0x30, 0x00, 0x00, 0xEA, 0x60, 0x00, 0x00, 0x3A, 0x98, 0x00, 0x00,
0x17, 0x6F, 0x92, 0x5F, 0xC5, 0x46, 0x00, 0x00, 0x00, 0x39, 0x49, 0x44,
0x41, 0x54, 0x78, 0xDA, 0x7C, 0x8E, 0xB1, 0x0D, 0x00, 0x20, 0x0C, 0xC3,
0x1C, 0x9E, 0xE5, 0xA6, 0x5E, 0x1B, 0xB6, 0x4A, 0xA0, 0xD0, 0xAC, 0x8E,
0x25, 0xC3, 0x7F, 0x65, 0x9B, 0x35, 0xC1, 0xC9, 0x2C, 0x80, 0x74, 0x6A,
0x98, 0x0E, 0x17, 0x7C, 0x1B, 0xCA, 0x36, 0x92, 0x76, 0x6A, 0x48, 0x66,
0x37, 0x68, 0xAA, 0x05, 0x38, 0x03, 0x00, 0x40, 0x17, 0x33, 0x3D, 0x58,
0x57, 0x6B, 0xB3, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE,
0x42, 0x60, 0x82
};
return base::StringPiece(reinterpret_cast<char*>(area_resizer_data),
static_cast<base::StringPiece::size_type>(
sizeof(area_resizer_data) / sizeof(unsigned char)));
}
case IDR_SEARCH_CANCEL:
case IDR_SEARCH_CANCEL_PRESSED:
case IDR_SEARCH_MAGNIFIER:
case IDR_SEARCH_MAGNIFIER_RESULTS:
case IDR_MEDIA_PAUSE_BUTTON:
case IDR_MEDIA_PLAY_BUTTON:
case IDR_MEDIA_PLAY_BUTTON_DISABLED:
case IDR_MEDIA_SOUND_FULL_BUTTON:
case IDR_MEDIA_SOUND_NONE_BUTTON:
case IDR_MEDIA_SOUND_DISABLED:
case IDR_MEDIA_SLIDER_THUMB:
case IDR_MEDIA_VOLUME_SLIDER_THUMB:
return NetResourceProvider(resource_id);
default:
break;
}
return base::StringPiece();
} }
bool GetApplicationDirectory(FilePath* path) { bool GetApplicationDirectory(FilePath* path) {

View File

@ -725,6 +725,21 @@ void BrowserWebViewDelegate::willSendRequest(
request.setRequestorID(browser_->UIT_GetUniqueID()); request.setRequestorID(browser_->UIT_GetUniqueID());
} }
void BrowserWebViewDelegate::reportFindInPageMatchCount(
int request_id, int count, bool final_update)
{
browser_->UIT_NotifyFindStatus(request_id, count, gfx::Rect(),
-1, // // Don't update active match ordinal.
final_update);
}
void BrowserWebViewDelegate::reportFindInPageSelection(
int request_id, int active_match_ordinal, const WebKit::WebRect& sel)
{
browser_->UIT_NotifyFindStatus(request_id, -1, sel, active_match_ordinal,
false);
}
// Public methods ------------------------------------------------------------ // Public methods ------------------------------------------------------------

View File

@ -161,6 +161,10 @@ class BrowserWebViewDelegate : public WebKit::WebViewClient,
virtual void willSendRequest( virtual void willSendRequest(
WebKit::WebFrame*, unsigned identifier, WebKit::WebURLRequest&, WebKit::WebFrame*, unsigned identifier, WebKit::WebURLRequest&,
const WebKit::WebURLResponse& redirectResponse); const WebKit::WebURLResponse& redirectResponse);
virtual void reportFindInPageMatchCount(
int request_id, int count, bool final_update);
virtual void reportFindInPageSelection(
int request_id, int active_match_ordinal, const WebKit::WebRect& sel);
// webkit_glue::WebPluginPageDelegate // webkit_glue::WebPluginPageDelegate
virtual webkit_glue::WebPluginDelegate* CreatePluginDelegate( virtual webkit_glue::WebPluginDelegate* CreatePluginDelegate(

View File

@ -76,8 +76,10 @@ void BrowserWebViewDelegate::closeWidgetSoon() {
void BrowserWebViewDelegate::didChangeCursor(const WebCursorInfo& cursor_info) { void BrowserWebViewDelegate::didChangeCursor(const WebCursorInfo& cursor_info) {
if (WebWidgetHost* host = GetWidgetHost()) { if (WebWidgetHost* host = GetWidgetHost()) {
current_cursor_.InitFromCursorInfo(cursor_info); current_cursor_.InitFromCursorInfo(cursor_info);
HINSTANCE mod_handle = GetModuleHandle(NULL); HMODULE hModule = ::GetModuleHandle(L"libcef.dll");
host->SetCursor(current_cursor_.GetCursor(mod_handle)); if(!hModule)
hModule = ::GetModuleHandle(NULL);
host->SetCursor(current_cursor_.GetCursor(hModule));
} }
} }

View File

@ -255,6 +255,7 @@ DWORD WINAPI ThreadHandlerUI(LPVOID lpParam)
CefContext::CefContext() CefContext::CefContext()
{ {
multi_threaded_message_loop_ = false;
hthreadui_ = NULL; hthreadui_ = NULL;
idthreadui_ = 0; idthreadui_ = 0;
heventui_ = NULL; heventui_ = NULL;
@ -272,8 +273,12 @@ CefContext::~CefContext()
{ {
// Just in case CefShutdown() isn't called // Just in case CefShutdown() isn't called
Shutdown(); Shutdown();
if(at_exit_manager_) if(!multi_threaded_message_loop_) {
delete at_exit_manager_; if(messageloopui_)
delete messageloopui_;
if(at_exit_manager_)
delete at_exit_manager_;
}
} }
bool CefContext::Initialize(bool multi_threaded_message_loop, bool CefContext::Initialize(bool multi_threaded_message_loop,
@ -378,7 +383,7 @@ bool CefContext::Initialize(bool multi_threaded_message_loop,
if (!DoInitialize()) { if (!DoInitialize()) {
// TODO: Process initialization errors // TODO: Process initialization errors
} }
// Create our own message loop there // Message loop is scoped to the context.
SetMessageLoopForUI(new CefMessageLoopForUI()); SetMessageLoopForUI(new CefMessageLoopForUI());
idthreadui_ = GetCurrentThreadId(); idthreadui_ = GetCurrentThreadId();
DCHECK(idthreadui_ != 0); DCHECK(idthreadui_ != 0);
@ -391,6 +396,8 @@ bool CefContext::Initialize(bool multi_threaded_message_loop,
Unlock(); Unlock();
if(initialized) { if(initialized) {
multi_threaded_message_loop_ = multi_threaded_message_loop;
if (multi_threaded_message_loop) { if (multi_threaded_message_loop) {
// Wait for initial UI thread setup to complete // Wait for initial UI thread setup to complete
WaitForSingleObject(heventui_, INFINITE); WaitForSingleObject(heventui_, INFINITE);
@ -470,7 +477,6 @@ void CefContext::Shutdown()
UnregisterClass(CefBrowserImpl::GetWndClass(), hinstance_); UnregisterClass(CefBrowserImpl::GetWndClass(), hinstance_);
idthreadui_ = 0; idthreadui_ = 0;
messageloopui_ = NULL;
// We have exited the transitional state // We have exited the transitional state
in_transition_ = false; in_transition_ = false;

View File

@ -69,17 +69,22 @@ private:
void DoUninitialize(); void DoUninitialize();
protected: protected:
bool multi_threaded_message_loop_;
HMODULE hinstance_; HMODULE hinstance_;
DWORD idthreadui_; DWORD idthreadui_;
HANDLE hthreadui_; HANDLE hthreadui_;
HANDLE heventui_; HANDLE heventui_;
MessageLoopForUI* messageloopui_;
bool in_transition_; bool in_transition_;
BrowserList browserlist_; BrowserList browserlist_;
WebPreferences* webprefs_; WebPreferences* webprefs_;
StatsTable* statstable_; StatsTable* statstable_;
std::wstring cache_path_; std::wstring cache_path_;
// MessageLoopForUI will be scoped to the context when running in single
// threaded message loop mode.
MessageLoopForUI* messageloopui_;
// AtExitManager will be scoped to the context when running in single threaded // AtExitManager will be scoped to the context when running in single threaded
// message loop mode. // message loop mode.
base::AtExitManager* at_exit_manager_; base::AtExitManager* at_exit_manager_;

View File

@ -219,6 +219,31 @@ void CEF_CALLBACK browser_get_frame_names(struct _cef_browser_t* self,
cef_string_list_append(names, stringList[i].c_str()); cef_string_list_append(names, stringList[i].c_str());
} }
void CEF_CALLBACK browser_find(struct _cef_browser_t* self, int identifier,
const wchar_t* searchText, int forward, int matchCase, int findNext)
{
DCHECK(self);
if(!self)
return;
std::wstring searchTextStr;
if(searchText)
searchTextStr = searchText;
CefBrowserCppToC::Get(self)->Find(identifier, searchTextStr,
forward?true:false, matchCase?true:false, findNext?true:false);
}
void CEF_CALLBACK browser_stop_finding(struct _cef_browser_t* self,
int clearSelection)
{
DCHECK(self);
if(!self)
return;
CefBrowserCppToC::Get(self)->StopFinding(clearSelection?true:false);
}
// CONSTRUCTOR - Do not edit by hand. // CONSTRUCTOR - Do not edit by hand.
@ -239,6 +264,8 @@ CefBrowserCppToC::CefBrowserCppToC(CefBrowser* cls)
struct_.struct_.get_focused_frame = browser_get_focused_frame; struct_.struct_.get_focused_frame = browser_get_focused_frame;
struct_.struct_.get_frame = browser_get_frame; struct_.struct_.get_frame = browser_get_frame;
struct_.struct_.get_frame_names = browser_get_frame_names; struct_.struct_.get_frame_names = browser_get_frame_names;
struct_.struct_.find = browser_find;
struct_.struct_.stop_finding = browser_stop_finding;
} }
#ifdef _DEBUG #ifdef _DEBUG

View File

@ -476,6 +476,22 @@ enum cef_retval_t CEF_CALLBACK handler_handle_console_message(
CefBrowserCToCpp::Wrap(browser), messageStr, sourceStr, line); CefBrowserCToCpp::Wrap(browser), messageStr, sourceStr, line);
} }
enum cef_retval_t CEF_CALLBACK handler_handle_find_result(
struct _cef_handler_t* self, cef_browser_t* browser, int identifier,
int count, const cef_rect_t* selectionRect, int activeMatchOrdinal,
int finalUpdate)
{
DCHECK(self);
DCHECK(browser);
if(!self || !browser)
return RV_CONTINUE;
CefRect rect(*selectionRect);
return CefHandlerCppToC::Get(self)->HandleFindResult(
CefBrowserCToCpp::Wrap(browser), identifier, count, rect,
activeMatchOrdinal, finalUpdate?true:false);
}
// CONSTRUCTOR - Do not edit by hand. // CONSTRUCTOR - Do not edit by hand.
@ -506,6 +522,7 @@ CefHandlerCppToC::CefHandlerCppToC(CefHandler* cls)
struct_.struct_.handle_set_focus = handler_handle_set_focus; struct_.struct_.handle_set_focus = handler_handle_set_focus;
struct_.struct_.handle_key_event = handler_handle_key_event; struct_.struct_.handle_key_event = handler_handle_key_event;
struct_.struct_.handle_console_message = handler_handle_console_message; struct_.struct_.handle_console_message = handler_handle_console_message;
struct_.struct_.handle_find_result = handler_handle_find_result;
} }
#ifdef _DEBUG #ifdef _DEBUG

View File

@ -176,6 +176,24 @@ void CefBrowserCToCpp::GetFrameNames(std::vector<std::wstring>& names)
cef_string_list_free(list); cef_string_list_free(list);
} }
void CefBrowserCToCpp::Find(int identifier, const std::wstring& searchText,
bool forward, bool matchCase, bool findNext)
{
if(CEF_MEMBER_MISSING(struct_, find))
return;
struct_->find(struct_, identifier, searchText.c_str(), forward,
matchCase, findNext);
}
void CefBrowserCToCpp::StopFinding(bool clearSelection)
{
if(CEF_MEMBER_MISSING(struct_, stop_finding))
return;
struct_->stop_finding(struct_, clearSelection);
}
#ifdef _DEBUG #ifdef _DEBUG
long CefCToCpp<CefBrowserCToCpp, CefBrowser, cef_browser_t>::DebugObjCt = 0; long CefCToCpp<CefBrowserCToCpp, CefBrowser, cef_browser_t>::DebugObjCt = 0;

View File

@ -45,6 +45,9 @@ public:
virtual CefRefPtr<CefFrame> GetFocusedFrame(); virtual CefRefPtr<CefFrame> GetFocusedFrame();
virtual CefRefPtr<CefFrame> GetFrame(const std::wstring& name); virtual CefRefPtr<CefFrame> GetFrame(const std::wstring& name);
virtual void GetFrameNames(std::vector<std::wstring>& names); virtual void GetFrameNames(std::vector<std::wstring>& names);
virtual void Find(int identifier, const std::wstring& searchText,
bool forward, bool matchCase, bool findNext);
virtual void StopFinding(bool clearSelection);
}; };
#endif // USING_CEF_SHARED #endif // USING_CEF_SHARED

View File

@ -156,7 +156,7 @@ void CefFrameCToCpp::ExecuteJavaScript(const std::wstring& jsCode,
const std::wstring& scriptUrl, int startLine) const std::wstring& scriptUrl, int startLine)
{ {
if(CEF_MEMBER_MISSING(struct_, execute_java_script)) if(CEF_MEMBER_MISSING(struct_, execute_java_script))
return; return;
struct_->execute_java_script(struct_, jsCode.c_str(), scriptUrl.c_str(), struct_->execute_java_script(struct_, jsCode.c_str(), scriptUrl.c_str(),
startLine); startLine);
@ -165,7 +165,7 @@ void CefFrameCToCpp::ExecuteJavaScript(const std::wstring& jsCode,
bool CefFrameCToCpp::IsMain() bool CefFrameCToCpp::IsMain()
{ {
if(CEF_MEMBER_MISSING(struct_, is_main)) if(CEF_MEMBER_MISSING(struct_, is_main))
return false; return false;
return struct_->is_main(struct_)?true:false; return struct_->is_main(struct_)?true:false;
} }
@ -173,7 +173,7 @@ bool CefFrameCToCpp::IsMain()
bool CefFrameCToCpp::IsFocused() bool CefFrameCToCpp::IsFocused()
{ {
if(CEF_MEMBER_MISSING(struct_, is_focused)) if(CEF_MEMBER_MISSING(struct_, is_focused))
return false; return false;
return struct_->is_focused(struct_)?true:false; return struct_->is_focused(struct_)?true:false;
} }

View File

@ -359,6 +359,18 @@ CefHandler::RetVal CefHandlerCToCpp::HandleConsoleMessage(
CefBrowserCppToC::Wrap(browser), message.c_str(), source.c_str(), line); CefBrowserCppToC::Wrap(browser), message.c_str(), source.c_str(), line);
} }
CefHandler::RetVal CefHandlerCToCpp::HandleFindResult(
CefRefPtr<CefBrowser> browser, int identifier, int count,
const CefRect& selectionRect, int activeMatchOrdinal, bool finalUpdate)
{
if(CEF_MEMBER_MISSING(struct_, handle_find_result))
return RV_CONTINUE;
return struct_->handle_find_result(struct_,
CefBrowserCppToC::Wrap(browser), identifier, count, &selectionRect,
activeMatchOrdinal, finalUpdate);
}
#ifdef _DEBUG #ifdef _DEBUG
long CefCToCpp<CefHandlerCToCpp, CefHandler, cef_handler_t>::DebugObjCt = 0; long CefCToCpp<CefHandlerCToCpp, CefHandler, cef_handler_t>::DebugObjCt = 0;

View File

@ -78,6 +78,9 @@ public:
KeyEventType type, int code, int modifiers, bool isSystemKey); KeyEventType type, int code, int modifiers, bool isSystemKey);
virtual RetVal HandleConsoleMessage(CefRefPtr<CefBrowser> browser, virtual RetVal HandleConsoleMessage(CefRefPtr<CefBrowser> browser,
const std::wstring& message, const std::wstring& source, int line); const std::wstring& message, const std::wstring& source, int line);
virtual RetVal HandleFindResult(CefRefPtr<CefBrowser> browser, int identifier,
int count, const CefRect& selectionRect, int activeMatchOrdinal,
bool finalUpdate);
}; };
#endif // BUILDING_CEF_SHARED #endif // BUILDING_CEF_SHARED

View File

@ -12,7 +12,7 @@
#include "thread_util.h" #include "thread_util.h"
#include "uiplugin_test.h" #include "uiplugin_test.h"
#include <sstream> #include <sstream>
#include <commdlg.h>
#define MAX_LOADSTRING 100 #define MAX_LOADSTRING 100
#define MAX_URL_LENGTH 255 #define MAX_URL_LENGTH 255
@ -28,6 +28,8 @@ HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
TCHAR szWorkingDir[MAX_PATH]; // The current working directory TCHAR szWorkingDir[MAX_PATH]; // The current working directory
UINT uFindMsg; // Message identifier for find events.
HWND hFindDlg = NULL; // Handle for the find dialog.
// Forward declarations of functions included in this code module: // Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance); ATOM MyRegisterClass(HINSTANCE hInstance);
@ -86,6 +88,9 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_CEFCLIENT)); hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_CEFCLIENT));
// Register the find event message.
uFindMsg = RegisterWindowMessage(FINDMSGSTRING);
// Main message loop // Main message loop
while (GetMessage(&msg, NULL, 0, 0)) while (GetMessage(&msg, NULL, 0, 0))
{ {
@ -94,6 +99,10 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
CefDoMessageLoopWork(); CefDoMessageLoopWork();
#endif #endif
// Allow processing of find dialog messages.
if(hFindDlg && IsDialogMessage(hFindDlg, &msg))
continue;
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{ {
TranslateMessage(&msg); TranslateMessage(&msg);
@ -562,6 +571,20 @@ public:
return RV_HANDLED; return RV_HANDLED;
} }
// Called to report find results returned by CefBrowser::Find(). |identifer|
// is the identifier passed to CefBrowser::Find(), |count| is the number of
// matches currently identified, |selectionRect| is the location of where the
// match was found (in window coordinates), |activeMatchOrdinal| is the
// current position in the search results, and |finalUpdate| is true if this
// is the last find notification. The return value is currently ignored.
virtual RetVal HandleFindResult(CefRefPtr<CefBrowser> browser,
int identifier, int count,
const CefRect& selectionRect,
int activeMatchOrdinal, bool finalUpdate)
{
return RV_CONTINUE;
}
// Retrieve the current navigation state flags // Retrieve the current navigation state flags
void GetNavState(bool &isLoading, bool &canGoBack, bool &canGoForward) void GetNavState(bool &isLoading, bool &canGoBack, bool &canGoForward)
{ {
@ -679,7 +702,14 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
static HWND backWnd = NULL, forwardWnd = NULL, reloadWnd = NULL, static HWND backWnd = NULL, forwardWnd = NULL, reloadWnd = NULL,
stopWnd = NULL, editWnd = NULL; stopWnd = NULL, editWnd = NULL;
static WNDPROC editWndOldProc = NULL; static WNDPROC editWndOldProc = NULL;
// Static members used for the find dialog.
static FINDREPLACE fr;
static WCHAR szFindWhat[80] = {0};
static WCHAR szLastFindWhat[80] = {0};
static bool findNext = false;
static bool lastMatchCase = false;
int wmId, wmEvent; int wmId, wmEvent;
PAINTSTRUCT ps; PAINTSTRUCT ps;
HDC hdc; HDC hdc;
@ -708,6 +738,53 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
return (LRESULT)CallWindowProc(editWndOldProc, hWnd, message, wParam, lParam); return (LRESULT)CallWindowProc(editWndOldProc, hWnd, message, wParam, lParam);
} }
else if (message == uFindMsg)
{
// Find event.
LPFINDREPLACE lpfr = (LPFINDREPLACE)lParam;
if (lpfr->Flags & FR_DIALOGTERM)
{
// The find dialog box has been dismissed so invalidate the handle and
// reset the search results.
hFindDlg = NULL;
if(g_handler.get())
{
g_handler->GetBrowser()->StopFinding(true);
szLastFindWhat[0] = 0;
findNext = false;
}
return 0;
}
if ((lpfr->Flags & FR_FINDNEXT) && g_handler.get())
{
// Search for the requested string.
bool matchCase = (lpfr->Flags & FR_MATCHCASE?true:false);
if(matchCase != lastMatchCase ||
(matchCase && wcsncmp(szFindWhat, szLastFindWhat,
sizeof(szLastFindWhat)/sizeof(WCHAR)) != 0) ||
(!matchCase && _wcsnicmp(szFindWhat, szLastFindWhat,
sizeof(szLastFindWhat)/sizeof(WCHAR)) != 0))
{
// The search string has changed, so reset the search results.
if(szLastFindWhat[0] != 0) {
g_handler->GetBrowser()->StopFinding(true);
findNext = false;
}
lastMatchCase = matchCase;
wcscpy_s(szLastFindWhat, sizeof(szLastFindWhat)/sizeof(WCHAR),
szFindWhat);
}
g_handler->GetBrowser()->Find(0, lpfr->lpstrFindWhat,
(lpfr->Flags & FR_DOWN)?true:false, matchCase, findNext);
if(!findNext)
findNext = true;
}
return 0;
}
else else
{ {
// Callback for the main window // Callback for the main window
@ -824,6 +901,25 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
MB_OK | MB_ICONINFORMATION); MB_OK | MB_ICONINFORMATION);
} }
return 0; return 0;
case ID_FIND:
if(!hFindDlg)
{
// Create the find dialog.
ZeroMemory(&fr, sizeof(fr));
fr.lStructSize = sizeof(fr);
fr.hwndOwner = hWnd;
fr.lpstrFindWhat = szFindWhat;
fr.wFindWhatLen = sizeof(szFindWhat);
fr.Flags = FR_HIDEWHOLEWORD | FR_DOWN;
hFindDlg = FindText(&fr);
}
else
{
// Give focus to the existing find dialog.
::SetFocus(hFindDlg);
}
return 0;
case IDC_NAV_BACK: // Back button case IDC_NAV_BACK: // Back button
if(browser.get()) if(browser.get())
browser->GoBack(); browser->GoBack();

View File

@ -52,6 +52,8 @@ BEGIN
POPUP "&File" POPUP "&File"
BEGIN BEGIN
MENUITEM "E&xit", IDM_EXIT MENUITEM "E&xit", IDM_EXIT
MENUITEM SEPARATOR
MENUITEM "&Find...", ID_FIND
END END
POPUP "&Help" POPUP "&Help"
BEGIN BEGIN

View File

@ -22,6 +22,7 @@
#define IDC_NAV_RELOAD 202 #define IDC_NAV_RELOAD 202
#define IDC_NAV_STOP 203 #define IDC_NAV_STOP 203
#define ID_WARN_CONSOLEMESSAGE 32000 #define ID_WARN_CONSOLEMESSAGE 32000
#define ID_FIND 32001
#define ID_TESTS_GETSOURCE 32769 #define ID_TESTS_GETSOURCE 32769
#define ID_TESTS_GETTEXT 32770 #define ID_TESTS_GETTEXT 32770
#define ID_TESTS_JAVASCRIPT_HANDLER 32771 #define ID_TESTS_JAVASCRIPT_HANDLER 32771

View File

@ -209,6 +209,14 @@ public:
return RV_CONTINUE; return RV_CONTINUE;
} }
virtual RetVal HandleFindResult(CefRefPtr<CefBrowser> browser,
int identifier, int count,
const CefRect& selectionRect,
int activeMatchOrdinal, bool finalUpdate)
{
return RV_CONTINUE;
}
CefRefPtr<CefBrowser> GetBrowser() CefRefPtr<CefBrowser> GetBrowser()
{ {
return browser_; return browser_;

View File

@ -1070,7 +1070,8 @@ class obj_analysis:
'unsigned long' : 'unsigned long', 'unsigned long' : 'unsigned long',
'size_t' : 'size_t', 'size_t' : 'size_t',
'bool' : 'int', 'bool' : 'int',
'CefWindowHandle' : 'cef_window_handle_t' 'CefWindowHandle' : 'cef_window_handle_t',
'CefRect' : 'cef_rect_t',
} }
if value in simpletypes.keys(): if value in simpletypes.keys():
return { return {