Merge pull request #9535 from brenca/datalist-element

Add datalist element support
This commit is contained in:
Cheng Zhao 2017-05-29 16:01:40 +09:00 committed by GitHub
commit 7d994f2a9e
22 changed files with 1704 additions and 55 deletions

View file

@ -982,6 +982,23 @@ bool WebContents::OnMessageReceived(const IPC::Message& message) {
return handled;
}
bool WebContents::OnMessageReceived(const IPC::Message& message,
content::RenderFrameHost* frame_host) {
bool handled = true;
auto relay = NativeWindowRelay::FromWebContents(web_contents());
if (!relay)
return false;
IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(NativeWindow, message, frame_host)
IPC_MESSAGE_FORWARD(AtomAutofillFrameHostMsg_ShowPopup,
relay->window.get(), NativeWindow::ShowAutofillPopup)
IPC_MESSAGE_FORWARD(AtomAutofillFrameHostMsg_HidePopup,
relay->window.get(), NativeWindow::HideAutofillPopup)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
// There are three ways of destroying a webContents:
// 1. call webContents.destroy();
// 2. garbage collection;
@ -1621,6 +1638,10 @@ bool WebContents::IsOffScreen() const {
return type_ == OFF_SCREEN;
}
bool WebContents::IsOffScreenOrEmbedderOffscreen() const {
return IsOffScreen() || (embedder_ && embedder_->IsOffScreen());
}
void WebContents::OnPaint(const gfx::Rect& dirty_rect, const SkBitmap& bitmap) {
Emit("paint", dirty_rect, gfx::Image::CreateFrom1xBitmap(bitmap));
}

View file

@ -12,6 +12,7 @@
#include "atom/browser/api/save_page_handler.h"
#include "atom/browser/api/trackable_object.h"
#include "atom/browser/common_web_contents_delegate.h"
#include "atom/browser/ui/autofill_popup.h"
#include "content/common/cursors/webcursor.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
@ -180,6 +181,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
// Methods for offscreen rendering
bool IsOffScreen() const;
bool IsOffScreenOrEmbedderOffscreen() const;
void OnPaint(const gfx::Rect& dirty_rect, const SkBitmap& bitmap);
void StartPainting();
void StopPainting();
@ -329,6 +331,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override;
bool OnMessageReceived(const IPC::Message& message) override;
bool OnMessageReceived(const IPC::Message& message,
content::RenderFrameHost* frame_host) override;
void WebContentsDestroyed() override;
void NavigationEntryCommitted(
const content::LoadCommittedDetails& load_details) override;

View file

@ -251,7 +251,7 @@ void NativeWindow::SetSizeConstraints(
SetContentSizeConstraints(content_constraints);
}
extensions::SizeConstraints NativeWindow::GetSizeConstraints() {
extensions::SizeConstraints NativeWindow::GetSizeConstraints() const {
extensions::SizeConstraints content_constraints = GetContentSizeConstraints();
extensions::SizeConstraints window_constraints;
if (content_constraints.HasMaximumSize()) {
@ -272,7 +272,7 @@ void NativeWindow::SetContentSizeConstraints(
size_constraints_ = size_constraints;
}
extensions::SizeConstraints NativeWindow::GetContentSizeConstraints() {
extensions::SizeConstraints NativeWindow::GetContentSizeConstraints() const {
return size_constraints_;
}
@ -282,7 +282,7 @@ void NativeWindow::SetMinimumSize(const gfx::Size& size) {
SetSizeConstraints(size_constraints);
}
gfx::Size NativeWindow::GetMinimumSize() {
gfx::Size NativeWindow::GetMinimumSize() const {
return GetSizeConstraints().GetMinimumSize();
}
@ -292,7 +292,7 @@ void NativeWindow::SetMaximumSize(const gfx::Size& size) {
SetSizeConstraints(size_constraints);
}
gfx::Size NativeWindow::GetMaximumSize() {
gfx::Size NativeWindow::GetMaximumSize() const {
return GetSizeConstraints().GetMaximumSize();
}

View file

@ -18,10 +18,12 @@
#include "base/observer_list.h"
#include "base/supports_user_data.h"
#include "content/public/browser/readback_types.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
#include "extensions/browser/app_window/size_constraints.h"
#include "native_mate/persistent_dictionary.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"
@ -98,14 +100,14 @@ class NativeWindow : public base::SupportsUserData,
virtual gfx::Rect GetContentBounds();
virtual void SetSizeConstraints(
const extensions::SizeConstraints& size_constraints);
virtual extensions::SizeConstraints GetSizeConstraints();
virtual extensions::SizeConstraints GetSizeConstraints() const;
virtual void SetContentSizeConstraints(
const extensions::SizeConstraints& size_constraints);
virtual extensions::SizeConstraints GetContentSizeConstraints();
virtual extensions::SizeConstraints GetContentSizeConstraints() const;
virtual void SetMinimumSize(const gfx::Size& size);
virtual gfx::Size GetMinimumSize();
virtual gfx::Size GetMinimumSize() const;
virtual void SetMaximumSize(const gfx::Size& size);
virtual gfx::Size GetMaximumSize();
virtual gfx::Size GetMaximumSize() const;
virtual void SetSheetOffset(const double offsetX, const double offsetY);
virtual double GetSheetOffsetX();
virtual double GetSheetOffsetY();
@ -147,9 +149,9 @@ class NativeWindow : public base::SupportsUserData,
virtual void SetMenu(AtomMenuModel* menu);
virtual void SetParentWindow(NativeWindow* parent);
virtual void SetBrowserView(NativeBrowserView* browser_view) = 0;
virtual gfx::NativeView GetNativeView() = 0;
virtual gfx::NativeWindow GetNativeWindow() = 0;
virtual gfx::AcceleratedWidget GetAcceleratedWidget() = 0;
virtual gfx::NativeView GetNativeView() const = 0;
virtual gfx::NativeWindow GetNativeWindow() const = 0;
virtual gfx::AcceleratedWidget GetAcceleratedWidget() const = 0;
// Taskbar/Dock APIs.
enum ProgressState {
@ -215,6 +217,12 @@ class NativeWindow : public base::SupportsUserData,
virtual void HandleKeyboardEvent(
content::WebContents*,
const content::NativeWebKeyboardEvent& event) {}
virtual void ShowAutofillPopup(
content::RenderFrameHost* frame_host,
const gfx::RectF& bounds,
const std::vector<base::string16>& values,
const std::vector<base::string16>& labels) {}
virtual void HideAutofillPopup(content::RenderFrameHost* frame_host) {}
// Public API used by platform-dependent delegates and observers to send UI
// related notifications.
@ -281,8 +289,10 @@ class NativeWindow : public base::SupportsUserData,
const std::vector<DraggableRegion>& regions);
// Converts between content bounds and window bounds.
virtual gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& bounds) = 0;
virtual gfx::Rect WindowBoundsToContentBounds(const gfx::Rect& bounds) = 0;
virtual gfx::Rect ContentBoundsToWindowBounds(
const gfx::Rect& bounds) const = 0;
virtual gfx::Rect WindowBoundsToContentBounds(
const gfx::Rect& bounds) const = 0;
// Called when the window needs to update its draggable region.
virtual void UpdateDraggableRegions(

View file

@ -89,9 +89,9 @@ class NativeWindowMac : public NativeWindow,
void SetContentProtection(bool enable) override;
void SetBrowserView(NativeBrowserView* browser_view) override;
void SetParentWindow(NativeWindow* parent) override;
gfx::NativeView GetNativeView() override;
gfx::NativeWindow GetNativeWindow() override;
gfx::AcceleratedWidget GetAcceleratedWidget() override;
gfx::NativeView GetNativeView() const override;
gfx::NativeWindow GetNativeWindow() const override;
gfx::AcceleratedWidget GetAcceleratedWidget() const override;
void SetProgressBar(double progress, const ProgressState state) override;
void SetOverlayIcon(const gfx::Image& overlay,
const std::string& description) override;
@ -140,8 +140,8 @@ class NativeWindowMac : public NativeWindow,
private:
// NativeWindow:
gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& bounds);
gfx::Rect WindowBoundsToContentBounds(const gfx::Rect& bounds);
gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& bounds) const;
gfx::Rect WindowBoundsToContentBounds(const gfx::Rect& bounds) const;
void UpdateDraggableRegions(
const std::vector<DraggableRegion>& regions) override;

View file

@ -1314,15 +1314,15 @@ void NativeWindowMac::SetParentWindow(NativeWindow* parent) {
[parent->GetNativeWindow() addChildWindow:window_ ordered:NSWindowAbove];
}
gfx::NativeView NativeWindowMac::GetNativeView() {
gfx::NativeView NativeWindowMac::GetNativeView() const {
return inspectable_web_contents()->GetView()->GetNativeView();
}
gfx::NativeWindow NativeWindowMac::GetNativeWindow() {
gfx::NativeWindow NativeWindowMac::GetNativeWindow() const {
return window_;
}
gfx::AcceleratedWidget NativeWindowMac::GetAcceleratedWidget() {
gfx::AcceleratedWidget NativeWindowMac::GetAcceleratedWidget() const {
return inspectable_web_contents()->GetView()->GetNativeView();
}
@ -1498,7 +1498,7 @@ std::vector<gfx::Rect> NativeWindowMac::CalculateNonDraggableRegions(
}
gfx::Rect NativeWindowMac::ContentBoundsToWindowBounds(
const gfx::Rect& bounds) {
const gfx::Rect& bounds) const {
if (has_frame()) {
gfx::Rect window_bounds(
[window_ frameRectForContentRect:bounds.ToCGRect()]);
@ -1511,7 +1511,7 @@ gfx::Rect NativeWindowMac::ContentBoundsToWindowBounds(
}
gfx::Rect NativeWindowMac::WindowBoundsToContentBounds(
const gfx::Rect& bounds) {
const gfx::Rect& bounds) const {
if (has_frame()) {
gfx::Rect content_bounds(
[window_ contentRectForFrameRect:bounds.ToCGRect()]);

View file

@ -7,6 +7,7 @@
#include <string>
#include <vector>
#include "atom/browser/api/atom_api_web_contents.h"
#include "atom/browser/native_browser_view_views.h"
#include "atom/browser/ui/views/menu_bar.h"
#include "atom/browser/window_list.h"
@ -319,6 +320,8 @@ NativeWindowViews::NativeWindowViews(
window_->CenterWindow(size);
Layout();
autofill_popup_.reset(new AutofillPopup(GetNativeView()));
#if defined(OS_WIN)
// Save initial window state.
if (fullscreen)
@ -924,11 +927,11 @@ void NativeWindowViews::SetParentWindow(NativeWindow* parent) {
#endif
}
gfx::NativeView NativeWindowViews::GetNativeView() {
gfx::NativeView NativeWindowViews::GetNativeView() const {
return window_->GetNativeView();
}
gfx::NativeWindow NativeWindowViews::GetNativeWindow() {
gfx::NativeWindow NativeWindowViews::GetNativeWindow() const {
return window_->GetNativeWindow();
}
@ -999,7 +1002,7 @@ bool NativeWindowViews::IsVisibleOnAllWorkspaces() {
return false;
}
gfx::AcceleratedWidget NativeWindowViews::GetAcceleratedWidget() {
gfx::AcceleratedWidget NativeWindowViews::GetAcceleratedWidget() const {
return GetNativeWindow()->GetHost()->GetAcceleratedWidget();
}
@ -1180,7 +1183,7 @@ void NativeWindowViews::OnWidgetMove() {
}
gfx::Rect NativeWindowViews::ContentBoundsToWindowBounds(
const gfx::Rect& bounds) {
const gfx::Rect& bounds) const {
if (!has_frame())
return bounds;
@ -1201,7 +1204,7 @@ gfx::Rect NativeWindowViews::ContentBoundsToWindowBounds(
}
gfx::Rect NativeWindowViews::WindowBoundsToContentBounds(
const gfx::Rect& bounds) {
const gfx::Rect& bounds) const {
if (!has_frame())
return bounds;
@ -1269,6 +1272,26 @@ void NativeWindowViews::HandleKeyboardEvent(
}
}
void NativeWindowViews::ShowAutofillPopup(
content::RenderFrameHost* frame_host,
const gfx::RectF& bounds,
const std::vector<base::string16>& values,
const std::vector<base::string16>& labels) {
auto wc = atom::api::WebContents::FromWrappedClass(
v8::Isolate::GetCurrent(), web_contents());
autofill_popup_->CreateView(
frame_host,
wc->IsOffScreenOrEmbedderOffscreen(),
widget(),
bounds);
autofill_popup_->SetItems(values, labels);
}
void NativeWindowViews::HideAutofillPopup(
content::RenderFrameHost* frame_host) {
autofill_popup_->Hide();
}
void NativeWindowViews::Layout() {
const auto size = GetContentsBounds().size();
const auto menu_bar_bounds =
@ -1306,11 +1329,11 @@ void NativeWindowViews::Layout() {
}
}
gfx::Size NativeWindowViews::GetMinimumSize() {
gfx::Size NativeWindowViews::GetMinimumSize() const {
return NativeWindow::GetMinimumSize();
}
gfx::Size NativeWindowViews::GetMaximumSize() {
gfx::Size NativeWindowViews::GetMaximumSize() const {
return NativeWindow::GetMaximumSize();
}

View file

@ -11,6 +11,7 @@
#include <vector>
#include "atom/browser/ui/accelerator_util.h"
#include "atom/browser/ui/autofill_popup.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/widget/widget_observer.h"
@ -106,8 +107,8 @@ class NativeWindowViews : public NativeWindow,
void SetMenu(AtomMenuModel* menu_model) override;
void SetBrowserView(NativeBrowserView* browser_view) override;
void SetParentWindow(NativeWindow* parent) override;
gfx::NativeView GetNativeView() override;
gfx::NativeWindow GetNativeWindow() override;
gfx::NativeView GetNativeView() const override;
gfx::NativeWindow GetNativeWindow() const override;
void SetOverlayIcon(const gfx::Image& overlay,
const std::string& description) override;
void SetProgressBar(double progress, const ProgressState state) override;
@ -118,7 +119,7 @@ class NativeWindowViews : public NativeWindow,
void SetVisibleOnAllWorkspaces(bool visible) override;
bool IsVisibleOnAllWorkspaces() override;
gfx::AcceleratedWidget GetAcceleratedWidget() override;
gfx::AcceleratedWidget GetAcceleratedWidget() const override;
#if defined(OS_WIN)
void SetIcon(HICON small_icon, HICON app_icon);
@ -171,16 +172,22 @@ class NativeWindowViews : public NativeWindow,
#endif
// NativeWindow:
gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& bounds) override;
gfx::Rect WindowBoundsToContentBounds(const gfx::Rect& bounds) override;
gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& bounds) const override;
gfx::Rect WindowBoundsToContentBounds(const gfx::Rect& bounds) const override;
void HandleKeyboardEvent(
content::WebContents*,
const content::NativeWebKeyboardEvent& event) override;
void ShowAutofillPopup(
content::RenderFrameHost* frame_host,
const gfx::RectF& bounds,
const std::vector<base::string16>& values,
const std::vector<base::string16>& labels) override;
void HideAutofillPopup(content::RenderFrameHost* frame_host) override;
// views::View:
void Layout() override;
gfx::Size GetMinimumSize() override;
gfx::Size GetMaximumSize() override;
gfx::Size GetMinimumSize() const override;
gfx::Size GetMaximumSize() const override;
bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
// Register accelerators supported by the menu model.
@ -194,6 +201,8 @@ class NativeWindowViews : public NativeWindow,
NativeBrowserView* browser_view_;
std::unique_ptr<AutofillPopup> autofill_popup_;
std::unique_ptr<MenuBar> menu_bar_;
bool menu_bar_autohide_;
bool menu_bar_visible_;

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 (size_t i = 0; i < damages.size(); i++) {
CopyBitmapTo(bitmap, *(bitmaps[i]), damages[i]);
}
damage.Intersect(GetViewBounds());
callback_.Run(damage, bitmap);
for (size_t 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_

View file

@ -0,0 +1,266 @@
// 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 <algorithm>
#include <utility>
#include <vector>
#include "atom/browser/osr/osr_render_widget_host_view.h"
#include "atom/browser/osr/osr_view_proxy.h"
#include "atom/browser/ui/autofill_popup.h"
#include "atom/common/api/api_messages.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/text_utils.h"
namespace atom {
namespace {
std::pair<int, int> CalculatePopupXAndWidth(
const display::Display& left_display,
const display::Display& right_display,
int popup_required_width,
const gfx::Rect& element_bounds,
bool is_rtl) {
int leftmost_display_x = left_display.bounds().x();
int rightmost_display_x =
right_display.GetSizeInPixel().width() + right_display.bounds().x();
// Calculate the start coordinates for the popup if it is growing right or
// the end position if it is growing to the left, capped to screen space.
int right_growth_start = std::max(
leftmost_display_x, std::min(rightmost_display_x, element_bounds.x()));
int left_growth_end =
std::max(leftmost_display_x,
std::min(rightmost_display_x, element_bounds.right()));
int right_available = rightmost_display_x - right_growth_start;
int left_available = left_growth_end - leftmost_display_x;
int popup_width =
std::min(popup_required_width, std::max(right_available, left_available));
std::pair<int, int> grow_right(right_growth_start, popup_width);
std::pair<int, int> grow_left(left_growth_end - popup_width, popup_width);
// Prefer to grow towards the end (right for LTR, left for RTL). But if there
// is not enough space available in the desired direction and more space in
// the other direction, reverse it.
if (is_rtl) {
return left_available >= popup_width || left_available >= right_available
? grow_left
: grow_right;
}
return right_available >= popup_width || right_available >= left_available
? grow_right
: grow_left;
}
std::pair<int, int> CalculatePopupYAndHeight(
const display::Display& top_display,
const display::Display& bottom_display,
int popup_required_height,
const gfx::Rect& element_bounds) {
int topmost_display_y = top_display.bounds().y();
int bottommost_display_y =
bottom_display.GetSizeInPixel().height() + bottom_display.bounds().y();
// Calculate the start coordinates for the popup if it is growing down or
// the end position if it is growing up, capped to screen space.
int top_growth_end = std::max(
topmost_display_y, std::min(bottommost_display_y, element_bounds.y()));
int bottom_growth_start =
std::max(topmost_display_y,
std::min(bottommost_display_y, element_bounds.bottom()));
int top_available = bottom_growth_start - topmost_display_y;
int bottom_available = bottommost_display_y - top_growth_end;
// TODO(csharp): Restrict the popup height to what is available.
if (bottom_available >= popup_required_height ||
bottom_available >= top_available) {
// The popup can appear below the field.
return std::make_pair(bottom_growth_start, popup_required_height);
} else {
// The popup must appear above the field.
return std::make_pair(top_growth_end - popup_required_height,
popup_required_height);
}
}
display::Display GetDisplayNearestPoint(
const gfx::Point& point,
gfx::NativeView container_view) {
return display::Screen::GetScreen()->GetDisplayNearestPoint(point);
}
} // namespace
AutofillPopup::AutofillPopup(gfx::NativeView container_view)
: container_view_(container_view), view_(nullptr) {
bold_font_list_ =
gfx::FontList().DeriveWithWeight(gfx::Font::Weight::BOLD);
smaller_font_list_ =
gfx::FontList().DeriveWithSizeDelta(kSmallerFontSizeDelta);
}
AutofillPopup::~AutofillPopup() {
Hide();
}
void AutofillPopup::CreateView(
content::RenderFrameHost* frame_host,
bool offscreen,
views::Widget* parent_widget,
const gfx::RectF& r) {
frame_host_ = frame_host;
gfx::Rect lb(std::floor(r.x()), std::floor(r.y() + r.height()),
std::floor(r.width()), std::floor(r.height()));
gfx::Point menu_position(lb.origin());
popup_bounds_in_view_ = lb;
views::View::ConvertPointToScreen(
parent_widget->GetContentsView(), &menu_position);
popup_bounds_ = gfx::Rect(menu_position, lb.size());
element_bounds_ = popup_bounds_;
Hide();
view_ = new AutofillPopupView(this, parent_widget);
view_->Show();
if (offscreen) {
auto* osr_rwhv = static_cast<OffScreenRenderWidgetHostView*>(
frame_host_->GetView());
view_->view_proxy_.reset(new OffscreenViewProxy(view_));
osr_rwhv->AddViewProxy(view_->view_proxy_.get());
}
}
void AutofillPopup::Hide() {
if (view_) {
view_->Hide();
view_ = nullptr;
}
}
void AutofillPopup::SetItems(const std::vector<base::string16>& values,
const std::vector<base::string16>& labels) {
values_ = values;
labels_ = labels;
UpdatePopupBounds();
if (view_) {
view_->OnSuggestionsChanged();
}
}
void AutofillPopup::AcceptSuggestion(int index) {
frame_host_->Send(new AtomAutofillFrameMsg_AcceptSuggestion(
frame_host_->GetRoutingID(), GetValueAt(index)));
}
void AutofillPopup::UpdatePopupBounds() {
int desired_width = GetDesiredPopupWidth();
int desired_height = GetDesiredPopupHeight();
bool is_rtl = false;
gfx::Point top_left_corner_of_popup =
element_bounds_.origin() +
gfx::Vector2d(element_bounds_.width() - desired_width, -desired_height);
// This is the bottom right point of the popup if the popup is below the
// element and grows to the right (since the is the lowest and furthest right
// the popup could go).
gfx::Point bottom_right_corner_of_popup =
element_bounds_.origin() +
gfx::Vector2d(desired_width, element_bounds_.height() + desired_height);
display::Display top_left_display =
GetDisplayNearestPoint(top_left_corner_of_popup, container_view_);
display::Display bottom_right_display =
GetDisplayNearestPoint(bottom_right_corner_of_popup, container_view_);
std::pair<int, int> popup_x_and_width =
CalculatePopupXAndWidth(top_left_display, bottom_right_display,
desired_width, element_bounds_, is_rtl);
std::pair<int, int> popup_y_and_height = CalculatePopupYAndHeight(
top_left_display, bottom_right_display, desired_height, element_bounds_);
popup_bounds_ = gfx::Rect(popup_x_and_width.first, popup_y_and_height.first,
popup_x_and_width.second, popup_y_and_height.second);
popup_bounds_in_view_ = gfx::Rect(popup_bounds_in_view_.origin(),
gfx::Size(popup_x_and_width.second, popup_y_and_height.second));
}
int AutofillPopup::GetDesiredPopupHeight() {
return 2 * kPopupBorderThickness + values_.size() * kRowHeight;
}
int AutofillPopup::GetDesiredPopupWidth() {
int popup_width = element_bounds_.width();
for (size_t i = 0; i < values_.size(); ++i) {
int row_size = kEndPadding + 2 * kPopupBorderThickness +
gfx::GetStringWidth(GetValueAt(i), GetValueFontListForRow(i)) +
gfx::GetStringWidth(GetLabelAt(i), GetLabelFontListForRow(i));
if (GetLabelAt(i).length() > 0)
row_size += kNamePadding + kEndPadding;
popup_width = std::max(popup_width, row_size);
}
return popup_width;
}
gfx::Rect AutofillPopup::GetRowBounds(int index) {
int top = kPopupBorderThickness + index * kRowHeight;
return gfx::Rect(kPopupBorderThickness, top,
popup_bounds_.width() - 2 * kPopupBorderThickness,
kRowHeight);
}
const gfx::FontList& AutofillPopup::GetValueFontListForRow(int index) const {
return bold_font_list_;
}
const gfx::FontList& AutofillPopup::GetLabelFontListForRow(int index) const {
return smaller_font_list_;
}
ui::NativeTheme::ColorId AutofillPopup::GetBackgroundColorIDForRow(
int index) const {
return (view_ && index == view_->GetSelectedLine())
? ui::NativeTheme::kColorId_ResultsTableHoveredBackground
: ui::NativeTheme::kColorId_ResultsTableNormalBackground;
}
int AutofillPopup::GetLineCount() {
return values_.size();
}
base::string16 AutofillPopup::GetValueAt(int i) {
return values_.at(i);
}
base::string16 AutofillPopup::GetLabelAt(int i) {
return labels_.at(i);
}
int AutofillPopup::LineFromY(int y) const {
int current_height = kPopupBorderThickness;
for (size_t i = 0; i < values_.size(); ++i) {
current_height += kRowHeight;
if (y <= current_height)
return i;
}
return values_.size() - 1;
}
} // namespace atom

View file

@ -0,0 +1,82 @@
// 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.
#ifndef ATOM_BROWSER_UI_AUTOFILL_POPUP_H_
#define ATOM_BROWSER_UI_AUTOFILL_POPUP_H_
#include <vector>
#include "atom/browser/ui/views/autofill_popup_view.h"
#include "content/public/browser/render_frame_host.h"
#include "ui/gfx/font_list.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/widget/widget.h"
namespace atom {
class AutofillPopupView;
class AutofillPopup {
public:
explicit AutofillPopup(gfx::NativeView);
~AutofillPopup();
void CreateView(content::RenderFrameHost* render_frame,
bool offscreen, views::Widget* widget, const gfx::RectF& bounds);
void Hide();
void SetItems(const std::vector<base::string16>& values,
const std::vector<base::string16>& labels);
private:
friend class AutofillPopupView;
void AcceptSuggestion(int index);
void UpdatePopupBounds();
int GetDesiredPopupHeight();
int GetDesiredPopupWidth();
gfx::Rect GetRowBounds(int i);
const gfx::FontList& GetValueFontListForRow(int index) const;
const gfx::FontList& GetLabelFontListForRow(int index) const;
ui::NativeTheme::ColorId GetBackgroundColorIDForRow(int index) const;
int GetLineCount();
base::string16 GetValueAt(int i);
base::string16 GetLabelAt(int i);
int LineFromY(int y) const;
// The native view that contains this
gfx::NativeView container_view_;
int selected_index_;
// Popup location
gfx::Rect popup_bounds_;
gfx::Rect popup_bounds_in_view_;
// Bounds of the autofilled element
gfx::Rect element_bounds_;
// Datalist suggestions
std::vector<base::string16> values_;
std::vector<base::string16> labels_;
// Font lists for the suggestions
gfx::FontList smaller_font_list_;
gfx::FontList bold_font_list_;
// For sending the accepted suggestion to the render frame that
// asked to open the popup
content::RenderFrameHost* frame_host_;
// The popup view. The lifetime is managed by the owning Widget
AutofillPopupView* view_;
DISALLOW_COPY_AND_ASSIGN(AutofillPopup);
};
} // namespace atom
#endif // ATOM_BROWSER_UI_AUTOFILL_POPUP_H_

View file

@ -0,0 +1,471 @@
// 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 "atom/browser/ui/views/autofill_popup_view.h"
#include "base/bind.h"
#include "base/i18n/rtl.h"
#include "content/public/browser/render_view_host.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/text_utils.h"
#include "ui/views/border.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/widget/widget.h"
namespace atom {
AutofillPopupView::AutofillPopupView(
AutofillPopup* popup,
views::Widget* parent_widget)
: popup_(popup),
parent_widget_(parent_widget),
view_proxy_(nullptr),
weak_ptr_factory_(this) {
CreateChildViews();
SetFocusBehavior(FocusBehavior::ALWAYS);
set_drag_controller(this);
}
AutofillPopupView::~AutofillPopupView() {
if (popup_) {
auto host = popup_->frame_host_->GetRenderViewHost()->GetWidget();
host->RemoveKeyPressEventCallback(keypress_callback_);
popup_->view_ = nullptr;
popup_ = nullptr;
}
RemoveObserver();
if (view_proxy_.get()) {
view_proxy_->ResetView();
}
if (GetWidget()) {
GetWidget()->Close();
}
}
void AutofillPopupView::Show() {
if (!popup_)
return;
const bool initialize_widget = !GetWidget();
if (initialize_widget) {
parent_widget_->AddObserver(this);
views::FocusManager* focus_manager = parent_widget_->GetFocusManager();
focus_manager->RegisterAccelerator(
ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE),
ui::AcceleratorManager::kNormalPriority,
this);
focus_manager->RegisterAccelerator(
ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE),
ui::AcceleratorManager::kNormalPriority,
this);
// The widget is destroyed by the corresponding NativeWidget, so we use
// a weak pointer to hold the reference and don't have to worry about
// deletion.
views::Widget* widget = new views::Widget;
views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
params.delegate = this;
params.parent = parent_widget_->GetNativeView();
widget->Init(params);
// No animation for popup appearance (too distracting).
widget->SetVisibilityAnimationTransition(views::Widget::ANIMATE_HIDE);
show_time_ = base::Time::Now();
}
SetBorder(views::CreateSolidBorder(
kPopupBorderThickness,
GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_UnfocusedBorderColor)));
DoUpdateBoundsAndRedrawPopup();
GetWidget()->Show();
if (initialize_widget)
views::WidgetFocusManager::GetInstance()->AddFocusChangeListener(this);
keypress_callback_ = base::Bind(&AutofillPopupView::HandleKeyPressEvent,
base::Unretained(this));
auto host = popup_->frame_host_->GetRenderViewHost()->GetWidget();
host->AddKeyPressEventCallback(keypress_callback_);
NotifyAccessibilityEvent(ui::AX_EVENT_MENU_START, true);
}
void AutofillPopupView::Hide() {
if (popup_) {
auto host = popup_->frame_host_->GetRenderViewHost()->GetWidget();
host->RemoveKeyPressEventCallback(keypress_callback_);
popup_ = nullptr;
}
RemoveObserver();
NotifyAccessibilityEvent(ui::AX_EVENT_MENU_END, true);
if (GetWidget()) {
GetWidget()->Close();
}
}
void AutofillPopupView::OnSuggestionsChanged() {
if (!popup_)
return;
CreateChildViews();
if (popup_->GetLineCount() == 0) {
popup_->Hide();
return;
}
DoUpdateBoundsAndRedrawPopup();
}
void AutofillPopupView::OnSelectedRowChanged(
base::Optional<int> previous_row_selection,
base::Optional<int> current_row_selection) {
SchedulePaint();
if (current_row_selection) {
int selected = current_row_selection.value_or(-1);
if (selected == -1 || selected >= child_count())
return;
child_at(selected)->NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true);
}
}
void AutofillPopupView::DrawAutofillEntry(gfx::Canvas* canvas,
int index,
const gfx::Rect& entry_rect) {
if (!popup_)
return;
canvas->FillRect(
entry_rect,
GetNativeTheme()->GetSystemColor(
popup_->GetBackgroundColorIDForRow(index)));
const bool is_rtl = base::i18n::IsRTL();
const int text_align =
is_rtl ? gfx::Canvas::TEXT_ALIGN_RIGHT : gfx::Canvas::TEXT_ALIGN_LEFT;
gfx::Rect value_rect = entry_rect;
value_rect.Inset(kEndPadding, 0);
int x_align_left = value_rect.x();
const int value_width = gfx::GetStringWidth(
popup_->GetValueAt(index),
popup_->GetValueFontListForRow(index));
int value_x_align_left = x_align_left;
value_x_align_left =
is_rtl ? value_rect.right() - value_width : value_rect.x();
canvas->DrawStringRectWithFlags(
popup_->GetValueAt(index),
popup_->GetValueFontListForRow(index),
GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_ResultsTableNormalText),
gfx::Rect(value_x_align_left, value_rect.y(), value_width,
value_rect.height()),
text_align);
// Draw the label text, if one exists.
if (!popup_->GetLabelAt(index).empty()) {
const int label_width = gfx::GetStringWidth(
popup_->GetLabelAt(index),
popup_->GetLabelFontListForRow(index));
int label_x_align_left = x_align_left;
label_x_align_left =
is_rtl ? value_rect.x() : value_rect.right() - label_width;
canvas->DrawStringRectWithFlags(
popup_->GetLabelAt(index),
popup_->GetLabelFontListForRow(index),
GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_ResultsTableNormalDimmedText),
gfx::Rect(label_x_align_left, entry_rect.y(), label_width,
entry_rect.height()),
text_align);
}
}
void AutofillPopupView::CreateChildViews() {
if (!popup_)
return;
RemoveAllChildViews(true);
for (int i = 0; i < popup_->GetLineCount(); ++i) {
auto child_view = new AutofillPopupChildView(popup_->GetValueAt(i));
child_view->set_drag_controller(this);
AddChildView(child_view);
}
}
void AutofillPopupView::DoUpdateBoundsAndRedrawPopup() {
if (!popup_)
return;
GetWidget()->SetBounds(popup_->popup_bounds_);
SchedulePaint();
}
void AutofillPopupView::OnPaint(gfx::Canvas* canvas) {
if (!popup_ || popup_->GetLineCount() != child_count())
return;
gfx::Canvas* draw_canvas = canvas;
SkBitmap bitmap;
if (view_proxy_.get()) {
bitmap.allocN32Pixels(popup_->popup_bounds_in_view_.width(),
popup_->popup_bounds_in_view_.height(),
true);
draw_canvas = new gfx::Canvas(new SkCanvas(bitmap), 1.0);
}
draw_canvas->DrawColor(GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_ResultsTableNormalBackground));
OnPaintBorder(draw_canvas);
for (int i = 0; i < popup_->GetLineCount(); ++i) {
gfx::Rect line_rect = popup_->GetRowBounds(i);
DrawAutofillEntry(draw_canvas, i, line_rect);
}
if (view_proxy_.get()) {
view_proxy_->SetBounds(popup_->popup_bounds_in_view_);
view_proxy_->SetBitmap(bitmap);
}
}
void AutofillPopupView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
node_data->role = ui::AX_ROLE_MENU;
node_data->SetName("Autofill Menu");
}
void AutofillPopupView::OnMouseCaptureLost() {
ClearSelection();
}
bool AutofillPopupView::OnMouseDragged(const ui::MouseEvent& event) {
if (HitTestPoint(event.location())) {
SetSelection(event.location());
// We must return true in order to get future OnMouseDragged and
// OnMouseReleased events.
return true;
}
// If we move off of the popup, we lose the selection.
ClearSelection();
return false;
}
void AutofillPopupView::OnMouseExited(const ui::MouseEvent& event) {
// Pressing return causes the cursor to hide, which will generate an
// OnMouseExited event. Pressing return should activate the current selection
// via AcceleratorPressed, so we need to let that run first.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&AutofillPopupView::ClearSelection,
weak_ptr_factory_.GetWeakPtr()));
}
void AutofillPopupView::OnMouseMoved(const ui::MouseEvent& event) {
// A synthesized mouse move will be sent when the popup is first shown.
// Don't preview a suggestion if the mouse happens to be hovering there.
#if defined(OS_WIN)
if (base::Time::Now() - show_time_ <= base::TimeDelta::FromMilliseconds(50))
return;
#else
if (event.flags() & ui::EF_IS_SYNTHESIZED)
return;
#endif
if (HitTestPoint(event.location()))
SetSelection(event.location());
else
ClearSelection();
}
bool AutofillPopupView::OnMousePressed(const ui::MouseEvent& event) {
return event.GetClickCount() == 1;
}
void AutofillPopupView::OnMouseReleased(const ui::MouseEvent& event) {
// We only care about the left click.
if (event.IsOnlyLeftMouseButton() && HitTestPoint(event.location()))
AcceptSelection(event.location());
}
void AutofillPopupView::OnGestureEvent(ui::GestureEvent* event) {
switch (event->type()) {
case ui::ET_GESTURE_TAP_DOWN:
case ui::ET_GESTURE_SCROLL_BEGIN:
case ui::ET_GESTURE_SCROLL_UPDATE:
if (HitTestPoint(event->location()))
SetSelection(event->location());
else
ClearSelection();
break;
case ui::ET_GESTURE_TAP:
case ui::ET_GESTURE_SCROLL_END:
if (HitTestPoint(event->location()))
AcceptSelection(event->location());
else
ClearSelection();
break;
case ui::ET_GESTURE_TAP_CANCEL:
case ui::ET_SCROLL_FLING_START:
ClearSelection();
break;
default:
return;
}
event->SetHandled();
}
bool AutofillPopupView::AcceleratorPressed(
const ui::Accelerator& accelerator) {
if (accelerator.modifiers() != ui::EF_NONE)
return false;
if (accelerator.key_code() == ui::VKEY_ESCAPE) {
if (popup_)
popup_->Hide();
return true;
}
if (accelerator.key_code() == ui::VKEY_RETURN)
return AcceptSelectedLine();
return false;
}
bool AutofillPopupView::HandleKeyPressEvent(
const content::NativeWebKeyboardEvent& event) {
if (!popup_)
return false;
switch (event.windowsKeyCode) {
case ui::VKEY_UP:
SelectPreviousLine();
return true;
case ui::VKEY_DOWN:
SelectNextLine();
return true;
case ui::VKEY_PRIOR: // Page up.
SetSelectedLine(0);
return true;
case ui::VKEY_NEXT: // Page down.
SetSelectedLine(popup_->GetLineCount() - 1);
return true;
case ui::VKEY_ESCAPE:
popup_->Hide();
return true;
case ui::VKEY_TAB:
// A tab press should cause the selected line to be accepted, but still
// return false so the tab key press propagates and changes the cursor
// location.
AcceptSelectedLine();
return false;
case ui::VKEY_RETURN:
return AcceptSelectedLine();
default:
return false;
}
}
void AutofillPopupView::OnNativeFocusChanged(gfx::NativeView focused_now) {
if (GetWidget() && GetWidget()->GetNativeView() != focused_now && popup_)
popup_->Hide();
}
void AutofillPopupView::OnWidgetBoundsChanged(views::Widget* widget,
const gfx::Rect& new_bounds) {
if (widget != parent_widget_)
return;
if (popup_)
popup_->Hide();
}
void AutofillPopupView::AcceptSuggestion(int index) {
if (!popup_)
return;
popup_->AcceptSuggestion(index);
popup_->Hide();
}
bool AutofillPopupView::AcceptSelectedLine() {
if (!selected_line_ || selected_line_.value() >= popup_->GetLineCount())
return false;
AcceptSuggestion(selected_line_.value());
return true;
}
void AutofillPopupView::AcceptSelection(const gfx::Point& point) {
if (!popup_)
return;
SetSelectedLine(popup_->LineFromY(point.y()));
AcceptSelectedLine();
}
void AutofillPopupView::SetSelectedLine(base::Optional<int> selected_line) {
if (!popup_)
return;
if (selected_line_ == selected_line)
return;
if (selected_line && selected_line.value() >= popup_->GetLineCount())
return;
auto previous_selected_line(selected_line_);
selected_line_ = selected_line;
OnSelectedRowChanged(previous_selected_line, selected_line_);
}
void AutofillPopupView::SetSelection(const gfx::Point& point) {
if (!popup_)
return;
SetSelectedLine(popup_->LineFromY(point.y()));
}
void AutofillPopupView::SelectNextLine() {
if (!popup_)
return;
int new_selected_line = selected_line_ ? *selected_line_ + 1 : 0;
if (new_selected_line >= popup_->GetLineCount())
new_selected_line = 0;
SetSelectedLine(new_selected_line);
}
void AutofillPopupView::SelectPreviousLine() {
if (!popup_)
return;
int new_selected_line = selected_line_.value_or(0) - 1;
if (new_selected_line < 0)
new_selected_line = popup_->GetLineCount() - 1;
SetSelectedLine(new_selected_line);
}
void AutofillPopupView::ClearSelection() {
SetSelectedLine(base::nullopt);
}
void AutofillPopupView::RemoveObserver() {
parent_widget_->GetFocusManager()->UnregisterAccelerators(this);
parent_widget_->RemoveObserver(this);
views::WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(this);
}
} // namespace atom

View file

@ -0,0 +1,152 @@
// 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.
#ifndef ATOM_BROWSER_UI_VIEWS_AUTOFILL_POPUP_VIEW_H_
#define ATOM_BROWSER_UI_VIEWS_AUTOFILL_POPUP_VIEW_H_
#include "atom/browser/ui/autofill_popup.h"
#include "atom/browser/osr/osr_view_proxy.h"
#include "base/optional.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/render_widget_host.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/views/drag_controller.h"
#include "ui/views/focus/widget_focus_manager.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/widget/widget_observer.h"
namespace atom {
const int kPopupBorderThickness = 1;
const int kSmallerFontSizeDelta = -1;
const int kEndPadding = 8;
const int kNamePadding = 15;
const int kRowHeight = 24;
class AutofillPopup;
// Child view only for triggering accessibility events. Rendering is handled
// by |AutofillPopupViewViews|.
class AutofillPopupChildView : public views::View {
public:
explicit AutofillPopupChildView(const base::string16& suggestion)
: suggestion_(suggestion) {
SetFocusBehavior(FocusBehavior::ALWAYS);
}
private:
~AutofillPopupChildView() override {}
// views::Views implementation
void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
node_data->role = ui::AX_ROLE_MENU_ITEM;
node_data->SetName(suggestion_);
}
base::string16 suggestion_;
DISALLOW_COPY_AND_ASSIGN(AutofillPopupChildView);
};
class AutofillPopupView : public views::WidgetDelegateView,
public views::WidgetFocusChangeListener,
public views::WidgetObserver,
public views::DragController {
public:
explicit AutofillPopupView(AutofillPopup* popup,
views::Widget* parent_widget);
~AutofillPopupView() override;
void Show();
void Hide();
void OnSuggestionsChanged();
int GetSelectedLine() { return selected_line_.value_or(-1); }
void WriteDragDataForView(
views::View*, const gfx::Point&, ui::OSExchangeData*) override {}
int GetDragOperationsForView(views::View*, const gfx::Point&) override {
return ui::DragDropTypes::DRAG_NONE;
}
bool CanStartDragForView(
views::View*, const gfx::Point&, const gfx::Point&) override {
return false;
}
private:
friend class AutofillPopup;
void OnSelectedRowChanged(base::Optional<int> previous_row_selection,
base::Optional<int> current_row_selection);
// Draw the given autofill entry in |entry_rect|.
void DrawAutofillEntry(gfx::Canvas* canvas,
int index,
const gfx::Rect& entry_rect);
// Creates child views based on the suggestions given by |controller_|. These
// child views are used for accessibility events only. We need child views to
// populate the correct |AXNodeData| when user selects a suggestion.
void CreateChildViews();
void DoUpdateBoundsAndRedrawPopup();
// views::Views implementation.
void OnPaint(gfx::Canvas* canvas) override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
void OnMouseCaptureLost() override;
bool OnMouseDragged(const ui::MouseEvent& event) override;
void OnMouseExited(const ui::MouseEvent& event) override;
void OnMouseMoved(const ui::MouseEvent& event) override;
bool OnMousePressed(const ui::MouseEvent& event) override;
void OnMouseReleased(const ui::MouseEvent& event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
bool HandleKeyPressEvent(const content::NativeWebKeyboardEvent& event);
// views::WidgetFocusChangeListener implementation.
void OnNativeFocusChanged(gfx::NativeView focused_now) override;
// views::WidgetObserver implementation.
void OnWidgetBoundsChanged(views::Widget* widget,
const gfx::Rect& new_bounds) override;
void AcceptSuggestion(int index);
bool AcceptSelectedLine();
void AcceptSelection(const gfx::Point& point);
void SetSelectedLine(base::Optional<int> selected_line);
void SetSelection(const gfx::Point& point);
void SelectNextLine();
void SelectPreviousLine();
void ClearSelection();
// Stop observing the widget.
void RemoveObserver();
// Controller for this popup. Weak reference.
AutofillPopup* popup_;
// The widget of the window that triggered this popup. Weak reference.
views::Widget* parent_widget_;
// The time when the popup was shown.
base::Time show_time_;
// The index of the currently selected line
base::Optional<int> selected_line_;
std::unique_ptr<OffscreenViewProxy> view_proxy_;
// The registered keypress callback, responsible for switching lines on
// key presses
content::RenderWidgetHost::KeyPressEventCallback keypress_callback_;
base::WeakPtrFactory<AutofillPopupView> weak_ptr_factory_;
};
} // namespace atom
#endif // ATOM_BROWSER_UI_VIEWS_AUTOFILL_POPUP_VIEW_H_

View file

@ -119,7 +119,7 @@ bool MenuBar::GetMenuButtonFromScreenPoint(const gfx::Point& point,
for (int i = 0; i < child_count(); ++i) {
views::View* view = child_at(i);
if (view->bounds().Contains(location) &&
if (view->GetMirroredBounds().Contains(location) &&
(menu_model_->GetTypeAt(i) == AtomMenuModel::TYPE_SUBMENU)) {
*menu_model = menu_model_->GetSubmenuModelAt(i);
*button = static_cast<views::MenuButton*>(view);

View file

@ -9,6 +9,7 @@
#include "base/values.h"
#include "content/public/common/common_param_traits.h"
#include "ipc/ipc_message_macros.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/ipc/gfx_param_traits.h"
// The message starter should be declared in ipc/ipc_message_start.h. Since
@ -37,6 +38,16 @@ IPC_MESSAGE_ROUTED3(AtomViewMsg_Message,
IPC_MESSAGE_ROUTED0(AtomViewMsg_Offscreen)
IPC_MESSAGE_ROUTED3(AtomAutofillFrameHostMsg_ShowPopup,
gfx::RectF /* bounds */,
std::vector<base::string16> /* values */,
std::vector<base::string16> /* labels */)
IPC_MESSAGE_ROUTED0(AtomAutofillFrameHostMsg_HidePopup)
IPC_MESSAGE_ROUTED1(AtomAutofillFrameMsg_AcceptSuggestion,
base::string16 /* suggestion */)
// Sent by the renderer when the draggable regions are updated.
IPC_MESSAGE_ROUTED1(AtomViewHostMsg_UpdateDraggableRegions,
std::vector<atom::DraggableRegion> /* regions */)

View file

@ -0,0 +1,233 @@
// 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/renderer/atom_autofill_agent.h"
#include <vector>
#include "atom/common/api/api_messages.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
#include "third_party/WebKit/public/platform/WebKeyboardEvent.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebOptionElement.h"
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/geometry/rect_f.h"
namespace atom {
namespace {
const size_t kMaxDataLength = 1024;
const size_t kMaxListSize = 512;
void GetDataListSuggestions(const blink::WebInputElement& element,
std::vector<base::string16>* values,
std::vector<base::string16>* labels) {
for (const auto& option : element.filteredDataListOptions()) {
values->push_back(option.value().utf16());
if (option.value() != option.label())
labels->push_back(option.label().utf16());
else
labels->push_back(base::string16());
}
}
void TrimStringVectorForIPC(std::vector<base::string16>* strings) {
// Limit the size of the vector.
if (strings->size() > kMaxListSize)
strings->resize(kMaxListSize);
// Limit the size of the strings in the vector.
for (size_t i = 0; i < strings->size(); ++i) {
if ((*strings)[i].length() > kMaxDataLength)
(*strings)[i].resize(kMaxDataLength);
}
}
} // namespace
AutofillAgent::AutofillAgent(
content::RenderFrame* frame)
: content::RenderFrameObserver(frame),
helper_(new Helper(this)),
focused_node_was_last_clicked_(false),
was_focused_before_now_(false),
weak_ptr_factory_(this) {
render_frame()->GetWebFrame()->setAutofillClient(this);
}
void AutofillAgent::OnDestruct() {
delete this;
}
void AutofillAgent::DidChangeScrollOffset() {
HidePopup();
}
void AutofillAgent::FocusedNodeChanged(const blink::WebNode&) {
focused_node_was_last_clicked_ = false;
was_focused_before_now_ = false;
HidePopup();
}
void AutofillAgent::textFieldDidEndEditing(
const blink::WebInputElement&) {
HidePopup();
}
void AutofillAgent::textFieldDidChange(
const blink::WebFormControlElement& element) {
if (!IsUserGesture() && !render_frame()->IsPasting())
return;
weak_ptr_factory_.InvalidateWeakPtrs();
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&AutofillAgent::textFieldDidChangeImpl,
weak_ptr_factory_.GetWeakPtr(), element));
}
void AutofillAgent::textFieldDidChangeImpl(
const blink::WebFormControlElement& element) {
ShowSuggestionsOptions options;
options.requires_caret_at_end = true;
ShowSuggestions(element, options);
}
void AutofillAgent::textFieldDidReceiveKeyDown(
const blink::WebInputElement& element,
const blink::WebKeyboardEvent& event) {
if (event.windowsKeyCode == ui::VKEY_DOWN ||
event.windowsKeyCode == ui::VKEY_UP) {
ShowSuggestionsOptions options;
options.autofill_on_empty_values = true;
options.requires_caret_at_end = true;
ShowSuggestions(element, options);
}
}
void AutofillAgent::openTextDataListChooser(
const blink::WebInputElement& element) {
ShowSuggestionsOptions options;
options.autofill_on_empty_values = true;
ShowSuggestions(element, options);
}
void AutofillAgent::dataListOptionsChanged(
const blink::WebInputElement& element) {
if (!element.focused())
return;
ShowSuggestionsOptions options;
options.requires_caret_at_end = true;
ShowSuggestions(element, options);
}
AutofillAgent::ShowSuggestionsOptions::ShowSuggestionsOptions()
: autofill_on_empty_values(false),
requires_caret_at_end(false) {
}
void AutofillAgent::ShowSuggestions(
const blink::WebFormControlElement& element,
const ShowSuggestionsOptions& options) {
if (!element.isEnabled() || element.isReadOnly())
return;
const blink::WebInputElement* input_element = toWebInputElement(&element);
if (input_element) {
if (!input_element->isTextField())
return;
}
blink::WebString value = element.editingValue();
if (value.length() > kMaxDataLength ||
(!options.autofill_on_empty_values && value.isEmpty()) ||
(options.requires_caret_at_end &&
(element.selectionStart() != element.selectionEnd() ||
element.selectionEnd() != static_cast<int>(value.length())))) {
HidePopup();
return;
}
std::vector<base::string16> data_list_values;
std::vector<base::string16> data_list_labels;
if (input_element) {
GetDataListSuggestions(
*input_element, &data_list_values, &data_list_labels);
TrimStringVectorForIPC(&data_list_values);
TrimStringVectorForIPC(&data_list_labels);
}
ShowPopup(element, data_list_values, data_list_labels);
}
AutofillAgent::Helper::Helper(AutofillAgent* agent)
: content::RenderViewObserver(agent->render_frame()->GetRenderView()),
agent_(agent) {
}
void AutofillAgent::Helper::OnMouseDown(const blink::WebNode& node) {
agent_->focused_node_was_last_clicked_ = !node.isNull() && node.focused();
}
void AutofillAgent::Helper::FocusChangeComplete() {
agent_->DoFocusChangeComplete();
}
bool AutofillAgent::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(AutofillAgent, message)
IPC_MESSAGE_HANDLER(AtomAutofillFrameMsg_AcceptSuggestion,
OnAcceptSuggestion)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
bool AutofillAgent::IsUserGesture() const {
return blink::WebUserGestureIndicator::isProcessingUserGesture();
}
void AutofillAgent::HidePopup() {
Send(new AtomAutofillFrameHostMsg_HidePopup(render_frame()->GetRoutingID()));
}
void AutofillAgent::ShowPopup(
const blink::WebFormControlElement& element,
const std::vector<base::string16>& values,
const std::vector<base::string16>& labels) {
gfx::RectF bounds =
render_frame()->GetRenderView()->ElementBoundsInWindow(element);
Send(new AtomAutofillFrameHostMsg_ShowPopup(
render_frame()->GetRoutingID(), bounds, values, labels));
}
void AutofillAgent::OnAcceptSuggestion(base::string16 suggestion) {
auto element = render_frame()->GetWebFrame()->document().focusedElement();
if (element.isFormControlElement()) {
toWebInputElement(&element)->setSuggestedValue(
blink::WebString::fromUTF16(suggestion));
}
}
void AutofillAgent::DoFocusChangeComplete() {
auto element = render_frame()->GetWebFrame()->document().focusedElement();
if (element.isNull() || !element.isFormControlElement())
return;
if (focused_node_was_last_clicked_ && was_focused_before_now_) {
ShowSuggestionsOptions options;
options.autofill_on_empty_values = true;
auto input_element = toWebInputElement(&element);
if (input_element)
ShowSuggestions(*input_element, options);
}
was_focused_before_now_ = true;
focused_node_was_last_clicked_ = false;
}
} // namespace atom

View file

@ -0,0 +1,91 @@
// 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_RENDERER_ATOM_AUTOFILL_AGENT_H_
#define ATOM_RENDERER_ATOM_AUTOFILL_AGENT_H_
#include <vector>
#include "base/memory/weak_ptr.h"
#include "content/public/renderer/render_frame_observer.h"
#include "content/public/renderer/render_view_observer.h"
#include "third_party/WebKit/public/web/WebAutofillClient.h"
#include "third_party/WebKit/public/web/WebFormControlElement.h"
#include "third_party/WebKit/public/web/WebInputElement.h"
#include "third_party/WebKit/public/web/WebNode.h"
namespace atom {
class AutofillAgent : public content::RenderFrameObserver,
public blink::WebAutofillClient {
public:
explicit AutofillAgent(content::RenderFrame* frame);
// content::RenderFrameObserver:
void OnDestruct() override;
void DidChangeScrollOffset() override;
void FocusedNodeChanged(const blink::WebNode&) override;
private:
class Helper : public content::RenderViewObserver {
public:
explicit Helper(AutofillAgent* agent);
// content::RenderViewObserver implementation.
void OnDestruct() override {}
void OnMouseDown(const blink::WebNode&) override;
void FocusChangeComplete() override;
private:
AutofillAgent* agent_;
};
friend class Helper;
struct ShowSuggestionsOptions {
ShowSuggestionsOptions();
bool autofill_on_empty_values;
bool requires_caret_at_end;
};
bool OnMessageReceived(const IPC::Message& message) override;
// blink::WebAutofillClient:
void textFieldDidEndEditing(const blink::WebInputElement&) override;
void textFieldDidChange(const blink::WebFormControlElement&) override;
void textFieldDidChangeImpl(const blink::WebFormControlElement&);
void textFieldDidReceiveKeyDown(const blink::WebInputElement&,
const blink::WebKeyboardEvent&) override;
void openTextDataListChooser(const blink::WebInputElement&) override;
void dataListOptionsChanged(const blink::WebInputElement&) override;
bool IsUserGesture() const;
void HidePopup();
void ShowPopup(const blink::WebFormControlElement&,
const std::vector<base::string16>&,
const std::vector<base::string16>&);
void ShowSuggestions(const blink::WebFormControlElement& element,
const ShowSuggestionsOptions& options);
void OnAcceptSuggestion(base::string16 suggestion);
void DoFocusChangeComplete();
std::unique_ptr<Helper> helper_;
// True when the last click was on the focused node.
bool focused_node_was_last_clicked_;
// This is set to false when the focus changes, then set back to true soon
// afterwards. This helps track whether an event happened after a node was
// already focused, or if it caused the focus to change.
bool was_focused_before_now_;
base::WeakPtrFactory<AutofillAgent> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(AutofillAgent);
};
} // namespace atom
#endif // ATOM_RENDERER_ATOM_AUTOFILL_AGENT_H_

View file

@ -11,6 +11,7 @@
#include "atom/common/color_util.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/options_switches.h"
#include "atom/renderer/atom_autofill_agent.h"
#include "atom/renderer/atom_render_frame_observer.h"
#include "atom/renderer/content_settings_observer.h"
#include "atom/renderer/guest_view_container.h"
@ -120,6 +121,7 @@ void RendererClientBase::RenderThreadStarted() {
void RendererClientBase::RenderFrameCreated(
content::RenderFrame* render_frame) {
new AtomRenderFrameObserver(render_frame, this);
new AutofillAgent(render_frame);
new PepperHelper(render_frame);
new ContentSettingsObserver(render_frame);
new printing::PrintWebViewHelper(render_frame);

View file

@ -244,6 +244,8 @@
'atom/browser/osr/osr_render_widget_host_view.cc',
'atom/browser/osr/osr_render_widget_host_view.h',
'atom/browser/osr/osr_render_widget_host_view_mac.mm',
'atom/browser/osr/osr_view_proxy.cc',
'atom/browser/osr/osr_view_proxy.h',
'atom/browser/net/about_protocol_handler.cc',
'atom/browser/net/about_protocol_handler.h',
'atom/browser/net/asar/asar_protocol_handler.cc',
@ -291,6 +293,8 @@
'atom/browser/ui/accelerator_util_views.cc',
'atom/browser/ui/atom_menu_model.cc',
'atom/browser/ui/atom_menu_model.h',
'atom/browser/ui/autofill_popup.cc',
'atom/browser/ui/autofill_popup.h',
'atom/browser/ui/certificate_trust.h',
'atom/browser/ui/certificate_trust_mac.mm',
'atom/browser/ui/certificate_trust_win.cc',
@ -318,6 +322,8 @@
'atom/browser/ui/tray_icon_cocoa.mm',
'atom/browser/ui/tray_icon_observer.h',
'atom/browser/ui/tray_icon_win.cc',
'atom/browser/ui/views/autofill_popup_view.cc',
'atom/browser/ui/views/autofill_popup_view.h',
'atom/browser/ui/views/frameless_view.cc',
'atom/browser/ui/views/frameless_view.h',
'atom/browser/ui/views/global_menu_bar_x11.cc',
@ -479,6 +485,8 @@
'atom/renderer/api/atom_api_spell_check_client.h',
'atom/renderer/api/atom_api_web_frame.cc',
'atom/renderer/api/atom_api_web_frame.h',
'atom/renderer/atom_autofill_agent.cc',
'atom/renderer/atom_autofill_agent.h',
'atom/renderer/atom_render_frame_observer.cc',
'atom/renderer/atom_render_frame_observer.h',
'atom/renderer/atom_render_view_observer.cc',