Merge pull request #2827 from atom/fix-2752

Move the BeginFrameSubscription method to WebContents
This commit is contained in:
Cheng Zhao 2015-09-18 19:29:17 +08:00
commit 7bb9595b81
28 changed files with 653 additions and 710 deletions

View file

@ -30,12 +30,14 @@
#include "chrome/browser/printing/print_preview_message_handler.h" #include "chrome/browser/printing/print_preview_message_handler.h"
#include "content/common/view_messages.h" #include "content/common/view_messages.h"
#include "content/public/browser/favicon_status.h" #include "content/public/browser/favicon_status.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/navigation_details.h" #include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_entry.h"
#include "content/public/browser/plugin_service.h" #include "content/public/browser/plugin_service.h"
#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/resource_request_details.h" #include "content/public/browser/resource_request_details.h"
#include "content/public/browser/service_worker_context.h" #include "content/public/browser/service_worker_context.h"
#include "content/public/browser/storage_partition.h" #include "content/public/browser/storage_partition.h"
@ -46,6 +48,7 @@
#include "net/http/http_response_headers.h" #include "net/http/http_response_headers.h"
#include "net/url_request/static_http_user_agent_settings.h" #include "net/url_request/static_http_user_agent_settings.h"
#include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "atom/common/node_includes.h" #include "atom/common/node_includes.h"
@ -813,6 +816,56 @@ bool WebContents::SendIPCMessage(const base::string16& channel,
return Send(new AtomViewMsg_Message(routing_id(), channel, args)); return Send(new AtomViewMsg_Message(routing_id(), channel, args));
} }
void WebContents::SendInputEvent(v8::Isolate* isolate,
v8::Local<v8::Value> input_event) {
const auto view = web_contents()->GetRenderWidgetHostView();
if (!view)
return;
const auto host = view->GetRenderWidgetHost();
if (!host)
return;
int type = mate::GetWebInputEventType(isolate, input_event);
if (blink::WebInputEvent::isMouseEventType(type)) {
blink::WebMouseEvent mouse_event;
if (mate::ConvertFromV8(isolate, input_event, &mouse_event)) {
host->ForwardMouseEvent(mouse_event);
return;
}
} else if (blink::WebInputEvent::isKeyboardEventType(type)) {
content::NativeWebKeyboardEvent keyboard_event;;
if (mate::ConvertFromV8(isolate, input_event, &keyboard_event)) {
host->ForwardKeyboardEvent(keyboard_event);
return;
}
} else if (type == blink::WebInputEvent::MouseWheel) {
blink::WebMouseWheelEvent mouse_wheel_event;
if (mate::ConvertFromV8(isolate, input_event, &mouse_wheel_event)) {
host->ForwardWheelEvent(mouse_wheel_event);
return;
}
}
isolate->ThrowException(v8::Exception::Error(mate::StringToV8(
isolate, "Invalid event object")));
}
void WebContents::BeginFrameSubscription(
const FrameSubscriber::FrameCaptureCallback& callback) {
const auto view = web_contents()->GetRenderWidgetHostView();
if (view) {
scoped_ptr<FrameSubscriber> frame_subscriber(new FrameSubscriber(
isolate(), view->GetVisibleViewportSize(), callback));
view->BeginFrameSubscription(frame_subscriber.Pass());
}
}
void WebContents::EndFrameSubscription() {
const auto view = web_contents()->GetRenderWidgetHostView();
if (view)
view->EndFrameSubscription();
}
void WebContents::SetSize(const SetSizeParams& params) { void WebContents::SetSize(const SetSizeParams& params) {
if (guest_delegate_) if (guest_delegate_)
guest_delegate_->SetSize(params); guest_delegate_->SetSize(params);
@ -875,6 +928,10 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
.SetMethod("focus", &WebContents::Focus) .SetMethod("focus", &WebContents::Focus)
.SetMethod("tabTraverse", &WebContents::TabTraverse) .SetMethod("tabTraverse", &WebContents::TabTraverse)
.SetMethod("_send", &WebContents::SendIPCMessage, true) .SetMethod("_send", &WebContents::SendIPCMessage, true)
.SetMethod("sendInputEvent", &WebContents::SendInputEvent)
.SetMethod("beginFrameSubscription",
&WebContents::BeginFrameSubscription)
.SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription)
.SetMethod("setSize", &WebContents::SetSize) .SetMethod("setSize", &WebContents::SetSize)
.SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency) .SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency)
.SetMethod("isGuest", &WebContents::IsGuest) .SetMethod("isGuest", &WebContents::IsGuest)

View file

@ -8,6 +8,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "atom/browser/api/frame_subscriber.h"
#include "atom/browser/api/trackable_object.h" #include "atom/browser/api/trackable_object.h"
#include "atom/browser/common_web_contents_delegate.h" #include "atom/browser/common_web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_observer.h"
@ -114,10 +115,18 @@ class WebContents : public mate::TrackableObject<WebContents>,
void Focus(); void Focus();
void TabTraverse(bool reverse); void TabTraverse(bool reverse);
// Sending messages to browser. // Send messages to browser.
bool SendIPCMessage(const base::string16& channel, bool SendIPCMessage(const base::string16& channel,
const base::ListValue& args); const base::ListValue& args);
// Send WebInputEvent to the page.
void SendInputEvent(v8::Isolate* isolate, v8::Local<v8::Value> input_event);
// Subscribe to the frame updates.
void BeginFrameSubscription(
const FrameSubscriber::FrameCaptureCallback& callback);
void EndFrameSubscription();
// Methods for creating <webview>. // Methods for creating <webview>.
void SetSize(const SetSizeParams& params); void SetSize(const SetSizeParams& params);
void SetAllowTransparency(bool allow); void SetAllowTransparency(bool allow);

View file

