- Add off-screen rendering support on Windows. This involves a number of new CefBrowser and CefHandler methods. See the "Off-Screen Rendering Example" in cefclient for example usage.

- Add CefRunMessageLoop() for efficient message loop usage and modify cefclient to use it.
- Add CefHandler::HandleNavStateChange() for back/forward state notifications and modify cefclient to use it.

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@208 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt
2011-03-24 20:36:47 +00:00
parent 658c53e87c
commit ff983a6e72
57 changed files with 3392 additions and 379 deletions

View File

@ -89,6 +89,10 @@
'tests/cefclient/cefclient_win.cpp', 'tests/cefclient/cefclient_win.cpp',
'tests/cefclient/clientplugin.cpp', 'tests/cefclient/clientplugin.cpp',
'tests/cefclient/clientplugin.h', 'tests/cefclient/clientplugin.h',
'tests/cefclient/osrlugin.cpp',
'tests/cefclient/osrplugin.h',
'tests/cefclient/osrplugin_test.cpp',
'tests/cefclient/osrplugin_test.h',
'tests/cefclient/plugin_test.cpp', 'tests/cefclient/plugin_test.cpp',
'tests/cefclient/plugin_test.h', 'tests/cefclient/plugin_test.h',
'tests/cefclient/Resource.h', 'tests/cefclient/Resource.h',
@ -620,6 +624,7 @@
'libcef/v8_impl.h', 'libcef/v8_impl.h',
'libcef/web_urlrequest_impl.cc', 'libcef/web_urlrequest_impl.cc',
'libcef/web_urlrequest_impl.h', 'libcef/web_urlrequest_impl.h',
'libcef/webview_host.cc',
'libcef/webview_host.h', 'libcef/webview_host.h',
'libcef/webwidget_host.cc', 'libcef/webwidget_host.cc',
'libcef/webwidget_host.h', 'libcef/webwidget_host.h',

View File

@ -85,12 +85,24 @@ bool CefInitialize(const CefSettings& settings,
/*--cef()--*/ /*--cef()--*/
void CefShutdown(); void CefShutdown();
// Perform message loop processing. This function must be called on the main // Perform a single iteration of CEF message loop processing. This function is
// application thread if CefInitialize() is called with a // used to integrate the CEF message loop into an existing application message
// CefSettings.multi_threaded_message_loop value of false. // loop. Care must be taken to balance performance against excessive CPU usage.
// This function should only be called on the main application thread and only
// if CefInitialize() is called with a CefSettings.multi_threaded_message_loop
// value of false. This function will not block.
/*--cef()--*/ /*--cef()--*/
void CefDoMessageLoopWork(); void CefDoMessageLoopWork();
// Run the CEF message loop. Use this function instead of an application-
// provided message loop to get the best balance between performance and CPU
// usage. This function should only be called on the main application thread and
// only if CefInitialize() is called with a
// CefSettings.multi_threaded_message_loop value of false. This function will
// block until a quit message is received by the system.
/*--cef()--*/
void CefRunMessageLoop();
// Register a new V8 extension with the specified JavaScript extension code and // Register a new V8 extension with the specified JavaScript extension code and
// handler. Functions implemented by the handler are prototyped using the // handler. Functions implemented by the handler are prototyped using the
// keyword 'native'. The calling of a native function is restricted to the scope // keyword 'native'. The calling of a native function is restricted to the scope
@ -242,7 +254,7 @@ public:
virtual int Release() =0; virtual int Release() =0;
// Return the current number of references. // Return the current number of references.
virtual int GetRefCt() = 0; virtual int GetRefCt() =0;
}; };
@ -396,6 +408,10 @@ public:
class CefBrowser : public CefBase class CefBrowser : public CefBase
{ {
public: public:
typedef cef_key_type_t KeyType;
typedef cef_mouse_button_type_t MouseButtonType;
typedef cef_paint_element_type_t PaintElementType;
// Create a new browser window using the window parameters specified by // Create a new browser window using the window parameters specified by
// |windowInfo|. All values will be copied internally and the actual window // |windowInfo|. All values will be copied internally and the actual window
// will be created on the UI thread. The |popup| parameter should be true if // will be created on the UI thread. The |popup| parameter should be true if
@ -505,6 +521,73 @@ public:
// instance. // instance.
/*--cef()--*/ /*--cef()--*/
virtual void CloseDevTools() =0; virtual void CloseDevTools() =0;
// Returns true if window rendering is disabled.
/*--cef()--*/
virtual bool IsWindowRenderingDisabled() =0;
// Get the size of the specified element. This method should only be called on
// the UI thread.
/*--cef()--*/
virtual bool GetSize(PaintElementType type, int& width, int& height) =0;
// Set the size of the specified element. This method is only used when window
// rendering is disabled.
/*--cef()--*/
virtual void SetSize(PaintElementType type, int width, int height) =0;
// Returns true if a popup is currently visible. This method should only be
// called on the UI thread.
/*--cef()--*/
virtual bool IsPopupVisible() =0;
// Hide the currently visible popup, if any.
/*--cef()--*/
virtual void HidePopup() =0;
// Invalidate the |dirtyRect| region of the view. This method is only used
// when window rendering is disabled and will result in a call to
// HandlePaint().
/*--cef()--*/
virtual void Invalidate(const CefRect& dirtyRect) =0;
// Get the raw image data contained in the specified element without
// performing validation. The specified |width| and |height| dimensions must
// match the current element size. On Windows |buffer| must be width*height*4
// bytes in size and represents a BGRA image with an upper-left origin. This
// method should only be called on the UI thread.
/*--cef()--*/
virtual bool GetImage(PaintElementType type, int width, int height,
void* buffer) =0;
// Send a key event to the browser.
/*--cef()--*/
virtual void SendKeyEvent(KeyType type, int key, int modifiers, bool sysChar,
bool imeChar) =0;
// Send a mouse click event to the browser. The |x| and |y| coordinates are
// relative to the upper-left corner of the view.
/*--cef()--*/
virtual void SendMouseClickEvent(int x, int y, MouseButtonType type,
bool mouseUp, int clickCount) =0;
// Send a mouse move event to the browser. The |x| and |y| coordinates are
// relative to the upper-left corner of the view.
/*--cef()--*/
virtual void SendMouseMoveEvent(int x, int y, bool mouseLeave) =0;
// Send a mouse wheel event to the browser. The |x| and |y| coordinates are
// relative to the upper-left corner of the view.
/*--cef()--*/
virtual void SendMouseWheelEvent(int x, int y, int delta) =0;
// Send a focus event to the browser.
/*--cef()--*/
virtual void SendFocusEvent(bool setFocus) =0;
// Send a capture lost event to the browser.
/*--cef()--*/
virtual void SendCaptureLostEvent() =0;
}; };
@ -662,6 +745,12 @@ public:
virtual RetVal HandleTitleChange(CefRefPtr<CefBrowser> browser, virtual RetVal HandleTitleChange(CefRefPtr<CefBrowser> browser,
const CefString& title) =0; const CefString& title) =0;
// Called on the UI thread when the navigation state has changed. The return
// value is currently ignored.
/*--cef()--*/
virtual RetVal HandleNavStateChange(CefRefPtr<CefBrowser> browser,
bool canGoBack, bool canGoForward) =0;
// Various browser navigation types supported by chrome. // Various browser navigation types supported by chrome.
typedef cef_handler_navtype_t NavType; typedef cef_handler_navtype_t NavType;
@ -805,7 +894,7 @@ public:
// options or RV_HANDLED to display the modified |printOptions|. // options or RV_HANDLED to display the modified |printOptions|.
/*--cef()--*/ /*--cef()--*/
virtual RetVal HandlePrintOptions(CefRefPtr<CefBrowser> browser, virtual RetVal HandlePrintOptions(CefRefPtr<CefBrowser> browser,
CefPrintOptions& printOptions) = 0; CefPrintOptions& printOptions) =0;
// Called on the UI thread to format print headers and footers. |printInfo| // Called on the UI thread to format print headers and footers. |printInfo|
// contains platform-specific information about the printer context. |url| is // contains platform-specific information about the printer context. |url| is
@ -943,8 +1032,56 @@ public:
int identifier, int count, int identifier, int count,
const CefRect& selectionRect, const CefRect& selectionRect,
int activeMatchOrdinal, bool finalUpdate) =0; int activeMatchOrdinal, bool finalUpdate) =0;
};
// Called on the UI thread to retrieve either the simulated screen rectangle
// if |screen| is true or the view rectangle if |screen| is false. The view
// rectangle is relative to the screen coordinates. This method is only called
// if window rendering has been disabled. Return RV_CONTINUE if the rectangle
// was provided.
/*--cef()--*/
virtual RetVal HandleGetRect(CefRefPtr<CefBrowser> browser, bool screen,
CefRect& rect) =0;
// Called on the UI thread retrieve the translation from view coordinates to
// actual screen coordinates. This method is only called if window rendering
// has been disabled. Return RV_CONTINUE if the screen coordinates were
// provided.
/*--cef()--*/
virtual RetVal HandleGetScreenPoint(CefRefPtr<CefBrowser> browser,
int viewX, int viewY, int& screenX,
int& screenY) =0;
// Called on the UI thread when the browser wants to show, hide, resize or
// move the popup. If |show| is true and |rect| is zero size then the popup
// should be shown. If |show| is true and |rect| is non-zero size then |rect|
// represents the popup location in view coordinates. If |show| is false
// then the popup should be hidden. This method is only called if window
// rendering has been disabled. The return value is currently ignored.
/*--cef()--*/
virtual RetVal HandlePopupChange(CefRefPtr<CefBrowser> browser, bool show,
const CefRect& rect) =0;
typedef cef_paint_element_type_t PaintElementType;
// Called when an element should be painted. |type| indicates whether the
// element is the view or the popup. |buffer| contains the pixel data for the
// whole image. |dirtyRect| indicates the portion of the image that has been
// repainted. On Windows |buffer| will be width*height*4 bytes in size and
// represents a BGRA image with an upper-left origin. This method is only
// called if window rendering has been disabled. The return value is currently
// ignored.
/*--cef()--*/
virtual RetVal HandlePaint(CefRefPtr<CefBrowser> browser,
PaintElementType type, const CefRect& dirtyRect,
const void* buffer) =0;
// Called when the browser window's cursor has changed. This method is only
// called if window rendering has been disabled. The return value is currently
// ignored.
/*--cef()--*/
virtual RetVal HandleCursorChange(CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor) =0;
};
// Class used to represent a web request. The methods of this class may be // Class used to represent a web request. The methods of this class may be
// called on any thread. // called on any thread.
@ -993,16 +1130,16 @@ public:
// Optional flags. Used in combination with CefWebURLRequest. // Optional flags. Used in combination with CefWebURLRequest.
/*--cef()--*/ /*--cef()--*/
virtual RequestFlags GetFlags() = 0; virtual RequestFlags GetFlags() =0;
/*--cef()--*/ /*--cef()--*/
virtual void SetFlags(RequestFlags flags) = 0; virtual void SetFlags(RequestFlags flags) =0;
// Optional URL to the first party for cookies. Used in combination with // Optional URL to the first party for cookies. Used in combination with
// CefWebURLRequest. // CefWebURLRequest.
/*--cef()--*/ /*--cef()--*/
virtual CefString GetFirstPartyForCookies() = 0; virtual CefString GetFirstPartyForCookies() =0;
/*--cef()--*/ /*--cef()--*/
virtual void SetFirstPartyForCookies(const CefString& url) = 0; virtual void SetFirstPartyForCookies(const CefString& url) =0;
}; };
@ -1096,15 +1233,15 @@ public:
// Returns the response status code. // Returns the response status code.
/*--cef()--*/ /*--cef()--*/
virtual int GetStatus() = 0; virtual int GetStatus() =0;
// Returns the response status text. // Returns the response status text.
/*--cef()--*/ /*--cef()--*/
virtual CefString GetStatusText() = 0; virtual CefString GetStatusText() =0;
// Returns the value for the specified response header field. // Returns the value for the specified response header field.
/*--cef()--*/ /*--cef()--*/
virtual CefString GetHeader(const CefString& name) = 0; virtual CefString GetHeader(const CefString& name) =0;
// Retrieves a map of all response header fields. // Retrieves a map of all response header fields.
/*--cef()--*/ /*--cef()--*/

View File

@ -58,11 +58,22 @@ CEF_EXPORT int cef_initialize(const struct _cef_settings_t* settings,
// CEF before the application exits. // CEF before the application exits.
CEF_EXPORT void cef_shutdown(); CEF_EXPORT void cef_shutdown();
// Perform message loop processing. This function must be called on the main // Perform a single iteration of CEF message loop processing. This function is
// application thread if cef_initialize() is called with a // used to integrate the CEF message loop into an existing application message
// CefSettings.multi_threaded_message_loop value of false (0). // loop. Care must be taken to balance performance against excessive CPU usage.
// This function should only be called on the main application thread and only
// if cef_initialize() is called with a CefSettings.multi_threaded_message_loop
// value of false (0). This function will not block.
CEF_EXPORT void cef_do_message_loop_work(); CEF_EXPORT void cef_do_message_loop_work();
// Run the CEF message loop. Use this function instead of an application-
// provided message loop to get the best balance between performance and CPU
// usage. This function should only be called on the main application thread and
// only if cef_initialize() is called with a
// CefSettings.multi_threaded_message_loop value of false (0). This function
// will block until a quit message is received by the system.
CEF_EXPORT void cef_run_message_loop();
// Register a new V8 extension with the specified JavaScript extension code and // Register a new V8 extension with the specified JavaScript extension code and
// handler. Functions implemented by the handler are prototyped using the // handler. Functions implemented by the handler are prototyped using the
// keyword 'native'. The calling of a native function is restricted to the scope // keyword 'native'. The calling of a native function is restricted to the scope
@ -316,6 +327,69 @@ typedef struct _cef_browser_t
// instance. // instance.
void (CEF_CALLBACK *close_dev_tools)(struct _cef_browser_t* self); void (CEF_CALLBACK *close_dev_tools)(struct _cef_browser_t* self);
// Returns true (1) if window rendering is disabled.
int (CEF_CALLBACK *is_window_rendering_disabled)(struct _cef_browser_t* self);
// Get the size of the specified element. This function should only be called
// on the UI thread.
int (CEF_CALLBACK *get_size)(struct _cef_browser_t* self,
enum cef_paint_element_type_t type, int* width, int* height);
// Set the size of the specified element. This function is only used when
// window rendering is disabled.
void (CEF_CALLBACK *set_size)(struct _cef_browser_t* self,
enum cef_paint_element_type_t type, int width, int height);
// Returns true (1) if a popup is currently visible. This function should only
// be called on the UI thread.
int (CEF_CALLBACK *is_popup_visible)(struct _cef_browser_t* self);
// Hide the currently visible popup, if any.
void (CEF_CALLBACK *hide_popup)(struct _cef_browser_t* self);
// Invalidate the |dirtyRect| region of the view. This function is only used
// when window rendering is disabled and will result in a call to
// handle_paint().
void (CEF_CALLBACK *invalidate)(struct _cef_browser_t* self,
const cef_rect_t* dirtyRect);
// Get the raw image data contained in the specified element without
// performing validation. The specified |width| and |height| dimensions must
// match the current element size. On Windows |buffer| must be width*height*4
// bytes in size and represents a BGRA image with an upper-left origin. This
// function should only be called on the UI thread.
int (CEF_CALLBACK *get_image)(struct _cef_browser_t* self,
enum cef_paint_element_type_t type, int width, int height,
void* buffer);
// Send a key event to the browser.
void (CEF_CALLBACK *send_key_event)(struct _cef_browser_t* self,
enum cef_key_type_t type, int key, int modifiers, int sysChar,
int imeChar);
// Send a mouse click event to the browser. The |x| and |y| coordinates are
// relative to the upper-left corner of the view.
void (CEF_CALLBACK *send_mouse_click_event)(struct _cef_browser_t* self,
int x, int y, enum cef_mouse_button_type_t type, int mouseUp,
int clickCount);
// Send a mouse move event to the browser. The |x| and |y| coordinates are
// relative to the upper-left corner of the view.
void (CEF_CALLBACK *send_mouse_move_event)(struct _cef_browser_t* self, int x,
int y, int mouseLeave);
// Send a mouse wheel event to the browser. The |x| and |y| coordinates are
// relative to the upper-left corner of the view.
void (CEF_CALLBACK *send_mouse_wheel_event)(struct _cef_browser_t* self,
int x, int y, int delta);
// Send a focus event to the browser.
void (CEF_CALLBACK *send_focus_event)(struct _cef_browser_t* self,
int setFocus);
// Send a capture lost event to the browser.
void (CEF_CALLBACK *send_capture_lost_event)(struct _cef_browser_t* self);
} cef_browser_t; } cef_browser_t;
@ -473,6 +547,12 @@ 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 cef_string_t* title); const cef_string_t* title);
// Called on the UI thread when the navigation state has changed. The return
// value is currently ignored.
enum cef_retval_t (CEF_CALLBACK *handle_nav_state_change)(
struct _cef_handler_t* self, struct _cef_browser_t* browser,
int canGoBack, int canGoForward);
// Called on the UI thread before browser navigation. The client has an // Called on the UI thread before browser navigation. The client has an
// opportunity to modify the |request| object if desired. Return RV_HANDLED // opportunity to modify the |request| object if desired. Return RV_HANDLED
// to cancel navigation. // to cancel navigation.
@ -703,6 +783,50 @@ typedef struct _cef_handler_t
int identifier, int count, const cef_rect_t* selectionRect, int identifier, int count, const cef_rect_t* selectionRect,
int activeMatchOrdinal, int finalUpdate); int activeMatchOrdinal, int finalUpdate);
// Called on the UI thread to retrieve either the simulated screen rectangle
// if |screen| is true (1) or the view rectangle if |screen| is false (0). The
// view rectangle is relative to the screen coordinates. This function is only
// called if window rendering has been disabled. Return RV_CONTINUE if the
// rectangle was provided.
enum cef_retval_t (CEF_CALLBACK *handle_get_rect)(struct _cef_handler_t* self,
struct _cef_browser_t* browser, int screen, cef_rect_t* rect);
// Called on the UI thread retrieve the translation from view coordinates to
// actual screen coordinates. This function is only called if window rendering
// has been disabled. Return RV_CONTINUE if the screen coordinates were
// provided.
enum cef_retval_t (CEF_CALLBACK *handle_get_screen_point)(
struct _cef_handler_t* self, struct _cef_browser_t* browser, int viewX,
int viewY, int* screenX, int* screenY);
// Called on the UI thread when the browser wants to show, hide, resize or
// move the popup. If |show| is true (1) and |rect| is zero size then the
// popup should be shown. If |show| is true (1) and |rect| is non-zero size
// then |rect| represents the popup location in view coordinates. If |show| is
// false (0) then the popup should be hidden. This function is only called if
// window rendering has been disabled. The return value is currently ignored.
enum cef_retval_t (CEF_CALLBACK *handle_popup_change)(
struct _cef_handler_t* self, struct _cef_browser_t* browser, int show,
const cef_rect_t* rect);
// Called when an element should be painted. |type| indicates whether the
// element is the view or the popup. |buffer| contains the pixel data for the
// whole image. |dirtyRect| indicates the portion of the image that has been
// repainted. On Windows |buffer| will be width*height*4 bytes in size and
// represents a BGRA image with an upper-left origin. This function is only
// called if window rendering has been disabled. The return value is currently
// ignored.
enum cef_retval_t (CEF_CALLBACK *handle_paint)(struct _cef_handler_t* self,
struct _cef_browser_t* browser, enum cef_paint_element_type_t type,
const cef_rect_t* dirtyRect, const void* buffer);
// Called when the browser window's cursor has changed. This function is only
// called if window rendering has been disabled. The return value is currently
// ignored.
enum cef_retval_t (CEF_CALLBACK *handle_cursor_change)(
struct _cef_handler_t* self, struct _cef_browser_t* browser,
cef_cursor_handle_t cursor);
} cef_handler_t; } cef_handler_t;

View File

@ -73,8 +73,9 @@ public:
pthread_mutexattr_t attr_; pthread_mutexattr_t attr_;
}; };
// Window handle. // Handle types.
#define CefWindowHandle cef_window_handle_t #define CefWindowHandle cef_window_handle_t
#define CefCursorHandle cef_cursor_handle_t
// Class representing window information. // Class representing window information.
class CefWindowInfo : public cef_window_info_t class CefWindowInfo : public cef_window_info_t

View File

@ -45,8 +45,9 @@ inline long CefAtomicDecrement(long volatile *pDest)
return __sync_sub_and_fetch(pDest, 1); return __sync_sub_and_fetch(pDest, 1);
} }
// Window handle. // Handle types.
#define CefWindowHandle cef_window_handle_t #define CefWindowHandle cef_window_handle_t
#define CefCursorHandle cef_cursor_handle_t
// Critical section wrapper. // Critical section wrapper.
class CefCriticalSection class CefCriticalSection

View File

@ -269,6 +269,22 @@ typedef struct _cef_urlparts_t
cef_string_t query; cef_string_t query;
} cef_urlparts_t; } cef_urlparts_t;
// Mouse button types.
enum cef_mouse_button_type_t
{
MBT_LEFT = 0,
MBT_MIDDLE,
MBT_RIGHT,
};
// Key types.
enum cef_key_type_t
{
KT_KEYUP = 0,
KT_KEYDOWN,
KT_CHAR,
};
// Define handler return value types. Returning RV_HANDLED indicates // Define handler return value types. Returning RV_HANDLED indicates
// that the implementation completely handled the method and that no further // that the implementation completely handled the method and that no further
// processing is required. Returning RV_CONTINUE indicates that the // processing is required. Returning RV_CONTINUE indicates that the
@ -348,16 +364,24 @@ enum cef_handler_errorcode_t
// Structure representing menu information. // Structure representing menu information.
typedef struct _cef_handler_menuinfo_t typedef struct _cef_handler_menuinfo_t
{ {
// Values from the cef_handler_menutypebits_t enumeration.
int typeFlags; int typeFlags;
// If window rendering is enabled |x| and |y| will be in screen coordinates.
// Otherwise, |x| and |y| will be in view coordinates.
int x; int x;
int y; int y;
cef_string_t linkUrl; cef_string_t linkUrl;
cef_string_t imageUrl; cef_string_t imageUrl;
cef_string_t pageUrl; cef_string_t pageUrl;
cef_string_t frameUrl; cef_string_t frameUrl;
cef_string_t selectionText; cef_string_t selectionText;
cef_string_t misspelledWord; cef_string_t misspelledWord;
// Values from the cef_handler_menucapabilitybits_t enumeration.
int editFlags; int editFlags;
cef_string_t securityInfo; cef_string_t securityInfo;
} cef_handler_menuinfo_t; } cef_handler_menuinfo_t;
@ -425,6 +449,12 @@ enum cef_handler_menuid_t
MENU_ID_VIEWSOURCE = 31, MENU_ID_VIEWSOURCE = 31,
}; };
enum cef_paint_element_type_t
{
PET_VIEW = 0,
PET_POPUP,
};
// Post data elements may represent either bytes or files. // Post data elements may represent either bytes or files.
enum cef_postdataelement_type_t enum cef_postdataelement_type_t
{ {

View File

@ -41,6 +41,7 @@ extern "C" {
// Window handle. // Window handle.
#define cef_window_handle_t GtkWidget* #define cef_window_handle_t GtkWidget*
#define cef_cursor_handle_t void*
// Class representing window information. // Class representing window information.
typedef struct _cef_window_info_t typedef struct _cef_window_info_t

View File

@ -45,6 +45,7 @@ class NSView;
#else #else
#define cef_window_handle_t void* #define cef_window_handle_t void*
#endif #endif
#define cef_cursor_handle_t void*
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -41,6 +41,7 @@ extern "C" {
// Window handle. // Window handle.
#define cef_window_handle_t HWND #define cef_window_handle_t HWND
#define cef_cursor_handle_t HCURSOR
// Class representing window information. // Class representing window information.
typedef struct _cef_window_info_t typedef struct _cef_window_info_t
@ -55,6 +56,11 @@ typedef struct _cef_window_info_t
int m_nHeight; int m_nHeight;
cef_window_handle_t m_hWndParent; cef_window_handle_t m_hWndParent;
HMENU m_hMenu; HMENU m_hMenu;
// If window rendering is disabled no browser window will be created. Set
// |m_hWndParent| to the window that will act as the parent for popup menus,
// dialog boxes, etc.
BOOL m_bWindowRenderingDisabled;
// Handle for the new browser window. // Handle for the new browser window.
cef_window_handle_t m_hWnd; cef_window_handle_t m_hWnd;

View File

@ -64,6 +64,10 @@ public:
CRITICAL_SECTION m_sec; CRITICAL_SECTION m_sec;
}; };
// Handle types.
#define CefWindowHandle cef_window_handle_t
#define CefCursorHandle cef_cursor_handle_t
// Class representing window information. // Class representing window information.
class CefWindowInfo : public cef_window_info_t class CefWindowInfo : public cef_window_info_t
{ {
@ -120,6 +124,7 @@ public:
m_nHeight = r.m_nHeight; m_nHeight = r.m_nHeight;
m_hWndParent = r.m_hWndParent; m_hWndParent = r.m_hWndParent;
m_hMenu = r.m_hMenu; m_hMenu = r.m_hMenu;
m_bWindowRenderingDisabled = r.m_bWindowRenderingDisabled;
m_hWnd = r.m_hWnd; m_hWnd = r.m_hWnd;
return *this; return *this;
} }
@ -148,6 +153,12 @@ public:
cef_string_copy(windowName.c_str(), windowName.length(), &m_windowName); cef_string_copy(windowName.c_str(), windowName.length(), &m_windowName);
} }
void SetAsOffScreen(HWND hWndParent)
{
m_bWindowRenderingDisabled = TRUE;
m_hWndParent = hWndParent;
}
protected: protected:
void Init() void Init()
{ {
@ -201,8 +212,6 @@ public:
} }
}; };
// Window handle.
#define CefWindowHandle cef_window_handle_t
#endif // _WIN32 #endif // _WIN32
#endif // _CEF_WIN_H #endif // _CEF_WIN_H

View File

