minor fixes and enable datalist elements in OSR

This commit is contained in:
Heilig Benedek 2017-05-21 19:55:19 +02:00
parent a95d6b997b
commit 218e28b136
12 changed files with 402 additions and 58 deletions

View file

@ -4,6 +4,7 @@
#include "atom/browser/osr/osr_render_widget_host_view.h"
#include <algorithm>
#include <vector>
#include "base/callback_helpers.h"
@ -22,9 +23,12 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/context_factory.h"
#include "media/base/video_frame.h"
#include "third_party/WebKit/public/platform/WebInputEvent.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_type.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/event_constants.h"
#include "ui/events/latency_info.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/native_widget_types.h"
@ -37,6 +41,70 @@ namespace {
const float kDefaultScaleFactor = 1.0;
const int kFrameRetryLimit = 2;
ui::MouseEvent UiMouseEventFromWebMouseEvent(blink::WebMouseEvent event) {
ui::EventType type = ui::EventType::ET_UNKNOWN;
switch (event.type()) {
case blink::WebInputEvent::MouseDown:
type = ui::EventType::ET_MOUSE_PRESSED;
break;
case blink::WebInputEvent::MouseUp:
type = ui::EventType::ET_MOUSE_RELEASED;
break;
case blink::WebInputEvent::MouseMove:
type = ui::EventType::ET_MOUSE_MOVED;
break;
case blink::WebInputEvent::MouseEnter:
type = ui::EventType::ET_MOUSE_ENTERED;
break;
case blink::WebInputEvent::MouseLeave:
type = ui::EventType::ET_MOUSE_EXITED;
break;
case blink::WebInputEvent::MouseWheel:
type = ui::EventType::ET_MOUSEWHEEL;
break;
default:
type = ui::EventType::ET_UNKNOWN;
break;
}
int button_flags = 0;
switch (event.button) {
case blink::WebMouseEvent::Button::X1:
button_flags |= ui::EventFlags::EF_BACK_MOUSE_BUTTON;
break;
case blink::WebMouseEvent::Button::X2:
button_flags |= ui::EventFlags::EF_FORWARD_MOUSE_BUTTON;
break;
case blink::WebMouseEvent::Button::Left:
button_flags |= ui::EventFlags::EF_LEFT_MOUSE_BUTTON;
break;
case blink::WebMouseEvent::Button::Middle:
button_flags |= ui::EventFlags::EF_MIDDLE_MOUSE_BUTTON;
break;
case blink::WebMouseEvent::Button::Right:
button_flags |= ui::EventFlags::EF_RIGHT_MOUSE_BUTTON;
break;
default:
button_flags = 0;
break;
}
ui::MouseEvent ui_event(type,
gfx::Point(std::floor(event.x), std::floor(event.y)),
gfx::Point(std::floor(event.x), std::floor(event.y)),
ui::EventTimeForNow(),
button_flags, button_flags);
ui_event.SetClickCount(event.clickCount);
return ui_event;
}
ui::MouseWheelEvent UiMouseWheelEventFromWebMouseEvent(
blink::WebMouseWheelEvent event) {
return ui::MouseWheelEvent(UiMouseEventFromWebMouseEvent(event),
std::floor(event.deltaX), std::floor(event.deltaY));
}
#if !defined(OS_MACOSX)
const int kResizeLockTimeoutMs = 67;
@ -619,6 +687,8 @@ void OffScreenRenderWidgetHostView::Destroy() {
child_host_view_->CancelWidget();
for (auto guest_host_view : guest_host_views_)
guest_host_view->CancelWidget();
for (auto proxy_view : proxy_views_)
proxy_view->RemoveObserver();
Hide();
}
}
@ -835,6 +905,22 @@ void OffScreenRenderWidgetHostView::RemoveGuestHostView(
guest_host_views_.erase(guest_host);
}
void OffScreenRenderWidgetHostView::AddViewProxy(OffscreenViewProxy* proxy) {
proxy->SetObserver(this);
proxy_views_.insert(proxy);
}
void OffScreenRenderWidgetHostView::RemoveViewProxy(OffscreenViewProxy* proxy) {
proxy->RemoveObserver();
proxy_views_.erase(proxy);
}
void OffScreenRenderWidgetHostView::ProxyViewDestroyed(
OffscreenViewProxy* proxy) {
proxy_views_.erase(proxy);
Invalidate();
}
void OffScreenRenderWidgetHostView::RegisterGuestViewFrameSwappedCallback(
content::RenderWidgetHostViewGuest* guest_host_view) {
guest_host_view->RegisterFrameSwappedCallback(base::MakeUnique<base::Closure>(
@ -906,12 +992,16 @@ void CopyBitmapTo(
char* dest = static_cast<char*>(destination.getPixels());
int pixelsize = source.bytesPerPixel();
if (pos.x() + pos.width() <= destination.width() &&
pos.y() + pos.height() <= destination.height()) {
for (int i = 0; i < pos.height(); i++) {
int width = pos.x() + pos.width() <= destination.width() ? pos.width()
: pos.width() - ((pos.x() + pos.width()) - destination.width());
int height = pos.y() + pos.height() <= destination.height() ? pos.height()
: pos.height() - ((pos.y() + pos.height()) - destination.height());
if (width > 0 && height > 0) {
for (int i = 0; i < height; i++) {
memcpy(dest + ((pos.y() + i) * destination.width() + pos.x()) * pixelsize,
src + (i * source.width()) * pixelsize,
pos.width() * pixelsize);
width * pixelsize);
}
}
@ -926,19 +1016,41 @@ void OffScreenRenderWidgetHostView::OnPaint(
if (parent_callback_) {
parent_callback_.Run(damage_rect, bitmap);
} else if (popup_host_view_ && popup_bitmap_.get()) {
gfx::Rect pos = popup_host_view_->popup_position_;
gfx::Rect damage(damage_rect);
damage.Union(pos);
SkBitmap copy = SkBitmapOperations::CreateTiledBitmap(bitmap,
pos.x(), pos.y(), pos.width(), pos.height());
CopyBitmapTo(bitmap, *popup_bitmap_, pos);
callback_.Run(damage, bitmap);
CopyBitmapTo(bitmap, copy, pos);
} else {
callback_.Run(damage_rect, bitmap);
gfx::Rect damage(damage_rect);
std::vector<gfx::Rect> damages;
std::vector<const SkBitmap*> bitmaps;
std::vector<SkBitmap> originals;
if (popup_host_view_ && popup_bitmap_.get()) {
gfx::Rect pos = popup_host_view_->popup_position_;
damage.Union(pos);
damages.push_back(pos);
bitmaps.push_back(popup_bitmap_.get());
originals.push_back(SkBitmapOperations::CreateTiledBitmap(bitmap,
pos.x(), pos.y(), pos.width(), pos.height()));
}
for (auto proxy_view : proxy_views_) {
gfx::Rect pos = proxy_view->GetBounds();
damage.Union(pos);
damages.push_back(pos);
bitmaps.push_back(proxy_view->GetBitmap());
originals.push_back(SkBitmapOperations::CreateTiledBitmap(bitmap,
pos.x(), pos.y(), pos.width(), pos.height()));
}
for (int i = 0; i < damages.size(); i++) {
CopyBitmapTo(bitmap, *(bitmaps[i]), damages[i]);
}
damage.Intersect(GetViewBounds());
callback_.Run(damage, bitmap);
for (int i = 0; i < damages.size(); i++) {
CopyBitmapTo(bitmap, originals[i], damages[i]);
}
}
ReleaseResize();
@ -951,6 +1063,11 @@ void OffScreenRenderWidgetHostView::OnPopupPaint(
InvalidateBounds(popup_host_view_->popup_position_);
}
void OffScreenRenderWidgetHostView::OnProxyViewPaint(
const gfx::Rect& damage_rect) {
InvalidateBounds(damage_rect);
}
void OffScreenRenderWidgetHostView::HoldResize() {
if (!hold_resize_)
hold_resize_ = true;
@ -992,6 +1109,21 @@ void OffScreenRenderWidgetHostView::ProcessKeyboardEvent(
void OffScreenRenderWidgetHostView::ProcessMouseEvent(
const blink::WebMouseEvent& event,
const ui::LatencyInfo& latency) {
for (auto proxy_view : proxy_views_) {
gfx::Rect bounds = proxy_view->GetBounds();
if (bounds.Contains(event.x, event.y)) {
blink::WebMouseEvent proxy_event(event);
proxy_event.x -= bounds.x();
proxy_event.y -= bounds.y();
proxy_event.windowX = proxy_event.x;
proxy_event.windowY = proxy_event.y;
ui::MouseEvent ui_event = UiMouseEventFromWebMouseEvent(proxy_event);
proxy_view->OnEvent(&ui_event);
return;
}
}
if (!IsPopupWidget()) {
if (popup_host_view_ &&
popup_host_view_->popup_position_.Contains(event.x, event.y)) {
@ -1005,6 +1137,7 @@ void OffScreenRenderWidgetHostView::ProcessMouseEvent(
return;
}
}
if (!render_widget_host_)
return;
render_widget_host_->ForwardMouseEvent(event);
@ -1013,6 +1146,21 @@ void OffScreenRenderWidgetHostView::ProcessMouseEvent(
void OffScreenRenderWidgetHostView::ProcessMouseWheelEvent(
const blink::WebMouseWheelEvent& event,
const ui::LatencyInfo& latency) {
for (auto proxy_view : proxy_views_) {
gfx::Rect bounds = proxy_view->GetBounds();
if (bounds.Contains(event.x, event.y)) {
blink::WebMouseWheelEvent proxy_event(event);
proxy_event.x -= bounds.x();
proxy_event.y -= bounds.y();
proxy_event.windowX = proxy_event.x;
proxy_event.windowY = proxy_event.y;
ui::MouseWheelEvent ui_event =
UiMouseWheelEventFromWebMouseEvent(proxy_event);
proxy_view->OnEvent(&ui_event);
return;
}
}
if (!IsPopupWidget()) {
if (popup_host_view_) {
if (popup_host_view_->popup_position_.Contains(event.x, event.y)) {

View file

@ -16,6 +16,7 @@
#include "atom/browser/native_window.h"
#include "atom/browser/native_window_observer.h"
#include "atom/browser/osr/osr_output_device.h"
#include "atom/browser/osr/osr_view_proxy.h"
#include "base/process/kill.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
@ -68,7 +69,8 @@ class OffScreenRenderWidgetHostView
#if !defined(OS_MACOSX)
public content::DelegatedFrameHostClient,
#endif
public NativeWindowObserver {
public NativeWindowObserver,
public OffscreenViewProxyObserver {
public:
OffScreenRenderWidgetHostView(bool transparent,
const OnPaintCallback& callback,
@ -208,6 +210,9 @@ class OffScreenRenderWidgetHostView
void CancelWidget();
void AddGuestHostView(OffScreenRenderWidgetHostView* guest_host);
void RemoveGuestHostView(OffScreenRenderWidgetHostView* guest_host);
void AddViewProxy(OffscreenViewProxy* proxy);
void RemoveViewProxy(OffscreenViewProxy* proxy);
void ProxyViewDestroyed(OffscreenViewProxy* proxy);
void RegisterGuestViewFrameSwappedCallback(
content::RenderWidgetHostViewGuest* guest_host_view);
@ -216,6 +221,7 @@ class OffScreenRenderWidgetHostView
void OnPaint(const gfx::Rect& damage_rect, const SkBitmap& bitmap);
void OnPopupPaint(const gfx::Rect& damage_rect, const SkBitmap& bitmap);
void OnProxyViewPaint(const gfx::Rect& damage_rect);
bool IsPopupWidget() const {
return popup_type_ != blink::WebPopupTypeNone;
@ -273,6 +279,7 @@ class OffScreenRenderWidgetHostView
std::unique_ptr<SkBitmap> popup_bitmap_;
OffScreenRenderWidgetHostView* child_host_view_;
std::set<OffScreenRenderWidgetHostView*> guest_host_views_;
std::set<OffscreenViewProxy*> proxy_views_;
NativeWindow* native_window_;
OffScreenOutputDevice* software_output_device_;

View file

@ -0,0 +1,58 @@
// Copyright (c) 2017 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/osr/osr_view_proxy.h"
namespace atom {
OffscreenViewProxy::OffscreenViewProxy(views::View* view)
: view_(view), observer_(nullptr) {
view_bitmap_.reset(new SkBitmap);
}
OffscreenViewProxy::~OffscreenViewProxy() {
if (observer_) {
observer_->ProxyViewDestroyed(this);
}
}
void OffscreenViewProxy::SetObserver(OffscreenViewProxyObserver* observer) {
if (observer_) {
observer_->ProxyViewDestroyed(this);
}
observer_ = observer;
}
void OffscreenViewProxy::RemoveObserver() {
observer_ = nullptr;
}
const SkBitmap* OffscreenViewProxy::GetBitmap() const {
return view_bitmap_.get();
}
void OffscreenViewProxy::SetBitmap(const SkBitmap& bitmap) {
if (view_bounds_.width() == bitmap.width() &&
view_bounds_.height() == bitmap.height() &&
observer_) {
view_bitmap_.reset(new SkBitmap(bitmap));
observer_->OnProxyViewPaint(view_bounds_);
}
}
const gfx::Rect& OffscreenViewProxy::GetBounds() {
return view_bounds_;
}
void OffscreenViewProxy::SetBounds(const gfx::Rect& bounds) {
view_bounds_ = bounds;
}
void OffscreenViewProxy::OnEvent(ui::Event* event) {
if (view_) {
view_->OnEvent(event);
}
}
} // namespace atom

View file

@ -0,0 +1,53 @@
// Copyright (c) 2017 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_OSR_OSR_VIEW_PROXY_H_
#define ATOM_BROWSER_OSR_OSR_VIEW_PROXY_H_
#include <set>
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/events/event.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/view.h"
namespace atom {
class OffscreenViewProxy;
class OffscreenViewProxyObserver {
public:
virtual void OnProxyViewPaint(const gfx::Rect& damage_rect) = 0;
virtual void ProxyViewDestroyed(OffscreenViewProxy* proxy) = 0;
};
class OffscreenViewProxy {
public:
explicit OffscreenViewProxy(views::View* view);
~OffscreenViewProxy();
void SetObserver(OffscreenViewProxyObserver* observer);
void RemoveObserver();
const SkBitmap* GetBitmap() const;
void SetBitmap(const SkBitmap& bitmap);
const gfx::Rect& GetBounds();
void SetBounds(const gfx::Rect& bounds);
void OnEvent(ui::Event* event);
void ResetView() { view_ = nullptr; }
private:
views::View* view_;
gfx::Rect view_bounds_;
std::unique_ptr<SkBitmap> view_bitmap_;
OffscreenViewProxyObserver* observer_;
};
} // namespace atom
#endif // ATOM_BROWSER_OSR_OSR_VIEW_PROXY_H_