@ -8,28 +8,23 @@
#include "atom/browser/api/atom_api_web_contents.h" #include "atom/browser/api/atom_api_web_contents.h"
#include "atom/browser/browser.h" #include "atom/browser/browser.h"
#include "atom/browser/native_window.h" #include "atom/browser/native_window.h"
#include "atom/common/node_includes.h"
#include "atom/common/options_switches.h"
#include "atom/common/event_types.h"
#include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/gfx_converter.h" #include "atom/common/native_mate_converters/gfx_converter.h"
#include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/native_mate_converters/image_converter.h" #include "atom/common/native_mate_converters/image_converter.h"
#include "atom/common/native_mate_converters/string16_converter.h" #include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/node_includes.h"
#include "atom/common/options_switches.h" #include "atom/common/options_switches.h"
#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host.h"
#include "native_mate/constructor.h" #include "native_mate/constructor.h"
#include "native_mate/dictionary.h" #include "native_mate/dictionary.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
#include "v8/include/v8.h"
#if defined(OS_WIN) #if defined(OS_WIN)
#include "atom/browser/native_window_views.h" #include "atom/browser/native_window_views.h"
#include "atom/browser/ui/win/taskbar_host.h" #include "atom/browser/ui/win/taskbar_host.h"
#endif #endif
#include "atom/common/node_includes.h"
#if defined(OS_WIN) #if defined(OS_WIN)
namespace mate { namespace mate {
@ -109,15 +104,6 @@ void Window::WillCloseWindow(bool* prevent_default) {
*prevent_default = Emit("close"); *prevent_default = Emit("close");
} }
void Window::OnFrameRendered(scoped_ptr<uint8[]> rgb, const int size) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
auto data = node::Buffer::New(isolate(), reinterpret_cast<const char*>(rgb.get()), static_cast<size_t>(size));
Emit("frame-rendered", data, size);
}
void Window::OnWindowClosed() { void Window::OnWindowClosed() {
if (api_web_contents_) { if (api_web_contents_) {
api_web_contents_->DestroyWebContents(); api_web_contents_->DestroyWebContents();
@ -463,14 +449,6 @@ void Window::CapturePage(mate::Arguments* args) {
rect, base::Bind(&OnCapturePageDone, args->isolate(), callback)); rect, base::Bind(&OnCapturePageDone, args->isolate(), callback));
} }
void Window::BeginFrameSubscription() {
window_->SetFrameSubscription(true);
}
void Window::EndFrameSubscription() {
window_->SetFrameSubscription(false);
}
void Window::SetProgressBar(double progress) { void Window::SetProgressBar(double progress) {
window_->SetProgressBar(progress); window_->SetProgressBar(progress);
} }
@ -547,127 +525,6 @@ bool Window::IsVisibleOnAllWorkspaces() {
return window_->IsVisibleOnAllWorkspaces(); return window_->IsVisibleOnAllWorkspaces();
} }
void Window::SendKeyboardEvent(v8::Isolate* isolate, const mate::Dictionary& data){
auto type = blink::WebInputEvent::Type::Char;
int modifiers = 0;
int keycode = 0;
int native = 0;
std::string type_str = "";
mate::Dictionary modifier_list = mate::Dictionary::CreateEmpty(isolate);
data.Get(switches::kEventType, &type_str);
data.Get(switches::kModifiers, &modifier_list);
data.Get(switches::kKeyCode, &keycode);
data.Get(switches::kNativeKeyCode, &native);
if(type_str.compare(event_types::kKeyDown) == 0){
type = blink::WebInputEvent::Type::KeyDown;
}else if(type_str.compare(event_types::kKeyUp) == 0){
type = blink::WebInputEvent::Type::KeyUp;
}else if(type_str.compare(event_types::kChar) == 0){
type = blink::WebInputEvent::Type::Char;
}
std::map<std::string, bool> modifier_types;
modifier_types[event_types::kModifierIsKeyPad] = false;
modifier_types[event_types::kModifierIsAutoRepeat] = false;
modifier_types[event_types::kModifierIsLeft] = false;
modifier_types[event_types::kModifierIsRight] = false;
modifier_types[event_types::kModifierShiftKey] = false;
modifier_types[event_types::kModifierControlKey] = false;
modifier_types[event_types::kModifierAltKey] = false;
modifier_types[event_types::kModifierMetaKey] = false;
modifier_types[event_types::kModifierCapsLockOn] = false;
modifier_types[event_types::kModifierNumLockOn] = false;
for(std::map<std::string, bool>::iterator it = modifier_types.begin(); it != modifier_types.end(); ++it){
modifier_list.Get(it->first,&(it->second));
if(it->second) modifiers = modifiers & event_types::modifierStrToWebModifier(it->first);
}
window_->SendKeyboardEvent(type, modifiers, keycode, native);
}
void Window::SendMouseEvent(v8::Isolate* isolate, const mate::Dictionary& data){
int x, y, movementX, movementY, clickCount;
std::string type_str = "";
std::string button_str = "";
mate::Dictionary modifier_list = mate::Dictionary::CreateEmpty(isolate);
blink::WebInputEvent::Type type = blink::WebInputEvent::Type::MouseMove;
blink::WebMouseEvent::Button button = blink::WebMouseEvent::Button::ButtonNone;
int modifiers = 0;
data.Get(switches::kEventType, &type_str);
data.Get(switches::kMouseEventButton, &button_str);
data.Get(switches::kModifiers, &modifier_list);
if(type_str.compare(event_types::kMouseDown) == 0){
type = blink::WebInputEvent::Type::MouseDown;
}else if(type_str.compare(event_types::kMouseUp) == 0){
type = blink::WebInputEvent::Type::MouseUp;
}else if(type_str.compare(event_types::kMouseMove) == 0){
type = blink::WebInputEvent::Type::MouseMove;
}else if(type_str.compare(event_types::kMouseEnter) == 0){
type = blink::WebInputEvent::Type::MouseEnter;
}else if(type_str.compare(event_types::kMouseLeave) == 0){
type = blink::WebInputEvent::Type::MouseLeave;
}else if(type_str.compare(event_types::kContextMenu) == 0){
type = blink::WebInputEvent::Type::ContextMenu;
}else if(type_str.compare(event_types::kMouseWheel) == 0){
type = blink::WebInputEvent::Type::MouseWheel;
}
std::map<std::string, bool> modifier_types;
modifier_types[event_types::kMouseLeftButton] = false;
modifier_types[event_types::kMouseRightButton] = false;
modifier_types[event_types::kMouseMiddleButton] = false;
modifier_types[event_types::kModifierLeftButtonDown] = false;
modifier_types[event_types::kModifierMiddleButtonDown] = false;
modifier_types[event_types::kModifierRightButtonDown] = false;
modifier_types[event_types::kModifierShiftKey] = false;
modifier_types[event_types::kModifierControlKey] = false;
modifier_types[event_types::kModifierAltKey] = false;
modifier_types[event_types::kModifierMetaKey] = false;
modifier_types[event_types::kModifierCapsLockOn] = false;
modifier_types[event_types::kModifierNumLockOn] = false;
for(std::map<std::string, bool>::iterator it = modifier_types.begin(); it != modifier_types.end(); ++it){
modifier_list.Get(it->first,&(it->second));
if(it->second) modifiers = modifiers & event_types::modifierStrToWebModifier(it->first);
}
if(type == blink::WebInputEvent::Type::MouseWheel){
bool precise = true;
x = 0;
y = 0;
data.Get(switches::kX, &x);
data.Get(switches::kY, &y);
data.Get(switches::kMouseWheelPrecise, &precise);
window_->SendMouseWheelEvent(modifiers, x, y, precise);
}else{
if (data.Get(switches::kX, &x) && data.Get(switches::kY, &y)) {
if(!data.Get(switches::kMovementX, &movementX)){
movementX = 0;
}
if(!data.Get(switches::kMovementY, &movementY)){
movementY = 0;
}
if(!data.Get(switches::kClickCount, &clickCount)){
clickCount = 0;
}
window_->SendMouseEvent(type, modifiers, button, x, y, movementX, movementY, clickCount);
}
}
}
int32_t Window::ID() const { int32_t Window::ID() const {
return weak_map_id(); return weak_map_id();
} }
@ -752,10 +609,6 @@ void Window::BuildPrototype(v8::Isolate* isolate,
&Window::SetVisibleOnAllWorkspaces) &Window::SetVisibleOnAllWorkspaces)
.SetMethod("isVisibleOnAllWorkspaces", .SetMethod("isVisibleOnAllWorkspaces",
&Window::IsVisibleOnAllWorkspaces) &Window::IsVisibleOnAllWorkspaces)
.SetMethod("sendMouseEvent", &Window::SendMouseEvent)
.SetMethod("sendKeyboardEvent", &Window::SendKeyboardEvent)
.SetMethod("beginFrameSubscription", &Window::BeginFrameSubscription)
.SetMethod("endFrameSubscription", &Window::EndFrameSubscription)
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
.SetMethod("showDefinitionForSelection", .SetMethod("showDefinitionForSelection",
&Window::ShowDefinitionForSelection) &Window::ShowDefinitionForSelection)

View file

@ -53,7 +53,6 @@ class Window : public mate::TrackableObject<Window>,
void OnPageTitleUpdated(bool* prevent_default, void OnPageTitleUpdated(bool* prevent_default,
const std::string& title) override; const std::string& title) override;
void WillCloseWindow(bool* prevent_default) override; void WillCloseWindow(bool* prevent_default) override;
void OnFrameRendered(scoped_ptr<uint8[]> rgb, const int size) override;
void OnWindowClosed() override; void OnWindowClosed() override;
void OnWindowBlur() override; void OnWindowBlur() override;
void OnWindowFocus() override; void OnWindowFocus() override;
@ -142,11 +141,6 @@ class Window : public mate::TrackableObject<Window>,
bool IsMenuBarVisible(); bool IsMenuBarVisible();
void SetAspectRatio(double aspect_ratio, mate::Arguments* args); void SetAspectRatio(double aspect_ratio, mate::Arguments* args);
void SendKeyboardEvent(v8::Isolate* isolate, const mate::Dictionary& data);
void SendMouseEvent(v8::Isolate* isolate, const mate::Dictionary& data);
void BeginFrameSubscription();
void EndFrameSubscription();
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
void ShowDefinitionForSelection(); void ShowDefinitionForSelection();
#endif #endif

View file