@ -70,6 +70,29 @@ void UIT_CreateBrowserWithHelper(CreateBrowserHelper* helper)
} // namespace } // namespace
CefBrowserImpl::PaintDelegate::PaintDelegate(CefBrowserImpl* browser)
: browser_(browser)
{
}
CefBrowserImpl::PaintDelegate::~PaintDelegate()
{
}
void CefBrowserImpl::PaintDelegate::Paint(bool popup,
const gfx::Rect& dirtyRect,
const void* buffer)
{
CefRefPtr<CefHandler> handler = browser_->GetHandler();
if (!handler.get())
return;
CefRect rect(dirtyRect.x(), dirtyRect.y(), dirtyRect.width(),
dirtyRect.height());
handler->HandlePaint(browser_, (popup?PET_POPUP:PET_VIEW), rect, buffer);
}
// static // static
bool CefBrowser::CreateBrowser(CefWindowInfo& windowInfo, bool popup, bool CefBrowser::CreateBrowser(CefWindowInfo& windowInfo, bool popup,
CefRefPtr<CefHandler> handler, CefRefPtr<CefHandler> handler,
@ -282,6 +305,137 @@ void CefBrowserImpl::CloseDevTools()
&CefBrowserImpl::UIT_CloseDevTools)); &CefBrowserImpl::UIT_CloseDevTools));
} }
bool CefBrowserImpl::GetSize(PaintElementType type, int& width, int& height)
{
if (!CefThread::CurrentlyOn(CefThread::UI)) {
NOTREACHED();
return false;
}
width = height = 0;
if(type == PET_VIEW) {
WebViewHost* host = UIT_GetWebViewHost();
if (host) {
host->GetSize(width, height);
return true;
}
} else if(type == PET_POPUP) {
if (popuphost_) {
popuphost_->GetSize(width, height);
return true;
}
}
return false;
}
void CefBrowserImpl::SetSize(PaintElementType type, int width, int height)
{
// Intentially post event tasks in all cases so that painting tasks can be
// handled at sane times.
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_SetSize, type, width, height));
}
bool CefBrowserImpl::IsPopupVisible()
{
if (!CefThread::CurrentlyOn(CefThread::UI)) {
NOTREACHED();
return false;
}
return (popuphost_ != NULL);
}
void CefBrowserImpl::HidePopup()
{
// Intentially post event tasks in all cases so that painting tasks can be
// handled at sane times.
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_ClosePopupWidget));
}
void CefBrowserImpl::Invalidate(const CefRect& dirtyRect)
{
// Intentially post event tasks in all cases so that painting tasks can be
// handled at sane times.
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_Invalidate, dirtyRect));
}
bool CefBrowserImpl::GetImage(PaintElementType type, int width, int height,
void* buffer)
{
if (!CefThread::CurrentlyOn(CefThread::UI)) {
NOTREACHED();
return false;
}
if(type == PET_VIEW) {
WebViewHost* host = UIT_GetWebViewHost();
if (host)
return host->GetImage(width, height, buffer);
} else if(type == PET_POPUP) {
if (popuphost_)
return popuphost_->GetImage(width, height, buffer);
}
return false;
}
void CefBrowserImpl::SendKeyEvent(KeyType type, int key, int modifiers,
bool sysChar, bool imeChar)
{
// Intentially post event tasks in all cases so that painting tasks can be
// handled at sane times.
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_SendKeyEvent, type, key, modifiers, sysChar,
imeChar));
}
void CefBrowserImpl::SendMouseClickEvent(int x, int y, MouseButtonType type,
bool mouseUp, int clickCount)
{
// Intentially post event tasks in all cases so that painting tasks can be
// handled at sane times.
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_SendMouseClickEvent, x, y, type, mouseUp,
clickCount));
}
void CefBrowserImpl::SendMouseMoveEvent(int x, int y, bool mouseLeave)
{
// Intentially post event tasks in all cases so that painting tasks can be
// handled at sane times.
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_SendMouseMoveEvent, x, y, mouseLeave));
}
void CefBrowserImpl::SendMouseWheelEvent(int x, int y, int delta)
{
// Intentially post event tasks in all cases so that painting tasks can be
// handled at sane times.
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_SendMouseWheelEvent, x, y, delta));
}
void CefBrowserImpl::SendFocusEvent(bool setFocus)
{
// Intentially post event tasks in all cases so that painting tasks can be
// handled at sane times.
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_SendFocusEvent, setFocus));
}
void CefBrowserImpl::SendCaptureLostEvent()
{
// Intentially post event tasks in all cases so that painting tasks can be
// handled at sane times.
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_SendCaptureLostEvent));
}
void CefBrowserImpl::Undo(CefRefPtr<CefFrame> frame) void CefBrowserImpl::Undo(CefRefPtr<CefFrame> frame)
{ {
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this, CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
@ -474,17 +628,14 @@ CefRefPtr<CefFrame> CefBrowserImpl::UIT_GetCefFrame(WebFrame* frame)
CefRefPtr<CefFrame> cef_frame; CefRefPtr<CefFrame> cef_frame;
WebView *view = UIT_GetWebView(); if(frame->parent() == 0) {
if(view) { // Use the single main frame reference.
if(frame == view->mainFrame()) { cef_frame = GetMainCefFrame();
// Use the single main frame reference. } else {
cef_frame = GetMainCefFrame(); // Locate or create the appropriate named reference.
} else { CefString name = string16(frame->name());
// Locate or create the appropriate named reference. DCHECK(!name.empty());
CefString name = string16(frame->name()); cef_frame = GetCefFrame(name);
DCHECK(!name.empty());
cef_frame = GetCefFrame(name);
}
} }
return cef_frame; return cef_frame;
@ -555,7 +706,10 @@ void CefBrowserImpl::UIT_DestroyBrowser()
void CefBrowserImpl::UIT_CloseBrowser() void CefBrowserImpl::UIT_CloseBrowser()
{ {
REQUIRE_UIT(); REQUIRE_UIT();
UIT_CloseView(UIT_GetMainWndHandle()); if (!IsWindowRenderingDisabled())
UIT_CloseView(UIT_GetMainWndHandle());
else
UIT_DestroyBrowser();
} }
void CefBrowserImpl::UIT_LoadURL(CefRefPtr<CefFrame> frame, void CefBrowserImpl::UIT_LoadURL(CefRefPtr<CefFrame> frame,
@ -775,13 +929,110 @@ bool CefBrowserImpl::UIT_Navigate(const BrowserNavigationEntry& entry,
view->setFocusedFrame(frame); view->setFocusedFrame(frame);
// Give focus to the window if it is currently visible. // Give focus to the window if it is currently visible.
if(UIT_IsViewVisible(UIT_GetMainWndHandle())) if (!IsWindowRenderingDisabled() &&
UIT_IsViewVisible(UIT_GetMainWndHandle()))
UIT_SetFocus(UIT_GetWebViewHost(), true); UIT_SetFocus(UIT_GetWebViewHost(), true);
} }
return true; return true;
} }
void CefBrowserImpl::UIT_SetSize(PaintElementType type, int width, int height)
{
if(type == PET_VIEW) {
WebViewHost* host = UIT_GetWebViewHost();
if (host)
host->SetSize(width, height);
} else if(type == PET_POPUP) {
if (popuphost_)
popuphost_->SetSize(width, height);
}
}
void CefBrowserImpl::UIT_Invalidate(const CefRect& dirtyRect)
{
REQUIRE_UIT();
WebViewHost* host = UIT_GetWebViewHost();
if (host) {
host->InvalidateRect(gfx::Rect(dirtyRect.x, dirtyRect.y, dirtyRect.width,
dirtyRect.height));
}
}
void CefBrowserImpl::UIT_SendKeyEvent(KeyType type, int key, int modifiers,
bool sysChar, bool imeChar)
{
REQUIRE_UIT();
if (popuphost_) {
// Send the event to the popup.
popuphost_->SendKeyEvent(type, key, modifiers, sysChar, imeChar);
} else {
WebViewHost* host = UIT_GetWebViewHost();
if (host)
host->SendKeyEvent(type, key, modifiers, sysChar, imeChar);
}
}
void CefBrowserImpl::UIT_SendMouseClickEvent(int x, int y, MouseButtonType type,
bool mouseUp, int clickCount)
{
REQUIRE_UIT();
if (popuphost_ && popup_rect_.Contains(x, y)) {
// Send the event to the popup.
popuphost_->SendMouseClickEvent(x - popup_rect_.x(), y - popup_rect_.y(),
type, mouseUp, clickCount);
} else {
WebViewHost* host = UIT_GetWebViewHost();
if (host)
host->SendMouseClickEvent(x, y, type, mouseUp, clickCount);
}
}
void CefBrowserImpl::UIT_SendMouseMoveEvent(int x, int y, bool mouseLeave)
{
REQUIRE_UIT();
if (popuphost_ && popup_rect_.Contains(x, y)) {
// Send the event to the popup.
popuphost_->SendMouseMoveEvent(x - popup_rect_.x(), y - popup_rect_.y(),
mouseLeave);
} else {
WebViewHost* host = UIT_GetWebViewHost();
if (host)
host->SendMouseMoveEvent(x, y, mouseLeave);
}
}
void CefBrowserImpl::UIT_SendMouseWheelEvent(int x, int y, int delta)
{
REQUIRE_UIT();
if (popuphost_ && popup_rect_.Contains(x, y)) {
// Send the event to the popup.
popuphost_->SendMouseWheelEvent(x - popup_rect_.x(), y - popup_rect_.y(),
delta);
} else {
WebViewHost* host = UIT_GetWebViewHost();
if (host)
host->SendMouseWheelEvent(x, y, delta);
}
}
void CefBrowserImpl::UIT_SendFocusEvent(bool setFocus)
{
REQUIRE_UIT();
WebViewHost* host = UIT_GetWebViewHost();
if (host)
host->SendFocusEvent(setFocus);
}
void CefBrowserImpl::UIT_SendCaptureLostEvent()
{
REQUIRE_UIT();
WebViewHost* host = UIT_GetWebViewHost();
if (host)
host->SendCaptureLostEvent();
}
CefRefPtr<CefBrowserImpl> CefBrowserImpl::UIT_CreatePopupWindow( CefRefPtr<CefBrowserImpl> CefBrowserImpl::UIT_CreatePopupWindow(
const CefString& url, const CefPopupFeatures& features) const CefString& url, const CefPopupFeatures& features)
{ {
@ -828,23 +1079,35 @@ CefRefPtr<CefBrowserImpl> CefBrowserImpl::UIT_CreatePopupWindow(
WebKit::WebWidget* CefBrowserImpl::UIT_CreatePopupWidget() WebKit::WebWidget* CefBrowserImpl::UIT_CreatePopupWidget()
{ {
REQUIRE_UIT(); REQUIRE_UIT();
DCHECK(!popuphost_); DCHECK(!popuphost_);
popuphost_ = WebWidgetHost::Create(UIT_GetMainWndHandle(), popuphost_ = WebWidgetHost::Create(
popup_delegate_.get()); (IsWindowRenderingDisabled()?NULL:UIT_GetMainWndHandle()),
popup_delegate_.get(), paint_delegate_.get());
popuphost_->set_popup(true); popuphost_->set_popup(true);
return popuphost_->webwidget(); return popuphost_->webwidget();
} }
void CefBrowserImpl::UIT_ClosePopupWidget() void CefBrowserImpl::UIT_ClosePopupWidget()
{ {
REQUIRE_UIT(); REQUIRE_UIT();
if (!popuphost_)
return;
#if !defined(OS_MACOSX) #if !defined(OS_MACOSX)
// Mac uses a WebPopupMenu for select lists so no closing is necessary. // Mac uses a WebPopupMenu for select lists so no closing is necessary.
UIT_CloseView(UIT_GetPopupWndHandle()); if (!IsWindowRenderingDisabled())
UIT_CloseView(UIT_GetPopupWndHandle());
#endif #endif
popuphost_ = NULL; popuphost_ = NULL;
popup_rect_ = gfx::Rect();
if (IsWindowRenderingDisabled() && handler_.get()) {
// Notify the handler of popup visibility change.
handler_->HandlePopupChange(this, false, CefRect());
}
} }
void CefBrowserImpl::UIT_Show(WebKit::WebNavigationPolicy policy) void CefBrowserImpl::UIT_Show(WebKit::WebNavigationPolicy policy)

View File

@ -36,6 +36,19 @@ class WebView;
class CefBrowserImpl : public CefThreadSafeBase<CefBrowser> class CefBrowserImpl : public CefThreadSafeBase<CefBrowser>
{ {
public: public:
class PaintDelegate : public WebWidgetHost::PaintDelegate
{
public:
PaintDelegate(CefBrowserImpl* browser);
virtual ~PaintDelegate();
virtual void Paint(bool popup, const gfx::Rect& dirtyRect,
const void* buffer);
protected:
CefBrowserImpl* browser_;
};
CefBrowserImpl(const CefWindowInfo& windowInfo, CefBrowserImpl(const CefWindowInfo& windowInfo,
const CefBrowserSettings& settings, bool popup, const CefBrowserSettings& settings, bool popup,
CefRefPtr<CefHandler> handler); CefRefPtr<CefHandler> handler);
@ -71,6 +84,22 @@ public:
virtual void SetZoomLevel(double zoomLevel); virtual void SetZoomLevel(double zoomLevel);
virtual void ShowDevTools(); virtual void ShowDevTools();
virtual void CloseDevTools(); virtual void CloseDevTools();
virtual bool IsWindowRenderingDisabled();
virtual bool GetSize(PaintElementType type, int& width, int& height);
virtual void SetSize(PaintElementType type, int width, int height);
virtual bool IsPopupVisible();
virtual void HidePopup();
virtual void Invalidate(const CefRect& dirtyRect);
virtual bool GetImage(PaintElementType type, int width, int height,
void* buffer);
virtual void SendKeyEvent(KeyType type, int key, int modifiers, bool sysChar,
bool imeChar);
virtual void SendMouseClickEvent(int x, int y, MouseButtonType type,
bool mouseUp, int clickCount);
virtual void SendMouseMoveEvent(int x, int y, bool mouseLeave);
virtual void SendMouseWheelEvent(int x, int y, int delta);
virtual void SendFocusEvent(bool setFocus);
virtual void SendCaptureLostEvent();
// Frame-related methods // Frame-related methods
void Undo(CefRefPtr<CefFrame> frame); void Undo(CefRefPtr<CefFrame> frame);
@ -134,8 +163,9 @@ public:
REQUIRE_UIT(); REQUIRE_UIT();
return delegate_.get(); return delegate_.get();
} }
gfx::NativeView UIT_GetWebViewWndHandle() const { gfx::NativeView UIT_GetWebViewWndHandle() {
REQUIRE_UIT(); REQUIRE_UIT();
DCHECK(!IsWindowRenderingDisabled());
return webviewhost_->view_handle(); return webviewhost_->view_handle();
} }
WebKit::WebWidget* UIT_GetPopup() const { WebKit::WebWidget* UIT_GetPopup() const {
@ -150,11 +180,12 @@ public:
REQUIRE_UIT(); REQUIRE_UIT();
return popup_delegate_.get(); return popup_delegate_.get();
} }
gfx::NativeView UIT_GetPopupWndHandle() const { gfx::NativeView UIT_GetPopupWndHandle() {
REQUIRE_UIT(); REQUIRE_UIT();
DCHECK(!IsWindowRenderingDisabled());
return popuphost_->view_handle(); return popuphost_->view_handle();
} }
gfx::NativeView UIT_GetMainWndHandle() const; gfx::NativeView UIT_GetMainWndHandle();
BrowserNavigationController* UIT_GetNavigationController() { BrowserNavigationController* UIT_GetNavigationController() {
REQUIRE_UIT(); REQUIRE_UIT();
@ -218,6 +249,16 @@ public:
bool reload, bool reload,
bool ignoreCahce); bool ignoreCahce);
void UIT_SetFocus(WebWidgetHost* host, bool enable); void UIT_SetFocus(WebWidgetHost* host, bool enable);
void UIT_SetSize(PaintElementType type, int width, int height);
void UIT_Invalidate(const CefRect& dirtyRect);
void UIT_SendKeyEvent(KeyType type, int key, int modifiers, bool sysChar,
bool imeChar);
void UIT_SendMouseClickEvent(int x, int y, MouseButtonType type,
bool mouseUp, int clickCount);
void UIT_SendMouseMoveEvent(int x, int y, bool mouseLeave);
void UIT_SendMouseWheelEvent(int x, int y, int delta);
void UIT_SendFocusEvent(bool setFocus);
void UIT_SendCaptureLostEvent();
CefRefPtr<CefBrowserImpl> UIT_CreatePopupWindow(const CefString& url, CefRefPtr<CefBrowserImpl> UIT_CreatePopupWindow(const CefString& url,
const CefPopupFeatures& features); const CefPopupFeatures& features);
@ -276,6 +317,8 @@ public:
bool can_go_back(); bool can_go_back();
bool can_go_forward(); bool can_go_forward();
void set_popup_rect(const gfx::Rect& rect) { popup_rect_ = rect; }
static bool ImplementsThreadSafeReferenceCounting() { return true; } static bool ImplementsThreadSafeReferenceCounting() { return true; }
protected: protected:
@ -293,9 +336,11 @@ protected:
CefRefPtr<CefHandler> handler_; CefRefPtr<CefHandler> handler_;
scoped_ptr<WebViewHost> webviewhost_; scoped_ptr<WebViewHost> webviewhost_;
WebWidgetHost* popuphost_; WebWidgetHost* popuphost_;
gfx::Rect popup_rect_;
scoped_ptr<BrowserWebViewDelegate> delegate_; scoped_ptr<BrowserWebViewDelegate> delegate_;
scoped_ptr<BrowserWebViewDelegate> popup_delegate_; scoped_ptr<BrowserWebViewDelegate> popup_delegate_;
scoped_ptr<BrowserNavigationController> nav_controller_; scoped_ptr<BrowserNavigationController> nav_controller_;
scoped_ptr<PaintDelegate> paint_delegate_;
scoped_ptr<BrowserDevToolsAgent> dev_tools_agent_; scoped_ptr<BrowserDevToolsAgent> dev_tools_agent_;
scoped_ptr<BrowserDevToolsClient> dev_tools_client_; scoped_ptr<BrowserDevToolsClient> dev_tools_client_;

View File

@ -24,7 +24,13 @@ CefWindowHandle CefBrowserImpl::GetWindowHandle()
return window_info_.m_Widget; return window_info_.m_Widget;
} }
gfx::NativeWindow CefBrowserImpl::UIT_GetMainWndHandle() const { bool CefBrowserImpl::IsWindowRenderingDisabled()
{
// TODO(port): Add support for off-screen rendering.
return false;
}
gfx::NativeWindow CefBrowserImpl::UIT_GetMainWndHandle() {
REQUIRE_UIT(); REQUIRE_UIT();
GtkWidget* toplevel = gtk_widget_get_ancestor(window_info_.m_Widget, GtkWidget* toplevel = gtk_widget_get_ancestor(window_info_.m_Widget,
GTK_TYPE_WINDOW); GTK_TYPE_WINDOW);
@ -51,7 +57,8 @@ void CefBrowserImpl::UIT_CreateBrowser(const CefString& url)
// Create the webview host object // Create the webview host object
webviewhost_.reset( webviewhost_.reset(
WebViewHost::Create(window_info_.m_ParentWidget, gfx::Rect(), WebViewHost::Create(window_info_.m_ParentWidget, gfx::Rect(),
delegate_.get(), dev_tools_agent_.get(), prefs)); delegate_.get(), NULL, dev_tools_agent_.get(),
prefs));
delegate_->RegisterDragDrop(); delegate_->RegisterDragDrop();
if (!settings_.developer_tools_disabled) if (!settings_.developer_tools_disabled)

View File

@ -25,7 +25,13 @@ CefWindowHandle CefBrowserImpl::GetWindowHandle()
return window_info_.m_View; return window_info_.m_View;
} }
gfx::NativeView CefBrowserImpl::UIT_GetMainWndHandle() const { bool CefBrowserImpl::IsWindowRenderingDisabled()
{
// TODO(port): Add support for off-screen rendering.
return false;
}
gfx::NativeView CefBrowserImpl::UIT_GetMainWndHandle() {
REQUIRE_UIT(); REQUIRE_UIT();
return window_info_.m_View; return window_info_.m_View;
} }
@ -79,7 +85,7 @@ void CefBrowserImpl::UIT_CreateBrowser(const CefString& url)
// Create the webview host object // Create the webview host object
webviewhost_.reset( webviewhost_.reset(
WebViewHost::Create(parentView, contentRect, delegate_.get(), WebViewHost::Create(parentView, contentRect, delegate_.get(),
dev_tools_agent_.get(), prefs)); NULL, dev_tools_agent_.get(), prefs));
delegate_->RegisterDragDrop(); delegate_->RegisterDragDrop();
if (!settings_.developer_tools_disabled) if (!settings_.developer_tools_disabled)

View File

@ -89,9 +89,15 @@ CefWindowHandle CefBrowserImpl::GetWindowHandle()
return window_info_.m_hWnd; return window_info_.m_hWnd;
} }
gfx::NativeWindow CefBrowserImpl::UIT_GetMainWndHandle() const { bool CefBrowserImpl::IsWindowRenderingDisabled()
{
return (window_info_.m_bWindowRenderingDisabled ? true : false);
}
gfx::NativeWindow CefBrowserImpl::UIT_GetMainWndHandle() {
REQUIRE_UIT(); REQUIRE_UIT();
return window_info_.m_hWnd; return window_info_.m_bWindowRenderingDisabled ?
window_info_.m_hWndParent : window_info_.m_hWnd;
} }
void CefBrowserImpl::UIT_CreateBrowser(const CefString& url) void CefBrowserImpl::UIT_CreateBrowser(const CefString& url)
@ -99,19 +105,24 @@ void CefBrowserImpl::UIT_CreateBrowser(const CefString& url)
REQUIRE_UIT(); REQUIRE_UIT();
Lock(); Lock();
std::wstring windowName(CefString(&window_info_.m_windowName)); if (!window_info_.m_bWindowRenderingDisabled) {
std::wstring windowName(CefString(&window_info_.m_windowName));
// Create the new browser window
window_info_.m_hWnd = CreateWindowEx(window_info_.m_dwExStyle, GetWndClass(),
windowName.c_str(), window_info_.m_dwStyle,
window_info_.m_x, window_info_.m_y, window_info_.m_nWidth,
window_info_.m_nHeight, window_info_.m_hWndParent, window_info_.m_hMenu,
::GetModuleHandle(NULL), NULL);
DCHECK(window_info_.m_hWnd != NULL);
// Set window user data to this object for future reference from the window // Create the new browser window
// procedure window_info_.m_hWnd = CreateWindowEx(window_info_.m_dwExStyle,
ui::SetWindowUserData(window_info_.m_hWnd, this); GetWndClass(), windowName.c_str(), window_info_.m_dwStyle,
window_info_.m_x, window_info_.m_y, window_info_.m_nWidth,
window_info_.m_nHeight, window_info_.m_hWndParent, window_info_.m_hMenu,
::GetModuleHandle(NULL), NULL);
DCHECK(window_info_.m_hWnd != NULL);
// Set window user data to this object for future reference from the window
// procedure
ui::SetWindowUserData(window_info_.m_hWnd, this);
} else {
// Create a new paint delegate.
paint_delegate_.reset(new PaintDelegate(this));
}
if (!settings_.developer_tools_disabled) if (!settings_.developer_tools_disabled)
dev_tools_agent_.reset(new BrowserDevToolsAgent()); dev_tools_agent_.reset(new BrowserDevToolsAgent());
@ -128,29 +139,32 @@ void CefBrowserImpl::UIT_CreateBrowser(const CefString& url)
// Create the webview host object // Create the webview host object
webviewhost_.reset( webviewhost_.reset(
WebViewHost::Create(window_info_.m_hWnd, gfx::Rect(), delegate_.get(), WebViewHost::Create(window_info_.m_hWnd, gfx::Rect(), delegate_.get(),
dev_tools_agent_.get(), prefs)); paint_delegate_.get(), dev_tools_agent_.get(),
prefs));
if (!settings_.developer_tools_disabled) if (!settings_.developer_tools_disabled)
dev_tools_agent_->SetWebView(webviewhost_->webview()); dev_tools_agent_->SetWebView(webviewhost_->webview());
if (!settings_.drag_drop_disabled)
delegate_->RegisterDragDrop();
Unlock(); Unlock();
// Size the web view window to the browser window if (!window_info_.m_bWindowRenderingDisabled) {
RECT cr; if (!settings_.drag_drop_disabled)
GetClientRect(window_info_.m_hWnd, &cr); delegate_->RegisterDragDrop();
// Size the web view window to the browser window
RECT cr;
GetClientRect(window_info_.m_hWnd, &cr);
// Respect the WS_VISIBLE window style when setting the window's position // Respect the WS_VISIBLE window style when setting the window's position
UINT flags = SWP_NOZORDER; UINT flags = SWP_NOZORDER;
if (window_info_.m_dwStyle & WS_VISIBLE) if (window_info_.m_dwStyle & WS_VISIBLE)
flags |= SWP_SHOWWINDOW; flags |= SWP_SHOWWINDOW;
else else
flags |= SWP_NOACTIVATE; flags |= SWP_NOACTIVATE;
SetWindowPos(UIT_GetWebViewWndHandle(), NULL, cr.left, cr.top, cr.right, SetWindowPos(UIT_GetWebViewWndHandle(), NULL, cr.left, cr.top, cr.right,
cr.bottom, flags); cr.bottom, flags);
}
if(handler_.get()) { if(handler_.get()) {
// Notify the handler that we're done creating the new window // Notify the handler that we're done creating the new window

View File

@ -43,7 +43,6 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/WebKitClient.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebKitClient.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPoint.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebPoint.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupMenu.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginParams.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginParams.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebRange.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebRange.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebScreenInfo.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebScreenInfo.h"
@ -102,7 +101,6 @@ using WebKit::WebNode;
using WebKit::WebPlugin; using WebKit::WebPlugin;
using WebKit::WebPluginParams; using WebKit::WebPluginParams;
using WebKit::WebPoint; using WebKit::WebPoint;
using WebKit::WebPopupMenu;
using WebKit::WebPopupType; using WebKit::WebPopupType;
using WebKit::WebRange; using WebKit::WebRange;
using WebKit::WebRect; using WebKit::WebRect;
@ -425,6 +423,12 @@ void BrowserWebViewDelegate::startDragging(
const WebImage& image, const WebImage& image,
const WebPoint& image_offset) { const WebPoint& image_offset) {
#if defined(OS_WIN) #if defined(OS_WIN)
// Dragging is not supported when window rendering is disabled.
if (browser_->IsWindowRenderingDisabled()) {
EndDragging();
return;
}
drag_delegate_ = new BrowserDragDelegate(this); drag_delegate_ = new BrowserDragDelegate(this);
drag_delegate_->StartDragging(WebDropData(data), mask, image.getSkBitmap(), drag_delegate_->StartDragging(WebDropData(data), mask, image.getSkBitmap(),
image_offset); image_offset);
@ -518,8 +522,22 @@ void BrowserWebViewDelegate::closeWidgetSoon() {
} }
WebScreenInfo BrowserWebViewDelegate::screenInfo() { WebScreenInfo BrowserWebViewDelegate::screenInfo() {
if (WebWidgetHost* host = GetWidgetHost()) if (WebWidgetHost* host = GetWidgetHost()) {
return host->GetScreenInfo(); WebScreenInfo info = host->GetScreenInfo();
if (browser_->IsWindowRenderingDisabled()) {
// Retrieve the screen rectangle from the handler.
CefRefPtr<CefHandler> handler = browser_->GetHandler();
if (handler.get()) {
CefRect rect(info.rect.x, info.rect.y, info.rect.width,
info.rect.height);
if (handler->HandleGetRect(browser_, true, rect) == RV_CONTINUE) {
info.rect = WebRect(rect.x, rect.y, rect.width, rect.height);
info.availableRect = info.rect;
}
}
}
}
return WebScreenInfo(); return WebScreenInfo();
} }
@ -985,14 +1003,13 @@ void BrowserWebViewDelegate::UpdateURL(WebFrame* frame) {
} }
bool is_main_frame = (frame->parent() == 0); bool is_main_frame = (frame->parent() == 0);
if (is_main_frame) { CefRefPtr<CefHandler> handler = browser_->GetHandler();
CefRefPtr<CefHandler> handler = browser_->GetHandler();
if(handler.get()) { if (is_main_frame && handler.get()) {
// Notify the handler of an address change // Notify the handler of an address change
std::string url = std::string(entry->GetURL().spec().c_str()); std::string url = std::string(entry->GetURL().spec().c_str());
handler->HandleAddressChange(browser_, browser_->UIT_GetCefFrame(frame), handler->HandleAddressChange(browser_, browser_->UIT_GetCefFrame(frame),
url); url);
}
} }
const WebHistoryItem& history_item = frame->currentHistoryItem(); const WebHistoryItem& history_item = frame->currentHistoryItem();
@ -1001,10 +1018,24 @@ void BrowserWebViewDelegate::UpdateURL(WebFrame* frame) {
BrowserNavigationController* controller = BrowserNavigationController* controller =
browser_->UIT_GetNavigationController(); browser_->UIT_GetNavigationController();
bool old_can_go_back = !controller->IsAtStart();
bool old_can_go_forward = !controller->IsAtEnd();
controller->DidNavigateToEntry(entry.release()); controller->DidNavigateToEntry(entry.release());
browser_->set_nav_state(!controller->IsAtStart(), !controller->IsAtEnd()); bool new_can_go_back = !controller->IsAtStart();
bool new_can_go_forward = !controller->IsAtEnd();
last_page_id_updated_ = std::max(last_page_id_updated_, page_id_); last_page_id_updated_ = std::max(last_page_id_updated_, page_id_);
if (old_can_go_back != new_can_go_back ||
old_can_go_forward != new_can_go_forward) {
browser_->set_nav_state(new_can_go_back, new_can_go_forward);
if (handler.get()) {
// Notify the handler of a navigation state change
handler->HandleNavStateChange(browser_, new_can_go_back,
new_can_go_forward);
}
}
} }
void BrowserWebViewDelegate::UpdateSessionHistory(WebFrame* frame) { void BrowserWebViewDelegate::UpdateSessionHistory(WebFrame* frame) {

View File

@ -35,6 +35,7 @@
#include "webkit/plugins/npapi/webplugin.h" #include "webkit/plugins/npapi/webplugin.h"
#include "webkit/plugins/npapi/webplugin_delegate_impl.h" #include "webkit/plugins/npapi/webplugin_delegate_impl.h"
using webkit::npapi::WebPluginDelegateImpl;
using WebKit::WebContextMenuData; using WebKit::WebContextMenuData;
using WebKit::WebCursorInfo; using WebKit::WebCursorInfo;
using WebKit::WebFrame; using WebKit::WebFrame;
@ -43,6 +44,8 @@ using WebKit::WebPopupMenuInfo;
using WebKit::WebRect; using WebKit::WebRect;
using WebKit::WebWidget; using WebKit::WebWidget;
static const wchar_t kPluginWindowClassName[] = L"WebPluginHost";
// WebViewClient -------------------------------------------------------------- // WebViewClient --------------------------------------------------------------
WebWidget* BrowserWebViewDelegate::createPopupMenu( WebWidget* BrowserWebViewDelegate::createPopupMenu(
@ -55,16 +58,25 @@ WebWidget* BrowserWebViewDelegate::createPopupMenu(
void BrowserWebViewDelegate::show(WebNavigationPolicy) { void BrowserWebViewDelegate::show(WebNavigationPolicy) {
if (this == browser_->UIT_GetWebViewDelegate()) { if (this == browser_->UIT_GetWebViewDelegate()) {
// Restore the window and bring it to the top if the window is currently if (!browser_->IsWindowRenderingDisabled()) {
// visible. // Restore the window and bring it to the top if the window is currently
HWND root = GetAncestor(browser_->UIT_GetMainWndHandle(), GA_ROOT); // visible.
if(IsWindowVisible(root)) { HWND root = GetAncestor(browser_->UIT_GetMainWndHandle(), GA_ROOT);
ShowWindow(root, SW_SHOWNORMAL); if(IsWindowVisible(root)) {
SetWindowPos(root, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); ShowWindow(root, SW_SHOWNORMAL);
SetWindowPos(root, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
}
} }
} else if (this == browser_->UIT_GetPopupDelegate()) { } else if (this == browser_->UIT_GetPopupDelegate()) {
// Show popup widgets without activation. if (!browser_->IsWindowRenderingDisabled()) {
ShowWindow(browser_->UIT_GetPopupWndHandle(), SW_SHOWNA); // Show popup widgets without activation.
ShowWindow(browser_->UIT_GetPopupWndHandle(), SW_SHOWNA);
} else {
// Notify the handler of popup visibility change.
CefRefPtr<CefHandler> handler = browser_->GetHandler();
if (handler.get())
handler->HandlePopupChange(browser_, true, CefRect());
}
} }
} }
@ -74,15 +86,34 @@ void BrowserWebViewDelegate::didChangeCursor(const WebCursorInfo& cursor_info) {
HMODULE hModule = ::GetModuleHandle(L"libcef.dll"); HMODULE hModule = ::GetModuleHandle(L"libcef.dll");
if(!hModule) if(!hModule)
hModule = ::GetModuleHandle(NULL); hModule = ::GetModuleHandle(NULL);
host->SetCursor(current_cursor_.GetCursor(hModule)); HCURSOR hCursor = current_cursor_.GetCursor(hModule);
if (!browser_->IsWindowRenderingDisabled()) {
host->SetCursor(hCursor);
} else {
// Notify the handler of cursor change.
CefRefPtr<CefHandler> handler = browser_->GetHandler();
if (handler.get())
handler->HandleCursorChange(browser_, hCursor);
}
} }
} }
WebRect BrowserWebViewDelegate::windowRect() { WebRect BrowserWebViewDelegate::windowRect() {
if (WebWidgetHost* host = GetWidgetHost()) { if (WebWidgetHost* host = GetWidgetHost()) {
RECT rect; if (!browser_->IsWindowRenderingDisabled()) {
::GetWindowRect(host->view_handle(), &rect); RECT rect;
return gfx::Rect(rect); ::GetWindowRect(host->view_handle(), &rect);
return gfx::Rect(rect);
} else {
// Retrieve the view rectangle from the handler.
CefRefPtr<CefHandler> handler = browser_->GetHandler();
if (handler.get()) {
CefRect rect(0, 0, 0, 0);
if (handler->HandleGetRect(browser_, false, rect) == RV_CONTINUE)
return WebRect(rect.x, rect.y, rect.width, rect.height);
}
}
} }
return WebRect(); return WebRect();
} }
@ -91,8 +122,20 @@ void BrowserWebViewDelegate::setWindowRect(const WebRect& rect) {
if (this == browser_->UIT_GetWebViewDelegate()) { if (this == browser_->UIT_GetWebViewDelegate()) {
// ignored // ignored
} else if (this == browser_->UIT_GetPopupDelegate()) { } else if (this == browser_->UIT_GetPopupDelegate()) {
MoveWindow(browser_->UIT_GetPopupWndHandle(), if (!browser_->IsWindowRenderingDisabled()) {
rect.x, rect.y, rect.width, rect.height, FALSE); MoveWindow(browser_->UIT_GetPopupWndHandle(), rect.x, rect.y, rect.width,
rect.height, FALSE);
} else {
browser_->set_popup_rect(rect);
browser_->UIT_GetPopupHost()->SetSize(rect.width, rect.height);
// Notify the handler of popup size change.
CefRefPtr<CefHandler> handler = browser_->GetHandler();
if (handler.get()) {
handler->HandlePopupChange(browser_, true,
CefRect(rect.x, rect.y, rect.width, rect.height));
}
}
} }
} }
@ -147,23 +190,66 @@ webkit::npapi::WebPluginDelegate* BrowserWebViewDelegate::CreatePluginDelegate(
const FilePath& file_path, const FilePath& file_path,
const std::string& mime_type) const std::string& mime_type)
{ {
HWND hwnd = browser_->UIT_GetWebViewHost() ? WebViewHost* host = browser_->UIT_GetWebViewHost();
browser_->UIT_GetWebViewHost()->view_handle() : NULL; if (!host)
if (!hwnd)
return NULL; return NULL;
return webkit::npapi::WebPluginDelegateImpl::Create(file_path, mime_type, HWND hwnd;
hwnd);
if (!browser_->IsWindowRenderingDisabled()) {
// Parent the plugin container to the existing browser window.
hwnd = browser_->UIT_GetWebViewHost()->view_handle();
DCHECK(hwnd != NULL);
} else {
// Parent the plugin container to the main window handle provided by the
// user.
hwnd = browser_->UIT_GetMainWndHandle();
DCHECK(hwnd != NULL);
}
return WebPluginDelegateImpl::Create(file_path, mime_type, hwnd);
} }
void BrowserWebViewDelegate::CreatedPluginWindow( void BrowserWebViewDelegate::CreatedPluginWindow(
gfx::PluginWindowHandle handle) { gfx::PluginWindowHandle handle) {
// ignored if (browser_->IsWindowRenderingDisabled()) {
static bool registered_class = false;
if (!registered_class) {
WNDCLASSEX wcex = {0};
wcex.cbSize = sizeof(wcex);
wcex.style = CS_DBLCLKS;
wcex.lpfnWndProc = DefWindowProc;
wcex.hInstance = GetModuleHandle(NULL);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.lpszClassName = kPluginWindowClassName;
RegisterClassEx(&wcex);
registered_class = true;
}
// Parent windowed plugin containers to a hidden window.
HWND parent = CreateWindow(kPluginWindowClassName, NULL,
WS_OVERLAPPED|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
0, 0, 0, 0, NULL, NULL,
GetModuleHandle(NULL), NULL);
DCHECK(parent != NULL);
SetParent(handle, parent);
WebViewHost* host = browser_->UIT_GetWebViewHost();
if (host)
host->AddWindowedPlugin(handle);
}
} }
void BrowserWebViewDelegate::WillDestroyPluginWindow( void BrowserWebViewDelegate::WillDestroyPluginWindow(
gfx::PluginWindowHandle handle) { gfx::PluginWindowHandle handle) {
// ignored if (browser_->IsWindowRenderingDisabled()) {
WebViewHost* host = browser_->UIT_GetWebViewHost();
if (host)
host->RemoveWindowedPlugin(handle);
// Destroy the hidden parent window.
DestroyWindow(GetParent(handle));
}
} }
void BrowserWebViewDelegate::DidMovePlugin( void BrowserWebViewDelegate::DidMovePlugin(
@ -196,6 +282,13 @@ void BrowserWebViewDelegate::DidMovePlugin(
move.window_rect.width(), move.window_rect.width(),
move.window_rect.height(), move.window_rect.height(),
flags); flags);
if (browser_->IsWindowRenderingDisabled()) {
WebViewHost* host = browser_->UIT_GetWebViewHost();
if (host) {
host->MoveWindowedPlugin(move);
}
}
} }
static void AddMenuItem(CefRefPtr<CefBrowser> browser, HMENU menu, int index, static void AddMenuItem(CefRefPtr<CefBrowser> browser, HMENU menu, int index,
@ -239,22 +332,30 @@ static void AddMenuSeparator(HMENU menu, int index)
void BrowserWebViewDelegate::showContextMenu( void BrowserWebViewDelegate::showContextMenu(
WebFrame* frame, const WebContextMenuData& data) WebFrame* frame, const WebContextMenuData& data)
{ {
POINT screen_pt = { data.mousePosition.x, data.mousePosition.y }; int screenX = -1, screenY = -1;
MapWindowPoints(browser_->UIT_GetMainWndHandle(), HWND_DESKTOP,
&screen_pt, 1); POINT mouse_pt = {data.mousePosition.x, data.mousePosition.y};
if (!browser_->IsWindowRenderingDisabled()) {
// Perform the conversion to screen coordinates only if window rendering is
// enabled.
MapWindowPoints(browser_->UIT_GetMainWndHandle(), HWND_DESKTOP,
&mouse_pt, 1);
screenX = mouse_pt.x;
screenY = mouse_pt.y;
}
HMENU menu = NULL; HMENU menu = NULL;
std::list<std::wstring> label_list; std::list<std::wstring> label_list;
// Enable recursive tasks on the message loop so we can get updates while // Enable recursive tasks on the message loop so we can get updates while
// the context menu is being displayed. // the context menu is being displayed.
bool old_state = MessageLoop::current()->NestableTasksAllowed(); bool old_state = MessageLoop::current()->NestableTasksAllowed();
MessageLoop::current()->SetNestableTasksAllowed(true); MessageLoop::current()->SetNestableTasksAllowed(true);
int edit_flags = data.editFlags; int edit_flags = data.editFlags;
if(browser_->UIT_CanGoBack()) if(browser_->UIT_CanGoBack())
edit_flags |= MENU_CAN_GO_BACK; edit_flags |= MENU_CAN_GO_BACK;
if(browser_->UIT_CanGoForward()) if(browser_->UIT_CanGoForward())
edit_flags |= MENU_CAN_GO_FORWARD; edit_flags |= MENU_CAN_GO_FORWARD;
int type_flags = MENUTYPE_NONE; int type_flags = MENUTYPE_NONE;
@ -276,7 +377,7 @@ void BrowserWebViewDelegate::showContextMenu(
type_flags |= MENUTYPE_VIDEO; type_flags |= MENUTYPE_VIDEO;
if(data.mediaType == WebContextMenuData::MediaTypeAudio) if(data.mediaType == WebContextMenuData::MediaTypeAudio)
type_flags |= MENUTYPE_AUDIO; type_flags |= MENUTYPE_AUDIO;
CefRefPtr<CefHandler> handler = browser_->GetHandler(); CefRefPtr<CefHandler> handler = browser_->GetHandler();
if(handler.get()) { if(handler.get()) {
// Gather menu information // Gather menu information
@ -290,10 +391,10 @@ void BrowserWebViewDelegate::showContextMenu(
CefString selectedTextStr(string16(data.selectedText)); CefString selectedTextStr(string16(data.selectedText));
CefString misspelledWordStr(string16(data.misspelledWord)); CefString misspelledWordStr(string16(data.misspelledWord));
CefString securityInfoStr(std::string(data.securityInfo)); CefString securityInfoStr(std::string(data.securityInfo));
menuInfo.typeFlags = type_flags; menuInfo.typeFlags = type_flags;
menuInfo.x = screen_pt.x; menuInfo.x = mouse_pt.x;
menuInfo.y = screen_pt.y; menuInfo.y = mouse_pt.y;
cef_string_set(linkStr.c_str(), linkStr.length(), &menuInfo.linkUrl, false); cef_string_set(linkStr.c_str(), linkStr.length(), &menuInfo.linkUrl, false);
cef_string_set(imageStr.c_str(), imageStr.length(), &menuInfo.imageUrl, cef_string_set(imageStr.c_str(), imageStr.length(), &menuInfo.imageUrl,
false); false);
@ -307,11 +408,18 @@ void BrowserWebViewDelegate::showContextMenu(
menuInfo.editFlags = edit_flags; menuInfo.editFlags = edit_flags;
cef_string_set(securityInfoStr.c_str(), securityInfoStr.length(), cef_string_set(securityInfoStr.c_str(), securityInfoStr.length(),
&menuInfo.securityInfo, false); &menuInfo.securityInfo, false);
// Notify the handler that a context menu is requested // Notify the handler that a context menu is requested
CefHandler::RetVal rv = handler->HandleBeforeMenu(browser_, menuInfo); CefHandler::RetVal rv = handler->HandleBeforeMenu(browser_, menuInfo);
if(rv == RV_HANDLED) if(rv == RV_HANDLED)
goto end; goto end;
if (browser_->IsWindowRenderingDisabled()) {
rv = handler->HandleGetScreenPoint(browser_, mouse_pt.x, mouse_pt.y,
screenX, screenY);
if(rv != RV_CONTINUE)
goto end;
}
} }
// Build the correct default context menu // Build the correct default context menu
@ -353,8 +461,8 @@ void BrowserWebViewDelegate::showContextMenu(
if(menu) { if(menu) {
// show the context menu // show the context menu
int selected_id = TrackPopupMenu(menu, int selected_id = TrackPopupMenu(menu,
TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_RECURSE, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_RECURSE,
screen_pt.x, screen_pt.y, 0, browser_->UIT_GetMainWndHandle(), NULL); screenX, screenY, 0, browser_->UIT_GetMainWndHandle(), NULL);
if(selected_id != 0) { if(selected_id != 0) {
// An action was chosen // An action was chosen

View File

@ -80,6 +80,23 @@ void CefDoMessageLoopWork()
_Context->process()->DoMessageLoopIteration(); _Context->process()->DoMessageLoopIteration();
} }
void CefRunMessageLoop()
{
// Verify that the context is in a valid state.
if (!CONTEXT_STATE_VALID()) {
NOTREACHED();
return;
}
// Must always be called on the same thread as Initialize.
if(!_Context->process()->CalledOnValidThread()) {
NOTREACHED();
return;
}
_Context->process()->RunMessageLoop();
}
static void UIT_RegisterPlugin(CefPluginInfo* plugin_info) static void UIT_RegisterPlugin(CefPluginInfo* plugin_info)
{ {
REQUIRE_UIT(); REQUIRE_UIT();

View File

@ -20,6 +20,7 @@ class CefMessageLoopForUI : public MessageLoopForUI
public: public:
CefMessageLoopForUI() CefMessageLoopForUI()
: is_iterating_(true)
{ {
} }
@ -32,10 +33,12 @@ public:
virtual bool DoIdleWork() { virtual bool DoIdleWork() {
bool valueToRet = inherited::DoIdleWork(); bool valueToRet = inherited::DoIdleWork();
pump_->Quit(); if (is_iterating_)
pump_->Quit();
return valueToRet; return valueToRet;
} }
// Do a single interation of the UI message loop.
void DoMessageLoopIteration() { void DoMessageLoopIteration() {
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
Run(); Run();
@ -44,7 +47,18 @@ public:
#endif #endif
} }
// Run the UI message loop.
void RunMessageLoop() {
is_iterating_ = false;
DoMessageLoopIteration();
}
bool is_iterating() { return is_iterating_; }
private: private:
// True if the message loop is doing one iteration at a time.
bool is_iterating_;
DISALLOW_COPY_AND_ASSIGN(CefMessageLoopForUI); DISALLOW_COPY_AND_ASSIGN(CefMessageLoopForUI);
}; };
@ -79,9 +93,15 @@ CefProcess::~CefProcess() {
void CefProcess::DoMessageLoopIteration() { void CefProcess::DoMessageLoopIteration() {
DCHECK(CalledOnValidThread() && ui_message_loop_.get() != NULL); DCHECK(CalledOnValidThread() && ui_message_loop_.get() != NULL);
DCHECK(ui_message_loop_->is_iterating());
ui_message_loop_->DoMessageLoopIteration(); ui_message_loop_->DoMessageLoopIteration();
} }
void CefProcess::RunMessageLoop() {
DCHECK(CalledOnValidThread() && ui_message_loop_.get() != NULL);
ui_message_loop_->RunMessageLoop();
}
void CefProcess::CreateUIThread() { void CefProcess::CreateUIThread() {
DCHECK(!created_ui_thread_ && ui_thread_.get() == NULL); DCHECK(!created_ui_thread_ && ui_thread_.get() == NULL);
created_ui_thread_ = true; created_ui_thread_ = true;

View File

@ -57,10 +57,13 @@ class CefProcess : public base::RefCounted<CefProcess>,
return ui_thread_.get(); return ui_thread_.get();
} }
// Necessary to perform work on the UI thread if started without a multi // Do a single iteration of the UI message loop on the current thread. If
// threaded message loop. // RunMessageLoop() was called you do not need to call this method.
void DoMessageLoopIteration(); void DoMessageLoopIteration();
// Run the UI message loop for the on the current thread.
void RunMessageLoop();
// Returns the thread that we perform I/O coordination on (network requests, // Returns the thread that we perform I/O coordination on (network requests,
// communication with renderers, etc. // communication with renderers, etc.
// NOTE: You should ONLY use this to pass to IPC or other objects which must // NOTE: You should ONLY use this to pass to IPC or other objects which must

13
libcef/webview_host.cc Normal file
View File

@ -0,0 +1,13 @@
// Copyright (c) 2011 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 "webview_host.h"
WebViewHost::WebViewHost()
{
}
WebViewHost::~WebViewHost()
{
}

View File

@ -30,9 +30,12 @@ class WebViewHost : public WebWidgetHost {
static WebViewHost* Create(gfx::NativeView parent_view, static WebViewHost* Create(gfx::NativeView parent_view,
const gfx::Rect& rect, const gfx::Rect& rect,
BrowserWebViewDelegate* delegate, BrowserWebViewDelegate* delegate,
PaintDelegate* paint_delegate,
WebKit::WebDevToolsAgentClient* devtools_client, WebKit::WebDevToolsAgentClient* devtools_client,
const WebPreferences& prefs); const WebPreferences& prefs);
virtual ~WebViewHost();
WebKit::WebView* webview() const; WebKit::WebView* webview() const;
#if defined(TOOLKIT_USES_GTK) #if defined(TOOLKIT_USES_GTK)
@ -50,6 +53,8 @@ class WebViewHost : public WebWidgetHost {
#endif #endif
protected: protected:
WebViewHost();
#if defined(OS_WIN) #if defined(OS_WIN)
virtual bool WndProc(UINT message, WPARAM wparam, LPARAM lparam) { virtual bool WndProc(UINT message, WPARAM wparam, LPARAM lparam) {
return false; return false;

View File

@ -22,6 +22,7 @@ using WebKit::WebView;
WebViewHost* WebViewHost::Create(GtkWidget* parent_view, WebViewHost* WebViewHost::Create(GtkWidget* parent_view,
const gfx::Rect& rect, const gfx::Rect& rect,
BrowserWebViewDelegate* delegate, BrowserWebViewDelegate* delegate,
PaintDelegate* paint_delegate,
WebDevToolsAgentClient* dev_tools_client, WebDevToolsAgentClient* dev_tools_client,
const WebPreferences& prefs) { const WebPreferences& prefs) {
WebViewHost* host = new WebViewHost(); WebViewHost* host = new WebViewHost();

View File

@ -23,6 +23,7 @@ using WebKit::WebView;
WebViewHost* WebViewHost::Create(NSView* parent_view, WebViewHost* WebViewHost::Create(NSView* parent_view,
const gfx::Rect& rect, const gfx::Rect& rect,
BrowserWebViewDelegate* delegate, BrowserWebViewDelegate* delegate,
PaintDelegate* paint_delegate,
WebDevToolsAgentClient* dev_tools_client, WebDevToolsAgentClient* dev_tools_client,
const WebPreferences& prefs) { const WebPreferences& prefs) {
WebViewHost* host = new WebViewHost(); WebViewHost* host = new WebViewHost();

View File

@ -20,28 +20,33 @@ static const wchar_t kWindowClassName[] = L"WebViewHost";
WebViewHost* WebViewHost::Create(HWND parent_view, WebViewHost* WebViewHost::Create(HWND parent_view,
const gfx::Rect&, const gfx::Rect&,
BrowserWebViewDelegate* delegate, BrowserWebViewDelegate* delegate,
PaintDelegate* paint_delegate,
WebDevToolsAgentClient* dev_tools_client, WebDevToolsAgentClient* dev_tools_client,
const WebPreferences& prefs) { const WebPreferences& prefs) {
WebViewHost* host = new WebViewHost(); WebViewHost* host = new WebViewHost();
static bool registered_class = false; if (!paint_delegate) {
if (!registered_class) { static bool registered_class = false;
WNDCLASSEX wcex = {0}; if (!registered_class) {
wcex.cbSize = sizeof(wcex); WNDCLASSEX wcex = {0};
wcex.style = CS_DBLCLKS; wcex.cbSize = sizeof(wcex);
wcex.lpfnWndProc = WebWidgetHost::WndProc; wcex.style = CS_DBLCLKS;
wcex.hInstance = GetModuleHandle(NULL); wcex.lpfnWndProc = WebWidgetHost::WndProc;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hInstance = GetModuleHandle(NULL);
wcex.lpszClassName = kWindowClassName; wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
RegisterClassEx(&wcex); wcex.lpszClassName = kWindowClassName;
registered_class = true; RegisterClassEx(&wcex);
} registered_class = true;
}
host->view_ = CreateWindow(kWindowClassName, NULL, host->view_ = CreateWindow(kWindowClassName, NULL,
WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS, 0, 0, WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS, 0, 0,
0, 0, parent_view, NULL, 0, 0, parent_view, NULL,
GetModuleHandle(NULL), NULL); GetModuleHandle(NULL), NULL);
ui::SetWindowUserData(host->view_, host); ui::SetWindowUserData(host->view_, host);
} else {
host->paint_delegate_ = paint_delegate;
}
#if defined(WEBKIT_HAS_WEB_AUTO_FILL_CLIENT) #if defined(WEBKIT_HAS_WEB_AUTO_FILL_CLIENT)
host->webwidget_ = WebView::create(delegate, dev_tools_client, NULL); host->webwidget_ = WebView::create(delegate, dev_tools_client, NULL);

View File

@ -3,10 +3,106 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "webwidget_host.h" #include "webwidget_host.h"
#include "cef_thread.h"
#include "base/message_loop.h" #include "base/message_loop.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebWidget.h"
using webkit::npapi::WebPluginGeometry;
using WebKit::WebSize;
void WebWidgetHost::ScheduleAnimation() { void WebWidgetHost::ScheduleAnimation() {
MessageLoop::current()->PostDelayedTask(FROM_HERE, MessageLoop::current()->PostDelayedTask(FROM_HERE,
factory_.NewRunnableMethod(&WebWidgetHost::ScheduleComposite), 10); factory_.NewRunnableMethod(&WebWidgetHost::ScheduleComposite), 10);
} }
void WebWidgetHost::DiscardBackingStore() {
canvas_.reset();
}
void WebWidgetHost::UpdatePaintRect(const gfx::Rect& rect) {
paint_rect_ = paint_rect_.Union(rect);
}
void WebWidgetHost::SetSize(int width, int height) {
// Force an entire re-paint. TODO(darin): Maybe reuse this memory buffer.
DiscardBackingStore();
webwidget_->resize(WebSize(width, height));
EnsureTooltip();
}
void WebWidgetHost::GetSize(int& width, int& height) {
const WebSize& size = webwidget_->size();
width = size.width;
height = size.height;
}
void WebWidgetHost::AddWindowedPlugin(gfx::PluginWindowHandle handle)
{
WebPluginGeometry geometry;
plugin_map_.insert(std::make_pair(handle, geometry));
}
void WebWidgetHost::RemoveWindowedPlugin(gfx::PluginWindowHandle handle)
{
PluginMap::iterator it = plugin_map_.find(handle);
DCHECK(it != plugin_map_.end());
plugin_map_.erase(it);
}
void WebWidgetHost::MoveWindowedPlugin(const WebPluginGeometry& move)
{
PluginMap::iterator it = plugin_map_.find(move.window);
DCHECK(it != plugin_map_.end());
it->second.window = move.window;
if (move.rects_valid) {
it->second.window_rect = move.window_rect;
it->second.clip_rect = move.clip_rect;
it->second.cutout_rects = move.cutout_rects;
it->second.rects_valid = true;
}
it->second.visible = move.visible;
}
gfx::PluginWindowHandle WebWidgetHost::GetWindowedPluginAt(int x, int y)
{
if (!plugin_map_.empty()) {
PluginMap::const_iterator it = plugin_map_.begin();
for(; it != plugin_map_.end(); ++it) {
if (it->second.visible && it->second.window_rect.Contains(x, y))
return it->second.window;
}
}
return NULL;
}
void WebWidgetHost::DoPaint() {
update_task_ = NULL;
if (update_rect_.IsEmpty())
return;
// TODO(cef): The below code is cross-platform but the IsIdle() method
// currently requires patches to Chromium. Since this code is only executed
// on Windows it's been stuck behind an #ifdef for now to avoid having to
// patch Chromium code on other platforms.
#if defined(OS_WIN)
if (MessageLoop::current()->IsIdle()) {
// Perform the paint.
UpdatePaintRect(update_rect_);
update_rect_ = gfx::Rect();
Paint();
} else {
// Try again later.
update_task_ = factory_.NewRunnableMethod(&WebWidgetHost::DoPaint);
CefThread::PostTask(CefThread::UI, FROM_HERE, update_task_);
}
#else
NOTIMPLEMENTED();
#endif
}

View File

@ -6,6 +6,7 @@
#define _WEBWIDGET_HOST_H #define _WEBWIDGET_HOST_H
#include "include/cef_string.h" #include "include/cef_string.h"
#include "include/cef_types.h"
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/scoped_ptr.h" #include "base/scoped_ptr.h"
#include "base/task.h" #include "base/task.h"
@ -13,6 +14,8 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
#include "ui/gfx/native_widget_types.h" #include "ui/gfx/native_widget_types.h"
#include "ui/gfx/rect.h" #include "ui/gfx/rect.h"
#include "webkit/plugins/npapi/webplugin.h"
#include <map>
namespace gfx { namespace gfx {
class Rect; class Rect;
@ -37,11 +40,20 @@ class NSEvent;
// This class is a simple NativeView-based host for a WebWidget // This class is a simple NativeView-based host for a WebWidget
class WebWidgetHost { class WebWidgetHost {
public: public:
class PaintDelegate {
public:
virtual void Paint(bool popup, const gfx::Rect& dirtyRect,
const void* buffer) =0;
};
// The new instance is deleted once the associated NativeView is destroyed. // The new instance is deleted once the associated NativeView is destroyed.
// The newly created window should be resized after it is created, using the // The newly created window should be resized after it is created, using the
// MoveWindow (or equivalent) function. // MoveWindow (or equivalent) function.
static WebWidgetHost* Create(gfx::NativeView parent_view, static WebWidgetHost* Create(gfx::NativeView parent_view,
WebKit::WebWidgetClient* client); WebKit::WebWidgetClient* client,
PaintDelegate* paint_delegate);
virtual ~WebWidgetHost();
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
static void HandleEvent(gfx::NativeView view, NSEvent* event); static void HandleEvent(gfx::NativeView view, NSEvent* event);
@ -62,7 +74,14 @@ class WebWidgetHost {
// Allow clients to update the paint rect. For example, if we get a gdk // Allow clients to update the paint rect. For example, if we get a gdk
// expose or WM_PAINT event, we need to update the paint rect. // expose or WM_PAINT event, we need to update the paint rect.
void UpdatePaintRect(const gfx::Rect& rect); void UpdatePaintRect(const gfx::Rect& rect);
void Paint(); void Paint();
void InvalidateRect(const gfx::Rect& rect);
bool GetImage(int width, int height, void* buffer);
void SetSize(int width, int height);
void GetSize(int& width, int& height);
skia::PlatformCanvas* canvas() const { return canvas_.get(); } skia::PlatformCanvas* canvas() const { return canvas_.get(); }
@ -74,12 +93,33 @@ class WebWidgetHost {
void SetTooltipText(const CefString& tooltip_text); void SetTooltipText(const CefString& tooltip_text);
void SendKeyEvent(cef_key_type_t type, int key, int modifiers, bool sysChar,
bool imeChar);
void SendMouseClickEvent(int x, int y, cef_mouse_button_type_t type,
bool mouseUp, int clickCount);
void SendMouseMoveEvent(int x, int y, bool mouseLeave);
void SendMouseWheelEvent(int x, int y, int delta);
void SendFocusEvent(bool setFocus);
void SendCaptureLostEvent();
// Manage windowed plugins when window rendering is disabled.
bool HasWindowedPlugins() { return !plugin_map_.empty(); }
void AddWindowedPlugin(gfx::PluginWindowHandle handle);
void RemoveWindowedPlugin(gfx::PluginWindowHandle handle);
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; } void set_popup(bool popup) { popup_ = popup; }
bool popup() { return popup_; } bool popup() { return popup_; }
PaintDelegate* paint_delegate() { return paint_delegate_; }
protected: protected:
WebWidgetHost(); WebWidgetHost();
~WebWidgetHost();
#if defined(OS_WIN) #if defined(OS_WIN)
// Per-class wndproc. Returns true if the event should be swallowed. // Per-class wndproc. Returns true if the event should be swallowed.
@ -136,23 +176,41 @@ class WebWidgetHost {
void ResetTooltip(); void ResetTooltip();
gfx::NativeView view_; gfx::NativeView view_;
// The paint delegate is used instead of the view when window rendering is
// disabled.
PaintDelegate* paint_delegate_;
WebKit::WebWidget* webwidget_; WebKit::WebWidget* webwidget_;
scoped_ptr<skia::PlatformCanvas> canvas_; scoped_ptr<skia::PlatformCanvas> canvas_;
// True if this widget is a popup widget. // True if this widget is a popup widget.
bool popup_; bool popup_;
// specifies the portion of the webwidget that needs painting // Specifies the portion of the webwidget that needs painting.
gfx::Rect paint_rect_; gfx::Rect paint_rect_;
// specifies the portion of the webwidget that needs scrolling // Specifies the portion of the webwidget that needs scrolling.
gfx::Rect scroll_rect_; gfx::Rect scroll_rect_;
int scroll_dx_; int scroll_dx_;
int scroll_dy_; int scroll_dy_;
// Specifies the portion of the webwidget that has been invalidated when
// window rendering is disabled.
gfx::Rect update_rect_;
CancelableTask* update_task_;
// The map of windowed plugins that need to be drawn when window rendering is
// disabled.
typedef std::map<gfx::PluginWindowHandle,webkit::npapi::WebPluginGeometry>
PluginMap;
PluginMap plugin_map_;
#if defined(OS_WIN) #if defined(OS_WIN)
bool track_mouse_leave_; bool track_mouse_leave_;
std::wstring tooltip_text_; std::wstring tooltip_text_;
gfx::NativeView tooltip_view_;
bool tooltip_showing_;
#endif #endif
#if defined(TOOLKIT_USES_GTK) #if defined(TOOLKIT_USES_GTK)
@ -162,8 +220,6 @@ class WebWidgetHost {
#endif #endif
WebKit::WebKeyboardEvent last_key_event_; WebKit::WebKeyboardEvent last_key_event_;
gfx::NativeView tooltip_view_;
bool tooltip_showing_;
#ifndef NDEBUG #ifndef NDEBUG
bool painting_; bool painting_;

View File

@ -284,7 +284,8 @@ gfx::NativeView WebWidgetHost::CreateWidget(
// static // static
WebWidgetHost* WebWidgetHost::Create(GtkWidget* parent_view, WebWidgetHost* WebWidgetHost::Create(GtkWidget* parent_view,
WebWidgetClient* client) { WebWidgetClient* client,
PaintDelegate* paint_delegate) {
WebWidgetHost* host = new WebWidgetHost(); WebWidgetHost* host = new WebWidgetHost();
host->view_ = CreateWidget(parent_view, host); host->view_ = CreateWidget(parent_view, host);
host->webwidget_ = WebPopupMenu::create(client); host->webwidget_ = WebPopupMenu::create(client);
@ -295,10 +296,6 @@ WebWidgetHost* WebWidgetHost::Create(GtkWidget* parent_view,
return host; return host;
} }
void WebWidgetHost::UpdatePaintRect(const gfx::Rect& rect) {
paint_rect_ = paint_rect_.Union(rect);
}
void WebWidgetHost::DidInvalidateRect(const gfx::Rect& damaged_rect) { void WebWidgetHost::DidInvalidateRect(const gfx::Rect& damaged_rect) {
DLOG_IF(WARNING, painting_) << "unexpected invalidation while painting"; DLOG_IF(WARNING, painting_) << "unexpected invalidation while painting";
@ -331,10 +328,12 @@ void WebWidgetHost::ScheduleComposite() {
WebWidgetHost::WebWidgetHost() WebWidgetHost::WebWidgetHost()
: view_(NULL), : view_(NULL),
paint_delegate_(NULL),
webwidget_(NULL), webwidget_(NULL),
popup_(false), popup_(false),
scroll_dx_(0), scroll_dx_(0),
scroll_dy_(0), scroll_dy_(0),
update_task_(NULL),
ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) { ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) {
set_painting(false); set_painting(false);
} }
@ -349,10 +348,8 @@ WebWidgetHost::~WebWidgetHost() {
} }
void WebWidgetHost::Resize(const gfx::Size &newsize) { void WebWidgetHost::Resize(const gfx::Size &newsize) {
// The pixel buffer backing us is now the wrong size
canvas_.reset();
logical_size_ = newsize; logical_size_ = newsize;
webwidget_->resize(newsize); SetSize(newsize.width(), newsize.height());
} }
void WebWidgetHost::Paint() { void WebWidgetHost::Paint() {
@ -419,6 +416,27 @@ void WebWidgetHost::Paint() {
gdk_window_end_paint(window); gdk_window_end_paint(window);
} }
void WebWidgetHost::SetTooltipText(const CefString& tooltip_text)
{
// TODO(port): Implement this method as part of tooltip support.
}
void WebWidgetHost::InvalidateRect(const gfx::Rect& rect)
{
// TODO(port): Implement this method as part of off-screen rendering support.
NOTIMPLEMENTED();
}
bool WebWidgetHost::GetImage(int width, int height, void* rgba_buffer)
{
if (!canvas_.get())
return false;
// TODO(port): Implement this method as part of off-screen rendering support.
NOTIMPLEMENTED();
return false;
}
WebScreenInfo WebWidgetHost::GetScreenInfo() { WebScreenInfo WebWidgetHost::GetScreenInfo() {
Display* display = GtkWidgetGetDisplay(view_); Display* display = GtkWidgetGetDisplay(view_);
int screen_num = GtkWidgetGetScreenNum(view_); int screen_num = GtkWidgetGetScreenNum(view_);
@ -439,3 +457,52 @@ void WebWidgetHost::PaintRect(const gfx::Rect& rect) {
void WebWidgetHost::WindowDestroyed() { void WebWidgetHost::WindowDestroyed() {
delete this; delete this;
} }
void WebWidgetHost::SendKeyEvent(cef_key_type_t type, int key, int modifiers,
bool sysChar, bool imeChar)
{
// TODO(port): Implement this method as part of off-screen rendering support.
NOTIMPLEMENTED();
}
void WebWidgetHost::SendMouseClickEvent(int x, int y,
cef_mouse_button_type_t type,
bool mouseUp, int clickCount)
{
// TODO(port): Implement this method as part of off-screen rendering support.
NOTIMPLEMENTED();
}
void WebWidgetHost::SendMouseMoveEvent(int x, int y, bool mouseLeave)
{
// TODO(port): Implement this method as part of off-screen rendering support.
NOTIMPLEMENTED();
}
void WebWidgetHost::SendMouseWheelEvent(int x, int y, int delta)
{
// TODO(port): Implement this method as part of off-screen rendering support.
NOTIMPLEMENTED();
}
void WebWidgetHost::SendFocusEvent(bool setFocus)
{
// TODO(port): Implement this method as part of off-screen rendering support.
NOTIMPLEMENTED();
}
void WebWidgetHost::SendCaptureLostEvent()
{
// TODO(port): Implement this method as part of off-screen rendering support.
NOTIMPLEMENTED();
}
void WebWidgetHost::EnsureTooltip()
{
// TODO(port): Implement this method as part of tooltip support.
}
void WebWidgetHost::ResetTooltip()
{
// TODO(port): Implement this method as part of tooltip support.
}

View File

@ -31,7 +31,8 @@ using WebKit::WebWidgetClient;
/*static*/ /*static*/
WebWidgetHost* WebWidgetHost::Create(NSView* parent_view, WebWidgetHost* WebWidgetHost::Create(NSView* parent_view,
WebWidgetClient* client) { WebWidgetClient* client,
PaintDelegate* paint_delegate) {
WebWidgetHost* host = new WebWidgetHost(); WebWidgetHost* host = new WebWidgetHost();
NSRect content_rect = [parent_view frame]; NSRect content_rect = [parent_view frame];
@ -133,16 +134,14 @@ void WebWidgetHost::ScheduleComposite() {
[view_ setNeedsDisplayInRect:r]; [view_ setNeedsDisplayInRect:r];
} }
void WebWidgetHost::DiscardBackingStore() {
canvas_.reset();
}
WebWidgetHost::WebWidgetHost() WebWidgetHost::WebWidgetHost()
: view_(NULL), : view_(NULL),
paint_delegate_(NULL),
webwidget_(NULL), webwidget_(NULL),
popup_(false), popup_(false),
scroll_dx_(0), scroll_dx_(0),
scroll_dy_(0), scroll_dy_(0),
update_task_(NULL),
ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) { ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) {
set_painting(false); set_painting(false);
} }
@ -150,10 +149,6 @@ WebWidgetHost::WebWidgetHost()
WebWidgetHost::~WebWidgetHost() { WebWidgetHost::~WebWidgetHost() {
} }
void WebWidgetHost::UpdatePaintRect(const gfx::Rect& rect) {
paint_rect_ = paint_rect_.Union(rect);
}
void WebWidgetHost::Paint() { void WebWidgetHost::Paint() {
gfx::Rect client_rect(NSRectToCGRect([view_ frame])); gfx::Rect client_rect(NSRectToCGRect([view_ frame]));
NSGraphicsContext* view_context = [NSGraphicsContext currentContext]; NSGraphicsContext* view_context = [NSGraphicsContext currentContext];
@ -218,8 +213,25 @@ void WebWidgetHost::Paint() {
} }
} }
void WebWidgetHost::SetTooltipText(const CefString& tooltip_text) { void WebWidgetHost::SetTooltipText(const CefString& tooltip_text)
// TODO(port): Implement this method. {
// TODO(port): Implement this method as part of tooltip support.
}
void WebWidgetHost::InvalidateRect(const gfx::Rect& rect)
{
// TODO(port): Implement this method as part of off-screen rendering support.
NOTIMPLEMENTED();
}
bool WebWidgetHost::GetImage(int width, int height, void* rgba_buffer)
{
if (!canvas_.get())
return false;
// TODO(port): Implement this method as part of off-screen rendering support.
NOTIMPLEMENTED();
return false;
} }
WebScreenInfo WebWidgetHost::GetScreenInfo() { WebScreenInfo WebWidgetHost::GetScreenInfo() {
@ -227,9 +239,7 @@ WebScreenInfo WebWidgetHost::GetScreenInfo() {
} }
void WebWidgetHost::Resize(const gfx::Rect& rect) { void WebWidgetHost::Resize(const gfx::Rect& rect) {
// Force an entire re-paint. TODO(darin): Maybe reuse this memory buffer. SetSize(rect.width(), rect.height());
DiscardBackingStore();
webwidget_->resize(WebSize(rect.width(), rect.height()));
} }
void WebWidgetHost::MouseEvent(NSEvent *event) { void WebWidgetHost::MouseEvent(NSEvent *event) {
@ -275,3 +285,52 @@ void WebWidgetHost::PaintRect(const gfx::Rect& rect) {
webwidget_->paint(webkit_glue::ToWebCanvas(canvas_.get()), rect); webwidget_->paint(webkit_glue::ToWebCanvas(canvas_.get()), rect);
set_painting(false); set_painting(false);
} }
void WebWidgetHost::SendKeyEvent(cef_key_type_t type, int key, int modifiers,
bool sysChar, bool imeChar)
{
// TODO(port): Implement this method as part of off-screen rendering support.
NOTIMPLEMENTED();
}
void WebWidgetHost::SendMouseClickEvent(int x, int y,
cef_mouse_button_type_t type,
bool mouseUp, int clickCount)
{
// TODO(port): Implement this method as part of off-screen rendering support.
NOTIMPLEMENTED();
}
void WebWidgetHost::SendMouseMoveEvent(int x, int y, bool mouseLeave)
{
// TODO(port): Implement this method as part of off-screen rendering support.
NOTIMPLEMENTED();
}
void WebWidgetHost::SendMouseWheelEvent(int x, int y, int delta)
{
// TODO(port): Implement this method as part of off-screen rendering support.
NOTIMPLEMENTED();
}
void WebWidgetHost::SendFocusEvent(bool setFocus)
{
// TODO(port): Implement this method as part of off-screen rendering support.
NOTIMPLEMENTED();
}
void WebWidgetHost::SendCaptureLostEvent()
{
// TODO(port): Implement this method as part of off-screen rendering support.
NOTIMPLEMENTED();
}
void WebWidgetHost::EnsureTooltip()
{
// TODO(port): Implement this method as part of tooltip support.
}
void WebWidgetHost::ResetTooltip()
{
// TODO(port): Implement this method as part of tooltip support.
}

View File

@ -4,6 +4,7 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "webwidget_host.h" #include "webwidget_host.h"
#include "cef_thread.h"
#include "ui/gfx/rect.h" #include "ui/gfx/rect.h"
#include "base/logging.h" #include "base/logging.h"
@ -14,9 +15,11 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/win/WebInputEventFactory.h" #include "third_party/WebKit/Source/WebKit/chromium/public/win/WebInputEventFactory.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/win/WebScreenInfoFactory.h" #include "third_party/WebKit/Source/WebKit/chromium/public/win/WebScreenInfoFactory.h"
#include "ui/base/win/hwnd_util.h" #include "ui/base/win/hwnd_util.h"
#include "ui/gfx/gdi_util.h"
#include <commctrl.h> #include <commctrl.h>
using webkit::npapi::WebPluginGeometry;
using WebKit::WebInputEvent; using WebKit::WebInputEvent;
using WebKit::WebInputEventFactory; using WebKit::WebInputEventFactory;
using WebKit::WebKeyboardEvent; using WebKit::WebKeyboardEvent;
@ -31,31 +34,64 @@ using WebKit::WebWidgetClient;
static const wchar_t kWindowClassName[] = L"WebWidgetHost"; static const wchar_t kWindowClassName[] = L"WebWidgetHost";
namespace {
struct MessageInfo {
UINT message;
WPARAM wParam;
LPARAM lParam;
};
BOOL CALLBACK SendMessageFunc(HWND hwnd, LPARAM lParam)
{
MessageInfo* info = reinterpret_cast<MessageInfo*>(lParam);
SendMessage(hwnd, info->message, info->wParam, info->lParam);
return TRUE;
}
// Plugins are hosted in a Chromium-created parent window so it's necessary to
// send messages directly to the child window.
void SendMessageToPlugin(HWND hwnd, UINT message, WPARAM wParam,
LPARAM lParam)
{
MessageInfo info = {message, wParam, lParam};
EnumChildWindows(hwnd, SendMessageFunc, reinterpret_cast<LPARAM>(&info));
}
} // namespace
/*static*/ /*static*/
WebWidgetHost* WebWidgetHost::Create(HWND parent_view, WebWidgetHost* WebWidgetHost::Create(HWND parent_view,
WebWidgetClient* client) { WebWidgetClient* client,
PaintDelegate* paint_delegate) {
WebWidgetHost* host = new WebWidgetHost(); WebWidgetHost* host = new WebWidgetHost();
static bool registered_class = false; if (!paint_delegate) {
if (!registered_class) { // Create a window for the host.
WNDCLASSEX wcex = {0}; static bool registered_class = false;
wcex.cbSize = sizeof(wcex); if (!registered_class) {
wcex.style = CS_DBLCLKS; WNDCLASSEX wcex = {0};
wcex.lpfnWndProc = WebWidgetHost::WndProc; wcex.cbSize = sizeof(wcex);
wcex.hInstance = GetModuleHandle(NULL); wcex.style = CS_DBLCLKS;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.lpfnWndProc = WebWidgetHost::WndProc;
wcex.lpszClassName = kWindowClassName; wcex.hInstance = GetModuleHandle(NULL);
RegisterClassEx(&wcex); wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
registered_class = true; wcex.lpszClassName = kWindowClassName;
RegisterClassEx(&wcex);
registered_class = true;
}
host->view_ = CreateWindowEx(WS_EX_TOOLWINDOW,
kWindowClassName, kWindowClassName, WS_POPUP,
0, 0, 0, 0,
parent_view, NULL, GetModuleHandle(NULL),
NULL);
ui::SetWindowUserData(host->view_, host);
} else {
host->paint_delegate_ = paint_delegate;
} }
host->view_ = CreateWindowEx(WS_EX_TOOLWINDOW,
kWindowClassName, kWindowClassName, WS_POPUP,
0, 0, 0, 0,
parent_view, NULL, GetModuleHandle(NULL), NULL);
ui::SetWindowUserData(host->view_, host);
host->webwidget_ = WebPopupMenu::create(client); host->webwidget_ = WebPopupMenu::create(client);
return host; return host;
@ -73,6 +109,7 @@ LRESULT CALLBACK WebWidgetHost::WndProc(HWND hwnd, UINT message, WPARAM wparam,
if (host && !host->WndProc(message, wparam, lparam)) { if (host && !host->WndProc(message, wparam, lparam)) {
switch (message) { switch (message) {
case WM_PAINT: { case WM_PAINT: {
// Paint to the window.
RECT rect; RECT rect;
if (GetUpdateRect(hwnd, &rect, FALSE)) { if (GetUpdateRect(hwnd, &rect, FALSE)) {
host->UpdatePaintRect(gfx::Rect(rect)); host->UpdatePaintRect(gfx::Rect(rect));
@ -161,10 +198,8 @@ void WebWidgetHost::DidInvalidateRect(const gfx::Rect& damaged_rect) {
paint_rect_ = paint_rect_.Union(scroll_rect_); paint_rect_ = paint_rect_.Union(scroll_rect_);
ResetScrollRect(); ResetScrollRect();
} }
paint_rect_ = paint_rect_.Union(damaged_rect);
RECT r = damaged_rect.ToRECT(); InvalidateRect(gfx::Rect(damaged_rect));
InvalidateRect(view_, &r, FALSE);
} }
void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) { void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
@ -187,36 +222,32 @@ void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
scroll_dx_ = dx; scroll_dx_ = dx;
scroll_dy_ = dy; scroll_dy_ = dy;
RECT r = clip_rect.ToRECT(); InvalidateRect(clip_rect);
InvalidateRect(view_, &r, FALSE);
} }
void WebWidgetHost::ScheduleComposite() { void WebWidgetHost::ScheduleComposite() {
if (!webwidget_) if (!webwidget_)
return; return;
WebSize size = webwidget_->size(); WebSize size = webwidget_->size();
gfx::Rect rect(0, 0, size.width, size.height); InvalidateRect(gfx::Rect(0, 0, size.width, size.height));
RECT r = rect.ToRECT();
InvalidateRect(view_, &r, FALSE);
} }
void WebWidgetHost::SetCursor(HCURSOR cursor) { void WebWidgetHost::SetCursor(HCURSOR cursor) {
DCHECK(view_);
SetClassLong(view_, GCL_HCURSOR, SetClassLong(view_, GCL_HCURSOR,
static_cast<LONG>(reinterpret_cast<LONG_PTR>(cursor))); static_cast<LONG>(reinterpret_cast<LONG_PTR>(cursor)));
::SetCursor(cursor); ::SetCursor(cursor);
} }
void WebWidgetHost::DiscardBackingStore() {
canvas_.reset();
}
WebWidgetHost::WebWidgetHost() WebWidgetHost::WebWidgetHost()
: view_(NULL), : view_(NULL),
paint_delegate_(NULL),
webwidget_(NULL), webwidget_(NULL),
popup_(false), popup_(false),
track_mouse_leave_(false), track_mouse_leave_(false),
scroll_dx_(0), scroll_dx_(0),
scroll_dy_(0), scroll_dy_(0),
update_task_(NULL),
tooltip_view_(NULL), tooltip_view_(NULL),
tooltip_showing_(false), tooltip_showing_(false),
ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) { ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) {
@ -224,7 +255,8 @@ WebWidgetHost::WebWidgetHost()
} }
WebWidgetHost::~WebWidgetHost() { WebWidgetHost::~WebWidgetHost() {
ui::SetWindowUserData(view_, 0); if (view_)
ui::SetWindowUserData(view_, 0);
TrackMouseLeave(false); TrackMouseLeave(false);
ResetTooltip(); ResetTooltip();
@ -243,15 +275,15 @@ bool WebWidgetHost::WndProc(UINT message, WPARAM wparam, LPARAM lparam) {
return false; return false;
} }
void WebWidgetHost::UpdatePaintRect(const gfx::Rect& rect) {
paint_rect_ = paint_rect_.Union(rect);
}
void WebWidgetHost::Paint() { void WebWidgetHost::Paint() {
RECT r; if (canvas_.get() && paint_rect_.IsEmpty())
GetClientRect(view_, &r); return;
gfx::Rect client_rect(r);
int width, height;
GetSize(width, height);
gfx::Rect client_rect(width, height);
gfx::Rect damaged_rect;
// Allocate a canvas if necessary // Allocate a canvas if necessary
if (!canvas_.get()) { if (!canvas_.get()) {
ResetScrollRect(); ResetScrollRect();
@ -270,10 +302,10 @@ void WebWidgetHost::Paint() {
if (!scroll_rect_.IsEmpty()) { if (!scroll_rect_.IsEmpty()) {
HDC hdc = canvas_->getTopPlatformDevice().getBitmapDC(); HDC hdc = canvas_->getTopPlatformDevice().getBitmapDC();
RECT damaged_rect, r = scroll_rect_.ToRECT(); RECT damaged_scroll_rect, r = scroll_rect_.ToRECT();
ScrollDC(hdc, scroll_dx_, scroll_dy_, NULL, &r, NULL, &damaged_rect); ScrollDC(hdc, scroll_dx_, scroll_dy_, NULL, &r, NULL, &damaged_scroll_rect);
PaintRect(gfx::Rect(damaged_rect)); PaintRect(gfx::Rect(damaged_scroll_rect));
} }
ResetScrollRect(); ResetScrollRect();
@ -282,6 +314,7 @@ void WebWidgetHost::Paint() {
// objects update their layout only when painted. // objects update their layout only when painted.
for (int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
paint_rect_ = client_rect.Intersect(paint_rect_); paint_rect_ = client_rect.Intersect(paint_rect_);
damaged_rect = damaged_rect.Union(paint_rect_);
if (!paint_rect_.IsEmpty()) { if (!paint_rect_.IsEmpty()) {
gfx::Rect rect(paint_rect_); gfx::Rect rect(paint_rect_);
paint_rect_ = gfx::Rect(); paint_rect_ = gfx::Rect();
@ -292,17 +325,116 @@ void WebWidgetHost::Paint() {
} }
DCHECK(paint_rect_.IsEmpty()); DCHECK(paint_rect_.IsEmpty());
// Paint to the screen if (plugin_map_.size() > 0) {
PAINTSTRUCT ps; typedef std::list<const WebPluginGeometry*> PluginList;
BeginPaint(view_, &ps); PluginList visible_plugins;
canvas_->getTopPlatformDevice().drawToHDC(ps.hdc,
ps.rcPaint.left, // Identify the visible plugins.
ps.rcPaint.top, PluginMap::const_iterator it = plugin_map_.begin();
&ps.rcPaint); for(; it != plugin_map_.end(); ++it) {
EndPaint(view_, &ps); if (it->second.visible && client_rect.Intersects(it->second.window_rect))
visible_plugins.push_back(&it->second);
}
// Draw children if (!visible_plugins.empty()) {
UpdateWindow(view_); HDC drawDC = canvas_->beginPlatformPaint();
HRGN oldRGN, newRGN;
POINT oldViewport;
// Paint the plugin windows.
PluginList::const_iterator it = visible_plugins.begin();
for(; it != visible_plugins.end(); ++it) {
const WebPluginGeometry* geom = *(it);
oldRGN = CreateRectRgn(0,0,1,1);
GetClipRgn(drawDC, oldRGN);
// Only paint inside the clip region.
newRGN = CreateRectRgn(geom->clip_rect.x(),
geom->clip_rect.y(),
geom->clip_rect.right(),
geom->clip_rect.bottom());
gfx::SubtractRectanglesFromRegion(newRGN, geom->cutout_rects);
OffsetRgn(newRGN, geom->window_rect.x(), geom->window_rect.y());
SelectClipRgn(drawDC, newRGN);
// Change the viewport origin to the plugin window origin.
SetViewportOrgEx(drawDC, geom->window_rect.x(), geom->window_rect.y(),
&oldViewport);
SendMessageToPlugin(geom->window, WM_PRINT,
reinterpret_cast<WPARAM>(drawDC),
PRF_OWNED | PRF_ERASEBKGND | PRF_CLIENT | PRF_NONCLIENT);
SetViewportOrgEx(drawDC, oldViewport.x, oldViewport.y, NULL);
SelectClipRgn(drawDC, oldRGN);
damaged_rect = damaged_rect.Union(geom->window_rect);
}
canvas_->endPlatformPaint();
// Make sure the damaged rectangle is inside the client rectangle.
damaged_rect = damaged_rect.Intersect(client_rect);
}
}
if (view_) {
// Paint to the window.
PAINTSTRUCT ps;
BeginPaint(view_, &ps);
canvas_->getTopPlatformDevice().drawToHDC(ps.hdc,
ps.rcPaint.left,
ps.rcPaint.top,
&ps.rcPaint);
EndPaint(view_, &ps);
// Draw children
UpdateWindow(view_);
} else {
// Paint to the delegate.
DCHECK(paint_delegate_);
const SkBitmap& bitmap =
canvas_->getTopPlatformDevice().accessBitmap(false);
DCHECK(bitmap.config() == SkBitmap::kARGB_8888_Config);
const void* pixels = bitmap.getPixels();
paint_delegate_->Paint(popup_, damaged_rect, pixels);
}
}
void WebWidgetHost::InvalidateRect(const gfx::Rect& rect)
{
if (rect.IsEmpty())
return;
if (view_) {
// Let the window handle painting.
RECT r = {rect.x(), rect.y(), rect.x() + rect.width(),
rect.y() + rect.height()};
::InvalidateRect(view_, &r, FALSE);
} else {
// The update rectangle will be painted by DoPaint().
update_rect_ = update_rect_.Union(rect);
if (!update_task_) {
update_task_ = factory_.NewRunnableMethod(&WebWidgetHost::DoPaint);
CefThread::PostTask(CefThread::UI, FROM_HERE, update_task_);
}
}
}
bool WebWidgetHost::GetImage(int width, int height, void* buffer)
{
if (!canvas_.get())
return false;
DCHECK(width == canvas_->getTopPlatformDevice().width());
DCHECK(height == canvas_->getTopPlatformDevice().height());
const SkBitmap& bitmap = canvas_->getTopPlatformDevice().accessBitmap(false);
DCHECK(bitmap.config() == SkBitmap::kARGB_8888_Config);
const void* pixels = bitmap.getPixels();
memcpy(buffer, pixels, width * height * 4);
return true;
} }
WebScreenInfo WebWidgetHost::GetScreenInfo() { WebScreenInfo WebWidgetHost::GetScreenInfo() {
@ -310,11 +442,7 @@ WebScreenInfo WebWidgetHost::GetScreenInfo() {
} }
void WebWidgetHost::Resize(LPARAM lparam) { void WebWidgetHost::Resize(LPARAM lparam) {
// Force an entire re-paint. TODO(darin): Maybe reuse this memory buffer. SetSize(LOWORD(lparam), HIWORD(lparam));
DiscardBackingStore();
webwidget_->resize(WebSize(LOWORD(lparam), HIWORD(lparam)));
EnsureTooltip();
} }
void WebWidgetHost::MouseEvent(UINT message, WPARAM wparam, LPARAM lparam) { void WebWidgetHost::MouseEvent(UINT message, WPARAM wparam, LPARAM lparam) {
@ -393,6 +521,9 @@ void WebWidgetHost::OnNotify(WPARAM wparam, NMHDR* header) {
} }
void WebWidgetHost::SetTooltipText(const CefString& tooltip_text) { void WebWidgetHost::SetTooltipText(const CefString& tooltip_text) {
if (!view_)
return;
std::wstring new_tooltip_text(tooltip_text); std::wstring new_tooltip_text(tooltip_text);
if (new_tooltip_text != tooltip_text_) { if (new_tooltip_text != tooltip_text_) {
tooltip_text_ = new_tooltip_text; tooltip_text_ = new_tooltip_text;
@ -417,33 +548,43 @@ void WebWidgetHost::SetTooltipText(const CefString& tooltip_text) {
} }
void WebWidgetHost::EnsureTooltip() { void WebWidgetHost::EnsureTooltip() {
if (!view_)
return;
UINT message = TTM_NEWTOOLRECT; UINT message = TTM_NEWTOOLRECT;
TOOLINFO ti; TOOLINFO ti;
ti.cbSize = sizeof(ti); ti.cbSize = sizeof(ti);
ti.hwnd = view_handle(); ti.hwnd = view_;
ti.uId = 0; ti.uId = 0;
if (!::IsWindow(tooltip_view_)) { if (!::IsWindow(tooltip_view_)) {
message = TTM_ADDTOOL; message = TTM_ADDTOOL;
tooltip_view_ = CreateWindowEx( tooltip_view_ = CreateWindowEx(
WS_EX_TRANSPARENT, WS_EX_TRANSPARENT,
TOOLTIPS_CLASS, L"tooltip_view_", TTS_NOPREFIX, 0, 0, 0, 0, view_handle(), NULL, TOOLTIPS_CLASS, L"tooltip_view_", TTS_NOPREFIX, 0, 0, 0, 0,
view_, NULL,
NULL, NULL); NULL, NULL);
ti.uFlags = TTF_SUBCLASS; ti.uFlags = TTF_SUBCLASS;
ti.lpszText = LPSTR_TEXTCALLBACK; ti.lpszText = LPSTR_TEXTCALLBACK;
} }
GetClientRect(view_handle(), &ti.rect); GetClientRect(view_, &ti.rect);
SendMessage(tooltip_view_, message, NULL, reinterpret_cast<LPARAM>(&ti)); SendMessage(tooltip_view_, message, NULL, reinterpret_cast<LPARAM>(&ti));
} }
void WebWidgetHost::ResetTooltip() { void WebWidgetHost::ResetTooltip() {
if (!view_)
return;
if (::IsWindow(tooltip_view_)) if (::IsWindow(tooltip_view_))
::DestroyWindow(tooltip_view_); ::DestroyWindow(tooltip_view_);
tooltip_view_ = NULL; tooltip_view_ = NULL;
} }
void WebWidgetHost::TrackMouseLeave(bool track) { void WebWidgetHost::TrackMouseLeave(bool track) {
if (!view_)
return;
if (track == track_mouse_leave_) if (track == track_mouse_leave_)
return; return;
track_mouse_leave_ = track; track_mouse_leave_ = track;
@ -476,3 +617,168 @@ void WebWidgetHost::PaintRect(const gfx::Rect& rect) {
webwidget_->paint(canvas_.get(), rect); webwidget_->paint(canvas_.get(), rect);
set_painting(false); set_painting(false);
} }
void WebWidgetHost::SendKeyEvent(cef_key_type_t type, int key, int modifiers,
bool sysChar, bool imeChar)
{
UINT message = 0;
WPARAM wparam = key;
LPARAM lparam = modifiers;
if (type == KT_KEYUP) {
if (sysChar)
message = WM_SYSKEYUP;
else if(imeChar)
message = WM_IME_KEYUP;
else
message = WM_KEYUP;
} else if(type == KT_KEYDOWN) {
if (sysChar)
message = WM_SYSKEYDOWN;
else if(imeChar)
message = WM_IME_KEYDOWN;
else
message = WM_KEYDOWN;
} else if(type == KT_CHAR) {
if (sysChar)
message = WM_SYSCHAR;
else if(imeChar)
message = WM_IME_CHAR;
else
message = WM_CHAR;
}
if (message == 0) {
NOTREACHED();
return;
}
const WebKeyboardEvent& event = WebInputEventFactory::keyboardEvent(
NULL, message, wparam, lparam);
last_key_event_ = event;
webwidget_->handleInputEvent(event);
}
void WebWidgetHost::SendMouseClickEvent(int x, int y,
cef_mouse_button_type_t type,
bool mouseUp, int clickCount)
{
DCHECK(clickCount >=1 && clickCount <= 2);
UINT message = 0;
WPARAM wparam = 0;
LPARAM lparam = MAKELPARAM(x, y);
if (type == MBT_LEFT) {
if (mouseUp)
message = (clickCount==1?WM_LBUTTONUP:WM_LBUTTONDBLCLK);
else
message = WM_LBUTTONDOWN;
} else if (type == MBT_MIDDLE) {
if (mouseUp)
message = (clickCount==1?WM_MBUTTONUP:WM_MBUTTONDBLCLK);
else
message = WM_MBUTTONDOWN;
} else if (type == MBT_RIGHT) {
if (mouseUp)
message = (clickCount==1?WM_RBUTTONUP:WM_RBUTTONDBLCLK);
else
message = WM_RBUTTONDOWN;
}
if (message == 0) {
NOTREACHED();
return;
}
if (GetKeyState(VK_CONTROL) & 0x8000)
wparam |= MK_CONTROL;
if (GetKeyState(VK_SHIFT) & 0x8000)
wparam |= MK_SHIFT;
if (GetKeyState(VK_LBUTTON) & 0x8000)
wparam |= MK_LBUTTON;
if (GetKeyState(VK_MBUTTON) & 0x8000)
wparam |= MK_MBUTTON;
if (GetKeyState(VK_RBUTTON) & 0x8000)
wparam |= MK_RBUTTON;
gfx::PluginWindowHandle plugin = GetWindowedPluginAt(x, y);
if (plugin) {
SendMessageToPlugin(plugin, message, wparam, lparam);
} else {
const WebMouseEvent& event = WebInputEventFactory::mouseEvent(NULL, message,
wparam, lparam);
webwidget_->handleInputEvent(event);
}
}
void WebWidgetHost::SendMouseMoveEvent(int x, int y, bool mouseLeave)
{
UINT message;
WPARAM wparam = 0;
LPARAM lparam = 0;
if (mouseLeave) {
message = WM_MOUSELEAVE;
} else {
message = WM_MOUSEMOVE;
lparam = MAKELPARAM(x, y);
}
if (GetKeyState(VK_CONTROL) & 0x8000)
wparam |= MK_CONTROL;
if (GetKeyState(VK_SHIFT) & 0x8000)
wparam |= MK_SHIFT;
if (GetKeyState(VK_LBUTTON) & 0x8000)
wparam |= MK_LBUTTON;
if (GetKeyState(VK_MBUTTON) & 0x8000)
wparam |= MK_MBUTTON;
if (GetKeyState(VK_RBUTTON) & 0x8000)
wparam |= MK_RBUTTON;
gfx::PluginWindowHandle plugin = GetWindowedPluginAt(x, y);
if (plugin) {
SendMessageToPlugin(plugin, message, wparam, lparam);
} else {
const WebMouseEvent& event = WebInputEventFactory::mouseEvent(NULL, message,
wparam, lparam);
webwidget_->handleInputEvent(event);
}
}
void WebWidgetHost::SendMouseWheelEvent(int x, int y, int delta)
{
WPARAM wparam = MAKEWPARAM(0, delta);
LPARAM lparam = MAKELPARAM(x, y);
if (GetKeyState(VK_CONTROL) & 0x8000)
wparam |= MK_CONTROL;
if (GetKeyState(VK_SHIFT) & 0x8000)
wparam |= MK_SHIFT;
if (GetKeyState(VK_LBUTTON) & 0x8000)
wparam |= MK_LBUTTON;
if (GetKeyState(VK_MBUTTON) & 0x8000)
wparam |= MK_MBUTTON;
if (GetKeyState(VK_RBUTTON) & 0x8000)
wparam |= MK_RBUTTON;
gfx::PluginWindowHandle plugin = GetWindowedPluginAt(x, y);
if (plugin) {
SendMessageToPlugin(plugin, WM_MOUSEWHEEL, wparam, lparam);
} else {
const WebMouseWheelEvent& event = WebInputEventFactory::mouseWheelEvent(
NULL, WM_MOUSEWHEEL, wparam, lparam);
webwidget_->handleInputEvent(event);
}
}
void WebWidgetHost::SendFocusEvent(bool setFocus)
{
SetFocus(setFocus);
}
void WebWidgetHost::SendCaptureLostEvent()
{
CaptureLostEvent();
}

View File

@ -285,6 +285,142 @@ void CEF_CALLBACK browser_close_dev_tools(struct _cef_browser_t* self)
CefBrowserCppToC::Get(self)->CloseDevTools(); CefBrowserCppToC::Get(self)->CloseDevTools();
} }
int CEF_CALLBACK browser_is_window_rendering_disabled(
struct _cef_browser_t* self)
{
DCHECK(self);
if(!self)
return 0;
return CefBrowserCppToC::Get(self)->IsWindowRenderingDisabled();
}
int CEF_CALLBACK browser_get_size(struct _cef_browser_t* self,
enum cef_paint_element_type_t type, int* width, int* height)
{
DCHECK(self);
DCHECK(width);
DCHECK(height);
if(!self || !width || !height)
return 0;
return CefBrowserCppToC::Get(self)->GetSize(type, *width, *height);
}
void CEF_CALLBACK browser_set_size(struct _cef_browser_t* self,
enum cef_paint_element_type_t type, int width, int height)
{
DCHECK(self);
if(!self)
return;
return CefBrowserCppToC::Get(self)->SetSize(type, width, height);
}
int CEF_CALLBACK browser_is_popup_visible(struct _cef_browser_t* self)
{
DCHECK(self);
if(!self)
return 0;
return CefBrowserCppToC::Get(self)->IsPopupVisible();
}
void CEF_CALLBACK browser_hide_popup(struct _cef_browser_t* self)
{
DCHECK(self);
if(!self)
return;
CefBrowserCppToC::Get(self)->HidePopup();
}
void CEF_CALLBACK browser_invalidate(struct _cef_browser_t* self,
const cef_rect_t* dirtyRect)
{
DCHECK(self);
DCHECK(dirtyRect);
if(!self || !dirtyRect)
return;
CefRect rect(*dirtyRect);
CefBrowserCppToC::Get(self)->Invalidate(rect);
}
int CEF_CALLBACK browser_get_image(struct _cef_browser_t* self,
enum cef_paint_element_type_t type, int width, int height, void* buffer)
{
DCHECK(self);
DCHECK(buffer);
if(!self || !buffer)
return 0;
return CefBrowserCppToC::Get(self)->GetImage(type, width, height, buffer);
}
void CEF_CALLBACK browser_send_key_event(struct _cef_browser_t* self,
enum cef_key_type_t type, int key, int modifiers, int sysChar,
int imeChar)
{
DCHECK(self);
if(!self)
return;
CefBrowserCppToC::Get(self)->SendKeyEvent(type, key, modifiers,
sysChar?true:false, imeChar?true:false);
}
void CEF_CALLBACK browser_send_mouse_click_event(struct _cef_browser_t* self,
int x, int y, enum cef_mouse_button_type_t type, int mouseUp,
int clickCount)
{
DCHECK(self);
if(!self)
return;
CefBrowserCppToC::Get(self)->SendMouseClickEvent(x, y, type,
mouseUp?true:false, clickCount);
}
void CEF_CALLBACK browser_send_mouse_move_event(struct _cef_browser_t* self,
int x, int y, int mouseLeave)
{
DCHECK(self);
if(!self)
return;
CefBrowserCppToC::Get(self)->SendMouseMoveEvent(x, y, mouseLeave?true:false);
}
void CEF_CALLBACK browser_send_mouse_wheel_event(struct _cef_browser_t* self,
int x, int y, int delta)
{
DCHECK(self);
if(!self)
return;
CefBrowserCppToC::Get(self)->SendMouseWheelEvent(x, y, delta);
}
void CEF_CALLBACK browser_send_focus_event(struct _cef_browser_t* self,
int setFocus)
{
DCHECK(self);
if(!self)
return;
CefBrowserCppToC::Get(self)->SendFocusEvent(setFocus?true:false);
}
void CEF_CALLBACK browser_send_capture_lost_event(struct _cef_browser_t* self)
{
DCHECK(self);
if(!self)
return;
CefBrowserCppToC::Get(self)->SendCaptureLostEvent();
}
// CONSTRUCTOR - Do not edit by hand. // CONSTRUCTOR - Do not edit by hand.
@ -313,6 +449,20 @@ CefBrowserCppToC::CefBrowserCppToC(CefBrowser* cls)
struct_.struct_.set_zoom_level = browser_set_zoom_level; struct_.struct_.set_zoom_level = browser_set_zoom_level;
struct_.struct_.show_dev_tools = browser_show_dev_tools; struct_.struct_.show_dev_tools = browser_show_dev_tools;
struct_.struct_.close_dev_tools = browser_close_dev_tools; struct_.struct_.close_dev_tools = browser_close_dev_tools;
struct_.struct_.is_window_rendering_disabled =
browser_is_window_rendering_disabled;
struct_.struct_.get_size = browser_get_size;
struct_.struct_.set_size = browser_set_size;
struct_.struct_.is_popup_visible = browser_is_popup_visible;
struct_.struct_.hide_popup = browser_hide_popup;
struct_.struct_.invalidate = browser_invalidate;
struct_.struct_.get_image = browser_get_image;
struct_.struct_.send_key_event = browser_send_key_event;
struct_.struct_.send_mouse_click_event = browser_send_mouse_click_event;
struct_.struct_.send_mouse_move_event = browser_send_mouse_move_event;
struct_.struct_.send_mouse_wheel_event = browser_send_mouse_wheel_event;
struct_.struct_.send_focus_event = browser_send_focus_event;
struct_.struct_.send_capture_lost_event = browser_send_capture_lost_event;
} }
#ifdef _DEBUG #ifdef _DEBUG

View File

@ -117,6 +117,20 @@ enum cef_retval_t CEF_CALLBACK handler_handle_title_change(
CefBrowserCToCpp::Wrap(browser), CefString(title)); CefBrowserCToCpp::Wrap(browser), CefString(title));
} }
enum cef_retval_t CEF_CALLBACK handler_handle_nav_state_change(
struct _cef_handler_t* self, cef_browser_t* browser, int canGoBack,
int canGoForward)
{
DCHECK(self);
DCHECK(browser);
if(!self || !browser)
return RV_CONTINUE;
return CefHandlerCppToC::Get(self)->HandleNavStateChange(
CefBrowserCToCpp::Wrap(browser), (canGoBack?true:false),
(canGoForward?true:false));
}
enum cef_retval_t CEF_CALLBACK handler_handle_before_browse( enum cef_retval_t CEF_CALLBACK handler_handle_before_browse(
struct _cef_handler_t* self, cef_browser_t* browser, cef_frame_t* frame, struct _cef_handler_t* self, cef_browser_t* browser, cef_frame_t* frame,
struct _cef_request_t* request, enum cef_handler_navtype_t navType, struct _cef_request_t* request, enum cef_handler_navtype_t navType,
@ -545,6 +559,81 @@ enum cef_retval_t CEF_CALLBACK handler_handle_find_result(
activeMatchOrdinal, finalUpdate?true:false); activeMatchOrdinal, finalUpdate?true:false);
} }
enum cef_retval_t CEF_CALLBACK handler_handle_get_rect(
struct _cef_handler_t* self, cef_browser_t* browser, int screen,
cef_rect_t* rect)
{
DCHECK(self);
DCHECK(browser);
DCHECK(rect);
if(!self || !browser || !rect)
return RV_CONTINUE;
CefRect changeRect(*rect);
cef_retval_t rv = CefHandlerCppToC::Get(self)->HandleGetRect(
CefBrowserCToCpp::Wrap(browser), screen?true:false, changeRect);
*rect = changeRect;
return rv;
}
enum cef_retval_t CEF_CALLBACK handler_handle_get_screen_point(
struct _cef_handler_t* self, cef_browser_t* browser, int viewX, int viewY,
int* screenX, int* screenY)
{
DCHECK(self);
DCHECK(browser);
DCHECK(screenX);
DCHECK(screenY);
if(!self || !browser || !screenX || !screenY)
return RV_CONTINUE;
return CefHandlerCppToC::Get(self)->HandleGetScreenPoint(
CefBrowserCToCpp::Wrap(browser), viewX, viewY, *screenX, *screenY);
}
enum cef_retval_t CEF_CALLBACK handler_handle_popup_change(
struct _cef_handler_t* self, cef_browser_t* browser, int show,
const cef_rect_t* rect)
{
DCHECK(self);
DCHECK(browser);
DCHECK(rect);
if(!self || !browser || !rect)
return RV_CONTINUE;
CefRect changeRect(*rect);
return CefHandlerCppToC::Get(self)->HandlePopupChange(
CefBrowserCToCpp::Wrap(browser), show?true:false, changeRect);
}
enum cef_retval_t CEF_CALLBACK handler_handle_paint(struct _cef_handler_t* self,
cef_browser_t* browser, enum cef_paint_element_type_t type,
const cef_rect_t* dirtyRect, const void* buffer)
{
DCHECK(self);
DCHECK(browser);
DCHECK(dirtyRect);
if(!self || !browser || !dirtyRect)
return RV_CONTINUE;
CefRect rect(*dirtyRect);
return CefHandlerCppToC::Get(self)->HandlePaint(
CefBrowserCToCpp::Wrap(browser), type, rect, buffer);
}
enum cef_retval_t CEF_CALLBACK handler_handle_cursor_change(
struct _cef_handler_t* self, cef_browser_t* browser,
cef_cursor_handle_t cursor)
{
DCHECK(self);
DCHECK(browser);
if(!self || !browser)
return RV_CONTINUE;
return CefHandlerCppToC::Get(self)->HandleCursorChange(
CefBrowserCToCpp::Wrap(browser), cursor);
}
// CONSTRUCTOR - Do not edit by hand. // CONSTRUCTOR - Do not edit by hand.
@ -555,6 +644,7 @@ CefHandlerCppToC::CefHandlerCppToC(CefHandler* cls)
struct_.struct_.handle_after_created = handler_handle_after_created; struct_.struct_.handle_after_created = handler_handle_after_created;
struct_.struct_.handle_address_change = handler_handle_address_change; struct_.struct_.handle_address_change = handler_handle_address_change;
struct_.struct_.handle_title_change = handler_handle_title_change; struct_.struct_.handle_title_change = handler_handle_title_change;
struct_.struct_.handle_nav_state_change = handler_handle_nav_state_change;
struct_.struct_.handle_before_browse = handler_handle_before_browse; struct_.struct_.handle_before_browse = handler_handle_before_browse;
struct_.struct_.handle_load_start = handler_handle_load_start; struct_.struct_.handle_load_start = handler_handle_load_start;
struct_.struct_.handle_load_end = handler_handle_load_end; struct_.struct_.handle_load_end = handler_handle_load_end;
@ -584,6 +674,11 @@ CefHandlerCppToC::CefHandlerCppToC(CefHandler* cls)
struct_.struct_.handle_status = handler_handle_status; struct_.struct_.handle_status = handler_handle_status;
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; struct_.struct_.handle_find_result = handler_handle_find_result;
struct_.struct_.handle_get_rect = handler_handle_get_rect;
struct_.struct_.handle_get_screen_point = handler_handle_get_screen_point;
struct_.struct_.handle_popup_change = handler_handle_popup_change;
struct_.struct_.handle_paint = handler_handle_paint;
struct_.struct_.handle_cursor_change = handler_handle_cursor_change;
} }
#ifdef _DEBUG #ifdef _DEBUG

View File

@ -236,6 +236,110 @@ void CefBrowserCToCpp::CloseDevTools()
struct_->close_dev_tools(struct_); struct_->close_dev_tools(struct_);
} }
bool CefBrowserCToCpp::IsWindowRenderingDisabled()
{
if (CEF_MEMBER_MISSING(struct_, is_window_rendering_disabled))
return false;
return struct_->is_window_rendering_disabled(struct_)?true:false;
}
bool CefBrowserCToCpp::GetSize(PaintElementType type, int& width, int& height)
{
if (CEF_MEMBER_MISSING(struct_, get_size))
return false;
return struct_->get_size(struct_, type, &width, &height)?true:false;
}
void CefBrowserCToCpp::SetSize(PaintElementType type, int width, int height)
{
if (CEF_MEMBER_MISSING(struct_, set_size))
return;
struct_->set_size(struct_, type, width, height);
}
bool CefBrowserCToCpp::IsPopupVisible()
{
if (CEF_MEMBER_MISSING(struct_, is_popup_visible))
return false;
return struct_->is_popup_visible(struct_)?true:false;
}
void CefBrowserCToCpp::HidePopup()
{
if (CEF_MEMBER_MISSING(struct_, hide_popup))
return;
struct_->hide_popup(struct_);
}
void CefBrowserCToCpp::Invalidate(const CefRect& dirtyRect)
{
if (CEF_MEMBER_MISSING(struct_, invalidate))
return;
struct_->invalidate(struct_, &dirtyRect);
}
bool CefBrowserCToCpp::GetImage(PaintElementType type, int width, int height,
void* buffer)
{
if (CEF_MEMBER_MISSING(struct_, get_image))
return false;
return struct_->get_image(struct_, type, width, height, buffer)?true:false;
}
void CefBrowserCToCpp::SendKeyEvent(KeyType type, int key, int modifiers,
bool sysChar, bool imeChar)
{
struct_->send_key_event(struct_, type, key, modifiers, sysChar, imeChar);
}
void CefBrowserCToCpp::SendMouseClickEvent(int x, int y, MouseButtonType type,
bool mouseUp, int clickCount)
{
if (CEF_MEMBER_MISSING(struct_, send_mouse_click_event))
return;
struct_->send_mouse_click_event(struct_, x, y, type, mouseUp, clickCount);
}
void CefBrowserCToCpp::SendMouseMoveEvent(int x, int y, bool mouseLeave)
{
if (CEF_MEMBER_MISSING(struct_, send_mouse_move_event))
return;
struct_->send_mouse_move_event(struct_, x, y, mouseLeave);
}
void CefBrowserCToCpp::SendMouseWheelEvent(int x, int y, int delta)
{
if (CEF_MEMBER_MISSING(struct_, send_mouse_wheel_event))
return;
struct_->send_mouse_wheel_event(struct_, x, y, delta);
}
void CefBrowserCToCpp::SendFocusEvent(bool setFocus)
{
if (CEF_MEMBER_MISSING(struct_, send_focus_event))
return;
struct_->send_focus_event(struct_, setFocus);
}
void CefBrowserCToCpp::SendCaptureLostEvent()
{
if (CEF_MEMBER_MISSING(struct_, send_capture_lost_event))
return;
struct_->send_capture_lost_event(struct_);
}
#ifdef _DEBUG #ifdef _DEBUG
template<> long CefCToCpp<CefBrowserCToCpp, CefBrowser, template<> long CefCToCpp<CefBrowserCToCpp, CefBrowser,

View File

@ -54,6 +54,22 @@ public:
virtual void SetZoomLevel(double zoomLevel); virtual void SetZoomLevel(double zoomLevel);
virtual void ShowDevTools(); virtual void ShowDevTools();
virtual void CloseDevTools(); virtual void CloseDevTools();
virtual bool IsWindowRenderingDisabled();
virtual bool GetSize(PaintElementType type, int& width, int& height);
virtual void SetSize(PaintElementType type, int width, int height);
virtual bool IsPopupVisible();
virtual void HidePopup();
virtual void Invalidate(const CefRect& dirtyRect);
virtual bool GetImage(PaintElementType type, int width, int height,
void* buffer);
virtual void SendKeyEvent(KeyType type, int key, int modifiers, bool sysChar,
bool imeChar);
virtual void SendMouseClickEvent(int x, int y, MouseButtonType type,
bool mouseUp, int clickCount);
virtual void SendMouseMoveEvent(int x, int y, bool mouseLeave);
virtual void SendMouseWheelEvent(int x, int y, int delta);
virtual void SendFocusEvent(bool setFocus);
virtual void SendCaptureLostEvent();
}; };
#endif // USING_CEF_SHARED #endif // USING_CEF_SHARED

View File

@ -85,6 +85,16 @@ CefHandler::RetVal CefHandlerCToCpp::HandleTitleChange(
title.GetStruct()); title.GetStruct());
} }
CefHandler::RetVal CefHandlerCToCpp::HandleNavStateChange(
CefRefPtr<CefBrowser> browser, bool canGoBack, bool canGoForward)
{
if(CEF_MEMBER_MISSING(struct_, handle_nav_state_change))
return RV_CONTINUE;
return struct_->handle_nav_state_change(struct_,
CefBrowserCppToC::Wrap(browser), canGoBack, canGoForward);
}
CefHandler::RetVal CefHandlerCToCpp::HandleBeforeBrowse( CefHandler::RetVal CefHandlerCToCpp::HandleBeforeBrowse(
CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request, NavType navType, bool isRedirect) CefRefPtr<CefRequest> request, NavType navType, bool isRedirect)
@ -404,6 +414,57 @@ CefHandler::RetVal CefHandlerCToCpp::HandleFindResult(
activeMatchOrdinal, finalUpdate); activeMatchOrdinal, finalUpdate);
} }
CefHandler::RetVal CefHandlerCToCpp::HandleGetRect(
CefRefPtr<CefBrowser> browser, bool screen, CefRect& rect)
{
if(CEF_MEMBER_MISSING(struct_, handle_get_rect))
return RV_CONTINUE;
return struct_->handle_get_rect(struct_, CefBrowserCppToC::Wrap(browser),
screen, &rect);
}
CefHandler::RetVal CefHandlerCToCpp::HandleGetScreenPoint(
CefRefPtr<CefBrowser> browser, int viewX, int viewY, int& screenX,
int& screenY)
{
if(CEF_MEMBER_MISSING(struct_, handle_get_screen_point))
return RV_CONTINUE;
return struct_->handle_get_screen_point(struct_,
CefBrowserCppToC::Wrap(browser), viewX, viewY, &screenX, &screenY);
}
CefHandler::RetVal CefHandlerCToCpp::HandlePopupChange(
CefRefPtr<CefBrowser> browser, bool show, const CefRect& rect)
{
if(CEF_MEMBER_MISSING(struct_, handle_popup_change))
return RV_CONTINUE;
return struct_->handle_popup_change(struct_, CefBrowserCppToC::Wrap(browser),
show, &rect);
}
CefHandler::RetVal CefHandlerCToCpp::HandlePaint(CefRefPtr<CefBrowser> browser,
PaintElementType type, const CefRect& dirtyRect, const void* buffer)
{
if(CEF_MEMBER_MISSING(struct_, handle_paint))
return RV_CONTINUE;
return struct_->handle_paint(struct_, CefBrowserCppToC::Wrap(browser), type,
&dirtyRect, buffer);
}
CefHandler::RetVal CefHandlerCToCpp::HandleCursorChange(
CefRefPtr<CefBrowser> browser, CefCursorHandle cursor)
{
if(CEF_MEMBER_MISSING(struct_, handle_cursor_change))
return RV_CONTINUE;
return struct_->handle_cursor_change(struct_, CefBrowserCppToC::Wrap(browser),
cursor);
}
#ifdef _DEBUG #ifdef _DEBUG
template<> long CefCToCpp<CefHandlerCToCpp, CefHandler, template<> long CefCToCpp<CefHandlerCToCpp, CefHandler,

View File

@ -40,6 +40,8 @@ public:
CefRefPtr<CefFrame> frame, const CefString& url); CefRefPtr<CefFrame> frame, const CefString& url);
virtual RetVal HandleTitleChange(CefRefPtr<CefBrowser> browser, virtual RetVal HandleTitleChange(CefRefPtr<CefBrowser> browser,
const CefString& title); const CefString& title);
virtual RetVal HandleNavStateChange(CefRefPtr<CefBrowser> browser,
bool canGoBack, bool canGoForward);
virtual RetVal HandleBeforeBrowse(CefRefPtr<CefBrowser> browser, virtual RetVal HandleBeforeBrowse(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request,
NavType navType, bool isRedirect); NavType navType, bool isRedirect);
@ -96,6 +98,16 @@ public:
virtual RetVal HandleFindResult(CefRefPtr<CefBrowser> browser, int identifier, virtual RetVal HandleFindResult(CefRefPtr<CefBrowser> browser, int identifier,
int count, const CefRect& selectionRect, int activeMatchOrdinal, int count, const CefRect& selectionRect, int activeMatchOrdinal,
bool finalUpdate); bool finalUpdate);
virtual RetVal HandleGetRect(CefRefPtr<CefBrowser> browser, bool screen,
CefRect& rect);
virtual RetVal HandleGetScreenPoint(CefRefPtr<CefBrowser> browser, int viewX,
int viewY, int& screenX, int& screenY);
virtual RetVal HandlePopupChange(CefRefPtr<CefBrowser> browser, bool show,
const CefRect& rect);
virtual RetVal HandlePaint(CefRefPtr<CefBrowser> browser,
PaintElementType type, const CefRect& dirtyRect, const void* buffer);
virtual RetVal HandleCursorChange(CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor);
}; };
#endif // BUILDING_CEF_SHARED #endif // BUILDING_CEF_SHARED

View File

@ -96,6 +96,11 @@ CEF_EXPORT void cef_do_message_loop_work()
CefDoMessageLoopWork(); CefDoMessageLoopWork();
} }
CEF_EXPORT void cef_run_message_loop()
{
CefRunMessageLoop();
}
CEF_EXPORT int cef_register_extension(const cef_string_t* extension_name, CEF_EXPORT int cef_register_extension(const cef_string_t* extension_name,
const cef_string_t* javascript_code, const cef_string_t* javascript_code,
struct _cef_v8handler_t* handler) struct _cef_v8handler_t* handler)

View File

@ -81,6 +81,11 @@ void CefDoMessageLoopWork()
cef_do_message_loop_work(); cef_do_message_loop_work();
} }
void CefRunMessageLoop()
{
cef_run_message_loop();
}
bool CefRegisterExtension(const CefString& extension_name, bool CefRegisterExtension(const CefString& extension_name,
const CefString& javascript_code, const CefString& javascript_code,
CefRefPtr<CefV8Handler> handler) CefRefPtr<CefV8Handler> handler)

View File

@ -3,4 +3,6 @@
# file entry should be proceeded by the code review or bug report link that it # file entry should be proceeded by the code review or bug report link that it
# relates to. # relates to.
patches = { patches = {
# http://codereview.chromium.org/6730028/
'base' : '../base/'
} }

33
patch/patches/base.patch Normal file
View File

@ -0,0 +1,33 @@
Index: message_loop.cc
===================================================================
--- message_loop.cc (revision 74933)
+++ message_loop.cc (working copy)
@@ -287,9 +287,13 @@
}
void MessageLoop::AssertIdle() const {
+ DCHECK(IsIdle());
+}
+
+bool MessageLoop::IsIdle() const {
// We only check |incoming_queue_|, since we don't want to lock |work_queue_|.
base::AutoLock lock(incoming_queue_lock_);
- DCHECK(incoming_queue_.empty());
+ return incoming_queue_.empty();
}
//------------------------------------------------------------------------------
Index: message_loop.h
===================================================================
--- message_loop.h (revision 74933)
+++ message_loop.h (working copy)
@@ -318,6 +318,9 @@
// Asserts that the MessageLoop is "idle".
void AssertIdle() const;
+ // Returns true if the MessageLoop is "idle".
+ bool IsIdle() const;
+
//----------------------------------------------------------------------------
protected:
struct RunState {

View File

@ -35,8 +35,13 @@ void ClientHandler::ClientDownloadListener::NotifyDownloadError(
// ClientHandler implementation // ClientHandler implementation
ClientHandler::ClientHandler() ClientHandler::ClientHandler()
: m_MainHwnd(NULL), m_BrowserHwnd(NULL), m_EditHwnd(NULL), m_bLoading(false), : m_MainHwnd(NULL),
m_bCanGoBack(false), m_bCanGoForward(false), m_BrowserHwnd(NULL),
m_EditHwnd(NULL),
m_BackHwnd(NULL),
m_ForwardHwnd(NULL),
m_StopHwnd(NULL),
m_ReloadHwnd(NULL),
ALLOW_THIS_IN_INITIALIZER_LIST( ALLOW_THIS_IN_INITIALIZER_LIST(
m_DownloadListener(new ClientDownloadListener(this))) m_DownloadListener(new ClientDownloadListener(this)))
{ {
@ -62,6 +67,17 @@ CefHandler::RetVal ClientHandler::HandleAfterCreated(
return RV_CONTINUE; return RV_CONTINUE;
} }
CefHandler::RetVal ClientHandler::HandleNavStateChange(
CefRefPtr<CefBrowser> browser, bool canGoBack, bool canGoForward)
{
REQUIRE_UI_THREAD();
SetNavState(canGoBack, canGoForward);
return RV_CONTINUE;
}
CefHandler::RetVal ClientHandler::HandleLoadStart(CefRefPtr<CefBrowser> browser, CefHandler::RetVal ClientHandler::HandleLoadStart(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame) CefRefPtr<CefFrame> frame)
{ {
@ -69,12 +85,8 @@ CefHandler::RetVal ClientHandler::HandleLoadStart(CefRefPtr<CefBrowser> browser,
if(!browser->IsPopup() && frame->IsMain()) if(!browser->IsPopup() && frame->IsMain())
{ {
Lock();
// We've just started loading a page // We've just started loading a page
m_bLoading = true; SetLoading(true);
m_bCanGoBack = false;
m_bCanGoForward = false;
Unlock();
} }
return RV_CONTINUE; return RV_CONTINUE;
} }
@ -86,16 +98,12 @@ CefHandler::RetVal ClientHandler::HandleLoadEnd(CefRefPtr<CefBrowser> browser,
if(!browser->IsPopup() && frame->IsMain()) if(!browser->IsPopup() && frame->IsMain())
{ {
Lock();
// We've just finished loading a page // We've just finished loading a page
m_bLoading = false; SetLoading(false);
m_bCanGoBack = browser->CanGoBack();
m_bCanGoForward = browser->CanGoForward();
CefRefPtr<CefDOMVisitor> visitor = GetDOMVisitor(frame->GetURL()); CefRefPtr<CefDOMVisitor> visitor = GetDOMVisitor(frame->GetURL());
if(visitor.get()) if(visitor.get())
frame->VisitDOM(visitor); frame->VisitDOM(visitor);
Unlock();
} }
return RV_CONTINUE; return RV_CONTINUE;
} }
@ -227,16 +235,6 @@ CefHandler::RetVal ClientHandler::HandleConsoleMessage(
return RV_HANDLED; return RV_HANDLED;
} }
void ClientHandler::GetNavState(bool &isLoading, bool &canGoBack,
bool &canGoForward)
{
Lock();
isLoading = m_bLoading;
canGoBack = m_bCanGoBack;
canGoForward = m_bCanGoForward;
Unlock();
}
void ClientHandler::SetMainHwnd(CefWindowHandle hwnd) void ClientHandler::SetMainHwnd(CefWindowHandle hwnd)
{ {
Lock(); Lock();
@ -251,6 +249,19 @@ void ClientHandler::SetEditHwnd(CefWindowHandle hwnd)
Unlock(); Unlock();
} }
void ClientHandler::SetButtonHwnds(CefWindowHandle backHwnd,
CefWindowHandle forwardHwnd,
CefWindowHandle stopHwnd,
CefWindowHandle reloadHwnd)
{
Lock();
m_BackHwnd = backHwnd;
m_ForwardHwnd = forwardHwnd;
m_StopHwnd = stopHwnd;
m_ReloadHwnd = reloadHwnd;
Unlock();
}
std::string ClientHandler::GetLogFile() std::string ClientHandler::GetLogFile()
{ {
Lock(); Lock();

View File

@ -11,7 +11,7 @@
// Define this value to redirect all popup URLs to the main application browser // Define this value to redirect all popup URLs to the main application browser
// window. // window.
//s#define TEST_REDIRECT_POPUP_URLS //#define TEST_REDIRECT_POPUP_URLS
// Client implementation of the browser handler class // Client implementation of the browser handler class
class ClientHandler : public CefThreadSafeBase<CefHandler> class ClientHandler : public CefThreadSafeBase<CefHandler>
@ -68,6 +68,11 @@ public:
virtual RetVal HandleTitleChange(CefRefPtr<CefBrowser> browser, virtual RetVal HandleTitleChange(CefRefPtr<CefBrowser> browser,
const CefString& title); const CefString& title);
// Called on the UI thread when the navigation state has changed. The return
// value is currently ignored.
virtual RetVal HandleNavStateChange(CefRefPtr<CefBrowser> browser,
bool canGoBack, bool canGoForward);
// Called on the UI thread before browser navigation. The client has an // Called on the UI thread before browser navigation. The client has an
// opportunity to modify the |request| object if desired. Return RV_HANDLED // opportunity to modify the |request| object if desired. Return RV_HANDLED
// to cancel navigation. // to cancel navigation.
@ -365,11 +370,82 @@ public:
return RV_CONTINUE; return RV_CONTINUE;
} }
// Called on the UI thread to retrieve either the simulated screen rectangle
// if |screen| is true or the view rectangle if |screen| is false. The view
// rectangle is relative to the screen coordinates. This method is only called
// if window rendering has been disabled. Return RV_CONTINUE if the rectangle
// was provided.
virtual RetVal HandleGetRect(CefRefPtr<CefBrowser> browser, bool screen,
CefRect& rect)
{
// Only called when rendering off-screen.
ASSERT(false);
return RV_CONTINUE;
}
// Called on the UI thread retrieve the translation from view coordinates to
// actual screen coordinates. This method is only called if window rendering
// has been disabled. Return RV_CONTINUE if the screen coordinates were
// provided.
virtual RetVal HandleGetScreenPoint(CefRefPtr<CefBrowser> browser,
int viewX, int viewY, int& screenX,
int& screenY)
{
// Only called when rendering off-screen.
ASSERT(false);
return RV_CONTINUE;
}
// Called on the UI thread when the browser wants to show, hide, resize or
// move the popup. If |show| is true and |rect| is zero size then the popup
// should be shown. If |show| is true and |rect| is non-zero size then |rect|
// represents the popup location in view coordinates. If |show| is false
// then the popup should be hidden. This method is only called if window
// rendering has been disabled. The return value is currently ignored.
virtual RetVal HandlePopupChange(CefRefPtr<CefBrowser> browser, bool show,
const CefRect& rect)
{
// Only called when rendering off-screen.
ASSERT(false);
return RV_CONTINUE;
}
// Called when an element should be painted. |type| indicates whether the
// element is the view or the popup. |buffer| contains the pixel data for the
// whole image. |dirtyRect| indicates the portion of the image that has been
// repainted. On Windows |buffer| will be width*height*4 bytes in size and
// represents a BGRA image with an upper-left origin. This method is only
// called if window rendering has been disabled. The return value is currently
// ignored.
virtual RetVal HandlePaint(CefRefPtr<CefBrowser> browser,
PaintElementType type, const CefRect& dirtyRect,
const void* buffer)
{
// Only called when rendering off-screen.
ASSERT(false);
return RV_CONTINUE;
}
// Called when the browser window's cursor has changed. This method is only
// called if window rendering has been disabled. The return value is currently
// ignored.
virtual RetVal HandleCursorChange(CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor)
{
// Only called when rendering off-screen.
ASSERT(false);
return RV_CONTINUE;
}
// Retrieve the current navigation state flags // Retrieve the current navigation state flags
void GetNavState(bool &isLoading, bool &canGoBack, bool &canGoForward);
void SetMainHwnd(CefWindowHandle hwnd); void SetMainHwnd(CefWindowHandle hwnd);
CefWindowHandle GetMainHwnd() { return m_MainHwnd; } CefWindowHandle GetMainHwnd() { return m_MainHwnd; }
void SetEditHwnd(CefWindowHandle hwnd); void SetEditHwnd(CefWindowHandle hwnd);
void SetButtonHwnds(CefWindowHandle backHwnd,
CefWindowHandle forwardHwnd,
CefWindowHandle reloadHwnd,
CefWindowHandle stopHwnd);
CefRefPtr<CefBrowser> GetBrowser() { return m_Browser; } CefRefPtr<CefBrowser> GetBrowser() { return m_Browser; }
CefWindowHandle GetBrowserHwnd() { return m_BrowserHwnd; } CefWindowHandle GetBrowserHwnd() { return m_BrowserHwnd; }
@ -393,6 +469,9 @@ public:
void SendNotification(NotificationType type); void SendNotification(NotificationType type);
protected: protected:
virtual void SetLoading(bool isLoading);
virtual void SetNavState(bool canGoBack, bool canGoForward);
// The child browser window // The child browser window
CefRefPtr<CefBrowser> m_Browser; CefRefPtr<CefBrowser> m_Browser;
@ -405,12 +484,11 @@ protected:
// The edit window handle // The edit window handle
CefWindowHandle m_EditHwnd; CefWindowHandle m_EditHwnd;
// True if the page is currently loading // The button window handles
bool m_bLoading; CefWindowHandle m_BackHwnd;
// True if the user can navigate backwards CefWindowHandle m_ForwardHwnd;
bool m_bCanGoBack; CefWindowHandle m_StopHwnd;
// True if the user can navigate forwards CefWindowHandle m_ReloadHwnd;
bool m_bCanGoForward;
std::string m_LogFile; std::string m_LogFile;
@ -422,8 +500,6 @@ protected:
DOMVisitorMap m_DOMVisitors; DOMVisitorMap m_DOMVisitors;
}; };
#ifdef TEST_REDIRECT_POPUP_URLS
// Handler for popup windows that loads the request in an existing browser // Handler for popup windows that loads the request in an existing browser
// window. // window.
class ClientPopupHandler : public ClientHandler class ClientPopupHandler : public ClientHandler
@ -455,8 +531,6 @@ public:
protected: protected:
CefRefPtr<CefBrowser> m_ParentBrowser; CefRefPtr<CefBrowser> m_ParentBrowser;
}; };
#endif // TEST_REDIRECT_POPUP_URLS
// Returns the main browser window instance. // Returns the main browser window instance.
CefRefPtr<CefBrowser> AppGetBrowser(); CefRefPtr<CefBrowser> AppGetBrowser();

View File

@ -30,6 +30,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
IDS_LOGO BINARY "res\\logo.png" IDS_LOGO BINARY "res\\logo.png"
IDS_UIPLUGIN BINARY "res\\uiplugin.html" IDS_UIPLUGIN BINARY "res\\uiplugin.html"
IDS_OSRPLUGIN BINARY "res\\osrplugin.html"
IDS_LOGOBALL BINARY "res\\logoball.png" IDS_LOGOBALL BINARY "res\\logoball.png"
IDS_LOCALSTORAGE BINARY "res\\localstorage.html" IDS_LOCALSTORAGE BINARY "res\\localstorage.html"
IDS_XMLHTTPREQUEST BINARY "res\\xmlhttprequest.html" IDS_XMLHTTPREQUEST BINARY "res\\xmlhttprequest.html"
@ -76,6 +77,7 @@ BEGIN
MENUITEM "Request", ID_TESTS_REQUEST MENUITEM "Request", ID_TESTS_REQUEST
MENUITEM "Scheme Handler", ID_TESTS_SCHEME_HANDLER MENUITEM "Scheme Handler", ID_TESTS_SCHEME_HANDLER
MENUITEM "UI App Example", ID_TESTS_UIAPP MENUITEM "UI App Example", ID_TESTS_UIAPP
MENUITEM "Off-Screen Rendering Example",ID_TESTS_OSRAPP
MENUITEM "Local Storage", ID_TESTS_LOCALSTORAGE MENUITEM "Local Storage", ID_TESTS_LOCALSTORAGE
MENUITEM "XMLHttpRequest", ID_TESTS_XMLHTTPREQUEST MENUITEM "XMLHttpRequest", ID_TESTS_XMLHTTPREQUEST
MENUITEM "WebURLRequest", ID_TESTS_WEBURLREQUEST MENUITEM "WebURLRequest", ID_TESTS_WEBURLREQUEST

View File

@ -592,6 +592,16 @@ void ClientHandler::SendNotification(NotificationType type)
[delegate performSelectorOnMainThread:sel withObject:nil waitUntilDone:NO]; [delegate performSelectorOnMainThread:sel withObject:nil waitUntilDone:NO];
} }
void ClientHandler::SetLoading(bool isLoading)
{
// TODO(port): Change button status.
}
void ClientHandler::SetNavState(bool canGoBack, bool canGoForward)
{
// TODO(port): Change button status.
}
// Global functions // Global functions

View File

@ -7,6 +7,7 @@
#include "cefclient.h" #include "cefclient.h"
#include "binding_test.h" #include "binding_test.h"
#include "extension_test.h" #include "extension_test.h"
#include "osrplugin_test.h"
#include "plugin_test.h" #include "plugin_test.h"
#include "resource.h" #include "resource.h"
#include "resource_util.h" #include "resource_util.h"
@ -91,13 +92,15 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
// Register the internal UI client plugin. // Register the internal UI client plugin.
InitUIPluginTest(); InitUIPluginTest();
// Register the internal OSR client plugin.
InitOSRPluginTest();
// Register the V8 extension handler. // Register the V8 extension handler.
InitExtensionTest(); InitExtensionTest();
// Register the scheme handler. // Register the scheme handler.
InitSchemeTest(); InitSchemeTest();
MSG msg;
HACCEL hAccelTable; HACCEL hAccelTable;
// Initialize global strings // Initialize global strings
@ -116,29 +119,34 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
// Register the find event message. // Register the find event message.
uFindMsg = RegisterWindowMessage(FINDMSGSTRING); uFindMsg = RegisterWindowMessage(FINDMSGSTRING);
// Main message loop int result = 0;
while (GetMessage(&msg, NULL, 0, 0))
{
#ifdef TEST_SINGLE_THREADED_MESSAGE_LOOP
// Allow the CEF to do its message loop processing.
CefDoMessageLoopWork();
#endif
#ifdef TEST_SINGLE_THREADED_MESSAGE_LOOP
// Run the CEF message loop. This function will block until the application
// recieves a WM_QUIT message.
CefRunMessageLoop();
#else
MSG msg;
// Run the application message loop.
while (GetMessage(&msg, NULL, 0, 0)) {
// Allow processing of find dialog messages. // Allow processing of find dialog messages.
if(hFindDlg && IsDialogMessage(hFindDlg, &msg)) if (hFindDlg && IsDialogMessage(hFindDlg, &msg))
continue; continue;
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
{
TranslateMessage(&msg); TranslateMessage(&msg);
DispatchMessage(&msg); DispatchMessage(&msg);
} }
} }
// Shut down the CEF result = (int)msg.wParam;
#endif
// Shut down CEF.
CefShutdown(); CefShutdown();
return (int) msg.wParam; return result;
} }
// //
@ -355,6 +363,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
SetWindowLongPtr(editWnd, GWLP_WNDPROC, SetWindowLongPtr(editWnd, GWLP_WNDPROC,
reinterpret_cast<LONG_PTR>(WndProc)); reinterpret_cast<LONG_PTR>(WndProc));
g_handler->SetEditHwnd(editWnd); g_handler->SetEditHwnd(editWnd);
g_handler->SetButtonHwnds(backWnd, forwardWnd, reloadWnd, stopWnd);
rect.top += URLBAR_HEIGHT; rect.top += URLBAR_HEIGHT;
@ -367,32 +376,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
CefBrowser::CreateBrowser(info, false, CefBrowser::CreateBrowser(info, false,
static_cast<CefRefPtr<CefHandler> >(g_handler), static_cast<CefRefPtr<CefHandler> >(g_handler),
"http://www.google.com"); "http://www.google.com");
// Start the timer that will be used to update child window state. The
// timer is also necessary in single-threaded message loop mode so that
// CefDoMessageLoopWork() is called frequently enough for things like
// smooth JavaScript animation.
SetTimer(hWnd, 1, USER_TIMER_MINIMUM, NULL);
} }
return 0; return 0;
case WM_TIMER: case WM_COMMAND:
if(g_handler.get() && g_handler->GetBrowserHwnd())
{
// Retrieve the current navigation state
bool isLoading, canGoBack, canGoForward;
g_handler->GetNavState(isLoading, canGoBack, canGoForward);
// Update the status of child windows
EnableWindow(editWnd, TRUE);
EnableWindow(backWnd, canGoBack);
EnableWindow(forwardWnd, canGoForward);
EnableWindow(reloadWnd, !isLoading);
EnableWindow(stopWnd, isLoading);
}
return 0;
case WM_COMMAND:
{ {
CefRefPtr<CefBrowser> browser; CefRefPtr<CefBrowser> browser;
if(g_handler.get()) if(g_handler.get())
@ -514,6 +501,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
if(browser.get()) if(browser.get())
RunUIPluginTest(browser); RunUIPluginTest(browser);
return 0; return 0;
case ID_TESTS_OSRAPP: // Test the OSR app
if(browser.get())
RunOSRPluginTest(browser);
return 0;
case ID_TESTS_DOMACCESS: // Test DOM access case ID_TESTS_DOMACCESS: // Test DOM access
if(browser.get()) if(browser.get())
RunDOMAccessTest(browser); RunDOMAccessTest(browser);
@ -613,15 +604,14 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{ {
// Dont erase the background if the browser window has been loaded // Dont erase the background if the browser window has been loaded
// (this avoids flashing) // (this avoids flashing)
return 0; return 0;
} }
break; break;
case WM_DESTROY: case WM_DESTROY:
// The frame window has exited // The frame window has exited
KillTimer(hWnd, 1); PostQuitMessage(0);
PostQuitMessage(0); return 0;
return 0;
} }
return DefWindowProc(hWnd, message, wParam, lParam); return DefWindowProc(hWnd, message, wParam, lParam);
@ -725,6 +715,10 @@ CefHandler::RetVal ClientHandler::HandleBeforeResourceLoad(
// Show the uiapp contents // Show the uiapp contents
resourceStream = GetBinaryResourceReader(IDS_UIPLUGIN); resourceStream = GetBinaryResourceReader(IDS_UIPLUGIN);
mimeType = "text/html"; mimeType = "text/html";
} else if(url == "http://tests/osrapp") {
// Show the osrapp contents
resourceStream = GetBinaryResourceReader(IDS_OSRPLUGIN);
mimeType = "text/html";
} else if(url == "http://tests/localstorage") { } else if(url == "http://tests/localstorage") {
// Show the localstorage contents // Show the localstorage contents
resourceStream = GetBinaryResourceReader(IDS_LOCALSTORAGE); resourceStream = GetBinaryResourceReader(IDS_LOCALSTORAGE);
@ -765,6 +759,20 @@ void ClientHandler::SendNotification(NotificationType type)
PostMessage(m_MainHwnd, WM_COMMAND, id, 0); PostMessage(m_MainHwnd, WM_COMMAND, id, 0);
} }
void ClientHandler::SetLoading(bool isLoading)
{
ASSERT(m_EditHwnd != NULL && m_ReloadHwnd != NULL && m_StopHwnd != NULL);
EnableWindow(m_EditHwnd, TRUE);
EnableWindow(m_ReloadHwnd, !isLoading);
EnableWindow(m_StopHwnd, isLoading);
}
void ClientHandler::SetNavState(bool canGoBack, bool canGoForward)
{
ASSERT(m_BackHwnd != NULL && m_ForwardHwnd != NULL);
EnableWindow(m_BackHwnd, canGoBack);
EnableWindow(m_ForwardHwnd, canGoForward);
}
// Global functions // Global functions

View File

@ -135,31 +135,21 @@ void ClientPlugin::Shutdown()
LRESULT ClientPlugin::OnPaint(UINT message, WPARAM wparam, LPARAM lparam, LRESULT ClientPlugin::OnPaint(UINT message, WPARAM wparam, LPARAM lparam,
BOOL& handled) BOOL& handled)
{ {
static LPCWSTR text = L"Left click in the green area for a message box!";
PAINTSTRUCT paint_struct; PAINTSTRUCT paint_struct;
BeginPaint(&paint_struct); BeginPaint(&paint_struct);
Paint(paint_struct.hdc);
RECT client_rect;
GetClientRect(&client_rect);
int old_mode = SetBkMode(paint_struct.hdc, TRANSPARENT);
COLORREF old_color = SetTextColor(paint_struct.hdc, RGB(0, 0, 255));
RECT text_rect = client_rect;
DrawText(paint_struct.hdc, text, -1, &text_rect, DT_CENTER | DT_CALCRECT);
client_rect.top = ((client_rect.bottom - client_rect.top)
- (text_rect.bottom - text_rect.top)) / 2;
DrawText(paint_struct.hdc, text, -1, &client_rect, DT_CENTER);
SetBkMode(paint_struct.hdc, old_mode);
SetTextColor(paint_struct.hdc, old_color);
EndPaint(&paint_struct); EndPaint(&paint_struct);
return 0; return 0;
} }
// PrintClient is necessary to support off-screen rendering.
LRESULT ClientPlugin::OnPrintClient(UINT message, WPARAM wparam, LPARAM lparam,
BOOL& handled)
{
Paint(reinterpret_cast<HDC>(wparam));
return 0;
}
LRESULT ClientPlugin::OnEraseBackGround(UINT message, WPARAM wparam, LRESULT ClientPlugin::OnEraseBackGround(UINT message, WPARAM wparam,
LPARAM lparam, BOOL& handled) LPARAM lparam, BOOL& handled)
{ {
@ -187,4 +177,24 @@ void ClientPlugin::RefreshDisplay() {
UpdateWindow(); UpdateWindow();
} }
void ClientPlugin::Paint(HDC hdc) {
static LPCWSTR text = L"Left click in the green area for a message box!";
RECT client_rect;
GetClientRect(&client_rect);
int old_mode = SetBkMode(hdc, TRANSPARENT);
COLORREF old_color = SetTextColor(hdc, RGB(0, 0, 255));
RECT text_rect = client_rect;
DrawText(hdc, text, -1, &text_rect, DT_CENTER | DT_CALCRECT);
client_rect.top = ((client_rect.bottom - client_rect.top)
- (text_rect.bottom - text_rect.top)) / 2;
DrawText(hdc, text, -1, &client_rect, DT_CENTER);
SetBkMode(hdc, old_mode);
SetTextColor(hdc, old_color);
}
#endif // _WIN32 #endif // _WIN32

View File

@ -33,6 +33,7 @@ class ClientPlugin : public CWindowImpl<ClientPlugin> {
BEGIN_MSG_MAP(ClientPlugin) BEGIN_MSG_MAP(ClientPlugin)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackGround) MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackGround)
MESSAGE_HANDLER(WM_PAINT, OnPaint) MESSAGE_HANDLER(WM_PAINT, OnPaint)
MESSAGE_HANDLER(WM_PRINTCLIENT, OnPrintClient)
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
END_MSG_MAP() END_MSG_MAP()
@ -74,6 +75,8 @@ class ClientPlugin : public CWindowImpl<ClientPlugin> {
protected: protected:
// Window message handlers. // Window message handlers.
LRESULT OnPaint(UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled); LRESULT OnPaint(UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled);
LRESULT OnPrintClient(UINT message, WPARAM wparam, LPARAM lparam,
BOOL& handled);
LRESULT OnEraseBackGround(UINT message, WPARAM wparam, LPARAM lparam, LRESULT OnEraseBackGround(UINT message, WPARAM wparam, LPARAM lparam,
BOOL& handled); BOOL& handled);
LRESULT OnLButtonDown(UINT message, WPARAM wparam, LPARAM lparam, LRESULT OnLButtonDown(UINT message, WPARAM wparam, LPARAM lparam,
@ -83,6 +86,8 @@ class ClientPlugin : public CWindowImpl<ClientPlugin> {
// the plugin window. // the plugin window.
void RefreshDisplay(); void RefreshDisplay();
void Paint(HDC hdc);
private: private:
// The plugins opaque instance handle // The plugins opaque instance handle
NPP instance_; NPP instance_;

View File

@ -0,0 +1,706 @@
// Copyright (c) 2011 The Chromium Embedded Framework Authors.
// Portions copyright (c) 2006-2008 The Chromium 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 "osrplugin.h"
#include "cefclient.h"
#include "string_util.h"
#include <gl/gl.h>
#include <gl/glu.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include <sstream>
#ifdef _WIN32
// Initialized in NP_Initialize.
NPNetscapeFuncs* g_osrbrowser = NULL;
namespace {
GLuint g_textureID = -1;
float g_spinX = 0.0f;
float g_spinY = 0.0f;
int g_width = -1, g_height = -1;
CefRefPtr<CefBrowser> g_offscreenBrowser;
// Class holding pointers for the client plugin window.
class ClientPlugin
{
public:
ClientPlugin()
{
hWnd = NULL;
hDC = NULL;
hRC = NULL;
}
HWND hWnd;
HDC hDC;
HGLRC hRC;
};
// Handler for off-screen rendering windows.
class ClientOSRHandler : public ClientHandler
{
public:
ClientOSRHandler(ClientPlugin* plugin)
: plugin_(plugin), view_buffer_(NULL), view_buffer_size_(0),
popup_buffer_(NULL), popup_buffer_size_(0)
{
}
virtual ~ClientOSRHandler()
{
if (view_buffer_)
delete [] view_buffer_;
if (popup_buffer_)
delete [] popup_buffer_;
}
virtual RetVal HandleBeforeCreated(CefRefPtr<CefBrowser> parentBrowser,
CefWindowInfo& createInfo, bool popup,
const CefPopupFeatures& popupFeatures,
CefRefPtr<CefHandler>& handler,
CefString& url,
CefBrowserSettings& settings)
{
REQUIRE_UI_THREAD();
// Popups will be redirected to this browser window.
if(popup) {
createInfo.m_bWindowRenderingDisabled = TRUE;
handler = new ClientPopupHandler(g_offscreenBrowser);
}
return RV_CONTINUE;
}
virtual RetVal HandleAfterCreated(CefRefPtr<CefBrowser> browser)
{
REQUIRE_UI_THREAD();
// Set the view size to match the plugin window size.
browser->SetSize(PET_VIEW, g_width, g_height);
g_offscreenBrowser = browser;
return ClientHandler::HandleAfterCreated(browser);
}
virtual RetVal HandleAddressChange(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& url)
{
REQUIRE_UI_THREAD();
// Set the "url" value in the HTML.
std::stringstream ss;
std::string urlStr = url;
StringReplace(urlStr, "'", "\\'");
ss << "document.getElementById('url').value = '" << urlStr.c_str() << "'";
AppGetBrowser()->GetMainFrame()->ExecuteJavaScript(ss.str(), "", 0);
return RV_CONTINUE;
}
virtual RetVal HandleTitleChange(CefRefPtr<CefBrowser> browser,
const CefString& title)
{
REQUIRE_UI_THREAD();
// Set the "title" value in the HTML.
std::stringstream ss;
std::string titleStr = title;
StringReplace(titleStr, "'", "\\'");
ss << "document.getElementById('title').innerHTML = '" <<
titleStr.c_str() << "'";
AppGetBrowser()->GetMainFrame()->ExecuteJavaScript(ss.str(), "", 0);
return RV_CONTINUE;
}
virtual RetVal HandleGetRect(CefRefPtr<CefBrowser> browser, bool screen,
CefRect& rect)
{
REQUIRE_UI_THREAD();
// The simulated screen and view rectangle are the same. This is necessary
// for popup menus to be located and sized inside the view.
rect.x = rect.y = 0;
rect.width = g_width;
rect.height = g_height;
return RV_CONTINUE;
}
virtual RetVal HandleGetScreenPoint(CefRefPtr<CefBrowser> browser,
int viewX, int viewY, int& screenX,
int& screenY)
{
REQUIRE_UI_THREAD();
// Convert the point from view coordinates to actual screen coordinates.
POINT screen_pt = {viewX, viewY};
MapWindowPoints(plugin_->hWnd, HWND_DESKTOP, &screen_pt, 1);
screenX = screen_pt.x;
screenY = screen_pt.y;
return RV_CONTINUE;
}
virtual RetVal HandlePopupChange(CefRefPtr<CefBrowser> browser, bool show,
const CefRect& rect)
{
REQUIRE_UI_THREAD();
if (show && rect.width > 0) {
// Update the popup rectange. It will always be inside the view due to
// HandleGetRect().
ASSERT(rect.x + rect.width < g_width &&
rect.y + rect.height < g_height);
popup_rect_ = rect;
} else if(!show) {
// Clear the popup buffer.
popup_rect_.set(0,0,0,0);
if (popup_buffer_) {
delete [] popup_buffer_;
popup_buffer_ = NULL;
popup_buffer_size_ = 0;
}
}
return RV_CONTINUE;
}
virtual RetVal HandlePaint(CefRefPtr<CefBrowser> browser,
PaintElementType type, const CefRect& dirtyRect,
const void* buffer)
{
REQUIRE_UI_THREAD();
wglMakeCurrent(plugin_->hDC, plugin_->hRC);
glBindTexture(GL_TEXTURE_2D, g_textureID);
if (type == PET_VIEW) {
// Paint the view.
SetRGB(buffer, g_width, g_height, true);
// Update the whole texture. This is done for simplicity instead of
// updating just the dirty region.
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, g_width, g_height, GL_RGB,
GL_UNSIGNED_BYTE, view_buffer_);
}
if(popup_rect_.width > 0) {
if (type == PET_POPUP) {
// Paint the popup.
SetRGB(buffer, popup_rect_.width, popup_rect_.height, false);
}
if (popup_buffer_) {
// Update the popup region.
glTexSubImage2D(GL_TEXTURE_2D, 0, popup_rect_.x,
g_height-popup_rect_.y-popup_rect_.height, popup_rect_.width,
popup_rect_.height, GL_RGB, GL_UNSIGNED_BYTE, popup_buffer_);
}
}
return RV_CONTINUE;
}
virtual RetVal HandleCursorChange(CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor)
{
REQUIRE_UI_THREAD();
// Change the plugin window's cursor.
SetClassLong(plugin_->hWnd, GCL_HCURSOR,
static_cast<LONG>(reinterpret_cast<LONG_PTR>(cursor)));
SetCursor(cursor);
return RV_CONTINUE;
}
protected:
virtual void SetLoading(bool isLoading)
{
// Set the "stop" and "reload" button state in the HTML.
std::stringstream ss;
ss << "document.getElementById('stop').disabled = "
<< (isLoading?"false":"true") << ";"
<< "document.getElementById('reload').disabled = "
<< (isLoading?"true":"false") << ";";
AppGetBrowser()->GetMainFrame()->ExecuteJavaScript(ss.str(), "", 0);
}
virtual void SetNavState(bool canGoBack, bool canGoForward)
{
// Set the "back" and "forward" button state in the HTML.
std::stringstream ss;
ss << "document.getElementById('back').disabled = "
<< (canGoBack?"false":"true") << ";";
ss << "document.getElementById('forward').disabled = "
<< (canGoForward?"false":"true") << ";";
AppGetBrowser()->GetMainFrame()->ExecuteJavaScript(ss.str(), "", 0);
}
// Set the contents of the RGB buffer.
void SetRGB(const void* src, int width, int height, bool view)
{
SetBufferSize(width, height, view);
ConvertToRGB((unsigned char*)src, view?view_buffer_:popup_buffer_, width,
height);
}
// Size the RGB buffer.
void SetBufferSize(int width, int height, bool view)
{
int dst_size = width * height * 3;
// Allocate a new buffer if necesary.
if (view) {
if (dst_size > view_buffer_size_) {
if (view_buffer_)
delete [] view_buffer_;
view_buffer_ = new unsigned char[dst_size];
view_buffer_size_ = dst_size;
}
} else {
if (dst_size > popup_buffer_size_) {
if (popup_buffer_)
delete [] popup_buffer_;
popup_buffer_ = new unsigned char[dst_size];
popup_buffer_size_ = dst_size;
}
}
}
// Convert from BGRA to RGB format and from upper-left to lower-left origin.
static void ConvertToRGB(const unsigned char* src, unsigned char* dst,
int width, int height)
{
int sp = 0, dp = (height-1) * width * 3;
for(int i = 0; i < height; i++) {
for(int j = 0; j < width; j++, dp += 3, sp += 4) {
dst[dp] = src[sp+2]; // R
dst[dp+1] = src[sp+1]; // G
dst[dp+2] = src[sp]; // B
}
dp -= width * 6;
}
}
private:
ClientPlugin* plugin_;
unsigned char* view_buffer_;
int view_buffer_size_;
unsigned char* popup_buffer_;
int popup_buffer_size_;
CefRect popup_rect_;
};
// Forward declarations of functions included in this code module:
LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam);
// Enable GL.
void EnableGL(HWND hWnd, HDC * hDC, HGLRC * hRC)
{
PIXELFORMATDESCRIPTOR pfd;
int format;
// Get the device context.
*hDC = GetDC(hWnd);
// Set the pixel format for the DC.
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 16;
pfd.iLayerType = PFD_MAIN_PLANE;
format = ChoosePixelFormat(*hDC, &pfd);
SetPixelFormat(*hDC, format, &pfd);
// Create and enable the render context.
*hRC = wglCreateContext(*hDC);
wglMakeCurrent(*hDC, *hRC);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glEnable(GL_TEXTURE_2D);
// Necessary for non-power-of-2 textures to render correctly.
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
}
// Disable GL.
void DisableGL(HWND hWnd, HDC hDC, HGLRC hRC)
{
// Delete the texture.
if(g_textureID != -1)
glDeleteTextures(1, &g_textureID);
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hRC);
ReleaseDC(hWnd, hDC);
}
// Size the GL view.
void SizeGL(ClientPlugin* plugin, int width, int height)
{
g_width = width;
g_height = height;
wglMakeCurrent(plugin->hDC, plugin->hRC);
// Match GL units to screen coordinates.
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 0, width, height, 0.1, 100.0);
// Delete the existing exture.
if(g_textureID != -1)
glDeleteTextures(1, &g_textureID);
// Create a new texture.
glGenTextures(1, &g_textureID);
glBindTexture(GL_TEXTURE_2D, g_textureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Start with all white contents.
int size = width * height * 3;
unsigned char* buffer = new unsigned char[size];
memset(buffer, 255, size);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
GL_RGB, GL_UNSIGNED_BYTE, buffer);
delete [] buffer;
if(g_offscreenBrowser.get())
g_offscreenBrowser->SetSize(PET_VIEW, width, height);
}
// Render the view contents.
void RenderGL(ClientPlugin* plugin)
{
wglMakeCurrent(plugin->hDC, plugin->hRC);
struct {
float tu, tv;
float x, y, z;
} static vertices[] = {
{0.0f, 0.0f, -1.0f, -1.0f, 0.0f},
{1.0f, 0.0f, 1.0f, -1.0f, 0.0f},
{1.0f, 1.0f, 1.0f, 1.0f, 0.0f},
{0.0f, 1.0f, -1.0f, 1.0f, 0.0f}
};
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//glTranslatef(0.0f, 0.0f, -3.0f);
// Rotate the view based on the mouse spin.
glRotatef(-g_spinX, 1.0f, 0.0f, 0.0f);
glRotatef(-g_spinY, 0.0f, 1.0f, 0.0f);
// Enable alpha blending.
//glEnable(GL_BLEND);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Draw the facets with the texture.
glBindTexture(GL_TEXTURE_2D, g_textureID);
glInterleavedArrays(GL_T2F_V3F, 0, vertices);
glDrawArrays(GL_QUADS, 0, 4);
//glDisable(GL_BLEND);
SwapBuffers(plugin->hDC);
}
NPError NPP_NewImpl(NPMIMEType plugin_type, NPP instance, uint16 mode,
int16 argc, char* argn[], char* argv[],
NPSavedData* saved) {
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
ClientPlugin *plugin = new ClientPlugin;
instance->pdata = reinterpret_cast<void*>(plugin);
return NPERR_NO_ERROR;
}
NPError NPP_DestroyImpl(NPP instance, NPSavedData** save) {
ClientPlugin *plugin = reinterpret_cast<ClientPlugin*>(instance->pdata);
if (plugin) {
if(plugin->hWnd) {
DestroyWindow(plugin->hWnd);
DisableGL(plugin->hWnd, plugin->hDC, plugin->hRC);
}
delete plugin;
}
return NPERR_NO_ERROR;
}
NPError NPP_SetWindowImpl(NPP instance, NPWindow* window_info) {
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
if (window_info == NULL)
return NPERR_GENERIC_ERROR;
ClientPlugin *plugin = reinterpret_cast<ClientPlugin*>(instance->pdata);
HWND parent_hwnd = reinterpret_cast<HWND>(window_info->window);
if (plugin->hWnd == NULL)
{
WNDCLASS wc;
HINSTANCE hInstance = GetModuleHandle(NULL);
// Register the window class.
wc.style = CS_OWNDC;
wc.lpfnWndProc = PluginWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = L"ClientOSRPlugin";
RegisterClass(&wc);
// Create the main window.
plugin->hWnd = CreateWindow(L"ClientOSRPlugin", L"Client OSR Plugin",
WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS, 0, 0, 0, 0, parent_hwnd, NULL,
hInstance, NULL);
SetWindowLongPtr(plugin->hWnd, GWLP_USERDATA,
reinterpret_cast<LONG_PTR>(plugin));
// Enable GL drawing for the window.
EnableGL(plugin->hWnd, &(plugin->hDC), &(plugin->hRC));
// Create the off-screen rendering window.
CefWindowInfo windowInfo;
windowInfo.SetAsOffScreen(plugin->hWnd);
CefBrowser::CreateBrowser(windowInfo, false,
new ClientOSRHandler(plugin), "http://www.google.com");
}
// Position the plugin window and make sure it's visible.
RECT parent_rect;
GetClientRect(parent_hwnd, &parent_rect);
SetWindowPos(plugin->hWnd, NULL, parent_rect.left, parent_rect.top,
parent_rect.right - parent_rect.left,
parent_rect.bottom - parent_rect.top, SWP_SHOWWINDOW);
UpdateWindow(plugin->hWnd);
ShowWindow(plugin->hWnd, SW_SHOW);
return NPERR_NO_ERROR;
}
// Plugin window procedure.
LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam)
{
static POINT lastMousePos, curMousePos;
static bool mouseRotation = false;
static bool mouseTracking = false;
ClientPlugin* plugin =
reinterpret_cast<ClientPlugin*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
switch(message)
{
case WM_CREATE:
// Start the timer that's used for redrawing.
SetTimer(hWnd, 1, USER_TIMER_MINIMUM, NULL);
return 0;
case WM_DESTROY:
// Stop the timer that's used for redrawing.
KillTimer(hWnd, 1);
g_offscreenBrowser = NULL;
return 0;
case WM_TIMER:
RenderGL(plugin);
break;
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
SetCapture(hWnd);
SetFocus(hWnd);
if (wParam & MK_SHIFT) {
// Start rotation effect.
lastMousePos.x = curMousePos.x = LOWORD(lParam);
lastMousePos.y = curMousePos.y = HIWORD(lParam);
mouseRotation = true;
} else {
if (g_offscreenBrowser.get()) {
g_offscreenBrowser->SendMouseClickEvent(LOWORD(lParam), HIWORD(lParam),
(message==WM_LBUTTONDOWN?MBT_LEFT:MBT_RIGHT), false, 1);
}
}
break;
case WM_LBUTTONUP:
case WM_RBUTTONUP:
if (GetCapture() == hWnd)
ReleaseCapture();
if (mouseRotation) {
// End rotation effect.
mouseRotation = false;
g_spinX = 0;
g_spinY = 0;
} else {
if (g_offscreenBrowser.get()) {
g_offscreenBrowser->SendMouseClickEvent(LOWORD(lParam), HIWORD(lParam),
(message==WM_LBUTTONUP?MBT_LEFT:MBT_RIGHT), true, 1);
}
}
break;
case WM_MOUSEMOVE:
if(mouseRotation) {
// Apply rotation effect.
curMousePos.x = LOWORD(lParam);
curMousePos.y = HIWORD(lParam);
g_spinX -= (curMousePos.x - lastMousePos.x);
g_spinY -= (curMousePos.y - lastMousePos.y);
lastMousePos.x = curMousePos.x;
lastMousePos.y = curMousePos.y;
} else {
if (!mouseTracking) {
// Start tracking mouse leave. Required for the WM_MOUSELEAVE event to
// be generated.
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = hWnd;
TrackMouseEvent(&tme);
mouseTracking = true;
}
if (g_offscreenBrowser.get()) {
g_offscreenBrowser->SendMouseMoveEvent(LOWORD(lParam), HIWORD(lParam),
false);
}
}
break;
case WM_MOUSELEAVE:
if (mouseTracking) {
// Stop tracking mouse leave.
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE & TME_CANCEL;
tme.hwndTrack = hWnd;
TrackMouseEvent(&tme);
mouseTracking = false;
}
if (g_offscreenBrowser.get())
g_offscreenBrowser->SendMouseMoveEvent(0, 0, true);
break;
case WM_MOUSEWHEEL:
if (g_offscreenBrowser.get()) {
g_offscreenBrowser->SendMouseWheelEvent(LOWORD(lParam), HIWORD(lParam),
GET_WHEEL_DELTA_WPARAM(wParam));
}
break;
case WM_SIZE: {
int width = LOWORD(lParam);
int height = HIWORD(lParam);
if(width > 0 && height > 0)
SizeGL(plugin, width, height);
} break;
case WM_SETFOCUS:
case WM_KILLFOCUS:
if (g_offscreenBrowser.get())
g_offscreenBrowser->SendFocusEvent(message==WM_SETFOCUS);
break;
case WM_CAPTURECHANGED:
case WM_CANCELMODE:
if(!mouseRotation) {
if (g_offscreenBrowser.get())
g_offscreenBrowser->SendCaptureLostEvent();
}
break;
case WM_KEYDOWN:
case WM_KEYUP:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_CHAR:
case WM_SYSCHAR:
case WM_IME_CHAR:
if (g_offscreenBrowser.get()) {
CefBrowser::KeyType type = KT_CHAR;
bool sysChar = false, imeChar = false;
if (message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
type = KT_KEYDOWN;
else if (message == WM_KEYUP || message == WM_SYSKEYUP)
type = KT_KEYUP;
if (message == WM_SYSKEYDOWN || message == WM_SYSKEYUP ||
message == WM_SYSCHAR)
sysChar = true;
if (message == WM_IME_CHAR)
imeChar = true;
g_offscreenBrowser->SendKeyEvent(type, wParam, lParam, sysChar, imeChar);
}
break;
case WM_PAINT: {
PAINTSTRUCT ps;
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
} return 0;
case WM_ERASEBKGND:
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
} // namespace
NPError API_CALL NP_OSRGetEntryPoints(NPPluginFuncs* pFuncs)
{
pFuncs->newp = NPP_NewImpl;
pFuncs->destroy = NPP_DestroyImpl;
pFuncs->setwindow = NPP_SetWindowImpl;
return NPERR_NO_ERROR;
}
NPError API_CALL NP_OSRInitialize(NPNetscapeFuncs* pFuncs)
{
g_osrbrowser = pFuncs;
return NPERR_NO_ERROR;
}
NPError API_CALL NP_OSRShutdown(void)
{
g_osrbrowser = NULL;
return NPERR_NO_ERROR;
}
CefRefPtr<CefBrowser> GetOffScreenBrowser()
{
return g_offscreenBrowser;
}
#endif // _WIN32

View File

@ -0,0 +1,27 @@
// Copyright (c) 2011 The Chromium Embedded Framework Authors.
// Portions copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Portions of this implementation are borrowed from webkit\default_plugin\
// plugin_impl.h
#ifndef _CEFCLIENT_OSRPLUGIN_H
#define _CEFCLIENT_OSRPLUGIN_H
#include "include/cef.h"
#include "include/cef_nplugin.h"
#ifdef _WIN32
extern NPNetscapeFuncs* g_osrbrowser;
NPError API_CALL NP_OSRGetEntryPoints(NPPluginFuncs* pFuncs);
NPError API_CALL NP_OSRInitialize(NPNetscapeFuncs* pFuncs);
NPError API_CALL NP_OSRShutdown(void);
CefRefPtr<CefBrowser> GetOffScreenBrowser();
#endif // _WIN32
#endif // _CEFCLIENT_OSRPLUGIN_H

View File

@ -0,0 +1,123 @@
// Copyright (c) 2011 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 "osrplugin_test.h"
#include "osrplugin.h"
#include "cefclient.h"
#include "plugin_test.h"
void InitOSRPluginTest()
{
// Structure providing information about the client plugin.
CefPluginInfo plugin_info;
CefString(&plugin_info.display_name).FromASCII("Client OSR Plugin");
CefString(&plugin_info.unique_name).FromASCII("client_osr_plugin");
CefString(&plugin_info.description).FromASCII("My Example Client OSR Plugin");
CefString(&plugin_info.mime_type).FromASCII(
"application/x-client-osr-plugin");
plugin_info.np_getentrypoints = NP_OSRGetEntryPoints;
plugin_info.np_initialize = NP_OSRInitialize;
plugin_info.np_shutdown = NP_OSRShutdown;
// Register the internal client plugin
CefRegisterPlugin(plugin_info);
}
void RunOSRPluginTest(CefRefPtr<CefBrowser> browser)
{
class Listener : public CefThreadSafeBase<CefDOMEventListener>
{
public:
Listener() {}
virtual void HandleEvent(CefRefPtr<CefDOMEvent> event)
{
CefRefPtr<CefBrowser> browser = GetOffScreenBrowser();
CefRefPtr<CefDOMNode> element = event->GetTarget();
ASSERT(element.get());
std::string elementId = element->GetElementAttribute("id");
if (elementId == "back") {
browser->GoBack();
} else if(elementId == "forward") {
browser->GoForward();
} else if(elementId == "stop") {
browser->Reload();
} else if(elementId == "reload") {
browser->StopLoad();
} else if (elementId == "go") {
// Retrieve the value of the "url" field and load it in the off-screen
// browser window.
CefRefPtr<CefDOMDocument> document = event->GetDocument();
ASSERT(document.get());
CefRefPtr<CefDOMNode> url = document->GetElementById("url");
ASSERT(url.get());
CefString value = url->GetValue();
if (!value.empty())
browser->GetMainFrame()->LoadURL(value);
} else if(elementId == "testWindowedPlugin") {
// Run the windowed plugin test.
RunPluginTest(browser);
} else if(elementId == "testWindowlessPlugin") {
// Load flash, which is a windowless plugin.
browser->GetMainFrame()->LoadURL(
"http://www.adobe.com/software/flash/about/");
} else if(elementId == "viewSource") {
// View the page source for the host browser window.
AppGetBrowser()->GetMainFrame()->ViewSource();
} else {
// Not reached.
ASSERT(false);
}
}
};
class Visitor : public CefThreadSafeBase<CefDOMVisitor>
{
public:
Visitor() {}
void RegisterClickListener(CefRefPtr<CefDOMDocument> document,
CefRefPtr<CefDOMEventListener> listener,
const std::string& elementId)
{
CefRefPtr<CefDOMNode> element = document->GetElementById(elementId);
ASSERT(element.get());
element->AddEventListener("click", listener, false);
}
virtual void Visit(CefRefPtr<CefDOMDocument> document)
{
CefRefPtr<CefDOMEventListener> listener(new Listener());
// Register click listeners for the various HTML elements.
RegisterClickListener(document, listener, "back");
RegisterClickListener(document, listener, "forward");
RegisterClickListener(document, listener, "stop");
RegisterClickListener(document, listener, "reload");
RegisterClickListener(document, listener, "go");
RegisterClickListener(document, listener, "testWindowedPlugin");
RegisterClickListener(document, listener, "testWindowlessPlugin");
RegisterClickListener(document, listener, "viewSource");
}
};
// Center the window on the screen.
int screenX = GetSystemMetrics(SM_CXFULLSCREEN);
int screenY = GetSystemMetrics(SM_CYFULLSCREEN);
int width = 1000, height = 760;
int x = (screenX - width) / 2;
int y = (screenY - height) / 2;
SetWindowPos(AppGetMainHwnd(), NULL, x, y, width, height,
SWP_NOZORDER | SWP_SHOWWINDOW);
// The DOM visitor will be called after the path is loaded.
CefRefPtr<CefHandler> handler = browser->GetHandler();
static_cast<ClientHandler*>(handler.get())->AddDOMVisitor(
"http://tests/osrapp", new Visitor());
browser->GetMainFrame()->LoadURL("http://tests/osrapp");
}

View File

@ -0,0 +1,16 @@
// Copyright (c) 2011 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.
#ifndef _CEFCLIENT_OSRPLUGIN_TEST_H
#define _CEFCLIENT_OSRPLUGIN_TEST_H
#include "include/cef.h"
// Register the internal client plugin and V8 extension.
void InitOSRPluginTest();
// Run the test.
void RunOSRPluginTest(CefRefPtr<CefBrowser> browser);
#endif // _CEFCLIENT_OSRPLUGIN_TEST_H

View File

@ -24,10 +24,11 @@ void InitPluginTest()
void RunPluginTest(CefRefPtr<CefBrowser> browser) void RunPluginTest(CefRefPtr<CefBrowser> browser)
{ {
// Add some extra space below the plugin to allow scrolling.
std::string html = std::string html =
"<html><body>Client Plugin:<br>" "<html><body>Client Plugin:<br>"
"<embed type=\"application/x-client-plugin\"" "<embed type=\"application/x-client-plugin\" width=600 height=40>"
"width=600 height=40>" "<div style=\"height:1000px;\">&nbsp;</div>"
"</body></html>"; "</body></html>";
browser->GetMainFrame()->LoadString(html, "about:blank"); browser->GetMainFrame()->LoadString(html, "about:blank");
} }

View File

@ -0,0 +1,51 @@
<html>
<head>
<title>Off-Screen Rendering App Example</title>
</head>
<body bottommargin="2" rightmargin="0" leftmargin="0" topmargin="0" marginwidth="0" marginheight="0" style="font-family: Verdana, Arial;">
<div align="center">
<table border="0" cellpadding="0" cellspacing="0" width="99.9%" height="100%">
<tr>
<td height="100%" align="center" valign="top">
<table border="0" cellpadding="2" cellspacing="0">
<tr>
<td colspan="2" style="font-size: 18pt;">Off-Screen Rendering App Example</td>
</tr>
<tr>
<td colspan="2" style="font-size: 8pt;"><i>An embedded OpenGL plugin window that renders content from an off-screen browser window.</i>
<a href="#" id="viewSource">View Page Source</a></td>
</tr>
<tr>
<td colspan="2" height="10"></td>
</tr>
<tr>
<td width="100" valign="top"><img src="logoball.png" width="100" height="101"></td>
<td style="font-size: 10pt;"><span style="font-size: 12pt;">You can rotate the view!</span>
<ul>
<li>Click and drag the view with the left mouse button while holding the shift key.</li>
<li>Enter a URL and click the "Go!" button to browse to a new Website.</li>
<li><a href="#" id="testWindowedPlugin">Click here</a> to test a windowed plugin. Windowed plugins must handle the WM_PRINTCLIENT message.</li>
<li><a href="#" id="testWindowlessPlugin">Click here</a> to test a windowless plugin. Windowless plugins can be used without modification.</li>
</ul>
</td>
</tr>
</table>
<div style="padding: 2px; margin: 5px; width: 960px;" align="left">
<span id="title" style="font-size: 12pt; font-weight: bold;">&nbsp;</span>
<br>
<input type="button" id="back" value="Back">
<input type="button" id="forward" value="Forward">
<input type="button" id="stop" value="Stop">
<input type="button" id="reload" value="Reload">
<input type="text" id="url" size="80"><input type="button" id="go" value="Go!">
</div>
<div style="padding: 2px; margin: 5px; border: red 1px solid; width: 960px;">
<embed type="application/x-client-osr-plugin" width=960 height=400></embed>
</div>
</td>
</tr>
</table>
</div>
</body>
</html>

View File

@ -50,6 +50,7 @@
#define ID_TESTS_WEBURLREQUEST 32790 #define ID_TESTS_WEBURLREQUEST 32790
#define ID_TESTS_DOMACCESS 32791 #define ID_TESTS_DOMACCESS 32791
#define ID_TESTS_DRAGDROP 32792 #define ID_TESTS_DRAGDROP 32792
#define ID_TESTS_OSRAPP 32793
#define IDC_STATIC -1 #define IDC_STATIC -1
#define IDS_LOGO 1000 #define IDS_LOGO 1000
#define IDS_UIPLUGIN 1001 #define IDS_UIPLUGIN 1001
@ -57,6 +58,7 @@
#define IDS_LOCALSTORAGE 1003 #define IDS_LOCALSTORAGE 1003
#define IDS_XMLHTTPREQUEST 1004 #define IDS_XMLHTTPREQUEST 1004
#define IDS_DOMACCESS 1005 #define IDS_DOMACCESS 1005
#define IDS_OSRPLUGIN 1006
// Avoid files associated with MacOS // Avoid files associated with MacOS
#define _X86_ #define _X86_

View File

@ -13,6 +13,8 @@
// Initialized in NP_Initialize. // Initialized in NP_Initialize.
NPNetscapeFuncs* g_uibrowser = NULL; NPNetscapeFuncs* g_uibrowser = NULL;
namespace {
// Global values. // Global values.
float g_rotationspeed = 0.0f; float g_rotationspeed = 0.0f;
float g_theta = 0.0f; float g_theta = 0.0f;
@ -39,9 +41,9 @@ LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC); void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC);
void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC); void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC);
static NPError NPP_NewImpl(NPMIMEType plugin_type, NPP instance, uint16 mode,
NPError NPP_New(NPMIMEType plugin_type, NPP instance, uint16 mode, int16 argc, int16 argc, char* argn[], char* argv[],
char* argn[], char* argv[], NPSavedData* saved) { NPSavedData* saved) {
if (instance == NULL) if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR; return NPERR_INVALID_INSTANCE_ERROR;
@ -51,8 +53,7 @@ NPError NPP_New(NPMIMEType plugin_type, NPP instance, uint16 mode, int16 argc,
return NPERR_NO_ERROR; return NPERR_NO_ERROR;
} }
static NPError NPP_DestroyImpl(NPP instance, NPSavedData** save) {
NPError NPP_Destroy(NPP instance, NPSavedData** save) {
ClientPlugin *plugin = reinterpret_cast<ClientPlugin*>(instance->pdata); ClientPlugin *plugin = reinterpret_cast<ClientPlugin*>(instance->pdata);
if (plugin) { if (plugin) {
@ -68,8 +69,7 @@ NPError NPP_Destroy(NPP instance, NPSavedData** save) {
return NPERR_NO_ERROR; return NPERR_NO_ERROR;
} }
static NPError NPP_SetWindowImpl(NPP instance, NPWindow* window_info) {
NPError NPP_SetWindow(NPP instance, NPWindow* window_info) {
if (instance == NULL) if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR; return NPERR_INVALID_INSTANCE_ERROR;
@ -96,11 +96,14 @@ NPError NPP_SetWindow(NPP instance, NPWindow* window_info) {
wc.lpszMenuName = NULL; wc.lpszMenuName = NULL;
wc.lpszClassName = L"ClientUIPlugin"; wc.lpszClassName = L"ClientUIPlugin";
RegisterClass(&wc); RegisterClass(&wc);
// Create the main window. // Create the main window.
plugin->hWnd = CreateWindow(L"ClientUIPlugin", L"Client UI Plugin", plugin->hWnd = CreateWindow(L"ClientUIPlugin", L"Client UI Plugin",
WS_CHILD, 0, 0, 0, 0, parent_hwnd, NULL, hInstance, NULL); WS_CHILD, 0, 0, 0, 0, parent_hwnd, NULL, hInstance, NULL);
SetWindowLongPtr(plugin->hWnd, GWLP_USERDATA,
reinterpret_cast<LONG_PTR>(plugin));
// Enable OpenGL drawing for the window. // Enable OpenGL drawing for the window.
EnableOpenGL(plugin->hWnd, &(plugin->hDC), &(plugin->hRC)); EnableOpenGL(plugin->hWnd, &(plugin->hDC), &(plugin->hRC));
} }
@ -118,26 +121,6 @@ NPError NPP_SetWindow(NPP instance, NPWindow* window_info) {
return NPERR_NO_ERROR; return NPERR_NO_ERROR;
} }
NPError API_CALL NP_UIGetEntryPoints(NPPluginFuncs* pFuncs)
{
pFuncs->newp = NPP_New;
pFuncs->destroy = NPP_Destroy;
pFuncs->setwindow = NPP_SetWindow;
return NPERR_NO_ERROR;
}
NPError API_CALL NP_UIInitialize(NPNetscapeFuncs* pFuncs)
{
g_uibrowser = pFuncs;
return NPERR_NO_ERROR;
}
NPError API_CALL NP_UIShutdown(void)
{
g_uibrowser = NULL;
return NPERR_NO_ERROR;
}
// Send the notification to the browser as a JavaScript function call. // Send the notification to the browser as a JavaScript function call.
static void NotifyNewRotation(float value) static void NotifyNewRotation(float value)
{ {
@ -147,18 +130,6 @@ static void NotifyNewRotation(float value)
0); 0);
} }
void ModifyRotation(float value)
{
g_rotationspeed += value;
NotifyNewRotation(g_rotationspeed);
}
void ResetRotation()
{
g_rotationspeed = 0.0;
NotifyNewRotation(g_rotationspeed);
}
// Nice little fly polygon borrowed from the OpenGL Red Book. // Nice little fly polygon borrowed from the OpenGL Red Book.
const GLubyte fly[] = { const GLubyte fly[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -183,9 +154,9 @@ const GLubyte fly[] = {
LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam, LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam) LPARAM lParam)
{ {
HDC hDC; ClientPlugin* plugin =
int width, height; reinterpret_cast<ClientPlugin*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
switch(message) switch(message)
{ {
case WM_CREATE: case WM_CREATE:
@ -209,19 +180,23 @@ LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
return 0; return 0;
case WM_SIZE: case WM_SIZE:
// Resize the OpenGL viewport to match the window size. if (plugin) {
width = LOWORD(lParam); // Resize the OpenGL viewport to match the window size.
height = HIWORD(lParam); int width = LOWORD(lParam);
glViewport(0, 0, width, height); int height = HIWORD(lParam);
wglMakeCurrent(plugin->hDC, plugin->hRC);
glViewport(0, 0, width, height);
}
break; break;
case WM_ERASEBKGND: case WM_ERASEBKGND:
return 0; return 0;
case WM_TIMER: case WM_TIMER:
wglMakeCurrent(plugin->hDC, plugin->hRC);
// Adjust the theta value and redraw the display when the timer fires. // Adjust the theta value and redraw the display when the timer fires.
hDC = GetDC(hWnd);
glClearColor(1.0f, 1.0f, 1.0f, 0.0f); glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
@ -240,8 +215,7 @@ LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT message, WPARAM wParam,
glDisable(GL_POLYGON_STIPPLE); glDisable(GL_POLYGON_STIPPLE);
glPopMatrix(); glPopMatrix();
SwapBuffers(hDC); SwapBuffers(plugin->hDC);
ReleaseDC(hWnd, hDC);
g_theta -= g_rotationspeed; g_theta -= g_rotationspeed;
} }
@ -272,7 +246,6 @@ void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC)
// Create and enable the render contex. // Create and enable the render contex.
*hRC = wglCreateContext(*hDC); *hRC = wglCreateContext(*hDC);
wglMakeCurrent(*hDC, *hRC);
} }
// Disable OpenGL. // Disable OpenGL.
@ -283,4 +256,38 @@ void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC)
ReleaseDC(hWnd, hDC); ReleaseDC(hWnd, hDC);
} }
} // namespace
NPError API_CALL NP_UIGetEntryPoints(NPPluginFuncs* pFuncs)
{
pFuncs->newp = NPP_NewImpl;
pFuncs->destroy = NPP_DestroyImpl;
pFuncs->setwindow = NPP_SetWindowImpl;
return NPERR_NO_ERROR;
}
NPError API_CALL NP_UIInitialize(NPNetscapeFuncs* pFuncs)
{
g_uibrowser = pFuncs;
return NPERR_NO_ERROR;
}
NPError API_CALL NP_UIShutdown(void)
{
g_uibrowser = NULL;
return NPERR_NO_ERROR;
}
void ModifyRotation(float value)
{
g_rotationspeed += value;
NotifyNewRotation(g_rotationspeed);
}
void ResetRotation()
{
g_rotationspeed = 0.0;
NotifyNewRotation(g_rotationspeed);
}
#endif // _WIN32 #endif // _WIN32

View File

@ -65,6 +65,12 @@ public:
return RV_CONTINUE; return RV_CONTINUE;
} }
virtual RetVal HandleNavStateChange(CefRefPtr<CefBrowser> browser,
bool canGoBack, bool canGoForward)
{
return RV_CONTINUE;
}
virtual RetVal HandleTitleChange(CefRefPtr<CefBrowser> browser, virtual RetVal HandleTitleChange(CefRefPtr<CefBrowser> browser,
const CefString& title) const CefString& title)
{ {
@ -284,6 +290,38 @@ public:
return RV_CONTINUE; return RV_CONTINUE;
} }
virtual RetVal HandleGetRect(CefRefPtr<CefBrowser> browser, bool screen,
CefRect& rect)
{
return RV_CONTINUE;
}
virtual RetVal HandleGetScreenPoint(CefRefPtr<CefBrowser> browser,
int viewX, int viewY, int& screenX,
int& screenY)
{
return RV_CONTINUE;
}
virtual RetVal HandlePopupChange(CefRefPtr<CefBrowser> browser, bool show,
const CefRect& rect)
{
return RV_CONTINUE;
}
virtual RetVal HandlePaint(CefRefPtr<CefBrowser> browser,
PaintElementType type, const CefRect& dirtyRect,
const void* buffer)
{
return RV_CONTINUE;
}
virtual RetVal HandleCursorChange(CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor)
{
return RV_CONTINUE;
}
CefRefPtr<CefBrowser> GetBrowser() CefRefPtr<CefBrowser> GetBrowser()
{ {
return browser_; return browser_;

View File

@ -1065,6 +1065,7 @@ class obj_analysis:
'size_t' : 'size_t', 'size_t' : 'size_t',
'time_t' : 'time_t', 'time_t' : 'time_t',
'bool' : 'int', 'bool' : 'int',
'CefCursorHandle' : 'cef_cursor_handle_t',
'CefWindowHandle' : 'cef_window_handle_t', 'CefWindowHandle' : 'cef_window_handle_t',
'CefRect' : 'cef_rect_t', 'CefRect' : 'cef_rect_t',
'CefThreadId' : 'cef_thread_id_t', 'CefThreadId' : 'cef_thread_id_t',