Merge pull request #12 from electron/master

update as upstream
This commit is contained in:
Heilig Benedek 2016-07-06 14:12:24 +02:00 committed by GitHub
commit 74120493fd
147 changed files with 2605 additions and 1221 deletions

View file

@ -72,6 +72,7 @@ forums
- [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)*
- [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(Japanese)*
- [`electron-tr`](http://www.meetup.com/Electron-JS-Istanbul/) *(Turkish)*
Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron)
for a community maintained list of useful example apps, tools and resources.

View file

@ -463,10 +463,11 @@ void App::DisableHardwareAcceleration(mate::Arguments* args) {
void App::ImportCertificate(
const base::DictionaryValue& options,
const net::CompletionCallback& callback) {
auto browser_context = AtomBrowserMainParts::Get()->browser_context();
auto browser_context = brightray::BrowserContext::From("", false);
if (!certificate_manager_model_) {
std::unique_ptr<base::DictionaryValue> copy = options.CreateDeepCopy();
CertificateManagerModel::Create(browser_context,
CertificateManagerModel::Create(
browser_context.get(),
base::Bind(&App::OnCertificateManagerModelCreated,
base::Unretained(this),
base::Passed(&copy),
@ -519,6 +520,8 @@ void App::BuildPrototype(
base::Bind(&Browser::SetAsDefaultProtocolClient, browser))
.SetMethod("removeAsDefaultProtocolClient",
base::Bind(&Browser::RemoveAsDefaultProtocolClient, browser))
.SetMethod("setBadgeCount", base::Bind(&Browser::SetBadgeCount, browser))
.SetMethod("getBadgeCount", base::Bind(&Browser::GetBadgeCount, browser))
#if defined(OS_MACOSX)
.SetMethod("hide", base::Bind(&Browser::Hide, browser))
.SetMethod("show", base::Bind(&Browser::Show, browser))
@ -528,8 +531,11 @@ void App::BuildPrototype(
base::Bind(&Browser::GetCurrentActivityType, browser))
#endif
#if defined(OS_WIN)
.SetMethod("setUserTasks",
base::Bind(&Browser::SetUserTasks, browser))
.SetMethod("setUserTasks", base::Bind(&Browser::SetUserTasks, browser))
#endif
#if defined(OS_LINUX)
.SetMethod("isUnityRunning",
base::Bind(&Browser::IsUnityRunning, browser))
#endif
.SetMethod("setPath", &App::SetPath)
.SetMethod("getPath", &App::GetPath)

View file

@ -30,7 +30,7 @@ struct Converter<atom::api::Cookies::Error> {
if (val == atom::api::Cookies::SUCCESS)
return v8::Null(isolate);
else
return v8::Exception::Error(StringToV8(isolate, "failed"));
return v8::Exception::Error(StringToV8(isolate, "Setting cookie failed"));
}
};

View file

@ -61,8 +61,10 @@ bool Menu::GetAcceleratorForCommandId(int command_id,
return mate::ConvertFromV8(isolate(), val, accelerator);
}
void Menu::ExecuteCommand(int command_id, int event_flags) {
execute_command_.Run(command_id);
void Menu::ExecuteCommand(int command_id, int flags) {
execute_command_.Run(
mate::internal::CreateEventFromFlags(isolate(), flags),
command_id);
}
void Menu::MenuWillShow(ui::SimpleMenuModel* source) {

View file

@ -90,7 +90,7 @@ class Menu : public mate::TrackableObject<Menu>,
base::Callback<bool(int)> is_enabled_;
base::Callback<bool(int)> is_visible_;
base::Callback<v8::Local<v8::Value>(int)> get_accelerator_;
base::Callback<void(int)> execute_command_;
base::Callback<void(v8::Local<v8::Value>, int)> execute_command_;
base::Callback<void()> menu_will_show_;
DISALLOW_COPY_AND_ASSIGN(Menu);

View file

@ -41,8 +41,10 @@
#include "net/http/http_auth_preferences.h"
#include "net/proxy/proxy_service.h"
#include "net/proxy/proxy_config_service_fixed.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_getter.h"
#include "ui/base/l10n/l10n_util.h"
using content::BrowserThread;
using content::StoragePartition;
@ -93,6 +95,15 @@ uint32_t GetQuotaMask(const std::vector<std::string>& quota_types) {
return quota_mask;
}
void SetUserAgentInIO(scoped_refptr<net::URLRequestContextGetter> getter,
const std::string& accept_lang,
const std::string& user_agent) {
getter->GetURLRequestContext()->set_http_user_agent_settings(
new net::StaticHttpUserAgentSettings(
net::HttpUtil::GenerateAcceptLanguageHeader(accept_lang),
user_agent));
}
} // namespace
namespace mate {
@ -455,6 +466,23 @@ void Session::AllowNTLMCredentialsForDomains(const std::string& domains) {
domains));
}
void Session::SetUserAgent(const std::string& user_agent,
mate::Arguments* args) {
browser_context_->SetUserAgent(user_agent);
std::string accept_lang = l10n_util::GetApplicationLocale("");
args->GetNext(&accept_lang);
auto getter = browser_context_->GetRequestContext();
getter->GetNetworkTaskRunner()->PostTask(
FROM_HERE,
base::Bind(&SetUserAgentInIO, getter, accept_lang, user_agent));
}
std::string Session::GetUserAgent() {
return browser_context_->GetUserAgent();
}
v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
if (cookies_.IsEmpty()) {
auto handle = atom::api::Cookies::Create(isolate, browser_context());
@ -520,6 +548,8 @@ void Session::BuildPrototype(v8::Isolate* isolate,
.SetMethod("clearHostResolverCache", &Session::ClearHostResolverCache)
.SetMethod("allowNTLMCredentialsForDomains",
&Session::AllowNTLMCredentialsForDomains)
.SetMethod("setUserAgent", &Session::SetUserAgent)
.SetMethod("getUserAgent", &Session::GetUserAgent)
.SetProperty("cookies", &Session::Cookies)
.SetProperty("protocol", &Session::Protocol)
.SetProperty("webRequest", &Session::WebRequest);

View file

@ -57,15 +57,7 @@ class Session: public mate::TrackableObject<Session>,
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype);
protected:
Session(v8::Isolate* isolate, AtomBrowserContext* browser_context);
~Session();
// content::DownloadManager::Observer:
void OnDownloadCreated(content::DownloadManager* manager,
content::DownloadItem* item) override;
private:
// Methods.
void ResolveProxy(const GURL& url, ResolveProxyCallback callback);
template<CacheAction action>
void DoCacheAction(const net::CompletionCallback& callback);
@ -80,10 +72,21 @@ class Session: public mate::TrackableObject<Session>,
mate::Arguments* args);
void ClearHostResolverCache(mate::Arguments* args);
void AllowNTLMCredentialsForDomains(const std::string& domains);
void SetUserAgent(const std::string& user_agent, mate::Arguments* args);
std::string GetUserAgent();
v8::Local<v8::Value> Cookies(v8::Isolate* isolate);
v8::Local<v8::Value> Protocol(v8::Isolate* isolate);
v8::Local<v8::Value> WebRequest(v8::Isolate* isolate);
protected:
Session(v8::Isolate* isolate, AtomBrowserContext* browser_context);
~Session();
// content::DownloadManager::Observer:
void OnDownloadCreated(content::DownloadManager* manager,
content::DownloadItem* item) override;
private:
// Cached object.
v8::Global<v8::Value> cookies_;
v8::Global<v8::Value> protocol_;

View file

@ -53,6 +53,10 @@ void SystemPreferences::BuildPrototype(
&SystemPreferences::SubscribeNotification)
.SetMethod("unsubscribeNotification",
&SystemPreferences::UnsubscribeNotification)
.SetMethod("subscribeLocalNotification",
&SystemPreferences::SubscribeLocalNotification)
.SetMethod("unsubscribeLocalNotification",
&SystemPreferences::UnsubscribeLocalNotification)
.SetMethod("getUserDefault", &SystemPreferences::GetUserDefault)
#endif
.SetMethod("isDarkMode", &SystemPreferences::IsDarkMode);

View file

@ -26,17 +26,18 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences> {
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype);
#if defined(OS_MACOSX)
using NotificationCallback = base::Callback<
void(const std::string&, const base::DictionaryValue&)>;
#endif
#if defined(OS_WIN)
bool IsAeroGlassEnabled();
#elif defined(OS_MACOSX)
using NotificationCallback = base::Callback<
void(const std::string&, const base::DictionaryValue&)>;
int SubscribeNotification(const std::string& name,
const NotificationCallback& callback);
void UnsubscribeNotification(int id);
int SubscribeLocalNotification(const std::string& name,
const NotificationCallback& callback);
void UnsubscribeLocalNotification(int request_id);
v8::Local<v8::Value> GetUserDefault(const std::string& name,
const std::string& type);
#endif
@ -46,6 +47,13 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences> {
explicit SystemPreferences(v8::Isolate* isolate);
~SystemPreferences() override;
#if defined(OS_MACOSX)
int DoSubscribeNotification(const std::string& name,
const NotificationCallback& callback,
bool is_local);
void DoUnsubscribeNotification(int request_id, bool is_local);
#endif
private:
DISALLOW_COPY_AND_ASSIGN(SystemPreferences);
};

View file

@ -30,34 +30,59 @@ std::map<int, id> g_id_map;
int SystemPreferences::SubscribeNotification(
const std::string& name, const NotificationCallback& callback) {
return DoSubscribeNotification(name, callback, false);
}
void SystemPreferences::UnsubscribeNotification(int request_id) {
DoUnsubscribeNotification(request_id, false);
}
int SystemPreferences::SubscribeLocalNotification(
const std::string& name, const NotificationCallback& callback) {
return DoSubscribeNotification(name, callback, true);
}
void SystemPreferences::UnsubscribeLocalNotification(int request_id) {
DoUnsubscribeNotification(request_id, true);
}
int SystemPreferences::DoSubscribeNotification(const std::string& name,
const NotificationCallback& callback, bool is_local) {
int request_id = g_next_id++;
__block NotificationCallback copied_callback = callback;
g_id_map[request_id] = [[NSDistributedNotificationCenter defaultCenter]
addObserverForName:base::SysUTF8ToNSString(name)
object:nil
queue:nil
usingBlock:^(NSNotification* notification) {
std::unique_ptr<base::DictionaryValue> user_info =
NSDictionaryToDictionaryValue(notification.userInfo);
if (user_info) {
copied_callback.Run(
base::SysNSStringToUTF8(notification.name),
*user_info);
} else {
copied_callback.Run(
base::SysNSStringToUTF8(notification.name),
base::DictionaryValue());
}
NSNotificationCenter* center = is_local ?
[NSNotificationCenter defaultCenter] :
[NSDistributedNotificationCenter defaultCenter];
g_id_map[request_id] = [center
addObserverForName:base::SysUTF8ToNSString(name)
object:nil
queue:nil
usingBlock:^(NSNotification* notification) {
std::unique_ptr<base::DictionaryValue> user_info =
NSDictionaryToDictionaryValue(notification.userInfo);
if (user_info) {
copied_callback.Run(
base::SysNSStringToUTF8(notification.name),
*user_info);
} else {
copied_callback.Run(
base::SysNSStringToUTF8(notification.name),
base::DictionaryValue());
}
}
];
return request_id;
}
void SystemPreferences::UnsubscribeNotification(int request_id) {
void SystemPreferences::DoUnsubscribeNotification(int request_id, bool is_local) {
auto iter = g_id_map.find(request_id);
if (iter != g_id_map.end()) {
id observer = iter->second;
[[NSDistributedNotificationCenter defaultCenter] removeObserver:observer];
NSNotificationCenter* center = is_local ?
[NSNotificationCenter defaultCenter] :
[NSDistributedNotificationCenter defaultCenter];
[center removeObserver:observer];
g_id_map.erase(iter);
}
}

View file

@ -16,7 +16,6 @@
#include "atom/common/node_includes.h"
#include "native_mate/constructor.h"
#include "native_mate/dictionary.h"
#include "ui/events/event_constants.h"
#include "ui/gfx/image/image.h"
namespace atom {
@ -44,24 +43,15 @@ mate::WrappableBase* Tray::New(v8::Isolate* isolate,
}
void Tray::OnClicked(const gfx::Rect& bounds, int modifiers) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
EmitCustomEvent("click",
ModifiersToObject(isolate(), modifiers), bounds);
EmitWithFlags("click", modifiers, bounds);
}
void Tray::OnDoubleClicked(const gfx::Rect& bounds, int modifiers) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
EmitCustomEvent("double-click",
ModifiersToObject(isolate(), modifiers), bounds);
EmitWithFlags("double-click", modifiers, bounds);
}
void Tray::OnRightClicked(const gfx::Rect& bounds, int modifiers) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
EmitCustomEvent("right-click",
ModifiersToObject(isolate(), modifiers), bounds);
EmitWithFlags("right-click", modifiers, bounds);
}
void Tray::OnBalloonShow() {
@ -159,14 +149,8 @@ void Tray::SetContextMenu(v8::Isolate* isolate, mate::Handle<Menu> menu) {
tray_icon_->SetContextMenu(menu->model());
}
v8::Local<v8::Object> Tray::ModifiersToObject(v8::Isolate* isolate,
int modifiers) {
mate::Dictionary obj(isolate, v8::Object::New(isolate));
obj.Set("shiftKey", static_cast<bool>(modifiers & ui::EF_SHIFT_DOWN));
obj.Set("ctrlKey", static_cast<bool>(modifiers & ui::EF_CONTROL_DOWN));
obj.Set("altKey", static_cast<bool>(modifiers & ui::EF_ALT_DOWN));
obj.Set("metaKey", static_cast<bool>(modifiers & ui::EF_COMMAND_DOWN));
return obj.GetHandle();
gfx::Rect Tray::GetBounds() {
return tray_icon_->GetBounds();
}
// static
@ -181,7 +165,8 @@ void Tray::BuildPrototype(v8::Isolate* isolate,
.SetMethod("setHighlightMode", &Tray::SetHighlightMode)
.SetMethod("displayBalloon", &Tray::DisplayBalloon)
.SetMethod("popUpContextMenu", &Tray::PopUpContextMenu)
.SetMethod("setContextMenu", &Tray::SetContextMenu);
.SetMethod("setContextMenu", &Tray::SetContextMenu)
.SetMethod("getBounds", &Tray::GetBounds);
}
} // namespace api

View file

@ -65,10 +65,9 @@ class Tray : public mate::TrackableObject<Tray>,
void DisplayBalloon(mate::Arguments* args, const mate::Dictionary& options);
void PopUpContextMenu(mate::Arguments* args);
void SetContextMenu(v8::Isolate* isolate, mate::Handle<Menu> menu);
gfx::Rect GetBounds();
private:
v8::Local<v8::Object> ModifiersToObject(v8::Isolate* isolate, int modifiers);
v8::Global<v8::Object> menu_;
std::unique_ptr<TrayIcon> tray_icon_;

View file

@ -17,6 +17,7 @@
#include "atom/browser/lib/bluetooth_chooser.h"
#include "atom/browser/native_window.h"
#include "atom/browser/net/atom_network_delegate.h"
#include "atom/browser/ui/drag_util.h"
#include "atom/browser/web_contents_permission_helper.h"
#include "atom/browser/web_contents_preferences.h"
#include "atom/browser/web_view_guest_delegate.h"
@ -61,11 +62,9 @@
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/static_http_user_agent_settings.h"
#include "net/url_request/url_request_context.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "third_party/WebKit/public/web/WebFindOptions.h"
#include "ui/base/l10n/l10n_util.h"
#include "atom/common/node_includes.h"
@ -76,15 +75,6 @@ struct PrintSettings {
bool print_background;
};
void SetUserAgentInIO(scoped_refptr<net::URLRequestContextGetter> getter,
std::string accept_lang,
std::string user_agent) {
getter->GetURLRequestContext()->set_http_user_agent_settings(
new net::StaticHttpUserAgentSettings(
net::HttpUtil::GenerateAcceptLanguageHeader(accept_lang),
user_agent));
}
} // namespace
namespace mate {
@ -618,7 +608,10 @@ void WebContents::DidFailProvisionalLoad(
bool was_ignored_by_handler) {
bool is_main_frame = !render_frame_host->GetParent();
Emit("did-fail-provisional-load", code, description, url, is_main_frame);
Emit("did-fail-load", code, description, url, is_main_frame);
// Do not emit "did-fail-load" for canceled requests.
if (code != net::ERR_ABORTED)
Emit("did-fail-load", code, description, url, is_main_frame);
}
void WebContents::DidFailLoad(content::RenderFrameHost* render_frame_host,
@ -811,7 +804,7 @@ void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) {
std::string user_agent;
if (options.Get("userAgent", &user_agent))
SetUserAgent(user_agent);
web_contents()->SetUserAgentOverride(user_agent);
std::string extra_headers;
if (options.Get("extraHeaders", &extra_headers))
@ -898,14 +891,9 @@ bool WebContents::IsCrashed() const {
return web_contents()->IsCrashed();
}
void WebContents::SetUserAgent(const std::string& user_agent) {
void WebContents::SetUserAgent(const std::string& user_agent,
mate::Arguments* args) {
web_contents()->SetUserAgentOverride(user_agent);
scoped_refptr<net::URLRequestContextGetter> getter =
web_contents()->GetBrowserContext()->GetRequestContext();
auto accept_lang = l10n_util::GetApplicationLocale("");
getter->GetNetworkTaskRunner()->PostTask(FROM_HERE,
base::Bind(&SetUserAgentInIO, getter, accept_lang, user_agent));
}
std::string WebContents::GetUserAgent() {
@ -1194,15 +1182,14 @@ void WebContents::SendInputEvent(v8::Isolate* isolate,
isolate, "Invalid event object")));
}
void WebContents::BeginFrameSubscription(
mate::Arguments* args) {
FrameSubscriber::FrameCaptureCallback callback;
void WebContents::BeginFrameSubscription(mate::Arguments* args) {
bool only_dirty = false;
FrameSubscriber::FrameCaptureCallback callback;
args->GetNext(&only_dirty);
if (!args->GetNext(&callback)) {
args->GetNext(&only_dirty);
if (!args->GetNext(&callback))
args->ThrowTypeError("'callback' must be defined");
args->ThrowError();
return;
}
const auto view = web_contents()->GetRenderWidgetHostView();
@ -1219,6 +1206,35 @@ void WebContents::EndFrameSubscription() {
view->EndFrameSubscription();
}
void WebContents::StartDrag(const mate::Dictionary& item,
mate::Arguments* args) {
base::FilePath file;
std::vector<base::FilePath> files;
if (!item.Get("files", &files) && item.Get("file", &file)) {
files.push_back(file);
}
mate::Handle<NativeImage> icon;
if (!item.Get("icon", &icon) && !file.empty()) {
// TODO(zcbenz): Set default icon from file.
}
// Error checking.
if (icon.IsEmpty()) {
args->ThrowError("icon must be set");
return;
}
// Start dragging.
if (!files.empty()) {
base::MessageLoop::ScopedNestableTaskAllower allow(
base::MessageLoop::current());
DragFileItems(files, icon->image(), web_contents()->GetNativeView());
} else {
args->ThrowError("There is nothing to drag");
}
}
void WebContents::OnCursorChange(const content::WebCursor& cursor) {
content::WebCursor::CursorInfo info;
cursor.GetCursorInfo(&info);
@ -1338,6 +1354,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
.SetMethod("beginFrameSubscription",
&WebContents::BeginFrameSubscription)
.SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription)
.SetMethod("startDrag", &WebContents::StartDrag)
.SetMethod("setSize", &WebContents::SetSize)
.SetMethod("isGuest", &WebContents::IsGuest)
.SetMethod("getType", &WebContents::GetType)

View file

@ -81,7 +81,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
void GoForward();
void GoToOffset(int offset);
bool IsCrashed() const;
void SetUserAgent(const std::string& user_agent);
void SetUserAgent(const std::string& user_agent, mate::Arguments* args);
std::string GetUserAgent();
void InsertCSS(const std::string& css);
bool SavePage(const base::FilePath& full_file_path,
@ -142,6 +142,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
void BeginFrameSubscription(mate::Arguments* args);
void EndFrameSubscription();
// Dragging native items.
void StartDrag(const mate::Dictionary& item, mate::Arguments* args);
// Methods for creating <webview>.
void SetSize(const SetSizeParams& params);
bool IsGuest() const;

View file

@ -106,9 +106,6 @@ Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) {
options,
parent.IsEmpty() ? nullptr : parent->window_.get()));
web_contents->SetOwnerWindow(window_.get());
window_->InitFromOptions(options);
window_->AddObserver(this);
AttachAsUserData(window_.get());
#if defined(TOOLKIT_VIEWS)
// Sets the window icon.
@ -116,6 +113,10 @@ Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) {
if (options.Get(options::kIcon, &icon))
SetIcon(icon);
#endif
window_->InitFromOptions(options);
window_->AddObserver(this);
AttachAsUserData(window_.get());
}
Window::~Window() {
@ -572,6 +573,10 @@ void Window::SetIgnoreMouseEvents(bool ignore) {
return window_->SetIgnoreMouseEvents(ignore);
}
void Window::SetContentProtection(bool enable) {
return window_->SetContentProtection(enable);
}
void Window::SetFocusable(bool focusable) {
return window_->SetFocusable(focusable);
}
@ -833,6 +838,7 @@ void Window::BuildPrototype(v8::Isolate* isolate,
.SetMethod("setDocumentEdited", &Window::SetDocumentEdited)
.SetMethod("isDocumentEdited", &Window::IsDocumentEdited)
.SetMethod("setIgnoreMouseEvents", &Window::SetIgnoreMouseEvents)
.SetMethod("setContentProtection", &Window::SetContentProtection)
.SetMethod("setFocusable", &Window::SetFocusable)
.SetMethod("focusOnWebView", &Window::FocusOnWebView)
.SetMethod("blurWebView", &Window::BlurWebView)

View file

@ -153,6 +153,7 @@ class Window : public mate::TrackableObject<Window>,
void SetDocumentEdited(bool edited);
bool IsDocumentEdited();
void SetIgnoreMouseEvents(bool ignore);
void SetContentProtection(bool enable);
void SetFocusable(bool focusable);
void CapturePage(mate::Arguments* args);
void SetProgressBar(double progress);

View file

@ -8,6 +8,7 @@
#include "native_mate/arguments.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "ui/events/event_constants.h"
namespace mate {
@ -65,6 +66,15 @@ v8::Local<v8::Object> CreateCustomEvent(
return event;
}
v8::Local<v8::Object> CreateEventFromFlags(v8::Isolate* isolate, int flags) {
mate::Dictionary obj = mate::Dictionary::CreateEmpty(isolate);
obj.Set("shiftKey", static_cast<bool>(flags & ui::EF_SHIFT_DOWN));
obj.Set("ctrlKey", static_cast<bool>(flags & ui::EF_CONTROL_DOWN));
obj.Set("altKey", static_cast<bool>(flags & ui::EF_ALT_DOWN));
obj.Set("metaKey", static_cast<bool>(flags & ui::EF_COMMAND_DOWN));
return obj.GetHandle();
}
} // namespace internal
} // namespace mate

View file

@ -30,6 +30,7 @@ v8::Local<v8::Object> CreateCustomEvent(
v8::Isolate* isolate,
v8::Local<v8::Object> object,
v8::Local<v8::Object> event);
v8::Local<v8::Object> CreateEventFromFlags(v8::Isolate* isolate, int flags);
} // namespace internal
@ -54,6 +55,16 @@ class EventEmitter : public Wrappable<T> {
internal::CreateCustomEvent(isolate(), GetWrapper(), event), args...);
}
// this.emit(name, new Event(flags), args...);
template<typename... Args>
bool EmitWithFlags(const base::StringPiece& name,
int flags,
const Args&... args) {
return EmitCustomEvent(
name,
internal::CreateEventFromFlags(isolate(), flags), args...);
}
// this.emit(name, new Event(), args...);
template<typename... Args>
bool Emit(const base::StringPiece& name, const Args&... args) {

View file

@ -5,8 +5,8 @@
#include "atom/browser/api/frame_subscriber.h"
#include "base/bind.h"
#include "atom/common/node_includes.h"
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "atom/common/node_includes.h"
#include "content/public/browser/render_widget_host.h"
#include <iostream>
@ -31,8 +31,11 @@ FrameSubscriber::FrameSubscriber(v8::Isolate* isolate,
content::RenderWidgetHostView* view,
const FrameCaptureCallback& callback,
bool only_dirty)
: isolate_(isolate), view_(view), callback_(callback),
only_dirty_(only_dirty), weak_factory_(this) {
: isolate_(isolate),
view_(view),
callback_(callback),
only_dirty_(only_dirty),
weak_factory_(this) {
}
bool FrameSubscriber::ShouldCaptureFrame(
@ -87,8 +90,9 @@ void FrameSubscriber::ReadbackResultAsBitmap(
}
void FrameSubscriber::OnFrameDelivered(const FrameCaptureCallback& callback,
const gfx::Rect& damage_rect, const SkBitmap& bitmap,
content::ReadbackResponse response) {
const gfx::Rect& damage_rect,
const SkBitmap& bitmap,
content::ReadbackResponse response) {
if (response != content::ReadbackResponse::READBACK_SUCCESS)
return;
@ -106,7 +110,7 @@ void FrameSubscriber::OnFrameDelivered(const FrameCaptureCallback& callback,
rgb_arr_size);
v8::Local<v8::Value> damage =
mate::Converter<gfx::Rect>::ToV8(isolate_, damage_rect);
mate::Converter<gfx::Rect>::ToV8(isolate_, damage_rect);
callback_.Run(buffer.ToLocalChecked(), damage);
}

View file

@ -35,7 +35,7 @@ class FrameSubscriberRenderWidgetHostView
class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber {
public:
using FrameCaptureCallback =
base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>)>;
base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>)>;
FrameSubscriber(v8::Isolate* isolate,
content::RenderWidgetHostView* view,
@ -52,8 +52,9 @@ class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber {
std::unique_ptr<cc::CopyOutputResult> result);
void OnFrameDelivered(const FrameCaptureCallback& callback,
const gfx::Rect& damage_rect, const SkBitmap& bitmap,
content::ReadbackResponse response);
const gfx::Rect& damage_rect,
const SkBitmap& bitmap,
content::ReadbackResponse response);
v8::Isolate* isolate_;
content::RenderWidgetHostView* view_;

View file

@ -7,8 +7,8 @@
#include <utility>
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/common/google_api_key.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/geolocation_provider.h"
namespace atom {
@ -25,6 +25,7 @@ const char* kGeolocationProviderURL =
} // namespace
AtomAccessTokenStore::AtomAccessTokenStore() {
LOG(ERROR) << "AtomAccessTokenStore";
content::GeolocationProvider::GetInstance()->UserDidOptIntoLocationServices();
}
@ -33,21 +34,35 @@ AtomAccessTokenStore::~AtomAccessTokenStore() {
void AtomAccessTokenStore::LoadAccessTokens(
const LoadAccessTokensCallback& callback) {
AccessTokenMap access_token_map;
// Equivelent to access_token_map[kGeolocationProviderURL].
// Somehow base::string16 is causing compilation errors when used in a pair
// of std::map on Linux, this can work around it.
std::pair<GURL, base::string16> token_pair;
token_pair.first = GURL(kGeolocationProviderURL);
access_token_map.insert(token_pair);
auto browser_context = AtomBrowserMainParts::Get()->browser_context();
callback.Run(access_token_map, browser_context->url_request_context_getter());
content::BrowserThread::PostTaskAndReply(
content::BrowserThread::UI,
FROM_HERE,
base::Bind(&AtomAccessTokenStore::GetRequestContextOnUIThread, this),
base::Bind(&AtomAccessTokenStore::RespondOnOriginatingThread,
this, callback));
}
void AtomAccessTokenStore::SaveAccessToken(const GURL& server_url,
const base::string16& access_token) {
}
void AtomAccessTokenStore::GetRequestContextOnUIThread() {
auto browser_context = brightray::BrowserContext::From("", false);
request_context_getter_ = browser_context->GetRequestContext();
}
void AtomAccessTokenStore::RespondOnOriginatingThread(
const LoadAccessTokensCallback& callback) {
// Equivelent to access_token_map[kGeolocationProviderURL].
// Somehow base::string16 is causing compilation errors when used in a pair
// of std::map on Linux, this can work around it.
AccessTokenMap access_token_map;
std::pair<GURL, base::string16> token_pair;
token_pair.first = GURL(kGeolocationProviderURL);
access_token_map.insert(token_pair);
callback.Run(access_token_map, request_context_getter_.get());
request_context_getter_ = nullptr;
}
} // namespace atom

View file

@ -9,12 +9,10 @@
namespace atom {
class AtomBrowserContext;
class AtomAccessTokenStore : public content::AccessTokenStore {
public:
AtomAccessTokenStore();
virtual ~AtomAccessTokenStore();
~AtomAccessTokenStore();
// content::AccessTokenStore:
void LoadAccessTokens(
@ -23,6 +21,11 @@ class AtomAccessTokenStore : public content::AccessTokenStore {
const base::string16& access_token) override;
private:
void GetRequestContextOnUIThread();
void RespondOnOriginatingThread(const LoadAccessTokensCallback& callback);
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
DISALLOW_COPY_AND_ASSIGN(AtomAccessTokenStore);
};

View file

@ -287,20 +287,21 @@ brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts(
void AtomBrowserClient::WebNotificationAllowed(
int render_process_id,
const base::Callback<void(bool)>& callback) {
const base::Callback<void(bool, bool)>& callback) {
content::WebContents* web_contents =
WebContentsPreferences::GetWebContentsFromProcessID(render_process_id);
if (!web_contents) {
callback.Run(false);
callback.Run(false, false);
return;
}
auto permission_helper =
WebContentsPermissionHelper::FromWebContents(web_contents);
if (!permission_helper) {
callback.Run(false);
callback.Run(false, false);
return;
}
permission_helper->RequestWebNotificationPermission(callback);
permission_helper->RequestWebNotificationPermission(
base::Bind(callback, web_contents->IsAudioMuted()));
}
void AtomBrowserClient::RenderProcessHostDestroyed(

View file

@ -100,7 +100,7 @@ class AtomBrowserClient : public brightray::BrowserClient,
const content::MainFunctionParams&) override;
void WebNotificationAllowed(
int render_process_id,
const base::Callback<void(bool)>& callback) override;
const base::Callback<void(bool, bool)>& callback) override;
// content::RenderProcessHostObserver:
void RenderProcessHostDestroyed(content::RenderProcessHost* host) override;

View file

@ -68,16 +68,7 @@ AtomBrowserContext::AtomBrowserContext(const std::string& partition,
: brightray::BrowserContext(partition, in_memory),
cert_verifier_(new AtomCertVerifier),
network_delegate_(new AtomNetworkDelegate) {
}
AtomBrowserContext::~AtomBrowserContext() {
}
net::NetworkDelegate* AtomBrowserContext::CreateNetworkDelegate() {
return network_delegate_;
}
std::string AtomBrowserContext::GetUserAgent() {
// Construct user agent string.
Browser* browser = Browser::Get();
std::string name = RemoveWhitespace(browser->GetName());
std::string user_agent;
@ -91,7 +82,22 @@ std::string AtomBrowserContext::GetUserAgent() {
browser->GetVersion().c_str(),
CHROME_VERSION_STRING);
}
return content::BuildUserAgentFromProduct(user_agent);
user_agent_ = content::BuildUserAgentFromProduct(user_agent);
}
AtomBrowserContext::~AtomBrowserContext() {
}
void AtomBrowserContext::SetUserAgent(const std::string& user_agent) {
user_agent_ = user_agent;
}
net::NetworkDelegate* AtomBrowserContext::CreateNetworkDelegate() {
return network_delegate_;
}
std::string AtomBrowserContext::GetUserAgent() {
return user_agent_;
}
std::unique_ptr<net::URLRequestJobFactory>

View file

@ -22,6 +22,8 @@ class AtomBrowserContext : public brightray::BrowserContext {
AtomBrowserContext(const std::string& partition, bool in_memory);
~AtomBrowserContext() override;
void SetUserAgent(const std::string& user_agent);
// brightray::URLRequestContextGetter::Delegate:
net::NetworkDelegate* CreateNetworkDelegate() override;
std::string GetUserAgent() override;
@ -47,6 +49,7 @@ class AtomBrowserContext : public brightray::BrowserContext {
std::unique_ptr<AtomDownloadManagerDelegate> download_manager_delegate_;
std::unique_ptr<WebViewManager> guest_manager_;
std::unique_ptr<AtomPermissionManager> permission_manager_;
std::string user_agent_;
// Managed by brightray::BrowserContext.
AtomCertVerifier* cert_verifier_;

View file

@ -124,6 +124,8 @@ void AtomBrowserMainParts::PostEarlyInitialization() {
}
void AtomBrowserMainParts::PreMainMessageLoopRun() {
js_env_->OnMessageLoopCreated();
// Run user's main script before most things get initialized, so we can have
// a chance to setup everything.
node_bindings_->PrepareMessageLoop();
@ -169,6 +171,8 @@ void AtomBrowserMainParts::PostMainMessageLoopStart() {
void AtomBrowserMainParts::PostMainMessageLoopRun() {
brightray::BrowserMainParts::PostMainMessageLoopRun();
js_env_->OnMessageLoopDestroying();
#if defined(OS_MACOSX)
FreeAppDelegate();
#endif

View file

@ -118,6 +118,10 @@ void Browser::SetName(const std::string& name) {
name_override_ = name;
}
int Browser::GetBadgeCount() {
return badge_count_;
}
bool Browser::OpenFile(const std::string& file_path) {
bool prevent_default = false;
FOR_EACH_OBSERVER(BrowserObserver,

View file

@ -87,6 +87,10 @@ class Browser : public WindowListObserver {
// Query the current state of default handler for a protocol.
bool IsDefaultProtocolClient(const std::string& protocol);
// Set/Get the badge count.
bool SetBadgeCount(int count);
int GetBadgeCount();
#if defined(OS_MACOSX)
// Hide the application.
void Hide();
@ -149,7 +153,12 @@ class Browser : public WindowListObserver {
// one from app's name.
// The returned string managed by Browser, and should not be modified.
PCWSTR GetAppUserModelID();
#endif
#endif // defined(OS_WIN)
#if defined(OS_LINUX)
// Whether Unity launcher is running.
bool IsUnityRunning();
#endif // defined(OS_LINUX)
// Tell the application to open a file.
bool OpenFile(const std::string& file_path);
@ -216,6 +225,8 @@ class Browser : public WindowListObserver {
std::string version_override_;
std::string name_override_;
int badge_count_ = 0;
#if defined(OS_WIN)
base::string16 app_user_model_id_;
#endif

View file

@ -10,6 +10,7 @@
#include "atom/browser/window_list.h"
#include "atom/common/atom_version.h"
#include "brightray/common/application_info.h"
#include "chrome/browser/ui/libgtk2ui/unity_service.h"
namespace atom {
@ -46,6 +47,16 @@ bool Browser::IsDefaultProtocolClient(const std::string& protocol) {
return false;
}
bool Browser::SetBadgeCount(int count) {
if (IsUnityRunning()) {
unity::SetDownloadCount(count);
badge_count_ = count;
return true;
} else {
return false;
}
}
std::string Browser::GetExecutableFileVersion() const {
return brightray::GetApplicationVersion();
}
@ -54,4 +65,8 @@ std::string Browser::GetExecutableFileProductName() const {
return brightray::GetApplicationName();
}
bool Browser::IsUnityRunning() {
return unity::IsRunning();
}
} // namespace atom

View file

@ -11,6 +11,7 @@
#include "atom/browser/window_list.h"
#include "base/mac/bundle_locations.h"
#include "base/mac/foundation_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/sys_string_conversions.h"
#include "brightray/common/application_info.h"
#include "net/base/mac/url_conversions.h"
@ -114,6 +115,12 @@ bool Browser::IsDefaultProtocolClient(const std::string& protocol) {
void Browser::SetAppUserModelID(const base::string16& name) {
}
bool Browser::SetBadgeCount(int count) {
DockSetBadgeText(count != 0 ? base::IntToString(count) : "");
badge_count_ = count;
return true;
}
void Browser::SetUserActivity(const std::string& type,
const base::DictionaryValue& user_info,
mate::Arguments* args) {

View file

@ -269,6 +269,10 @@ bool Browser::IsDefaultProtocolClient(const std::string& protocol) {
}
}
bool Browser::SetBadgeCount(int count) {
return false;
}
PCWSTR Browser::GetAppUserModelID() {
if (app_user_model_id_.empty()) {
SetAppUserModelID(base::ReplaceStringPlaceholders(

View file

@ -7,6 +7,7 @@
#include <string>
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
#include "content/public/common/content_switches.h"
#include "gin/array_buffer.h"
#include "gin/v8_initializer.h"
@ -23,6 +24,14 @@ JavascriptEnvironment::JavascriptEnvironment()
context_scope_(v8::Local<v8::Context>::New(isolate_, context_)) {
}
void JavascriptEnvironment::OnMessageLoopCreated() {
isolate_holder_.AddRunMicrotasksObserver();
}
void JavascriptEnvironment::OnMessageLoopDestroying() {
isolate_holder_.RemoveRunMicrotasksObserver();
}
bool JavascriptEnvironment::Initialize() {
auto cmd = base::CommandLine::ForCurrentProcess();
if (cmd->HasSwitch("debug-brk")) {

View file

@ -14,6 +14,9 @@ class JavascriptEnvironment {
public:
JavascriptEnvironment();
void OnMessageLoopCreated();
void OnMessageLoopDestroying();
v8::Isolate* isolate() const { return isolate_; }
v8::Local<v8::Context> context() const {
return v8::Local<v8::Context>::New(isolate_, context_);

View file

@ -157,6 +157,7 @@ class NativeWindow : public base::SupportsUserData,
virtual void SetDocumentEdited(bool edited);
virtual bool IsDocumentEdited();
virtual void SetIgnoreMouseEvents(bool ignore) = 0;
virtual void SetContentProtection(bool enable) = 0;
virtual void SetFocusable(bool focusable);
virtual void SetMenu(ui::MenuModel* menu);
virtual bool HasModalDialog();

View file

@ -79,6 +79,7 @@ class NativeWindowMac : public NativeWindow {
void SetDocumentEdited(bool edited) override;
bool IsDocumentEdited() override;
void SetIgnoreMouseEvents(bool ignore) override;
void SetContentProtection(bool enable) override;
bool HasModalDialog() override;
void SetParentWindow(NativeWindow* parent) override;
gfx::NativeWindow GetNativeWindow() override;

View file

@ -70,6 +70,7 @@ bool ScopedDisableResize::disable_resize_ = false;
@interface AtomNSWindowDelegate : NSObject<NSWindowDelegate> {
@private
atom::NativeWindowMac* shell_;
bool is_zooming_;
}
- (id)initWithShell:(atom::NativeWindowMac*)shell;
@end
@ -79,6 +80,7 @@ bool ScopedDisableResize::disable_resize_ = false;
- (id)initWithShell:(atom::NativeWindowMac*)shell {
if ((self = [super init])) {
shell_ = shell;
is_zooming_ = false;
}
return self;
}
@ -172,16 +174,20 @@ bool ScopedDisableResize::disable_resize_ = false;
}
- (BOOL)windowShouldZoom:(NSWindow*)window toFrame:(NSRect)newFrame {
// Cocoa doen't have concept of maximize/unmaximize, so wee need to emulate
// them by calculating size change when zooming.
if (newFrame.size.width < [window frame].size.width ||
newFrame.size.height < [window frame].size.height)
shell_->NotifyWindowUnmaximize();
else
shell_->NotifyWindowMaximize();
is_zooming_ = true;
return YES;
}
- (void)windowDidEndLiveResize:(NSNotification*)notification {
if (is_zooming_) {
if (shell_->IsMaximized())
shell_->NotifyWindowMaximize();
else
shell_->NotifyWindowUnmaximize();
is_zooming_ = false;
}
}
- (void)windowWillEnterFullScreen:(NSNotification*)notification {
// Hide the native toolbar before entering fullscreen, so there is no visual
// artifacts.
@ -199,6 +205,7 @@ bool ScopedDisableResize::disable_resize_ = false;
// have to set one, because title bar is visible here.
NSWindow* window = shell_->GetNativeWindow();
if ((shell_->transparent() || !shell_->has_frame()) &&
base::mac::IsOSYosemiteOrLater() &&
// FIXME(zcbenz): Showing titlebar for hiddenInset window is weird under
// fullscreen mode.
shell_->title_bar_style() != atom::NativeWindowMac::HIDDEN_INSET) {
@ -223,6 +230,7 @@ bool ScopedDisableResize::disable_resize_ = false;
// Restore the titlebar visibility.
NSWindow* window = shell_->GetNativeWindow();
if ((shell_->transparent() || !shell_->has_frame()) &&
base::mac::IsOSYosemiteOrLater() &&
shell_->title_bar_style() != atom::NativeWindowMac::HIDDEN_INSET) {
[window setTitleVisibility:NSWindowTitleHidden];
}
@ -526,8 +534,10 @@ NativeWindowMac::NativeWindowMac(
[window_ setDisableKeyOrMainWindow:YES];
if (transparent() || !has_frame()) {
// Don't show title bar.
[window_ setTitleVisibility:NSWindowTitleHidden];
if (base::mac::IsOSYosemiteOrLater()) {
// Don't show title bar.
[window_ setTitleVisibility:NSWindowTitleHidden];
}
// Remove non-transparent corners, see http://git.io/vfonD.
[window_ setOpaque:NO];
}
@ -852,6 +862,11 @@ void NativeWindowMac::Center() {
}
void NativeWindowMac::SetTitle(const std::string& title) {
// For macOS <= 10.9, the setTitleVisibility API is not available, we have
// to avoid calling setTitle for frameless window.
if (!base::mac::IsOSYosemiteOrLater() && (transparent() || !has_frame()))
return;
[window_ setTitle:base::SysUTF8ToNSString(title)];
}
@ -935,6 +950,11 @@ void NativeWindowMac::SetIgnoreMouseEvents(bool ignore) {
[window_ setIgnoresMouseEvents:ignore];
}
void NativeWindowMac::SetContentProtection(bool enable) {
[window_ setSharingType:enable ? NSWindowSharingNone
: NSWindowSharingReadOnly];
}
bool NativeWindowMac::HasModalDialog() {
return [window_ attachedSheet] != nil;
}

View file

@ -752,6 +752,13 @@ void NativeWindowViews::SetIgnoreMouseEvents(bool ignore) {
#endif
}
void NativeWindowViews::SetContentProtection(bool enable) {
#if defined(OS_WIN)
DWORD affinity = enable ? WDA_MONITOR : WDA_NONE;
::SetWindowDisplayAffinity(GetAcceleratedWidget(), affinity);
#endif
}
void NativeWindowViews::SetFocusable(bool focusable) {
#if defined(OS_WIN)
LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);

View file

@ -97,6 +97,7 @@ class NativeWindowViews : public NativeWindow,
void SetHasShadow(bool has_shadow) override;
bool HasShadow() override;
void SetIgnoreMouseEvents(bool ignore) override;
void SetContentProtection(bool enable) override;
void SetFocusable(bool focusable) override;
void SetMenu(ui::MenuModel* menu_model) override;
void SetParentWindow(NativeWindow* parent) override;

View file

@ -17,9 +17,9 @@
<key>CFBundleIconFile</key>
<string>electron.icns</string>
<key>CFBundleVersion</key>
<string>1.2.3</string>
<string>1.2.6</string>
<key>CFBundleShortVersionString</key>
<string>1.2.3</string>
<string>1.2.6</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>LSMinimumSystemVersion</key>

View file

@ -56,8 +56,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,2,3,0
PRODUCTVERSION 1,2,3,0
FILEVERSION 1,2,6,0
PRODUCTVERSION 1,2,6,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -74,12 +74,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "GitHub, Inc."
VALUE "FileDescription", "Electron"
VALUE "FileVersion", "1.2.3"
VALUE "FileVersion", "1.2.6"
VALUE "InternalName", "electron.exe"
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
VALUE "OriginalFilename", "electron.exe"
VALUE "ProductName", "Electron"
VALUE "ProductVersion", "1.2.3"
VALUE "ProductVersion", "1.2.6"
VALUE "SquirrelAwareVersion", "1"
END
END

View file

@ -29,6 +29,10 @@ void SetPlatformAccelerator(ui::Accelerator* accelerator) {
modifiers ^= NSShiftKeyMask;
}
if (character == NSDeleteFunctionKey) {
character = NSDeleteCharacter;
}
NSString* characters =
[[[NSString alloc] initWithCharacters:&character length:1] autorelease];

View file

@ -17,12 +17,14 @@ AtomMenuModel::~AtomMenuModel() {
}
void AtomMenuModel::SetRole(int index, const base::string16& role) {
roles_[index] = role;
int command_id = GetCommandIdAt(index);
roles_[command_id] = role;
}
base::string16 AtomMenuModel::GetRoleAt(int index) {
if (ContainsKey(roles_, index))
return roles_[index];
int command_id = GetCommandIdAt(index);
if (ContainsKey(roles_, command_id))
return roles_[command_id];
else
return base::string16();
}

View file

@ -42,7 +42,7 @@ class AtomMenuModel : public ui::SimpleMenuModel {
private:
Delegate* delegate_; // weak ref.
std::map<int, base::string16> roles_;
std::map<int, base::string16> roles_; // command id -> role
base::ObserverList<Observer> observers_;
DISALLOW_COPY_AND_ASSIGN(AtomMenuModel);

View file

@ -38,6 +38,8 @@ Role kRolesMap[] = {
{ @selector(performMiniaturize:), "minimize" },
{ @selector(performClose:), "close" },
{ @selector(performZoom:), "zoom" },
{ @selector(terminate:), "quit" },
{ @selector(toggleFullScreen:), "togglefullscreen" },
};
} // namespace

View file

@ -0,0 +1,24 @@
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_UI_DRAG_UTIL_H_
#define ATOM_BROWSER_UI_DRAG_UTIL_H_
#include <vector>
#include "ui/gfx/image/image.h"
namespace base {
class FilePath;
}
namespace atom {
void DragFileItems(const std::vector<base::FilePath>& files,
const gfx::Image& icon,
gfx::NativeView view);
} // namespace atom
#endif // ATOM_BROWSER_UI_DRAG_UTIL_H_

View file

@ -0,0 +1,58 @@
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#import <Cocoa/Cocoa.h>
#include "atom/browser/ui/drag_util.h"
#include "base/files/file_path.h"
#include "base/strings/sys_string_conversions.h"
namespace atom {
namespace {
// Write information about the file being dragged to the pasteboard.
void AddFilesToPasteboard(NSPasteboard* pasteboard,
const std::vector<base::FilePath>& files) {
NSMutableArray* fileList = [NSMutableArray array];
for (const base::FilePath& file : files)
[fileList addObject:base::SysUTF8ToNSString(file.value())];
[pasteboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType]
owner:nil];
[pasteboard setPropertyList:fileList forType:NSFilenamesPboardType];
}
} // namespace
void DragFileItems(const std::vector<base::FilePath>& files,
const gfx::Image& icon,
gfx::NativeView view) {
NSPasteboard* pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
AddFilesToPasteboard(pasteboard, files);
// Synthesize a drag event, since we don't have access to the actual event
// that initiated a drag (possibly consumed by the Web UI, for example).
NSPoint position = [[view window] mouseLocationOutsideOfEventStream];
NSTimeInterval eventTime = [[NSApp currentEvent] timestamp];
NSEvent* dragEvent = [NSEvent mouseEventWithType:NSLeftMouseDragged
location:position
modifierFlags:NSLeftMouseDraggedMask
timestamp:eventTime
windowNumber:[[view window] windowNumber]
context:nil
eventNumber:0
clickCount:1
pressure:1.0];
// Run the drag operation.
[[view window] dragImage:icon.ToNSImage()
at:position
offset:NSZeroSize
event:dragEvent
pasteboard:pasteboard
source:view
slideBack:YES];
}
} // namespace atom

View file

@ -0,0 +1,48 @@
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/ui/drag_util.h"
#include "ui/aura/window.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/drag_utils.h"
#include "ui/base/dragdrop/file_info.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/screen.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/public/drag_drop_client.h"
namespace atom {
void DragFileItems(const std::vector<base::FilePath>& files,
const gfx::Image& icon,
gfx::NativeView view) {
// Set up our OLE machinery
ui::OSExchangeData data;
drag_utils::CreateDragImageForFile(files[0], icon.AsImageSkia(), &data);
std::vector<ui::FileInfo> file_infos;
for (const base::FilePath& file : files) {
file_infos.push_back(ui::FileInfo(file, base::FilePath()));
}
data.SetFilenames(file_infos);
aura::Window* root_window = view->GetRootWindow();
if (!root_window || !aura::client::GetDragDropClient(root_window))
return;
gfx::Point location = gfx::Screen::GetScreen()->GetCursorScreenPoint();
// TODO(varunjain): Properly determine and send DRAG_EVENT_SOURCE below.
aura::client::GetDragDropClient(root_window)->StartDragAndDrop(
data,
root_window,
view,
location,
ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK,
ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
}
} // namespace atom

View file

@ -4,7 +4,7 @@
#include "atom/browser/ui/file_dialog.h"
#include "atom/browser/native_window.h"
#include "atom/browser/native_window_views.h"
#include "base/callback.h"
#include "base/files/file_util.h"
#include "base/strings/string_util.h"
@ -40,7 +40,8 @@ class FileChooserDialog {
const std::string& button_label,
const base::FilePath& default_path,
const Filters& filters)
: dialog_scope_(parent_window),
: parent_(static_cast<atom::NativeWindowViews*>(parent_window)),
dialog_scope_(parent_window),
filters_(filters) {
const char* confirm_text = GTK_STOCK_OK;
@ -58,9 +59,10 @@ class FileChooserDialog {
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
confirm_text, GTK_RESPONSE_ACCEPT,
NULL);
if (parent_window) {
gfx::NativeWindow window = parent_window->GetNativeWindow();
libgtk2ui::SetGtkTransientForAura(dialog_, window);
if (parent_) {
parent_->SetEnabled(false);
libgtk2ui::SetGtkTransientForAura(dialog_, parent_->GetNativeWindow());
gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE);
}
if (action == GTK_FILE_CHOOSER_ACTION_SAVE)
@ -69,8 +71,6 @@ class FileChooserDialog {
if (action != GTK_FILE_CHOOSER_ACTION_OPEN)
gtk_file_chooser_set_create_folders(GTK_FILE_CHOOSER(dialog_), TRUE);
gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE);
if (!default_path.empty()) {
if (base::DirectoryExists(default_path)) {
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog_),
@ -89,6 +89,8 @@ class FileChooserDialog {
virtual ~FileChooserDialog() {
gtk_widget_destroy(dialog_);
if (parent_)
parent_->SetEnabled(true);
}
void RunAsynchronous() {
@ -143,6 +145,7 @@ class FileChooserDialog {
void AddFilters(const Filters& filters);
base::FilePath AddExtensionForFilename(const gchar* filename) const;
atom::NativeWindowViews* parent_;
atom::NativeWindow::DialogScope dialog_scope_;
GtkWidget* dialog_;
@ -208,7 +211,9 @@ base::FilePath FileChooserDialog::AddExtensionForFilename(
const auto& extensions = filters_[i].second;
for (const auto& extension : extensions) {
if (extension == "*" || path.MatchesExtension("." + extension))
if (extension == "*" ||
base::EndsWith(path.value(), "." + extension,
base::CompareCase::INSENSITIVE_ASCII))
return path;
}

View file

@ -5,7 +5,7 @@
#include "atom/browser/ui/message_box.h"
#include "atom/browser/browser.h"
#include "atom/browser/native_window.h"
#include "atom/browser/native_window_views.h"
#include "base/callback.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@ -36,7 +36,8 @@ class GtkMessageBox {
const std::string& detail,
const gfx::ImageSkia& icon)
: dialog_scope_(parent_window),
cancel_id_(cancel_id) {
cancel_id_(cancel_id),
parent_(static_cast<NativeWindowViews*>(parent_window)) {
// Create dialog.
dialog_ = gtk_message_dialog_new(
nullptr, // parent
@ -75,14 +76,17 @@ class GtkMessageBox {
}
// Parent window.
if (parent_window) {
gfx::NativeWindow window = parent_window->GetNativeWindow();
libgtk2ui::SetGtkTransientForAura(dialog_, window);
if (parent_) {
parent_->SetEnabled(false);
libgtk2ui::SetGtkTransientForAura(dialog_, parent_->GetNativeWindow());
gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE);
}
}
~GtkMessageBox() {
gtk_widget_destroy(dialog_);
if (parent_)
parent_->SetEnabled(true);
}
GtkMessageType GetMessageType(MessageBoxType type) {
@ -123,7 +127,6 @@ class GtkMessageBox {
}
int RunSynchronous() {
gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE);
Show();
int response = gtk_dialog_run(GTK_DIALOG(dialog_));
if (response < 0)
@ -149,6 +152,7 @@ class GtkMessageBox {
// The id to return when the dialog is closed without pressing buttons.
int cancel_id_;
NativeWindowViews* parent_;
GtkWidget* dialog_;
MessageBoxCallback callback_;

View file

@ -30,6 +30,10 @@ void TrayIcon::PopUpContextMenu(const gfx::Point& pos,
ui::SimpleMenuModel* menu_model) {
}
gfx::Rect TrayIcon::GetBounds() {
return gfx::Rect();
}
void TrayIcon::NotifyClicked(const gfx::Rect& bounds, int modifiers) {
FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnClicked(bounds, modifiers));
}

View file

@ -60,8 +60,12 @@ class TrayIcon {
// Set the context menu for this icon.
virtual void SetContextMenu(ui::SimpleMenuModel* menu_model) = 0;
// Returns the bounds of tray icon.
virtual gfx::Rect GetBounds();
void AddObserver(TrayIconObserver* obs) { observers_.AddObserver(obs); }
void RemoveObserver(TrayIconObserver* obs) { observers_.RemoveObserver(obs); }
void NotifyClicked(const gfx::Rect& = gfx::Rect(), int modifiers = 0);
void NotifyDoubleClicked(const gfx::Rect& = gfx::Rect(), int modifiers = 0);
void NotifyBalloonShow();

View file

@ -32,6 +32,7 @@ class TrayIconCocoa : public TrayIcon,
void PopUpContextMenu(const gfx::Point& pos,
ui::SimpleMenuModel* menu_model) override;
void SetContextMenu(ui::SimpleMenuModel* menu_model) override;
gfx::Rect GetBounds() override;
protected:
// AtomMenuModel::Observer:

View file

@ -8,6 +8,7 @@
#include "base/strings/sys_string_conversions.h"
#include "ui/events/cocoa/cocoa_event_utils.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/mac/coordinate_conversion.h"
#include "ui/gfx/screen.h"
namespace {
@ -236,13 +237,13 @@ const CGFloat kVerticalTitleMargin = 2;
// Single click event.
if (event.clickCount == 1)
trayIcon_->NotifyClicked(
[self getBoundsFromEvent:event],
gfx::ScreenRectFromNSRect(event.window.frame),
ui::EventFlagsFromModifiers([event modifierFlags]));
// Double click event.
if (event.clickCount == 2)
trayIcon_->NotifyDoubleClicked(
[self getBoundsFromEvent:event],
gfx::ScreenRectFromNSRect(event.window.frame),
ui::EventFlagsFromModifiers([event modifierFlags]));
[self setNeedsDisplay:YES];
@ -262,7 +263,7 @@ const CGFloat kVerticalTitleMargin = 2;
}
if (menuController_ && ![menuController_ isMenuOpen]) {
// Redraw the dray icon to show highlight if it is enabled.
// Redraw the tray icon to show highlight if it is enabled.
[self setNeedsDisplay:YES];
[statusItem_ popUpStatusItemMenu:[menuController_ menu]];
// The popUpStatusItemMenu returns only after the showing menu is closed.
@ -273,7 +274,7 @@ const CGFloat kVerticalTitleMargin = 2;
- (void)rightMouseUp:(NSEvent*)event {
trayIcon_->NotifyRightClicked(
[self getBoundsFromEvent:event],
gfx::ScreenRectFromNSRect(event.window.frame),
ui::EventFlagsFromModifiers([event modifierFlags]));
}
@ -324,13 +325,6 @@ const CGFloat kVerticalTitleMargin = 2;
return isHighlightEnable_ && (inMouseEventSequence_ || isMenuOpen);
}
- (gfx::Rect)getBoundsFromEvent:(NSEvent*)event {
NSRect frame = event.window.frame;
gfx::Rect bounds(frame.origin.x, 0, NSWidth(frame), NSHeight(frame));
NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
bounds.set_y(NSHeight([screen frame]) - NSMaxY(frame));
return bounds;
}
@end
namespace atom {
@ -386,6 +380,15 @@ void TrayIconCocoa::SetContextMenu(ui::SimpleMenuModel* menu_model) {
[status_item_view_ setMenuController:menu_.get()];
}
gfx::Rect TrayIconCocoa::GetBounds() {
auto bounds = gfx::ScreenRectFromNSRect([status_item_view_ window].frame);
// Calling [window frame] immediately after the view gets created will have
// negative |y| sometimes.
if (bounds.y() < 0)
bounds.set_y(0);
return bounds;
}
void TrayIconCocoa::MenuClosed() {
[status_item_view_ setNeedsDisplay:YES];
}

View file

@ -50,14 +50,7 @@ void GetMenuBarColor(SkColor* enabled, SkColor* disabled, SkColor* highlight,
MenuBar::MenuBar()
: background_color_(kDefaultColor),
menu_model_(NULL) {
#if defined(OS_WIN)
background_color_ = color_utils::GetSysSkColor(COLOR_MENUBAR);
#elif defined(USE_X11)
GetMenuBarColor(&enabled_color_, &disabled_color_, &highlight_color_,
&hover_color_, &background_color_);
#endif
set_background(views::Background::CreateSolidBackground(background_color_));
UpdateMenuBarColor();
SetLayoutManager(new views::BoxLayout(
views::BoxLayout::kHorizontal, 0, 0, 0));
}
@ -152,11 +145,27 @@ void MenuBar::OnMenuButtonClicked(views::MenuButton* source,
int id = source->tag();
ui::MenuModel::ItemType type = menu_model_->GetTypeAt(id);
if (type != ui::MenuModel::TYPE_SUBMENU)
if (type != ui::MenuModel::TYPE_SUBMENU) {
menu_model_->ActivatedAt(id, 0);
return;
}
MenuDelegate menu_delegate(this);
menu_delegate.RunMenu(menu_model_->GetSubmenuModelAt(id), source);
}
void MenuBar::OnNativeThemeChanged(const ui::NativeTheme* theme) {
UpdateMenuBarColor();
}
void MenuBar::UpdateMenuBarColor() {
#if defined(OS_WIN)
background_color_ = color_utils::GetSysSkColor(COLOR_MENUBAR);
#elif defined(USE_X11)
GetMenuBarColor(&enabled_color_, &disabled_color_, &highlight_color_,
&hover_color_, &background_color_);
#endif
set_background(views::Background::CreateSolidBackground(background_color_));
}
} // namespace atom

View file

@ -60,9 +60,11 @@ class MenuBar : public views::View,
void OnMenuButtonClicked(views::MenuButton* source,
const gfx::Point& point,
const ui::Event* event) override;
void OnNativeThemeChanged(const ui::NativeTheme* theme) override;
private:
void UpdateMenuBarColor();
SkColor background_color_;
#if defined(USE_X11)

View file

@ -13,6 +13,7 @@
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/win/dpi.h"
#include "ui/views/controls/menu/menu_runner.h"
namespace atom {
@ -48,26 +49,19 @@ NotifyIcon::~NotifyIcon() {
void NotifyIcon::HandleClickEvent(int modifiers,
bool left_mouse_click,
bool double_button_click) {
NOTIFYICONIDENTIFIER icon_id;
memset(&icon_id, 0, sizeof(NOTIFYICONIDENTIFIER));
icon_id.uID = icon_id_;
icon_id.hWnd = window_;
icon_id.cbSize = sizeof(NOTIFYICONIDENTIFIER);
RECT rect = { 0 };
Shell_NotifyIconGetRect(&icon_id, &rect);
gfx::Rect bounds = GetBounds();
if (left_mouse_click) {
if (double_button_click) // double left click
NotifyDoubleClicked(gfx::Rect(rect), modifiers);
NotifyDoubleClicked(bounds, modifiers);
else // single left click
NotifyClicked(gfx::Rect(rect), modifiers);
NotifyClicked(bounds, modifiers);
return;
} else if (!double_button_click) { // single right click
if (menu_model_)
PopUpContextMenu(gfx::Point(), menu_model_);
else
NotifyRightClicked(gfx::Rect(rect), modifiers);
NotifyRightClicked(bounds, modifiers);
}
}
@ -140,8 +134,9 @@ void NotifyIcon::DisplayBalloon(HICON icon,
void NotifyIcon::PopUpContextMenu(const gfx::Point& pos,
ui::SimpleMenuModel* menu_model) {
// Returns if context menu isn't set.
if (!menu_model)
if (menu_model == nullptr && menu_model_ == nullptr)
return;
// Set our window as the foreground window, so the context menu closes when
// we click away from it.
if (!SetForegroundWindow(window_))
@ -153,7 +148,7 @@ void NotifyIcon::PopUpContextMenu(const gfx::Point& pos,
rect.set_origin(gfx::Screen::GetScreen()->GetCursorScreenPoint());
views::MenuRunner menu_runner(
menu_model,
menu_model != nullptr ? menu_model : menu_model_,
views::MenuRunner::CONTEXT_MENU | views::MenuRunner::HAS_MNEMONICS);
ignore_result(menu_runner.RunMenuAt(
NULL, NULL, rect, views::MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_MOUSE));
@ -163,6 +158,18 @@ void NotifyIcon::SetContextMenu(ui::SimpleMenuModel* menu_model) {
menu_model_ = menu_model;
}
gfx::Rect NotifyIcon::GetBounds() {
NOTIFYICONIDENTIFIER icon_id;
memset(&icon_id, 0, sizeof(NOTIFYICONIDENTIFIER));
icon_id.uID = icon_id_;
icon_id.hWnd = window_;
icon_id.cbSize = sizeof(NOTIFYICONIDENTIFIER);
RECT rect = { 0 };
Shell_NotifyIconGetRect(&icon_id, &rect);
return gfx::win::ScreenToDIPRect(gfx::Rect(rect));
}
void NotifyIcon::InitIconData(NOTIFYICONDATA* icon_data) {
memset(icon_data, 0, sizeof(NOTIFYICONDATA));
icon_data->cbSize = sizeof(NOTIFYICONDATA);

View file

@ -54,6 +54,7 @@ class NotifyIcon : public TrayIcon {
void PopUpContextMenu(const gfx::Point& pos,
ui::SimpleMenuModel* menu_model) override;
void SetContextMenu(ui::SimpleMenuModel* menu_model) override;
gfx::Rect GetBounds() override;
private:
void InitIconData(NOTIFYICONDATA* icon_data);

View file

@ -54,12 +54,16 @@ std::string Read(const std::string& format_string,
void Write(const mate::Dictionary& data,
mate::Arguments* args) {
ui::ScopedClipboardWriter writer(GetClipboardType(args));
base::string16 text, html;
base::string16 text, html, bookmark;
gfx::Image image;
if (data.Get("text", &text))
if (data.Get("text", &text)) {
writer.WriteText(text);
if (data.Get("bookmark", &bookmark))
writer.WriteBookmark(bookmark, base::UTF16ToUTF8(text));
}
if (data.Get("rtf", &text)) {
std::string rtf = base::UTF16ToUTF8(text);
writer.WriteRTF(rtf);
@ -122,6 +126,23 @@ void WriteHtml(const base::string16& html, mate::Arguments* args) {
writer.WriteHTML(html, std::string());
}
v8::Local<v8::Value> ReadBookmark(mate::Arguments* args) {
base::string16 title;
std::string url;
mate::Dictionary dict = mate::Dictionary::CreateEmpty(args->isolate());
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
clipboard->ReadBookmark(&title, &url);
dict.Set("title", title);
dict.Set("url", url);
return dict.GetHandle();
}
void WriteBookmark(const base::string16& title, const std::string& url,
mate::Arguments* args) {
ui::ScopedClipboardWriter writer(GetClipboardType(args));
writer.WriteBookmark(title, url);
}
gfx::Image ReadImage(mate::Arguments* args) {
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
SkBitmap bitmap = clipboard->ReadImage(GetClipboardType(args));
@ -150,6 +171,8 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
dict.SetMethod("writeRTF", &WriteRtf);
dict.SetMethod("readHTML", &ReadHtml);
dict.SetMethod("writeHTML", &WriteHtml);
dict.SetMethod("readBookmark", &ReadBookmark);
dict.SetMethod("writeBookmark", &WriteBookmark);
dict.SetMethod("readImage", &ReadImage);
dict.SetMethod("writeImage", &WriteImage);
dict.SetMethod("clear", &Clear);

View file

@ -160,10 +160,14 @@ base::win::ScopedHICON ReadICOFromPath(int size, const base::FilePath& path) {
LR_LOADFROMFILE)));
}
void ReadImageSkiaFromICO(gfx::ImageSkia* image, HICON icon) {
bool ReadImageSkiaFromICO(gfx::ImageSkia* image, HICON icon) {
// Convert the icon from the Windows specific HICON to gfx::ImageSkia.
std::unique_ptr<SkBitmap> bitmap(IconUtil::CreateSkBitmapFromHICON(icon));
if (!bitmap)
return false;
image->AddRepresentation(gfx::ImageSkiaRep(*bitmap, 1.0f));
return true;
}
#endif
@ -344,14 +348,17 @@ mate::Handle<NativeImage> NativeImage::CreateFromDataURL(
void NativeImage::BuildPrototype(
v8::Isolate* isolate, v8::Local<v8::ObjectTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype)
.SetMethod("toPng", &NativeImage::ToPNG)
.SetMethod("toJpeg", &NativeImage::ToJPEG)
.SetMethod("toPNG", &NativeImage::ToPNG)
.SetMethod("toJPEG", &NativeImage::ToJPEG)
.SetMethod("getNativeHandle", &NativeImage::GetNativeHandle)
.SetMethod("toDataURL", &NativeImage::ToDataURL)
.SetMethod("isEmpty", &NativeImage::IsEmpty)
.SetMethod("getSize", &NativeImage::GetSize)
.SetMethod("setTemplateImage", &NativeImage::SetTemplateImage)
.SetMethod("isTemplateImage", &NativeImage::IsTemplateImage);
.SetMethod("isTemplateImage", &NativeImage::IsTemplateImage)
// TODO(kevinsawicki): Remove in 2.0, deprecate before then with warnings
.SetMethod("toPng", &NativeImage::ToPNG)
.SetMethod("toJpeg", &NativeImage::ToJPEG);
}
} // namespace api

View file

@ -16,11 +16,8 @@ v8::Local<v8::Value> CallEmitWithArgs(v8::Isolate* isolate,
v8::Local<v8::Object> obj,
ValueVector* args) {
// Perform microtask checkpoint after running JavaScript.
std::unique_ptr<v8::MicrotasksScope> script_scope(
Locker::IsBrowserProcess() ?
nullptr :
new v8::MicrotasksScope(isolate,
v8::MicrotasksScope::kRunMicrotasks));
v8::MicrotasksScope script_scope(
isolate, v8::MicrotasksScope::kRunMicrotasks);
// Use node::MakeCallback to call the callback, and it will also run pending
// tasks in Node.js.
return node::MakeCallback(

View file

@ -7,7 +7,7 @@
#define ATOM_MAJOR_VERSION 1
#define ATOM_MINOR_VERSION 2
#define ATOM_PATCH_VERSION 3
#define ATOM_PATCH_VERSION 6
#define ATOM_VERSION_IS_RELEASE 1

View file

@ -8,7 +8,7 @@
#ifndef ATOM_COMMON_CHROME_VERSION_H_
#define ATOM_COMMON_CHROME_VERSION_H_
#define CHROME_VERSION_STRING "51.0.2704.103"
#define CHROME_VERSION_STRING "51.0.2704.106"
#define CHROME_VERSION "v" CHROME_VERSION_STRING
#endif // ATOM_COMMON_CHROME_VERSION_H_

View file

@ -137,7 +137,8 @@ void UnregisterNonABICompliantCodeRange(void* start) {
} // namespace
CrashReporterWin::CrashReporterWin() {
CrashReporterWin::CrashReporterWin()
: skip_system_crash_handler_(false) {
}
CrashReporterWin::~CrashReporterWin() {

View file

@ -48,11 +48,8 @@ struct V8FunctionInvoker<v8::Local<v8::Value>(ArgTypes...)> {
v8::EscapableHandleScope handle_scope(isolate);
if (!function.IsAlive())
return v8::Null(isolate);
std::unique_ptr<v8::MicrotasksScope> script_scope(
Locker::IsBrowserProcess() ?
nullptr :
new v8::MicrotasksScope(isolate,
v8::MicrotasksScope::kRunMicrotasks));
v8::MicrotasksScope script_scope(isolate,
v8::MicrotasksScope::kRunMicrotasks);
v8::Local<v8::Function> holder = function.NewHandle(isolate);
v8::Local<v8::Context> context = holder->CreationContext();
v8::Context::Scope context_scope(context);
@ -71,11 +68,8 @@ struct V8FunctionInvoker<void(ArgTypes...)> {
v8::HandleScope handle_scope(isolate);
if (!function.IsAlive())
return;
std::unique_ptr<v8::MicrotasksScope> script_scope(
Locker::IsBrowserProcess() ?
nullptr :
new v8::MicrotasksScope(isolate,
v8::MicrotasksScope::kRunMicrotasks));
v8::MicrotasksScope script_scope(isolate,
v8::MicrotasksScope::kRunMicrotasks);
v8::Local<v8::Function> holder = function.NewHandle(isolate);
v8::Local<v8::Context> context = holder->CreationContext();
v8::Context::Scope context_scope(context);
@ -94,11 +88,8 @@ struct V8FunctionInvoker<ReturnType(ArgTypes...)> {
ReturnType ret = ReturnType();
if (!function.IsAlive())
return ret;
std::unique_ptr<v8::MicrotasksScope> script_scope(
Locker::IsBrowserProcess() ?
nullptr :
new v8::MicrotasksScope(isolate,
v8::MicrotasksScope::kRunMicrotasks));
v8::MicrotasksScope script_scope(isolate,
v8::MicrotasksScope::kRunMicrotasks);
v8::Local<v8::Function> holder = function.NewHandle(isolate);
v8::Local<v8::Context> context = holder->CreationContext();
v8::Context::Scope context_scope(context);

View file

@ -226,10 +226,8 @@ void NodeBindings::UvRunOnce() {
v8::Context::Scope context_scope(env->context());
// Perform microtask checkpoint after running JavaScript.
std::unique_ptr<v8::MicrotasksScope> script_scope(is_browser_ ?
nullptr :
new v8::MicrotasksScope(env->isolate(),
v8::MicrotasksScope::kRunMicrotasks));
v8::MicrotasksScope script_scope(env->isolate(),
v8::MicrotasksScope::kRunMicrotasks);
// Deal with uv events.
int r = uv_run(uv_loop_, UV_RUN_NOWAIT);

View file

@ -52,45 +52,30 @@ app.once('ready', () => {
label: 'Edit',
submenu: [
{
label: 'Undo',
accelerator: 'CmdOrCtrl+Z',
role: 'undo'
},
{
label: 'Redo',
accelerator: 'Shift+CmdOrCtrl+Z',
role: 'redo'
},
{
type: 'separator'
},
{
label: 'Cut',
accelerator: 'CmdOrCtrl+X',
role: 'cut'
},
{
label: 'Copy',
accelerator: 'CmdOrCtrl+C',
role: 'copy'
},
{
label: 'Paste',
accelerator: 'CmdOrCtrl+V',
role: 'paste'
},
{
label: 'Paste and Match Style',
accelerator: 'Shift+Command+V',
role: 'pasteandmatchstyle'
},
{
label: 'Delete',
role: 'delete'
},
{
label: 'Select All',
accelerator: 'CmdOrCtrl+A',
role: 'selectall'
}
]
@ -106,19 +91,11 @@ app.once('ready', () => {
}
},
{
label: 'Toggle Full Screen',
accelerator: (() => {
return (process.platform === 'darwin') ? 'Ctrl+Command+F' : 'F11'
})(),
click (item, focusedWindow) {
if (focusedWindow) focusedWindow.setFullScreen(!focusedWindow.isFullScreen())
}
role: 'togglefullscreen'
},
{
label: 'Toggle Developer Tools',
accelerator: (() => {
return (process.platform === 'darwin') ? 'Alt+Command+I' : 'Ctrl+Shift+I'
})(),
accelerator: process.platform === 'darwin' ? 'Alt+Command+I' : 'Ctrl+Shift+I',
click (item, focusedWindow) {
if (focusedWindow) focusedWindow.toggleDevTools()
}
@ -126,23 +103,17 @@ app.once('ready', () => {
]
},
{
label: 'Window',
role: 'window',
submenu: [
{
label: 'Minimize',
accelerator: 'CmdOrCtrl+M',
role: 'minimize'
},
{
label: 'Close',
accelerator: 'CmdOrCtrl+W',
role: 'close'
}
]
},
{
label: 'Help',
role: 'help',
submenu: [
{
@ -180,14 +151,12 @@ app.once('ready', () => {
label: 'Electron',
submenu: [
{
label: 'About Electron',
role: 'about'
},
{
type: 'separator'
},
{
label: 'Services',
role: 'services',
submenu: []
},
@ -195,54 +164,52 @@ app.once('ready', () => {
type: 'separator'
},
{
label: 'Hide Electron',
accelerator: 'Command+H',
role: 'hide'
},
{
label: 'Hide Others',
accelerator: 'Command+Alt+H',
role: 'hideothers'
},
{
label: 'Show All',
role: 'unhide'
},
{
type: 'separator'
},
{
label: 'Quit ' + app.getName(),
accelerator: 'Command+Q',
click () { app.quit() }
role: 'quit'
}
]
})
template[3].submenu = [
{
label: 'Close',
accelerator: 'CmdOrCtrl+W',
role: 'close'
},
{
label: 'Minimize',
accelerator: 'CmdOrCtrl+M',
role: 'minimize'
},
{
label: 'Zoom',
role: 'zoom'
},
{
type: 'separator'
},
{
label: 'Bring All to Front',
role: 'front'
}
]
}
if (process.platform === 'win32') {
template.unshift({
label: 'File',
submenu: [
{
role: 'quit'
}
]
})
}
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
})

View file

@ -112,11 +112,11 @@ const nativeImage = require('electron').nativeImage;
var image = nativeImage.createFromPath('/Users/somebody/images/icon.png');
```
### `image.toPng()`
### `image.toPNG()`
`PNG`エンコードされた画像を含む[Buffer][buffer]を返します。
### `image.toJpeg(quality)`
### `image.toJPEG(quality)`
* `quality` Integer (**required**) - Between 0 - 100.

View file

@ -647,6 +647,33 @@ dock 아이콘을 표시합니다.
dock 아이콘의 `image`를 설정합니다.
### `app.launcher.setBadgeCount(count)` _Linux_
* `count` Integer
Unity 런처에서 앱 아이콘 옆에 표시될 숫자를 설정합니다. `0`으로 설정하면 뱃지를
숨깁니다.
**참고:** 이 기능은 현재 Ubuntu Unity에서만 사용할 수 있습니다. 다른 환경에서 이
함수를 호출하는 것은 아무런 효과가 없습니다.
**참고:** 이 기능을 사용하려면 `package.json``desktopName` 필드에 `.desktop` 파일 이름을 설정해야 합니다. 기본적으로 패키징된 애플리케이션의 `app.getName().desktop`을 사용합니다.
### `app.launcher.getBadgeCount()` _Linux_
런처 아이콘 옆 배지의 카운터에 표시된 현재 값을 반환합니다.
**참고:** `setBadgeCount`가 Ubuntu Unity에서만 지원하기 때문에, 애플리케이션이 다른
플랫폼에서 돌아가고 있다면 이 메서드는 `0`을 반환합니다.
### `app.launcher.isUnityRunning()` _Linux_
현재 데스크톱 환경이 Unity인지 여부를 반환합니다. Unity가 맞다면 `true`를 반환합니다.
### `app.launcher.isCounterBadgeAvailable()` _Linux_
현재 데스크톱 환경이 애플리케이션 아이콘 카운터 뱃지를 사용할 수 있는지 여부를
반환합니다. 사용할 수 있다면 `true`를 반환합니다.
[dock-menu]:https://developer.apple.com/library/mac/documentation/Carbon/Conceptual/customizing_docktile/concepts/dockconcepts.html#//apple_ref/doc/uid/TP30000986-CH2-TPXREF103
[tasks]:http://msdn.microsoft.com/en-us/library/windows/desktop/dd378460(v=vs.85).aspx#tasks
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx

View file

@ -62,6 +62,38 @@ win.loadURL('https://github.com')
참고로 `ready-to-show` 이벤트를 사용하더라도 어플리케이션을 네이티브 느낌이 나도록
하기 위해 `backgroundColor`도 같이 설정하는 것을 권장합니다.
## 부모와 자식 윈도우
`parent` 옵션을 사용하면 자식 윈도우를 만들 수 있습니다:
```javascript
let top = new BrowserWindow()
let child = new BrowserWindow({parent: top})
```
`child` 윈도우는 언제나 `top` 윈도우의 상위에 표시됩니다.
### 모달 윈도우
모달 윈도우는 부모 윈도우를 비활성화 시키는 자식 윈도우입니다. 모달 윈도우를 만드려면 `parent`, `modal` 옵션을 동시에 설정해야 합니다:
```javascript
let child = new BrowserWindow({parent: top, modal: true, show: false})
child.loadURL('https://github.com')
child.once('ready-to-show', () => {
child.show()
})
```
### 플랫폼별 특이사항
* On macOS the child windows will keep the relative position to parent window
when parent window moves, while on Windows and Linux child windows will not
move.
* On Windows it is not supported to change parent window dynamically.
* On Linux the type of modal windows will be changed to `dialog`.
* On Linux many desktop environments do not support hiding a modal window.
## Class: BrowserWindow
`BrowserWindow`는 [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)를
@ -125,6 +157,9 @@ On Windows it is
* `show` Boolean - 윈도우가 생성되면 보여줄지 여부. 기본값은 `true`입니다.
* `frame` Boolean - `false`로 지정하면 창을 [Frameless Window](frameless-window.md)
형태로 생성합니다. 기본값은 `true`입니다.
* `parent` BrowserWindow - 부모 윈도우를 설정합니다. 기본 값은 `null`입니다.
* `modal` Boolean - 이 윈도우가 모달 윈도우인지 여부를 설정합니다. 이 옵션은 자식
윈도우에서만 작동합니다. 기본값은 `false`입니다.
* `acceptFirstMouse` Boolean - 윈도우가 비활성화 상태일 때 내부 콘텐츠 클릭 시
활성화 되는 동시에 단일 mouse-down 이벤트를 발생시킬지 여부. 기본값은 `false`입니다.
* `disableAutoHideCursor` Boolean - 타이핑중 자동으로 커서를 숨길지 여부. 기본값은
@ -528,6 +563,10 @@ let win = new BrowserWindow({width: 800, height: 600});
윈도우가 사용자에게 표시되고 있는지 여부를 반환합니다.
### `win.isModal()`
현재 윈도우가 모달 윈도우인지 여부를 반환합니다.
### `win.maximize()`
윈도우를 최대화 시킵니다.
@ -894,7 +933,7 @@ Linux 플랫폼에선 Unity 데스크톱 환경만 지원합니다. 그리고
### `win.setHasShadow(hasShadow)` _macOS_
* `hasShadow` (Boolean)
* `hasShadow` Boolean
윈도우가 그림자를 가질지 여부를 지정합니다. Windows와 Linux에선 아무 일도 일어나지
않습니다.
@ -995,10 +1034,32 @@ Linux 플랫폼에선 Unity 데스크톱 환경만 지원합니다. 그리고
이 윈도우에서 일어나는 모든 마우스 이벤트가 이 윈도우 밑의 윈도우로 전달됩니다. 하지만
이 윈도우가 포커스되어 있다면, 여전히 키보드 이벤트는 받을 수 있습니다.
### `win.setContentProtection(enable)` _macOS_ _Windows_
윈도우 콘텐츠가 외부 어플리케이션에 의해 캡쳐되는 것을 막습니다.
macOS에선 NSWindow의 sharingType을 NSWindowSharingNone로 설정합니다.
Windows에선 WDA_MONITOR와 함께 SetWindowDisplayAffinity를 호출합니다.
### `win.setFocusable(focusable)` _Windows_
* `focusable` Boolean
윈도우가 포커스될 수 있는지 여부를 변경합니다.
### `win.setParentWindow(parent)` _Linux_ _macOS_
* `parent` BrowserWindow
`parent` 인수를 현재 윈도우의 부모 윈도우로 설정합니다. `null`로 설정하면
현재 윈도우를 상위 윈도우로 전환합니다.
### `win.getParentWindow()`
모든 부모 윈도우를 반환합니다.
### `win.getChildWindows()`
모든 자식 윈도우를 반환합니다.
[blink-feature-string]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in

View file

@ -76,6 +76,19 @@ console.log(clipboard.readText('selection'));
클립보드에 `text`를 RTF 형식으로 씁니다.
### `clipboard.readBookmark()` _macOS_ _Windows_
클립보드로부터 북마크 형식으로 표현된 `title``url` 키를 담은 객체를 반환합니다.
`title``url` 값들은 북마크를 사용할 수 없을 때 빈 문자열을 포함합니다.
### `clipboard.writeBookmark(title, url[, type])` _macOS_ _Windows_
* `title` String
* `url` String
* `type` String (optional)
`title``url`을 클립보드에 북마크 형식으로 씁니다.
### `clipboard.clear([type])`
* `type` String (optional)
@ -110,6 +123,8 @@ console.log(clipboard.has('<p>selection</p>'));
* `text` String
* `html` String
* `image` [NativeImage](native-image.md)
* `rtf` String
* `bookmark` String - `text`에 있는 URL의 텍스트.
* `type` String (optional)
```javascript

View file

@ -2,7 +2,7 @@
> 네이티브 애플리케이션 메뉴와 컨텍스트 메뉴에 아이템을 추가합니다.
[`menu`](menu.md)에서 예시를 확인할 수 있습니다.
[`Menu`](menu.md)에서 예시를 확인할 수 있습니다.
## Class: MenuItem
@ -11,9 +11,9 @@
### new MenuItem(options)
* `options` Object
* `click` Function - 메뉴 아이템이 클릭될 때 `click(menuItem, browserWindow)`
형태로 호출 되는 콜백 함수
* `role` String - 메뉴 아이템의 액션을 정의합니다; 이 속성을 지정하면 `click`
* `click` Function - 메뉴 아이템이 클릭될 때 `click(menuItem, browserWindow,
event)` 형태로 호출 되는 콜백 함수.
* `role` String - 메뉴 아이템의 액션을 정의합니다. 이 속성을 지정하면 `click`
속성이 무시됩니다.
* `type` String - `MenuItem`의 타입 `normal`, `separator`, `submenu`,
`checkbox` 또는 `radio`를 사용할 수 있습니다. 만약 값이 `Menu`가 아니면
@ -39,6 +39,9 @@
함수로 일일이 구현하려 시도하는 것 보다 더 좋을 수 있습니다. 빌트-인 `role` 동작은
더 좋은 네이티브 경험을 제공할 것입니다.
`role`을 사용하는 동안에는 `label``accelerator`는 필수가 아니며 각 플랫폼에 대해
적합한 값이 기본값으로 사용됩니다.
`role` 속성은 다음 값을 가질 수 있습니다:
* `undo`
@ -51,6 +54,8 @@
* `delete`
* `minimize` - 현재 윈도우를 최소화합니다
* `close` - 현재 윈도우를 닫습니다
* `quit`- 애플리케이션을 닫습니다
* `togglefullscreen` - 현재 윈도우에서 전체 화면 모드를 토글합니다
macOS에서의 `role`은 다음 값을 추가로 가질 수 있습니다:
@ -67,20 +72,28 @@ macOS에서의 `role`은 다음 값을 추가로 가질 수 있습니다:
macOS에서는 `role`을 지정할 때, `label``accelerator`만 MenuItem에 효과가
적용되도록 변경되며, 다른 옵션들은 모두 무시됩니다.
## Instance Properties
### Instance Properties
다음 속성들은 존재하는 `MenuItem`에서 계속 변경될 수 있습니다:
다음`MenuItem`의 인스턴스에서 사용할 수 있는 속성입니다:
* `enabled` Boolean
* `visible` Boolean
* `checked` Boolean
#### `menuItem.enabled`
이 속성들의 의미는 위 옵션에서 설명한 것과 같습니다.
아이템이 활성화되어있는지 여부를 표시하는 Boolean 값입니다. 이 속성은 동적으로 변경될
수 있습니다.
`checkbox` 메뉴 아이템은 선택될 때 해당 아이템의 `checked` 속성을 통해 활성화 그리고
비활성화 상태인지를 표시합니다. 또한 `click` 함수를 지정하여 추가적인 작업을 할 수도
있습니다.
#### `menuItem.visible`
`radio` 메뉴 아이템은 클릭되었을 때 `checked` 속성을 활성화 합니다. 그리고 같은
메뉴의 인접한 모든 다른 아이템은 비활성화됩니다. 또한 `click` 함수를 지정하여 추가적인
작업을 할 수도 있습니다.
아이템이 보여지고있는지 여부를 표시하는 Boolean 값입니다. 이 속성은 동적으로 변경될
수 있습니다.
#### `menuItem.checked`
아이템이 선택되어있는지 여부를 반환하는 Boolean 값입니다. 이 속성은 동적으로 변경될
수 있습니다.
`checkbox` 메뉴 아이템은 선택되면 `checked` 속성을 토글합니다.
`radio` 메뉴 아이템은 클릭되었을 때 `checked` 속성을 활성화 합니다. 그리고
같은 메뉴의 모든 인접한 아이템에 대한 속성이 꺼집니다.
추가적인 작업을 위해 `click` 함수를 추가할 수도 있습니다.

View file

@ -38,45 +38,30 @@ const template = [
label: 'Edit',
submenu: [
{
label: 'Undo',
accelerator: 'CmdOrCtrl+Z',
role: 'undo'
},
{
label: 'Redo',
accelerator: 'Shift+CmdOrCtrl+Z',
role: 'redo'
},
{
type: 'separator'
},
{
label: 'Cut',
accelerator: 'CmdOrCtrl+X',
role: 'cut'
},
{
label: 'Copy',
accelerator: 'CmdOrCtrl+C',
role: 'copy'
},
{
label: 'Paste',
accelerator: 'CmdOrCtrl+V',
role: 'paste'
},
{
label: 'Paste and Match Style',
accelerator: 'Shift+Command+V',
role: 'pasteandmatchstyle'
},
{
label: 'Delete',
role: 'delete'
},
{
label: 'Select All',
accelerator: 'CmdOrCtrl+A',
role: 'selectall'
},
]
@ -92,12 +77,7 @@ const template = [
}
},
{
label: 'Toggle Full Screen',
accelerator: process.platform === 'darwin' ? 'Ctrl+Command+F' : 'F11',
click(item, focusedWindow) {
if (focusedWindow)
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
}
role: 'togglefullscreen'
},
{
label: 'Toggle Developer Tools',
@ -110,23 +90,17 @@ const template = [
]
},
{
label: 'Window',
role: 'window',
submenu: [
{
label: 'Minimize',
accelerator: 'CmdOrCtrl+M',
role: 'minimize'
},
{
label: 'Close',
accelerator: 'CmdOrCtrl+W',
role: 'close'
},
]
},
{
label: 'Help',
role: 'help',
submenu: [
{
@ -143,14 +117,12 @@ if (process.platform === 'darwin') {
label: name,
submenu: [
{
label: 'About ' + name,
role: 'about'
},
{
type: 'separator'
},
{
label: 'Services',
role: 'services',
submenu: []
},
@ -158,26 +130,19 @@ if (process.platform === 'darwin') {
type: 'separator'
},
{
label: 'Hide ' + name,
accelerator: 'Command+H',
role: 'hide'
},
{
label: 'Hide Others',
accelerator: 'Command+Alt+H',
role: 'hideothers'
},
{
label: 'Show All',
role: 'unhide'
},
{
type: 'separator'
},
{
label: 'Quit',
accelerator: 'Command+Q',
click() { app.quit(); }
role: 'quit'
},
]
});
@ -217,7 +182,7 @@ Menu.setApplicationMenu(menu);
새로운 메뉴를 생성합니다.
### Methods
## Methods
`menu` 클래스는 다음과 같은 메서드를 가지고 있습니다:

View file

@ -125,11 +125,11 @@ let image = nativeImage.createFromPath('/Users/somebody/images/icon.png');
`nativeImage` 인스턴스 객체에서 사용할 수 있는 메서드입니다.
### `image.toPng()`
### `image.toPNG()`
`PNG` 이미지를 인코딩한 데이터를 [Buffer][buffer]로 반환합니다.
### `image.toJpeg(quality)`
### `image.toJPEG(quality)`
* `quality` Integer (**required**) 0 - 100 사이의 값

View file

@ -4,16 +4,15 @@
`session` 모듈은 새로운 `Session` 객체를 만드는데 사용할 수 있습니다.
또한 존재하는 [`BrowserWindow`](browser-window.md)의
[`webContents`](web-contents.md)에서 `session` 속성으로 접근할 수도 있습니다.
또한 [`WebContents`](web-contents.md)의 `session` 속성이나 `session` 모듈을 통해 현재 존재하는 페이지의 `session`에 접근할 수 있습니다.
```javascript
const {BrowserWindow} = require('electron');
const {session, BrowserWindow} = require('electron')
let win = new BrowserWindow({width: 800, height: 600});
win.loadURL('http://github.com');
let win = new BrowserWindow({width: 800, height: 600})
win.loadURL('http://github.com')
let ses = win.webContents.session;
let ses = win.webContents.session
```
## Methods
@ -75,92 +74,7 @@ session.defaultSession.on('will-download', (event, item, webContents) => {
### Instance Methods
`Session` 객체는 다음과 같은 메서드와 속성을 가지고 있습니다:
#### `ses.cookies`
`cookies` 속성은 쿠키를 조작하는 방법을 제공합니다. 예를 들어 다음과 같이 할 수
있습니다:
```javascript
// 모든 쿠키를 요청합니다.
session.defaultSession.cookies.get({}, (error, cookies) => {
console.log(cookies);
});
// url에 관련된 쿠키를 모두 가져옵니다.
session.defaultSession.cookies.get({url: 'http://www.github.com'}, (error, cookies) => {
console.log(cookies);
});
// 지정한 쿠키 데이터를 설정합니다.
// 동일한 쿠키가 있으면 해당 쿠키를 덮어씁니다.
const cookie = {url: 'http://www.github.com', name: 'dummy_name', value: 'dummy'};
session.defaultSession.cookies.set(cookie, (error) => {
if (error)
console.error(error);
});
```
#### `ses.cookies.get(filter, callback)`
* `filter` Object
* `url` String (optional) - `url`에 해당하는 쿠키를 취득합니다. 이 속성을
생략하면 모든 url에서 찾습니다.
* `name` String (optional) - 쿠키의 이름입니다.
* `domain` String (optional) - 도메인 또는 서브 도메인에 일치하는 쿠키를
취득합니다.
* `path` String (optional) - `path`에 일치하는 쿠키를 취득합니다.
* `secure` Boolean (optional) - 보안 속성에 따라 쿠키를 필터링합니다.
* `session` Boolean (optional) - 세션 또는 지속성 쿠키를 필터링합니다.
* `callback` Function
`details` 객체에서 묘사한 모든 쿠키를 요청합니다. 모든 작업이 끝나면 `callback`
`callback(error, cookies)` 형태로 호출됩니다.
`cookies``cookie` 객체의 배열입니다.
* `cookie` Object
* `name` String - 쿠키의 이름.
* `value` String - 쿠키의 값.
* `domain` String - 쿠키의 도메인.
* `hostOnly` String - 쿠키가 호스트 전용인가에 대한 여부.
* `path` String - 쿠키의 경로.
* `secure` Boolean - 쿠키가 안전한 것으로 표시되는지에 대한 여부.
* `httpOnly` Boolean - 쿠키가 HTTP로만 표시되는지에 대한 여부.
* `session` Boolean - 쿠키가 세션 쿠키 또는 만료일이 있는 영구 쿠키인지에 대한
여부.
* `expirationDate` Double - (Option) UNIX 시간으로 표시되는 쿠키의 만료일에
대한 초 단위 시간. 세션 쿠키는 지원되지 않음.
#### `ses.cookies.set(details, callback)`
* `details` Object
* `url` String - 쿠키에 대한 `url` 링크.
* `name` String - 쿠키의 이름입니다. 기본적으로 비워두면 생략됩니다.
* `value` String - 쿠키의 값입니다. 기본적으로 비워두면 생략됩니다.
* `domain` String - 쿠키의 도메인입니다. 기본적으로 비워두면 생략됩니다.
* `path` String - 쿠키의 경로입니다. 기본적으로 비워두면 생략됩니다.
* `secure` Boolean - 쿠키가 안전한 것으로 표시되는지에 대한 여부입니다. 기본값은
false입니다.
* `session` Boolean - 쿠키가 Http 전용으로 표시되는지에 대한 여부입니다. 기본값은
false입니다.
* `expirationDate` Double (optional) - UNIX 시간으로 표시되는 쿠키의 만료일에
대한 초 단위 시간입니다. 생략되면 쿠키가 세션 쿠기가 되며 세션 사이에 유지되지
않게 됩니다.
* `callback` Function
`details` 객체에 따라 쿠키를 설정합니다. 작업이 완료되면 `callback`
`callback(error)` 형태로 호출됩니다.
#### `ses.cookies.remove(url, name, callback)`
* `url` String - 쿠키와 관련된 URL입니다.
* `name` String - 지울 쿠키의 이름입니다.
* `callback` Function
`url``name`에 일치하는 쿠키를 삭제합니다. 작업이 완료되면 `callback`
`callback()` 형식으로 호출됩니다.
`Session` 객체는 다음과 같은 메서드를 가지고 있습니다:
#### `ses.getCacheSize(callback)`
@ -232,7 +146,7 @@ proxyURL = [<proxyScheme>"://"]<proxyHost>[":"<proxyPort>]
* `http=foopy;socks=foopy2` - http:// URL에 `foopy` HTTP 프록시를 사용합니다.
그리고 `socks4://foopy2` 프록시를 다른 모든 URL에 사용합니다.
### `app.resolveProxy(url, callback)`
#### `ses.resolveProxy(url, callback)`
* `url` URL
* `callback` Function
@ -339,14 +253,156 @@ session.defaultSession.allowNTLMCredentialsForDomains('*example.com, *foobar.com
session.defaultSession.allowNTLMCredentialsForDomains('*')
```
#### `ses.setUserAgent(userAgent[, acceptLanguages])`
* `userAgent` String
* `acceptLanguages` String (optional)
현재 세션에 대해 `userAgent``acceptLanguages`를 덮어씁니다.
`acceptLanguages`는 반드시 쉼표로 구분된 순서에 맞춘 언어 코드의 리스트여야 하며
예를 들면 `"en-US,fr,de,ko,zh-CN,ja"` 입니다.
이는 현재 존재하는 `WebContents`에 적용되지 않으며 각 `WebContents`
`webContents.setUserAgent`를 사용하여 세션 전체의 유저 에이전트를 덮어쓸 수 있습니다.
#### `ses.getUserAgent()`
현재 세션의 유저 에이전트를 표현하는 `String`을 반환합니다.
### Instance Properties
다음은 `Session` 인스턴스에서 사용할 수 있는 속성들입니다:
#### `ses.cookies`
현재 세션의 `Cookies` 클래스 인스턴스를 반환합니다.
#### `ses.webRequest`
`webRequest` API는 생명주기의 다양한 단계에 맞춰 요청 콘텐츠를 가로채거나 변경할 수
있도록 합니다.
현재 세션의 `WebRequest` 클래스 인스턴스를 반환합니다.
각 API는 `filter``listener`를 선택적으로 받을 수 있습니다. `listener`는 API의
이벤트가 발생했을 때 `listener(details)` 형태로 호출되며 `defails`는 요청을 묘사하는
객체입니다. `listener``null`을 전달하면 이벤트 수신을 중지합니다.
#### `ses.protocol`
현재 세션의 [protocol](protocol.md) 모듈 인스턴스를 반환합니다.
```javascript
const {app, session} = require('electron')
const path = require('path')
app.on('ready', function () {
const protocol = session.fromPartition(partitionName).protocol
protocol.registerFileProtocol('atom', function (request, callback) {
var url = request.url.substr(7)
callback({path: path.normalize(__dirname + '/' + url)})
}, function (error) {
if (error)
console.error('Failed to register protocol')
})
})
```
## Class: Cookies
`Cookies` 클래스는 쿠키를 탐색하고 조작하는 방법을 제공합니다. `Cookies` 클래스의
인스턴스는 반드시 `Session` 클래스의 `cookies` 속성에서 접근해야 합니다.
예를 들어:
```javascript
// 모든 쿠키를 요청합니다.
session.defaultSession.cookies.get({}, (error, cookies) => {
console.log(cookies);
});
// url에 관련된 쿠키를 모두 가져옵니다.
session.defaultSession.cookies.get({url: 'http://www.github.com'}, (error, cookies) => {
console.log(cookies);
});
// 지정한 쿠키 데이터를 설정합니다.
// 동일한 쿠키가 있으면 해당 쿠키를 덮어씁니다.
const cookie = {url: 'http://www.github.com', name: 'dummy_name', value: 'dummy'};
session.defaultSession.cookies.set(cookie, (error) => {
if (error)
console.error(error);
});
```
### Instance Methods
다음은 `Cookies` 객체에서 사용할 수 있는 메서드들입니다:
#### `ses.cookies.get(filter, callback)`
* `filter` Object
* `url` String (optional) - `url`에 해당하는 쿠키를 취득합니다. 이 속성을
생략하면 모든 url에서 찾습니다.
* `name` String (optional) - 쿠키의 이름입니다.
* `domain` String (optional) - 도메인 또는 서브 도메인에 일치하는 쿠키를
취득합니다.
* `path` String (optional) - `path`에 일치하는 쿠키를 취득합니다.
* `secure` Boolean (optional) - 보안 속성에 따라 쿠키를 필터링합니다.
* `session` Boolean (optional) - 세션 또는 지속성 쿠키를 필터링합니다.
* `callback` Function
`details` 객체에서 묘사한 모든 쿠키를 요청합니다. 모든 작업이 끝나면 `callback`
`callback(error, cookies)` 형태로 호출됩니다.
`cookies``cookie` 객체의 배열입니다.
* `cookie` Object
* `name` String - 쿠키의 이름.
* `value` String - 쿠키의 값.
* `domain` String - 쿠키의 도메인.
* `hostOnly` String - 쿠키가 호스트 전용인가에 대한 여부.
* `path` String - 쿠키의 경로.
* `secure` Boolean - 쿠키가 안전한 것으로 표시되는지에 대한 여부.
* `httpOnly` Boolean - 쿠키가 HTTP로만 표시되는지에 대한 여부.
* `session` Boolean - 쿠키가 세션 쿠키 또는 만료일이 있는 영구 쿠키인지에 대한
여부.
* `expirationDate` Double - (Option) UNIX 시간으로 표시되는 쿠키의 만료일에
대한 초 단위 시간. 세션 쿠키는 지원되지 않음.
#### `ses.cookies.set(details, callback)`
* `details` Object
* `url` String - 쿠키에 대한 `url` 링크.
* `name` String - 쿠키의 이름입니다. 기본적으로 비워두면 생략됩니다.
* `value` String - 쿠키의 값입니다. 기본적으로 비워두면 생략됩니다.
* `domain` String - 쿠키의 도메인입니다. 기본적으로 비워두면 생략됩니다.
* `path` String - 쿠키의 경로입니다. 기본적으로 비워두면 생략됩니다.
* `secure` Boolean - 쿠키가 안전한 것으로 표시되는지에 대한 여부입니다. 기본값은
false입니다.
* `httpOnly` Boolean - 쿠키가 Http 전용으로 표시되는지에 대한 여부입니다. 기본값은
false입니다.
* `expirationDate` Double (optional) - UNIX 시간으로 표시되는 쿠키의 만료일에
대한 초 단위 시간입니다. 생략되면 쿠키가 세션 쿠기가 되며 세션 사이에 유지되지
않게 됩니다.
* `callback` Function
`details` 객체에 따라 쿠키를 설정합니다. 작업이 완료되면 `callback`
`callback(error)` 형태로 호출됩니다.
#### `ses.cookies.remove(url, name, callback)`
* `url` String - 쿠키와 관련된 URL입니다.
* `name` String - 지울 쿠키의 이름입니다.
* `callback` Function
`url``name`에 일치하는 쿠키를 삭제합니다. 작업이 완료되면 `callback`
`callback()` 형식으로 호출됩니다.
## Class: WebRequest
`WebRequest` 클래스는 생명 주기의 다양한 단계에서 요청의 콘텐츠를 조작하거나 가로채는
방법을 제공합니다. `WebRequest` 클래스는 반드시 `Session` 클래스의 `webRequest`
속성에서 접근해야 합니다.
`WebRequest`의 메서드는 선택적인 `filter``listener` 속성을 허용하며 `listener`
API의 이벤트가 발생했을 때 `listener(details)` 형식으로 호출되고, `details`는 요청에
관한 내용을 표현하는 객체입니다. `listener``null`을 전달하면 이벤트의 구독을
해제합니다.
`filter``urls` 속성을 가진 객체입니다. 이 속성은 URL 규칙의 배열이며 URL 규칙에
일치하지 않는 요청을 모두 거르는데 사용됩니다. 만약 `filter`가 생략되면 모든 요청을
@ -355,19 +411,25 @@ session.defaultSession.allowNTLMCredentialsForDomains('*')
어떤 `listener`의 이벤트들은 `callback`을 같이 전달하는데, 이벤트 처리시
`listener`의 작업을 완료한 후 `response` 객체를 포함하여 호출해야 합니다.
다음은 요청에 `User-Agent` 헤더를 추가하는 예시입니다:
```javascript
// 다음 url에 대한 User Agent를 조작합니다.
const filter = {
urls: ['https://*.github.com/*', '*://electron.github.io']
};
}
session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => {
details.requestHeaders['User-Agent'] = "MyAgent";
callback({cancel: false, requestHeaders: details.requestHeaders});
});
details.requestHeaders['User-Agent'] = "MyAgent"
callback({cancel: false, requestHeaders: details.requestHeaders})
})
```
#### `ses.webRequest.onBeforeRequest([filter, ]listener)`
### Instance Methods
다음은 `WebRequest` 객체에서 사용할 수 있는 메서드들입니다:
#### `webRequest.onBeforeRequest([filter, ]listener)`
* `filter` Object
* `listener` Function
@ -396,7 +458,7 @@ session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback
* `redirectURL` String (optional) - 원래 요청은 전송과 완료가 방지되지만 이
속성을 지정하면 해당 URL로 리다이렉트됩니다.
#### `ses.webRequest.onBeforeSendHeaders([filter, ]listener)`
#### `webRequest.onBeforeSendHeaders([filter, ]listener)`
* `filter` Object
* `listener` Function
@ -421,7 +483,7 @@ HTTP 요청을 보내기 전 요청 헤더를 사용할 수 있을 때 `listener
* `requestHeaders` Object (optional) - 이 속성이 제공되면, 요청은 이 헤더로
만들어 집니다.
#### `ses.webRequest.onSendHeaders([filter, ]listener)`
#### `webRequest.onSendHeaders([filter, ]listener)`
* `filter` Object
* `listener` Function
@ -438,7 +500,7 @@ HTTP 요청을 보내기 전 요청 헤더를 사용할 수 있을 때 `listener
* `timestamp` Double
* `requestHeaders` Object
#### `ses.webRequest.onHeadersReceived([filter, ]listener)`
#### `webRequest.onHeadersReceived([filter, ]listener)`
* `filter` Object
* `listener` Function
@ -467,7 +529,7 @@ HTTP 요청을 보내기 전 요청 헤더를 사용할 수 있을 때 `listener
변경하기 위해 반드시 지정되어야 합니다. 그렇지 않은 경우, 기존의 응답 헤더의 상태가
사용됩니다.
#### `ses.webRequest.onResponseStarted([filter, ]listener)`
#### `webRequest.onResponseStarted([filter, ]listener)`
* `filter` Object
* `listener` Function
@ -486,7 +548,7 @@ HTTP 요청을 보내기 전 요청 헤더를 사용할 수 있을 때 `listener
* `statusCode` Integer
* `statusLine` String
#### `ses.webRequest.onBeforeRedirect([filter, ]listener)`
#### `webRequest.onBeforeRedirect([filter, ]listener)`
* `filter` Object
* `listener` Function
@ -506,7 +568,7 @@ HTTP 요청을 보내기 전 요청 헤더를 사용할 수 있을 때 `listener
* `fromCache` Boolean
* `responseHeaders` Object
#### `ses.webRequest.onCompleted([filter, ]listener)`
#### `webRequest.onCompleted([filter, ]listener)`
* `filter` Object
* `listener` Function
@ -524,7 +586,7 @@ HTTP 요청을 보내기 전 요청 헤더를 사용할 수 있을 때 `listener
* `statusCode` Integer
* `statusLine` String
#### `ses.webRequest.onErrorOccurred([filter, ]listener)`
#### `webRequest.onErrorOccurred([filter, ]listener)`
* `filter` Object
* `listener` Function
@ -539,23 +601,3 @@ HTTP 요청을 보내기 전 요청 헤더를 사용할 수 있을 때 `listener
* `timestamp` Double
* `fromCache` Boolean
* `error` String - 에러 설명.
#### `ses.protocol`
현재 세션의 [protocol](protocol.md) 모듈 인스턴스를 반환합니다.
```javascript
const {app, session} = require('electron')
const path = require('path')
app.on('ready', function () {
const protocol = session.fromPartition(partitionName).protocol
protocol.registerFileProtocol('atom', function (request, callback) {
var url = request.url.substr(7)
callback({path: path.normalize(__dirname + '/' + url)})
}, function (error) {
if (error)
console.error('Failed to register protocol')
})
})
```

View file

@ -2,6 +2,11 @@
> 시스템 설정을 가져옵니다.
```javascript
const {systemPreferences} = require('electron');
console.log(systemPreferences.isDarkMode());
```
## Methods
### `systemPreferences.isDarkMode()` _macOS_
@ -34,6 +39,17 @@ macOS의 네이티브 알림을 구독하며, 해당하는 `event`가 발생하
`id`와 함께 구독자를 제거합니다.
### `systemPreferences.subscribeLocalNotification(event, callback)` _macOS_
`subscribeNotification`와 같지만, 로컬 기본값으로 `NSNotificationCenter`
사용합니다. 다음과 같은 이벤트에 필수적입니다:
* `NSUserDefaultsDidChangeNotification`
### `systemPreferences.unsubscribeLocalNotification(id)` _macOS_
`unsubscribeNotification`와 같지만, `NSNotificationCenter`에서 구독자를 제거합니다.
### `systemPreferences.getUserDefault(key, type)` _macOS_
* `key` String

View file

@ -3,20 +3,20 @@
> 아이콘과 컨텍스트 메뉴를 시스템 알림 영역에 추가합니다.
```javascript
const {app, Menu, Tray} = require('electron');
const {app, Menu, Tray} = require('electron')
let appIcon = null;
let tray = null
app.on('ready', () => {
appIcon = new Tray('/path/to/my/icon'); // 현재 애플리케이션 디렉터리를 기준으로 하려면 `__dirname + '/images/tray.png'` 형식으로 입력해야 합니다.
tray = new Tray('/path/to/my/icon') // 현재 애플리케이션 디렉터리를 기준으로 하려면 `__dirname + '/images/tray.png'` 형식으로 입력해야 합니다.
const contextMenu = Menu.buildFromTemplate([
{label: 'Item1', type: 'radio'},
{label: 'Item2', type: 'radio'},
{label: 'Item3', type: 'radio', checked: true},
{label: 'Item4', type: 'radio'}
]);
appIcon.setToolTip('이것은 나의 애플리케이션 입니다!');
appIcon.setContextMenu(contextMenu);
});
tray.setToolTip('이것은 나의 애플리케이션 입니다!')
tray.setContextMenu(contextMenu)
})
```
__플랫폼별 한계:__
@ -33,8 +33,8 @@ __플랫폼별 한계:__
호출해야 합니다. 예를 들면:
```javascript
contextMenu.items[2].checked = false;
appIcon.setContextMenu(contextMenu);
contextMenu.items[2].checked = false
appIcon.setContextMenu(contextMenu)
```
이러한 이유로 Tray API가 모든 플랫폼에서 똑같이 작동하게 하고 싶다면 `click` 이벤트에
@ -50,20 +50,18 @@ appIcon.setContextMenu(contextMenu);
전달된 `image`를 이용하여 트레이 아이콘을 만듭니다.
## Events
### Instance Events
`Tray` 모듈은 다음과 같은 이벤트를 가지고 있습니다:
**참고:** 몇몇 이벤트는 특정한 플랫폼에서만 작동합니다.
### Event: 'click'
#### Event: 'click'
* `event` Event
* `altKey` Boolean
* `shiftKey` Boolean
* `ctrlKey` Boolean
* `metaKey` Boolean
* `bounds` Object - 트레이 아이콘의 범위
* `bounds` Object _macOS_ _Windows_ - 트레이 아이콘의 범위
* `x` Integer
* `y` Integer
* `width` Integer
@ -71,9 +69,7 @@ appIcon.setContextMenu(contextMenu);
트레이 아이콘이 클릭될 때 발생하는 이벤트입니다.
**참고:** `bounds`는 macOS 와 Windows에서만 작동합니다.
### Event: 'right-click' _macOS_ _Windows_
#### Event: 'right-click' _macOS_ _Windows_
* `event` Event
* `altKey` Boolean
@ -88,7 +84,7 @@ appIcon.setContextMenu(contextMenu);
트레이 아이콘을 오른쪽 클릭될 때 호출 됩니다.
### Event: 'double-click' _macOS_ _Windows_
#### Event: 'double-click' _macOS_ _Windows_
* `event` Event
* `altKey` Boolean
@ -103,83 +99,81 @@ appIcon.setContextMenu(contextMenu);
트레이 아이콘이 더블 클릭될 때 발생하는 이벤트입니다.
### Event: 'balloon-show' _Windows_
#### Event: 'balloon-show' _Windows_
풍선 팝업이 보여질 때 발생하는 이벤트입니다.
### Event: 'balloon-click' _Windows_
#### Event: 'balloon-click' _Windows_
풍선 팝업이 클릭될 때 발생하는 이벤트입니다.
### Event: 'balloon-closed' _Windows_
#### Event: 'balloon-closed' _Windows_
풍선 팝업이 시간이 지나 사라지거나 유저가 클릭하여 닫을 때 발생하는 이벤트입니다.
### Event: 'drop' _macOS_
#### Event: 'drop' _macOS_
드래그 가능한 아이템이 트레이 아이콘에 드롭되면 발생하는 이벤트입니다.
### Event: 'drop-files' _macOS_
#### Event: 'drop-files' _macOS_
* `event`
* `event` Event
* `files` Array - 드롭된 파일의 경로
트레이 아이콘에 파일이 드롭되면 발생하는 이벤트입니다.
### Event: 'drag-enter' _macOS_
#### Event: 'drag-enter' _macOS_
트레이 아이콘에 드래그 작업이 시작될 때 발생하는 이벤트입니다.
### Event: 'drag-leave' _macOS_
#### Event: 'drag-leave' _macOS_
트레이 아이콘에 드래그 작업이 종료될 때 발생하는 이벤트입니다.
### Event: 'drag-end' _macOS_
#### Event: 'drag-end' _macOS_
트레이 아이콘에 드래그 작업이 종료되거나 다른 위치에서 종료될 때 발생하는 이벤트입니다.
## Methods
### Instance Methods
`Tray` 모듈은 다음과 같은 메서드를 가지고 있습니다:
`Tray` 클래스는 다음과 같은 메서드를 가지고 있습니다:
**참고:** 몇몇 메서드는 특정 플랫폼에서만 작동합니다.
### `Tray.destroy()`
#### `tray.destroy()`
트레이 아이콘을 즉시 삭제시킵니다.
### `Tray.setImage(image)`
#### `tray.setImage(image)`
* `image` [NativeImage](native-image.md)
`image`를 사용하여 트레이 아이콘의 이미지를 설정합니다.
### `Tray.setPressedImage(image)` _macOS_
#### `tray.setPressedImage(image)` _macOS_
* `image` [NativeImage](native-image.md)
`image`를 사용하여 트레이 아이콘이 눌렸을 때의 이미지를 설정합니다.
### `Tray.setToolTip(toolTip)`
#### `tray.setToolTip(toolTip)`
* `toolTip` String
트레이 아이콘의 툴팁 텍스트를 설정합니다.
### `Tray.setTitle(title)` _macOS_
#### `tray.setTitle(title)` _macOS_
* `title` String
상태바에서 트레이 아이콘 옆에 표시되는 제목 텍스트를 설정합니다.
### `Tray.setHighlightMode(highlight)` _macOS_
#### `tray.setHighlightMode(highlight)` _macOS_
* `highlight` Boolean
트레이 아이콘이 클릭됐을 때 아이콘의 배경이 파란색으로 하이라이트 될지 여부를 지정합니다.
기본값은 true입니다.
### `Tray.displayBalloon(options)` _Windows_
#### `tray.displayBalloon(options)` _Windows_
* `options` Object
* `icon` [NativeImage](native-image.md)
@ -188,7 +182,7 @@ appIcon.setContextMenu(contextMenu);
트레이에 풍선 팝업을 생성합니다.
### `Tray.popUpContextMenu([menu, position])` _macOS_ _Windows_
#### `tray.popUpContextMenu([menu, position])` _macOS_ _Windows_
* `menu` Menu (optional)
* `position` Object (optional) - 팝업 메뉴의 위치
@ -200,10 +194,20 @@ appIcon.setContextMenu(contextMenu);
`position`은 Windows에서만 사용할 수 있으며 기본값은 (0, 0)입니다.
### `Tray.setContextMenu(menu)`
### `tray.setContextMenu(menu)`
* `menu` Menu
트레이에 컨텍스트 메뉴를 설정합니다.
### `tray.getBounds()` _macOS_ _Windows_
이 트레이 아이콘의 `bounds``Object` 형식으로 반환합니다.
* `bounds` Object
* `x` Integer
* `y` Integer
* `width` Integer
* `height` Integer
[event-emitter]: http://nodejs.org/api/events.html#events_class_events_eventemitter

View file

@ -349,23 +349,25 @@ Returns:
표시합니다. 자세한 사항은 아래를 참고하세요.
`mediaFlags`는 다음과 같은 속성을 가지고 있습니다:
* `inError` Boolean - 미디어 객체가 크래시되었는지 여부.
* `isPaused` Boolean - 미디어 객체가 일시중지되었는지 여부.
* `isMuted` Boolean - 미디어 객체가 음소거되었는지 여부.
* `hasAudio` Boolean - 미디어 객체가 오디오를 가지고 있는지 여부.
* `isLooping` Boolean - 미디어 객체가 루프중인지 여부.
* `isControlsVisible` Boolean - 미디어 객체의 컨트롤이 보이는지 여부.
* `canToggleControls` Boolean - 미디어 객체의 컨트롤을 토글할 수 있는지 여부.
* `canRotate` Boolean - 미디어 객체를 돌릴 수 있는지 여부.
* `inError` Boolean - 미디어 객체가 크래시되었는지 여부.
* `isPaused` Boolean - 미디어 객체가 일시중지되었는지 여부.
* `isMuted` Boolean - 미디어 객체가 음소거되었는지 여부.
* `hasAudio` Boolean - 미디어 객체가 오디오를 가지고 있는지 여부.
* `isLooping` Boolean - 미디어 객체가 루프중인지 여부.
* `isControlsVisible` Boolean - 미디어 객체의 컨트롤이 보이는지 여부.
* `canToggleControls` Boolean - 미디어 객체의 컨트롤을 토글할 수 있는지 여부.
* `canRotate` Boolean - 미디어 객체를 돌릴 수 있는지 여부.
`editFlags`는 다음과 같은 속성을 가지고 있습니다:
* `canUndo` Boolean - 렌더러에서 실행 취소할 수 있는지 여부.
* `canRedo` Boolean - 렌더러에서 다시 실행할 수 있는지 여부.
* `canCut` Boolean - 렌더러에서 잘라내기를 실행할 수 있는지 여부.
* `canCopy` Boolean - 렌더러에서 복사를 실행할 수 있는지 여부.
* `canPaste` Boolean - 렌더러에서 붙여넣기를 실행할 수 있는지 여부.
* `canDelete` Boolean - 렌더러에서 삭제를 실행할 수 있는지 여부.
* `canSelectAll` Boolean - 렌더러에서 모두 선택을 실행할 수 있는지 여부.
* `canUndo` Boolean - 렌더러에서 실행 취소할 수 있는지 여부.
* `canRedo` Boolean - 렌더러에서 다시 실행할 수 있는지 여부.
* `canCut` Boolean - 렌더러에서 잘라내기를 실행할 수 있는지 여부.
* `canCopy` Boolean - 렌더러에서 복사를 실행할 수 있는지 여부.
* `canPaste` Boolean - 렌더러에서 붙여넣기를 실행할 수 있는지 여부.
* `canDelete` Boolean - 렌더러에서 삭제를 실행할 수 있는지 여부.
* `canSelectAll` Boolean - 렌더러에서 모두 선택을 실행할 수 있는지 여부.
새로운 컨텍스트 메뉴의 제어가 필요할 때 발생하는 이벤트입니다.
@ -904,12 +906,14 @@ Input `event`를 웹 페이지로 전송합니다.
* `hasPreciseScrollingDeltas` Boolean
* `canScroll` Boolean
### `webContents.beginFrameSubscription(callback)`
### `webContents.beginFrameSubscription([onlyDirty ,]callback)`
* `onlyDirty` Boolean (optional) - 기본값은 `false`입니다.
* `callback` Function
캡처된 프레임과 프레젠테이션 이벤트를 구독하기 시작합니다. `callback`
프레젠테이션 이벤트가 발생했을 때 `callback(frameBuffer)` 형태로 호출됩니다.
프레젠테이션 이벤트가 발생했을 때 `callback(frameBuffer, dirtyRect)` 형태로
호출됩니다.
`frameBuffer`는 raw 픽셀 데이터를 가지고 있는 `Buffer` 객체입니다. 많은 장치에서
32비트 BGRA 포맷을 사용하여 효율적으로 픽셀 데이터를 저장합니다. 하지만 실질적인
@ -917,6 +921,10 @@ Input `event`를 웹 페이지로 전송합니다.
프로세서에선 little-endian 방식을 사용하므로 위의 포맷을 그대로 표현합니다. 하지만
몇몇 프로세서는 big-endian 방식을 사용하는데, 이 경우 32비트 ARGB 포맷을 사용합니다)
`dirtyRect`는 페이지의 어떤 부분이 다시 그려졌는지를 표현하는 `x, y, width, height`
속성을 포함하는 객체입니다. 만약 `onlyDirty``true`로 지정되어 있으면,
`frameBuffer`가 다시 그려진 부분만 포함합니다. `onlyDirty`의 기본값은 `false`입니다.
### `webContents.endFrameSubscription()`
프레임 프레젠테이션 이벤트들에 대한 구독을 중지합니다.

View file

@ -53,14 +53,12 @@ Electron 문서 구조를 이해하는 데 참고할 수 있는 유용한 도움
[Method](https://developer.mozilla.org/ko/docs/Glossary/Method) 문서의
예시입니다:
---
```
`methodName(required[, optional]))`
* `require` String (**required**)
* `required` String (**required**)
* `optional` Integer
---
```
메서드 이름은 인수가 무엇을 받는지에 따라 결정됩니다. 선택적 인수는 브라켓([, ])으로
묶어 이 인수가 다른 인수뒤에서 선택적으로 사용될 수 있다는 것을 표시합니다.
@ -73,19 +71,25 @@ Electron 문서 구조를 이해하는 데 참고할 수 있는 유용한 도움
와 같은 일반적으로 쓰이는 타입 중 하나를 받거나 Electron의 [`webContent`](api/web-content.md)
같은 커스텀 타입을 받습니다.
만약 인수가 특정 플랫폼에 대해서만 적용된다면, 해당하는 플랫폼들을 공백-구분된 이텔릭체
리스트를 데이터 타입 뒤에 표기합니다. 값은 `OS X`, `Windows` 또는 `Linux`가 될 수
있습니다.
```
* `animate` Boolean (optional) _OS X_ _Windows_
```
### Events
[Event](https://developer.mozilla.org/ko/docs/Web/API/Event) 문서의 예시입니다:
---
```
Event: 'wake-up'
Returns:
* `time` String
---
```
이벤트는 `.on` 리스너 메서드로 사용할 수 있습니다. 만약 이벤트에서 값을 반환한다면
문서에서 표시된 대로 일정한 타입의 값을 반환합니다. 이벤트를 처리하거나 응답하려 한다면
@ -94,5 +98,5 @@ Returns:
```javascript
Alarm.on('wake-up', (time) => {
console.log(time)
});
})
```

View file

@ -19,11 +19,11 @@
## node-inspector로 디버깅 하기
**참고:** Electron은 현재 node-inspector 유틸리티와 호환성 문제가 있습니다. 따라서
node-inspector 콘솔 내에서 메인 프로세스의 `process` 객체를 탐색할 경우 크래시가
**참고:** Electron은 현재 node-inspector 유틸리티와 호환성 문제가 있습니다. 이러한
이유로 node-inspector 콘솔 내에서 메인 프로세스의 `process` 객체를 탐색할 경우 크래시가
발생할 수 있습니다.
### 1. [node-gyp 필수 도구][node-gyp-required-tools] 설치했는지 확인
### 1. [node-gyp 필수 도구][node-gyp-required-tools] 설치
### 2. [node-inspector][node-inspector] 설치
@ -31,17 +31,19 @@ node-inspector 콘솔 내에서 메인 프로세스의 `process` 객체를 탐
$ npm install node-inspector
```
### 3. 패치된 버전의 `node-pre-gyp` 설치
### 3. [node-pre-gyp][node-pre-gyp] 설치
```bash
$ npm install git+https://git@github.com/enlight/node-pre-gyp.git#detect-electron-runtime-in-find
$ npm install node-pre-gyp
```
### 4. Electron용 `node-inspector` `v8` 모듈을 재 컴파일 (target을 사용하는 Electron의 버전에 맞춰 변경)
### 4. Electron용 `node-inspector` `v8` 모듈을 재 컴파일
**참고:** target 인수를 사용하는 Electron의 버전에 맞춰 변경하세요.
```bash
$ node_modules/.bin/node-pre-gyp --target=0.36.11 --runtime=electron --fallback-to-build --directory node_modules/v8-debug/ --dist-url=https://atom.io/download/atom-shell reinstall
$ node_modules/.bin/node-pre-gyp --target=0.36.11 --runtime=electron --fallback-to-build --directory node_modules/v8-profiler/ --dist-url=https://atom.io/download/atom-shell reinstall
$ node_modules/.bin/node-pre-gyp --target=1.2.5 --runtime=electron --fallback-to-build --directory node_modules/v8-debug/ --dist-url=https://atom.io/download/atom-shell reinstall
$ node_modules/.bin/node-pre-gyp --target=1.2.5 --runtime=electron --fallback-to-build --directory node_modules/v8-profiler/ --dist-url=https://atom.io/download/atom-shell reinstall
```
또한 [네이티브 모듈을 사용하는 방법][how-to-install-native-modules] 문서도 참고해보세요.
@ -60,7 +62,7 @@ $ electron --debug=5858 your/app
$ electron --debug-brk=5858 your/app
```
### 6. Electron을 사용하는 [node-inspector][node-inspector] 시작
### 6. Electron을 사용하는 [node-inspector][node-inspector] 시작하기
```bash
$ ELECTRON_RUN_AS_NODE=true path/to/electron.exe node_modules/node-inspector/bin/inspector.js
@ -69,9 +71,10 @@ $ ELECTRON_RUN_AS_NODE=true path/to/electron.exe node_modules/node-inspector/bin
### 7. 디버거 UI 로드
Chrome 브라우저에서 http://127.0.0.1:8080/debug?ws=127.0.0.1:8080&port=5858 주소에
접속합니다. (기본 포트 또는 지정한 포트로 접속) 엔트리의 라인이 debug-brk로 시작하는
접속합니다. (기본 포트 또는 지정한 포트로 접속) 엔트리의 라인이 `debug-brk`로 시작하는
경우 일시정지 버튼을 클릭해야 할 수도 있습니다.
[node-inspector]: https://github.com/node-inspector/node-inspector
[node-pre-gyp]: https://github.com/mapbox/node-pre-gyp
[node-gyp-required-tools]: https://github.com/nodejs/node-gyp#installation
[how-to-install-native-modules]: using-native-node-modules.md#네이티브-모듈을-설치하는-방법

View file

@ -212,7 +212,7 @@ $ ./Electron.app/Contents/MacOS/Electron your-app/
### 미리 작성된 앱 실행하기
[`atom/electron-quick-start`](https://github.com/electron/electron-quick-start)
[`electron/electron-quick-start`](https://github.com/electron/electron-quick-start)
저장소를 클론하면 이 문서에서 작성한 예시 앱을 바로 실행해 볼 수 있습니다.
**참고**: 이 예시를 실행시키려면 [Git](https://git-scm.com)과

View file

@ -52,10 +52,10 @@ Existem muitas perguntas comuns que são feitas, verifique antes de criar uma is
* [contentTracing](../../docs/api/content-tracing.md)
* [dialog](../../docs/api/dialog.md)
* [globalShortcut](../../docs/api/global-shortcut.md)
* [ipcMain](../../docs/api/ipc-main-process.md)
* [ipcMain](../../docs/api/ipc-main.md)
* [Menu](../../docs/api/menu.md)
* [MenuItem](../../docs/api/menu-item.md)
* [powerMonitor](../../docs/api/power-monitor.md)
* [powerMonitor](api/power-monitor.md)
* [powerSaveBlocker](../../docs/api/power-save-blocker.md)
* [protocol](../../docs/api/protocol.md)
* [session](../../docs/api/session.md)
@ -64,7 +64,7 @@ Existem muitas perguntas comuns que são feitas, verifique antes de criar uma is
### Módulos para o Processo Renderizador:
* [DesktopCapturer](../../docs/api/desktop-capturer)
* [DesktopCapturer](../../docs/api/desktop-capturer.md)
* [ipcRenderer](../../docs/api/ipc-renderer.md)
* [remote](../../docs/api/remote.md)
* [webFrame](../../docs/api/web-frame.md)

View file

@ -40,7 +40,7 @@ Emitido quando está verificando se uma atualização foi inicializada.
### Evento: 'update-available'
Emitido quando há uma atualização disponível. A autalização é baixada automaticamente.
Emitido quando há uma atualização disponível. A atualização é baixada automaticamente.
### Evento: 'update-not-available'

View file

@ -0,0 +1,35 @@
# powerMonitor
> Monitorar as mudanças de estado de energia.
Você só pode usá-lo no processo principal. Você não deve usar este módulo até que o evento `ready` do modulo `app` seja emitido.
Por exemplo:
```javascript
app.on('ready', () => {
require('electron').powerMonitor.on('suspend', () => {
console.log('O sistema está indo dormir');
});
});
```
## Eventos
O módulo `power-monitor` emite os seguintes eventos:
### Evento: 'suspend'
Emitido quando o sistema está a suspender.
### Evento: 'resume'
Emitido quando o sistema está a retomar.
### Evento: 'on-ac' _Windows_
Emitido quando o sistema muda para energia AC.
### Evento: 'on-battery' _Windows_
Emitido quando o sistema muda para a energia da bateria.

View file

@ -41,6 +41,6 @@ Atualmente o Electron não suporta páginas em segundo plano nas extensões do C
Algumas extensões do Chrome podem usar a API `chrome.*`. Apesar de um esforço na implementação destas APIs no Electron, elas ainda não estão finalizadas.
Dado que nem todas as funções `chrome.*` esstão implementadas, algumas extensões que utilizam `chrome.devtools.*` podem não funcionar. Você pode reportar este erro no issue tracker para que possamos adicionar suporte a essas APIs.
Dado que nem todas as funções `chrome.*` estão implementadas, algumas extensões que utilizam `chrome.devtools.*` podem não funcionar. Você pode reportar este erro no issue tracker para que possamos adicionar suporte a essas APIs.
[devtools-extension]: https://developer.chrome.com/extensions/devtools

View file

@ -1,8 +1,8 @@
# Online/Offline Event Detection
Os eventos de detecão Online e Offile podem ser implementados no processo
Os eventos de detecção Online e Offline podem ser implementados no processo
de renderização utilizando a API padrão do HTML, como é mostrado no exemplo
a seguir.
a seguir:
_main.js_
@ -41,7 +41,7 @@ Pode haver casos onde você também deseja responder a estes eventos no processo
Mas o processo principal não consegue detectar esses eventos diretamente, pois não possui
um objeto `navigator`. Utilizando a ferramentas para comunicação entre processos, os eventos
podem ser direcionados para o processo principal e manipulados quando necessário. Você
pode ver isto no exemplo abaixo.
pode ver isto no exemplo abaixo:
_main.js_

View file

@ -107,11 +107,11 @@ const nativeImage = require('electron').nativeImage;
var image = nativeImage.createFromPath('/Users/somebody/images/icon.png');
```
### `image.toPng()`
### `image.toPNG()`
返回一个 [Buffer][buffer] ,它包含了图片的 `PNG` 编码数据.
### `image.toJpeg(quality)`
### `image.toJPEG(quality)`
* `quality` Integer (**必须**) - 在 0 - 100 之间.

View file

@ -6,7 +6,7 @@
在用户默认浏览器中打开URL的示例:
```javascript
var shell = require('shell');
const {shell} = require('electron');
shell.openExternal('https://github.com');
```

View file

@ -846,14 +846,14 @@ win.webContents.debugger.sendCommand("Network.enable");
发送给定命令给调试目标.
#### Event: 'detach'
### Event: 'detach'
* `event` Event
* `reason` String - 拆分调试器原因.
在调试 session 结束时发出事件.这在 `webContents` 关闭时或 `webContents` 请求开发者工具栏时发生.
#### Event: 'message'
### Event: 'message'
* `event` Event
* `method` String - 方法名.

137
docs/api/app-locales.md Normal file
View file

@ -0,0 +1,137 @@
# Possible Values of `app.getLocale()`
Electron uses Chromium's `l10n_util` library to fetch the locale. Possible
values are listed below:
| Language Code | Language Name |
|---------------|---------------|
| af | Afrikaans |
| ar-AE | Arabic (U.A.E.) |
| ar-IQ | Arabic (Iraq) |
| ar | Arabic (Standard) |
| ar-BH | Arabic (Bahrain) |
| ar-DZ | Arabic (Algeria) |
| ar-EG | Arabic (Egypt) |
| ar | Aragonese |
| ar-JO | Arabic (Jordan) |
| ar-KW | Arabic (Kuwait) |
| ar-LB | Arabic (Lebanon) |
| ar-LY | Arabic (Libya) |
| ar-MA | Arabic (Morocco) |
| ar-OM | Arabic (Oman) |
| ar-QA | Arabic (Qatar) |
| ar-SA | Arabic (Saudi Arabia) |
| ar-SY | Arabic (Syria) |
| ar-TN | Arabic (Tunisia) |
| ar-YE | Arabic (Yemen) |
| as | Assamese |
| ast | Asturian |
| az | Azerbaijani |
| be | Belarusian |
| bg | Bulgarian |
| bg | Bulgarian |
| bn | Bengali |
| br | Breton |
| bs | Bosnian |
| ca | Catalan |
| ce | Chechen |
| ch | Chamorro |
| co | Corsican |
| cr | Cree |
| cs | Czech |
| cv | Chuvash |
| da | Danish |
| de | German (Standard) |
| de-AT | German (Austria) |
| de-CH | German (Switzerland) |
| de-DE | German (Germany) |
| de-LI | German (Liechtenstein) |
| de-LU | German (Luxembourg) |
| el | Greek |
| en-AU | English (Australia) |
| en-BZ | English (Belize) |
| en | English |
| en-CA | English (Canada) |
| en-GB | English (United Kingdom) |
| en-IE | English (Ireland) |
| en-JM | English (Jamaica) |
| en-NZ | English (New Zealand) |
| en-PH | English (Philippines) |
| en-TT | English (Trinidad & Tobago) |
| en-US | English (United States) |
| en-ZA | English (South Africa) |
| en-ZW | English (Zimbabwe) |
| eo | Esperanto |
| et | Estonian |
| eu | Basque |
| fa | Persian |
| fa | Farsi |
| fa-IR | Persian/Iran |
| fi | Finnish |
| fj | Fijian |
| fo | Faeroese |
| fr-CH | French (Switzerland) |
| fr-FR | French (France) |
| fr-LU | French (Luxembourg) |
| fr-MC | French (Monaco) |
| fr | French (Standard) |
| fr-BE | French (Belgium) |
| fr-CA | French (Canada) |
| fur | Friulian |
| fy | Frisian |
| ga | Irish |
| gd-IE | Gaelic (Irish) |
| gd | Gaelic (Scots) |
| gl | Galacian |
| gu | Gujurati |
| he | Hebrew |
| hi | Hindi |
| hr | Croatian |
| ht | Haitian |
| hu | Hungarian |
| hy | Armenian |
| id | Indonesian |
| is | Icelandic |
| it-CH | Italian (Switzerland) |
| it | Italian (Standard) |
| iu | Inuktitut |
| ja | Japanese |
| ka | Georgian |
| kk | Kazakh |
| km | Khmer |
| kn | Kannada |
| ko | Korean |
| ko-KP | Korean (North Korea) |
| ko-KR | Korean (South Korea) |
| ks | Kashmiri |
| ky | Kirghiz |
| la | Latin |
| lb | Luxembourgish |
| lt | Lithuanian |
| lv | Latvian |
| mi | Maori |
| mk | FYRO Macedonian |
| ml | Malayalam |
| mo | Moldavian |
| mr | Marathi |
| ms | Malay |
| mt | Maltese |
| my | Burmese |
| nb | Norwegian (Bokmal) |
| ne | Nepali |
| ng | Ndonga |
| nl | Dutch (Standard) |
| nl-BE | Dutch (Belgian) |
| nn | Norwegian (Nynorsk) |
| no | Norwegian |
| nv | Navajo |
| oc | Occitan |
| om | Oromo |
| or | Oriya |
| sq | Albanian |
| tlh | Klingon |
| zh-TW | Chinese (Taiwan) |
| zh | Chinese |
| zh-CN | Chinese (PRC) |
| zh-HK | Chinese (Hong Kong) |
| zh-SG | Chinese (Singapore) |

View file

@ -396,7 +396,8 @@ Overrides the current application's name.
### `app.getLocale()`
Returns the current application locale.
Returns the current application locale. Possible return values are documented
[here](app-locales.md).
**Note:** When distributing your packaged app, you have to also ship the
`locales` folder.
@ -577,6 +578,26 @@ Disables hardware acceleration for current app.
This method can only be called before app is ready.
### `app.setBadgeCount(count)` _Linux_ _macOS_
* `count` Integer
Sets the counter badge for current app. Setting the count to `0` will hide the
badge. Returns `true` when the call succeeded, otherwise returns `false`.
On macOS it shows on the dock icon. On Linux it only works for Unity launcher,
**Note:** Unity launcher requires the exsistence of a `.desktop` file to work,
for more information please read [Desktop Environment Integration][unity-requiremnt].
### `app.getBadgeCount()` _Linux_ _macOS_
Returns the current value displayed in the counter badge.
### `app.isUnityRunning()` _Linux_
Returns whether current desktop environment is Unity launcher.
### `app.commandLine.appendSwitch(switch[, value])`
Append a switch (with optional `value`) to Chromium's command line.
@ -654,3 +675,4 @@ Sets the `image` associated with this dock icon.
[LSCopyDefaultHandlerForURLScheme]: https://developer.apple.com/library/mac/documentation/Carbon/Reference/LaunchServicesReference/#//apple_ref/c/func/LSCopyDefaultHandlerForURLScheme
[handoff]: https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html
[activity-type]: https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUserActivity_Class/index.html#//apple_ref/occ/instp/NSUserActivity/activityType
[unity-requiremnt]: ../tutorial/desktop-environment-integration.md#unity-launcher-shortcuts-linux

View file

@ -542,11 +542,11 @@ the [close event](#event-close).
### `win.focus()`
Focus on the window.
Focuses on the window.
### `win.blur()`
Remove focus on the window.
Removes focus from the window.
### `win.isFocused()`
@ -945,7 +945,7 @@ convey some sort of application status or to passively notify the user.
### `win.setHasShadow(hasShadow)` _macOS_
* `hasShadow` (Boolean)
* `hasShadow` Boolean
Sets whether the window should have a shadow. On Windows and Linux does
nothing.
@ -1050,6 +1050,13 @@ All mouse events happened in this window will be passed to the window below
this window, but if this window has focus, it will still receive keyboard
events.
### `win.setContentProtection(enable)` _macOS_ _Windows_
Prevents the window contents from being captured by other apps.
On macOS it sets the NSWindow's sharingType to NSWindowSharingNone.
On Windows it calls SetWindowDisplayAffinity with WDA_MONITOR.
### `win.setFocusable(focusable)` _Windows_
* `focusable` Boolean

View file

@ -75,6 +75,20 @@ Returns the content in the clipboard as RTF.
Writes the `text` into the clipboard in RTF.
### `clipboard.readBookmark()` _macOS_ _Windows_
Returns an Object containing `title` and `url` keys representing the bookmark in
the clipboard. The `title` and `url` values will be empty strings when the
bookmark is unavailable.
### `clipboard.writeBookmark(title, url[, type])` _macOS_ _Windows_
* `title` String
* `url` String
* `type` String (optional)
Writes the `title` and `url` into the clipboard as a bookmark.
### `clipboard.clear([type])`
* `type` String (optional)
@ -111,6 +125,8 @@ Reads `data` from the clipboard.
* `text` String
* `html` String
* `image` [NativeImage](native-image.md)
* `rtf` String
* `bookmark` String - The title of the url at `text`.
* `type` String (optional)
```javascript

View file

@ -2,7 +2,7 @@
> Add items to native application menus and context menus.
See [`menu`](menu.md) for examples.
See [`Menu`](menu.md) for examples.
## Class: MenuItem
@ -11,12 +11,12 @@ Create a new `MenuItem` with the following method:
### new MenuItem(options)
* `options` Object
* `click` Function - Will be called with `click(menuItem, browserWindow)` when
the menu item is clicked
* `role` String - Define the action of the menu item; when specified the
`click` property will be ignored
* `click` Function - Will be called with
`click(menuItem, browserWindow, event)` when the menu item is clicked.
* `role` String - Define the action of the menu item, when specified the
`click` property will be ignored.
* `type` String - Can be `normal`, `separator`, `submenu`, `checkbox` or
`radio`
`radio`.
* `label` String
* `sublabel` String
* `accelerator` [Accelerator](accelerator.md)
@ -25,20 +25,23 @@ Create a new `MenuItem` with the following method:
unclickable.
* `visible` Boolean - If false, the menu item will be entirely hidden.
* `checked` Boolean - Should only be specified for `checkbox` or `radio` type
menu items.
menu items.
* `submenu` Menu - Should be specified for `submenu` type menu items. If
`submenu` is specified, the `type: 'submenu'` can be omitted. If the value
is not a `Menu` then it will be automatically converted to one using
`Menu.buildFromTemplate`.
`submenu` is specified, the `type: 'submenu'` can be omitted. If the value
is not a `Menu` then it will be automatically converted to one using
`Menu.buildFromTemplate`.
* `id` String - Unique within a single menu. If defined then it can be used
as a reference to this item by the position attribute.
as a reference to this item by the position attribute.
* `position` String - This field allows fine-grained definition of the
specific location within a given menu.
specific location within a given menu.
It is best to specify `role` for any menu item that matches a standard role,
rather than trying to manually implement the behavior in a `click` function.
The built-in `role` behavior will give the best native experience.
The `label` and `accelerator` are optional when using a `role` and will default
to appropriate values for each platform.
The `role` property can have following values:
* `undo`
@ -51,6 +54,8 @@ The `role` property can have following values:
* `delete`
* `minimize` - Minimize current window
* `close` - Close current window
* `quit`- Quit the application
* `togglefullscreen`- Toggle full screen mode on the current window
On macOS `role` can also have following additional values:
@ -67,19 +72,29 @@ On macOS `role` can also have following additional values:
When specifying `role` on macOS, `label` and `accelerator` are the only options
that will affect the MenuItem. All other options will be ignored.
## Instance Properties
### Instance Properties
The following properties (and no others) can be updated on an existing `MenuItem`:
The following properties are available on instances of `MenuItem`:
* `enabled` Boolean
* `visible` Boolean
* `checked` Boolean
#### `menuItem.enabled`
Their meanings are as described above.
A Boolean indicating whether the item is enabled, this property can be
dynamically changed.
A `checkbox` menu item will toggle its `checked` property on and off when
selected. You can add a `click` function to do additional work.
#### `menuItem.visible`
A Boolean indicating whether the item is visible, this property can be
dynamically changed.
#### `menuItem.checked`
A Boolean indicating whether the item is checked, this property can be
dynamically changed.
A `checkbox` menu item will toggle the `checked` property on and off when
selected.
A `radio` menu item will turn on its `checked` property when clicked, and
will turn off that property for all adjacent items in the same menu. Again,
you can add a `click` function for additional behavior.
will turn off that property for all adjacent items in the same menu.
You can add a `click` function for additional behavior.

View file

@ -39,45 +39,30 @@ const template = [
label: 'Edit',
submenu: [
{
label: 'Undo',
accelerator: 'CmdOrCtrl+Z',
role: 'undo'
},
{
label: 'Redo',
accelerator: 'Shift+CmdOrCtrl+Z',
role: 'redo'
},
{
type: 'separator'
},
{
label: 'Cut',
accelerator: 'CmdOrCtrl+X',
role: 'cut'
},
{
label: 'Copy',
accelerator: 'CmdOrCtrl+C',
role: 'copy'
},
{
label: 'Paste',
accelerator: 'CmdOrCtrl+V',
role: 'paste'
},
{
label: 'Paste and Match Style',
accelerator: 'Shift+Command+V',
role: 'pasteandmatchstyle'
},
{
label: 'Delete',
role: 'delete'
},
{
label: 'Select All',
accelerator: 'CmdOrCtrl+A',
role: 'selectall'
},
]
@ -93,12 +78,7 @@ const template = [
}
},
{
label: 'Toggle Full Screen',
accelerator: process.platform === 'darwin' ? 'Ctrl+Command+F' : 'F11',
click(item, focusedWindow) {
if (focusedWindow)
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
}
role: 'togglefullscreen'
},
{
label: 'Toggle Developer Tools',
@ -111,23 +91,17 @@ const template = [
]
},
{
label: 'Window',
role: 'window',
submenu: [
{
label: 'Minimize',
accelerator: 'CmdOrCtrl+M',
role: 'minimize'
},
{
label: 'Close',
accelerator: 'CmdOrCtrl+W',
role: 'close'
},
]
},
{
label: 'Help',
role: 'help',
submenu: [
{
@ -144,14 +118,12 @@ if (process.platform === 'darwin') {
label: name,
submenu: [
{
label: 'About ' + name,
role: 'about'
},
{
type: 'separator'
},
{
label: 'Services',
role: 'services',
submenu: []
},
@ -159,26 +131,19 @@ if (process.platform === 'darwin') {
type: 'separator'
},
{
label: 'Hide ' + name,
accelerator: 'Command+H',
role: 'hide'
},
{
label: 'Hide Others',
accelerator: 'Command+Alt+H',
role: 'hideothers'
},
{
label: 'Show All',
role: 'unhide'
},
{
type: 'separator'
},
{
label: 'Quit',
accelerator: 'Command+Q',
click() { app.quit(); }
role: 'quit'
},
]
});

View file

@ -127,11 +127,11 @@ Creates a new `nativeImage` instance from `dataURL`.
The following methods are available on instances of `nativeImage`:
### `image.toPng()`
### `image.toPNG()`
Returns a [Buffer][buffer] that contains the image's `PNG` encoded data.
### `image.toJpeg(quality)`
### `image.toJPEG(quality)`
* `quality` Integer (**required**) - Between 0 - 100.

View file

@ -5,16 +5,15 @@
The `session` module can be used to create new `Session` objects.
You can also access the `session` of existing pages by using the `session`
property of [`webContents`](web-contents.md) which is a property of
[`BrowserWindow`](browser-window.md).
property of [`WebContents`](web-contents.md), or from the `session` module.
```javascript
const {BrowserWindow} = require('electron');
const {session, BrowserWindow} = require('electron')
let win = new BrowserWindow({width: 800, height: 600});
win.loadURL('http://github.com');
let win = new BrowserWindow({width: 800, height: 600})
win.loadURL('http://github.com')
const ses = win.webContents.session;
const ses = win.webContents.session
```
## Methods
@ -78,91 +77,6 @@ session.defaultSession.on('will-download', (event, item, webContents) => {
The following methods are available on instances of `Session`:
#### `ses.cookies`
The `cookies` gives you ability to query and modify cookies. For example:
```javascript
// Query all cookies.
session.defaultSession.cookies.get({}, (error, cookies) => {
console.log(cookies);
});
// Query all cookies associated with a specific url.
session.defaultSession.cookies.get({url: 'http://www.github.com'}, (error, cookies) => {
console.log(cookies);
});
// Set a cookie with the given cookie data;
// may overwrite equivalent cookies if they exist.
const cookie = {url: 'http://www.github.com', name: 'dummy_name', value: 'dummy'};
session.defaultSession.cookies.set(cookie, (error) => {
if (error)
console.error(error);
});
```
#### `ses.cookies.get(filter, callback)`
* `filter` Object
* `url` String (optional) - Retrieves cookies which are associated with
`url`. Empty implies retrieving cookies of all urls.
* `name` String (optional) - Filters cookies by name.
* `domain` String (optional) - Retrieves cookies whose domains match or are
subdomains of `domains`
* `path` String (optional) - Retrieves cookies whose path matches `path`.
* `secure` Boolean (optional) - Filters cookies by their Secure property.
* `session` Boolean (optional) - Filters out session or persistent cookies.
* `callback` Function
Sends a request to get all cookies matching `details`, `callback` will be called
with `callback(error, cookies)` on complete.
`cookies` is an Array of `cookie` objects.
* `cookie` Object
* `name` String - The name of the cookie.
* `value` String - The value of the cookie.
* `domain` String - The domain of the cookie.
* `hostOnly` String - Whether the cookie is a host-only cookie.
* `path` String - The path of the cookie.
* `secure` Boolean - Whether the cookie is marked as secure.
* `httpOnly` Boolean - Whether the cookie is marked as HTTP only.
* `session` Boolean - Whether the cookie is a session cookie or a persistent
cookie with an expiration date.
* `expirationDate` Double (optional) - The expiration date of the cookie as
the number of seconds since the UNIX epoch. Not provided for session
cookies.
#### `ses.cookies.set(details, callback)`
* `details` Object
* `url` String - The url to associate the cookie with.
* `name` String - The name of the cookie. Empty by default if omitted.
* `value` String - The value of the cookie. Empty by default if omitted.
* `domain` String - The domain of the cookie. Empty by default if omitted.
* `path` String - The path of the cookie. Empty by default if omitted.
* `secure` Boolean - Whether the cookie should be marked as Secure. Defaults to
false.
* `session` Boolean - Whether the cookie should be marked as HTTP only. Defaults
to false.
* `expirationDate` Double - The expiration date of the cookie as the number of
seconds since the UNIX epoch. If omitted then the cookie becomes a session
cookie and will not be retained between sessions.
* `callback` Function
Sets a cookie with `details`, `callback` will be called with `callback(error)`
on complete.
#### `ses.cookies.remove(url, name, callback)`
* `url` String - The URL associated with the cookie.
* `name` String - The name of cookie to remove.
* `callback` Function
Removes the cookies matching `url` and `name`, `callback` will called with
`callback()` on complete.
#### `ses.getCacheSize(callback)`
* `callback` Function
@ -341,15 +255,157 @@ session.defaultSession.allowNTLMCredentialsForDomains('*example.com, *foobar.com
session.defaultSession.allowNTLMCredentialsForDomains('*')
```
#### `ses.setUserAgent(userAgent[, acceptLanguages])`
* `userAgent` String
* `acceptLanguages` String (optional)
Overrides the `userAgent` and `acceptLanguages` for this session.
The `acceptLanguages` must a comma separated ordered list of language codes, for
example `"en-US,fr,de,ko,zh-CN,ja"`.
This doesn't affect existing `WebContents`, and each `WebContents` can use
`webContents.setUserAgent` to override the session-wide user agent.
#### `ses.getUserAgent()`
Returns a `String` representing the user agent for this session.
### Instance Properties
The following properties are available on instances of `Session`:
#### `ses.cookies`
Returns an instance of `Cookies` class for this session.
#### `ses.webRequest`
The `webRequest` API set allows to intercept and modify contents of a request at
various stages of its lifetime.
Returns an instance of `WebRequest` class for this session.
Each API accepts an optional `filter` and a `listener`, the `listener` will be
called with `listener(details)` when the API's event has happened, the `details`
is an object that describes the request. Passing `null` as `listener` will
unsubscribe from the event.
#### `ses.protocol`
Returns an instance of [protocol](protocol.md) module for this session.
```javascript
const {app, session} = require('electron')
const path = require('path')
app.on('ready', function () {
const protocol = session.fromPartition(partitionName).protocol
protocol.registerFileProtocol('atom', function (request, callback) {
var url = request.url.substr(7)
callback({path: path.normalize(__dirname + '/' + url)})
}, function (error) {
if (error)
console.error('Failed to register protocol')
})
})
```
## Class: Cookies
The `Cookies` class gives you ability to query and modify cookies. Instances of
`Cookies` class must be received by using `cookies` property of `Session` class.
For example:
```javascript
// Query all cookies.
session.defaultSession.cookies.get({}, (error, cookies) => {
console.log(cookies)
})
// Query all cookies associated with a specific url.
session.defaultSession.cookies.get({url: 'http://www.github.com'}, (error, cookies) => {
console.log(cookies)
})
// Set a cookie with the given cookie data;
// may overwrite equivalent cookies if they exist.
const cookie = {url: 'http://www.github.com', name: 'dummy_name', value: 'dummy'}
session.defaultSession.cookies.set(cookie, (error) => {
if (error)
console.error(error)
})
```
### Instance Methods
The following methods are available on instances of `Cookies`:
#### `cookies.get(filter, callback)`
* `filter` Object
* `url` String (optional) - Retrieves cookies which are associated with
`url`. Empty implies retrieving cookies of all urls.
* `name` String (optional) - Filters cookies by name.
* `domain` String (optional) - Retrieves cookies whose domains match or are
subdomains of `domains`
* `path` String (optional) - Retrieves cookies whose path matches `path`.
* `secure` Boolean (optional) - Filters cookies by their Secure property.
* `session` Boolean (optional) - Filters out session or persistent cookies.
* `callback` Function
Sends a request to get all cookies matching `details`, `callback` will be called
with `callback(error, cookies)` on complete.
`cookies` is an Array of `cookie` objects.
* `cookie` Object
* `name` String - The name of the cookie.
* `value` String - The value of the cookie.
* `domain` String - The domain of the cookie.
* `hostOnly` String - Whether the cookie is a host-only cookie.
* `path` String - The path of the cookie.
* `secure` Boolean - Whether the cookie is marked as secure.
* `httpOnly` Boolean - Whether the cookie is marked as HTTP only.
* `session` Boolean - Whether the cookie is a session cookie or a persistent
cookie with an expiration date.
* `expirationDate` Double (optional) - The expiration date of the cookie as
the number of seconds since the UNIX epoch. Not provided for session
cookies.
#### `cookies.set(details, callback)`
* `details` Object
* `url` String - The url to associate the cookie with.
* `name` String - The name of the cookie. Empty by default if omitted.
* `value` String - The value of the cookie. Empty by default if omitted.
* `domain` String - The domain of the cookie. Empty by default if omitted.
* `path` String - The path of the cookie. Empty by default if omitted.
* `secure` Boolean - Whether the cookie should be marked as Secure. Defaults to
false.
* `httpOnly` Boolean - Whether the cookie should be marked as HTTP only.
Defaults to false.
* `expirationDate` Double - The expiration date of the cookie as the number of
seconds since the UNIX epoch. If omitted then the cookie becomes a session
cookie and will not be retained between sessions.
* `callback` Function
Sets a cookie with `details`, `callback` will be called with `callback(error)`
on complete.
#### `cookies.remove(url, name, callback)`
* `url` String - The URL associated with the cookie.
* `name` String - The name of cookie to remove.
* `callback` Function
Removes the cookies matching `url` and `name`, `callback` will called with
`callback()` on complete.
## Class: WebRequest
The `WebRequest` class allows to intercept and modify contents of a request at
various stages of its lifetime. Instances of `WebRequest` class must be received
by using `webRequest` property of `Session` class.
The methods of `WebRequest` accept an optional `filter` and a `listener`, the
`listener` will be called with `listener(details)` when the API's event has
happened, the `details` is an object that describes the request. Passing `null`
as `listener` will unsubscribe from the event.
The `filter` is an object that has an `urls` property, which is an Array of URL
patterns that will be used to filter out the requests that do not match the URL
@ -358,19 +414,25 @@ patterns. If the `filter` is omitted then all requests will be matched.
For certain events the `listener` is passed with a `callback`, which should be
called with an `response` object when `listener` has done its work.
An example of adding `User-Agent` header for requests:
```javascript
// Modify the user agent for all requests to the following urls.
const filter = {
urls: ['https://*.github.com/*', '*://electron.github.io']
};
}
session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => {
details.requestHeaders['User-Agent'] = "MyAgent";
callback({cancel: false, requestHeaders: details.requestHeaders});
});
details.requestHeaders['User-Agent'] = "MyAgent"
callback({cancel: false, requestHeaders: details.requestHeaders})
})
```
#### `ses.webRequest.onBeforeRequest([filter, ]listener)`
### Instance Methods
The following methods are available on instances of `WebRequest`:
#### `webRequest.onBeforeRequest([filter, ]listener)`
* `filter` Object
* `listener` Function
@ -400,7 +462,7 @@ The `callback` has to be called with an `response` object:
* `redirectURL` String (optional) - The original request is prevented from
being sent or completed, and is instead redirected to the given URL.
#### `ses.webRequest.onBeforeSendHeaders([filter, ]listener)`
#### `webRequest.onBeforeSendHeaders([filter, ]listener)`
* `filter` Object
* `listener` Function
@ -425,7 +487,7 @@ The `callback` has to be called with an `response` object:
* `requestHeaders` Object (optional) - When provided, request will be made
with these headers.
#### `ses.webRequest.onSendHeaders([filter, ]listener)`
#### `webRequest.onSendHeaders([filter, ]listener)`
* `filter` Object
* `listener` Function
@ -442,7 +504,7 @@ response are visible by the time this listener is fired.
* `timestamp` Double
* `requestHeaders` Object
#### `ses.webRequest.onHeadersReceived([filter,]listener)`
#### `webRequest.onHeadersReceived([filter,]listener)`
* `filter` Object
* `listener` Function
@ -471,7 +533,7 @@ The `callback` has to be called with an `response` object:
`responseHeaders` to change header status otherwise original response
header's status will be used.
#### `ses.webRequest.onResponseStarted([filter, ]listener)`
#### `webRequest.onResponseStarted([filter, ]listener)`
* `filter` Object
* `listener` Function
@ -492,7 +554,7 @@ and response headers are available.
* `statusCode` Integer
* `statusLine` String
#### `ses.webRequest.onBeforeRedirect([filter, ]listener)`
#### `webRequest.onBeforeRedirect([filter, ]listener)`
* `filter` Object
* `listener` Function
@ -513,7 +575,7 @@ redirect is about to occur.
* `fromCache` Boolean
* `responseHeaders` Object
#### `ses.webRequest.onCompleted([filter, ]listener)`
#### `webRequest.onCompleted([filter, ]listener)`
* `filter` Object
* `listener` Function
@ -532,7 +594,7 @@ completed.
* `statusCode` Integer
* `statusLine` String
#### `ses.webRequest.onErrorOccurred([filter, ]listener)`
#### `webRequest.onErrorOccurred([filter, ]listener)`
* `filter` Object
* `listener` Function
@ -547,22 +609,3 @@ The `listener` will be called with `listener(details)` when an error occurs.
* `timestamp` Double
* `fromCache` Boolean
* `error` String - The error description.
#### `ses.protocol`
Returns an instance of [protocol](protocol.md) module for this session.
```javascript
const {app, session} = require('electron')
const path = require('path')
app.on('ready', function () {
const protocol = session.fromPartition(partitionName).protocol
protocol.registerFileProtocol('atom', function (request, callback) {
var url = request.url.substr(7)
callback({path: path.normalize(__dirname + '/' + url)})
}, function (error) {
if (error)
console.error('Failed to register protocol')
})
})

View file

@ -40,6 +40,17 @@ example values of `event` are:
Removes the subscriber with `id`.
### `systemPreferences.subscribeLocalNotification(event, callback)` _macOS_
Same as `subscribeNotification`, but uses `NSNotificationCenter` for local defaults.
This is necessary for events such as:
* `NSUserDefaultsDidChangeNotification`
### `systemPreferences.unsubscribeLocalNotification(id)` _macOS_
Same as `unsubscribeNotification`, but removes the subscriber from `NSNotificationCenter`.
### `systemPreferences.getUserDefault(key, type)` _macOS_
* `key` String

View file

@ -3,20 +3,20 @@
> Add icons and context menus to the system's notification area.
```javascript
const {app, Menu, Tray} = require('electron');
const {app, Menu, Tray} = require('electron')
let appIcon = null;
let tray = null
app.on('ready', () => {
appIcon = new Tray('/path/to/my/icon');
tray = new Tray('/path/to/my/icon')
const contextMenu = Menu.buildFromTemplate([
{label: 'Item1', type: 'radio'},
{label: 'Item2', type: 'radio'},
{label: 'Item3', type: 'radio', checked: true},
{label: 'Item4', type: 'radio'}
]);
appIcon.setToolTip('This is my application.');
appIcon.setContextMenu(contextMenu);
});
tray.setToolTip('This is my application.')
tray.setContextMenu(contextMenu)
})
```
__Platform limitations:__
@ -49,21 +49,18 @@ rely on the `click` event and always attach a context menu to the tray icon.
Creates a new tray icon associated with the `image`.
## Events
### Instance Events
The `Tray` module emits the following events:
**Note:** Some events are only available on specific operating systems and are
labeled as such.
### Event: 'click'
#### Event: 'click'
* `event` Event
* `altKey` Boolean
* `shiftKey` Boolean
* `ctrlKey` Boolean
* `metaKey` Boolean
* `bounds` Object - the bounds of tray icon.
* `bounds` Object _macOS_ _Windows_ - the bounds of tray icon.
* `x` Integer
* `y` Integer
* `width` Integer
@ -71,9 +68,7 @@ labeled as such.
Emitted when the tray icon is clicked.
**Note:** The `bounds` payload is only implemented on macOS and Windows.
### Event: 'right-click' _macOS_ _Windows_
#### Event: 'right-click' _macOS_ _Windows_
* `event` Event
* `altKey` Boolean
@ -88,7 +83,7 @@ Emitted when the tray icon is clicked.
Emitted when the tray icon is right clicked.
### Event: 'double-click' _macOS_ _Windows_
#### Event: 'double-click' _macOS_ _Windows_
* `event` Event
* `altKey` Boolean
@ -103,85 +98,82 @@ Emitted when the tray icon is right clicked.
Emitted when the tray icon is double clicked.
### Event: 'balloon-show' _Windows_
#### Event: 'balloon-show' _Windows_
Emitted when the tray balloon shows.
### Event: 'balloon-click' _Windows_
#### Event: 'balloon-click' _Windows_
Emitted when the tray balloon is clicked.
### Event: 'balloon-closed' _Windows_
#### Event: 'balloon-closed' _Windows_
Emitted when the tray balloon is closed because of timeout or user manually
closes it.
### Event: 'drop' _macOS_
#### Event: 'drop' _macOS_
Emitted when any dragged items are dropped on the tray icon.
### Event: 'drop-files' _macOS_
#### Event: 'drop-files' _macOS_
* `event`
* `event` Event
* `files` Array - the file path of dropped files.
Emitted when dragged files are dropped in the tray icon.
### Event: 'drag-enter' _macOS_
#### Event: 'drag-enter' _macOS_
Emitted when a drag operation enters the tray icon.
### Event: 'drag-leave' _macOS_
#### Event: 'drag-leave' _macOS_
Emitted when a drag operation exits the tray icon.
### Event: 'drag-end' _macOS_
#### Event: 'drag-end' _macOS_
Emitted when a drag operation ends on the tray or ends at another location.
## Methods
### Instance Methods
The `Tray` module has the following methods:
The `Tray` class has the following methods:
**Note:** Some methods are only available on specific operating systems and are
labeled as such.
### `Tray.destroy()`
#### `tray.destroy()`
Destroys the tray icon immediately.
### `Tray.setImage(image)`
#### `tray.setImage(image)`
* `image` [NativeImage](native-image.md)
Sets the `image` associated with this tray icon.
### `Tray.setPressedImage(image)` _macOS_
#### `tray.setPressedImage(image)` _macOS_
* `image` [NativeImage](native-image.md)
Sets the `image` associated with this tray icon when pressed on macOS.
### `Tray.setToolTip(toolTip)`
#### `tray.setToolTip(toolTip)`
* `toolTip` String
Sets the hover text for this tray icon.
### `Tray.setTitle(title)` _macOS_
#### `tray.setTitle(title)` _macOS_
* `title` String
Sets the title displayed aside of the tray icon in the status bar.
### `Tray.setHighlightMode(highlight)` _macOS_
#### `tray.setHighlightMode(highlight)` _macOS_
* `highlight` Boolean
Sets whether the tray icon's background becomes highlighted (in blue)
when the tray icon is clicked. Defaults to true.
### `Tray.displayBalloon(options)` _Windows_
#### `tray.displayBalloon(options)` _Windows_
* `options` Object
* `icon` [NativeImage](native-image.md)
@ -190,7 +182,7 @@ when the tray icon is clicked. Defaults to true.
Displays a tray balloon.
### `Tray.popUpContextMenu([menu, position])` _macOS_ _Windows_
#### `tray.popUpContextMenu([menu, position])` _macOS_ _Windows_
* `menu` Menu (optional)
* `position` Object (optional) - The pop up position.
@ -202,10 +194,20 @@ be shown instead of the tray icon's context menu.
The `position` is only available on Windows, and it is (0, 0) by default.
### `Tray.setContextMenu(menu)`
#### `tray.setContextMenu(menu)`
* `menu` Menu
Sets the context menu for this icon.
#### `tray.getBounds()` _macOS_ _Windows_
Returns the `bounds` of this tray icon as `Object`.
* `bounds` Object
* `x` Integer
* `y` Integer
* `width` Integer
* `height` Integer
[event-emitter]: http://nodejs.org/api/events.html#events_class_events_eventemitter

View file

@ -339,9 +339,9 @@ Returns:
was invoked on. Elements with source URLs are images, audio and video.
* `mediaType` String - Type of the node the context menu was invoked on. Can
be `none`, `image`, `audio`, `video`, `canvas`, `file` or `plugin`.
* `hasImageContent` Boolean - Wether the context menu was invoked on an image
* `hasImageContent` Boolean - Whether the context menu was invoked on an image
which has non-empty contents.
* `isEditable` Boolean - Wether the context is editable.
* `isEditable` Boolean - Whether the context is editable.
* `selectionText` String - Text of the selection that the context menu was
invoked on.
* `titleText` String - Title or alt text of the selection that the context
@ -356,29 +356,31 @@ Returns:
Can be `none`, `mouse`, `keyboard`, `touch`, `touchMenu`.
* `mediaFlags` Object - The flags for the media element the context menu was
invoked on. See more about this below.
* `editFlags` Object - These flags indicate wether the renderer believes it is
* `editFlags` Object - These flags indicate whether the renderer believes it is
able to perform the corresponding action. See more about this below.
The `mediaFlags` is an object with the following properties:
* `inError` Boolean - Wether the media element has crashed.
* `isPaused` Boolean - Wether the media element is paused.
* `isMuted` Boolean - Wether the media element is muted.
* `hasAudio` Boolean - Wether the media element has audio.
* `isLooping` Boolean - Wether the media element is looping.
* `isControlsVisible` Boolean - Wether the media element's controls are
visible.
* `canToggleControls` Boolean - Wether the media element's controls are
toggleable.
* `canRotate` Boolean - Wether the media element can be rotated.
* `inError` Boolean - Whether the media element has crashed.
* `isPaused` Boolean - Whether the media element is paused.
* `isMuted` Boolean - Whether the media element is muted.
* `hasAudio` Boolean - Whether the media element has audio.
* `isLooping` Boolean - Whether the media element is looping.
* `isControlsVisible` Boolean - Whether the media element's controls are
visible.
* `canToggleControls` Boolean - Whether the media element's controls are
toggleable.
* `canRotate` Boolean - Whether the media element can be rotated.
The `editFlags` is an object with the following properties:
* `canUndo` Boolean - Wether the renderer believes it can undo.
* `canRedo` Boolean - Wether the renderer believes it can redo.
* `canCut` Boolean - Wether the renderer believes it can cut.
* `canCopy` Boolean - Wether the renderer believes it can copy
* `canPaste` Boolean - Wether the renderer believes it can paste.
* `canDelete` Boolean - Wether the renderer believes it can delete.
* `canSelectAll` Boolean - Wether the renderer believes it can select all.
* `canUndo` Boolean - Whether the renderer believes it can undo.
* `canRedo` Boolean - Whether the renderer believes it can redo.
* `canCut` Boolean - Whether the renderer believes it can cut.
* `canCopy` Boolean - Whether the renderer believes it can copy
* `canPaste` Boolean - Whether the renderer believes it can paste.
* `canDelete` Boolean - Whether the renderer believes it can delete.
* `canSelectAll` Boolean - Whether the renderer believes it can select all.
Emitted when there is a new context menu that needs to be handled.
@ -919,7 +921,7 @@ For the `mouseWheel` event, the `event` object also have following properties:
### `webContents.beginFrameSubscription([onlyDirty ,]callback)`
* `onlyDirty` Boolean
* `onlyDirty` Boolean (optional) - Defaults to `false`
* `callback` Function
Begin subscribing for presentation events and captured frames, the `callback`
@ -941,6 +943,16 @@ defaults to `false`.
End subscribing for frame presentation events.
### `webContents.startDrag(item)`
* `item` object
* `file` String
* `icon` [NativeImage](native-image.md)
Sets the `item` as dragging item for current drag-drop operation, `file` is the
absolute path of the file to be dragged, and `icon` is the image showing under
the cursor when dragging.
### `webContents.savePage(fullPath, saveType, callback)`
* `fullPath` String - The full file path.

Some files were not shown because too many files have changed in this diff Show more