@ -0,0 +1,66 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/frame_subscriber.h"
#include "atom/common/node_includes.h"
#include "base/bind.h"
#include "media/base/video_frame.h"
#include "media/base/yuv_convert.h"
namespace atom {
namespace api {
FrameSubscriber::FrameSubscriber(v8::Isolate* isolate,
const gfx::Size& size,
const FrameCaptureCallback& callback)
: isolate_(isolate), size_(size), callback_(callback) {
}
bool FrameSubscriber::ShouldCaptureFrame(
const gfx::Rect& damage_rect,
base::TimeTicks present_time,
scoped_refptr<media::VideoFrame>* storage,
DeliverFrameCallback* callback) {
*storage = media::VideoFrame::CreateFrame(media::VideoFrame::YV12, size_,
gfx::Rect(size_), size_,
base::TimeDelta());
*callback = base::Bind(&FrameSubscriber::OnFrameDelivered,
base::Unretained(this),
*storage);
return true;
}
void FrameSubscriber::OnFrameDelivered(
scoped_refptr<media::VideoFrame> frame, base::TimeTicks, bool result) {
if (!result)
return;
gfx::Rect rect = frame->visible_rect();
size_t rgb_arr_size = rect.width() * rect.height() * 4;
v8::MaybeLocal<v8::Object> buffer = node::Buffer::New(isolate_, rgb_arr_size);
if (buffer.IsEmpty())
return;
// Convert a frame of YUV to 32 bit ARGB.
media::ConvertYUVToRGB32(frame->data(media::VideoFrame::kYPlane),
frame->data(media::VideoFrame::kUPlane),
frame->data(media::VideoFrame::kVPlane),
reinterpret_cast<uint8*>(
node::Buffer::Data(buffer.ToLocalChecked())),
rect.width(), rect.height(),
frame->stride(media::VideoFrame::kYPlane),
frame->stride(media::VideoFrame::kUVPlane),
rect.width() * 4,
media::YV12);
v8::Locker locker(isolate_);
v8::HandleScope handle_scope(isolate_);
callback_.Run(buffer.ToLocalChecked());
}
} // namespace api
} // namespace atom

View file

@ -0,0 +1,45 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_API_FRAME_SUBSCRIBER_H_
#define ATOM_BROWSER_API_FRAME_SUBSCRIBER_H_
#include "base/callback.h"
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
#include "ui/gfx/geometry/size.h"
#include "v8/include/v8.h"
namespace atom {
namespace api {
class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber {
public:
using FrameCaptureCallback = base::Callback<void(v8::Local<v8::Value>)>;
FrameSubscriber(v8::Isolate* isolate,
const gfx::Size& size,
const FrameCaptureCallback& callback);
bool ShouldCaptureFrame(const gfx::Rect& damage_rect,
base::TimeTicks present_time,
scoped_refptr<media::VideoFrame>* storage,
DeliverFrameCallback* callback) override;
private:
void OnFrameDelivered(
scoped_refptr<media::VideoFrame> frame, base::TimeTicks, bool);
v8::Isolate* isolate_;
gfx::Size size_;
FrameCaptureCallback callback_;
DISALLOW_COPY_AND_ASSIGN(FrameSubscriber);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_FRAME_SUBSCRIBER_H_

View file

@ -8,11 +8,6 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "media/base/video_frame.h"
#include "media/base/yuv_convert.h"
#include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h" #include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/window_list.h" #include "atom/browser/window_list.h"
@ -43,11 +38,6 @@
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
#include "ui/gfx/screen.h" #include "ui/gfx/screen.h"
#include "ui/gl/gpu_switching_manager.h" #include "ui/gl/gpu_switching_manager.h"
#include "ui/events/event.h"
using content::NavigationEntry;
using content::RenderWidgetHostView;
using content::RenderWidgetHost;
DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::NativeWindowRelay); DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::NativeWindowRelay);
@ -112,9 +102,8 @@ NativeWindow* NativeWindow::FromWebContents(
content::WebContents* web_contents) { content::WebContents* web_contents) {
WindowList& window_list = *WindowList::GetInstance(); WindowList& window_list = *WindowList::GetInstance();
for (NativeWindow* window : window_list) { for (NativeWindow* window : window_list) {
if (window->web_contents() == web_contents){ if (window->web_contents() == web_contents)
return window; return window;
}
} }
return nullptr; return nullptr;
} }
@ -167,9 +156,6 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
options.Get(switches::kTitle, &title); options.Get(switches::kTitle, &title);
SetTitle(title); SetTitle(title);
offscreen_ = false;
options.Get(switches::kOffScreenRender, &offscreen_);
// Then show it. // Then show it.
bool show = true; bool show = true;
options.Get(switches::kShow, &show); options.Get(switches::kShow, &show);
@ -210,38 +196,6 @@ bool NativeWindow::IsDocumentEdited() {
void NativeWindow::SetMenu(ui::MenuModel* menu) { void NativeWindow::SetMenu(ui::MenuModel* menu) {
} }
void NativeWindow::ShowDefinitionForSelection() {
NOTIMPLEMENTED();
}
void NativeWindow::SetAutoHideMenuBar(bool auto_hide) {
}
bool NativeWindow::IsMenuBarAutoHide() {
return false;
}
void NativeWindow::SetMenuBarVisibility(bool visible) {
}
bool NativeWindow::IsMenuBarVisible() {
return true;
}
double NativeWindow::GetAspectRatio() {
return aspect_ratio_;
}
gfx::Size NativeWindow::GetAspectRatioExtraSize() {
return aspect_ratio_extraSize_;
}
void NativeWindow::SetAspectRatio(double aspect_ratio,
const gfx::Size& extra_size) {
aspect_ratio_ = aspect_ratio;
aspect_ratio_extraSize_ = extra_size;
}
bool NativeWindow::HasModalDialog() { bool NativeWindow::HasModalDialog() {
return has_dialog_attached_; return has_dialog_attached_;
} }
@ -296,27 +250,36 @@ void NativeWindow::CapturePage(const gfx::Rect& rect,
kBGRA_8888_SkColorType); kBGRA_8888_SkColorType);
} }
void NativeWindow::SetFrameSubscription(bool isOffscreen) { void NativeWindow::ShowDefinitionForSelection() {
if (!isOffscreen && !offscreen_) return; NOTIMPLEMENTED();
}
const auto view = web_contents()->GetRenderWidgetHostView(); void NativeWindow::SetAutoHideMenuBar(bool auto_hide) {
}
if (view) { bool NativeWindow::IsMenuBarAutoHide() {
if (isOffscreen) { return false;
scoped_ptr<content::RenderWidgetHostViewFrameSubscriber> subscriber( }
new RenderSubscriber(
view->GetVisibleViewportSize(),
base::Bind(&NativeWindow::OnFrameReceived, base::Unretained(this))
)
);
view->BeginFrameSubscription(subscriber.Pass()); void NativeWindow::SetMenuBarVisibility(bool visible) {
} else { }
view->EndFrameSubscription();
}
offscreen_ = isOffscreen; bool NativeWindow::IsMenuBarVisible() {
} return true;
}
double NativeWindow::GetAspectRatio() {
return aspect_ratio_;
}
gfx::Size NativeWindow::GetAspectRatioExtraSize() {
return aspect_ratio_extraSize_;
}
void NativeWindow::SetAspectRatio(double aspect_ratio,
const gfx::Size& extra_size) {
aspect_ratio_ = aspect_ratio;
aspect_ratio_extraSize_ = extra_size;
} }
void NativeWindow::RequestToClosePage() { void NativeWindow::RequestToClosePage() {
@ -461,69 +424,6 @@ void NativeWindow::DevToolsClosed() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsClosed()); FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsClosed());
} }
void NativeWindow::SendKeyboardEvent(blink::WebInputEvent::Type type, int modifiers, int keycode, int nativeKeycode){
auto keyb_event = new content::NativeWebKeyboardEvent;
keyb_event->nativeKeyCode = nativeKeycode;
keyb_event->windowsKeyCode = keycode;
keyb_event->setKeyIdentifierFromWindowsKeyCode();
keyb_event->type = type;
keyb_event->modifiers = modifiers;
keyb_event->isSystemKey = false;
keyb_event->timeStampSeconds = base::Time::Now().ToDoubleT();
keyb_event->skip_in_browser = false;
if (type == blink::WebInputEvent::Char || type == blink::WebInputEvent::RawKeyDown) {
keyb_event->text[0] = keycode;
keyb_event->unmodifiedText[0] = keycode;
}
const auto view = web_contents()->GetRenderWidgetHostView();
const auto host = view ? view->GetRenderWidgetHost() : nullptr;
host->ForwardKeyboardEvent(*keyb_event);
}
void NativeWindow::SendMouseEvent(blink::WebInputEvent::Type type, int modifiers, blink::WebMouseEvent::Button button, int x, int y, int movementX, int movementY, int clickCount){
auto mouse_event = new blink::WebMouseEvent();
mouse_event->x = x;
mouse_event->y = y;
mouse_event->windowX = x;
mouse_event->windowY = y;
mouse_event->clickCount = clickCount;
mouse_event->type = type;
mouse_event->modifiers = modifiers;
mouse_event->button = button;
mouse_event->timeStampSeconds = base::Time::Now().ToDoubleT();
const auto view = web_contents()->GetRenderWidgetHostView();
const auto host = view ? view->GetRenderWidgetHost() : nullptr;
host->ForwardMouseEvent(*mouse_event);
}
void NativeWindow::SendMouseWheelEvent(int modifiers, int x, int y, bool precise){
auto wheel_event = new blink::WebMouseWheelEvent();
wheel_event->type = blink::WebInputEvent::MouseWheel;
wheel_event->deltaX = x;
wheel_event->deltaY = y;
if(x) wheel_event->wheelTicksX = x > 0.0f ? 1.0f : -1.0f;
if(y) wheel_event->wheelTicksY = y > 0.0f ? 1.0f : -1.0f;
wheel_event->modifiers = modifiers;
wheel_event->hasPreciseScrollingDeltas = precise;
wheel_event->canScroll = true;
const auto view = web_contents()->GetRenderWidgetHostView();
const auto host = view ? view->GetRenderWidgetHost() : nullptr;
host->ForwardWheelEvent(*wheel_event);
}
void NativeWindow::DidFinishLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url) {
SetFrameSubscription(offscreen_);
}
void NativeWindow::RenderViewCreated( void NativeWindow::RenderViewCreated(
content::RenderViewHost* render_view_host) { content::RenderViewHost* render_view_host) {
if (!transparent_) if (!transparent_)
@ -601,43 +501,4 @@ void NativeWindow::OnCapturePageDone(const CapturePageCallback& callback,
callback.Run(bitmap); callback.Run(bitmap);
} }
void NativeWindow::OnFrameReceived(bool result,
scoped_refptr<media::VideoFrame> frame) {
if (result) {
gfx::Rect rect = frame->visible_rect();
const int rgb_arr_size = rect.width() * rect.height() * 4;
scoped_ptr<uint8[]> rgb_bytes(new uint8[rgb_arr_size]);
// Convert a frame of YUV to 32 bit ARGB.
media::ConvertYUVToRGB32(frame->data(media::VideoFrame::kYPlane),
frame->data(media::VideoFrame::kUPlane),
frame->data(media::VideoFrame::kVPlane),
rgb_bytes.get(),
rect.width(), rect.height(),
frame->stride(media::VideoFrame::kYPlane),
frame->stride(media::VideoFrame::kUVPlane),
rect.width() * 4,
media::YV12);
FOR_EACH_OBSERVER(NativeWindowObserver,
observers_,
OnFrameRendered(rgb_bytes.Pass(), rgb_arr_size));
}
}
bool RenderSubscriber::ShouldCaptureFrame(
const gfx::Rect& damage_rect,
base::TimeTicks present_time,
scoped_refptr<media::VideoFrame>* storage,
DeliverFrameCallback* callback) {
last_present_time_ = present_time;
*storage = media::VideoFrame::CreateFrame(media::VideoFrame::YV12, size_,
gfx::Rect(size_), size_,
base::TimeDelta());
*callback = base::Bind(&RenderSubscriber::CallbackMethod, callback_, *storage);
return true;
}
} // namespace atom } // namespace atom

