diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index c19cf6f7d945..977a241a7da7 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -8,6 +8,8 @@ #include "atom/browser/api/atom_api_web_contents.h" #include "atom/browser/browser.h" #include "atom/browser/native_window.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/gfx_converter.h" #include "atom/common/native_mate_converters/gurl_converter.h" @@ -516,6 +518,144 @@ bool 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; + std::string type_str = ""; + std::vector modifier_array; + + data.Get(switches::kMouseEventType, &type_str); + data.Get(switches::kModifiers, &modifier_array); + data.Get(switches::kKeyCode, &keycode); + + 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; + } + + for(std::vector::iterator mod = modifier_array.begin(); mod != modifier_array.end(); ++mod) { + if(mod->compare(event_types::kModifierIsKeyPad) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::IsKeyPad; + }else if(mod->compare(event_types::kModifierIsAutoRepeat) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::IsAutoRepeat; + }else if(mod->compare(event_types::kModifierIsLeft) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::IsLeft; + }else if(mod->compare(event_types::kModifierIsRight) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::IsRight; + }else if(mod->compare(event_types::kModifierShiftKey) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::ShiftKey; + }else if(mod->compare(event_types::kModifierControlKey) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::ControlKey; + }else if(mod->compare(event_types::kModifierAltKey) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::AltKey; + }else if(mod->compare(event_types::kModifierMetaKey) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::MetaKey; + }else if(mod->compare(event_types::kModifierCapsLockOn) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::CapsLockOn; + }else if(mod->compare(event_types::kModifierNumLockOn) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::NumLockOn; + } + } + + window_->SendKeyboardEvent(type, modifiers, keycode); +} + +void Window::SendMouseEvent(v8::Isolate* isolate, const mate::Dictionary& data){ + int x, y, movementX, movementY, clickCount; + std::string type_str = ""; + std::string button_str = ""; + std::vector modifier_array; + + blink::WebInputEvent::Type type = blink::WebInputEvent::Type::MouseMove; + blink::WebMouseEvent::Button button = blink::WebMouseEvent::Button::ButtonNone; + int modifiers = 0; + + data.Get(switches::kMouseEventType, &type_str); + data.Get(switches::kMouseEventButton, &button_str); + data.Get(switches::kModifiers, &modifier_array); + + 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; + } + + if(button_str.compare(event_types::kMouseLeftButton) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::LeftButtonDown; + button = blink::WebMouseEvent::Button::ButtonLeft; + }else if(button_str.compare(event_types::kMouseRightButton) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::RightButtonDown; + button = blink::WebMouseEvent::Button::ButtonRight; + }else if(button_str.compare(event_types::kMouseMiddleButton) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::MiddleButtonDown; + button = blink::WebMouseEvent::Button::ButtonMiddle; + } + + for(std::vector::iterator mod = modifier_array.begin(); mod != modifier_array.end(); ++mod) { + if(mod->compare(event_types::kModifierLeftButtonDown) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::LeftButtonDown; + }else if(mod->compare(event_types::kModifierMiddleButtonDown) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::MiddleButtonDown; + }else if(mod->compare(event_types::kModifierRightButtonDown) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::RightButtonDown; + }else if(mod->compare(event_types::kModifierShiftKey) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::ShiftKey; + }else if(mod->compare(event_types::kModifierControlKey) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::ControlKey; + }else if(mod->compare(event_types::kModifierAltKey) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::AltKey; + }else if(mod->compare(event_types::kModifierMetaKey) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::MetaKey; + }else if(mod->compare(event_types::kModifierCapsLockOn) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::CapsLockOn; + }else if(mod->compare(event_types::kModifierNumLockOn) == 0){ + modifiers = modifiers & blink::WebInputEvent::Modifiers::NumLockOn; + } + } + + 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 { return weak_map_id(); } @@ -599,6 +739,8 @@ void Window::BuildPrototype(v8::Isolate* isolate, &Window::SetVisibleOnAllWorkspaces) .SetMethod("isVisibleOnAllWorkspaces", &Window::IsVisibleOnAllWorkspaces) + .SetMethod("sendMouseEvent", &Window::SendMouseEvent) + .SetMethod("sendKeyboardEvent", &Window::SendKeyboardEvent) #if defined(OS_MACOSX) .SetMethod("showDefinitionForSelection", &Window::ShowDefinitionForSelection) diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 925aa6749714..8bff9769469e 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -138,6 +138,8 @@ class Window : public mate::TrackableObject, void SetMenuBarVisibility(bool visible); bool IsMenuBarVisible(); 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); #if defined(OS_MACOSX) void ShowDefinitionForSelection(); diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index b21d04aa2389..da7218d2ea74 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -9,6 +9,8 @@ #include #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" @@ -547,10 +549,69 @@ void NativeWindow::DevToolsClosed() { FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsClosed()); } -void NativeWindow::RenderViewReady(){ - if(offscreen_){ - const auto view = web_contents()->GetRenderWidgetHostView(); +void NativeWindow::SendKeyboardEvent(blink::WebInputEvent::Type type, int modifiers, int keycode){ + auto keyb_event = new content::NativeWebKeyboardEvent; + keyb_event->nativeKeyCode = keycode; + 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::KeyDown) { + 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) { + const auto view = web_contents()->GetRenderWidgetHostView(); + const auto host = view ? view->GetRenderWidgetHost() : nullptr; + + if(offscreen_){ scoped_ptr subscriber(new RenderSubscriber( view->GetVisibleViewportSize(), base::Bind(&NativeWindow::OnFrameReceived, base::Unretained(this)) )); diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index 793bd614c8d8..88686ee22f59 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -11,6 +11,8 @@ #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/ui/accelerator_util.h" #include "base/cancelable_callback.h" @@ -236,6 +238,10 @@ class NativeWindow : public content::WebContentsObserver, void OnFrameReceived(bool result, scoped_refptr frame); + void SendKeyboardEvent(blink::WebInputEvent::Type type, int modifiers, int keycode); + 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); + protected: NativeWindow(brightray::InspectableWebContents* inspectable_web_contents, const mate::Dictionary& options); @@ -248,6 +254,7 @@ class NativeWindow : public content::WebContentsObserver, // content::WebContentsObserver: void RenderViewCreated(content::RenderViewHost* render_view_host) override; void RenderViewReady() override; + void DidFinishLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url) override; void BeforeUnloadDialogCancelled() override; void TitleWasSet(content::NavigationEntry* entry, bool explicit_set) override; bool OnMessageReceived(const IPC::Message& message) override; diff --git a/atom/common/event_types.cc b/atom/common/event_types.cc new file mode 100644 index 000000000000..dd87783e68bd --- /dev/null +++ b/atom/common/event_types.cc @@ -0,0 +1,45 @@ +// 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" + +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[] = "key-down"; +const char kKeyUp[] = "key-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"; + +} // namespace switches + +} // namespace atom diff --git a/atom/common/event_types.h b/atom/common/event_types.h new file mode 100644 index 000000000000..b7eae781fc42 --- /dev/null +++ b/atom/common/event_types.h @@ -0,0 +1,48 @@ +// 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_ + +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[]; + +} // namespace switches + +} // namespace atom + +#endif // ATOM_COMMON_EVENT_TYPES_H_ diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index 73a54157fabd..ee70080ae6ae 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -112,6 +112,16 @@ const char kAppUserModelId[] = "app-user-model-id"; const char kOffScreenRender[] = "offscreen-render"; +const char kModifiers[] = "modifiers"; +const char kKeyCode[] = "keycode"; + +const char kMovementX[] = "movement-x"; +const char kMovementY[] = "movement-y"; +const char kClickCount[] = "click-count"; +const char kMouseEventType[] = "type"; +const char kMouseEventButton[] = "button"; +const char kMouseWheelPrecise[] = "precise"; + } // namespace switches } // namespace atom diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index edd37ff03589..505305deb49c 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -62,6 +62,16 @@ extern const char kAppUserModelId[]; extern const char kOffScreenRender[]; +extern const char kModifiers[]; +extern const char kKeyCode[]; + +extern const char kMovementX[]; +extern const char kMovementY[]; +extern const char kClickCount[]; +extern const char kMouseEventType[]; +extern const char kMouseEventButton[]; +extern const char kMouseWheelPrecise[]; + } // namespace switches } // namespace atom diff --git a/filenames.gypi b/filenames.gypi index 40af1ebb1fe7..2e84b73c2c11 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -301,6 +301,8 @@ 'atom/common/node_includes.h', 'atom/common/options_switches.cc', 'atom/common/options_switches.h', + 'atom/common/event_types.cc', + 'atom/common/event_types.h', 'atom/common/platform_util.h', 'atom/common/platform_util_linux.cc', 'atom/common/platform_util_mac.mm',