electron/atom/browser/api/atom_api_window.cc

1072 lines
30 KiB
C++
Raw Normal View History

// Copyright (c) 2013 GitHub, Inc.
2014-04-25 09:49:37 +00:00
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
2014-03-16 00:30:26 +00:00
#include "atom/browser/api/atom_api_window.h"
#include "atom/common/native_mate_converters/value_converter.h"
Implement initial, experimental BrowserView API Right now, `<webview>` is the only way to embed additional content in a `BrowserWindow`. Unfortunately `<webview>` suffers from a [number of problems](https://github.com/electron/electron/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aopen%20label%3Awebview%20). To make matters worse, many of these are upstream Chromium bugs instead of Electron-specific bugs. For us at [Figma](https://www.figma.com), the main issue is very slow performance. Despite the upstream improvements to `<webview>` through the OOPIF work, it is probable that there will continue to be `<webview>`-specific bugs in the future. Therefore, this introduces a `<webview>` alternative to called `BrowserView`, which... - is a thin wrapper around `api::WebContents` (so bugs in `BrowserView` will likely also be bugs in `BrowserWindow` web contents) - is instantiated in the main process like `BrowserWindow` (and unlike `<webview>`, which lives in the DOM of a `BrowserWindow` web contents) - needs to be added to a `BrowserWindow` to display something on the screen This implements the most basic API. The API is expected to evolve and change in the near future and has consequently been marked as experimental. Please do not use this API in production unless you are prepared to deal with breaking changes. In the future, we will want to change the API to support multiple `BrowserView`s per window. We will also want to consider z-ordering auto-resizing, and possibly even nested views.
2017-04-11 17:47:30 +00:00
#include "atom/browser/api/atom_api_browser_view.h"
#include "atom/browser/api/atom_api_menu.h"
2014-04-24 08:45:25 +00:00
#include "atom/browser/api/atom_api_web_contents.h"
#include "atom/browser/browser.h"
#include "atom/browser/native_window.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
2014-10-24 04:48:52 +00:00
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
2015-02-07 01:00:26 +00:00
#include "atom/common/native_mate_converters/image_converter.h"
2015-02-11 01:14:26 +00:00
#include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/options_switches.h"
2016-07-27 16:24:58 +00:00
#include "base/command_line.h"
2016-11-30 07:30:03 +00:00
#include "base/threading/thread_task_runner_handle.h"
#include "content/public/browser/render_process_host.h"
2016-07-27 16:24:58 +00:00
#include "content/public/common/content_switches.h"
#include "native_mate/constructor.h"
#include "native_mate/dictionary.h"
#include "ui/gfx/geometry/rect.h"
2016-05-20 13:22:15 +00:00
#if defined(TOOLKIT_VIEWS)
2015-08-06 03:10:34 +00:00
#include "atom/browser/native_window_views.h"
2016-05-20 13:22:15 +00:00
#endif
#if defined(OS_WIN)
2015-08-06 03:10:34 +00:00
#include "atom/browser/ui/win/taskbar_host.h"
2016-11-12 16:59:57 +00:00
#include "ui/base/win/shell.h"
2015-08-06 03:10:34 +00:00
#endif
2016-09-06 08:24:37 +00:00
#include "atom/common/node_includes.h"
2015-08-06 03:10:34 +00:00
#if defined(OS_WIN)
namespace mate {
template<>
2015-08-06 03:10:34 +00:00
struct Converter<atom::TaskbarHost::ThumbarButton> {
static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
2015-08-06 03:10:34 +00:00
atom::TaskbarHost::ThumbarButton* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
dict.Get("click", &(out->clicked_callback));
dict.Get("tooltip", &(out->tooltip));
dict.Get("flags", &out->flags);
return dict.Get("icon", &(out->icon));
}
};
} // namespace mate
2015-08-06 03:10:34 +00:00
#endif
namespace atom {
namespace api {
namespace {
// Converts binary data to Buffer.
2015-10-29 02:53:48 +00:00
v8::Local<v8::Value> ToBuffer(v8::Isolate* isolate, void* val, int size) {
auto buffer = node::Buffer::Copy(isolate, static_cast<char*>(val), size);
2015-10-29 02:53:48 +00:00
if (buffer.IsEmpty())
return v8::Null(isolate);
else
return buffer.ToLocalChecked();
}
} // namespace
Window::Window(v8::Isolate* isolate, v8::Local<v8::Object> wrapper,
const mate::Dictionary& options) {
mate::Handle<class WebContents> web_contents;
// If no WebContents was passed to the constructor, create it from options.
if (!options.Get("webContents", &web_contents)) {
// Use options.webPreferences to create WebContents.
mate::Dictionary web_preferences = mate::Dictionary::CreateEmpty(isolate);
options.Get(options::kWebPreferences, &web_preferences);
// Copy the backgroundColor to webContents.
v8::Local<v8::Value> value;
if (options.Get(options::kBackgroundColor, &value))
web_preferences.Set(options::kBackgroundColor, value);
v8::Local<v8::Value> transparent;
if (options.Get("transparent", &transparent))
web_preferences.Set("transparent", transparent);
2016-12-20 22:43:52 +00:00
// Offscreen windows are always created frameless.
bool offscreen;
2016-12-21 22:15:05 +00:00
if (web_preferences.Get("offscreen", &offscreen) && offscreen) {
auto window_options = const_cast<mate::Dictionary&>(options);
window_options.Set(options::kFrame, false);
2016-12-20 22:43:52 +00:00
}
// Creates the WebContents used by BrowserWindow.
web_contents = WebContents::Create(isolate, web_preferences);
}
Init(isolate, wrapper, options, web_contents);
}
void Window::Init(v8::Isolate* isolate,
v8::Local<v8::Object> wrapper,
const mate::Dictionary& options,
mate::Handle<class WebContents> web_contents) {
web_contents_.Reset(isolate, web_contents.ToV8());
api_web_contents_ = web_contents.get();
// Keep a copy of the options for later use.
mate::Dictionary(isolate, web_contents->GetWrapper()).Set(
"browserWindowOptions", options);
2016-06-19 03:06:08 +00:00
// The parent window.
mate::Handle<Window> parent;
if (options.Get("parent", &parent))
parent_window_.Reset(isolate, parent.ToV8());
// Creates BrowserWindow.
2016-06-19 03:06:08 +00:00
window_.reset(NativeWindow::Create(
web_contents->managed_web_contents(),
options,
parent.IsEmpty() ? nullptr : parent->window_.get()));
web_contents->SetOwnerWindow(window_.get());
2016-05-20 10:46:05 +00:00
2016-05-20 13:22:15 +00:00
#if defined(TOOLKIT_VIEWS)
2016-05-20 10:46:05 +00:00
// Sets the window icon.
mate::Handle<NativeImage> icon;
2016-05-20 13:22:15 +00:00
if (options.Get(options::kIcon, &icon))
SetIcon(icon);
2016-05-20 10:46:05 +00:00
#endif
2016-07-02 07:16:47 +00:00
window_->InitFromOptions(options);
window_->AddObserver(this);
InitWith(isolate, wrapper);
2016-07-02 07:16:47 +00:00
AttachAsUserData(window_.get());
// We can only append this window to parent window's child windows after this
// window's JS wrapper gets initialized.
if (!parent.IsEmpty())
parent->child_windows_.Set(isolate, ID(), wrapper);
}
Window::~Window() {
if (!window_->IsClosed())
window_->CloseContents(nullptr);
// Destroy the native window in next tick because the native code might be
// iterating all windows.
2016-11-30 07:30:03 +00:00
base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, window_.release());
}
void Window::WillCloseWindow(bool* prevent_default) {
*prevent_default = Emit("close");
}
void Window::WillDestroyNativeObject() {
// Close all child windows before closing current window.
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
for (v8::Local<v8::Value> value : child_windows_.Values(isolate())) {
mate::Handle<Window> child;
if (mate::ConvertFromV8(isolate(), value, &child))
child->window_->CloseImmediately();
}
}
void Window::OnWindowClosed() {
api_web_contents_->DestroyWebContents(true /* async */);
2015-06-24 09:58:12 +00:00
RemoveFromWeakMap();
window_->RemoveObserver(this);
// We can not call Destroy here because we need to call Emit first, but we
// also do not want any method to be used, so just mark as destroyed here.
MarkDestroyed();
Emit("closed");
2016-06-17 07:57:03 +00:00
RemoveFromParentChildWindows();
// Destroy the native class when window is closed.
2016-11-30 07:30:03 +00:00
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, GetDestroyClosure());
}
2017-04-21 20:45:30 +00:00
void Window::OnWindowEndSession() {
Emit("session-end");
2017-04-21 20:45:30 +00:00
}
2013-05-24 09:58:39 +00:00
void Window::OnWindowBlur() {
Emit("blur");
}
void Window::OnWindowFocus() {
Emit("focus");
}
void Window::OnWindowShow() {
Emit("show");
}
void Window::OnWindowHide() {
Emit("hide");
}
2016-06-13 12:19:56 +00:00
void Window::OnReadyToShow() {
Emit("ready-to-show");
}
2014-11-25 04:43:25 +00:00
void Window::OnWindowMaximize() {
Emit("maximize");
}
void Window::OnWindowUnmaximize() {
Emit("unmaximize");
}
void Window::OnWindowMinimize() {
Emit("minimize");
}
void Window::OnWindowRestore() {
Emit("restore");
}
2015-05-09 15:55:10 +00:00
void Window::OnWindowResize() {
2015-05-09 18:03:16 +00:00
Emit("resize");
2015-05-09 15:55:10 +00:00
}
void Window::OnWindowMove() {
2015-05-09 18:03:16 +00:00
Emit("move");
2015-05-09 15:55:10 +00:00
}
2015-05-20 08:37:13 +00:00
void Window::OnWindowMoved() {
Emit("moved");
}
2014-11-25 04:43:25 +00:00
void Window::OnWindowEnterFullScreen() {
Emit("enter-full-screen");
}
void Window::OnWindowLeaveFullScreen() {
Emit("leave-full-screen");
}
2016-01-22 00:31:09 +00:00
void Window::OnWindowScrollTouchBegin() {
Emit("scroll-touch-begin");
}
2016-01-22 00:31:09 +00:00
void Window::OnWindowScrollTouchEnd() {
Emit("scroll-touch-end");
}
void Window::OnWindowScrollTouchEdge() {
Emit("scroll-touch-edge");
}
void Window::OnWindowSwipe(const std::string& direction) {
Emit("swipe", direction);
}
void Window::OnWindowSheetBegin() {
Emit("sheet-begin");
}
void Window::OnWindowSheetEnd() {
Emit("sheet-end");
}
void Window::OnWindowEnterHtmlFullScreen() {
Emit("enter-html-full-screen");
}
void Window::OnWindowLeaveHtmlFullScreen() {
Emit("leave-html-full-screen");
}
void Window::OnRendererUnresponsive() {
Emit("unresponsive");
}
void Window::OnRendererResponsive() {
Emit("responsive");
}
2015-06-25 21:09:25 +00:00
void Window::OnExecuteWindowsCommand(const std::string& command_name) {
2015-06-25 16:25:55 +00:00
Emit("app-command", command_name);
2015-06-18 00:31:50 +00:00
}
void Window::OnTouchBarItemResult(const std::string& item_id,
const base::DictionaryValue& details) {
Emit("-touch-bar-interaction", item_id, details);
}
2015-10-27 01:12:01 +00:00
#if defined(OS_WIN)
void Window::OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) {
if (IsWindowMessageHooked(message)) {
messages_callback_map_[message].Run(
2015-10-29 02:53:48 +00:00
ToBuffer(isolate(), static_cast<void*>(&w_param), sizeof(WPARAM)),
ToBuffer(isolate(), static_cast<void*>(&l_param), sizeof(LPARAM)));
}
2015-10-27 01:12:01 +00:00
}
#endif
// static
mate::WrappableBase* Window::New(mate::Arguments* args) {
2015-03-26 03:34:41 +00:00
if (!Browser::Get()->is_ready()) {
args->ThrowError("Cannot create BrowserWindow before app is ready");
return nullptr;
}
if (args->Length() > 1) {
args->ThrowError();
return nullptr;
}
mate::Dictionary options;
if (!(args->Length() == 1 && args->GetNext(&options))) {
options = mate::Dictionary::CreateEmpty(args->isolate());
}
return new Window(args->isolate(), args->GetThis(), options);
}
void Window::Close() {
window_->Close();
}
void Window::Focus() {
window_->Focus(true);
2013-05-16 14:56:52 +00:00
}
2016-03-11 05:45:51 +00:00
void Window::Blur() {
window_->Focus(false);
}
bool Window::IsFocused() {
return window_->IsFocused();
}
void Window::Show() {
window_->Show();
}
2014-10-17 14:51:20 +00:00
void Window::ShowInactive() {
// This method doesn't make sense for modal window..
if (IsModal())
return;
2014-10-17 14:51:20 +00:00
window_->ShowInactive();
}
void Window::Hide() {
window_->Hide();
2013-10-03 00:27:59 +00:00
}
bool Window::IsVisible() {
return window_->IsVisible();
}
bool Window::IsEnabled() {
return window_->IsEnabled();
}
void Window::Maximize() {
window_->Maximize();
}
void Window::Unmaximize() {
window_->Unmaximize();
}
2014-06-28 01:17:37 +00:00
bool Window::IsMaximized() {
2014-05-14 21:58:49 +00:00
return window_->IsMaximized();
}
void Window::Minimize() {
window_->Minimize();
}
void Window::Restore() {
window_->Restore();
}
2014-07-26 05:58:26 +00:00
bool Window::IsMinimized() {
return window_->IsMinimized();
}
2014-11-25 06:34:14 +00:00
void Window::SetFullScreen(bool fullscreen) {
window_->SetFullScreen(fullscreen);
}
bool Window::IsFullscreen() {
return window_->IsFullscreen();
}
void Window::SetBounds(const gfx::Rect& bounds, mate::Arguments* args) {
2016-01-15 04:54:12 +00:00
bool animate = false;
args->GetNext(&animate);
window_->SetBounds(bounds, animate);
}
gfx::Rect Window::GetBounds() {
return window_->GetBounds();
}
2016-08-04 19:02:24 +00:00
void Window::SetContentBounds(const gfx::Rect& bounds, mate::Arguments* args) {
bool animate = false;
args->GetNext(&animate);
window_->SetContentBounds(bounds, animate);
}
2016-07-29 01:19:17 +00:00
gfx::Rect Window::GetContentBounds() {
return window_->GetContentBounds();
}
void Window::SetSize(int width, int height, mate::Arguments* args) {
2016-01-15 04:54:12 +00:00
bool animate = false;
args->GetNext(&animate);
2016-01-15 04:54:12 +00:00
window_->SetSize(gfx::Size(width, height), animate);
}
std::vector<int> Window::GetSize() {
std::vector<int> result(2);
gfx::Size size = window_->GetSize();
result[0] = size.width();
result[1] = size.height();
return result;
}
void Window::SetContentSize(int width, int height, mate::Arguments* args) {
2016-01-15 04:54:12 +00:00
bool animate = false;
args->GetNext(&animate);
2016-01-15 04:54:12 +00:00
window_->SetContentSize(gfx::Size(width, height), animate);
2014-05-15 08:05:35 +00:00
}
2014-05-15 07:30:04 +00:00
std::vector<int> Window::GetContentSize() {
std::vector<int> result(2);
gfx::Size size = window_->GetContentSize();
result[0] = size.width();
result[1] = size.height();
return result;
}
void Window::SetMinimumSize(int width, int height) {
window_->SetMinimumSize(gfx::Size(width, height));
2013-04-18 07:38:04 +00:00
}
std::vector<int> Window::GetMinimumSize() {
std::vector<int> result(2);
gfx::Size size = window_->GetMinimumSize();
result[0] = size.width();
result[1] = size.height();
return result;
}
void Window::SetMaximumSize(int width, int height) {
window_->SetMaximumSize(gfx::Size(width, height));
2013-04-18 07:38:04 +00:00
}
std::vector<int> Window::GetMaximumSize() {
std::vector<int> result(2);
gfx::Size size = window_->GetMaximumSize();
result[0] = size.width();
result[1] = size.height();
return result;
}
void Window::SetSheetOffset(double offsetY, mate::Arguments* args) {
double offsetX = 0.0;
args->GetNext(&offsetX);
window_->SetSheetOffset(offsetX, offsetY);
2016-04-19 05:45:38 +00:00
}
void Window::SetResizable(bool resizable) {
window_->SetResizable(resizable);
2013-04-18 07:38:04 +00:00
}
bool Window::IsResizable() {
return window_->IsResizable();
}
void Window::SetMovable(bool movable) {
window_->SetMovable(movable);
}
bool Window::IsMovable() {
return window_->IsMovable();
}
void Window::SetMinimizable(bool minimizable) {
window_->SetMinimizable(minimizable);
}
bool Window::IsMinimizable() {
return window_->IsMinimizable();
}
2016-01-22 21:24:33 +00:00
void Window::SetMaximizable(bool maximizable) {
window_->SetMaximizable(maximizable);
}
bool Window::IsMaximizable() {
return window_->IsMaximizable();
}
2016-01-23 07:47:37 +00:00
void Window::SetFullScreenable(bool fullscreenable) {
window_->SetFullScreenable(fullscreenable);
2016-01-22 21:24:33 +00:00
}
2016-01-23 07:47:37 +00:00
bool Window::IsFullScreenable() {
return window_->IsFullScreenable();
2016-01-22 21:24:33 +00:00
}
void Window::SetClosable(bool closable) {
window_->SetClosable(closable);
}
bool Window::IsClosable() {
return window_->IsClosable();
}
void Window::SetAlwaysOnTop(bool top, mate::Arguments* args) {
2016-09-22 02:49:06 +00:00
std::string level = "floating";
int relativeLevel = 0;
std::string error;
args->GetNext(&level);
args->GetNext(&relativeLevel);
window_->SetAlwaysOnTop(top, level, relativeLevel, &error);
if (!error.empty()) {
args->ThrowError(error);
}
2013-04-18 07:38:04 +00:00
}
bool Window::IsAlwaysOnTop() {
return window_->IsAlwaysOnTop();
}
void Window::Center() {
window_->Center();
}
void Window::SetPosition(int x, int y, mate::Arguments* args) {
2016-01-15 04:54:12 +00:00
bool animate = false;
args->GetNext(&animate);
2016-01-15 04:54:12 +00:00
window_->SetPosition(gfx::Point(x, y), animate);
}
std::vector<int> Window::GetPosition() {
std::vector<int> result(2);
gfx::Point pos = window_->GetPosition();
result[0] = pos.x();
result[1] = pos.y();
return result;
}
void Window::SetTitle(const std::string& title) {
window_->SetTitle(title);
2013-04-18 06:30:05 +00:00
}
std::string Window::GetTitle() {
return window_->GetTitle();
}
void Window::FlashFrame(bool flash) {
window_->FlashFrame(flash);
}
void Window::SetSkipTaskbar(bool skip) {
window_->SetSkipTaskbar(skip);
}
void Window::SetKiosk(bool kiosk) {
window_->SetKiosk(kiosk);
}
bool Window::IsKiosk() {
return window_->IsKiosk();
}
2015-10-23 03:35:33 +00:00
void Window::SetBackgroundColor(const std::string& color_name) {
window_->SetBackgroundColor(color_name);
}
void Window::SetHasShadow(bool has_shadow) {
window_->SetHasShadow(has_shadow);
}
bool Window::HasShadow() {
return window_->HasShadow();
}
void Window::FocusOnWebView() {
window_->FocusOnWebView();
}
void Window::BlurWebView() {
window_->BlurWebView();
}
bool Window::IsWebViewFocused() {
return window_->IsWebViewFocused();
}
2013-11-22 06:23:19 +00:00
2014-08-21 13:00:49 +00:00
void Window::SetRepresentedFilename(const std::string& filename) {
window_->SetRepresentedFilename(filename);
}
std::string Window::GetRepresentedFilename() {
return window_->GetRepresentedFilename();
}
void Window::SetDocumentEdited(bool edited) {
window_->SetDocumentEdited(edited);
}
bool Window::IsDocumentEdited() {
return window_->IsDocumentEdited();
}
void Window::SetIgnoreMouseEvents(bool ignore) {
return window_->SetIgnoreMouseEvents(ignore);
}
void Window::SetContentProtection(bool enable) {
return window_->SetContentProtection(enable);
}
2016-06-13 08:10:28 +00:00
void Window::SetFocusable(bool focusable) {
return window_->SetFocusable(focusable);
}
void Window::SetProgressBar(double progress, mate::Arguments* args) {
mate::Dictionary options;
std::string mode;
NativeWindow::ProgressState state = NativeWindow::PROGRESS_NORMAL;
args->GetNext(&options) && options.Get("mode", &mode);
if (mode == "error") {
state = NativeWindow::PROGRESS_ERROR;
} else if (mode == "paused") {
state = NativeWindow::PROGRESS_PAUSED;
} else if (mode == "indeterminate") {
state = NativeWindow::PROGRESS_INDETERMINATE;
} else if (mode == "none") {
state = NativeWindow::PROGRESS_NONE;
}
window_->SetProgressBar(progress, state);
2014-09-17 01:42:47 +00:00
}
2015-02-07 01:07:29 +00:00
void Window::SetOverlayIcon(const gfx::Image& overlay,
2015-02-11 01:14:26 +00:00
const std::string& description) {
2015-02-07 01:07:29 +00:00
window_->SetOverlayIcon(overlay, description);
}
2015-08-06 04:44:07 +00:00
bool Window::SetThumbarButtons(mate::Arguments* args) {
2015-08-06 03:10:34 +00:00
#if defined(OS_WIN)
std::vector<TaskbarHost::ThumbarButton> buttons;
if (!args->GetNext(&buttons)) {
args->ThrowError();
2015-08-06 04:44:07 +00:00
return false;
2015-08-06 03:10:34 +00:00
}
auto window = static_cast<NativeWindowViews*>(window_.get());
2015-08-06 04:44:07 +00:00
return window->taskbar_host().SetThumbarButtons(
window_->GetAcceleratedWidget(), buttons);
2015-08-06 04:44:07 +00:00
#else
return false;
2015-08-06 03:10:34 +00:00
#endif
}
2015-06-24 11:51:11 +00:00
void Window::SetMenu(v8::Isolate* isolate, v8::Local<v8::Value> value) {
mate::Handle<Menu> menu;
if (value->IsObject() &&
mate::V8ToString(value->ToObject()->GetConstructorName()) == "Menu" &&
mate::ConvertFromV8(isolate, value, &menu)) {
menu_.Reset(isolate, menu.ToV8());
window_->SetMenu(menu->model());
} else if (value->IsNull()) {
menu_.Reset();
window_->SetMenu(nullptr);
} else {
isolate->ThrowException(v8::Exception::TypeError(
mate::StringToV8(isolate, "Invalid Menu")));
}
}
2014-11-12 12:31:55 +00:00
void Window::SetAutoHideMenuBar(bool auto_hide) {
window_->SetAutoHideMenuBar(auto_hide);
}
bool Window::IsMenuBarAutoHide() {
return window_->IsMenuBarAutoHide();
}
void Window::SetMenuBarVisibility(bool visible) {
window_->SetMenuBarVisibility(visible);
}
bool Window::IsMenuBarVisible() {
return window_->IsMenuBarVisible();
}
#if defined(OS_WIN)
bool Window::HookWindowMessage(UINT message,
const MessageCallback& callback) {
messages_callback_map_[message] = callback;
return true;
}
void Window::UnhookWindowMessage(UINT message) {
if (!ContainsKey(messages_callback_map_, message))
return;
messages_callback_map_.erase(message);
}
bool Window::IsWindowMessageHooked(UINT message) {
return ContainsKey(messages_callback_map_, message);
}
void Window::UnhookAllWindowMessages() {
messages_callback_map_.clear();
}
2016-07-14 20:27:16 +00:00
bool Window::SetThumbnailClip(const gfx::Rect& region) {
auto window = static_cast<NativeWindowViews*>(window_.get());
return window->taskbar_host().SetThumbnailClip(
window_->GetAcceleratedWidget(), region);
}
bool Window::SetThumbnailToolTip(const std::string& tooltip) {
auto window = static_cast<NativeWindowViews*>(window_.get());
return window->taskbar_host().SetThumbnailToolTip(
window_->GetAcceleratedWidget(), tooltip);
}
void Window::SetAppDetails(const mate::Dictionary& options) {
base::string16 app_id;
base::FilePath app_icon_path;
2016-11-28 22:26:30 +00:00
int app_icon_index = 0;
base::string16 relaunch_command;
base::string16 relaunch_display_name;
options.Get("appId", &app_id);
options.Get("appIconPath", &app_icon_path);
options.Get("appIconIndex", &app_icon_index);
options.Get("relaunchCommand", &relaunch_command);
options.Get("relaunchDisplayName", &relaunch_display_name);
ui::win::SetAppDetailsForWindow(
app_id, app_icon_path, app_icon_index,
relaunch_command, relaunch_display_name,
window_->GetAcceleratedWidget());
}
#endif
2016-05-20 13:22:15 +00:00
#if defined(TOOLKIT_VIEWS)
void Window::SetIcon(mate::Handle<NativeImage> icon) {
#if defined(OS_WIN)
static_cast<NativeWindowViews*>(window_.get())->SetIcon(
icon->GetHICON(GetSystemMetrics(SM_CXSMICON)),
icon->GetHICON(GetSystemMetrics(SM_CXICON)));
2016-05-20 13:22:15 +00:00
#elif defined(USE_X11)
static_cast<NativeWindowViews*>(window_.get())->SetIcon(
icon->image().AsImageSkia());
#endif
}
#endif
void Window::SetAspectRatio(double aspect_ratio, mate::Arguments* args) {
gfx::Size extra_size;
args->GetNext(&extra_size);
window_->SetAspectRatio(aspect_ratio, extra_size);
}
2016-10-14 16:42:50 +00:00
void Window::PreviewFile(const std::string& path, mate::Arguments* args) {
2016-10-26 00:47:22 +00:00
std::string display_name;
2016-10-26 00:55:34 +00:00
if (!args->GetNext(&display_name))
2016-10-26 00:47:22 +00:00
display_name = path;
window_->PreviewFile(path, display_name);
2016-10-12 01:08:01 +00:00
}
2016-11-21 18:30:13 +00:00
void Window::CloseFilePreview() {
window_->CloseFilePreview();
}
2016-06-17 07:57:03 +00:00
void Window::SetParentWindow(v8::Local<v8::Value> value,
mate::Arguments* args) {
if (IsModal()) {
args->ThrowError("Can not be called for modal window");
return;
}
2016-06-17 07:57:03 +00:00
mate::Handle<Window> parent;
if (value->IsNull()) {
RemoveFromParentChildWindows();
parent_window_.Reset();
window_->SetParentWindow(nullptr);
} else if (mate::ConvertFromV8(isolate(), value, &parent)) {
2016-06-17 07:09:43 +00:00
parent_window_.Reset(isolate(), value);
2016-06-17 07:57:03 +00:00
window_->SetParentWindow(parent->window_.get());
parent->child_windows_.Set(isolate(), ID(), GetWrapper());
2016-06-17 07:09:43 +00:00
} else {
args->ThrowError("Must pass BrowserWindow instance or null");
}
}
v8::Local<v8::Value> Window::GetParentWindow() const {
2016-06-17 07:09:43 +00:00
if (parent_window_.IsEmpty())
return v8::Null(isolate());
else
return v8::Local<v8::Value>::New(isolate(), parent_window_);
}
std::vector<v8::Local<v8::Object>> Window::GetChildWindows() const {
2016-06-17 07:57:03 +00:00
return child_windows_.Values(isolate());
}
Implement initial, experimental BrowserView API Right now, `<webview>` is the only way to embed additional content in a `BrowserWindow`. Unfortunately `<webview>` suffers from a [number of problems](https://github.com/electron/electron/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aopen%20label%3Awebview%20). To make matters worse, many of these are upstream Chromium bugs instead of Electron-specific bugs. For us at [Figma](https://www.figma.com), the main issue is very slow performance. Despite the upstream improvements to `<webview>` through the OOPIF work, it is probable that there will continue to be `<webview>`-specific bugs in the future. Therefore, this introduces a `<webview>` alternative to called `BrowserView`, which... - is a thin wrapper around `api::WebContents` (so bugs in `BrowserView` will likely also be bugs in `BrowserWindow` web contents) - is instantiated in the main process like `BrowserWindow` (and unlike `<webview>`, which lives in the DOM of a `BrowserWindow` web contents) - needs to be added to a `BrowserWindow` to display something on the screen This implements the most basic API. The API is expected to evolve and change in the near future and has consequently been marked as experimental. Please do not use this API in production unless you are prepared to deal with breaking changes. In the future, we will want to change the API to support multiple `BrowserView`s per window. We will also want to consider z-ordering auto-resizing, and possibly even nested views.
2017-04-11 17:47:30 +00:00
v8::Local<v8::Value> Window::GetBrowserView() const {
if (browser_view_.IsEmpty()) {
return v8::Null(isolate());
}
return v8::Local<v8::Value>::New(isolate(), browser_view_);
}
void Window::SetBrowserView(v8::Local<v8::Value> value) {
mate::Handle<BrowserView> browser_view;
if (value->IsNull()) {
window_->SetBrowserView(nullptr);
browser_view_.Reset();
} else if (mate::ConvertFromV8(isolate(), value, &browser_view)) {
window_->SetBrowserView(browser_view->view());
browser_view_.Reset(isolate(), value);
}
}
bool Window::IsModal() const {
return window_->is_modal();
}
2016-01-07 20:38:35 +00:00
v8::Local<v8::Value> Window::GetNativeWindowHandle() {
gfx::AcceleratedWidget handle = window_->GetAcceleratedWidget();
return ToBuffer(
isolate(), static_cast<void*>(&handle), sizeof(gfx::AcceleratedWidget));
2016-01-07 20:38:35 +00:00
}
void Window::SetVisibleOnAllWorkspaces(bool visible) {
return window_->SetVisibleOnAllWorkspaces(visible);
}
bool Window::IsVisibleOnAllWorkspaces() {
return window_->IsVisibleOnAllWorkspaces();
}
void Window::SetAutoHideCursor(bool auto_hide) {
window_->SetAutoHideCursor(auto_hide);
}
void Window::SetVibrancy(mate::Arguments* args) {
std::string type;
2016-11-07 20:22:41 +00:00
args->GetNext(&type);
window_->SetVibrancy(type);
2016-11-07 20:22:41 +00:00
}
void Window::SetTouchBar(const std::vector<mate::PersistentDictionary>& items) {
window_->SetTouchBar(items);
}
2017-03-01 00:08:12 +00:00
void Window::RefreshTouchBarItem(const std::string& item_id) {
window_->RefreshTouchBarItem(item_id);
}
2017-03-29 04:11:39 +00:00
void Window::SetEscapeTouchBarItem(const mate::PersistentDictionary& item) {
window_->SetEscapeTouchBarItem(item);
}
2015-06-24 08:37:48 +00:00
int32_t Window::ID() const {
return weak_map_id();
}
2015-06-05 09:01:17 +00:00
v8::Local<v8::Value> Window::WebContents(v8::Isolate* isolate) {
Implement initial, experimental BrowserView API Right now, `<webview>` is the only way to embed additional content in a `BrowserWindow`. Unfortunately `<webview>` suffers from a [number of problems](https://github.com/electron/electron/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aopen%20label%3Awebview%20). To make matters worse, many of these are upstream Chromium bugs instead of Electron-specific bugs. For us at [Figma](https://www.figma.com), the main issue is very slow performance. Despite the upstream improvements to `<webview>` through the OOPIF work, it is probable that there will continue to be `<webview>`-specific bugs in the future. Therefore, this introduces a `<webview>` alternative to called `BrowserView`, which... - is a thin wrapper around `api::WebContents` (so bugs in `BrowserView` will likely also be bugs in `BrowserWindow` web contents) - is instantiated in the main process like `BrowserWindow` (and unlike `<webview>`, which lives in the DOM of a `BrowserWindow` web contents) - needs to be added to a `BrowserWindow` to display something on the screen This implements the most basic API. The API is expected to evolve and change in the near future and has consequently been marked as experimental. Please do not use this API in production unless you are prepared to deal with breaking changes. In the future, we will want to change the API to support multiple `BrowserView`s per window. We will also want to consider z-ordering auto-resizing, and possibly even nested views.
2017-04-11 17:47:30 +00:00
if (web_contents_.IsEmpty()) {
return v8::Null(isolate);
Implement initial, experimental BrowserView API Right now, `<webview>` is the only way to embed additional content in a `BrowserWindow`. Unfortunately `<webview>` suffers from a [number of problems](https://github.com/electron/electron/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aopen%20label%3Awebview%20). To make matters worse, many of these are upstream Chromium bugs instead of Electron-specific bugs. For us at [Figma](https://www.figma.com), the main issue is very slow performance. Despite the upstream improvements to `<webview>` through the OOPIF work, it is probable that there will continue to be `<webview>`-specific bugs in the future. Therefore, this introduces a `<webview>` alternative to called `BrowserView`, which... - is a thin wrapper around `api::WebContents` (so bugs in `BrowserView` will likely also be bugs in `BrowserWindow` web contents) - is instantiated in the main process like `BrowserWindow` (and unlike `<webview>`, which lives in the DOM of a `BrowserWindow` web contents) - needs to be added to a `BrowserWindow` to display something on the screen This implements the most basic API. The API is expected to evolve and change in the near future and has consequently been marked as experimental. Please do not use this API in production unless you are prepared to deal with breaking changes. In the future, we will want to change the API to support multiple `BrowserView`s per window. We will also want to consider z-ordering auto-resizing, and possibly even nested views.
2017-04-11 17:47:30 +00:00
}
return v8::Local<v8::Value>::New(isolate, web_contents_);
2014-04-24 08:45:25 +00:00
}
2016-06-17 07:57:03 +00:00
void Window::RemoveFromParentChildWindows() {
if (parent_window_.IsEmpty())
return;
mate::Handle<Window> parent;
if (!mate::ConvertFromV8(isolate(), GetParentWindow(), &parent))
return;
parent->child_windows_.Remove(ID());
2016-06-17 07:57:03 +00:00
}
// static
void Window::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
2016-08-02 10:28:12 +00:00
prototype->SetClassName(mate::StringToV8(isolate, "BrowserWindow"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.MakeDestroyable()
.SetMethod("close", &Window::Close)
.SetMethod("focus", &Window::Focus)
2016-03-11 05:45:51 +00:00
.SetMethod("blur", &Window::Blur)
.SetMethod("isFocused", &Window::IsFocused)
.SetMethod("show", &Window::Show)
2014-10-17 14:51:20 +00:00
.SetMethod("showInactive", &Window::ShowInactive)
.SetMethod("hide", &Window::Hide)
.SetMethod("isVisible", &Window::IsVisible)
.SetMethod("isEnabled", &Window::IsEnabled)
.SetMethod("maximize", &Window::Maximize)
.SetMethod("unmaximize", &Window::Unmaximize)
2014-05-14 21:58:49 +00:00
.SetMethod("isMaximized", &Window::IsMaximized)
.SetMethod("minimize", &Window::Minimize)
.SetMethod("restore", &Window::Restore)
2014-07-26 05:58:26 +00:00
.SetMethod("isMinimized", &Window::IsMinimized)
2014-11-25 06:34:14 +00:00
.SetMethod("setFullScreen", &Window::SetFullScreen)
.SetMethod("isFullScreen", &Window::IsFullscreen)
.SetMethod("setAspectRatio", &Window::SetAspectRatio)
2016-10-12 01:08:01 +00:00
.SetMethod("previewFile", &Window::PreviewFile)
2016-11-21 18:30:13 +00:00
.SetMethod("closeFilePreview", &Window::CloseFilePreview)
#if !defined(OS_WIN)
.SetMethod("setParentWindow", &Window::SetParentWindow)
#endif
2016-06-17 07:09:43 +00:00
.SetMethod("getParentWindow", &Window::GetParentWindow)
2016-06-17 07:57:03 +00:00
.SetMethod("getChildWindows", &Window::GetChildWindows)
Implement initial, experimental BrowserView API Right now, `<webview>` is the only way to embed additional content in a `BrowserWindow`. Unfortunately `<webview>` suffers from a [number of problems](https://github.com/electron/electron/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aopen%20label%3Awebview%20). To make matters worse, many of these are upstream Chromium bugs instead of Electron-specific bugs. For us at [Figma](https://www.figma.com), the main issue is very slow performance. Despite the upstream improvements to `<webview>` through the OOPIF work, it is probable that there will continue to be `<webview>`-specific bugs in the future. Therefore, this introduces a `<webview>` alternative to called `BrowserView`, which... - is a thin wrapper around `api::WebContents` (so bugs in `BrowserView` will likely also be bugs in `BrowserWindow` web contents) - is instantiated in the main process like `BrowserWindow` (and unlike `<webview>`, which lives in the DOM of a `BrowserWindow` web contents) - needs to be added to a `BrowserWindow` to display something on the screen This implements the most basic API. The API is expected to evolve and change in the near future and has consequently been marked as experimental. Please do not use this API in production unless you are prepared to deal with breaking changes. In the future, we will want to change the API to support multiple `BrowserView`s per window. We will also want to consider z-ordering auto-resizing, and possibly even nested views.
2017-04-11 17:47:30 +00:00
.SetMethod("getBrowserView", &Window::GetBrowserView)
.SetMethod("setBrowserView", &Window::SetBrowserView)
.SetMethod("isModal", &Window::IsModal)
2016-01-07 20:38:35 +00:00
.SetMethod("getNativeWindowHandle", &Window::GetNativeWindowHandle)
.SetMethod("getBounds", &Window::GetBounds)
.SetMethod("setBounds", &Window::SetBounds)
.SetMethod("getSize", &Window::GetSize)
.SetMethod("setSize", &Window::SetSize)
2016-07-29 01:19:17 +00:00
.SetMethod("getContentBounds", &Window::GetContentBounds)
2016-08-04 19:02:24 +00:00
.SetMethod("setContentBounds", &Window::SetContentBounds)
2014-05-15 08:05:35 +00:00
.SetMethod("getContentSize", &Window::GetContentSize)
.SetMethod("setContentSize", &Window::SetContentSize)
.SetMethod("setMinimumSize", &Window::SetMinimumSize)
.SetMethod("getMinimumSize", &Window::GetMinimumSize)
.SetMethod("setMaximumSize", &Window::SetMaximumSize)
.SetMethod("getMaximumSize", &Window::GetMaximumSize)
2016-04-19 05:45:38 +00:00
.SetMethod("setSheetOffset", &Window::SetSheetOffset)
.SetMethod("setResizable", &Window::SetResizable)
.SetMethod("isResizable", &Window::IsResizable)
.SetMethod("setMovable", &Window::SetMovable)
.SetMethod("isMovable", &Window::IsMovable)
.SetMethod("setMinimizable", &Window::SetMinimizable)
.SetMethod("isMinimizable", &Window::IsMinimizable)
2016-01-22 21:24:33 +00:00
.SetMethod("setMaximizable", &Window::SetMaximizable)
.SetMethod("isMaximizable", &Window::IsMaximizable)
2016-01-23 07:47:37 +00:00
.SetMethod("setFullScreenable", &Window::SetFullScreenable)
.SetMethod("isFullScreenable", &Window::IsFullScreenable)
.SetMethod("setClosable", &Window::SetClosable)
.SetMethod("isClosable", &Window::IsClosable)
.SetMethod("setAlwaysOnTop", &Window::SetAlwaysOnTop)
.SetMethod("isAlwaysOnTop", &Window::IsAlwaysOnTop)
.SetMethod("center", &Window::Center)
.SetMethod("setPosition", &Window::SetPosition)
.SetMethod("getPosition", &Window::GetPosition)
.SetMethod("setTitle", &Window::SetTitle)
.SetMethod("getTitle", &Window::GetTitle)
.SetMethod("flashFrame", &Window::FlashFrame)
.SetMethod("setSkipTaskbar", &Window::SetSkipTaskbar)
.SetMethod("setKiosk", &Window::SetKiosk)
.SetMethod("isKiosk", &Window::IsKiosk)
2015-10-23 03:35:33 +00:00
.SetMethod("setBackgroundColor", &Window::SetBackgroundColor)
.SetMethod("setHasShadow", &Window::SetHasShadow)
.SetMethod("hasShadow", &Window::HasShadow)
.SetMethod("setRepresentedFilename", &Window::SetRepresentedFilename)
.SetMethod("getRepresentedFilename", &Window::GetRepresentedFilename)
.SetMethod("setDocumentEdited", &Window::SetDocumentEdited)
2014-08-21 13:00:49 +00:00
.SetMethod("isDocumentEdited", &Window::IsDocumentEdited)
.SetMethod("setIgnoreMouseEvents", &Window::SetIgnoreMouseEvents)
.SetMethod("setContentProtection", &Window::SetContentProtection)
2016-06-13 08:10:28 +00:00
.SetMethod("setFocusable", &Window::SetFocusable)
.SetMethod("focusOnWebView", &Window::FocusOnWebView)
.SetMethod("blurWebView", &Window::BlurWebView)
.SetMethod("isWebViewFocused", &Window::IsWebViewFocused)
2014-09-17 01:42:47 +00:00
.SetMethod("setProgressBar", &Window::SetProgressBar)
2015-02-07 00:12:32 +00:00
.SetMethod("setOverlayIcon", &Window::SetOverlayIcon)
.SetMethod("setThumbarButtons", &Window::SetThumbarButtons)
2015-06-24 11:51:11 +00:00
.SetMethod("setMenu", &Window::SetMenu)
2014-11-12 12:31:55 +00:00
.SetMethod("setAutoHideMenuBar", &Window::SetAutoHideMenuBar)
.SetMethod("isMenuBarAutoHide", &Window::IsMenuBarAutoHide)
.SetMethod("setMenuBarVisibility", &Window::SetMenuBarVisibility)
.SetMethod("isMenuBarVisible", &Window::IsMenuBarVisible)
.SetMethod("setVisibleOnAllWorkspaces",
&Window::SetVisibleOnAllWorkspaces)
.SetMethod("isVisibleOnAllWorkspaces",
&Window::IsVisibleOnAllWorkspaces)
#if defined(OS_MACOSX)
.SetMethod("setAutoHideCursor", &Window::SetAutoHideCursor)
#endif
2016-11-07 20:22:41 +00:00
.SetMethod("setVibrancy", &Window::SetVibrancy)
.SetMethod("_setTouchBarItems", &Window::SetTouchBar)
.SetMethod("_refreshTouchBarItem", &Window::RefreshTouchBarItem)
.SetMethod("_setEscapeTouchBarItem", &Window::SetEscapeTouchBarItem)
#if defined(OS_WIN)
.SetMethod("hookWindowMessage", &Window::HookWindowMessage)
.SetMethod("isWindowMessageHooked", &Window::IsWindowMessageHooked)
.SetMethod("unhookWindowMessage", &Window::UnhookWindowMessage)
.SetMethod("unhookAllWindowMessages", &Window::UnhookAllWindowMessages)
2016-07-14 20:27:16 +00:00
.SetMethod("setThumbnailClip", &Window::SetThumbnailClip)
.SetMethod("setThumbnailToolTip", &Window::SetThumbnailToolTip)
.SetMethod("setAppDetails", &Window::SetAppDetails)
#endif
2016-05-20 13:22:15 +00:00
#if defined(TOOLKIT_VIEWS)
.SetMethod("setIcon", &Window::SetIcon)
#endif
.SetProperty("id", &Window::ID)
.SetProperty("webContents", &Window::WebContents);
2013-04-18 16:06:10 +00:00
}
2015-10-01 05:45:59 +00:00
// static
v8::Local<v8::Value> Window::From(v8::Isolate* isolate,
NativeWindow* native_window) {
auto existing = TrackableObject::FromWrappedClass(isolate, native_window);
if (existing)
return existing->GetWrapper();
2015-10-01 05:45:59 +00:00
else
return v8::Null(isolate);
}
} // namespace api
} // namespace atom
namespace {
2015-06-24 08:37:48 +00:00
using atom::api::Window;
2015-05-22 11:11:22 +00:00
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate();
2016-08-02 10:28:12 +00:00
Window::SetConstructor(isolate, base::Bind(&Window::New));
2016-08-02 08:02:04 +00:00
mate::Dictionary browser_window(
isolate, Window::GetConstructor(isolate)->GetFunction());
2015-06-24 09:58:12 +00:00
browser_window.SetMethod("fromId",
&mate::TrackableObject<Window>::FromWeakMapID);
browser_window.SetMethod("getAllWindows",
&mate::TrackableObject<Window>::GetAll);
2015-06-24 08:37:48 +00:00
2014-06-28 11:49:55 +00:00
mate::Dictionary dict(isolate, exports);
2015-06-24 08:37:48 +00:00
dict.Set("BrowserWindow", browser_window);
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_window, Initialize)