View file

@ -9,10 +9,6 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "media/base/video_frame.h"
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "atom/browser/native_window_observer.h" #include "atom/browser/native_window_observer.h"
#include "atom/browser/ui/accelerator_util.h" #include "atom/browser/ui/accelerator_util.h"
#include "base/cancelable_callback.h" #include "base/cancelable_callback.h"
@ -227,14 +223,6 @@ class NativeWindow : public content::WebContentsObserver,
has_dialog_attached_ = has_dialog_attached; has_dialog_attached_ = has_dialog_attached;
} }
void OnFrameReceived(bool result, scoped_refptr<media::VideoFrame> frame);
void SendKeyboardEvent(blink::WebInputEvent::Type type, int modifiers, int keycode, int nativeKeycode);
void SendMouseEvent(blink::WebInputEvent::Type type, int modifiers, blink::WebMouseEvent::Button button, int x, int y, int movementX, int movementY, int clickCount);
void SendMouseWheelEvent(int modifiers, int x, int y, bool clickCount);
void SetFrameSubscription(bool isOffscreen);
protected: protected:
NativeWindow(brightray::InspectableWebContents* inspectable_web_contents, NativeWindow(brightray::InspectableWebContents* inspectable_web_contents,
const mate::Dictionary& options); const mate::Dictionary& options);
@ -246,7 +234,6 @@ class NativeWindow : public content::WebContentsObserver,
// content::WebContentsObserver: // content::WebContentsObserver:
void RenderViewCreated(content::RenderViewHost* render_view_host) override; void RenderViewCreated(content::RenderViewHost* render_view_host) override;
void DidFinishLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url) override;
void BeforeUnloadDialogCancelled() override; void BeforeUnloadDialogCancelled() override;
void TitleWasSet(content::NavigationEntry* entry, bool explicit_set) override; void TitleWasSet(content::NavigationEntry* entry, bool explicit_set) override;
bool OnMessageReceived(const IPC::Message& message) override; bool OnMessageReceived(const IPC::Message& message) override;
@ -267,8 +254,6 @@ class NativeWindow : public content::WebContentsObserver,
const SkBitmap& bitmap, const SkBitmap& bitmap,
content::ReadbackResponse response); content::ReadbackResponse response);
bool offscreen_;
// Whether window has standard frame. // Whether window has standard frame.
bool has_frame_; bool has_frame_;
@ -311,31 +296,6 @@ class NativeWindow : public content::WebContentsObserver,
DISALLOW_COPY_AND_ASSIGN(NativeWindow); DISALLOW_COPY_AND_ASSIGN(NativeWindow);
}; };
//This class provides a way to listen to frame renders and to use the rendered frames for offscreen rendering
class RenderSubscriber : public content::RenderWidgetHostViewFrameSubscriber {
public:
RenderSubscriber(gfx::Size size, base::Callback<void(bool, scoped_refptr<media::VideoFrame>)> callback) : size_(size), callback_(callback) {}
bool ShouldCaptureFrame(const gfx::Rect& damage_rect,
base::TimeTicks present_time,
scoped_refptr<media::VideoFrame>* storage,
DeliverFrameCallback* callback) override;
base::TimeTicks last_present_time() const { return last_present_time_; }
static void CallbackMethod(base::Callback<void(bool, scoped_refptr<media::VideoFrame>)> callback,
scoped_refptr<media::VideoFrame> frame,
base::TimeTicks present_time,
bool success) {
callback.Run(success, frame);
}
private:
gfx::Size size_;
base::Callback<void(bool, scoped_refptr<media::VideoFrame>)> callback_;
base::TimeTicks last_present_time_;
};
// This class provides a hook to get a NativeWindow from a WebContents. // This class provides a hook to get a NativeWindow from a WebContents.
class NativeWindowRelay : class NativeWindowRelay :
public content::WebContentsUserData<NativeWindowRelay> { public content::WebContentsUserData<NativeWindowRelay> {

View file

@ -27,8 +27,6 @@ class NativeWindowObserver {
const std::string& partition_id, const std::string& partition_id,
WindowOpenDisposition disposition) {} WindowOpenDisposition disposition) {}
virtual void OnFrameRendered(scoped_ptr<uint8[]> rgb, const int size) {}
// Called when user is starting an navigation in web page. // Called when user is starting an navigation in web page.
virtual void WillNavigate(bool* prevent_default, const GURL& url) {} virtual void WillNavigate(bool* prevent_default, const GURL& url) {}

View file

@ -9,6 +9,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "atom/common/keyboad_util.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
@ -17,74 +18,6 @@
namespace accelerator_util { namespace accelerator_util {
namespace {
// Return key code of the char.
ui::KeyboardCode KeyboardCodeFromCharCode(char c, bool* shifted) {
*shifted = false;
switch (c) {
case 8: case 0x7F: return ui::VKEY_BACK;
case 9: return ui::VKEY_TAB;
case 0xD: case 3: return ui::VKEY_RETURN;
case 0x1B: return ui::VKEY_ESCAPE;
case ' ': return ui::VKEY_SPACE;
case 'a': return ui::VKEY_A;
case 'b': return ui::VKEY_B;
case 'c': return ui::VKEY_C;
case 'd': return ui::VKEY_D;
case 'e': return ui::VKEY_E;
case 'f': return ui::VKEY_F;
case 'g': return ui::VKEY_G;
case 'h': return ui::VKEY_H;
case 'i': return ui::VKEY_I;
case 'j': return ui::VKEY_J;
case 'k': return ui::VKEY_K;
case 'l': return ui::VKEY_L;
case 'm': return ui::VKEY_M;
case 'n': return ui::VKEY_N;
case 'o': return ui::VKEY_O;
case 'p': return ui::VKEY_P;
case 'q': return ui::VKEY_Q;
case 'r': return ui::VKEY_R;
case 's': return ui::VKEY_S;
case 't': return ui::VKEY_T;
case 'u': return ui::VKEY_U;
case 'v': return ui::VKEY_V;
case 'w': return ui::VKEY_W;
case 'x': return ui::VKEY_X;
case 'y': return ui::VKEY_Y;
case 'z': return ui::VKEY_Z;
case ')': *shifted = true; case '0': return ui::VKEY_0;
case '!': *shifted = true; case '1': return ui::VKEY_1;
case '@': *shifted = true; case '2': return ui::VKEY_2;
case '#': *shifted = true; case '3': return ui::VKEY_3;
case '$': *shifted = true; case '4': return ui::VKEY_4;
case '%': *shifted = true; case '5': return ui::VKEY_5;
case '^': *shifted = true; case '6': return ui::VKEY_6;
case '&': *shifted = true; case '7': return ui::VKEY_7;
case '*': *shifted = true; case '8': return ui::VKEY_8;
case '(': *shifted = true; case '9': return ui::VKEY_9;
case ':': *shifted = true; case ';': return ui::VKEY_OEM_1;
case '+': *shifted = true; case '=': return ui::VKEY_OEM_PLUS;
case '<': *shifted = true; case ',': return ui::VKEY_OEM_COMMA;
case '_': *shifted = true; case '-': return ui::VKEY_OEM_MINUS;
case '>': *shifted = true; case '.': return ui::VKEY_OEM_PERIOD;
case '?': *shifted = true; case '/': return ui::VKEY_OEM_2;
case '~': *shifted = true; case '`': return ui::VKEY_OEM_3;
case '{': *shifted = true; case '[': return ui::VKEY_OEM_4;
case '|': *shifted = true; case '\\': return ui::VKEY_OEM_5;
case '}': *shifted = true; case ']': return ui::VKEY_OEM_6;
case '"': *shifted = true; case '\'': return ui::VKEY_OEM_7;
default: return ui::VKEY_UNKNOWN;
}
}
} // namespace
bool StringToAccelerator(const std::string& description, bool StringToAccelerator(const std::string& description,
ui::Accelerator* accelerator) { ui::Accelerator* accelerator) {
if (!base::IsStringASCII(description)) { if (!base::IsStringASCII(description)) {
@ -104,7 +37,7 @@ bool StringToAccelerator(const std::string& description,
// to be correct and usually only uses few special tokens. // to be correct and usually only uses few special tokens.
if (tokens[i].size() == 1) { if (tokens[i].size() == 1) {
bool shifted = false; bool shifted = false;
key = KeyboardCodeFromCharCode(tokens[i][0], &shifted); key = atom::KeyboardCodeFromCharCode(tokens[i][0], &shifted);
if (shifted) if (shifted)
modifiers |= ui::EF_SHIFT_DOWN; modifiers |= ui::EF_SHIFT_DOWN;
} else if (tokens[i] == "ctrl" || tokens[i] == "control") { } else if (tokens[i] == "ctrl" || tokens[i] == "control") {

View file

@ -1,118 +0,0 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/common/event_types.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
namespace atom {
namespace event_types {
const char kMouseDown[] = "down";
const char kMouseUp[] = "up";
const char kMouseMove[] = "move";
const char kMouseEnter[] = "enter";
const char kMouseLeave[] = "leave";
const char kContextMenu[] = "context-menu";
const char kMouseWheel[] = "wheel";
const char kKeyDown[] = "down";
const char kKeyUp[] = "up";
const char kChar[] = "char";
const char kMouseLeftButton[] = "left";
const char kMouseRightButton[] = "right";
const char kMouseMiddleButton[] = "middle";
const char kModifierLeftButtonDown[] = "left-button-down";
const char kModifierMiddleButtonDown[] = "middle-button-down";
const char kModifierRightButtonDown[] = "right-button-down";
const char kModifierShiftKey[] = "shift";
const char kModifierControlKey[] = "control";
const char kModifierAltKey[] = "alt";
const char kModifierMetaKey[] = "meta";
const char kModifierCapsLockOn[] = "caps-lock";
const char kModifierNumLockOn[] = "num-lock";
const char kModifierIsKeyPad[] = "keypad";
const char kModifierIsAutoRepeat[] = "auto-repeat";
const char kModifierIsLeft[] = "left";
const char kModifierIsRight[] = "right";
int modifierStrToWebModifier(std::string modifier){
if(modifier.compare(event_types::kModifierLeftButtonDown) == 0){
return blink::WebInputEvent::Modifiers::LeftButtonDown;
}else if(modifier.compare(event_types::kModifierMiddleButtonDown) == 0){
return blink::WebInputEvent::Modifiers::MiddleButtonDown;
}else if(modifier.compare(event_types::kModifierRightButtonDown) == 0){
return blink::WebInputEvent::Modifiers::RightButtonDown;
}else if(modifier.compare(event_types::kMouseLeftButton) == 0){
return blink::WebInputEvent::Modifiers::LeftButtonDown;
}else if(modifier.compare(event_types::kMouseRightButton) == 0){
return blink::WebInputEvent::Modifiers::RightButtonDown;
}else if(modifier.compare(event_types::kMouseMiddleButton) == 0){
return blink::WebInputEvent::Modifiers::MiddleButtonDown;
}else if(modifier.compare(event_types::kModifierIsKeyPad) == 0){
return blink::WebInputEvent::Modifiers::IsKeyPad;
}else if(modifier.compare(event_types::kModifierIsAutoRepeat) == 0){
return blink::WebInputEvent::Modifiers::IsAutoRepeat;
}else if(modifier.compare(event_types::kModifierIsLeft) == 0){
return blink::WebInputEvent::Modifiers::IsLeft;
}else if(modifier.compare(event_types::kModifierIsRight) == 0){
return blink::WebInputEvent::Modifiers::IsRight;
}else if(modifier.compare(event_types::kModifierShiftKey) == 0){
return blink::WebInputEvent::Modifiers::ShiftKey;
}else if(modifier.compare(event_types::kModifierControlKey) == 0){
return blink::WebInputEvent::Modifiers::ControlKey;
}else if(modifier.compare(event_types::kModifierAltKey) == 0){
return blink::WebInputEvent::Modifiers::AltKey;
}else if(modifier.compare(event_types::kModifierMetaKey) == 0){
return blink::WebInputEvent::Modifiers::MetaKey;
}else if(modifier.compare(event_types::kModifierCapsLockOn) == 0){
return blink::WebInputEvent::Modifiers::CapsLockOn;
}else if(modifier.compare(event_types::kModifierNumLockOn) == 0){
return blink::WebInputEvent::Modifiers::NumLockOn;
}else{
return 0;
}
}
} // namespace event_types
} // namespace atom

View file

@ -1,52 +0,0 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_EVENT_TYPES_H_
#define ATOM_COMMON_EVENT_TYPES_H_
#include "third_party/WebKit/public/web/WebInputEvent.h"
namespace atom {
namespace event_types {
extern const char kMouseDown[];
extern const char kMouseUp[];
extern const char kMouseMove[];
extern const char kMouseEnter[];
extern const char kMouseLeave[];
extern const char kContextMenu[];
extern const char kMouseWheel[];
extern const char kKeyDown[];
extern const char kKeyUp[];
extern const char kChar[];
extern const char kMouseLeftButton[];
extern const char kMouseRightButton[];
extern const char kMouseMiddleButton[];
extern const char kModifierLeftButtonDown[];
extern const char kModifierMiddleButtonDown[];
extern const char kModifierRightButtonDown[];
extern const char kModifierShiftKey[];
extern const char kModifierControlKey[];
extern const char kModifierAltKey[];
extern const char kModifierMetaKey[];
extern const char kModifierCapsLockOn[];
extern const char kModifierNumLockOn[];
extern const char kModifierIsKeyPad[];
extern const char kModifierIsAutoRepeat[];
extern const char kModifierIsLeft[];
extern const char kModifierIsRight[];
int modifierStrToWebModifier(std::string modifier);
} // namespace event_types
} // namespace atom
#endif // ATOM_COMMON_EVENT_TYPES_H_

View file

@ -0,0 +1,73 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/common/keyboad_util.h"
namespace atom {
// Return key code of the char.
ui::KeyboardCode KeyboardCodeFromCharCode(char c, bool* shifted) {
*shifted = false;
switch (c) {
case 8: case 0x7F: return ui::VKEY_BACK;
case 9: return ui::VKEY_TAB;
case 0xD: case 3: return ui::VKEY_RETURN;
case 0x1B: return ui::VKEY_ESCAPE;
case ' ': return ui::VKEY_SPACE;
case 'a': return ui::VKEY_A;
case 'b': return ui::VKEY_B;
case 'c': return ui::VKEY_C;
case 'd': return ui::VKEY_D;
case 'e': return ui::VKEY_E;
case 'f': return ui::VKEY_F;
case 'g': return ui::VKEY_G;
case 'h': return ui::VKEY_H;
case 'i': return ui::VKEY_I;
case 'j': return ui::VKEY_J;
case 'k': return ui::VKEY_K;
case 'l': return ui::VKEY_L;
case 'm': return ui::VKEY_M;
case 'n': return ui::VKEY_N;
case 'o': return ui::VKEY_O;
case 'p': return ui::VKEY_P;
case 'q': return ui::VKEY_Q;
case 'r': return ui::VKEY_R;
case 's': return ui::VKEY_S;
case 't': return ui::VKEY_T;
case 'u': return ui::VKEY_U;
case 'v': return ui::VKEY_V;
case 'w': return ui::VKEY_W;
case 'x': return ui::VKEY_X;
case 'y': return ui::VKEY_Y;
case 'z': return ui::VKEY_Z;
case ')': *shifted = true; case '0': return ui::VKEY_0;
case '!': *shifted = true; case '1': return ui::VKEY_1;
case '@': *shifted = true; case '2': return ui::VKEY_2;
case '#': *shifted = true; case '3': return ui::VKEY_3;
case '$': *shifted = true; case '4': return ui::VKEY_4;
case '%': *shifted = true; case '5': return ui::VKEY_5;
case '^': *shifted = true; case '6': return ui::VKEY_6;
case '&': *shifted = true; case '7': return ui::VKEY_7;
case '*': *shifted = true; case '8': return ui::VKEY_8;
case '(': *shifted = true; case '9': return ui::VKEY_9;
case ':': *shifted = true; case ';': return ui::VKEY_OEM_1;
case '+': *shifted = true; case '=': return ui::VKEY_OEM_PLUS;
case '<': *shifted = true; case ',': return ui::VKEY_OEM_COMMA;
case '_': *shifted = true; case '-': return ui::VKEY_OEM_MINUS;
case '>': *shifted = true; case '.': return ui::VKEY_OEM_PERIOD;
case '?': *shifted = true; case '/': return ui::VKEY_OEM_2;
case '~': *shifted = true; case '`': return ui::VKEY_OEM_3;
case '{': *shifted = true; case '[': return ui::VKEY_OEM_4;
case '|': *shifted = true; case '\\': return ui::VKEY_OEM_5;
case '}': *shifted = true; case ']': return ui::VKEY_OEM_6;
case '"': *shifted = true; case '\'': return ui::VKEY_OEM_7;
default: return ui::VKEY_UNKNOWN;
}
}
} // namespace atom

View file

@ -0,0 +1,18 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_KEYBOAD_UTIL_H_
#define ATOM_COMMON_KEYBOAD_UTIL_H_
#include "ui/events/keycodes/keyboard_codes.h"
namespace atom {
// Return key code of the char, and also determine whether the SHIFT key is
// pressed.
ui::KeyboardCode KeyboardCodeFromCharCode(char c, bool* shifted);
} // namespace atom
#endif // ATOM_COMMON_KEYBOAD_UTIL_H_

View file

@ -5,13 +5,204 @@
#include "atom/common/native_mate_converters/blink_converter.h" #include "atom/common/native_mate_converters/blink_converter.h"
#include <string> #include <string>
#include <vector>
#include "atom/common/keyboad_util.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "native_mate/dictionary.h" #include "native_mate/dictionary.h"
#include "third_party/WebKit/public/web/WebDeviceEmulationParams.h" #include "third_party/WebKit/public/web/WebDeviceEmulationParams.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
namespace {
template<typename T>
int VectorToBitArray(const std::vector<T>& vec) {
int bits = 0;
for (const T& item : vec)
bits |= item;
return bits;
}
} // namespace
namespace mate { namespace mate {
template<>
struct Converter<char> {
static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
char* out) {
std::string code = base::StringToLowerASCII(V8ToString(val));
if (code.length() != 1)
return false;
*out = code[0];
return true;
}
};
template<>
struct Converter<blink::WebInputEvent::Type> {
static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
blink::WebInputEvent::Type* out) {
std::string type = base::StringToLowerASCII(V8ToString(val));
if (type == "mousedown")
*out = blink::WebInputEvent::MouseDown;
else if (type == "mouseup")
*out = blink::WebInputEvent::MouseUp;
else if (type == "mousemove")
*out = blink::WebInputEvent::MouseMove;
else if (type == "mouseenter")
*out = blink::WebInputEvent::MouseEnter;
else if (type == "mouseleave")
*out = blink::WebInputEvent::MouseLeave;
else if (type == "contextmenu")
*out = blink::WebInputEvent::ContextMenu;
else if (type == "mousewheel")
*out = blink::WebInputEvent::MouseWheel;
else if (type == "keydown")
*out = blink::WebInputEvent::KeyDown;
else if (type == "keyup")
*out = blink::WebInputEvent::KeyUp;
else if (type == "char")
*out = blink::WebInputEvent::Char;
else if (type == "touchstart")
*out = blink::WebInputEvent::TouchStart;
else if (type == "touchmove")
*out = blink::WebInputEvent::TouchMove;
else if (type == "touchend")
*out = blink::WebInputEvent::TouchEnd;
else if (type == "touchcancel")
*out = blink::WebInputEvent::TouchCancel;
return true;
}
};
template<>
struct Converter<blink::WebInputEvent::Modifiers> {
static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
blink::WebInputEvent::Modifiers* out) {
std::string modifier = base::StringToLowerASCII(V8ToString(val));
if (modifier == "shift")
*out = blink::WebInputEvent::ShiftKey;
else if (modifier == "control" || modifier == "ctrl")
*out = blink::WebInputEvent::ControlKey;
else if (modifier == "alt")
*out = blink::WebInputEvent::AltKey;
else if (modifier == "meta" || modifier == "command" || modifier == "cmd")
*out = blink::WebInputEvent::MetaKey;
else if (modifier == "iskeypad")
*out = blink::WebInputEvent::IsKeyPad;
else if (modifier == "isautorepeat")
*out = blink::WebInputEvent::IsAutoRepeat;
else if (modifier == "leftbuttondown")
*out = blink::WebInputEvent::LeftButtonDown;
else if (modifier == "middlebuttondown")
*out = blink::WebInputEvent::MiddleButtonDown;
else if (modifier == "rightbuttondown")
*out = blink::WebInputEvent::RightButtonDown;
else if (modifier == "capslock")
*out = blink::WebInputEvent::CapsLockOn;
else if (modifier == "numlock")
*out = blink::WebInputEvent::NumLockOn;
else if (modifier == "left")
*out = blink::WebInputEvent::IsLeft;
else if (modifier == "right")
*out = blink::WebInputEvent::IsRight;
return true;
}
};
int GetWebInputEventType(v8::Isolate* isolate, v8::Local<v8::Value> val) {
blink::WebInputEvent::Type type = blink::WebInputEvent::Undefined;
mate::Dictionary dict;
ConvertFromV8(isolate, val, &dict) && dict.Get("type", &type);
return type;
}
bool Converter<blink::WebInputEvent>::FromV8(
v8::Isolate* isolate, v8::Local<v8::Value> val,
blink::WebInputEvent* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
if (!dict.Get("type", &out->type))
return false;
std::vector<blink::WebInputEvent::Modifiers> modifiers;
if (dict.Get("modifiers", &modifiers))
out->modifiers = VectorToBitArray(modifiers);
out->timeStampSeconds = base::Time::Now().ToDoubleT();
return true;
}
bool Converter<blink::WebKeyboardEvent>::FromV8(
v8::Isolate* isolate, v8::Local<v8::Value> val,
blink::WebKeyboardEvent* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
if (!ConvertFromV8(isolate, val, static_cast<blink::WebInputEvent*>(out)))
return false;
char code;
if (!dict.Get("keyCode", &code))
return false;
bool shifted = false;
out->windowsKeyCode = atom::KeyboardCodeFromCharCode(code, &shifted);
if (out->windowsKeyCode == ui::VKEY_UNKNOWN)
return false;
if (shifted)
out->modifiers |= blink::WebInputEvent::ShiftKey;
out->setKeyIdentifierFromWindowsKeyCode();
return true;
}
bool Converter<content::NativeWebKeyboardEvent>::FromV8(
v8::Isolate* isolate, v8::Local<v8::Value> val,
content::NativeWebKeyboardEvent* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
if (!ConvertFromV8(isolate, val, static_cast<blink::WebKeyboardEvent*>(out)))
return false;
dict.Get("skipInBrowser", &out->skip_in_browser);
return true;
}
bool Converter<blink::WebMouseEvent>::FromV8(
v8::Isolate* isolate, v8::Local<v8::Value> val, blink::WebMouseEvent* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
if (!ConvertFromV8(isolate, val, static_cast<blink::WebInputEvent*>(out)))
return false;
if (!dict.Get("x", &out->x) || !dict.Get("y", &out->y))
return false;
dict.Get("globalX", &out->globalX);
dict.Get("globalY", &out->globalY);
dict.Get("movementX", &out->movementX);
dict.Get("movementY", &out->movementY);
dict.Get("clickCount", &out->clickCount);
return true;
}
bool Converter<blink::WebMouseWheelEvent>::FromV8(
v8::Isolate* isolate, v8::Local<v8::Value> val,
blink::WebMouseWheelEvent* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
if (!ConvertFromV8(isolate, val, static_cast<blink::WebMouseEvent*>(out)))
return false;
dict.Get("deltaX", &out->deltaX);
dict.Get("deltaY", &out->deltaY);
dict.Get("wheelTicksX", &out->wheelTicksX);
dict.Get("wheelTicksY", &out->wheelTicksY);
dict.Get("accelerationRatioX", &out->accelerationRatioX);
dict.Get("accelerationRatioY", &out->accelerationRatioY);
dict.Get("hasPreciseScrollingDeltas", &out->hasPreciseScrollingDeltas);
dict.Get("canScroll", &out->canScroll);
return true;
}
bool Converter<blink::WebFloatPoint>::FromV8( bool Converter<blink::WebFloatPoint>::FromV8(
v8::Isolate* isolate, v8::Local<v8::Value> val, blink::WebFloatPoint* out) { v8::Isolate* isolate, v8::Local<v8::Value> val, blink::WebFloatPoint* out) {
mate::Dictionary dict; mate::Dictionary dict;

View file

@ -8,14 +8,54 @@
#include "native_mate/converter.h" #include "native_mate/converter.h"
namespace blink { namespace blink {
class WebInputEvent;
class WebMouseEvent;
class WebMouseWheelEvent;
class WebKeyboardEvent;
struct WebDeviceEmulationParams; struct WebDeviceEmulationParams;
struct WebFloatPoint; struct WebFloatPoint;
struct WebPoint; struct WebPoint;
struct WebSize; struct WebSize;
} }
namespace content {
struct NativeWebKeyboardEvent;
}
namespace mate { namespace mate {
int GetWebInputEventType(v8::Isolate* isolate, v8::Local<v8::Value> val);
template<>
struct Converter<blink::WebInputEvent> {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
blink::WebInputEvent* out);
};
template<>
struct Converter<blink::WebKeyboardEvent> {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
blink::WebKeyboardEvent* out);
};
template<>
struct Converter<content::NativeWebKeyboardEvent> {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
content::NativeWebKeyboardEvent* out);
};
template<>
struct Converter<blink::WebMouseEvent> {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
blink::WebMouseEvent* out);
};
template<>
struct Converter<blink::WebMouseWheelEvent> {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
blink::WebMouseWheelEvent* out);
};
template<> template<>
struct Converter<blink::WebFloatPoint> { struct Converter<blink::WebFloatPoint> {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val, static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,

View file

@ -116,19 +116,6 @@ const char kRegisterStandardSchemes[] = "register-standard-schemes";
// The browser process app model ID // The browser process app model ID
const char kAppUserModelId[] = "app-user-model-id"; const char kAppUserModelId[] = "app-user-model-id";
const char kOffScreenRender[] = "offscreen-render";
const char kModifiers[] = "modifiers";
const char kKeyCode[] = "code";
const char kNativeKeyCode[] = "native";
const char kMovementX[] = "movement-x";
const char kMovementY[] = "movement-y";
const char kClickCount[] = "click-count";
const char kEventType[] = "type";
const char kMouseEventButton[] = "button";
const char kMouseWheelPrecise[] = "precise";
} // namespace switches } // namespace switches
} // namespace atom } // namespace atom

View file

@ -62,19 +62,6 @@ extern const char kRegisterStandardSchemes[];
extern const char kAppUserModelId[]; extern const char kAppUserModelId[];
extern const char kOffScreenRender[];
extern const char kModifiers[];
extern const char kKeyCode[];
extern const char kNativeKeyCode[];
extern const char kMovementX[];
extern const char kMovementY[];
extern const char kClickCount[];
extern const char kEventType[];
extern const char kMouseEventButton[];
extern const char kMouseWheelPrecise[];
} // namespace switches } // namespace switches
} // namespace atom } // namespace atom

View file

@ -292,6 +292,7 @@ registerWebViewElement = ->
"inspectServiceWorker" "inspectServiceWorker"
"print" "print"
"printToPDF" "printToPDF"
"sendInputEvent"
] ]
# Forward proto.foo* method calls to WebViewImpl.foo*. # Forward proto.foo* method calls to WebViewImpl.foo*.

View file

@ -244,15 +244,6 @@ Emitted when DevTools is closed.
Emitted when DevTools is focused / opened. Emitted when DevTools is focused / opened.
### Event: 'frame-rendered'
* `event` Event
* `frame` Buffer
* `size` Number
Emitted when *offscreen render* is enabled, the current frame's pixel data
and size are available.
### Event: 'app-command': ### Event: 'app-command':
Emitted when an [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx) Emitted when an [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx)
@ -781,68 +772,3 @@ Sets whether the window should be visible on all workspaces.
Returns whether the window is visible on all workspaces. Returns whether the window is visible on all workspaces.
**Note:** This API always returns false on Windows. **Note:** This API always returns false on Windows.
### BrowserWindow.beginFrameSubscription()
Enables offscreen rendering, after this call `frame-rendered` events will be
fired when the window receives a new frame from the renderer.
### BrowserWindow.endFrameSubscription()
Enables offscreen rendering, after this call `frame-rendered` events will
no longer be fired if offscreen rendering was enabled before.
### BrowserWindow.sendMouseEvent(options)
Sends a mouse event to the BrowserWindow.
* `options` Object
* `type` String - The type of the mouse event.
* `down` String - Mouse down event.
* `up` String - Mouse up event.
* `move` String - Mouse move event.
* `enter` String - Mouse enter event.
* `leave` String - Mouse leave event.
* `context-menu` String - Context menu event.
* `wheel` String - Mouse wheel event.
* `x` Integer - The x component of the location of the mouse event.
* `y` Integer - The y component of the location of the mouse event.
* `movement-x` Integer - The x component of the mouse movement since the last event.
* `movement-y` Integer - The y component of the mouse movement since the last event.
* `button` String - The mouse button associated with the mouse event. Also sets the associated modifier values on the event.
* `left` String - The left button was pressed.
* `right` String - The right button was pressed.
* `middle` String - The middle button was pressed.
* `click-count` Integer - The number of clicks associated with the mouse event.
* `precise` Boolean - For the `wheel` event type, this option sets the `hasPreciseScrollingDeltas` option of the event.
* `modifiers` Object - The modifier values associated with the event.
* `left-button-down` Boolean - The left mouse button was pressed.
* `middle-button-down` Boolean - The right mouse button was pressed.
* `right-button-down` Boolean - The middle mouse button was pressed.
* `shift` Boolean - The shift key was pressed.
* `control` Boolean - The control key was pressed.
* `alt` Boolean - The alt key was pressed.
* `meta` Boolean - The meta key was pressed.
* `caps-lock` Boolean - The caps-lock key was on.
* `num-lock` Boolean - The num-lock key was on.
### BrowserWindow.sendKeyboardEvent(options)
Sends a keyboard event to the BrowserWindow.
* `options` Object
* `type` String - The type of the keyboard event.
* `down` String - Key down event.
* `up` String - Key up event.
* `char` String - Character event.
* `code` Integer - The key code of the key that generated the event.
* `native` Integer - The native key code of the key that generated the event.
* `modifiers` Object - The modifier values associated with the event.
* `keypad` Boolean - Sets the `IsKeyPad` option of the event.
* `auto-repeat` Boolean - Sets the `IsAutoRepeat` option of the event.
* `left` Boolean - Sets the `IsLeft` option of the event.
* `right` Boolean - Sets the `IsRight` option of the event.
* `shift` Boolean - The shift key was pressed.
* `control` Boolean - The control key was pressed.
* `alt` Boolean - The alt key was pressed.
* `meta` Boolean - The meta key was pressed.
* `caps-lock` Boolean - The caps-lock key was on.
* `num-lock` Boolean - The num-lock key was on.

View file

@ -511,3 +511,57 @@ Enable device emulation with the given parameters.
### `webContents.disableDeviceEmulation()` ### `webContents.disableDeviceEmulation()`
Disable device emulation enabled by `webContents.enableDeviceEmulation`. Disable device emulation enabled by `webContents.enableDeviceEmulation`.
### `webContents.sendInputEvent(event)`
* `event` Object
* `type` String (**required**) - The type of the event, can be `mouseDown`,
`mouseUp`, `mouseEnter`, `mouseLeave`, `contextMenu`, `mouseWheel`,
`keyDown`, `keyUp`, `char`.
* `modifiers` Array - An array of modifiers of the event, can
include `shift`, `control`, `alt`, `meta`, `isKeypad`, `isAutoRepeat`,
`leftButtonDown`, `middleButtonDown`, `rightButtonDown`, `capsLock`,
`numLock`, `left`, `right`.
Sends an input `event` to the page.
For keyboard events, the `event` object also have following properties:
* `keyCode` String (**required**) - A single character that will be sent as
keyboard event. Can be any ASCII character on the keyboard, like `a`, `1`
and `=`.
For mouse events, the `event` object also have following properties:
* `x` Integer (**required**)
* `y` Integer (**required**)
* `globalX` Integer
* `globalY` Integer
* `movementX` Integer
* `movementY` Integer
* `clickCount` Integer
For the `mouseWheel` event, the `event` object also have following properties:
* `deltaX` Integer
* `deltaY` Integer
* `wheelTicksX` Integer
* `wheelTicksY` Integer
* `accelerationRatioX` Integer
* `accelerationRatioY` Integer
* `hasPreciseScrollingDeltas` Boolean
* `canScroll` Boolean
### `webContents.beginFrameSubscription(callback)`
* `callback` Function
Begin subscribing for presentation events and captured frames, the `callback`
will be called with `callback(frameBuffer)` when there is a presentation event.
The `frameBuffer` is a `Buffer` that contains raw pixel data, in the format of
32bit ARGB.
### `webContents.endFrameSubscription()`
End subscribing for frame presentation events.

View file

@ -358,6 +358,15 @@ page can handle it by listening to the `channel` event of `ipc` module.
See [WebContents.send](web-contents.md#webcontentssendchannel-args) for See [WebContents.send](web-contents.md#webcontentssendchannel-args) for
examples. examples.
### `<webview>.sendInputEvent(event)`
* `event` Object
Sends an input `event` to the page.
See [WebContents.sendInputEvent](web-contents.md##webcontentssendinputeventevent)
for detailed description of `event` object.
## DOM events ## DOM events
The following DOM events are available to the `webview` tag: The following DOM events are available to the `webview` tag:

View file

@ -103,6 +103,8 @@
'atom/browser/api/event_emitter.h', 'atom/browser/api/event_emitter.h',
'atom/browser/api/trackable_object.cc', 'atom/browser/api/trackable_object.cc',
'atom/browser/api/trackable_object.h', 'atom/browser/api/trackable_object.h',
'atom/browser/api/frame_subscriber.cc',
'atom/browser/api/frame_subscriber.h',
'atom/browser/auto_updater.cc', 'atom/browser/auto_updater.cc',
'atom/browser/auto_updater.h', 'atom/browser/auto_updater.h',
'atom/browser/auto_updater_delegate.h', 'atom/browser/auto_updater_delegate.h',
@ -283,6 +285,8 @@
'atom/common/google_api_key.h', 'atom/common/google_api_key.h',
'atom/common/id_weak_map.cc', 'atom/common/id_weak_map.cc',
'atom/common/id_weak_map.h', 'atom/common/id_weak_map.h',
'atom/common/keyboad_util.cc',
'atom/common/keyboad_util.h',
'atom/common/linux/application_info.cc', 'atom/common/linux/application_info.cc',
'atom/common/native_mate_converters/accelerator_converter.cc', 'atom/common/native_mate_converters/accelerator_converter.cc',
'atom/common/native_mate_converters/accelerator_converter.h', 'atom/common/native_mate_converters/accelerator_converter.h',
@ -311,8 +315,6 @@
'atom/common/node_includes.h', 'atom/common/node_includes.h',
'atom/common/options_switches.cc', 'atom/common/options_switches.cc',
'atom/common/options_switches.h', 'atom/common/options_switches.h',
'atom/common/event_types.cc',
'atom/common/event_types.h',
'atom/common/platform_util.h', 'atom/common/platform_util.h',
'atom/common/platform_util_linux.cc', 'atom/common/platform_util_linux.cc',
'atom/common/platform_util_mac.mm', 'atom/common/platform_util_mac.mm',

View file

@ -295,11 +295,19 @@ describe 'browser-window module', ->
w.minimize() w.minimize()
describe 'will-navigate event', -> describe 'will-navigate event', ->
return if isCI and process.platform is 'darwin' @timeout 10000
it 'emits when user starts a navigation', (done) -> it 'emits when user starts a navigation', (done) ->
@timeout 10000 url = "file://#{fixtures}/pages/will-navigate.html"
w.webContents.on 'will-navigate', (event, url) -> w.webContents.on 'will-navigate', (event, u) ->
event.preventDefault() event.preventDefault()
assert.equal url, 'https://www.github.com/' assert.equal u, url
done()
w.loadUrl url
describe 'beginFrameSubscription method', ->
it 'subscribes frame updates', (done) ->
w.loadUrl "file://#{fixtures}/api/blank.html"
w.webContents.beginFrameSubscription (data) ->
assert.notEqual data.length, 0
w.webContents.endFrameSubscription()
done() done()
w.loadUrl "file://#{fixtures}/pages/will-navigate.html"

9
spec/fixtures/pages/onkeyup.html vendored Normal file
View file

@ -0,0 +1,9 @@
<html>
<body>
<script type="text/javascript" charset="utf-8">
document.onkeyup = function(e) {
require('ipc').sendToHost('keyup', e.keyCode, e.shiftKey, e.ctrlKey);
}
</script>
</body>
</html>

9
spec/fixtures/pages/onmouseup.html vendored Normal file
View file

@ -0,0 +1,9 @@
<html>
<body>
<script type="text/javascript" charset="utf-8">
document.onmouseup = function(e) {
require('ipc').sendToHost('mouseup', e.x, e.y, e.shiftKey, e.ctrlKey);
}
</script>
</body>
</html>

View file

@ -1,7 +1,7 @@
<html> <html>
<body> <body>
<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
location = 'https://www.github.com' location.reload();
</script> </script>
</body> </body>
</html> </html>

View file

@ -336,3 +336,26 @@ describe '<webview> tag', ->
webview.addEventListener 'did-finish-load', listener2 webview.addEventListener 'did-finish-load', listener2
webview.src = "file://#{fixtures}/pages/fullscreen.html" webview.src = "file://#{fixtures}/pages/fullscreen.html"
document.body.appendChild webview document.body.appendChild webview
describe 'sendInputEvent', ->
it 'can send keyboard event', (done) ->
webview.addEventListener 'ipc-message', (e) ->
assert.equal e.channel, 'keyup'
assert.deepEqual e.args, [67, true, false]
done()
webview.addEventListener 'dom-ready', ->
webview.sendInputEvent type: 'keyup', keyCode: 'c', modifiers: ['shift']
webview.src = "file://#{fixtures}/pages/onkeyup.html"
webview.setAttribute 'nodeintegration', 'on'
document.body.appendChild webview
it 'can send mouse event', (done) ->
webview.addEventListener 'ipc-message', (e) ->
assert.equal e.channel, 'mouseup'
assert.deepEqual e.args, [10, 20, false, true]
done()
webview.addEventListener 'dom-ready', ->
webview.sendInputEvent type: 'mouseup', modifiers: ['ctrl'], x: 10, y: 20
webview.src = "file://#{fixtures}/pages/onmouseup.html"
webview.setAttribute 'nodeintegration', 'on'
document.body.appendChild webview