diff --git a/cef.gyp b/cef.gyp index 7b9c88589..8962b6771 100644 --- a/cef.gyp +++ b/cef.gyp @@ -950,7 +950,6 @@ '<@(includes_win)', 'libcef/browser/backing_store_osr.cc', 'libcef/browser/backing_store_osr.h', - 'libcef/browser/backing_store_osr_win.cc', 'libcef/browser/browser_host_impl_win.cc', 'libcef/browser/browser_main_win.cc', 'libcef/browser/javascript_dialog_win.cc', diff --git a/cef_paths2.gypi b/cef_paths2.gypi index 30d6ebe59..cb1ec4984 100644 --- a/cef_paths2.gypi +++ b/cef_paths2.gypi @@ -128,6 +128,7 @@ 'tests/cefclient/res/cefclient.ico', 'tests/cefclient/res/logoball.png', 'tests/cefclient/res/small.ico', + 'tests/cefclient/res/transparency.html', 'tests/cefclient/resource_util_win.cpp', ], 'cefclient_sources_mac': [ diff --git a/include/capi/cef_browser_capi.h b/include/capi/cef_browser_capi.h index 89d98f0d8..b10c64c89 100644 --- a/include/capi/cef_browser_capi.h +++ b/include/capi/cef_browser_capi.h @@ -318,7 +318,7 @@ typedef struct _cef_browser_host_t { // function is only used when window rendering is disabled. /// void (CEF_CALLBACK *invalidate)(struct _cef_browser_host_t* self, - const cef_rect_t* dirtyRect); + const cef_rect_t* dirtyRect, enum cef_paint_element_type_t type); /// // Send a key event to the browser. @@ -331,23 +331,25 @@ typedef struct _cef_browser_host_t { // relative to the upper-left corner of the view. /// void (CEF_CALLBACK *send_mouse_click_event)(struct _cef_browser_host_t* self, - int x, int y, enum cef_mouse_button_type_t type, int mouseUp, - int clickCount); + const struct _cef_mouse_event_t* event, + 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_host_t* self, - int x, int y, int mouseLeave); + const struct _cef_mouse_event_t* event, 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. The |deltaX| and |deltaY| // values represent the movement delta in the X and Y directions respectively. + // In order to scroll inside select popups with window rendering disabled + // cef_render_handler_t::GetScreenPoint should be implemented properly. /// void (CEF_CALLBACK *send_mouse_wheel_event)(struct _cef_browser_host_t* self, - int x, int y, int deltaX, int deltaY); + const struct _cef_mouse_event_t* event, int deltaX, int deltaY); /// // Send a focus event to the browser. diff --git a/include/capi/cef_render_handler_capi.h b/include/capi/cef_render_handler_capi.h index 6ba75be16..da57b65ec 100644 --- a/include/capi/cef_render_handler_capi.h +++ b/include/capi/cef_render_handler_capi.h @@ -57,8 +57,7 @@ typedef struct _cef_render_handler_t { /// // Called to retrieve the root window rectangle in screen coordinates. Return - // true (1) if the rectangle was provided. Return false (0) if the screen - // rectangle is the same as the view rectangle. + // true (1) if the rectangle was provided. /// int (CEF_CALLBACK *get_root_screen_rect)(struct _cef_render_handler_t* self, struct _cef_browser_t* browser, cef_rect_t* rect); @@ -81,15 +80,13 @@ typedef struct _cef_render_handler_t { /// // Called when the browser wants to show or hide the popup widget. The popup // should be shown if |show| is true (1) and hidden if |show| is false (0). - // NOTE: Popup widgets are not yet supported. /// void (CEF_CALLBACK *on_popup_show)(struct _cef_render_handler_t* self, struct _cef_browser_t* browser, int show); /// // Called when the browser wants to move or resize the popup widget. |rect| - // contains the new location and size. NOTE: Popup widgets are not yet - // supported. + // contains the new location and size. /// void (CEF_CALLBACK *on_popup_size)(struct _cef_render_handler_t* self, struct _cef_browser_t* browser, const cef_rect_t* rect); @@ -99,8 +96,7 @@ typedef struct _cef_render_handler_t { // element is the view or the popup widget. |buffer| contains the pixel data // for the whole image. |dirtyRects| contains the set of rectangles that need // to be repainted. On Windows |buffer| will be |width|*|height|*4 bytes in - // size and represents a BGRA image with an upper-left origin. NOTE: Popup - // widgets are not yet supported. + // size and represents a BGRA image with an upper-left origin. /// void (CEF_CALLBACK *on_paint)(struct _cef_render_handler_t* self, struct _cef_browser_t* browser, enum cef_paint_element_type_t type, diff --git a/include/cef_browser.h b/include/cef_browser.h index d9defce97..c19e5f502 100644 --- a/include/cef_browser.h +++ b/include/cef_browser.h @@ -219,6 +219,7 @@ class CefBrowserHost : public virtual CefBase { public: typedef cef_file_dialog_mode_t FileDialogMode; 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 @@ -359,7 +360,7 @@ class CefBrowserHost : public virtual CefBase { // method is only used when window rendering is disabled. /// /*--cef()--*/ - virtual void Invalidate(const CefRect& dirtyRect) =0; + virtual void Invalidate(const CefRect& dirtyRect, PaintElementType type) =0; /// // Send a key event to the browser. @@ -372,7 +373,8 @@ class CefBrowserHost : public virtual CefBase { // relative to the upper-left corner of the view. /// /*--cef()--*/ - virtual void SendMouseClickEvent(int x, int y, MouseButtonType type, + virtual void SendMouseClickEvent(const CefMouseEvent& event, + MouseButtonType type, bool mouseUp, int clickCount) =0; /// @@ -380,15 +382,19 @@ class CefBrowserHost : public virtual CefBase { // relative to the upper-left corner of the view. /// /*--cef()--*/ - virtual void SendMouseMoveEvent(int x, int y, bool mouseLeave) =0; + virtual void SendMouseMoveEvent(const CefMouseEvent& event, + 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. The |deltaX| and |deltaY| // values represent the movement delta in the X and Y directions respectively. + // In order to scroll inside select popups with window rendering disabled + // CefRenderHandler::GetScreenPoint should be implemented properly. /// /*--cef()--*/ - virtual void SendMouseWheelEvent(int x, int y, int deltaX, int deltaY) =0; + virtual void SendMouseWheelEvent(const CefMouseEvent& event, + int deltaX, int deltaY) =0; /// // Send a focus event to the browser. diff --git a/include/cef_render_handler.h b/include/cef_render_handler.h index ca2bbbbd6..5064950cd 100644 --- a/include/cef_render_handler.h +++ b/include/cef_render_handler.h @@ -54,8 +54,7 @@ class CefRenderHandler : public virtual CefBase { /// // Called to retrieve the root window rectangle in screen coordinates. Return - // true if the rectangle was provided. Return false if the screen rectangle is - // the same as the view rectangle. + // true if the rectangle was provided. /// /*--cef()--*/ virtual bool GetRootScreenRect(CefRefPtr browser, @@ -82,7 +81,6 @@ class CefRenderHandler : public virtual CefBase { /// // Called when the browser wants to show or hide the popup widget. The popup // should be shown if |show| is true and hidden if |show| is false. - // NOTE: Popup widgets are not yet supported. /// /*--cef()--*/ virtual void OnPopupShow(CefRefPtr browser, @@ -91,7 +89,6 @@ class CefRenderHandler : public virtual CefBase { /// // Called when the browser wants to move or resize the popup widget. |rect| // contains the new location and size. - // NOTE: Popup widgets are not yet supported. /// /*--cef()--*/ virtual void OnPopupSize(CefRefPtr browser, @@ -103,7 +100,6 @@ class CefRenderHandler : public virtual CefBase { // for the whole image. |dirtyRects| contains the set of rectangles that need // to be repainted. On Windows |buffer| will be |width|*|height|*4 bytes // in size and represents a BGRA image with an upper-left origin. - // NOTE: Popup widgets are not yet supported. /// /*--cef()--*/ virtual void OnPaint(CefRefPtr browser, diff --git a/include/internal/cef_types.h b/include/internal/cef_types.h index af2cdea53..d6772fb5b 100644 --- a/include/internal/cef_types.h +++ b/include/internal/cef_types.h @@ -975,6 +975,27 @@ enum cef_mouse_button_type_t { MBT_RIGHT, }; +/// +// Structure representing mouse event information. +/// +typedef struct _cef_mouse_event_t { + /// + // X coordinate relative to the left side of the view. + /// + int x; + + /// + // Y coordinate relative to the top side of the view. + /// + int y; + + /// + // Bit flags describing any pressed modifier keys. See + // cef_event_flags_t for values. + /// + uint32 modifiers; +} cef_mouse_event_t; + /// // Paint element types. /// @@ -988,7 +1009,7 @@ enum cef_paint_element_type_t { /// enum cef_event_flags_t { EVENTFLAG_NONE = 0, - EVENTFLAG_CAPS_LOCK_DOWN = 1 << 0, + EVENTFLAG_CAPS_LOCK_ON = 1 << 0, EVENTFLAG_SHIFT_DOWN = 1 << 1, EVENTFLAG_CONTROL_DOWN = 1 << 2, EVENTFLAG_ALT_DOWN = 1 << 3, @@ -997,8 +1018,10 @@ enum cef_event_flags_t { EVENTFLAG_RIGHT_MOUSE_BUTTON = 1 << 6, // Mac OS-X command key. EVENTFLAG_COMMAND_DOWN = 1 << 7, - // Windows extended key (see WM_KEYDOWN doc). - EVENTFLAG_EXTENDED = 1 << 8, + EVENTFLAG_NUM_LOCK_ON = 1 << 8, + EVENTFLAG_IS_KEY_PAD = 1 << 9, + EVENTFLAG_IS_LEFT = 1 << 10, + EVENTFLAG_IS_RIGHT = 1 << 11, }; /// @@ -1119,17 +1142,6 @@ enum cef_key_event_type_t { KEYEVENT_CHAR }; -/// -// Key event modifiers. -/// -enum cef_key_event_modifiers_t { - KEY_SHIFT = 1 << 0, - KEY_CTRL = 1 << 1, - KEY_ALT = 1 << 2, - KEY_META = 1 << 3, - KEY_KEYPAD = 1 << 4, // Only used on Mac OS-X -}; - /// // Structure representing keyboard event information. /// @@ -1141,9 +1153,9 @@ typedef struct _cef_key_event_t { /// // Bit flags describing any pressed modifier keys. See - // cef_key_event_modifiers_t for values. + // cef_event_flags_t for values. /// - int modifiers; + uint32 modifiers; /// // The Windows key code for the key event. This value is used by the DOM diff --git a/include/internal/cef_types_win.h b/include/internal/cef_types_win.h index e81ee26fc..fbaaaaf59 100644 --- a/include/internal/cef_types_win.h +++ b/include/internal/cef_types_win.h @@ -76,6 +76,9 @@ typedef struct _cef_window_info_t { BOOL window_rendering_disabled; // Set to true to enable transparent painting. + // If window rendering is disabled and |transparent_painting| is set to true + // WebKit rendering will draw on a transparent background (RGBA=0x00000000). + // When this value is false the background will be white and opaque. BOOL transparent_painting; // Handle for the new browser window. diff --git a/include/internal/cef_types_wrappers.h b/include/internal/cef_types_wrappers.h index 051f3edc8..54e9dc917 100644 --- a/include/internal/cef_types_wrappers.h +++ b/include/internal/cef_types_wrappers.h @@ -199,6 +199,25 @@ struct CefKeyEventTraits { /// typedef CefStructBase CefKeyEvent; +struct CefMouseEventTraits { + typedef cef_mouse_event_t struct_type; + + static inline void init(struct_type* s) {} + + static inline void clear(struct_type* s) {} + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + target->x = src->x; + target->y = src->y; + target->modifiers = src->modifiers; + } +}; + +/// +// Class representing a mouse event. +/// +typedef CefStructBase CefMouseEvent; struct CefPopupFeaturesTraits { typedef cef_popup_features_t struct_type; diff --git a/libcef/browser/backing_store_osr.cc b/libcef/browser/backing_store_osr.cc index eeacca26a..5ff6b0ab4 100644 --- a/libcef/browser/backing_store_osr.cc +++ b/libcef/browser/backing_store_osr.cc @@ -4,22 +4,79 @@ #include "libcef/browser/backing_store_osr.h" +#include "content/public/browser/render_process_host.h" #include "ui/gfx/rect.h" +#include "ui/surface/transport_dib.h" BackingStoreOSR::BackingStoreOSR(content::RenderWidgetHost* widget, const gfx::Size& size) - : content::BackingStore(widget, size) { - bitmap_.Allocate(size.width(), size.height(), true); + : content::BackingStore(widget, size), + device_(SkBitmap::kARGB_8888_Config, size.width(), size.height(), true), + canvas_(&device_) { + canvas_.drawColor(SK_ColorWHITE); +} + +void BackingStoreOSR::PaintToBackingStore( + content::RenderProcessHost* process, + TransportDIB::Id bitmap, + const gfx::Rect& bitmap_rect, + const std::vector& copy_rects, + float scale_factor, + const base::Closure& completion_callback, + bool* scheduled_completion_callback) { + *scheduled_completion_callback = false; + TransportDIB* dib = process->GetTransportDIB(bitmap); + if (!dib) + return; + + SkBitmap src_bitmap; + src_bitmap.setConfig(SkBitmap::kARGB_8888_Config, + bitmap_rect.width(), + bitmap_rect.height()); + src_bitmap.setPixels(dib->memory()); + + SkPaint copy_paint; + copy_paint.setXfermodeMode(SkXfermode::kSrc_Mode); + + for (size_t i = 0; i < copy_rects.size(); i++) { + SkIRect src_rect = SkIRect::MakeXYWH(copy_rects[i].x() - bitmap_rect.x(), + copy_rects[i].y() - bitmap_rect.y(), + copy_rects[i].width(), + copy_rects[i].height()); + SkRect paint_rect = SkRect::MakeXYWH(copy_rects[i].x(), + copy_rects[i].y(), + copy_rects[i].width(), + copy_rects[i].height()); + canvas_.drawBitmapRect(src_bitmap, &src_rect, paint_rect, ©_paint); + } + src_bitmap.setPixels(0); +} + +bool BackingStoreOSR::CopyFromBackingStore(const gfx::Rect& rect, + skia::PlatformBitmap* output) { + if (!output->Allocate(rect.width(), rect.height(), true)) + return false; + + SkPaint copy_paint; + copy_paint.setXfermodeMode(SkXfermode::kSrc_Mode); + + SkCanvas canvas(output->GetBitmap()); + canvas.drawColor(SK_ColorWHITE); + canvas.drawBitmap(device_.accessBitmap(false), 0, 0, ©_paint); + return true; } void BackingStoreOSR::ScrollBackingStore(const gfx::Vector2d& delta, const gfx::Rect& clip_rect, const gfx::Size& view_size) { - SkIRect subset_rect = SkIRect::MakeXYWH(clip_rect.x(), clip_rect.y(), - clip_rect.width(), clip_rect.height()); - bitmap_.GetBitmap().scrollRect(&subset_rect, delta.x(), delta.y()); + SkIRect subset_rect = SkIRect::MakeXYWH(clip_rect.x(), + clip_rect.y(), + clip_rect.width(), + clip_rect.height()); + device_.accessBitmap(true).scrollRect(&subset_rect, delta.x(), delta.y()); } const void* BackingStoreOSR::getPixels() const { - return const_cast(this)->bitmap_.GetBitmap().getPixels(); + return const_cast(this)->device_. + accessBitmap(false).getPixels(); } diff --git a/libcef/browser/backing_store_osr.h b/libcef/browser/backing_store_osr.h index da81b4c8d..91446c27b 100644 --- a/libcef/browser/backing_store_osr.h +++ b/libcef/browser/backing_store_osr.h @@ -42,7 +42,8 @@ class BackingStoreOSR : public content::BackingStore { const gfx::Size& size); virtual ~BackingStoreOSR() {} - skia::PlatformBitmap bitmap_; + SkDevice device_; + SkCanvas canvas_; DISALLOW_COPY_AND_ASSIGN(BackingStoreOSR); }; diff --git a/libcef/browser/backing_store_osr_win.cc b/libcef/browser/backing_store_osr_win.cc deleted file mode 100644 index e54a39e8e..000000000 --- a/libcef/browser/backing_store_osr_win.cc +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2012 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 "libcef/browser/backing_store_osr.h" - -#include "content/public/browser/render_process_host.h" -#include "ui/gfx/gdi_util.h" -#include "ui/gfx/rect.h" -#include "ui/surface/transport_dib.h" - -// Portions extracted from content/browser/renderer_host/backing_store_win.cc. - -namespace { - -void CallStretchDIBits(HDC hdc, int dest_x, int dest_y, int dest_w, int dest_h, - int src_x, int src_y, int src_w, int src_h, void* pixels, - const BITMAPINFO* bitmap_info) { - // When blitting a rectangle that touches the bottom left corner of the bitmap - // StretchDIBits looks at it top-down! For more details, see - // http://wiki.allegro.cc/index.php?title=StretchDIBits. - int rv; - int bitmap_h = -bitmap_info->bmiHeader.biHeight; - int bottom_up_src_y = bitmap_h - src_y - src_h; - if (bottom_up_src_y == 0 && src_x == 0 && src_h != bitmap_h) { - rv = StretchDIBits(hdc, - dest_x, dest_h + dest_y - 1, dest_w, -dest_h, - src_x, bitmap_h - src_y + 1, src_w, -src_h, - pixels, bitmap_info, DIB_RGB_COLORS, SRCCOPY); - } else { - rv = StretchDIBits(hdc, - dest_x, dest_y, dest_w, dest_h, - src_x, bottom_up_src_y, src_w, src_h, - pixels, bitmap_info, DIB_RGB_COLORS, SRCCOPY); - } - DCHECK(rv != GDI_ERROR); -} - -} // namespace - -void BackingStoreOSR::PaintToBackingStore( - content::RenderProcessHost* process, - TransportDIB::Id bitmap, - const gfx::Rect& bitmap_rect, - const std::vector& copy_rects, - float scale_factor, - const base::Closure& completion_callback, - bool* scheduled_completion_callback) { - *scheduled_completion_callback = false; - TransportDIB* dib = process->GetTransportDIB(bitmap); - if (!dib) - return; - - BITMAPINFOHEADER hdr; - gfx::CreateBitmapHeader(bitmap_rect.width(), bitmap_rect.height(), &hdr); - - // Account for a bitmap_rect that exceeds the bounds of our view. - gfx::Rect view_rect(size()); - HDC temp_dc = bitmap_.GetSurface(); - for (size_t i = 0; i < copy_rects.size(); i++) { - gfx::Rect paint_rect(copy_rects[i]); - paint_rect.Intersect(view_rect); - CallStretchDIBits(temp_dc, - paint_rect.x(), - paint_rect.y(), - paint_rect.width(), - paint_rect.height(), - paint_rect.x() - bitmap_rect.x(), - paint_rect.y() - bitmap_rect.y(), - paint_rect.width(), - paint_rect.height(), - dib->memory(), - reinterpret_cast(&hdr)); - } -} - -bool BackingStoreOSR::CopyFromBackingStore(const gfx::Rect& rect, - skia::PlatformBitmap* output) { - if (!output->Allocate(rect.width(), rect.height(), true)) - return false; - - HDC src_dc = bitmap_.GetSurface(); - HDC dst_dc = output->GetSurface(); - return BitBlt(dst_dc, 0, 0, rect.width(), rect.height(), - src_dc, rect.x(), rect.y(), SRCCOPY) ? true : false; -} diff --git a/libcef/browser/browser_host_impl.cc b/libcef/browser/browser_host_impl.cc index 52153527f..4616b7db6 100644 --- a/libcef/browser/browser_host_impl.cc +++ b/libcef/browser/browser_host_impl.cc @@ -91,15 +91,15 @@ bool GetCefKeyEvent(const content::NativeWebKeyboardEvent& event, cef_event.modifiers = 0; if (event.modifiers & WebKit::WebKeyboardEvent::ShiftKey) - cef_event.modifiers |= KEY_SHIFT; + cef_event.modifiers |= EVENTFLAG_SHIFT_DOWN; if (event.modifiers & WebKit::WebKeyboardEvent::ControlKey) - cef_event.modifiers |= KEY_CTRL; + cef_event.modifiers |= EVENTFLAG_CONTROL_DOWN; if (event.modifiers & WebKit::WebKeyboardEvent::AltKey) - cef_event.modifiers |= KEY_ALT; + cef_event.modifiers |= EVENTFLAG_ALT_DOWN; if (event.modifiers & WebKit::WebKeyboardEvent::MetaKey) - cef_event.modifiers |= KEY_META; + cef_event.modifiers |= EVENTFLAG_COMMAND_DOWN; if (event.modifiers & WebKit::WebKeyboardEvent::IsKeyPad) - cef_event.modifiers |= KEY_KEYPAD; + cef_event.modifiers |= EVENTFLAG_IS_KEY_PAD; cef_event.windows_key_code = event.windowsKeyCode; cef_event.native_key_code = event.nativeKeyCode; @@ -136,7 +136,6 @@ class CefFileDialogCallbackImpl : public CefFileDialogCallback { std::vector::const_iterator it = file_paths.begin(); for (; it != file_paths.end(); ++it) vec.push_back(FilePath(*it)); - } callback_.Run(vec); callback_.Reset(); @@ -226,16 +225,24 @@ bool CefBrowserHost::CreateBrowser(const CefWindowInfo& windowInfo, return false; } + CefBrowserSettings new_settings = settings; + // Verify that render handler is in place for a windowless browser. - if (CefBrowserHostImpl::IsWindowRenderingDisabled(windowInfo) && - !client->GetRenderHandler().get()) { - NOTREACHED() << "CefRenderHandler implementation is required"; - return false; + if (CefBrowserHostImpl::IsWindowRenderingDisabled(windowInfo)) { + if (!client->GetRenderHandler().get()) { + NOTREACHED() << "CefRenderHandler implementation is required"; + return false; + } + if (!new_settings.accelerated_compositing_disabled) { + // Accelerated compositing is not supported when window rendering is + // disabled. + new_settings.accelerated_compositing_disabled = true; + } } // Create the browser on the UI thread. CreateBrowserHelper* helper = - new CreateBrowserHelper(windowInfo, client, url, settings); + new CreateBrowserHelper(windowInfo, client, url, new_settings); CEF_POST_TASK(CEF_UIT, base::Bind(CreateBrowserWithHelper, helper)); return true; @@ -265,10 +272,19 @@ CefRefPtr CefBrowserHost::CreateBrowserSync( return NULL; } - if (CefBrowserHostImpl::IsWindowRenderingDisabled(windowInfo) && - !client->GetRenderHandler().get()) { - NOTREACHED() << "CefRenderHandler implementation is required"; - return NULL; + CefBrowserSettings new_settings = settings; + + // Verify that render handler is in place for a windowless browser. + if (CefBrowserHostImpl::IsWindowRenderingDisabled(windowInfo)) { + if (!client->GetRenderHandler().get()) { + NOTREACHED() << "CefRenderHandler implementation is required"; + return NULL; + } + if (!new_settings.accelerated_compositing_disabled) { + // Accelerated compositing is not supported when window rendering is + // disabled. + new_settings.accelerated_compositing_disabled = true; + } } _Context->browser_context()->set_use_osr_next_contents_view( @@ -278,7 +294,7 @@ CefRefPtr CefBrowserHost::CreateBrowserSync( CefContentBrowserClient::Get()->CreateBrowserInfo(); DCHECK(!info->is_popup()); CefRefPtr browser = - CefBrowserHostImpl::Create(windowInfo, settings, client, NULL, info, + CefBrowserHostImpl::Create(windowInfo, new_settings, client, NULL, info, NULL); if (!url.empty()) browser->LoadURL(CefFrameHostImpl::kMainFrameId, url); @@ -550,7 +566,7 @@ void CefBrowserHostImpl::WasResized() { NOTREACHED() << "Window rendering is not disabled"; return; } - + if (!CEF_CURRENTLY_ON_UIT()) { CEF_POST_TASK(CEF_UIT, base::Bind(&CefBrowserHostImpl::WasResized, this)); return; @@ -564,7 +580,8 @@ void CefBrowserHostImpl::WasResized() { widget->WasResized(); } -void CefBrowserHostImpl::Invalidate(const CefRect& dirtyRect) { +void CefBrowserHostImpl::Invalidate(const CefRect& dirtyRect, + PaintElementType type) { if (!IsWindowRenderingDisabled()) { NOTREACHED() << "Window rendering is not disabled"; return; @@ -572,7 +589,7 @@ void CefBrowserHostImpl::Invalidate(const CefRect& dirtyRect) { if (!CEF_CURRENTLY_ON_UIT()) { CEF_POST_TASK(CEF_UIT, - base::Bind(&CefBrowserHostImpl::Invalidate, this, dirtyRect)); + base::Bind(&CefBrowserHostImpl::Invalidate, this, dirtyRect, type)); return; } @@ -588,7 +605,7 @@ void CefBrowserHostImpl::Invalidate(const CefRect& dirtyRect) { if (orview) { gfx::Rect rect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height); - orview->Invalidate(rect); + orview->Invalidate(rect, type); } #else // TODO(port): Implement this method to work on other platforms as part of @@ -604,74 +621,148 @@ void CefBrowserHostImpl::SendKeyEvent(const CefKeyEvent& event) { return; } - if (!web_contents()) - return; + content::NativeWebKeyboardEvent web_event; + PlatformTranslateKeyEvent(web_event, event); - content::RenderWidgetHost* widget = web_contents()->GetRenderViewHost(); - if (!widget) - return; - gfx::NativeEvent native_event; - if (PlatformTranslateKeyEvent(native_event, event)) - widget->ForwardKeyboardEvent(content::NativeWebKeyboardEvent(native_event)); + if (!IsWindowRenderingDisabled()) { + content::RenderWidgetHost* widget = web_contents()->GetRenderViewHost(); + if (widget) + widget->ForwardKeyboardEvent(web_event); + } else { +#if defined(OS_WIN) + if (!web_contents()) + return; + content::RenderWidgetHostView* view = + web_contents()->GetRenderViewHost()->GetView(); + CefRenderWidgetHostViewOSR* orview = + static_cast(view); + if (orview) + orview->SendKeyEvent(web_event); +#else + // TODO(port): Implement this method to work on other platforms as part of + // off-screen rendering support. + NOTREACHED(); +#endif + } } -void CefBrowserHostImpl::SendMouseClickEvent(int x, int y, +void CefBrowserHostImpl::SendMouseClickEvent(const CefMouseEvent& event, MouseButtonType type, bool mouseUp, int clickCount) { if (!CEF_CURRENTLY_ON_UIT()) { CEF_POST_TASK(CEF_UIT, - base::Bind(&CefBrowserHostImpl::SendMouseClickEvent, this, x, y, type, + base::Bind(&CefBrowserHostImpl::SendMouseClickEvent, this, event, type, mouseUp, clickCount)); return; } - if (!web_contents()) - return; + WebKit::WebMouseEvent web_event; + PlatformTranslateClickEvent(web_event, event, type, mouseUp, clickCount); - content::RenderWidgetHost* widget = web_contents()->GetRenderViewHost(); - if (!widget) - return; - WebKit::WebMouseEvent event; - if (PlatformTranslateClickEvent(event, x, y, type, mouseUp, clickCount)) - widget->ForwardMouseEvent(event); + SendMouseEvent(web_event); } -void CefBrowserHostImpl::SendMouseMoveEvent(int x, int y, bool mouseLeave) { +void CefBrowserHostImpl::SendMouseMoveEvent(const CefMouseEvent& event, + bool mouseLeave) { if (!CEF_CURRENTLY_ON_UIT()) { CEF_POST_TASK(CEF_UIT, - base::Bind(&CefBrowserHostImpl::SendMouseMoveEvent, this, x, y, + base::Bind(&CefBrowserHostImpl::SendMouseMoveEvent, this, event, mouseLeave)); return; } - if (!web_contents()) - return; + WebKit::WebMouseEvent web_event; + PlatformTranslateMoveEvent(web_event, event, mouseLeave); - content::RenderWidgetHost* widget = web_contents()->GetRenderViewHost(); - if (!widget) - return; - WebKit::WebMouseEvent event; - if (PlatformTranslateMoveEvent(event, x, y, mouseLeave)) - widget->ForwardMouseEvent(event); + SendMouseEvent(web_event); } -void CefBrowserHostImpl::SendMouseWheelEvent(int x, int y, +void CefBrowserHostImpl::SendMouseWheelEvent(const CefMouseEvent& event, int deltaX, int deltaY) { if (!CEF_CURRENTLY_ON_UIT()) { CEF_POST_TASK(CEF_UIT, - base::Bind(&CefBrowserHostImpl::SendMouseWheelEvent, this, x, y, + base::Bind(&CefBrowserHostImpl::SendMouseWheelEvent, this, event, deltaX, deltaY)); return; } - if (!web_contents()) - return; + WebKit::WebMouseWheelEvent web_event; + PlatformTranslateWheelEvent(web_event, event, deltaX, deltaY); - content::RenderWidgetHost* widget = web_contents()->GetRenderViewHost(); - if (!widget) - return; - WebKit::WebMouseWheelEvent event; - if (PlatformTranslateWheelEvent(event, x, y, deltaX, deltaY)) - widget->ForwardWheelEvent(event); + if (!IsWindowRenderingDisabled()) { + content::RenderWidgetHost* widget = web_contents()->GetRenderViewHost(); + if (widget) + widget->ForwardWheelEvent(web_event); + } else { +#if defined(OS_WIN) + if (!web_contents()) + return; + content::RenderWidgetHostView* view = + web_contents()->GetRenderViewHost()->GetView(); + CefRenderWidgetHostViewOSR* orview = + static_cast(view); + + if (orview) + orview->SendMouseWheelEvent(web_event); +#else + // TODO(port): Implement this method to work on other platforms as part of + // off-screen rendering support. + NOTREACHED(); +#endif + } +} + +int CefBrowserHostImpl::TranslateModifiers(uint32 cef_modifiers) { + int webkit_modifiers = 0; + // Set modifiers based on key state. + if (cef_modifiers & EVENTFLAG_SHIFT_DOWN) + webkit_modifiers |= WebKit::WebInputEvent::ShiftKey; + if (cef_modifiers & EVENTFLAG_CONTROL_DOWN) + webkit_modifiers |= WebKit::WebInputEvent::ControlKey; + if (cef_modifiers & EVENTFLAG_ALT_DOWN) + webkit_modifiers |= WebKit::WebInputEvent::AltKey; + if (cef_modifiers & EVENTFLAG_COMMAND_DOWN) + webkit_modifiers |= WebKit::WebInputEvent::MetaKey; + if (cef_modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON) + webkit_modifiers |= WebKit::WebInputEvent::LeftButtonDown; + if (cef_modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON) + webkit_modifiers |= WebKit::WebInputEvent::MiddleButtonDown; + if (cef_modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON) + webkit_modifiers |= WebKit::WebInputEvent::RightButtonDown; + if (cef_modifiers & EVENTFLAG_CAPS_LOCK_ON) + webkit_modifiers |= WebKit::WebInputEvent::CapsLockOn; + if (cef_modifiers & EVENTFLAG_NUM_LOCK_ON) + webkit_modifiers |= WebKit::WebInputEvent::NumLockOn; + if (cef_modifiers & EVENTFLAG_IS_LEFT) + webkit_modifiers |= WebKit::WebInputEvent::IsLeft; + if (cef_modifiers & EVENTFLAG_IS_RIGHT) + webkit_modifiers |= WebKit::WebInputEvent::IsRight; + if (cef_modifiers & EVENTFLAG_IS_KEY_PAD) + webkit_modifiers |= WebKit::WebInputEvent::IsKeyPad; + return webkit_modifiers; +} + +void CefBrowserHostImpl::SendMouseEvent(const WebKit::WebMouseEvent& event) { + if (!IsWindowRenderingDisabled()) { + content::RenderWidgetHost* widget = web_contents()->GetRenderViewHost(); + if (widget) + widget->ForwardMouseEvent(event); + } else { +#if defined(OS_WIN) + if (!web_contents()) + return; + content::RenderWidgetHostView* view = + web_contents()->GetRenderViewHost()->GetView(); + CefRenderWidgetHostViewOSR* orview = + static_cast(view); + + if (orview) + orview->SendMouseEvent(event); +#else + // TODO(port): Implement this method to work on other platforms as part of + // off-screen rendering support. + NOTREACHED(); +#endif + } } void CefBrowserHostImpl::SendFocusEvent(bool setFocus) { @@ -1440,10 +1531,16 @@ bool CefBrowserHostImpl::ShouldCreateWebContents( } } - if (IsWindowRenderingDisabled(pending_window_info_) && - !pending_client_->GetRenderHandler().get()) { - NOTREACHED() << "CefRenderHandler implementation is required"; - return false; + if (IsWindowRenderingDisabled(pending_window_info_)) { + if (!pending_client_->GetRenderHandler().get()) { + NOTREACHED() << "CefRenderHandler implementation is required"; + return false; + } + if (!pending_settings_.accelerated_compositing_disabled) { + // Accelerated compositing is not supported when window rendering is + // disabled. + pending_settings_.accelerated_compositing_disabled = true; + } } _Context->browser_context()->set_use_osr_next_contents_view( diff --git a/libcef/browser/browser_host_impl.h b/libcef/browser/browser_host_impl.h index feeb100c7..48d9f0761 100644 --- a/libcef/browser/browser_host_impl.h +++ b/libcef/browser/browser_host_impl.h @@ -35,8 +35,9 @@ struct NativeWebKeyboardEvent; } namespace WebKit { - class WebMouseEvent; - class WebMouseWheelEvent; +class WebMouseEvent; +class WebMouseWheelEvent; +class WebInputEvent; } namespace net { @@ -125,12 +126,15 @@ class CefBrowserHostImpl : public CefBrowserHost, CefRefPtr callback) OVERRIDE; virtual bool IsWindowRenderingDisabled() OVERRIDE; virtual void WasResized() OVERRIDE; - virtual void Invalidate(const CefRect& dirtyRect) OVERRIDE; + virtual void Invalidate(const CefRect& dirtyRect, + PaintElementType type) OVERRIDE; virtual void SendKeyEvent(const CefKeyEvent& event) OVERRIDE; - virtual void SendMouseClickEvent(int x, int y, MouseButtonType type, + virtual void SendMouseClickEvent(const CefMouseEvent& event, + MouseButtonType type, bool mouseUp, int clickCount) OVERRIDE; - virtual void SendMouseMoveEvent(int x, int y, bool mouseLeave) OVERRIDE; - virtual void SendMouseWheelEvent(int x, int y, + virtual void SendMouseMoveEvent(const CefMouseEvent& event, + bool mouseLeave) OVERRIDE; + virtual void SendMouseWheelEvent(const CefMouseEvent& event, int deltaX, int deltaY) OVERRIDE; virtual void SendFocusEvent(bool setFocus) OVERRIDE; virtual void SendCaptureLostEvent() OVERRIDE; @@ -221,6 +225,8 @@ class CefBrowserHostImpl : public CefBrowserHost, // Returns the URL that is currently loading (or loaded) in the main frame. GURL GetLoadingURL(); + bool IsTransparent(); + #if defined(OS_WIN) static void RegisterWindowClass(); #endif @@ -385,16 +391,22 @@ class CefBrowserHostImpl : public CefBrowserHost, void PlatformRunFileChooser(const content::FileChooserParams& params, RunFileChooserCallback callback); - static bool PlatformTranslateKeyEvent(gfx::NativeEvent& native_event, - const CefKeyEvent& key_event); - static bool PlatformTranslateClickEvent(WebKit::WebMouseEvent& ev, - int x, int y, MouseButtonType type, - bool mouseUp, int clickCount); - static bool PlatformTranslateMoveEvent(WebKit::WebMouseEvent& ev, - int x, int y, bool mouseLeave); - static bool PlatformTranslateWheelEvent(WebKit::WebMouseWheelEvent& ev, - int x, int y, - int deltaX, int deltaY); + void PlatformTranslateKeyEvent(content::NativeWebKeyboardEvent& native_event, + const CefKeyEvent& key_event); + void PlatformTranslateClickEvent(WebKit::WebMouseEvent& web_event, + const CefMouseEvent& mouse_event, + CefBrowserHost::MouseButtonType type, + bool mouseUp, int clickCount); + void PlatformTranslateMoveEvent(WebKit::WebMouseEvent& web_event, + const CefMouseEvent& mouse_event, + bool mouseLeave); + void PlatformTranslateWheelEvent(WebKit::WebMouseWheelEvent& web_event, + const CefMouseEvent& mouse_event, + int deltaX, int deltaY); + void PlatformTranslateMouseEvent(WebKit::WebMouseEvent& web_event, + const CefMouseEvent& mouse_event); + int TranslateModifiers(uint32 cefKeyStates); + void SendMouseEvent(const WebKit::WebMouseEvent& web_event); void OnAddressChange(CefRefPtr frame, const GURL& url); diff --git a/libcef/browser/browser_host_impl_gtk.cc b/libcef/browser/browser_host_impl_gtk.cc index eb9dda83a..677f03271 100644 --- a/libcef/browser/browser_host_impl_gtk.cc +++ b/libcef/browser/browser_host_impl_gtk.cc @@ -334,44 +334,51 @@ void CefBrowserHostImpl::PlatformRunFileChooser( void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) { } -//static +// static bool CefBrowserHostImpl::IsWindowRenderingDisabled(const CefWindowInfo& info) { // TODO(port): Implement this method as part of off-screen rendering support. return false; } -// static -bool CefBrowserHostImpl::PlatformTranslateKeyEvent( - gfx::NativeEvent& native_event, const CefKeyEvent& event) { +bool CefBrowserHostImpl::IsTransparent() { + return false; +} + +void CefBrowserHostImpl::PlatformTranslateKeyEvent( + content::NativeWebKeyboardEvent& native_event, + const CefKeyEvent& event) { // TODO(port): Implement this method as part of off-screen rendering support. NOTIMPLEMENTED(); - return false; } -// static -bool CefBrowserHostImpl::PlatformTranslateClickEvent( - WebKit::WebMouseEvent& ev, - int x, int y, MouseButtonType type, - bool mouseUp, int clickCount) { - // TODO(port): Implement this method as part of off-screen rendering support. - NOTIMPLEMENTED(); - return false; -} - -// static -bool CefBrowserHostImpl::PlatformTranslateMoveEvent( +void CefBrowserHostImpl::PlatformTranslateClickEvent( WebKit::WebMouseEvent& ev, - int x, int y, bool mouseLeave) { + const CefMouseEvent& mouse_event, + MouseButtonType type, + bool mouseUp, int clickCount) { // TODO(port): Implement this method as part of off-screen rendering support. NOTIMPLEMENTED(); - return false; } -// static -bool CefBrowserHostImpl::PlatformTranslateWheelEvent( - WebKit::WebMouseWheelEvent& ev, - int x, int y, int deltaX, int deltaY) { +void CefBrowserHostImpl::PlatformTranslateMoveEvent( + WebKit::WebMouseEvent& ev, + const CefMouseEvent& mouse_event, + bool mouseLeave) { + // TODO(port): Implement this method as part of off-screen rendering support. + NOTIMPLEMENTED(); +} + +void CefBrowserHostImpl::PlatformTranslateWheelEvent( + WebKit::WebMouseWheelEvent& ev, + const CefMouseEvent& mouse_event, + int deltaX, int deltaY) { + // TODO(port): Implement this method as part of off-screen rendering support. + NOTIMPLEMENTED(); +} + +void CefBrowserHostImpl::PlatformTranslateMouseEvent( + WebKit::WebMouseEvent& ev, + const CefMouseEvent& mouse_event) { // TODO(port): Implement this method as part of off-screen rendering support. NOTIMPLEMENTED(); - return false; } diff --git a/libcef/browser/browser_host_impl_mac.mm b/libcef/browser/browser_host_impl_mac.mm index bfac2da3c..7dbca7178 100644 --- a/libcef/browser/browser_host_impl_mac.mm +++ b/libcef/browser/browser_host_impl_mac.mm @@ -319,44 +319,51 @@ void CefBrowserHostImpl::PlatformRunFileChooser( void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) { } -//static +// static bool CefBrowserHostImpl::IsWindowRenderingDisabled(const CefWindowInfo& info) { // TODO(port): Implement this method as part of off-screen rendering support. return false; } -// static -bool CefBrowserHostImpl::PlatformTranslateKeyEvent( - gfx::NativeEvent& native_event, const CefKeyEvent& event) { +bool CefBrowserHostImpl::IsTransparent() { + return false; +} + +void CefBrowserHostImpl::PlatformTranslateKeyEvent( + content::NativeWebKeyboardEvent& native_event, + const CefKeyEvent& event) { // TODO(port): Implement this method as part of off-screen rendering support. NOTIMPLEMENTED(); - return false; } -// static -bool CefBrowserHostImpl::PlatformTranslateClickEvent( - WebKit::WebMouseEvent& ev, - int x, int y, MouseButtonType type, - bool mouseUp, int clickCount) { - // TODO(port): Implement this method as part of off-screen rendering support. - NOTIMPLEMENTED(); - return false; -} - -// static -bool CefBrowserHostImpl::PlatformTranslateMoveEvent( +void CefBrowserHostImpl::PlatformTranslateClickEvent( WebKit::WebMouseEvent& ev, - int x, int y, bool mouseLeave) { - // TODO(port): Implement this method as part of off-screen rendering support. + const CefMouseEvent& mouse_event, + MouseButtonType type, + bool mouseUp, int clickCount) { + // TODO(port): Implement this method as part of off-screen rendering support. NOTIMPLEMENTED(); - return false; } -// static -bool CefBrowserHostImpl::PlatformTranslateWheelEvent( - WebKit::WebMouseWheelEvent& ev, - int x, int y, int deltaX, int deltaY) { - // TODO(port): Implement this method as part of off-screen rendering support. +void CefBrowserHostImpl::PlatformTranslateMoveEvent( + WebKit::WebMouseEvent& ev, + const CefMouseEvent& mouse_event, + bool mouseLeave) { + // TODO(port): Implement this method as part of off-screen rendering support. + NOTIMPLEMENTED(); +} + +void CefBrowserHostImpl::PlatformTranslateWheelEvent( + WebKit::WebMouseWheelEvent& ev, + const CefMouseEvent& mouse_event, + int deltaX, int deltaY) { + // TODO(port): Implement this method as part of off-screen rendering support. + NOTIMPLEMENTED(); +} + +void CefBrowserHostImpl::PlatformTranslateMouseEvent( + WebKit::WebMouseEvent& ev, + const CefMouseEvent& mouse_event) { + // TODO(port): Implement this method as part of off-screen rendering support. NOTIMPLEMENTED(); - return false; } diff --git a/libcef/browser/browser_host_impl_win.cc b/libcef/browser/browser_host_impl_win.cc index a4cc09ca4..458b34bea 100644 --- a/libcef/browser/browser_host_impl_win.cc +++ b/libcef/browser/browser_host_impl_win.cc @@ -687,97 +687,168 @@ bool CefBrowserHostImpl::IsWindowRenderingDisabled(const CefWindowInfo& info) { return info.window_rendering_disabled ? true : false; } -// static -bool CefBrowserHostImpl::PlatformTranslateKeyEvent( - gfx::NativeEvent& native_event, const CefKeyEvent& key_event) { - UINT message = 0; - WPARAM wparam = key_event.windows_key_code; - LPARAM lparam = key_event.native_key_code; +bool CefBrowserHostImpl::IsTransparent() { + return window_info_.transparent_painting != 0; +} +void CefBrowserHostImpl::PlatformTranslateKeyEvent( + content::NativeWebKeyboardEvent& result, const CefKeyEvent& key_event) { + result.timeStampSeconds = GetMessageTime() / 1000.0; + + result.windowsKeyCode = key_event.windows_key_code; + result.nativeKeyCode = key_event.native_key_code; + result.isSystemKey = key_event.is_system_key; switch (key_event.type) { - case KEYEVENT_KEYUP: - message = key_event.is_system_key ? WM_SYSKEYUP : WM_KEYUP; - break; - case KEYEVENT_RAWKEYDOWN: - case KEYEVENT_KEYDOWN: - message = key_event.is_system_key ? WM_SYSKEYDOWN : WM_KEYDOWN; - break; - case KEYEVENT_CHAR: - message = key_event.is_system_key ? WM_SYSCHAR : WM_CHAR; - break; - default: - return false; - } - - gfx::NativeEvent ev = {NULL, message, wparam, lparam}; - native_event = ev; - return true; -} - -// static -bool CefBrowserHostImpl::PlatformTranslateClickEvent( - WebKit::WebMouseEvent& ev, - int x, int y, MouseButtonType type, - bool mouseUp, int clickCount) { - DCHECK(clickCount >=1 && clickCount <= 2); - - UINT message = 0; - WPARAM wparam = KeyStatesToWord(); - 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) { + case KEYEVENT_RAWKEYDOWN: + case KEYEVENT_KEYDOWN: + result.type = WebKit::WebInputEvent::RawKeyDown; + break; + case KEYEVENT_KEYUP: + result.type = WebKit::WebInputEvent::KeyUp; + break; + case KEYEVENT_CHAR: + result.type = WebKit::WebInputEvent::Char; + break; + default: NOTREACHED(); - return false; } - ev = WebKit::WebInputEventFactory::mouseEvent(NULL, message, wparam, lparam); - return true; + if (result.type == WebKit::WebInputEvent::Char || + result.type == WebKit::WebInputEvent::RawKeyDown) { + result.text[0] = result.windowsKeyCode; + result.unmodifiedText[0] = result.windowsKeyCode; + } + if (result.type != WebKit::WebInputEvent::Char) + result.setKeyIdentifierFromWindowsKeyCode(); + + result.modifiers |= TranslateModifiers(key_event.modifiers); } -// static -bool CefBrowserHostImpl::PlatformTranslateMoveEvent( - WebKit::WebMouseEvent& ev, - int x, int y, bool mouseLeave) { - UINT message; - WPARAM wparam = KeyStatesToWord(); - LPARAM lparam = 0; +void CefBrowserHostImpl::PlatformTranslateClickEvent( + WebKit::WebMouseEvent& result, + const CefMouseEvent& mouse_event, + CefBrowserHost::MouseButtonType type, + bool mouseUp, int clickCount) { + PlatformTranslateMouseEvent(result, mouse_event); - if (mouseLeave) { - message = WM_MOUSELEAVE; + switch (type) { + case MBT_LEFT: + result.type = mouseUp ? WebKit::WebInputEvent::MouseUp : + WebKit::WebInputEvent::MouseDown; + result.button = WebKit::WebMouseEvent::ButtonLeft; + break; + case MBT_MIDDLE: + result.type = mouseUp ? WebKit::WebInputEvent::MouseUp : + WebKit::WebInputEvent::MouseDown; + result.button = WebKit::WebMouseEvent::ButtonMiddle; + break; + case MBT_RIGHT: + result.type = mouseUp ? WebKit::WebInputEvent::MouseUp : + WebKit::WebInputEvent::MouseDown; + result.button = WebKit::WebMouseEvent::ButtonRight; + break; + default: + NOTREACHED(); + } + + result.clickCount = clickCount; +} + +void CefBrowserHostImpl::PlatformTranslateMoveEvent( + WebKit::WebMouseEvent& result, + const CefMouseEvent& mouse_event, + bool mouseLeave) { + PlatformTranslateMouseEvent(result, mouse_event); + + if (!mouseLeave) { + result.type = WebKit::WebInputEvent::MouseMove; + if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON) + result.button = WebKit::WebMouseEvent::ButtonLeft; + else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON) + result.button = WebKit::WebMouseEvent::ButtonMiddle; + else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON) + result.button = WebKit::WebMouseEvent::ButtonRight; + else + result.button = WebKit::WebMouseEvent::ButtonNone; } else { - message = WM_MOUSEMOVE; - lparam = MAKELPARAM(x, y); + result.type = WebKit::WebInputEvent::MouseLeave; + result.button = WebKit::WebMouseEvent::ButtonNone; } - ev = WebKit::WebInputEventFactory::mouseEvent(NULL, message, wparam, lparam); - return true; + result.clickCount = 0; } -// static -bool CefBrowserHostImpl::PlatformTranslateWheelEvent( - WebKit::WebMouseWheelEvent& ev, - int x, int y, int deltaX, int deltaY) { - WPARAM wparam = MAKEWPARAM(KeyStatesToWord(), deltaY); - LPARAM lparam = MAKELPARAM(x, y); +void CefBrowserHostImpl::PlatformTranslateWheelEvent( + WebKit::WebMouseWheelEvent& result, + const CefMouseEvent& mouse_event, + int deltaX, int deltaY) { + PlatformTranslateMouseEvent(result, mouse_event); - ev = WebKit::WebInputEventFactory::mouseWheelEvent(NULL, WM_MOUSEWHEEL, - wparam, lparam); - return true; + result.type = WebKit::WebInputEvent::MouseWheel; + result.button = WebKit::WebMouseEvent::ButtonNone; + + float wheelDelta; + bool horizontalScroll = false; + + wheelDelta = static_cast(deltaY ? deltaY : deltaX); + + horizontalScroll = (deltaY == 0); + + static const ULONG defaultScrollCharsPerWheelDelta = 1; + static const FLOAT scrollbarPixelsPerLine = 100.0f / 3.0f; + static const ULONG defaultScrollLinesPerWheelDelta = 3; + wheelDelta /= WHEEL_DELTA; + float scrollDelta = wheelDelta; + if (horizontalScroll) { + ULONG scrollChars = defaultScrollCharsPerWheelDelta; + SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &scrollChars, 0); + scrollDelta *= static_cast(scrollChars) * scrollbarPixelsPerLine; + } else { + ULONG scrollLines = defaultScrollLinesPerWheelDelta; + SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scrollLines, 0); + if (scrollLines == WHEEL_PAGESCROLL) + result.scrollByPage = true; + if (!result.scrollByPage) + scrollDelta *= static_cast(scrollLines) * scrollbarPixelsPerLine; + } + + // Set scroll amount based on above calculations. WebKit expects positive + // deltaY to mean "scroll up" and positive deltaX to mean "scroll left". + if (horizontalScroll) { + result.deltaX = scrollDelta; + result.wheelTicksX = wheelDelta; + } else { + result.deltaY = scrollDelta; + result.wheelTicksY = wheelDelta; + } +} + +void CefBrowserHostImpl::PlatformTranslateMouseEvent( + WebKit::WebMouseEvent& result, + const CefMouseEvent& mouse_event) { + // position + result.x = mouse_event.x; + result.y = mouse_event.y; + result.windowX = result.x; + result.windowY = result.y; + result.globalX = result.x; + result.globalY = result.y; + + // global position + if (IsWindowRenderingDisabled()) { + GetClient()->GetRenderHandler()->GetScreenPoint(GetBrowser(), + result.x, result.y, + result.globalX, result.globalY); + } else { + POINT globalPoint = { result.x, result.y }; + ClientToScreen(GetWindowHandle(), &globalPoint); + result.globalX = globalPoint.x; + result.globalY = globalPoint.y; + } + + // modifiers + result.modifiers |= TranslateModifiers(mouse_event.modifiers); + + // timestamp + result.timeStampSeconds = GetMessageTime() / 1000.0; } diff --git a/libcef/browser/render_widget_host_view_osr.cc b/libcef/browser/render_widget_host_view_osr.cc index 851116aac..5734460d0 100644 --- a/libcef/browser/render_widget_host_view_osr.cc +++ b/libcef/browser/render_widget_host_view_osr.cc @@ -7,6 +7,7 @@ #include "libcef/browser/browser_host_impl.h" #include "libcef/browser/render_widget_host_view_osr.h" +#include "base/message_loop.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/render_view_host.h" @@ -20,13 +21,18 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR( content::RenderWidgetHost* widget) : render_widget_host_(content::RenderWidgetHostImpl::From(widget)), - about_to_validate_and_paint_(false) { + about_to_validate_and_paint_(false), + parent_host_view_(NULL), + popup_host_view_(NULL), + weak_factory_(this) { DCHECK(render_widget_host_); render_widget_host_->SetView(this); // CefBrowserHostImpl might not be created at this time for popups. - browser_impl_ = CefBrowserHostImpl::GetBrowserForHost( - content::RenderViewHost::From(render_widget_host_)); + if (render_widget_host_->IsRenderView()) { + browser_impl_ = CefBrowserHostImpl::GetBrowserForHost( + content::RenderViewHost::From(render_widget_host_)); + } } CefRenderWidgetHostViewOSR::~CefRenderWidgetHostViewOSR() { @@ -49,7 +55,7 @@ void CefRenderWidgetHostViewOSR::SetBounds(const gfx::Rect& rect) { } gfx::NativeView CefRenderWidgetHostViewOSR::GetNativeView() const { - return gfx::NativeView(); + return browser_impl_.get() ? browser_impl_->GetWindowHandle() : NULL; } gfx::NativeViewId CefRenderWidgetHostViewOSR::GetNativeViewId() const { @@ -81,12 +87,14 @@ void CefRenderWidgetHostViewOSR::Hide() { WasHidden(); } - bool CefRenderWidgetHostViewOSR::IsShowing() { return true; } gfx::Rect CefRenderWidgetHostViewOSR::GetViewBounds() const { + if (IsPopupWidget()) + return popup_position_; + if (!browser_impl_.get()) return gfx::Rect(); CefRect rc; @@ -99,10 +107,24 @@ gfx::Rect CefRenderWidgetHostViewOSR::GetViewBounds() const { void CefRenderWidgetHostViewOSR::InitAsPopup( RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) { + parent_host_view_ = static_cast( + parent_host_view); + browser_impl_ = parent_host_view_->get_browser_impl(); + if (!browser_impl_.get()) + return; + + parent_host_view_->CancelWidget(); + + parent_host_view_->set_popup_host_view(this); + NotifyShowWidget(); + + popup_position_ = pos; + NotifySizeWidget(); } void CefRenderWidgetHostViewOSR::InitAsFullscreen( - RenderWidgetHostView* reference_host_view) { + RenderWidgetHostView* reference_host_view) { + NOTREACHED() << "Fullscreen widgets are not supported in OSR"; } void CefRenderWidgetHostViewOSR::WasShown() { @@ -172,6 +194,8 @@ void CefRenderWidgetHostViewOSR::RenderViewGone( base::TerminationStatus status, int error_code) { render_widget_host_ = NULL; + parent_host_view_ = NULL; + popup_host_view_ = NULL; } #if defined(OS_WIN) && !defined(USE_AURA) @@ -185,11 +209,7 @@ gfx::Rect CefRenderWidgetHostViewOSR::GetBoundsInRootWindow() { if (!browser_impl_.get()) return gfx::Rect(); CefRect rc; - // If GetRootScreenRect is not implemented use the view rect as the root - // screen rect. if (browser_impl_->GetClient()->GetRenderHandler()->GetRootScreenRect( - browser_impl_->GetBrowser(), rc) || - browser_impl_->GetClient()->GetRenderHandler()->GetViewRect( browser_impl_->GetBrowser(), rc)) { return gfx::Rect(rc.x, rc.y, rc.width, rc.height); } @@ -197,6 +217,13 @@ gfx::Rect CefRenderWidgetHostViewOSR::GetBoundsInRootWindow() { } void CefRenderWidgetHostViewOSR::Destroy() { + if (IsPopupWidget()) { + if (parent_host_view_) + parent_host_view_->CancelWidget(); + } else { + CancelWidget(); + } + delete this; } @@ -214,13 +241,15 @@ void CefRenderWidgetHostViewOSR::SetTooltipText(const string16& tooltip_text) { content::BackingStore* CefRenderWidgetHostViewOSR::AllocBackingStore( const gfx::Size& size) { - return new BackingStoreOSR(render_widget_host_, size); + return render_widget_host_ ? + new BackingStoreOSR(render_widget_host_, size) : + NULL; } void CefRenderWidgetHostViewOSR::CopyFromCompositingSurface( const gfx::Rect& src_subrect, const gfx::Size& dst_size, - const base::Callback& callback, + const base::Callback& callback, skia::PlatformBitmap* output) { } @@ -269,7 +298,20 @@ void CefRenderWidgetHostViewOSR::SetClickthroughRegion(SkRegion* region) { } #endif -void CefRenderWidgetHostViewOSR::Invalidate(const gfx::Rect& rect) { +void CefRenderWidgetHostViewOSR::SetBackground(const SkBitmap& background) { + if (!render_widget_host_) + return; + RenderWidgetHostViewBase::SetBackground(background); + render_widget_host_->SetBackground(background); +} + +void CefRenderWidgetHostViewOSR::Invalidate(const gfx::Rect& rect, + CefBrowserHost::PaintElementType type) { + if (!IsPopupWidget() && type == PET_POPUP) { + if (popup_host_view_) + popup_host_view_->Invalidate(rect, type); + return; + } std::vector dirtyRects; dirtyRects.push_back(rect); Paint(dirtyRects); @@ -322,9 +364,72 @@ void CefRenderWidgetHostViewOSR::Paint( return; browser_impl_->GetClient()->GetRenderHandler()->OnPaint( - browser_impl_->GetBrowser(), PET_VIEW, rcList, + browser_impl_->GetBrowser(), + IsPopupWidget() ? PET_POPUP : PET_VIEW, + rcList, backing_store->getPixels(), - client_rect.width(), client_rect.height()); + client_rect.width(), + client_rect.height()); + } +} + +bool CefRenderWidgetHostViewOSR::InstallTransparency() { + if (browser_impl_.get() && browser_impl_->IsTransparent()) { + SkBitmap bg; + bg.setConfig(SkBitmap::kARGB_8888_Config, 1, 1); // 1x1 alpha bitmap. + bg.allocPixels(); + bg.eraseARGB(0x00, 0x00, 0x00, 0x00); + SetBackground(bg); + return true; + } + return false; +} + +void CefRenderWidgetHostViewOSR::CancelWidget() { + if (IsPopupWidget()) { + if (render_widget_host_) + render_widget_host_->LostCapture(); + + if (browser_impl_.get()) { + NotifyHideWidget(); + browser_impl_ = NULL; + } + + if (parent_host_view_) { + parent_host_view_->set_popup_host_view(NULL); + parent_host_view_ = NULL; + } + + if (!weak_factory_.HasWeakPtrs()) { + MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(&CefRenderWidgetHostViewOSR::ShutdownHost, + weak_factory_.GetWeakPtr())); + } + } else if (popup_host_view_) { + popup_host_view_->CancelWidget(); + } +} + +void CefRenderWidgetHostViewOSR::NotifyShowWidget() { + if (browser_impl_.get()) { + browser_impl_->GetClient()->GetRenderHandler()->OnPopupShow( + browser_impl_->GetBrowser(), true); + } +} + +void CefRenderWidgetHostViewOSR::NotifyHideWidget() { + if (browser_impl_.get()) { + browser_impl_->GetClient()->GetRenderHandler()->OnPopupShow( + browser_impl_->GetBrowser(), false); + } +} + +void CefRenderWidgetHostViewOSR::NotifySizeWidget() { + if (browser_impl_.get()) { + CefRect widget_pos(popup_position_.x(), popup_position_.y(), + popup_position_.width(), popup_position_.height()); + browser_impl_->GetClient()->GetRenderHandler()->OnPopupSize( + browser_impl_->GetBrowser(), widget_pos); } } @@ -337,3 +442,71 @@ void CefRenderWidgetHostViewOSR::set_browser_impl( CefRefPtr browser) { browser_impl_ = browser; } + +void CefRenderWidgetHostViewOSR::set_popup_host_view( + CefRenderWidgetHostViewOSR* popup_view) { + popup_host_view_ = popup_view; +} + +void CefRenderWidgetHostViewOSR::ShutdownHost() { + weak_factory_.InvalidateWeakPtrs(); + if (render_widget_host_) + render_widget_host_->Shutdown(); + // Do not touch any members at this point, |this| has been deleted. +} + +void CefRenderWidgetHostViewOSR::set_parent_host_view( + CefRenderWidgetHostViewOSR* parent_view) { + parent_host_view_ = parent_view; +} + +void CefRenderWidgetHostViewOSR::SendKeyEvent( + const content::NativeWebKeyboardEvent& event) { + if (!IsPopupWidget() && popup_host_view_) { + popup_host_view_->SendKeyEvent(event); + return; + } + if (!render_widget_host_) + return; + render_widget_host_->ForwardKeyboardEvent(event); +} + +void CefRenderWidgetHostViewOSR::SendMouseEvent( + const WebKit::WebMouseEvent& event) { + if (!IsPopupWidget() && popup_host_view_) { + if (popup_host_view_->popup_position_.Contains(event.x, event.y)) { + WebKit::WebMouseEvent popup_event(event); + popup_event.x -= popup_host_view_->popup_position_.x(); + popup_event.y -= popup_host_view_->popup_position_.y(); + popup_event.windowX = popup_event.x; + popup_event.windowY = popup_event.y; + + popup_host_view_->SendMouseEvent(popup_event); + return; + } + } + if (!render_widget_host_) + return; + render_widget_host_->ForwardMouseEvent(event); +} + +void CefRenderWidgetHostViewOSR::SendMouseWheelEvent( + const WebKit::WebMouseWheelEvent& event) { + if (!IsPopupWidget() && popup_host_view_) { + if (popup_host_view_->popup_position_.Contains(event.x, event.y)) { + WebKit::WebMouseWheelEvent popup_event(event); + popup_event.x -= popup_host_view_->popup_position_.x(); + popup_event.y -= popup_host_view_->popup_position_.y(); + popup_event.windowX = popup_event.x; + popup_event.windowY = popup_event.y; + popup_host_view_->SendMouseWheelEvent(popup_event); + return; + } else { + // scrolling outside the popup widget, will destroy widget + CancelWidget(); + } + } + if (!render_widget_host_) + return; + render_widget_host_->ForwardWheelEvent(event); +} diff --git a/libcef/browser/render_widget_host_view_osr.h b/libcef/browser/render_widget_host_view_osr.h index 163483bd6..b14d90cc0 100644 --- a/libcef/browser/render_widget_host_view_osr.h +++ b/libcef/browser/render_widget_host_view_osr.h @@ -10,7 +10,9 @@ #include #include "include/cef_base.h" +#include "include/cef_browser.h" +#include "base/memory/weak_ptr.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" namespace content { @@ -90,7 +92,7 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase { virtual void CopyFromCompositingSurface( const gfx::Rect& src_subrect, const gfx::Size& dst_size, - const base::Callback& callback, + const base::Callback& callback, skia::PlatformBitmap* output) OVERRIDE; virtual void OnAcceleratedCompositingStateChange() OVERRIDE; virtual void SetHasHorizontalScrollbar( @@ -113,12 +115,31 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase { virtual void SetClickthroughRegion(SkRegion* region) OVERRIDE; #endif - // CefRenderWidgetHostViewOSR methods - void Invalidate(const gfx::Rect& rect); + // RenderWidgetHostViewBase methods. + virtual void SetBackground(const SkBitmap& background) OVERRIDE; + + void SendKeyEvent(const content::NativeWebKeyboardEvent& event); + void SendMouseEvent(const WebKit::WebMouseEvent& event); + void SendMouseWheelEvent(const WebKit::WebMouseWheelEvent& event); + + void Invalidate(const gfx::Rect& rect, + CefBrowserHost::PaintElementType type); void Paint(const std::vector& copy_rects); + bool InstallTransparency(); + + void CancelWidget(); + void NotifyShowWidget(); + void NotifyHideWidget(); + void NotifySizeWidget(); CefRefPtr get_browser_impl() const; void set_browser_impl(CefRefPtr browser); + void set_popup_host_view(CefRenderWidgetHostViewOSR* popup_view); + void set_parent_host_view(CefRenderWidgetHostViewOSR* parent_view); + + bool IsPopupWidget() const { + return popup_type_ != WebKit::WebPopupTypeNone; + } private: friend class CefWebContentsViewOSR; @@ -126,16 +147,26 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase { explicit CefRenderWidgetHostViewOSR(content::RenderWidgetHost* widget); virtual ~CefRenderWidgetHostViewOSR(); + // After calling this function, object gets deleted + void ShutdownHost(); + + // Factory used to safely scope delayed calls to ShutdownHost(). + base::WeakPtrFactory weak_factory_; + // The associated Model. While |this| is being Destroyed, // |render_widget_host_| is NULL and the Windows message loop is run one last // time. Message handlers must check for a NULL |render_widget_host_|. content::RenderWidgetHostImpl* render_widget_host_; + CefRenderWidgetHostViewOSR* parent_host_view_; + CefRenderWidgetHostViewOSR* popup_host_view_; CefRefPtr browser_impl_; bool about_to_validate_and_paint_; std::vector pending_update_rects_; + gfx::Rect popup_position_; + DISALLOW_COPY_AND_ASSIGN(CefRenderWidgetHostViewOSR); }; diff --git a/libcef/browser/web_contents_view_osr.cc b/libcef/browser/web_contents_view_osr.cc index 56dfa0640..7c900c2bf 100644 --- a/libcef/browser/web_contents_view_osr.cc +++ b/libcef/browser/web_contents_view_osr.cc @@ -33,6 +33,13 @@ content::RenderWidgetHostView* CefWebContentsViewOSR::CreateViewForWidget( return view_; } +content::RenderWidgetHostView* CefWebContentsViewOSR::CreateViewForPopupWidget( + content::RenderWidgetHost* render_widget_host) { + CefRenderWidgetHostViewOSR* popup_widget = + new CefRenderWidgetHostViewOSR(render_widget_host); + return popup_widget; +} + void CefWebContentsViewOSR::SetView(content::RenderWidgetHostView* view) { view_ = view; } @@ -66,6 +73,11 @@ void CefWebContentsViewOSR::SizeContents(const gfx::Size& size) { } void CefWebContentsViewOSR::RenderViewCreated(content::RenderViewHost* host) { + if (view_) { + CefRenderWidgetHostViewOSR* osr_view = + static_cast(view_); + osr_view->InstallTransparency(); + } } void CefWebContentsViewOSR::Focus() { diff --git a/libcef/browser/web_contents_view_osr.h b/libcef/browser/web_contents_view_osr.h index f0996f7ea..fcfb26069 100644 --- a/libcef/browser/web_contents_view_osr.h +++ b/libcef/browser/web_contents_view_osr.h @@ -30,6 +30,8 @@ class CefWebContentsViewOSR : public content::WebContentsView, virtual void CreateView(const gfx::Size& initial_size) OVERRIDE; virtual content::RenderWidgetHostView* CreateViewForWidget( content::RenderWidgetHost* render_widget_host) OVERRIDE; + virtual content::RenderWidgetHostView* CreateViewForPopupWidget( + content::RenderWidgetHost* render_widget_host); virtual void SetView(content::RenderWidgetHostView* view) OVERRIDE; virtual gfx::NativeView GetNativeView() const OVERRIDE; virtual gfx::NativeView GetContentNativeView() const OVERRIDE; diff --git a/libcef_dll/cpptoc/browser_host_cpptoc.cc b/libcef_dll/cpptoc/browser_host_cpptoc.cc index 1986e43a3..4e914fc53 100644 --- a/libcef_dll/cpptoc/browser_host_cpptoc.cc +++ b/libcef_dll/cpptoc/browser_host_cpptoc.cc @@ -289,7 +289,7 @@ void CEF_CALLBACK browser_host_was_resized(struct _cef_browser_host_t* self) { } void CEF_CALLBACK browser_host_invalidate(struct _cef_browser_host_t* self, - const cef_rect_t* dirtyRect) { + const cef_rect_t* dirtyRect, enum cef_paint_element_type_t type) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING DCHECK(self); @@ -305,7 +305,8 @@ void CEF_CALLBACK browser_host_invalidate(struct _cef_browser_host_t* self, // Execute CefBrowserHostCppToC::Get(self)->Invalidate( - dirtyRectVal); + dirtyRectVal, + type); } void CEF_CALLBACK browser_host_send_key_event(struct _cef_browser_host_t* self, @@ -331,50 +332,76 @@ void CEF_CALLBACK browser_host_send_key_event(struct _cef_browser_host_t* self, } void CEF_CALLBACK browser_host_send_mouse_click_event( - struct _cef_browser_host_t* self, int x, int y, + struct _cef_browser_host_t* self, const struct _cef_mouse_event_t* event, enum cef_mouse_button_type_t type, int mouseUp, int clickCount) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING DCHECK(self); if (!self) return; + // Verify param: event; type: struct_byref_const + DCHECK(event); + if (!event) + return; + + // Translate param: event; type: struct_byref_const + CefMouseEvent eventObj; + if (event) + eventObj.Set(*event, false); // Execute CefBrowserHostCppToC::Get(self)->SendMouseClickEvent( - x, - y, + eventObj, type, mouseUp?true:false, clickCount); } void CEF_CALLBACK browser_host_send_mouse_move_event( - struct _cef_browser_host_t* self, int x, int y, int mouseLeave) { + struct _cef_browser_host_t* self, const struct _cef_mouse_event_t* event, + int mouseLeave) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING DCHECK(self); if (!self) return; + // Verify param: event; type: struct_byref_const + DCHECK(event); + if (!event) + return; + + // Translate param: event; type: struct_byref_const + CefMouseEvent eventObj; + if (event) + eventObj.Set(*event, false); // Execute CefBrowserHostCppToC::Get(self)->SendMouseMoveEvent( - x, - y, + eventObj, mouseLeave?true:false); } void CEF_CALLBACK browser_host_send_mouse_wheel_event( - struct _cef_browser_host_t* self, int x, int y, int deltaX, int deltaY) { + struct _cef_browser_host_t* self, const struct _cef_mouse_event_t* event, + int deltaX, int deltaY) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING DCHECK(self); if (!self) return; + // Verify param: event; type: struct_byref_const + DCHECK(event); + if (!event) + return; + + // Translate param: event; type: struct_byref_const + CefMouseEvent eventObj; + if (event) + eventObj.Set(*event, false); // Execute CefBrowserHostCppToC::Get(self)->SendMouseWheelEvent( - x, - y, + eventObj, deltaX, deltaY); } diff --git a/libcef_dll/ctocpp/browser_host_ctocpp.cc b/libcef_dll/ctocpp/browser_host_ctocpp.cc index 9cfc3b8ab..63f1849a1 100644 --- a/libcef_dll/ctocpp/browser_host_ctocpp.cc +++ b/libcef_dll/ctocpp/browser_host_ctocpp.cc @@ -238,7 +238,8 @@ void CefBrowserHostCToCpp::WasResized() { struct_->was_resized(struct_); } -void CefBrowserHostCToCpp::Invalidate(const CefRect& dirtyRect) { +void CefBrowserHostCToCpp::Invalidate(const CefRect& dirtyRect, + PaintElementType type) { if (CEF_MEMBER_MISSING(struct_, invalidate)) return; @@ -246,7 +247,8 @@ void CefBrowserHostCToCpp::Invalidate(const CefRect& dirtyRect) { // Execute struct_->invalidate(struct_, - &dirtyRect); + &dirtyRect, + type); } void CefBrowserHostCToCpp::SendKeyEvent(const CefKeyEvent& event) { @@ -260,7 +262,7 @@ void CefBrowserHostCToCpp::SendKeyEvent(const CefKeyEvent& event) { &event); } -void CefBrowserHostCToCpp::SendMouseClickEvent(int x, int y, +void CefBrowserHostCToCpp::SendMouseClickEvent(const CefMouseEvent& event, MouseButtonType type, bool mouseUp, int clickCount) { if (CEF_MEMBER_MISSING(struct_, send_mouse_click_event)) return; @@ -269,14 +271,14 @@ void CefBrowserHostCToCpp::SendMouseClickEvent(int x, int y, // Execute struct_->send_mouse_click_event(struct_, - x, - y, + &event, type, mouseUp, clickCount); } -void CefBrowserHostCToCpp::SendMouseMoveEvent(int x, int y, bool mouseLeave) { +void CefBrowserHostCToCpp::SendMouseMoveEvent(const CefMouseEvent& event, + bool mouseLeave) { if (CEF_MEMBER_MISSING(struct_, send_mouse_move_event)) return; @@ -284,13 +286,12 @@ void CefBrowserHostCToCpp::SendMouseMoveEvent(int x, int y, bool mouseLeave) { // Execute struct_->send_mouse_move_event(struct_, - x, - y, + &event, mouseLeave); } -void CefBrowserHostCToCpp::SendMouseWheelEvent(int x, int y, int deltaX, - int deltaY) { +void CefBrowserHostCToCpp::SendMouseWheelEvent(const CefMouseEvent& event, + int deltaX, int deltaY) { if (CEF_MEMBER_MISSING(struct_, send_mouse_wheel_event)) return; @@ -298,8 +299,7 @@ void CefBrowserHostCToCpp::SendMouseWheelEvent(int x, int y, int deltaX, // Execute struct_->send_mouse_wheel_event(struct_, - x, - y, + &event, deltaX, deltaY); } diff --git a/libcef_dll/ctocpp/browser_host_ctocpp.h b/libcef_dll/ctocpp/browser_host_ctocpp.h index bf0f9df18..2b0c9cb85 100644 --- a/libcef_dll/ctocpp/browser_host_ctocpp.h +++ b/libcef_dll/ctocpp/browser_host_ctocpp.h @@ -53,12 +53,14 @@ class CefBrowserHostCToCpp CefRefPtr callback) OVERRIDE; virtual bool IsWindowRenderingDisabled() OVERRIDE; virtual void WasResized() OVERRIDE; - virtual void Invalidate(const CefRect& dirtyRect) OVERRIDE; + virtual void Invalidate(const CefRect& dirtyRect, + PaintElementType type) OVERRIDE; virtual void SendKeyEvent(const CefKeyEvent& event) OVERRIDE; - virtual void SendMouseClickEvent(int x, int y, MouseButtonType type, - bool mouseUp, int clickCount) OVERRIDE; - virtual void SendMouseMoveEvent(int x, int y, bool mouseLeave) OVERRIDE; - virtual void SendMouseWheelEvent(int x, int y, int deltaX, + virtual void SendMouseClickEvent(const CefMouseEvent& event, + MouseButtonType type, bool mouseUp, int clickCount) OVERRIDE; + virtual void SendMouseMoveEvent(const CefMouseEvent& event, + bool mouseLeave) OVERRIDE; + virtual void SendMouseWheelEvent(const CefMouseEvent& event, int deltaX, int deltaY) OVERRIDE; virtual void SendFocusEvent(bool setFocus) OVERRIDE; virtual void SendCaptureLostEvent() OVERRIDE; diff --git a/patch/patch.cfg b/patch/patch.cfg index 57158252a..0f68b1ac1 100644 --- a/patch/patch.cfg +++ b/patch/patch.cfg @@ -31,6 +31,11 @@ patches = [ 'name': 'webkit_451', 'path': '../third_party/WebKit/Source/', }, + { + # http://code.google.com/p/chromium/issues/detail?id=155761 + 'name': 'content_popups', + 'path': '../content/', + }, { # http://code.google.com/p/chromiumembedded/issues/detail?id=364 'name': 'spi_webcore_364', diff --git a/patch/patches/content_popups.patch b/patch/patches/content_popups.patch new file mode 100644 index 000000000..e4fb06c6f --- /dev/null +++ b/patch/patches/content_popups.patch @@ -0,0 +1,31 @@ +Index: browser/web_contents/web_contents_impl.cc +=================================================================== +--- browser/web_contents/web_contents_impl.cc (revision 170167) ++++ browser/web_contents/web_contents_impl.cc (working copy) +@@ -1402,8 +1402,10 @@ + new RenderWidgetHostImpl(this, process, route_id); + created_widgets_.insert(widget_host); + +- RenderWidgetHostViewPort* widget_view = +- RenderWidgetHostViewPort::CreateViewForWidget(widget_host); ++ RenderWidgetHostViewPort* widget_view = RenderWidgetHostViewPort::FromRWHV( ++ view_->CreateViewForPopupWidget(widget_host)); ++ if (!widget_view) ++ widget_view = RenderWidgetHostViewPort::CreateViewForWidget(widget_host); + if (!is_fullscreen) { + // Popups should not get activated. + widget_view->SetPopupType(popup_type); +Index: public/browser/web_contents_view.h +=================================================================== +--- public/browser/web_contents_view.h (revision 170167) ++++ public/browser/web_contents_view.h (working copy) +@@ -37,6 +37,9 @@ + virtual RenderWidgetHostView* CreateViewForWidget( + RenderWidgetHost* render_widget_host) = 0; + ++ virtual RenderWidgetHostView* CreateViewForPopupWidget( ++ RenderWidgetHost* render_widget_host) { return NULL; } ++ + // This is required because some WebContentsView cache the + // RenderWidgetHostView created by the above method. In that case, when the + // view created by the above method is destroyed, the old one needs to be set diff --git a/tests/cefclient/cefclient.cpp b/tests/cefclient/cefclient.cpp index bea0af727..5fed17a35 100644 --- a/tests/cefclient/cefclient.cpp +++ b/tests/cefclient/cefclient.cpp @@ -332,3 +332,7 @@ void RunDragDropTest(CefRefPtr browser) { void RunGeolocationTest(CefRefPtr browser) { browser->GetMainFrame()->LoadURL("http://html5demos.com/geo"); } + +void RunTransparencyTest(CefRefPtr browser) { + browser->GetMainFrame()->LoadURL("http://tests/transparency"); +} diff --git a/tests/cefclient/cefclient.h b/tests/cefclient/cefclient.h index f763ccc43..529e1d26d 100644 --- a/tests/cefclient/cefclient.h +++ b/tests/cefclient/cefclient.h @@ -53,6 +53,7 @@ void RunHTML5VideoTest(CefRefPtr browser); void RunXMLHTTPRequestTest(CefRefPtr browser); void RunDragDropTest(CefRefPtr browser); void RunGeolocationTest(CefRefPtr browser); +void RunTransparencyTest(CefRefPtr browser); #if defined(OS_WIN) void RunTransparentPopupTest(CefRefPtr browser); diff --git a/tests/cefclient/cefclient.rc b/tests/cefclient/cefclient.rc index 1a1e993c6..4aa5877f5 100644 --- a/tests/cefclient/cefclient.rc +++ b/tests/cefclient/cefclient.rc @@ -30,12 +30,13 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US IDS_BINDING BINARY "res\\binding.html" IDS_DIALOGS BINARY "res\\dialogs.html" +IDS_DOMACCESS BINARY "res\\domaccess.html" +IDS_LOCALSTORAGE BINARY "res\\localstorage.html" IDS_LOGO BINARY "res\\logo.png" IDS_LOGOBALL BINARY "res\\logoball.png" -IDS_LOCALSTORAGE BINARY "res\\localstorage.html" IDS_PERFORMANCE BINARY "res\\performance.html" +IDS_TRANSPARENCY BINARY "res\\transparency.html" IDS_XMLHTTPREQUEST BINARY "res\\xmlhttprequest.html" -IDS_DOMACCESS BINARY "res\\domaccess.html" ///////////////////////////////////////////////////////////////////////////// // @@ -82,6 +83,7 @@ BEGIN MENUITEM "HTML5 Video", ID_TESTS_HTML5VIDEO MENUITEM "Drag && Drop", ID_TESTS_DRAGDROP MENUITEM "Geolocation", ID_TESTS_GEOLOCATION + MENUITEM "Transparency", ID_TESTS_TRANSPARENCY MENUITEM "Zoom In", ID_TESTS_ZOOM_IN MENUITEM "Zoom Out", ID_TESTS_ZOOM_OUT MENUITEM "Zoom Reset", ID_TESTS_ZOOM_RESET diff --git a/tests/cefclient/cefclient_osr_widget_win.cpp b/tests/cefclient/cefclient_osr_widget_win.cpp index b49b5a91c..9db463751 100644 --- a/tests/cefclient/cefclient_osr_widget_win.cpp +++ b/tests/cefclient/cefclient_osr_widget_win.cpp @@ -3,6 +3,10 @@ // can be found in the LICENSE file. #include "cefclient/cefclient_osr_widget_win.h" + +#include + +#include "include/cef_runnable.h" #include "cefclient/resource.h" #include "cefclient/util.h" @@ -108,11 +112,23 @@ void OSRWindow::OnPaint(CefRefPtr browser, const RectList& dirtyRects, const void* buffer, int width, int height) { + if (painting_popup_) { + renderer_.OnPaint(browser, type, dirtyRects, buffer, width, height); + return; + } if (!hDC_) EnableGL(); wglMakeCurrent(hDC_, hRC_); renderer_.OnPaint(browser, type, dirtyRects, buffer, width, height); + if (type == PET_VIEW && !renderer_.popup_rect().IsEmpty()) { + painting_popup_ = true; + CefRect client_popup_rect(0, 0, + renderer_.popup_rect().width, + renderer_.popup_rect().height); + browser->GetHost()->Invalidate(client_popup_rect, PET_POPUP); + painting_popup_ = false; + } renderer_.Render(); SwapBuffers(hDC_); } @@ -128,18 +144,51 @@ void OSRWindow::OnCursorChange(CefRefPtr browser, SetCursor(cursor); } +void OSRWindow::Invalidate() { + if (!CefCurrentlyOn(TID_UI)) { + CefPostTask(TID_UI, NewCefRunnableMethod(this, &OSRWindow::Invalidate)); + return; + } + + // Don't post another task if the previous task is still pending. + if (render_task_pending_) + return; + + render_task_pending_ = true; + + // Render at 30fps. + static const int kRenderDelay = 1 / 30; + CefPostDelayedTask(TID_UI, NewCefRunnableMethod(this, &OSRWindow::Render), + kRenderDelay); +} + OSRWindow::OSRWindow(OSRBrowserProvider* browser_provider, bool transparent) : renderer_(transparent), browser_provider_(browser_provider), hWnd_(NULL), hDC_(NULL), - hRC_(NULL) { + hRC_(NULL), + painting_popup_(false), + render_task_pending_(false) { } OSRWindow::~OSRWindow() { DestroyWidget(); } +void OSRWindow::Render() { + ASSERT(CefCurrentlyOn(TID_UI)); + if (render_task_pending_) + render_task_pending_ = false; + + if (!hDC_) + EnableGL(); + + wglMakeCurrent(hDC_, hRC_); + renderer_.Render(); + SwapBuffers(hDC_); +} + void OSRWindow::EnableGL() { ASSERT(CefCurrentlyOn(TID_UI)); @@ -210,6 +259,136 @@ ATOM OSRWindow::RegisterOSRClass(HINSTANCE hInstance, LPCTSTR className) { return RegisterClassEx(&wcex); } +bool OSRWindow::isKeyDown(WPARAM wparam) { + return (GetKeyState(wparam) & 0x8000) != 0; +} + +int OSRWindow::GetCefMouseModifiers(WPARAM wparam) { + int modifiers = 0; + if (wparam & MK_CONTROL) + modifiers |= EVENTFLAG_CONTROL_DOWN; + if (wparam & MK_SHIFT) + modifiers |= EVENTFLAG_SHIFT_DOWN; + if (isKeyDown(VK_MENU)) + modifiers |= EVENTFLAG_ALT_DOWN; + if (wparam & MK_LBUTTON) + modifiers |= EVENTFLAG_LEFT_MOUSE_BUTTON; + if (wparam & MK_MBUTTON) + modifiers |= EVENTFLAG_MIDDLE_MOUSE_BUTTON; + if (wparam & MK_RBUTTON) + modifiers |= EVENTFLAG_RIGHT_MOUSE_BUTTON; + + // Low bit set from GetKeyState indicates "toggled". + if (::GetKeyState(VK_NUMLOCK) & 1) + modifiers |= EVENTFLAG_NUM_LOCK_ON; + if (::GetKeyState(VK_CAPITAL) & 1) + modifiers |= EVENTFLAG_CAPS_LOCK_ON; + return modifiers; +} + +int OSRWindow::GetCefKeyboardModifiers(WPARAM wparam, LPARAM lparam) { + int modifiers = 0; + if (isKeyDown(VK_SHIFT)) + modifiers |= EVENTFLAG_SHIFT_DOWN; + if (isKeyDown(VK_CONTROL)) + modifiers |= EVENTFLAG_CONTROL_DOWN; + if (isKeyDown(VK_MENU)) + modifiers |= EVENTFLAG_ALT_DOWN; + + // Low bit set from GetKeyState indicates "toggled". + if (::GetKeyState(VK_NUMLOCK) & 1) + modifiers |= EVENTFLAG_NUM_LOCK_ON; + if (::GetKeyState(VK_CAPITAL) & 1) + modifiers |= EVENTFLAG_CAPS_LOCK_ON; + + switch (wparam) { + case VK_RETURN: + if ((lparam >> 16) & KF_EXTENDED) + modifiers |= EVENTFLAG_IS_KEY_PAD; + break; + case VK_INSERT: + case VK_DELETE: + case VK_HOME: + case VK_END: + case VK_PRIOR: + case VK_NEXT: + case VK_UP: + case VK_DOWN: + case VK_LEFT: + case VK_RIGHT: + if (!((lparam >> 16) & KF_EXTENDED)) + modifiers |= EVENTFLAG_IS_KEY_PAD; + break; + case VK_NUMLOCK: + case VK_NUMPAD0: + case VK_NUMPAD1: + case VK_NUMPAD2: + case VK_NUMPAD3: + case VK_NUMPAD4: + case VK_NUMPAD5: + case VK_NUMPAD6: + case VK_NUMPAD7: + case VK_NUMPAD8: + case VK_NUMPAD9: + case VK_DIVIDE: + case VK_MULTIPLY: + case VK_SUBTRACT: + case VK_ADD: + case VK_DECIMAL: + case VK_CLEAR: + modifiers |= EVENTFLAG_IS_KEY_PAD; + break; + case VK_SHIFT: + if (isKeyDown(VK_LSHIFT)) + modifiers |= EVENTFLAG_IS_LEFT; + else if (isKeyDown(VK_RSHIFT)) + modifiers |= EVENTFLAG_IS_RIGHT; + break; + case VK_CONTROL: + if (isKeyDown(VK_LCONTROL)) + modifiers |= EVENTFLAG_IS_LEFT; + else if (isKeyDown(VK_RCONTROL)) + modifiers |= EVENTFLAG_IS_RIGHT; + break; + case VK_MENU: + if (isKeyDown(VK_LMENU)) + modifiers |= EVENTFLAG_IS_LEFT; + else if (isKeyDown(VK_RMENU)) + modifiers |= EVENTFLAG_IS_RIGHT; + break; + case VK_LWIN: + modifiers |= EVENTFLAG_IS_LEFT; + break; + case VK_RWIN: + modifiers |= EVENTFLAG_IS_RIGHT; + break; + } + return modifiers; +} + +bool OSRWindow::IsOverPopupWidget(int x, int y) const { + const CefRect& rc = renderer_.popup_rect(); + int popup_right = rc.x + rc.width; + int popup_bottom = rc.y + rc.height; + return (x >= rc.x) && (x < popup_right) && + (y >= rc.y) && (y < popup_bottom); +} + +int OSRWindow::GetPopupXOffset() const { + return renderer_.original_popup_rect().x - renderer_.popup_rect().x; +} + +int OSRWindow::GetPopupYOffset() const { + return renderer_.original_popup_rect().y - renderer_.popup_rect().y; +} + +void OSRWindow::ApplyPopupOffset(int& x, int& y) const { + if (IsOverPopupWidget(x, y)) { + x += GetPopupXOffset(); + y += GetPopupYOffset(); + } +} + // Plugin window procedure. // static LRESULT CALLBACK OSRWindow::WndProc(HWND hWnd, UINT message, @@ -218,12 +397,42 @@ LRESULT CALLBACK OSRWindow::WndProc(HWND hWnd, UINT message, static bool mouseRotation = false; static bool mouseTracking = false; + static int lastClickX = 0; + static int lastClickY = 0; + static CefBrowserHost::MouseButtonType lastClickButton = MBT_LEFT; + static int gLastClickCount = 0; + static double gLastClickTime = 0; + + static bool gLastMouseDownOnView = false; + OSRWindow* window = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); CefRefPtr browser; if (window && window->browser_provider_->GetBrowser().get()) browser = window->browser_provider_->GetBrowser()->GetHost(); + LONG currentTime = 0; + bool cancelPreviousClick = false; + + if (message == WM_LBUTTONDOWN || message == WM_RBUTTONDOWN || + message == WM_MBUTTONDOWN || message == WM_MOUSEMOVE || + message == WM_MOUSELEAVE) { + currentTime = GetMessageTime(); + int x = GET_X_LPARAM(lParam); + int y = GET_Y_LPARAM(lParam); + cancelPreviousClick = + (abs(lastClickX - x) > (GetSystemMetrics(SM_CXDOUBLECLK) / 2)) + || (abs(lastClickY - y) > (GetSystemMetrics(SM_CYDOUBLECLK) / 2)) + || ((currentTime - gLastClickTime) > GetDoubleClickTime()); + if (cancelPreviousClick && + (message == WM_MOUSEMOVE || message == WM_MOUSELEAVE)) { + gLastClickCount = 0; + lastClickX = 0; + lastClickY = 0; + gLastClickTime = 0; + } + } + switch (message) { case WM_DESTROY: if (window) @@ -232,46 +441,89 @@ LRESULT CALLBACK OSRWindow::WndProc(HWND hWnd, UINT message, case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: + case WM_MBUTTONDOWN: { SetCapture(hWnd); SetFocus(hWnd); + int x = GET_X_LPARAM(lParam); + int y = GET_Y_LPARAM(lParam); if (wParam & MK_SHIFT) { // Start rotation effect. - lastMousePos.x = curMousePos.x = LOWORD(lParam); - lastMousePos.y = curMousePos.y = HIWORD(lParam); + lastMousePos.x = curMousePos.x = x; + lastMousePos.y = curMousePos.y = y; mouseRotation = true; } else { + CefBrowserHost::MouseButtonType btnType = + (message == WM_LBUTTONDOWN ? MBT_LEFT : ( + message == WM_RBUTTONDOWN ? MBT_RIGHT : MBT_MIDDLE)); + if (!cancelPreviousClick && (btnType == lastClickButton)) { + ++gLastClickCount; + } else { + gLastClickCount = 1; + lastClickX = x; + lastClickY = y; + } + gLastClickTime = currentTime; + lastClickButton = btnType; + if (browser.get()) { - browser->SendMouseClickEvent(LOWORD(lParam), HIWORD(lParam), - (message == WM_LBUTTONDOWN?MBT_LEFT:MBT_RIGHT), false, 1); + CefMouseEvent mouse_event; + mouse_event.x = x; + mouse_event.y = y; + gLastMouseDownOnView = !window->IsOverPopupWidget(x, y); + window->ApplyPopupOffset(mouse_event.x, mouse_event.y); + mouse_event.modifiers = GetCefMouseModifiers(wParam); + browser->SendMouseClickEvent(mouse_event, btnType, false, + gLastClickCount); } } break; + } case WM_LBUTTONUP: case WM_RBUTTONUP: + case WM_MBUTTONUP: if (GetCapture() == hWnd) ReleaseCapture(); if (mouseRotation) { // End rotation effect. mouseRotation = false; window->renderer_.SetSpin(0, 0); + window->Invalidate(); } else { + int x = GET_X_LPARAM(lParam); + int y = GET_Y_LPARAM(lParam); + CefBrowserHost::MouseButtonType btnType = + (message == WM_LBUTTONDOWN ? MBT_LEFT : ( + message == WM_RBUTTONDOWN ? MBT_RIGHT : MBT_MIDDLE)); if (browser.get()) { - browser->SendMouseClickEvent(LOWORD(lParam), HIWORD(lParam), - (message == WM_LBUTTONUP?MBT_LEFT:MBT_RIGHT), true, 1); + CefMouseEvent mouse_event; + mouse_event.x = x; + mouse_event.y = y; + if (gLastMouseDownOnView && + window->IsOverPopupWidget(x, y) && + (window->GetPopupXOffset() || window->GetPopupYOffset())) { + break; + } + window->ApplyPopupOffset(mouse_event.x, mouse_event.y); + mouse_event.modifiers = GetCefMouseModifiers(wParam); + browser->SendMouseClickEvent(mouse_event, btnType, true, + gLastClickCount); } } break; - case WM_MOUSEMOVE: + case WM_MOUSEMOVE: { + int x = GET_X_LPARAM(lParam); + int y = GET_Y_LPARAM(lParam); if (mouseRotation) { // Apply rotation effect. - curMousePos.x = LOWORD(lParam); - curMousePos.y = HIWORD(lParam); + curMousePos.x = x; + curMousePos.y = y; window->renderer_.IncrementSpin((curMousePos.x - lastMousePos.x), (curMousePos.y - lastMousePos.y)); lastMousePos.x = curMousePos.x; lastMousePos.y = curMousePos.y; + window->Invalidate(); } else { if (!mouseTracking) { // Start tracking mouse leave. Required for the WM_MOUSELEAVE event to @@ -284,10 +536,16 @@ LRESULT CALLBACK OSRWindow::WndProc(HWND hWnd, UINT message, mouseTracking = true; } if (browser.get()) { - browser->SendMouseMoveEvent(LOWORD(lParam), HIWORD(lParam), false); + CefMouseEvent mouse_event; + mouse_event.x = x; + mouse_event.y = y; + window->ApplyPopupOffset(mouse_event.x, mouse_event.y); + mouse_event.modifiers = GetCefMouseModifiers(wParam); + browser->SendMouseMoveEvent(mouse_event, false); } } break; + } case WM_MOUSELEAVE: if (mouseTracking) { @@ -299,14 +557,34 @@ LRESULT CALLBACK OSRWindow::WndProc(HWND hWnd, UINT message, TrackMouseEvent(&tme); mouseTracking = false; } - if (browser.get()) - browser->SendMouseMoveEvent(0, 0, true); + if (browser.get()) { + CefMouseEvent mouse_event; + mouse_event.x = 0; + mouse_event.y = 0; + mouse_event.modifiers = GetCefMouseModifiers(wParam); + browser->SendMouseMoveEvent(mouse_event, true); + } break; case WM_MOUSEWHEEL: if (browser.get()) { - browser->SendMouseWheelEvent(LOWORD(lParam), HIWORD(lParam), - 0, GET_WHEEL_DELTA_WPARAM(wParam)); + POINT screen_point = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; + HWND scrolled_wnd = ::WindowFromPoint(screen_point); + if (scrolled_wnd != hWnd) { + break; + } + ScreenToClient(hWnd, &screen_point); + int delta = GET_WHEEL_DELTA_WPARAM(wParam); + + CefMouseEvent mouse_event; + mouse_event.x = screen_point.x; + mouse_event.y = screen_point.y; + window->ApplyPopupOffset(mouse_event.x, mouse_event.y); + mouse_event.modifiers = GetCefMouseModifiers(wParam); + + browser->SendMouseWheelEvent(mouse_event, + isKeyDown(VK_SHIFT) ? delta : 0, + !isKeyDown(VK_SHIFT) ? delta : 0); } break; @@ -347,7 +625,7 @@ LRESULT CALLBACK OSRWindow::WndProc(HWND hWnd, UINT message, event.type = KEYEVENT_KEYUP; else event.type = KEYEVENT_CHAR; - + event.modifiers = GetCefKeyboardModifiers(wParam, lParam); if (browser.get()) browser->SendKeyEvent(event); break; @@ -363,7 +641,7 @@ LRESULT CALLBACK OSRWindow::WndProc(HWND hWnd, UINT message, browser->Invalidate(CefRect(rc.left, rc.top, rc.right - rc.left, - rc.bottom - rc.top)); + rc.bottom - rc.top), PET_VIEW); } return 0; } diff --git a/tests/cefclient/cefclient_osr_widget_win.h b/tests/cefclient/cefclient_osr_widget_win.h index 99d7a2678..cb75e0e3e 100644 --- a/tests/cefclient/cefclient_osr_widget_win.h +++ b/tests/cefclient/cefclient_osr_widget_win.h @@ -65,16 +65,26 @@ class OSRWindow : public ClientHandler::RenderHandler { virtual void OnCursorChange(CefRefPtr browser, CefCursorHandle cursor) OVERRIDE; + void Invalidate(); + private: OSRWindow(OSRBrowserProvider* browser_provider, bool transparent); virtual ~OSRWindow(); + void Render(); void EnableGL(); void DisableGL(); void OnDestroyed(); static ATOM RegisterOSRClass(HINSTANCE hInstance, LPCTSTR className); static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + static int GetCefKeyboardModifiers(WPARAM wparam, LPARAM lparam); + static int GetCefMouseModifiers(WPARAM wparam); + static bool isKeyDown(WPARAM wparam); + bool IsOverPopupWidget(int x, int y) const; + int GetPopupXOffset() const; + int GetPopupYOffset() const; + void ApplyPopupOffset(int& x, int& y) const; ClientOSRenderer renderer_; OSRBrowserProvider* browser_provider_; @@ -82,6 +92,9 @@ class OSRWindow : public ClientHandler::RenderHandler { HDC hDC_; HGLRC hRC_; + bool painting_popup_; + bool render_task_pending_; + IMPLEMENT_REFCOUNTING(OSRWindow); }; diff --git a/tests/cefclient/cefclient_win.cpp b/tests/cefclient/cefclient_win.cpp index ae4f82664..724553103 100644 --- a/tests/cefclient/cefclient_win.cpp +++ b/tests/cefclient/cefclient_win.cpp @@ -16,6 +16,7 @@ #include "cefclient/binding_test.h" #include "cefclient/cefclient_osr_widget_win.h" #include "cefclient/client_handler.h" +#include "cefclient/client_switches.h" #include "cefclient/dialog_test.h" #include "cefclient/dom_test.h" #include "cefclient/performance_test.h" @@ -311,11 +312,15 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, AppGetBrowserSettings(settings); if (AppIsOffScreenRenderingEnabled()) { + CefRefPtr cmd_line = AppGetCommandLine(); + bool transparent = + cmd_line->HasSwitch(cefclient::kTransparentPaintingEnabled); + CefRefPtr osr_window = - OSRWindow::Create(&g_main_browser_provider, false); + OSRWindow::Create(&g_main_browser_provider, transparent); osr_window->CreateWidget(hWnd, rect, hInst, szOSRWindowClass); info.SetAsOffScreen(osr_window->hwnd()); - info.SetTransparentPainting(FALSE); + info.SetTransparentPainting(transparent ? TRUE : FALSE); g_handler->SetOSRHandler(osr_window.get()); } else { // Initialize window info to the defaults for a child window. @@ -458,6 +463,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, if (browser.get()) RunGeolocationTest(browser); return 0; + case ID_TESTS_TRANSPARENCY: // Test transparency + if (browser.get()) + RunTransparencyTest(browser); + return 0; case ID_TESTS_ZOOM_IN: if (browser.get()) ModifyZoom(browser, 0.5); diff --git a/tests/cefclient/client_handler.cpp b/tests/cefclient/client_handler.cpp index 3a4c426cb..48fddea3b 100644 --- a/tests/cefclient/client_handler.cpp +++ b/tests/cefclient/client_handler.cpp @@ -392,6 +392,12 @@ CefRefPtr ClientHandler::GetResourceHandler( GetBinaryResourceReader("localstorage.html"); ASSERT(stream.get()); return new CefStreamResourceHandler("text/html", stream); + } else if (url == "http://tests/transparency") { + // Show the transparency contents + CefRefPtr stream = + GetBinaryResourceReader("transparency.html"); + ASSERT(stream.get()); + return new CefStreamResourceHandler("text/html", stream); } else if (url == "http://tests/xmlhttprequest") { // Show the xmlhttprequest contents CefRefPtr stream = diff --git a/tests/cefclient/client_switches.cpp b/tests/cefclient/client_switches.cpp index d8d3bac3b..ed580aa4d 100644 --- a/tests/cefclient/client_switches.cpp +++ b/tests/cefclient/client_switches.cpp @@ -58,6 +58,7 @@ const char kAcceledated2dCanvasDisabled[] = "accelerated-2d-canvas-disabled"; const char kAcceleratedPluginsDisabled[] = "accelerated-plugins-disabled"; const char kDeveloperToolsDisabled[] = "developer-tools-disabled"; const char kOffScreenRenderingEnabled[] = "off-screen-rendering-enabled"; +const char kTransparentPaintingEnabled[] = "transparent-painting-enabled"; // Other attributes. const char kProxyType[] = "proxy-type"; diff --git a/tests/cefclient/client_switches.h b/tests/cefclient/client_switches.h index eb9d89a29..3ba64fd79 100644 --- a/tests/cefclient/client_switches.h +++ b/tests/cefclient/client_switches.h @@ -54,6 +54,7 @@ extern const char kAcceledated2dCanvasDisabled[]; extern const char kAcceleratedPluginsDisabled[]; extern const char kDeveloperToolsDisabled[]; extern const char kOffScreenRenderingEnabled[]; +extern const char kTransparentPaintingEnabled[]; // Other attributes. extern const char kProxyType[]; diff --git a/tests/cefclient/osrenderer.cpp b/tests/cefclient/osrenderer.cpp index 950d44f5d..a6f3409d3 100644 --- a/tests/cefclient/osrenderer.cpp +++ b/tests/cefclient/osrenderer.cpp @@ -3,7 +3,6 @@ // that can be found in the LICENSE file. #include "cefclient/osrenderer.h" -#include "cefclient/util.h" #if defined(OS_WIN) #include @@ -14,6 +13,8 @@ #error Platform is not supported. #endif +#include "cefclient/util.h" + #ifndef GL_BGR #define GL_BGR 0x80E0 #endif @@ -141,18 +142,41 @@ void ClientOSRenderer::Render() { void ClientOSRenderer::OnPopupShow(CefRefPtr browser, bool show) { if (!show) { - // Invalidate the previous popup rectangle so that it will be repainted. - browser->GetHost()->Invalidate(popup_rect_); - // Clear the popup rectangle. + CefRect popup_rect = popup_rect_; popup_rect_.Set(0, 0, 0, 0); + original_popup_rect_.Set(0, 0, 0, 0); + // Invalidate the previous popup rectangle so that it will be repainted. + browser->GetHost()->Invalidate(popup_rect, PET_VIEW); } } void ClientOSRenderer::OnPopupSize(CefRefPtr browser, const CefRect& rect) { - if (rect.width > 0 && rect.height > 0) - popup_rect_ = rect; + if (rect.width <= 0 || rect.height <= 0) + return; + original_popup_rect_ = rect; + popup_rect_ = GetPopupRectInWebView(original_popup_rect_); +} + +CefRect ClientOSRenderer::GetPopupRectInWebView(const CefRect& original_rect) { + CefRect rc(original_rect); + // if x or y are negative, move them to 0. + if (rc.x < 0) + rc.x = 0; + if (rc.y < 0) + rc.y = 0; + // if popup goes outside the view, try to reposition origin + if (rc.x + rc.width > view_width_) + rc.x = view_width_ - rc.width; + if (rc.y + rc.height > view_height_) + rc.y = view_height_ - rc.height; + // if x or y became negative, move them to 0 again. + if (rc.x < 0) + rc.x = 0; + if (rc.y < 0) + rc.y = 0; + return rc; } void ClientOSRenderer::OnPaint(CefRefPtr browser, @@ -204,8 +228,8 @@ void ClientOSRenderer::OnPaint(CefRefPtr browser, popup_rect_.height > 0) { int skip_pixels = 0, x = popup_rect_.x; int skip_rows = 0, y = popup_rect_.y; - int width = popup_rect_.width; - int height = popup_rect_.height; + int w = width; + int h = height; // Adjust the popup to fit inside the view. if (x < 0) { @@ -216,16 +240,16 @@ void ClientOSRenderer::OnPaint(CefRefPtr browser, skip_rows = -y; y = 0; } - if (x + width > view_width_) - width -= x + width - view_width_; - if (y + height > view_height_) - height -= y + height - view_height_; + if (x + w > view_width_) + w -= x + w - view_width_; + if (y + h > view_height_) + h -= y + h - view_height_; // Update the popup rectangle. - glPixelStorei(GL_UNPACK_ROW_LENGTH, popup_rect_.width); + glPixelStorei(GL_UNPACK_ROW_LENGTH, width); glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels); glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows); - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_BGRA, + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer); } diff --git a/tests/cefclient/osrenderer.h b/tests/cefclient/osrenderer.h index 1eecb6e1e..f549cf183 100644 --- a/tests/cefclient/osrenderer.h +++ b/tests/cefclient/osrenderer.h @@ -43,6 +43,11 @@ class ClientOSRenderer { int GetViewWidth() { return view_width_; } int GetViewHeight() { return view_height_; } + const CefRect& popup_rect() const { return popup_rect_; } + const CefRect& original_popup_rect() const { return original_popup_rect_; } + + CefRect GetPopupRectInWebView(const CefRect& original_rect); + private: bool transparent_; bool initialized_; @@ -50,6 +55,7 @@ class ClientOSRenderer { int view_width_; int view_height_; CefRect popup_rect_; + CefRect original_popup_rect_; float spin_x_; float spin_y_; }; diff --git a/tests/cefclient/res/transparency.html b/tests/cefclient/res/transparency.html new file mode 100644 index 000000000..a8dd3b46e --- /dev/null +++ b/tests/cefclient/res/transparency.html @@ -0,0 +1,63 @@ + + + +Transparency Examples + + + + +

Image Transparency

+Hover over an image to make it fully opaque.
+klematis +klematis + +

Block Transparency

+White 0% White 25% White 50% White 75% White 100% +
+Black 0% Black 25% Black 50% Black 75% Black 100% + + + diff --git a/tests/cefclient/resource.h b/tests/cefclient/resource.h index 45b60fe0b..cd4c924f9 100644 --- a/tests/cefclient/resource.h +++ b/tests/cefclient/resource.h @@ -48,15 +48,17 @@ #define ID_TESTS_BEGIN_TRACING 32780 #define ID_TESTS_END_TRACING 32781 #define ID_TESTS_PERFORMANCE 32782 +#define ID_TESTS_TRANSPARENCY 32783 #define IDC_STATIC -1 #define IDS_BINDING 1000 #define IDS_DIALOGS 1001 -#define IDS_LOGO 1002 -#define IDS_LOGOBALL 1003 -#define IDS_LOCALSTORAGE 1004 -#define IDS_XMLHTTPREQUEST 1005 -#define IDS_DOMACCESS 1006 -#define IDS_PERFORMANCE 1007 +#define IDS_DOMACCESS 1002 +#define IDS_LOCALSTORAGE 1003 +#define IDS_LOGO 1004 +#define IDS_LOGOBALL 1005 +#define IDS_PERFORMANCE 1006 +#define IDS_TRANSPARENCY 1007 +#define IDS_XMLHTTPREQUEST 1008 // Avoid files associated with MacOS #define _X86_ diff --git a/tests/cefclient/resource_util_win.cpp b/tests/cefclient/resource_util_win.cpp index 390484007..d6fa7b803 100644 --- a/tests/cefclient/resource_util_win.cpp +++ b/tests/cefclient/resource_util_win.cpp @@ -50,6 +50,7 @@ CefRefPtr GetBinaryResourceReader(const char* resource_name) { {"domaccess.html", IDS_DOMACCESS}, {"localstorage.html", IDS_LOCALSTORAGE}, {"performance.html", IDS_PERFORMANCE}, + {"transparency.html", IDS_TRANSPARENCY}, {"xmlhttprequest.html", IDS_XMLHTTPREQUEST}, }; diff --git a/tests/unittests/os_rendering_unittest.cc b/tests/unittests/os_rendering_unittest.cc index 74d9b87f7..7523eab19 100644 --- a/tests/unittests/os_rendering_unittest.cc +++ b/tests/unittests/os_rendering_unittest.cc @@ -17,16 +17,22 @@ const char kOsrHtml[] = " OSR Test " " " " " -" " -"

OSR Testing h1 - Focus and blur this page and will get this " -" red black

" +" " +"

OSR Testing h1 - Focus and blur " +" " +" this page and will get this red black

" "
    " "
  1. OnPaint should be called each time a page loads
  2. " "
  3. Move mouse " @@ -54,7 +60,7 @@ const char kOsrHtml[] = " " " "; -// #define(DEBUGGER_ATTACHED) +// #define DEBUGGER_ATTACHED // default osr widget size const int kOsrWidth = 600; @@ -78,6 +84,8 @@ const CefRect kExpectedRectLI[] = { // bounding client rects for edit box and navigate button const CefRect kEditBoxRect(412, 245, 153, 22); const CefRect kNavigateButtonRect(360, 271, 140, 22); +const CefRect kSelectRect(467, 22, 75, 20); +const CefRect kExpandedSelectRect(467, 42, 81, 322); const int kVerticalScrollbarWidth = GetSystemMetrics(SM_CXVSCROLL); const int kHorizontalScrollbarWidth = GetSystemMetrics(SM_CXHSCROLL); @@ -109,6 +117,8 @@ enum OSRTestType { OSR_TEST_FOCUS, // loading webview should trigger a full paint (L01) OSR_TEST_PAINT, + // same as OSR_TEST_PAINT but with alpha values + OSR_TEST_TRANSPARENCY, // moving mouse over L02, OnCursorChange will be called OSR_TEST_CURSOR, // moving mouse on L03, OnPaint will be called for its bounding rectangle @@ -131,6 +141,22 @@ enum OSRTestType { OSR_TEST_TOOLTIP, // mouse wheel will trigger a scroll event OSR_TEST_SCROLLING, + // clicking on dropdown box, PET_POPUP OnPaint is triggered + OSR_TEST_POPUP_PAINT, + // clicking on dropdown box, a popup will show up + OSR_TEST_POPUP_SHOW, + // clicking on dropdown box, OnPopupSize should be called + OSR_TEST_POPUP_SIZE, + // taking focus away from the webview, will close popup + OSR_TEST_POPUP_HIDE_ON_BLUR, + // clicking outside the popup widget will close popup + OSR_TEST_POPUP_HIDE_ON_CLICK, + // scrolling outside the popup widget will close popup + OSR_TEST_POPUP_HIDE_ON_SCROLL, + // pressing ESC will close popup + OSR_TEST_POPUP_HIDE_ON_ESC, + // scrolling inside the popup should trigger repaint for popup area + OSR_TEST_POPUP_SCROLL_INSIDE, }; // Used in the browser process. @@ -213,14 +239,38 @@ class OSRTestHandler : public TestHandler, virtual void OnPopupShow(CefRefPtr browser, bool show) OVERRIDE { - // popup widgets are not yet supported - EXPECT_FALSE("OnPopupShow should not be reached"); + if (show && started()) { + switch (test_type_) { + case OSR_TEST_POPUP_SHOW: + if (!succeeded()) { + EXPECT_TRUE(show); + DestroySucceededTestSoon(); + } + break; + } + } + if (!show && started()) { + switch (test_type_) { + case OSR_TEST_POPUP_HIDE_ON_BLUR: + case OSR_TEST_POPUP_HIDE_ON_CLICK: + case OSR_TEST_POPUP_HIDE_ON_ESC: + case OSR_TEST_POPUP_HIDE_ON_SCROLL: + DestroySucceededTestSoon(); + break; + } + } } virtual void OnPopupSize(CefRefPtr browser, const CefRect& rect) OVERRIDE { - // popup widgets are not yet supported - EXPECT_FALSE("OnPopupSize should not be reached"); + if (started()) { + switch (test_type_) { + case OSR_TEST_POPUP_SIZE: + EXPECT_EQ(kExpandedSelectRect, rect); + DestroySucceededTestSoon(); + break; + } + } } virtual void OnPaint(CefRefPtr browser, @@ -229,21 +279,23 @@ class OSRTestHandler : public TestHandler, const void* buffer, int width, int height) OVERRIDE { // bitmap must as big as GetViewRect said - if (test_type_ != OSR_TEST_RESIZE || !started()) { + if (test_type_ != OSR_TEST_RESIZE && type == PET_VIEW) { EXPECT_EQ(kOsrWidth, width); EXPECT_EQ(kOsrHeight, height); + } else if (type == PET_POPUP) { + EXPECT_EQ(kExpandedSelectRect.width, width); + EXPECT_EQ(kExpandedSelectRect.height, height); } EXPECT_TRUE(browser->GetHost()->IsWindowRenderingDisabled()); - // We don't support popup widgets yet - EXPECT_EQ(type, PET_VIEW); - // start test only when painting something else then background if (IsBackgroundInBuffer(reinterpret_cast(buffer), - width * height, RGB(255, 255, 255))) { + width * height, + test_type_ == OSR_TEST_TRANSPARENCY ? + 0x00000000 : + 0xFFFFFFFF)) return; - } // Send events after the first full repaint switch (test_type_) { @@ -251,6 +303,14 @@ class OSRTestHandler : public TestHandler, // test that we have a full repaint EXPECT_EQ(dirtyRects.size(), 1); EXPECT_TRUE(IsFullRepaint(dirtyRects[0])); + EXPECT_EQ(*(reinterpret_cast(buffer)), 0xffff8080); + DestroySucceededTestSoon(); + break; + case OSR_TEST_TRANSPARENCY: + // test that we have a full repaint + EXPECT_EQ(dirtyRects.size(), 1); + EXPECT_TRUE(IsFullRepaint(dirtyRects[0])); + EXPECT_EQ(*(reinterpret_cast(buffer)), 0x7f7f0000); DestroySucceededTestSoon(); break; case OSR_TEST_FOCUS: @@ -266,16 +326,24 @@ class OSRTestHandler : public TestHandler, case OSR_TEST_CURSOR: if (StartTest()) { // make mouse leave first - browser->GetHost()->SendMouseMoveEvent(0, 0, true); + CefMouseEvent mouse_event; + mouse_event.x = 0; + mouse_event.y = 0; + mouse_event.modifiers = 0; + browser->GetHost()->SendMouseMoveEvent(mouse_event, true); // enter mouse in the LI2 element having hand cursor - browser->GetHost()->SendMouseMoveEvent(MiddleX(ExpectedRect(2)), - MiddleY(ExpectedRect(2)), false); + mouse_event.x = MiddleX(ExpectedRect(2)); + mouse_event.y = MiddleY(ExpectedRect(2)); + browser->GetHost()->SendMouseMoveEvent(mouse_event, false); } break; case OSR_TEST_MOUSE_MOVE: if (StartTest()) { - browser->GetHost()->SendMouseMoveEvent(MiddleX(ExpectedRect(3)), - MiddleY(ExpectedRect(3)), false); + CefMouseEvent mouse_event; + mouse_event.x = MiddleX(ExpectedRect(3)); + mouse_event.y = MiddleY(ExpectedRect(3)); + mouse_event.modifiers = 0; + browser->GetHost()->SendMouseMoveEvent(mouse_event, false); } else { EXPECT_EQ(dirtyRects.size(), 1); EXPECT_EQ(dirtyRects[0], ExpectedRect(3)); @@ -285,18 +353,26 @@ class OSRTestHandler : public TestHandler, case OSR_TEST_CLICK_RIGHT: case OSR_TEST_SCREEN_POINT: if (StartTest()) { - browser->GetHost()->SendMouseClickEvent(MiddleX(ExpectedRect(4)), - MiddleY(ExpectedRect(4)), MBT_RIGHT, false, 1); - browser->GetHost()->SendMouseClickEvent(MiddleX(ExpectedRect(4)), - MiddleY(ExpectedRect(4)), MBT_RIGHT, true, 1); + CefMouseEvent mouse_event; + mouse_event.x = MiddleX(ExpectedRect(4)); + mouse_event.y = MiddleY(ExpectedRect(4)); + mouse_event.modifiers = 0; + browser->GetHost()->SendMouseClickEvent( + mouse_event, MBT_RIGHT, false, 1); + browser->GetHost()->SendMouseClickEvent( + mouse_event, MBT_RIGHT, true, 1); } break; case OSR_TEST_CLICK_LEFT: if (StartTest()) { - browser->GetHost()->SendMouseClickEvent(MiddleX(kEditBoxRect), - MiddleY(kEditBoxRect), MBT_LEFT, false, 1); - browser->GetHost()->SendMouseClickEvent(MiddleX(kEditBoxRect), - MiddleY(kEditBoxRect), MBT_LEFT, true, 1); + CefMouseEvent mouse_event; + mouse_event.x = MiddleX(kEditBoxRect); + mouse_event.y = MiddleY(kEditBoxRect); + mouse_event.modifiers = 0; + browser->GetHost()->SendMouseClickEvent( + mouse_event, MBT_LEFT, false, 1); + browser->GetHost()->SendMouseClickEvent( + mouse_event, MBT_LEFT, true, 1); } else { EXPECT_EQ(dirtyRects.size(), 1); EXPECT_EQ(dirtyRects[0], kEditBoxRect); @@ -305,10 +381,14 @@ class OSRTestHandler : public TestHandler, break; case OSR_TEST_CLICK_MIDDLE: if (StartTest()) { - browser->GetHost()->SendMouseClickEvent(MiddleX(ExpectedRect(0)), - MiddleY(ExpectedRect(0)), MBT_MIDDLE, false, 1); - browser->GetHost()->SendMouseClickEvent(MiddleX(ExpectedRect(0)), - MiddleY(ExpectedRect(0)), MBT_MIDDLE, true, 1); + CefMouseEvent mouse_event; + mouse_event.x = MiddleX(ExpectedRect(0)); + mouse_event.y = MiddleY(ExpectedRect(0)); + mouse_event.modifiers = 0; + browser->GetHost()->SendMouseClickEvent( + mouse_event, MBT_MIDDLE, false, 1); + browser->GetHost()->SendMouseClickEvent( + mouse_event, MBT_MIDDLE, true, 1); } else { EXPECT_EQ(dirtyRects.size(), 1); CefRect expectedRect( @@ -335,7 +415,7 @@ class OSRTestHandler : public TestHandler, static const CefRect invalidate_rect(0, 0, 1, 1); if (StartTest()) { invalidating = true; - browser->GetHost()->Invalidate(invalidate_rect); + browser->GetHost()->Invalidate(invalidate_rect, PET_VIEW); invalidating = false; } else { EXPECT_TRUE(invalidating); @@ -348,14 +428,19 @@ class OSRTestHandler : public TestHandler, case OSR_TEST_KEY_EVENTS: if (StartTest()) { // click inside edit box - browser->GetHost()->SendMouseClickEvent(MiddleX(kEditBoxRect), - MiddleY(kEditBoxRect), MBT_LEFT, false, 1); - browser->GetHost()->SendMouseClickEvent(MiddleX(kEditBoxRect), - MiddleY(kEditBoxRect), MBT_LEFT, true, 1); + CefMouseEvent mouse_event; + mouse_event.x = MiddleX(kEditBoxRect); + mouse_event.y = MiddleY(kEditBoxRect); + mouse_event.modifiers = 0; + browser->GetHost()->SendMouseClickEvent( + mouse_event, MBT_LEFT, false, 1); + browser->GetHost()->SendMouseClickEvent( + mouse_event, MBT_LEFT, true, 1); // write "done" word CefKeyEvent event; event.is_system_key = false; + event.modifiers = 0; size_t word_lenght = strlen(kKeyTestWord); for (size_t i = 0; i < word_lenght; ++i) { @@ -376,24 +461,32 @@ class OSRTestHandler : public TestHandler, browser->GetHost()->SendKeyEvent(event); } // click button to navigate - browser->GetHost()->SendMouseClickEvent(MiddleX(kNavigateButtonRect), - MiddleY(kNavigateButtonRect), MBT_LEFT, false, 1); - browser->GetHost()->SendMouseClickEvent(MiddleX(kNavigateButtonRect), - MiddleY(kNavigateButtonRect), MBT_LEFT, true, 1); + mouse_event.x = MiddleX(kNavigateButtonRect); + mouse_event.y = MiddleY(kNavigateButtonRect); + browser->GetHost()->SendMouseClickEvent( + mouse_event, MBT_LEFT, false, 1); + browser->GetHost()->SendMouseClickEvent( + mouse_event, MBT_LEFT, true, 1); } break; case OSR_TEST_TOOLTIP: if (StartTest()) { - browser->GetHost()->SendMouseMoveEvent(MiddleX(ExpectedRect(10)), - MiddleY(ExpectedRect(10)), false); + CefMouseEvent mouse_event; + mouse_event.x = MiddleX(ExpectedRect(10)); + mouse_event.y = MiddleY(ExpectedRect(10)); + mouse_event.modifiers = 0; + browser->GetHost()->SendMouseMoveEvent(mouse_event, false); } break; case OSR_TEST_SCROLLING: { static const int deltaY = 10; if (StartTest()) { // scroll down once - browser->GetHost()->SendMouseWheelEvent(MiddleX(ExpectedRect(0)), - MiddleY(ExpectedRect(0)), 0, - deltaY); + CefMouseEvent mouse_event; + mouse_event.x = MiddleX(ExpectedRect(0)); + mouse_event.y = MiddleY(ExpectedRect(0)); + mouse_event.modifiers = 0; + browser->GetHost()->SendMouseWheelEvent(mouse_event, 0, - deltaY); } else { // there should be 3 update areas: // 1) vertical scrollbar @@ -412,6 +505,99 @@ class OSRTestHandler : public TestHandler, } break; } + case OSR_TEST_POPUP_HIDE_ON_CLICK: + if (StartTest()) { + ExpandDropDown(); + // Wait for the first popup paint to occur + } else if (type == PET_POPUP) { + CefMouseEvent mouse_event; + mouse_event.x = 1; + mouse_event.y = 1; + mouse_event.modifiers = 0; + browser->GetHost()->SendMouseClickEvent( + mouse_event, MBT_LEFT, false, 1); + } + break; + case OSR_TEST_POPUP_HIDE_ON_SCROLL: + if (StartTest()) { + ExpandDropDown(); + // Wait for the first popup paint to occur + } else if (type == PET_POPUP) { + CefMouseEvent mouse_event; + mouse_event.x = mouse_event.y = 1; + mouse_event.modifiers = 0; + browser->GetHost()->SendMouseWheelEvent(mouse_event, 0, -10); + } + break; + case OSR_TEST_POPUP_HIDE_ON_BLUR: + if (StartTest()) { + ExpandDropDown(); + // Wait for the first popup paint to occur + } else if (type == PET_POPUP) { + browser->GetHost()->SendFocusEvent(false); + } + break; + case OSR_TEST_POPUP_HIDE_ON_ESC: + if (StartTest()) { + ExpandDropDown(); + // Wait for the first popup paint to occur + } else if (type == PET_POPUP) { + CefKeyEvent event; + event.is_system_key = false; + BYTE VkCode = LOBYTE(VK_ESCAPE); + UINT scanCode = MapVirtualKey(VkCode, MAPVK_VK_TO_VSC); + event.native_key_code = (scanCode << 16) | // key scan code + 1; // key repeat count + event.windows_key_code = VkCode; + event.type = KEYEVENT_CHAR; + browser->GetHost()->SendKeyEvent(event); + } + break; + case OSR_TEST_POPUP_SHOW: + case OSR_TEST_POPUP_SIZE: + if (StartTest()) { + ExpandDropDown(); + } + break; + case OSR_TEST_POPUP_PAINT: + if (StartTest()) { + ExpandDropDown(); + } else if (type == PET_POPUP) { + EXPECT_EQ(dirtyRects.size(), 1); + EXPECT_EQ(dirtyRects[0], + CefRect(0, 0, + kExpandedSelectRect.width, + kExpandedSelectRect.height)); + // first pixel of border + EXPECT_EQ(*(reinterpret_cast(buffer)), 0xff7f9db9); + EXPECT_EQ(kExpandedSelectRect.width, width); + EXPECT_EQ(kExpandedSelectRect.height, height); + DestroySucceededTestSoon(); + } + break; + case OSR_TEST_POPUP_SCROLL_INSIDE: + static enum {NotStarted, Started, Scrolled} + scroll_inside_state = NotStarted; + if (StartTest()) { + ExpandDropDown(); + scroll_inside_state = Started; + } else if (type == PET_POPUP) { + if (scroll_inside_state == Started) { + CefMouseEvent mouse_event; + mouse_event.x = MiddleX(kExpandedSelectRect); + mouse_event.y = MiddleY(kExpandedSelectRect); + mouse_event.modifiers = 0; + browser->GetHost()->SendMouseWheelEvent(mouse_event, 0, -10); + scroll_inside_state = Scrolled; + } else if (scroll_inside_state == Scrolled) { + EXPECT_EQ(dirtyRects.size(), 1); + // border is not redrawn + EXPECT_EQ(dirtyRects[0], CefRect(1, 1, + kExpandedSelectRect.width - 3, + kExpandedSelectRect.height - 2)); + DestroySucceededTestSoon(); + } + } } } @@ -447,6 +633,8 @@ class OSRTestHandler : public TestHandler, CefWindowInfo windowInfo; CefBrowserSettings settings; windowInfo.SetAsOffScreen(GetDesktopWindow()); + if (test_type_ == OSR_TEST_TRANSPARENCY) + windowInfo.SetTransparentPainting(TRUE); CefBrowserHost::CreateBrowser(windowInfo, this, url, settings); } @@ -475,10 +663,20 @@ class OSRTestHandler : public TestHandler, void DestroySucceededTestSoon() { succeeded_ = true; - CefPostTask(TID_IO, NewCefRunnableMethod(this, + CefPostTask(TID_UI, NewCefRunnableMethod(this, &OSRTestHandler::DestroyTest)); } + void ExpandDropDown() { + GetBrowser()->GetHost()->SendFocusEvent(true); + CefMouseEvent mouse_event; + mouse_event.x = MiddleX(kSelectRect); + mouse_event.y = MiddleY(kSelectRect); + mouse_event.modifiers = 0; + GetBrowser()->GetHost()->SendMouseClickEvent( + mouse_event, MBT_LEFT, false, 1); + } + // true if the events for this test are already sent bool started() { return started_; } @@ -517,6 +715,7 @@ TEST(OSRTest, name) {\ OSR_TEST(Windowless, OSR_TEST_IS_WINDOWLESS); OSR_TEST(Focus, OSR_TEST_FOCUS); OSR_TEST(Paint, OSR_TEST_PAINT); +OSR_TEST(TransparentPaint, OSR_TEST_TRANSPARENCY); OSR_TEST(Cursor, OSR_TEST_CURSOR); OSR_TEST(MouseMove, OSR_TEST_MOUSE_MOVE); OSR_TEST(MouseRightClick, OSR_TEST_CLICK_RIGHT); @@ -528,3 +727,11 @@ OSR_TEST(Invalidate, OSR_TEST_INVALIDATE); OSR_TEST(KeyEvents, OSR_TEST_KEY_EVENTS); OSR_TEST(Tooltip, OSR_TEST_TOOLTIP); OSR_TEST(Scrolling, OSR_TEST_SCROLLING); +OSR_TEST(PopupPaint, OSR_TEST_POPUP_PAINT); +OSR_TEST(PopupShow, OSR_TEST_POPUP_SHOW); +OSR_TEST(PopupSize, OSR_TEST_POPUP_SIZE); +OSR_TEST(PopupHideOnBlur, OSR_TEST_POPUP_HIDE_ON_BLUR); +OSR_TEST(PopupHideOnClick, OSR_TEST_POPUP_HIDE_ON_CLICK); +OSR_TEST(PopupHideOnScroll, OSR_TEST_POPUP_HIDE_ON_SCROLL); +OSR_TEST(PopupHideOnEsc, OSR_TEST_POPUP_HIDE_ON_ESC); +OSR_TEST(PopupScrollInside, OSR_TEST_POPUP_SCROLL_INSIDE);