mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
211 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40066ca343 | ||
|
|
6671e78f5d | ||
|
|
0480e32f99 | ||
|
|
ead94b7b1f | ||
|
|
288ef13fb5 | ||
|
|
4765445b4f | ||
|
|
03ec5ced05 | ||
|
|
e2e18200fb | ||
|
|
328583575d | ||
|
|
704b8335aa | ||
|
|
d25d1f3f8b | ||
|
|
abd466ee4a | ||
|
|
fcc1f4d7ed | ||
|
|
c1267b2320 | ||
|
|
ee61ab2d26 | ||
|
|
0ec7f35c24 | ||
|
|
377a8eefb2 | ||
|
|
1ee4caae2d | ||
|
|
ebf509bbe4 | ||
|
|
4c45c80fb4 | ||
|
|
b40a0e6e0c | ||
|
|
51f60d8d73 | ||
|
|
0b8c2545b9 | ||
|
|
5efb88e7ea | ||
|
|
937668097a | ||
|
|
da0a1eac24 | ||
|
|
c3b058cea3 | ||
|
|
2e9fd7ce77 | ||
|
|
4c9f5b71f7 | ||
|
|
418efbe660 | ||
|
|
006c77a00f | ||
|
|
f109591d03 | ||
|
|
c47ad29124 | ||
|
|
6e3cb9e8eb | ||
|
|
70aa9b06ee | ||
|
|
c8a2246952 | ||
|
|
d35996b4a0 | ||
|
|
a9c40de393 | ||
|
|
549cccfce4 | ||
|
|
1da75f5c18 | ||
|
|
68c413c391 | ||
|
|
83111ad84c | ||
|
|
89328c873c | ||
|
|
0c92d44077 | ||
|
|
6f221cb6b1 | ||
|
|
11f64b714d | ||
|
|
4c23e3950a | ||
|
|
44376374b0 | ||
|
|
022c2c0d8c | ||
|
|
0dba0b9cad | ||
|
|
97930fcd84 | ||
|
|
9c88a5c1ab | ||
|
|
7692edf50e | ||
|
|
8215d661ca | ||
|
|
8f820e09be | ||
|
|
145d5abe80 | ||
|
|
b90c0c7895 | ||
|
|
dda7740399 | ||
|
|
3f4455a79d | ||
|
|
f47851f1e7 | ||
|
|
eb064240f8 | ||
|
|
7b881ebc23 | ||
|
|
2bfc7aa152 | ||
|
|
eae5cc9d2c | ||
|
|
03434f45bb | ||
|
|
4ded709307 | ||
|
|
4b6639c9fd | ||
|
|
4b65610d40 | ||
|
|
755c1f5238 | ||
|
|
04c8bc38b2 | ||
|
|
ad3f4a26fd | ||
|
|
7de37859f0 | ||
|
|
993b878925 | ||
|
|
38acc7090b | ||
|
|
4ec79d5d18 | ||
|
|
1c68aae43e | ||
|
|
686af28f54 | ||
|
|
6725523042 | ||
|
|
aa8dbbf6b6 | ||
|
|
0e2ac2d802 | ||
|
|
68b453770b | ||
|
|
2a0be28111 | ||
|
|
f9f20957a4 | ||
|
|
d93ccd47a8 | ||
|
|
e152b8850c | ||
|
|
5bb2c2c5c9 | ||
|
|
816b10d8f3 | ||
|
|
b7a40f3097 | ||
|
|
2515425cd5 | ||
|
|
a0c39c64cc | ||
|
|
114801d412 | ||
|
|
2be368bded | ||
|
|
f5d79677fa | ||
|
|
5f95fea3e2 | ||
|
|
c0b87c1a62 | ||
|
|
054c55a9bb | ||
|
|
23b92ef9ec | ||
|
|
d5f5cdb45a | ||
|
|
33978455b8 | ||
|
|
2bd167663d | ||
|
|
bda5bb4a74 | ||
|
|
67edcc8f91 | ||
|
|
73f6162f5c | ||
|
|
fe9e026f9e | ||
|
|
3230927f10 | ||
|
|
f460d81dd0 | ||
|
|
610a503188 | ||
|
|
a9e22801e9 | ||
|
|
ee1f69062e | ||
|
|
20e9a87158 | ||
|
|
a4e04e6083 | ||
|
|
63294892f0 | ||
|
|
be67dca686 | ||
|
|
b1eefbdcd9 | ||
|
|
fed77d1837 | ||
|
|
b46fc8bc4c | ||
|
|
b4c48664f8 | ||
|
|
b6958e5221 | ||
|
|
f02affbc18 | ||
|
|
46c6233b62 | ||
|
|
d6144d63fb | ||
|
|
c4049cb393 | ||
|
|
eaac67ac60 | ||
|
|
9c7bb0b370 | ||
|
|
24ae9b0ea9 | ||
|
|
2d11b1d9eb | ||
|
|
e3dde12c45 | ||
|
|
681a772f5f | ||
|
|
5839d7dcd5 | ||
|
|
a06392459e | ||
|
|
fd11b7e7db | ||
|
|
bb42c85df8 | ||
|
|
bb0ac688b2 | ||
|
|
7de97a55f7 | ||
|
|
b25c8ca621 | ||
|
|
db46e9c203 | ||
|
|
ebfc127628 | ||
|
|
070772b4b9 | ||
|
|
d9ad51e989 | ||
|
|
fce641aab6 | ||
|
|
a21e095a59 | ||
|
|
a67b29d8d2 | ||
|
|
795ac86266 | ||
|
|
8a744255fa | ||
|
|
a3b8e81c21 | ||
|
|
4bfa03e5f4 | ||
|
|
3f0d598a59 | ||
|
|
1235907835 | ||
|
|
9a0372b61b | ||
|
|
6f45678e9c | ||
|
|
0ea80f674b | ||
|
|
316e6850ae | ||
|
|
8386baf267 | ||
|
|
a734326907 | ||
|
|
2b547bd44a | ||
|
|
a1a17b7ee8 | ||
|
|
d00490271b | ||
|
|
fee56df400 | ||
|
|
d2b48b2aa7 | ||
|
|
467870deb6 | ||
|
|
6fcc197db8 | ||
|
|
f3c7965cea | ||
|
|
8ff30a2abc | ||
|
|
bb1e4c2208 | ||
|
|
820c72af55 | ||
|
|
a63193c826 | ||
|
|
3a3a95b0a9 | ||
|
|
367d12402a | ||
|
|
49f995925c | ||
|
|
bdfc19ad20 | ||
|
|
1b3b35926a | ||
|
|
23268531ae | ||
|
|
f47ae3c02f | ||
|
|
9c6ab6f1e0 | ||
|
|
331bc42d57 | ||
|
|
39bb670719 | ||
|
|
537ead8917 | ||
|
|
96b2705bd3 | ||
|
|
6753fcc1b4 | ||
|
|
593a79ce20 | ||
|
|
d4c954870a | ||
|
|
59d6e7d6ef | ||
|
|
2b04af4349 | ||
|
|
fe7462b352 | ||
|
|
c65cfadd09 | ||
|
|
34658473c9 | ||
|
|
f610e332b3 | ||
|
|
67324ce732 | ||
|
|
9e1da8f097 | ||
|
|
361b9cad0f | ||
|
|
f63532fa95 | ||
|
|
4a47deafc2 | ||
|
|
cad26fa606 | ||
|
|
078c7bf8ab | ||
|
|
a05e98f463 | ||
|
|
f64dc5f57d | ||
|
|
1db72f8010 | ||
|
|
060d06d396 | ||
|
|
a737e15ddb | ||
|
|
e45e246027 | ||
|
|
45739ce434 | ||
|
|
777ff450cf | ||
|
|
85800256de | ||
|
|
632c18ab37 | ||
|
|
2a6fcf48e5 | ||
|
|
0d77fd4a2c | ||
|
|
2610aa60e9 | ||
|
|
7bf17f2541 | ||
|
|
157a290e38 | ||
|
|
664f95a7b4 | ||
|
|
a8ae14e94f |
@@ -71,8 +71,9 @@ API 레퍼런스가 있습니다. Electron을 빌드 하는 방법과 프로젝
|
||||
- Atom 포럼의 [`electron`](http://discuss.atom.io/c/electron) 카테고리
|
||||
- Freenode 채팅의 `#atom-shell` 채널
|
||||
- Slack의 [`Atom`](http://atom-slack.herokuapp.com/) 채널
|
||||
- [`electron-br`](https://electron-br.slack.com) *(브라질 포르투갈어)* 커뮤니티
|
||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(한국어)* 커뮤니티
|
||||
- [`electron-br`](https://electron-br.slack.com) *(브라질)* 커뮤니티
|
||||
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(한국)* 커뮤니티
|
||||
- [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(일본)* 커뮤니티
|
||||
|
||||
[awesome-electron](https://github.com/sindresorhus/awesome-electron) 프로젝트에
|
||||
커뮤니티가 운영중인 유용한 예제 어플리케이션과 도구, 리소스가 있으니 한번 참고해 보시기
|
||||
|
||||
8
atom.gyp
8
atom.gyp
@@ -4,7 +4,7 @@
|
||||
'product_name%': 'Electron',
|
||||
'company_name%': 'GitHub, Inc',
|
||||
'company_abbr%': 'github',
|
||||
'version%': '0.36.8',
|
||||
'version%': '0.36.12',
|
||||
},
|
||||
'includes': [
|
||||
'filenames.gypi',
|
||||
@@ -69,7 +69,7 @@
|
||||
{
|
||||
'destination': '<(PRODUCT_DIR)/<(product_name).app/Contents/Resources',
|
||||
'files': [
|
||||
'atom/browser/default_app',
|
||||
'default_app',
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -171,7 +171,7 @@
|
||||
{
|
||||
'destination': '<(PRODUCT_DIR)/resources',
|
||||
'files': [
|
||||
'atom/browser/default_app',
|
||||
'default_app',
|
||||
]
|
||||
},
|
||||
],
|
||||
@@ -212,7 +212,7 @@
|
||||
{
|
||||
'destination': '<(PRODUCT_DIR)/resources',
|
||||
'files': [
|
||||
'atom/browser/default_app',
|
||||
'default_app',
|
||||
]
|
||||
},
|
||||
],
|
||||
|
||||
@@ -132,19 +132,20 @@ void OnClientCertificateSelected(
|
||||
std::shared_ptr<content::ClientCertificateDelegate> delegate,
|
||||
mate::Arguments* args) {
|
||||
mate::Dictionary cert_data;
|
||||
if (!(args->Length() == 1 && args->GetNext(&cert_data))) {
|
||||
if (!args->GetNext(&cert_data)) {
|
||||
args->ThrowError();
|
||||
return;
|
||||
}
|
||||
|
||||
std::string encoded_data;
|
||||
cert_data.Get("data", &encoded_data);
|
||||
v8::Local<v8::Object> data;
|
||||
if (!cert_data.Get("data", &data))
|
||||
return;
|
||||
|
||||
auto certs =
|
||||
net::X509Certificate::CreateCertificateListFromBytes(
|
||||
encoded_data.data(), encoded_data.size(),
|
||||
net::X509Certificate::FORMAT_AUTO);
|
||||
delegate->ContinueWithCertificate(certs[0].get());
|
||||
auto certs = net::X509Certificate::CreateCertificateListFromBytes(
|
||||
node::Buffer::Data(data), node::Buffer::Length(data),
|
||||
net::X509Certificate::FORMAT_AUTO);
|
||||
if (certs.size() > 0)
|
||||
delegate->ContinueWithCertificate(certs[0].get());
|
||||
}
|
||||
|
||||
void PassLoginInformation(scoped_refptr<LoginHandler> login_handler,
|
||||
@@ -282,6 +283,12 @@ void App::OnGpuProcessCrashed(base::TerminationStatus exit_code) {
|
||||
Emit("gpu-process-crashed");
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
void App::OnPlatformThemeChanged() {
|
||||
Emit("platform-theme-changed");
|
||||
}
|
||||
#endif
|
||||
|
||||
base::FilePath App::GetPath(mate::Arguments* args, const std::string& name) {
|
||||
bool succeed = false;
|
||||
base::FilePath path;
|
||||
@@ -370,6 +377,8 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
|
||||
#if defined(OS_MACOSX)
|
||||
.SetMethod("hide", base::Bind(&Browser::Hide, browser))
|
||||
.SetMethod("show", base::Bind(&Browser::Show, browser))
|
||||
.SetMethod("isDarkMode",
|
||||
base::Bind(&Browser::IsDarkMode, browser))
|
||||
#endif
|
||||
#if defined(OS_WIN)
|
||||
.SetMethod("setUserTasks",
|
||||
|
||||
@@ -71,6 +71,10 @@ class App : public AtomBrowserClient::Delegate,
|
||||
// content::GpuDataManagerObserver:
|
||||
void OnGpuProcessCrashed(base::TerminationStatus exit_code) override;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
void OnPlatformThemeChanged() override;
|
||||
#endif
|
||||
|
||||
// mate::Wrappable:
|
||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override;
|
||||
|
||||
@@ -218,7 +218,8 @@ WebContents::WebContents(content::WebContents* web_contents)
|
||||
|
||||
WebContents::WebContents(v8::Isolate* isolate,
|
||||
const mate::Dictionary& options)
|
||||
: request_id_(0) {
|
||||
: embedder_(nullptr),
|
||||
request_id_(0) {
|
||||
// Whether it is a guest WebContents.
|
||||
bool is_guest = false;
|
||||
options.Get("isGuest", &is_guest);
|
||||
@@ -273,10 +274,10 @@ WebContents::WebContents(v8::Isolate* isolate,
|
||||
guest_delegate_->Initialize(this);
|
||||
|
||||
NativeWindow* owner_window = nullptr;
|
||||
WebContents* embedder = nullptr;
|
||||
if (options.Get("embedder", &embedder) && embedder) {
|
||||
if (options.Get("embedder", &embedder_) && embedder_) {
|
||||
// New WebContents's owner_window is the embedder's owner_window.
|
||||
auto relay = NativeWindowRelay::FromWebContents(embedder->web_contents());
|
||||
auto relay =
|
||||
NativeWindowRelay::FromWebContents(embedder_->web_contents());
|
||||
if (relay)
|
||||
owner_window = relay->window.get();
|
||||
}
|
||||
@@ -296,6 +297,7 @@ WebContents::~WebContents() {
|
||||
// The WebContentsDestroyed will not be called automatically because we
|
||||
// unsubscribe from webContents before destroying it. So we have to manually
|
||||
// call it here to make sure "destroyed" event is emitted.
|
||||
RenderViewDeleted(web_contents()->GetRenderViewHost());
|
||||
WebContentsDestroyed();
|
||||
}
|
||||
}
|
||||
@@ -461,6 +463,13 @@ void WebContents::FindReply(content::WebContents* web_contents,
|
||||
}
|
||||
}
|
||||
|
||||
bool WebContents::CheckMediaAccessPermission(
|
||||
content::WebContents* web_contents,
|
||||
const GURL& security_origin,
|
||||
content::MediaStreamType type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebContents::RequestMediaAccessPermission(
|
||||
content::WebContents* web_contents,
|
||||
const content::MediaStreamRequest& request,
|
||||
@@ -485,17 +494,7 @@ void WebContents::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
|
||||
}
|
||||
|
||||
void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
|
||||
int process_id = render_view_host->GetProcess()->GetID();
|
||||
Emit("render-view-deleted", process_id);
|
||||
|
||||
// process.emit('ATOM_BROWSER_RELEASE_RENDER_VIEW', processId);
|
||||
// Tell the rpc server that a render view has been deleted and we need to
|
||||
// release all objects owned by it.
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
node::Environment* env = node::Environment::GetCurrent(isolate());
|
||||
mate::EmitEvent(isolate(), env->process_object(),
|
||||
"ATOM_BROWSER_RELEASE_RENDER_VIEW", process_id);
|
||||
Emit("render-view-deleted", render_view_host->GetProcess()->GetID());
|
||||
}
|
||||
|
||||
void WebContents::RenderProcessGone(base::TerminationStatus status) {
|
||||
@@ -675,9 +674,6 @@ bool WebContents::OnMessageReceived(const IPC::Message& message) {
|
||||
// be destroyed on close, and WebContentsDestroyed would be called for it, so
|
||||
// we need to make sure the api::WebContents is also deleted.
|
||||
void WebContents::WebContentsDestroyed() {
|
||||
// The RenderViewDeleted was not called when the WebContents is destroyed.
|
||||
RenderViewDeleted(web_contents()->GetRenderViewHost());
|
||||
|
||||
// This event is only for internal use, which is emitted when WebContents is
|
||||
// being destroyed.
|
||||
Emit("will-destroy");
|
||||
@@ -1073,7 +1069,7 @@ void WebContents::BeginFrameSubscription(
|
||||
const auto view = web_contents()->GetRenderWidgetHostView();
|
||||
if (view) {
|
||||
scoped_ptr<FrameSubscriber> frame_subscriber(new FrameSubscriber(
|
||||
isolate(), view->GetVisibleViewportSize(), callback));
|
||||
isolate(), view, callback));
|
||||
view->BeginFrameSubscription(frame_subscriber.Pass());
|
||||
}
|
||||
}
|
||||
@@ -1128,6 +1124,12 @@ v8::Local<v8::Value> WebContents::Session(v8::Isolate* isolate) {
|
||||
return v8::Local<v8::Value>::New(isolate, session_);
|
||||
}
|
||||
|
||||
content::WebContents* WebContents::HostWebContents() {
|
||||
if (!embedder_)
|
||||
return nullptr;
|
||||
return embedder_->web_contents();
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebContents::DevToolsWebContents(v8::Isolate* isolate) {
|
||||
if (devtools_web_contents_.IsEmpty())
|
||||
return v8::Null(isolate);
|
||||
@@ -1211,6 +1213,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("addWorkSpace", &WebContents::AddWorkSpace)
|
||||
.SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace)
|
||||
.SetProperty("session", &WebContents::Session)
|
||||
.SetProperty("hostWebContents", &WebContents::HostWebContents)
|
||||
.SetProperty("devToolsWebContents", &WebContents::DevToolsWebContents)
|
||||
.SetProperty("debugger", &WebContents::Debugger);
|
||||
}
|
||||
|
||||
@@ -147,6 +147,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
|
||||
// Properties.
|
||||
v8::Local<v8::Value> Session(v8::Isolate* isolate);
|
||||
content::WebContents* HostWebContents();
|
||||
v8::Local<v8::Value> DevToolsWebContents(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> Debugger(v8::Isolate* isolate);
|
||||
|
||||
@@ -201,6 +202,10 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
const gfx::Rect& selection_rect,
|
||||
int active_match_ordinal,
|
||||
bool final_update) override;
|
||||
bool CheckMediaAccessPermission(
|
||||
content::WebContents* web_contents,
|
||||
const GURL& security_origin,
|
||||
content::MediaStreamType type) override;
|
||||
void RequestMediaAccessPermission(
|
||||
content::WebContents* web_contents,
|
||||
const content::MediaStreamRequest& request,
|
||||
@@ -287,6 +292,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||
|
||||
scoped_ptr<WebViewGuestDelegate> guest_delegate_;
|
||||
|
||||
// The host webcontents that may contain this webcontents.
|
||||
WebContents* embedder_;
|
||||
|
||||
// The type of current WebContents.
|
||||
Type type_;
|
||||
|
||||
|
||||
@@ -191,6 +191,14 @@ void Window::OnWindowFocus() {
|
||||
Emit("focus");
|
||||
}
|
||||
|
||||
void Window::OnWindowShow() {
|
||||
Emit("show");
|
||||
}
|
||||
|
||||
void Window::OnWindowHide() {
|
||||
Emit("hide");
|
||||
}
|
||||
|
||||
void Window::OnWindowMaximize() {
|
||||
Emit("maximize");
|
||||
}
|
||||
@@ -294,6 +302,10 @@ void Window::Focus() {
|
||||
window_->Focus(true);
|
||||
}
|
||||
|
||||
void Window::Blur() {
|
||||
window_->Focus(false);
|
||||
}
|
||||
|
||||
bool Window::IsFocused() {
|
||||
return window_->IsFocused();
|
||||
}
|
||||
@@ -688,6 +700,7 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
.MakeDestroyable()
|
||||
.SetMethod("close", &Window::Close)
|
||||
.SetMethod("focus", &Window::Focus)
|
||||
.SetMethod("blur", &Window::Blur)
|
||||
.SetMethod("isFocused", &Window::IsFocused)
|
||||
.SetMethod("show", &Window::Show)
|
||||
.SetMethod("showInactive", &Window::ShowInactive)
|
||||
|
||||
@@ -58,6 +58,8 @@ class Window : public mate::TrackableObject<Window>,
|
||||
void OnWindowClosed() override;
|
||||
void OnWindowBlur() override;
|
||||
void OnWindowFocus() override;
|
||||
void OnWindowShow() override;
|
||||
void OnWindowHide() override;
|
||||
void OnWindowMaximize() override;
|
||||
void OnWindowUnmaximize() override;
|
||||
void OnWindowMinimize() override;
|
||||
@@ -83,6 +85,7 @@ class Window : public mate::TrackableObject<Window>,
|
||||
// APIs for NativeWindow.
|
||||
void Close();
|
||||
void Focus();
|
||||
void Blur();
|
||||
bool IsFocused();
|
||||
void Show();
|
||||
void ShowInactive();
|
||||
|
||||
@@ -4,19 +4,18 @@
|
||||
|
||||
#include "atom/browser/api/frame_subscriber.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/bind.h"
|
||||
#include "media/base/video_frame.h"
|
||||
#include "media/base/yuv_convert.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "content/public/browser/render_widget_host.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
FrameSubscriber::FrameSubscriber(v8::Isolate* isolate,
|
||||
const gfx::Size& size,
|
||||
content::RenderWidgetHostView* view,
|
||||
const FrameCaptureCallback& callback)
|
||||
: isolate_(isolate), size_(size), callback_(callback), weak_factory_(this) {
|
||||
: isolate_(isolate), view_(view), callback_(callback), weak_factory_(this) {
|
||||
}
|
||||
|
||||
bool FrameSubscriber::ShouldCaptureFrame(
|
||||
@@ -24,39 +23,39 @@ bool FrameSubscriber::ShouldCaptureFrame(
|
||||
base::TimeTicks present_time,
|
||||
scoped_refptr<media::VideoFrame>* storage,
|
||||
DeliverFrameCallback* callback) {
|
||||
*storage = media::VideoFrame::CreateFrame(
|
||||
media::PIXEL_FORMAT_YV12,
|
||||
size_, gfx::Rect(size_), size_, base::TimeDelta());
|
||||
*callback = base::Bind(&FrameSubscriber::OnFrameDelivered,
|
||||
weak_factory_.GetWeakPtr(), *storage);
|
||||
return true;
|
||||
const auto host = view_ ? view_->GetRenderWidgetHost() : nullptr;
|
||||
if (!view_ || !host)
|
||||
return false;
|
||||
|
||||
const auto size = view_->GetVisibleViewportSize();
|
||||
|
||||
host->CopyFromBackingStore(
|
||||
gfx::Rect(size),
|
||||
size,
|
||||
base::Bind(&FrameSubscriber::OnFrameDelivered,
|
||||
weak_factory_.GetWeakPtr(), callback_),
|
||||
kBGRA_8888_SkColorType);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void FrameSubscriber::OnFrameDelivered(
|
||||
scoped_refptr<media::VideoFrame> frame, base::TimeTicks, bool result) {
|
||||
if (!result)
|
||||
void FrameSubscriber::OnFrameDelivered(const FrameCaptureCallback& callback,
|
||||
const SkBitmap& bitmap, content::ReadbackResponse response) {
|
||||
if (bitmap.computeSize64() == 0)
|
||||
return;
|
||||
|
||||
v8::Locker locker(isolate_);
|
||||
v8::HandleScope handle_scope(isolate_);
|
||||
|
||||
gfx::Rect rect = frame->visible_rect();
|
||||
size_t rgb_arr_size = rect.width() * rect.height() * 4;
|
||||
size_t rgb_arr_size = bitmap.width() * bitmap.height() *
|
||||
bitmap.bytesPerPixel();
|
||||
v8::MaybeLocal<v8::Object> buffer = node::Buffer::New(isolate_, rgb_arr_size);
|
||||
if (buffer.IsEmpty())
|
||||
return;
|
||||
|
||||
// Convert a frame of YUV to 32 bit ARGB.
|
||||
media::ConvertYUVToRGB32(frame->data(media::VideoFrame::kYPlane),
|
||||
frame->data(media::VideoFrame::kUPlane),
|
||||
frame->data(media::VideoFrame::kVPlane),
|
||||
reinterpret_cast<uint8*>(
|
||||
node::Buffer::Data(buffer.ToLocalChecked())),
|
||||
rect.width(), rect.height(),
|
||||
frame->stride(media::VideoFrame::kYPlane),
|
||||
frame->stride(media::VideoFrame::kUVPlane),
|
||||
rect.width() * 4,
|
||||
media::YV12);
|
||||
bitmap.copyPixelsTo(
|
||||
reinterpret_cast<uint8*>(node::Buffer::Data(buffer.ToLocalChecked())),
|
||||
rgb_arr_size);
|
||||
|
||||
callback_.Run(buffer.ToLocalChecked());
|
||||
}
|
||||
|
||||
@@ -7,7 +7,10 @@
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "content/public/browser/render_widget_host_view.h"
|
||||
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
|
||||
#include "content/public/browser/readback_types.h"
|
||||
#include "third_party/skia/include/core/SkBitmap.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
@@ -20,7 +23,7 @@ class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber {
|
||||
using FrameCaptureCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
||||
|
||||
FrameSubscriber(v8::Isolate* isolate,
|
||||
const gfx::Size& size,
|
||||
content::RenderWidgetHostView* view,
|
||||
const FrameCaptureCallback& callback);
|
||||
|
||||
bool ShouldCaptureFrame(const gfx::Rect& damage_rect,
|
||||
@@ -29,11 +32,11 @@ class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber {
|
||||
DeliverFrameCallback* callback) override;
|
||||
|
||||
private:
|
||||
void OnFrameDelivered(
|
||||
scoped_refptr<media::VideoFrame> frame, base::TimeTicks, bool);
|
||||
void OnFrameDelivered(const FrameCaptureCallback& callback,
|
||||
const SkBitmap& bitmap, content::ReadbackResponse response);
|
||||
|
||||
v8::Isolate* isolate_;
|
||||
gfx::Size size_;
|
||||
content::RenderWidgetHostView* view_;
|
||||
FrameCaptureCallback callback_;
|
||||
|
||||
base::WeakPtrFactory<FrameSubscriber> weak_factory_;
|
||||
|
||||
@@ -31,7 +31,7 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
|
||||
|
||||
static AtomBrowserMainParts* Get();
|
||||
|
||||
// Sets the exit code, will fail if the the message loop is not ready.
|
||||
// Sets the exit code, will fail if the message loop is not ready.
|
||||
bool SetExitCode(int code);
|
||||
|
||||
// Gets the exit code
|
||||
|
||||
@@ -181,4 +181,8 @@ void Browser::OnWindowAllClosed() {
|
||||
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnWindowAllClosed());
|
||||
}
|
||||
|
||||
void Browser::PlatformThemeChanged() {
|
||||
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnPlatformThemeChanged());
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -83,6 +83,9 @@ class Browser : public WindowListObserver {
|
||||
// Show the application.
|
||||
void Show();
|
||||
|
||||
// Check if the system is in Dark Mode.
|
||||
bool IsDarkMode();
|
||||
|
||||
// Bounce the dock icon.
|
||||
enum BounceType {
|
||||
BOUNCE_CRITICAL = 0,
|
||||
@@ -142,6 +145,9 @@ class Browser : public WindowListObserver {
|
||||
// Request basic auth login.
|
||||
void RequestLogin(LoginHandler* login_handler);
|
||||
|
||||
// Tell the application that plaform's theme changed.
|
||||
void PlatformThemeChanged();
|
||||
|
||||
void AddObserver(BrowserObserver* obs) {
|
||||
observers_.AddObserver(obs);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,11 @@ void Browser::Show() {
|
||||
[[AtomApplication sharedApplication] unhide:nil];
|
||||
}
|
||||
|
||||
bool Browser::IsDarkMode() {
|
||||
NSString *mode = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
|
||||
return [mode isEqualToString: @"Dark"];
|
||||
}
|
||||
|
||||
void Browser::AddRecentDocument(const base::FilePath& path) {
|
||||
NSString* path_string = base::mac::FilePathToNSString(path);
|
||||
if (!path_string)
|
||||
|
||||
@@ -45,6 +45,8 @@ class BrowserObserver {
|
||||
// The browser requests HTTP login.
|
||||
virtual void OnLogin(LoginHandler* login_handler) {}
|
||||
|
||||
virtual void OnPlatformThemeChanged() {}
|
||||
|
||||
protected:
|
||||
virtual ~BrowserObserver() {}
|
||||
};
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
const v8Util = process.atomBinding('v8_util');
|
||||
|
||||
class ObjectsRegistry extends EventEmitter {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.setMaxListeners(Number.MAX_VALUE);
|
||||
this.nextId = 0;
|
||||
|
||||
// Stores all objects by ref-counting.
|
||||
// (id) => {object, count}
|
||||
this.storage = {};
|
||||
|
||||
// Stores the IDs of objects referenced by WebContents.
|
||||
// (webContentsId) => {(id) => (count)}
|
||||
this.owners = {};
|
||||
}
|
||||
|
||||
// Register a new object, the object would be kept referenced until you release
|
||||
// it explicitly.
|
||||
add(webContentsId, obj) {
|
||||
var base, base1, id;
|
||||
id = this.saveToStorage(obj);
|
||||
|
||||
// Remember the owner.
|
||||
if ((base = this.owners)[webContentsId] == null) {
|
||||
base[webContentsId] = {};
|
||||
}
|
||||
if ((base1 = this.owners[webContentsId])[id] == null) {
|
||||
base1[id] = 0;
|
||||
}
|
||||
this.owners[webContentsId][id]++;
|
||||
|
||||
// Returns object's id
|
||||
return id;
|
||||
}
|
||||
|
||||
// Get an object according to its ID.
|
||||
get(id) {
|
||||
var ref;
|
||||
return (ref = this.storage[id]) != null ? ref.object : void 0;
|
||||
}
|
||||
|
||||
// Dereference an object according to its ID.
|
||||
remove(webContentsId, id) {
|
||||
var pointer;
|
||||
this.dereference(id, 1);
|
||||
|
||||
// Also reduce the count in owner.
|
||||
pointer = this.owners[webContentsId];
|
||||
if (pointer == null) {
|
||||
return;
|
||||
}
|
||||
--pointer[id];
|
||||
if (pointer[id] === 0) {
|
||||
return delete pointer[id];
|
||||
}
|
||||
}
|
||||
|
||||
// Clear all references to objects refrenced by the WebContents.
|
||||
clear(webContentsId) {
|
||||
var count, id, ref;
|
||||
this.emit("clear-" + webContentsId);
|
||||
if (this.owners[webContentsId] == null) {
|
||||
return;
|
||||
}
|
||||
ref = this.owners[webContentsId];
|
||||
for (id in ref) {
|
||||
count = ref[id];
|
||||
this.dereference(id, count);
|
||||
}
|
||||
return delete this.owners[webContentsId];
|
||||
}
|
||||
|
||||
// Private: Saves the object into storage and assigns an ID for it.
|
||||
saveToStorage(object) {
|
||||
var id;
|
||||
id = v8Util.getHiddenValue(object, 'atomId');
|
||||
if (!id) {
|
||||
id = ++this.nextId;
|
||||
this.storage[id] = {
|
||||
count: 0,
|
||||
object: object
|
||||
};
|
||||
v8Util.setHiddenValue(object, 'atomId', id);
|
||||
}
|
||||
++this.storage[id].count;
|
||||
return id;
|
||||
}
|
||||
|
||||
// Private: Dereference the object from store.
|
||||
dereference(id, count) {
|
||||
var pointer;
|
||||
pointer = this.storage[id];
|
||||
if (pointer == null) {
|
||||
return;
|
||||
}
|
||||
pointer.count -= count;
|
||||
if (pointer.count === 0) {
|
||||
v8Util.deleteHiddenValue(pointer.object, 'atomId');
|
||||
return delete this.storage[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new ObjectsRegistry;
|
||||
@@ -24,6 +24,9 @@
|
||||
// Don't add the "Enter Full Screen" menu item automatically.
|
||||
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"NSFullScreenMenuItemEverywhere"];
|
||||
|
||||
// Add observer to monitor the system's Dark Mode theme.
|
||||
[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(platformThemeChanged:) name:@"AppleInterfaceThemeChangedNotification" object:nil];
|
||||
|
||||
atom::Browser::Get()->WillFinishLaunching();
|
||||
}
|
||||
|
||||
@@ -59,4 +62,8 @@
|
||||
return flag;
|
||||
}
|
||||
|
||||
- (void)platformThemeChanged:(NSNotification *)notify {
|
||||
atom::Browser::Get()->PlatformThemeChanged();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -115,6 +115,12 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
|
||||
} else {
|
||||
SetSizeConstraints(size_constraints);
|
||||
}
|
||||
#if defined(USE_X11)
|
||||
bool resizable;
|
||||
if (options.Get(options::kResizable, &resizable)) {
|
||||
SetResizable(resizable);
|
||||
}
|
||||
#endif
|
||||
#if defined(OS_WIN) || defined(USE_X11)
|
||||
bool closable;
|
||||
if (options.Get(options::kClosable, &closable)) {
|
||||
@@ -133,12 +139,17 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
|
||||
if (options.Get(options::kAlwaysOnTop, &top) && top) {
|
||||
SetAlwaysOnTop(true);
|
||||
}
|
||||
#if defined(OS_MACOSX) || defined(OS_WIN)
|
||||
bool fullscreen;
|
||||
if (options.Get(options::kFullscreen, &fullscreen) && fullscreen) {
|
||||
// Disable fullscreen button if 'fullscreen' is specified to false.
|
||||
bool fullscreenable = true;
|
||||
bool fullscreen = false;
|
||||
if (options.Get(options::kFullscreen, &fullscreen) && !fullscreen)
|
||||
fullscreenable = false;
|
||||
// Overriden by 'fullscreenable'.
|
||||
options.Get(options::kFullScreenable, &fullscreenable);
|
||||
SetFullScreenable(fullscreenable);
|
||||
if (fullscreen) {
|
||||
SetFullScreen(true);
|
||||
}
|
||||
#endif
|
||||
bool skip;
|
||||
if (options.Get(options::kSkipTaskbar, &skip) && skip) {
|
||||
SetSkipTaskbar(skip);
|
||||
@@ -417,6 +428,14 @@ void NativeWindow::NotifyWindowFocus() {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowFocus());
|
||||
}
|
||||
|
||||
void NativeWindow::NotifyWindowShow() {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowShow());
|
||||
}
|
||||
|
||||
void NativeWindow::NotifyWindowHide() {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowHide());
|
||||
}
|
||||
|
||||
void NativeWindow::NotifyWindowMaximize() {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowMaximize());
|
||||
}
|
||||
|
||||
@@ -210,6 +210,8 @@ class NativeWindow : public base::SupportsUserData,
|
||||
void NotifyWindowClosed();
|
||||
void NotifyWindowBlur();
|
||||
void NotifyWindowFocus();
|
||||
void NotifyWindowShow();
|
||||
void NotifyWindowHide();
|
||||
void NotifyWindowMaximize();
|
||||
void NotifyWindowUnmaximize();
|
||||
void NotifyWindowMinimize();
|
||||
|
||||
@@ -79,6 +79,21 @@ bool ScopedDisableResize::disable_resize_ = false;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)windowDidChangeOcclusionState:(NSNotification *)notification {
|
||||
// notification.object is the window that changed its state.
|
||||
// It's safe to use self.window instead if you don't assign one delegate to many windows
|
||||
NSWindow *window = notification.object;
|
||||
|
||||
// check occlusion binary flag
|
||||
if (window.occlusionState & NSWindowOcclusionStateVisible) {
|
||||
// The app is visible
|
||||
shell_->NotifyWindowShow();
|
||||
} else {
|
||||
// The app is not visible
|
||||
shell_->NotifyWindowHide();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)windowDidBecomeMain:(NSNotification*)notification {
|
||||
content::WebContents* web_contents = shell_->web_contents();
|
||||
if (!web_contents)
|
||||
@@ -482,19 +497,9 @@ NativeWindowMac::NativeWindowMac(
|
||||
options.Get(options::kDisableAutoHideCursor, &disableAutoHideCursor);
|
||||
[window_ setDisableAutoHideCursor:disableAutoHideCursor];
|
||||
|
||||
// Disable fullscreen button when 'fullscreenable' is false or 'fullscreen'
|
||||
// is specified to false.
|
||||
bool fullscreenable = true;
|
||||
options.Get(options::kFullScreenable, &fullscreenable);
|
||||
bool fullscreen = false;
|
||||
if (options.Get(options::kFullscreen, &fullscreen) && !fullscreen)
|
||||
fullscreenable = false;
|
||||
SetFullScreenable(fullscreenable);
|
||||
|
||||
// Disable zoom button if window is not resizable
|
||||
if (!maximizable) {
|
||||
// Disable zoom button if window is not resizable.
|
||||
if (!maximizable)
|
||||
SetMaximizable(false);
|
||||
}
|
||||
|
||||
NSView* view = inspectable_web_contents()->GetView()->GetNativeView();
|
||||
[view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
@@ -583,7 +588,16 @@ void NativeWindowMac::Unmaximize() {
|
||||
}
|
||||
|
||||
bool NativeWindowMac::IsMaximized() {
|
||||
return [window_ isZoomed];
|
||||
if (([window_ styleMask] & NSResizableWindowMask) != 0) {
|
||||
return [window_ isZoomed];
|
||||
} else {
|
||||
NSRect rectScreen = [[NSScreen mainScreen] visibleFrame];
|
||||
NSRect rectWindow = [window_ frame];
|
||||
return (rectScreen.origin.x == rectWindow.origin.x &&
|
||||
rectScreen.origin.y == rectWindow.origin.y &&
|
||||
rectScreen.size.width == rectWindow.size.width &&
|
||||
rectScreen.size.height == rectWindow.size.height);
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindowMac::Minimize() {
|
||||
@@ -896,21 +910,11 @@ void NativeWindowMac::HandleKeyboardEvent(
|
||||
// Handle the cmd+~ shortcut.
|
||||
if ((event.os_event.modifierFlags & NSCommandKeyMask) /* cmd */ &&
|
||||
(event.os_event.keyCode == 50 /* ~ */)) {
|
||||
// Switch to next visible window.
|
||||
NSArray* windows = [NSApp windows];
|
||||
NSIndexSet* indexes = [windows indexesOfObjectsPassingTest:
|
||||
^BOOL(id window, NSUInteger idx, BOOL* stop) {
|
||||
return [window isVisible];
|
||||
}];
|
||||
if ([indexes count] == 0)
|
||||
return;
|
||||
NSUInteger current = [windows indexOfObject:event.os_event.window];
|
||||
if (current == NSNotFound) // Some faked event.
|
||||
return;
|
||||
NSUInteger next = [indexes indexGreaterThanIndex:current];
|
||||
if (next == NSNotFound)
|
||||
next = [indexes firstIndex];
|
||||
[[windows objectAtIndex:next] makeKeyAndOrderFront:nil];
|
||||
if (event.os_event.modifierFlags & NSShiftKeyMask) {
|
||||
[NSApp sendAction:@selector(_cycleWindowsReversed:) to:nil from:nil];
|
||||
} else {
|
||||
[NSApp sendAction:@selector(_cycleWindows:) to:nil from:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,12 @@ class NativeWindowObserver {
|
||||
// Called when window gains focus.
|
||||
virtual void OnWindowFocus() {}
|
||||
|
||||
// Called when window is shown.
|
||||
virtual void OnWindowShow() {}
|
||||
|
||||
// Called when window is hidden.
|
||||
virtual void OnWindowHide() {}
|
||||
|
||||
// Called when window state changed.
|
||||
virtual void OnWindowMaximize() {}
|
||||
virtual void OnWindowUnmaximize() {}
|
||||
|
||||
@@ -117,7 +117,8 @@ NativeWindowViews::NativeWindowViews(
|
||||
movable_(true),
|
||||
resizable_(true),
|
||||
maximizable_(true),
|
||||
minimizable_(true) {
|
||||
minimizable_(true),
|
||||
fullscreenable_(true) {
|
||||
options.Get(options::kTitle, &title_);
|
||||
options.Get(options::kAutoHideMenuBar, &menu_bar_autohide_);
|
||||
|
||||
@@ -300,14 +301,35 @@ bool NativeWindowViews::IsFocused() {
|
||||
|
||||
void NativeWindowViews::Show() {
|
||||
window_->native_widget_private()->ShowWithWindowState(GetRestoredState());
|
||||
|
||||
NotifyWindowShow();
|
||||
|
||||
#if defined(USE_X11)
|
||||
if (global_menu_bar_)
|
||||
global_menu_bar_->OnWindowMapped();
|
||||
#endif
|
||||
}
|
||||
|
||||
void NativeWindowViews::ShowInactive() {
|
||||
window_->ShowInactive();
|
||||
|
||||
NotifyWindowShow();
|
||||
|
||||
#if defined(USE_X11)
|
||||
if (global_menu_bar_)
|
||||
global_menu_bar_->OnWindowMapped();
|
||||
#endif
|
||||
}
|
||||
|
||||
void NativeWindowViews::Hide() {
|
||||
window_->Hide();
|
||||
|
||||
NotifyWindowHide();
|
||||
|
||||
#if defined(USE_X11)
|
||||
if (global_menu_bar_)
|
||||
global_menu_bar_->OnWindowUnmapped();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool NativeWindowViews::IsVisible() {
|
||||
@@ -347,6 +369,9 @@ bool NativeWindowViews::IsMinimized() {
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetFullScreen(bool fullscreen) {
|
||||
if (!IsFullScreenable())
|
||||
return;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// There is no native fullscreen state on Windows.
|
||||
if (fullscreen) {
|
||||
@@ -490,11 +515,12 @@ bool NativeWindowViews::IsMaximizable() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetFullScreenable(bool maximizable) {
|
||||
void NativeWindowViews::SetFullScreenable(bool fullscreenable) {
|
||||
fullscreenable_ = fullscreenable;
|
||||
}
|
||||
|
||||
bool NativeWindowViews::IsFullScreenable() {
|
||||
return true;
|
||||
return fullscreenable_;
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetClosable(bool closable) {
|
||||
|
||||
@@ -212,6 +212,7 @@ class NativeWindowViews : public NativeWindow,
|
||||
bool resizable_;
|
||||
bool maximizable_;
|
||||
bool minimizable_;
|
||||
bool fullscreenable_;
|
||||
std::string title_;
|
||||
gfx::Size widget_size_;
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>atom.icns</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.36.8</string>
|
||||
<string>0.36.12</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.36.8</string>
|
||||
<string>0.36.12</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.developer-tools</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
||||
@@ -56,8 +56,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,36,8,0
|
||||
PRODUCTVERSION 0,36,8,0
|
||||
FILEVERSION 0,36,12,0
|
||||
PRODUCTVERSION 0,36,12,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -74,12 +74,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Electron"
|
||||
VALUE "FileVersion", "0.36.8"
|
||||
VALUE "FileVersion", "0.36.12"
|
||||
VALUE "InternalName", "electron.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "electron.exe"
|
||||
VALUE "ProductName", "Electron"
|
||||
VALUE "ProductVersion", "0.36.8"
|
||||
VALUE "ProductVersion", "0.36.12"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
|
||||
@@ -18,13 +18,12 @@
|
||||
|
||||
namespace accelerator_util {
|
||||
|
||||
bool StringToAccelerator(const std::string& description,
|
||||
bool StringToAccelerator(const std::string& shortcut,
|
||||
ui::Accelerator* accelerator) {
|
||||
if (!base::IsStringASCII(description)) {
|
||||
if (!base::IsStringASCII(shortcut)) {
|
||||
LOG(ERROR) << "The accelerator string can only contain ASCII characters";
|
||||
return false;
|
||||
}
|
||||
std::string shortcut(base::ToLowerASCII(description));
|
||||
|
||||
std::vector<std::string> tokens = base::SplitString(
|
||||
shortcut, "+", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||
@@ -33,95 +32,35 @@ bool StringToAccelerator(const std::string& description,
|
||||
int modifiers = ui::EF_NONE;
|
||||
ui::KeyboardCode key = ui::VKEY_UNKNOWN;
|
||||
for (size_t i = 0; i < tokens.size(); i++) {
|
||||
// We use straight comparing instead of map because the accelerator tends
|
||||
// to be correct and usually only uses few special tokens.
|
||||
if (tokens[i].size() == 1) {
|
||||
bool shifted = false;
|
||||
key = atom::KeyboardCodeFromCharCode(tokens[i][0], &shifted);
|
||||
if (shifted)
|
||||
bool shifted = false;
|
||||
ui::KeyboardCode code = atom::KeyboardCodeFromStr(tokens[i], &shifted);
|
||||
if (shifted)
|
||||
modifiers |= ui::EF_SHIFT_DOWN;
|
||||
switch (code) {
|
||||
// The token can be a modifier.
|
||||
case ui::VKEY_SHIFT:
|
||||
modifiers |= ui::EF_SHIFT_DOWN;
|
||||
} else if (tokens[i] == "ctrl" || tokens[i] == "control") {
|
||||
modifiers |= ui::EF_CONTROL_DOWN;
|
||||
} else if (tokens[i] == "super") {
|
||||
modifiers |= ui::EF_COMMAND_DOWN;
|
||||
#if defined(OS_MACOSX)
|
||||
} else if (tokens[i] == "cmd" || tokens[i] == "command") {
|
||||
modifiers |= ui::EF_COMMAND_DOWN;
|
||||
#endif
|
||||
} else if (tokens[i] == "commandorcontrol" || tokens[i] == "cmdorctrl") {
|
||||
#if defined(OS_MACOSX)
|
||||
modifiers |= ui::EF_COMMAND_DOWN;
|
||||
#else
|
||||
modifiers |= ui::EF_CONTROL_DOWN;
|
||||
#endif
|
||||
} else if (tokens[i] == "alt") {
|
||||
modifiers |= ui::EF_ALT_DOWN;
|
||||
} else if (tokens[i] == "shift") {
|
||||
modifiers |= ui::EF_SHIFT_DOWN;
|
||||
} else if (tokens[i] == "plus") {
|
||||
modifiers |= ui::EF_SHIFT_DOWN;
|
||||
key = ui::VKEY_OEM_PLUS;
|
||||
} else if (tokens[i] == "tab") {
|
||||
key = ui::VKEY_TAB;
|
||||
} else if (tokens[i] == "space") {
|
||||
key = ui::VKEY_SPACE;
|
||||
} else if (tokens[i] == "backspace") {
|
||||
key = ui::VKEY_BACK;
|
||||
} else if (tokens[i] == "delete") {
|
||||
key = ui::VKEY_DELETE;
|
||||
} else if (tokens[i] == "insert") {
|
||||
key = ui::VKEY_INSERT;
|
||||
} else if (tokens[i] == "enter" || tokens[i] == "return") {
|
||||
key = ui::VKEY_RETURN;
|
||||
} else if (tokens[i] == "up") {
|
||||
key = ui::VKEY_UP;
|
||||
} else if (tokens[i] == "down") {
|
||||
key = ui::VKEY_DOWN;
|
||||
} else if (tokens[i] == "left") {
|
||||
key = ui::VKEY_LEFT;
|
||||
} else if (tokens[i] == "right") {
|
||||
key = ui::VKEY_RIGHT;
|
||||
} else if (tokens[i] == "home") {
|
||||
key = ui::VKEY_HOME;
|
||||
} else if (tokens[i] == "end") {
|
||||
key = ui::VKEY_END;
|
||||
} else if (tokens[i] == "pageup") {
|
||||
key = ui::VKEY_PRIOR;
|
||||
} else if (tokens[i] == "pagedown") {
|
||||
key = ui::VKEY_NEXT;
|
||||
} else if (tokens[i] == "esc" || tokens[i] == "escape") {
|
||||
key = ui::VKEY_ESCAPE;
|
||||
} else if (tokens[i] == "volumemute") {
|
||||
key = ui::VKEY_VOLUME_MUTE;
|
||||
} else if (tokens[i] == "volumeup") {
|
||||
key = ui::VKEY_VOLUME_UP;
|
||||
} else if (tokens[i] == "volumedown") {
|
||||
key = ui::VKEY_VOLUME_DOWN;
|
||||
} else if (tokens[i] == "medianexttrack") {
|
||||
key = ui::VKEY_MEDIA_NEXT_TRACK;
|
||||
} else if (tokens[i] == "mediaprevioustrack") {
|
||||
key = ui::VKEY_MEDIA_PREV_TRACK;
|
||||
} else if (tokens[i] == "mediastop") {
|
||||
key = ui::VKEY_MEDIA_STOP;
|
||||
} else if (tokens[i] == "mediaplaypause") {
|
||||
key = ui::VKEY_MEDIA_PLAY_PAUSE;
|
||||
} else if (tokens[i].size() > 1 && tokens[i][0] == 'f') {
|
||||
// F1 - F24.
|
||||
int n;
|
||||
if (base::StringToInt(tokens[i].c_str() + 1, &n) && n > 0 && n < 25) {
|
||||
key = static_cast<ui::KeyboardCode>(ui::VKEY_F1 + n - 1);
|
||||
} else {
|
||||
LOG(WARNING) << tokens[i] << "is not available on keyboard";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
LOG(WARNING) << "Invalid accelerator token: " << tokens[i];
|
||||
return false;
|
||||
break;
|
||||
case ui::VKEY_CONTROL:
|
||||
modifiers |= ui::EF_CONTROL_DOWN;
|
||||
break;
|
||||
case ui::VKEY_MENU:
|
||||
modifiers |= ui::EF_ALT_DOWN;
|
||||
break;
|
||||
case ui::VKEY_COMMAND:
|
||||
modifiers |= ui::EF_COMMAND_DOWN;
|
||||
break;
|
||||
case ui::VKEY_ALTGR:
|
||||
modifiers |= ui::EF_ALTGR_DOWN;
|
||||
break;
|
||||
// Or it is a normal key.
|
||||
default:
|
||||
key = code;
|
||||
}
|
||||
}
|
||||
|
||||
if (key == ui::VKEY_UNKNOWN) {
|
||||
LOG(WARNING) << "The accelerator doesn't contain a valid key";
|
||||
LOG(WARNING) << shortcut << " doesn't contain a valid key";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,9 +32,12 @@ Role kRolesMap[] = {
|
||||
{ @selector(cut:), "cut" },
|
||||
{ @selector(copy:), "copy" },
|
||||
{ @selector(paste:), "paste" },
|
||||
{ @selector(delete:), "delete" },
|
||||
{ @selector(pasteAndMatchStyle:), "paste-and-match-style" },
|
||||
{ @selector(selectAll:), "selectall" },
|
||||
{ @selector(performMiniaturize:), "minimize" },
|
||||
{ @selector(performClose:), "close" },
|
||||
{ @selector(performZoom:), "zoom" },
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -210,6 +210,14 @@ void GlobalMenuBarX11::InitServer(gfx::AcceleratedWidget xid) {
|
||||
server_ = server_new(path.c_str());
|
||||
}
|
||||
|
||||
void GlobalMenuBarX11::OnWindowMapped() {
|
||||
GlobalMenuBarRegistrarX11::GetInstance()->OnWindowMapped(xid_);
|
||||
}
|
||||
|
||||
void GlobalMenuBarX11::OnWindowUnmapped() {
|
||||
GlobalMenuBarRegistrarX11::GetInstance()->OnWindowUnmapped(xid_);
|
||||
}
|
||||
|
||||
void GlobalMenuBarX11::BuildMenuFromModel(ui::MenuModel* model,
|
||||
DbusmenuMenuitem* parent) {
|
||||
for (int i = 0; i < model->GetItemCount(); ++i) {
|
||||
|
||||
@@ -40,12 +40,16 @@ class GlobalMenuBarX11 {
|
||||
explicit GlobalMenuBarX11(NativeWindowViews* window);
|
||||
virtual ~GlobalMenuBarX11();
|
||||
|
||||
// Creates the object path for DbusemenuServer which is attached to |xid|.
|
||||
// Creates the object path for DbusmenuServer which is attached to |xid|.
|
||||
static std::string GetPathForWindow(gfx::AcceleratedWidget xid);
|
||||
|
||||
void SetMenu(ui::MenuModel* menu_model);
|
||||
bool IsServerStarted() const;
|
||||
|
||||
// Called by NativeWindow when it show/hides.
|
||||
void OnWindowMapped();
|
||||
void OnWindowUnmapped();
|
||||
|
||||
private:
|
||||
// Creates a DbusmenuServer.
|
||||
void InitServer(gfx::AcceleratedWidget xid);
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace atom {
|
||||
namespace {
|
||||
|
||||
// Filter out the "&" in menu label.
|
||||
base::string16 FilterAccecelator(const base::string16& label) {
|
||||
base::string16 FilterAccelerator(const base::string16& label) {
|
||||
base::string16 out;
|
||||
base::RemoveChars(label, base::ASCIIToUTF16("&").c_str(), &out);
|
||||
return out;
|
||||
@@ -26,7 +26,7 @@ base::string16 FilterAccecelator(const base::string16& label) {
|
||||
SubmenuButton::SubmenuButton(views::ButtonListener* listener,
|
||||
const base::string16& title,
|
||||
views::MenuButtonListener* menu_button_listener)
|
||||
: views::MenuButton(listener, FilterAccecelator(title),
|
||||
: views::MenuButton(listener, FilterAccelerator(title),
|
||||
menu_button_listener, false),
|
||||
accelerator_(0),
|
||||
show_underline_(false),
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/base64.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/pattern.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
@@ -119,6 +120,20 @@ bool PopulateImageSkiaRepsFromPath(gfx::ImageSkia* image,
|
||||
return succeed;
|
||||
}
|
||||
|
||||
base::FilePath NormalizePath(const base::FilePath& path) {
|
||||
if (!path.ReferencesParent()) {
|
||||
return path;
|
||||
}
|
||||
|
||||
base::FilePath absolute_path = MakeAbsoluteFilePath(path);
|
||||
// MakeAbsoluteFilePath returns an empty path on failures so use original path
|
||||
if (absolute_path.empty()) {
|
||||
return path;
|
||||
} else {
|
||||
return absolute_path;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
bool IsTemplateFilename(const base::FilePath& path) {
|
||||
return (base::MatchPattern(path.value(), "*Template.*") ||
|
||||
@@ -254,17 +269,19 @@ mate::Handle<NativeImage> NativeImage::CreateFromJPEG(
|
||||
mate::Handle<NativeImage> NativeImage::CreateFromPath(
|
||||
v8::Isolate* isolate, const base::FilePath& path) {
|
||||
gfx::ImageSkia image_skia;
|
||||
if (path.MatchesExtension(FILE_PATH_LITERAL(".ico"))) {
|
||||
base::FilePath image_path = NormalizePath(path);
|
||||
|
||||
if (image_path.MatchesExtension(FILE_PATH_LITERAL(".ico"))) {
|
||||
#if defined(OS_WIN)
|
||||
ReadImageSkiaFromICO(&image_skia, path);
|
||||
ReadImageSkiaFromICO(&image_skia, image_path);
|
||||
#endif
|
||||
} else {
|
||||
PopulateImageSkiaRepsFromPath(&image_skia, path);
|
||||
PopulateImageSkiaRepsFromPath(&image_skia, image_path);
|
||||
}
|
||||
gfx::Image image(image_skia);
|
||||
mate::Handle<NativeImage> handle = Create(isolate, image);
|
||||
#if defined(OS_MACOSX)
|
||||
if (IsTemplateFilename(path))
|
||||
if (IsTemplateFilename(image_path))
|
||||
handle->SetTemplateImage(true);
|
||||
#endif
|
||||
return handle;
|
||||
|
||||
@@ -2,49 +2,15 @@
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "atom/common/api/object_life_monitor.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/stl_util.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "v8/include/v8-profiler.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// A Persistent that can be copied and will not free itself.
|
||||
template<class T>
|
||||
struct LeakedPersistentTraits {
|
||||
typedef v8::Persistent<T, LeakedPersistentTraits<T> > LeakedPersistent;
|
||||
static const bool kResetInDestructor = false;
|
||||
template<class S, class M>
|
||||
static V8_INLINE void Copy(const v8::Persistent<S, M>& source,
|
||||
LeakedPersistent* dest) {
|
||||
// do nothing, just allow copy
|
||||
}
|
||||
};
|
||||
|
||||
// The handles are leaked on purpose.
|
||||
using FunctionTemplateHandle =
|
||||
LeakedPersistentTraits<v8::FunctionTemplate>::LeakedPersistent;
|
||||
std::map<std::string, FunctionTemplateHandle> function_templates_;
|
||||
|
||||
v8::Local<v8::Object> CreateObjectWithName(v8::Isolate* isolate,
|
||||
const std::string& name) {
|
||||
if (name == "Object")
|
||||
return v8::Object::New(isolate);
|
||||
|
||||
if (ContainsKey(function_templates_, name))
|
||||
return v8::Local<v8::FunctionTemplate>::New(
|
||||
isolate, function_templates_[name])->GetFunction()->NewInstance();
|
||||
|
||||
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
|
||||
t->SetClassName(mate::StringToV8(isolate, name));
|
||||
function_templates_[name] = FunctionTemplateHandle(isolate, t);
|
||||
return t->GetFunction()->NewInstance();
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> GetHiddenValue(v8::Local<v8::Object> object,
|
||||
v8::Local<v8::String> key) {
|
||||
return object->GetHiddenValue(key);
|
||||
@@ -78,7 +44,6 @@ void TakeHeapSnapshot(v8::Isolate* isolate) {
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
mate::Dictionary dict(context->GetIsolate(), exports);
|
||||
dict.SetMethod("createObjectWithName", &CreateObjectWithName);
|
||||
dict.SetMethod("getHiddenValue", &GetHiddenValue);
|
||||
dict.SetMethod("setHiddenValue", &SetHiddenValue);
|
||||
dict.SetMethod("deleteHiddenValue", &DeleteHiddenValue);
|
||||
|
||||
@@ -31,16 +31,16 @@ ObjectLifeMonitor::ObjectLifeMonitor(v8::Isolate* isolate,
|
||||
// static
|
||||
void ObjectLifeMonitor::OnObjectGC(
|
||||
const v8::WeakCallbackInfo<ObjectLifeMonitor>& data) {
|
||||
// Usually FirstWeakCallback should do nothing other than reset |object_|
|
||||
// and then set a second weak callback to run later. We can sidestep that,
|
||||
// because posting a task to the current message loop is all but free - but
|
||||
// DO NOT add any more work to this method. The only acceptable place to add
|
||||
// code is RunCallback.
|
||||
ObjectLifeMonitor* self = data.GetParameter();
|
||||
self->target_.Reset();
|
||||
base::MessageLoop::current()->PostTask(
|
||||
FROM_HERE, base::Bind(&ObjectLifeMonitor::RunCallback,
|
||||
self->weak_ptr_factory_.GetWeakPtr()));
|
||||
self->RunCallback();
|
||||
data.SetSecondPassCallback(Free);
|
||||
}
|
||||
|
||||
// static
|
||||
void ObjectLifeMonitor::Free(
|
||||
const v8::WeakCallbackInfo<ObjectLifeMonitor>& data) {
|
||||
delete data.GetParameter();
|
||||
}
|
||||
|
||||
void ObjectLifeMonitor::RunCallback() {
|
||||
@@ -50,7 +50,6 @@ void ObjectLifeMonitor::RunCallback() {
|
||||
v8::Context::Scope context_scope(context);
|
||||
v8::Local<v8::Function>::New(isolate_, destructor_)->Call(
|
||||
context->Global(), 0, nullptr);
|
||||
delete this;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -23,6 +23,7 @@ class ObjectLifeMonitor {
|
||||
v8::Local<v8::Function> destructor);
|
||||
|
||||
static void OnObjectGC(const v8::WeakCallbackInfo<ObjectLifeMonitor>& data);
|
||||
static void Free(const v8::WeakCallbackInfo<ObjectLifeMonitor>& data);
|
||||
|
||||
void RunCallback();
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#define ATOM_MAJOR_VERSION 0
|
||||
#define ATOM_MINOR_VERSION 36
|
||||
#define ATOM_PATCH_VERSION 8
|
||||
#define ATOM_PATCH_VERSION 12
|
||||
|
||||
#define ATOM_VERSION_IS_RELEASE 1
|
||||
|
||||
|
||||
@@ -211,7 +211,7 @@ bool CrashService::Initialize(const base::string16& application_name,
|
||||
std::wstring pipe_name = kTestPipeName;
|
||||
int max_reports = -1;
|
||||
|
||||
// The checkpoint file allows CrashReportSender to enforce the the maximum
|
||||
// The checkpoint file allows CrashReportSender to enforce the maximum
|
||||
// reports per day quota. Does not seem to serve any other purpose.
|
||||
base::FilePath checkpoint_path = operating_dir.Append(kCheckPointFile);
|
||||
|
||||
|
||||
@@ -3,12 +3,19 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "atom/common/keyboard_util.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_util.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
// Return key code of the char.
|
||||
namespace {
|
||||
|
||||
// Return key code of the char, and also determine whether the SHIFT key is
|
||||
// pressed.
|
||||
ui::KeyboardCode KeyboardCodeFromCharCode(base::char16 c, bool* shifted) {
|
||||
c = base::ToLowerASCII(c);
|
||||
*shifted = false;
|
||||
switch (c) {
|
||||
case 0x08: return ui::VKEY_BACK;
|
||||
@@ -72,28 +79,98 @@ ui::KeyboardCode KeyboardCodeFromCharCode(base::char16 c, bool* shifted) {
|
||||
}
|
||||
}
|
||||
|
||||
// Return key code of the char.
|
||||
ui::KeyboardCode KeyboardCodeFromKeyIdentifier(const std::string& chr) {
|
||||
if (chr == "enter") return ui::VKEY_RETURN;
|
||||
if (chr == "backspace") return ui::VKEY_BACK;
|
||||
if (chr == "delete") return ui::VKEY_DELETE;
|
||||
if (chr == "tab") return ui::VKEY_TAB;
|
||||
if (chr == "escape") return ui::VKEY_ESCAPE;
|
||||
if (chr == "control") return ui::VKEY_CONTROL;
|
||||
if (chr == "alt") return ui::VKEY_MENU;
|
||||
if (chr == "shift") return ui::VKEY_SHIFT;
|
||||
if (chr == "end") return ui::VKEY_END;
|
||||
if (chr == "home") return ui::VKEY_HOME;
|
||||
if (chr == "insert") return ui::VKEY_INSERT;
|
||||
if (chr == "left") return ui::VKEY_LEFT;
|
||||
if (chr == "up") return ui::VKEY_UP;
|
||||
if (chr == "right") return ui::VKEY_RIGHT;
|
||||
if (chr == "down") return ui::VKEY_DOWN;
|
||||
if (chr == "pageup") return ui::VKEY_PRIOR;
|
||||
if (chr == "pagedown") return ui::VKEY_NEXT;
|
||||
if (chr == "printscreen") return ui::VKEY_SNAPSHOT;
|
||||
// Return key code represented by |str|.
|
||||
ui::KeyboardCode KeyboardCodeFromKeyIdentifier(const std::string& s,
|
||||
bool* shifted) {
|
||||
std::string str = base::ToLowerASCII(s);
|
||||
if (str == "ctrl" || str == "control") {
|
||||
return ui::VKEY_CONTROL;
|
||||
} else if (str == "super" || str == "cmd" || str == "command" ||
|
||||
str == "meta") {
|
||||
return ui::VKEY_COMMAND;
|
||||
} else if (str == "commandorcontrol" || str == "cmdorctrl") {
|
||||
#if defined(OS_MACOSX)
|
||||
return ui::VKEY_COMMAND;
|
||||
#else
|
||||
return ui::VKEY_CONTROL;
|
||||
#endif
|
||||
} else if (str == "alt" || str == "option") {
|
||||
return ui::VKEY_MENU;
|
||||
} else if (str == "shift") {
|
||||
return ui::VKEY_SHIFT;
|
||||
} else if (str == "altgr") {
|
||||
return ui::VKEY_ALTGR;
|
||||
} else if (str == "plus") {
|
||||
*shifted = true;
|
||||
return ui::VKEY_OEM_PLUS;
|
||||
} else if (str == "tab") {
|
||||
return ui::VKEY_TAB;
|
||||
} else if (str == "space") {
|
||||
return ui::VKEY_SPACE;
|
||||
} else if (str == "backspace") {
|
||||
return ui::VKEY_BACK;
|
||||
} else if (str == "delete") {
|
||||
return ui::VKEY_DELETE;
|
||||
} else if (str == "insert") {
|
||||
return ui::VKEY_INSERT;
|
||||
} else if (str == "enter" || str == "return") {
|
||||
return ui::VKEY_RETURN;
|
||||
} else if (str == "up") {
|
||||
return ui::VKEY_UP;
|
||||
} else if (str == "down") {
|
||||
return ui::VKEY_DOWN;
|
||||
} else if (str == "left") {
|
||||
return ui::VKEY_LEFT;
|
||||
} else if (str == "right") {
|
||||
return ui::VKEY_RIGHT;
|
||||
} else if (str == "home") {
|
||||
return ui::VKEY_HOME;
|
||||
} else if (str == "end") {
|
||||
return ui::VKEY_END;
|
||||
} else if (str == "pageup") {
|
||||
return ui::VKEY_PRIOR;
|
||||
} else if (str == "pagedown") {
|
||||
return ui::VKEY_NEXT;
|
||||
} else if (str == "esc" || str == "escape") {
|
||||
return ui::VKEY_ESCAPE;
|
||||
} else if (str == "volumemute") {
|
||||
return ui::VKEY_VOLUME_MUTE;
|
||||
} else if (str == "volumeup") {
|
||||
return ui::VKEY_VOLUME_UP;
|
||||
} else if (str == "volumedown") {
|
||||
return ui::VKEY_VOLUME_DOWN;
|
||||
} else if (str == "medianexttrack") {
|
||||
return ui::VKEY_MEDIA_NEXT_TRACK;
|
||||
} else if (str == "mediaprevioustrack") {
|
||||
return ui::VKEY_MEDIA_PREV_TRACK;
|
||||
} else if (str == "mediastop") {
|
||||
return ui::VKEY_MEDIA_STOP;
|
||||
} else if (str == "mediaplaypause") {
|
||||
return ui::VKEY_MEDIA_PLAY_PAUSE;
|
||||
} else if (str == "printscreen") {
|
||||
return ui::VKEY_SNAPSHOT;
|
||||
} else if (str.size() > 1 && str[0] == 'f') {
|
||||
// F1 - F24.
|
||||
int n;
|
||||
if (base::StringToInt(str.c_str() + 1, &n) && n > 0 && n < 25) {
|
||||
return static_cast<ui::KeyboardCode>(ui::VKEY_F1 + n - 1);
|
||||
} else {
|
||||
LOG(WARNING) << str << "is not available on keyboard";
|
||||
return ui::VKEY_UNKNOWN;
|
||||
}
|
||||
} else {
|
||||
LOG(WARNING) << "Invalid accelerator token: " << str;
|
||||
return ui::VKEY_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
return ui::VKEY_UNKNOWN;
|
||||
} // namespace
|
||||
|
||||
ui::KeyboardCode KeyboardCodeFromStr(const std::string& str, bool* shifted) {
|
||||
if (str.size() == 1)
|
||||
return KeyboardCodeFromCharCode(str[0], shifted);
|
||||
else
|
||||
return KeyboardCodeFromKeyIdentifier(str, shifted);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -6,17 +6,14 @@
|
||||
#define ATOM_COMMON_KEYBOARD_UTIL_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ui/events/keycodes/keyboard_codes.h"
|
||||
#include "base/strings/string_util.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
// Return key code of the char, and also determine whether the SHIFT key is
|
||||
// Return key code of the |str|, and also determine whether the SHIFT key is
|
||||
// pressed.
|
||||
ui::KeyboardCode KeyboardCodeFromCharCode(base::char16 c, bool* shifted);
|
||||
|
||||
// Return key code of the char from a string representation of the char
|
||||
ui::KeyboardCode KeyboardCodeFromKeyIdentifier(const std::string& chr);
|
||||
ui::KeyboardCode KeyboardCodeFromStr(const std::string& str, bool* shifted);
|
||||
|
||||
} // namespace atom
|
||||
|
||||
|
||||
@@ -159,25 +159,22 @@ bool Converter<blink::WebKeyboardEvent>::FromV8(
|
||||
return false;
|
||||
if (!ConvertFromV8(isolate, val, static_cast<blink::WebInputEvent*>(out)))
|
||||
return false;
|
||||
base::char16 code;
|
||||
std::string identifier;
|
||||
bool shifted = false;
|
||||
|
||||
if (dict.Get("keyCode", &code))
|
||||
out->windowsKeyCode = atom::KeyboardCodeFromCharCode(code, &shifted);
|
||||
else if (dict.Get("keyCode", &identifier))
|
||||
out->windowsKeyCode = atom::KeyboardCodeFromKeyIdentifier(
|
||||
base::ToLowerASCII(identifier));
|
||||
std::string str;
|
||||
bool shifted = false;
|
||||
if (dict.Get("keyCode", &str))
|
||||
out->windowsKeyCode = atom::KeyboardCodeFromStr(str, &shifted);
|
||||
else
|
||||
return false;
|
||||
|
||||
if (shifted)
|
||||
out->modifiers |= blink::WebInputEvent::ShiftKey;
|
||||
out->setKeyIdentifierFromWindowsKeyCode();
|
||||
if (out->type == blink::WebInputEvent::Char ||
|
||||
out->type == blink::WebInputEvent::RawKeyDown) {
|
||||
out->text[0] = code;
|
||||
out->unmodifiedText[0] = code;
|
||||
if ((out->type == blink::WebInputEvent::Char ||
|
||||
out->type == blink::WebInputEvent::RawKeyDown) &&
|
||||
str.size() == 1) {
|
||||
out->text[0] = str[0];
|
||||
out->unmodifiedText[0] = str[0];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -173,6 +173,8 @@ bool Converter<content::StopFindAction>::FromV8(
|
||||
// static
|
||||
v8::Local<v8::Value> Converter<content::WebContents*>::ToV8(
|
||||
v8::Isolate* isolate, content::WebContents* val) {
|
||||
if (!val)
|
||||
return v8::Null(isolate);
|
||||
return atom::api::WebContents::CreateFrom(isolate, val).ToV8();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,9 @@ v8::Local<v8::Value> Converter<const net::URLRequest*>::ToV8(
|
||||
v8::Isolate* isolate, const net::URLRequest* val) {
|
||||
scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
|
||||
dict->SetString("method", val->method());
|
||||
dict->SetStringWithoutPathExpansion("url", val->url().spec());
|
||||
std::string url;
|
||||
if (!val->url_chain().empty()) url = val->url().spec();
|
||||
dict->SetStringWithoutPathExpansion("url", url);
|
||||
dict->SetString("referrer", val->referrer());
|
||||
scoped_ptr<base::ListValue> list(new base::ListValue);
|
||||
atom::GetUploadData(list.get(), val);
|
||||
|
||||
@@ -76,15 +76,10 @@ class V8ValueConverter::FromV8ValueState {
|
||||
};
|
||||
|
||||
V8ValueConverter::V8ValueConverter()
|
||||
: date_allowed_(false),
|
||||
reg_exp_allowed_(false),
|
||||
: reg_exp_allowed_(false),
|
||||
function_allowed_(false),
|
||||
strip_null_from_objects_(false) {}
|
||||
|
||||
void V8ValueConverter::SetDateAllowed(bool val) {
|
||||
date_allowed_ = val;
|
||||
}
|
||||
|
||||
void V8ValueConverter::SetRegExpAllowed(bool val) {
|
||||
reg_exp_allowed_ = val;
|
||||
}
|
||||
@@ -243,12 +238,17 @@ base::Value* V8ValueConverter::FromV8ValueImpl(
|
||||
return NULL;
|
||||
|
||||
if (val->IsDate()) {
|
||||
if (!date_allowed_)
|
||||
// JSON.stringify would convert this to a string, but an object is more
|
||||
// consistent within this class.
|
||||
return FromV8Object(val->ToObject(), state, isolate);
|
||||
v8::Date* date = v8::Date::Cast(*val);
|
||||
return new base::FundamentalValue(date->NumberValue() / 1000.0);
|
||||
v8::Local<v8::Value> toISOString =
|
||||
date->Get(v8::String::NewFromUtf8(isolate, "toISOString"));
|
||||
if (toISOString->IsFunction()) {
|
||||
v8::Local<v8::Value> result =
|
||||
toISOString.As<v8::Function>()->Call(val, 0, nullptr);
|
||||
if (!result.IsEmpty()) {
|
||||
v8::String::Utf8Value utf8(result->ToString());
|
||||
return new base::StringValue(std::string(*utf8, utf8.length()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (val->IsRegExp()) {
|
||||
|
||||
@@ -22,7 +22,6 @@ class V8ValueConverter {
|
||||
public:
|
||||
V8ValueConverter();
|
||||
|
||||
void SetDateAllowed(bool val);
|
||||
void SetRegExpAllowed(bool val);
|
||||
void SetFunctionAllowed(bool val);
|
||||
void SetStripNullFromObjects(bool val);
|
||||
@@ -58,9 +57,6 @@ class V8ValueConverter {
|
||||
FromV8ValueState* state,
|
||||
v8::Isolate* isolate) const;
|
||||
|
||||
// If true, we will convert Date JavaScript objects to doubles.
|
||||
bool date_allowed_;
|
||||
|
||||
// If true, we will convert RegExp JavaScript objects to string.
|
||||
bool reg_exp_allowed_;
|
||||
|
||||
|
||||
@@ -165,7 +165,6 @@ node::Environment* NodeBindings::CreateEnvironment(
|
||||
base::FilePath script_path =
|
||||
resources_path.Append(FILE_PATH_LITERAL("atom.asar"))
|
||||
.Append(process_type)
|
||||
.Append(FILE_PATH_LITERAL("lib"))
|
||||
.Append(FILE_PATH_LITERAL("init.js"));
|
||||
std::string script_path_str = script_path.AsUTF8Unsafe();
|
||||
args.insert(args.begin() + 1, script_path_str.c_str());
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "third_party/WebKit/public/web/WebDocument.h"
|
||||
#include "third_party/WebKit/public/web/WebLocalFrame.h"
|
||||
#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
|
||||
#include "third_party/WebKit/public/web/WebScriptExecutionCallback.h"
|
||||
#include "third_party/WebKit/public/web/WebScriptSource.h"
|
||||
#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
|
||||
#include "third_party/WebKit/public/web/WebView.h"
|
||||
@@ -26,6 +26,34 @@ namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
class ScriptExecutionCallback : public blink::WebScriptExecutionCallback {
|
||||
public:
|
||||
using CompletionCallback =
|
||||
base::Callback<void(
|
||||
const v8::Local<v8::Value>& result)>;
|
||||
|
||||
explicit ScriptExecutionCallback(const CompletionCallback& callback)
|
||||
: callback_(callback) {}
|
||||
~ScriptExecutionCallback() {}
|
||||
|
||||
void completed(
|
||||
const blink::WebVector<v8::Local<v8::Value>>& result) override {
|
||||
if (!callback_.is_null() && !result.isEmpty() && !result[0].IsEmpty())
|
||||
// Right now only single results per frame is supported.
|
||||
callback_.Run(result[0]);
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
CompletionCallback callback_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ScriptExecutionCallback);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
WebFrame::WebFrame()
|
||||
: web_frame_(blink::WebLocalFrame::frameForCurrentContext()) {
|
||||
}
|
||||
@@ -124,9 +152,14 @@ void WebFrame::ExecuteJavaScript(const base::string16& code,
|
||||
mate::Arguments* args) {
|
||||
bool has_user_gesture = false;
|
||||
args->GetNext(&has_user_gesture);
|
||||
scoped_ptr<blink::WebScopedUserGesture> gesture(
|
||||
has_user_gesture ? new blink::WebScopedUserGesture : nullptr);
|
||||
web_frame_->executeScriptAndReturnValue(blink::WebScriptSource(code));
|
||||
ScriptExecutionCallback::CompletionCallback completion_callback;
|
||||
args->GetNext(&completion_callback);
|
||||
scoped_ptr<blink::WebScriptExecutionCallback> callback(
|
||||
new ScriptExecutionCallback(completion_callback));
|
||||
web_frame_->requestExecuteScriptAndReturnValue(
|
||||
blink::WebScriptSource(code),
|
||||
has_user_gesture,
|
||||
callback.release());
|
||||
}
|
||||
|
||||
mate::ObjectTemplateBuilder WebFrame::GetObjectTemplateBuilder(
|
||||
|
||||
@@ -32,7 +32,7 @@ enum NotificationType {
|
||||
NOTIFICATION_BROWSER_CLOSING,
|
||||
|
||||
// This message is sent after a window has been closed. The source is a
|
||||
// Source<Browser> containing the affected Browser. No details are exptected.
|
||||
// Source<Browser> containing the affected Browser. No details are expected.
|
||||
NOTIFICATION_BROWSER_CLOSED,
|
||||
|
||||
// This message is sent when closing a browser has been cancelled, either by
|
||||
@@ -411,7 +411,7 @@ enum NotificationType {
|
||||
// the source is a Profile.
|
||||
NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
|
||||
|
||||
// An error occured while attempting to load an extension. The details are a
|
||||
// An error occurred while attempting to load an extension. The details are a
|
||||
// string with details about why the load failed.
|
||||
NOTIFICATION_EXTENSION_LOAD_ERROR,
|
||||
|
||||
@@ -434,7 +434,7 @@ enum NotificationType {
|
||||
// The details are an InstalledExtensionInfo, and the source is a Profile.
|
||||
NOTIFICATION_EXTENSION_INSTALLED,
|
||||
|
||||
// An error occured during extension install. The details are a string with
|
||||
// An error occurred during extension install. The details are a string with
|
||||
// details about why the install failed.
|
||||
NOTIFICATION_EXTENSION_INSTALL_ERROR,
|
||||
|
||||
@@ -625,7 +625,7 @@ enum NotificationType {
|
||||
// TabSpecificContentSettings object, there are no details.
|
||||
NOTIFICATION_COLLECTED_COOKIES_SHOWN,
|
||||
|
||||
// Sent when a non-default setting in the the notification content settings
|
||||
// Sent when a non-default setting in the notification content settings
|
||||
// map has changed. The source is the DesktopNotificationService, the
|
||||
// details are None.
|
||||
NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED,
|
||||
@@ -776,7 +776,7 @@ enum NotificationType {
|
||||
NOTIFICATION_USER_LIST_CHANGED,
|
||||
|
||||
// Sent when the screen lock state has changed. The source is
|
||||
// ScreenLocker and the details is a bool specifing that the
|
||||
// ScreenLocker and the details is a bool specifying that the
|
||||
// screen is locked. When details is a false, the source object
|
||||
// is being deleted, so the receiver shouldn't use the screen locker
|
||||
// object.
|
||||
@@ -838,7 +838,7 @@ enum NotificationType {
|
||||
// which was installed.
|
||||
NOTIFICATION_APP_INSTALLED_TO_NTP,
|
||||
|
||||
// Similar to NOTIFICATION_APP_INSTALLED_TO_NTP but used to nofity ash AppList
|
||||
// Similar to NOTIFICATION_APP_INSTALLED_TO_NTP but used to notify ash AppList
|
||||
// about installed app. Source is the profile in which the app is installed
|
||||
// and Details is the string ID of the extension.
|
||||
NOTIFICATION_APP_INSTALLED_TO_APPLIST,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
そうでない場合、おそらくご使用の Electron のバージョンと互換性のない API 変更を含んだ development ブランチのドキュメントを使っているものと思われます。
|
||||
その場合、atom.io の [available versions](http://electron.atom.io/docs/) リストにある別のバージョンのドキュメントに切り替えることができます。また GitHub で閲覧している場合、"Switch branches/tags" ドロップダウンを開いて、バージョンに対応したタグを選ぶこともできます。
|
||||
|
||||
_リンクになっていないリストは未翻訳のものです。_
|
||||
## FAQ
|
||||
|
||||
頻繁に聞かれる質問がありますので、issueを作成する前にこれをチェックしてください。
|
||||
@@ -31,3 +32,57 @@
|
||||
## API リファレンス
|
||||
|
||||
* [概要](api/synopsis.md)
|
||||
* [Process Object](api/process.md)
|
||||
* [サポートしているChromeコマンドラインスイッチ](api/chrome-command-line-switches.md)
|
||||
* [環境変数](api/environment-variables.md)
|
||||
|
||||
### カスタムDOM要素:
|
||||
|
||||
* [`File` Object](api/file-object.md)
|
||||
* `<webview>` Tag
|
||||
* [`window.open` 関数](api/window-open.md)
|
||||
|
||||
### Main Processのモジュール:
|
||||
|
||||
* [app](api/app.md)
|
||||
* [autoUpdater](api/auto-updater.md)
|
||||
* BrowserWindow
|
||||
* [フレームの無いウィンドウ](api/frameless-window.md)
|
||||
* [contentTracing](api/content-tracing.md)
|
||||
* [dialog](api/dialog.md)
|
||||
* [globalShortcut](api/global-shortcut.md)
|
||||
* [ipcMain](api/ipc-main.md)
|
||||
* [Menu](api/menu.md)
|
||||
* [MenuItem](api/menu-item.md)
|
||||
* [powerMonitor](api/power-monitor.md)
|
||||
* [powerSaveBlocker](api/power-save-blocker.md)
|
||||
* [protocol](api/protocol.md)
|
||||
* [session](api/session.md)
|
||||
* webContents
|
||||
* [Tray](api/tray.md)
|
||||
|
||||
### Renderer Processのモジュール (Web Page):
|
||||
|
||||
* [desktopCapturer](api/desktop-capturer.md)
|
||||
* [ipcRenderer](api/ipc-renderer.md)
|
||||
* [remote](api/remote.md)
|
||||
* [webFrame](api/web-frame.md)
|
||||
|
||||
### 両方のProcessのモジュール :
|
||||
|
||||
* [clipboard](api/clipboard.md)
|
||||
* [crashReporter](api/crash-reporter.md)
|
||||
* [nativeImage](api/native-image.md)
|
||||
* [screen](api/screen.md)
|
||||
* [shell](api/shell.md)
|
||||
|
||||
## 開発
|
||||
|
||||
* Coding Style
|
||||
* Source Code Directory Structure
|
||||
* Technical Differences to NW.js (formerly node-webkit)
|
||||
* Build System Overview
|
||||
* Build Instructions (OS X)
|
||||
* Build Instructions (Windows)
|
||||
* Build Instructions (Linux)
|
||||
* Setting Up Symbol Server in debugger
|
||||
|
||||
@@ -378,6 +378,7 @@ if (browserOptions.transparent) {
|
||||
// No transparency, so we load a fallback that uses basic styles.
|
||||
win.loadURL('file://' + __dirname + '/fallback.html');
|
||||
}
|
||||
```
|
||||
|
||||
### `app.commandLine.appendSwitch(switch[, value])`
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
* `channel` String - イベント名
|
||||
* `arg` (optional)
|
||||
|
||||
`channel`経由でメインプロセスに非同期にイベントを送信し、任意の引数を送信できます。
|
||||
`channel`経由でメインプロセスに同期的にイベントを送信し、任意の引数を送信できます。
|
||||
|
||||
メインプロセスは`ipcMain`で`channel`を受信することでハンドルし、 `event.returnValue`を設定してリプライします。
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ var template = [
|
||||
];
|
||||
|
||||
if (process.platform == 'darwin') {
|
||||
var name = require('electron').app.getName();
|
||||
var name = require('electron').remote.app.getName();
|
||||
template.unshift({
|
||||
label: name,
|
||||
submenu: [
|
||||
|
||||
@@ -12,6 +12,27 @@ Node.js の新しいバージョンがリリースされたとき、私たちは
|
||||
|
||||
通常、Node.js の新しい機能は V8 のアップグレードによってもたらされますが、Electron は Chrome ブラウザーに搭載されている V8 を使用しているので、新しい Node.js に入ったばかりのピカピカに新しい JavaScript 機能は Electron ではたいてい既に導入されています。
|
||||
|
||||
## ウェブページ間のデータを共有する方法は?
|
||||
|
||||
ウェブページ(レンダラープロセス)間のデータを共有するために最も単純な方法は、ブラウザで、すでに提供されているHTML5 APIを使用することです。もっとも良い方法は、[Storage API][storage]、[`localStorage`][local-storage]、[`sessionStorage`][session-storage]、[IndexedDB][indexed-db]です。
|
||||
|
||||
```javascript
|
||||
// In the main process.
|
||||
global.sharedObject = {
|
||||
someProperty: 'default value'
|
||||
};
|
||||
```
|
||||
|
||||
```javascript
|
||||
// In page 1.
|
||||
require('remote').getGlobal('sharedObject').someProperty = 'new value';
|
||||
```
|
||||
|
||||
```javascript
|
||||
// In page 2.
|
||||
console.log(require('remote').getGlobal('sharedObject').someProperty);
|
||||
```
|
||||
|
||||
## 何分か経つと、アプリの Window/tray が消えてしまいます
|
||||
|
||||
これは、Window/trayを格納するのに使用している変数がガベージコレクトされたときに発生します。
|
||||
@@ -104,3 +125,7 @@ npm uninstall -g electron
|
||||
[memory-management]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management
|
||||
[variable-scope]: https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx
|
||||
[electron-module]: https://www.npmjs.com/package/electron
|
||||
[storage]: https://developer.mozilla.org/en-US/docs/Web/API/Storage
|
||||
[local-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
|
||||
[session-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage
|
||||
[indexed-db]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
|
||||
|
||||
@@ -210,6 +210,23 @@ var window = new BrowserWindow({...});
|
||||
window.setProgressBar(0.5);
|
||||
```
|
||||
|
||||
## タスクバーでアイコンをオーバーレイする (Windows)
|
||||
|
||||
Windowsで、タスクバーボタンはアプリケーションステータスを表示するために小さなオーバーレイを使うことができます。MSDNから引用します。
|
||||
|
||||
> アイコン オーバーレイは、状況に応じた状態通知として機能し、通知領域に状態アイコンを個別に表示する必要性をなくして、情報をユーザーに伝えることを目的としています。たとえば、現在、通知領域に表示される Microsoft Office Outlook の新着メールの通知は、タスク バー ボタンのオーバーレイとして表示できるようになります。ここでも、開発サイクルの間に、アプリケーションに最適な方法を決定する必要があります。アイコン オーバーレイは、重要で長期にわたる状態や通知 (ネットワークの状態、メッセンジャーの状態、新着メールなど) を提供することを目的としています。ユーザーに対して、絶えず変化するオーバーレイやアニメーションを表示しないようにしてください。
|
||||
|
||||
__タスクバーボタンでのオーバーレイ:__
|
||||
|
||||

|
||||
|
||||
ウィンドウでオーバーレイアイコンを設定するために、[BrowserWindow.setOverlayIcon][setoverlayicon] APIを使用できます。
|
||||
|
||||
```javascript
|
||||
var window = new BrowserWindow({...});
|
||||
window.setOverlayIcon('path/to/overlay.png', 'Description for overlay');
|
||||
```
|
||||
|
||||
## Windowのファイル表示 (OS X)
|
||||
|
||||
OS Xでは、ウィンドウがrepresented fileを設定でき、タイトルバー上にファイルのアイコンを表示でき、タイトル上でCommand-クリックまたはControl-クリックをすると、パスがポップアップ表示されます。
|
||||
@@ -228,15 +245,16 @@ window.setRepresentedFilename('/etc/passwd');
|
||||
window.setDocumentEdited(true);
|
||||
```
|
||||
|
||||
[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath
|
||||
[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments
|
||||
[setusertaskstasks]: ../api/app.md#appsetusertaskstasks
|
||||
[setprogressbar]: ../api/browser-window.md#browserwindowsetprogressbarprogress
|
||||
[setrepresentedfilename]: ../api/browser-window.md#browserwindowsetrepresentedfilenamefilename
|
||||
[setdocumentedited]: ../api/browser-window.md#browserwindowsetdocumenteditededited
|
||||
[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath-os-x-windows
|
||||
[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments-os-x-windows
|
||||
[setusertaskstasks]: ../api/app.md#appsetusertaskstasks-windows
|
||||
[setprogressbar]: ../api/browser-window.md#winsetprogressbarprogress
|
||||
[setoverlayicon]: ../api/browser-window.md#winsetoverlayiconoverlay-description-windows-7
|
||||
[setrepresentedfilename]: ../api/browser-window.md#winsetrepresentedfilenamefilename-os-x
|
||||
[setdocumentedited]: ../api/browser-window.md#winsetdocumenteditededited-os-x
|
||||
[app-registration]: http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121(v=vs.85).aspx
|
||||
[unity-launcher]: https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher
|
||||
[setthumbarbuttons]: ../api/browser-window.md#browserwindowsetthumbarbuttonsbuttons
|
||||
[setthumbarbuttons]: ../api/browser-window.md#winsetthumbarbuttonsbuttons-windows-7
|
||||
[tray-balloon]: ../api/tray.md#traydisplayballoonoptions-windows
|
||||
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx
|
||||
[notification-spec]: https://developer.gnome.org/notification-spec/
|
||||
|
||||
@@ -24,6 +24,8 @@ Electron はウェブページを表示させるために Chromium を使用し
|
||||
|
||||
Electron では、メインプロセスとレンダラープロセスとのコミュニケーションをするために [ipc](../api/ipc-renderer.md) モジュールを提供しています。またそれと、RPC 形式の通信を行う [remote](../api/remote.md) モジュールもあります。
|
||||
|
||||
Electron では、メインプロセスとレンダラープロセスとのコミュニケーションをするには幾つかのほうほうがあります。メッセージを送信する[`ipcRenderer`](../api/ipc-renderer.md)モジュールと[`ipcMain`](../api/ipc-main.md)モジュールのように、RPC 形式の通信を行う[remote](../api/remote.md)モジュールです。[ウェブページ間のデータを共有する方法][share-data]にFAQエントリーがあります。
|
||||
|
||||
## Electronアプリを作成する
|
||||
|
||||
一般的に Electron アプリの構成は次のようになります:
|
||||
@@ -169,3 +171,5 @@ $ cd electron-quick-start
|
||||
# Install dependencies and run the app
|
||||
$ npm install && npm start
|
||||
```
|
||||
|
||||
[share-data]: ../faq/electron-faq.md#how-to-share-data-between-web-pages
|
||||
|
||||
@@ -41,7 +41,7 @@ var driver = new webdriver.Builder()
|
||||
.withCapabilities({
|
||||
chromeOptions: {
|
||||
// Here is the path to your Electron binary.
|
||||
binary: '/Path-to-Your-App.app/Contents/MacOS/Atom',
|
||||
binary: '/Path-to-Your-App.app/Contents/MacOS/Electron',
|
||||
}
|
||||
})
|
||||
.forBrowser('electron')
|
||||
|
||||
@@ -6,6 +6,8 @@ Electronで、Chromeブラウザーに同梱される Widevine CDMプラグイ
|
||||
|
||||
Electronは、ライセンス的な理由でWidevine CDMプラグインは同梱されません。Widevine CDMプラグインを取得するために、最初に、使用するElectronビルドのChromバージョンとアーキテクチャを合わせた公式のChromeブラウザーをインストールする必要があります。
|
||||
|
||||
__Note:__ Chromeブラウザの主要バージョンは、Electronが使用するChromeバージョンと同じでなければなりません。そうでなければ、プラグインは、`navigator.plugins`経由でロードされて表示されるにも関わらず動作しません。
|
||||
|
||||
### Windows & OS X
|
||||
|
||||
Chromeブラウザーで、`chrome://components/`を開き、 `WidevineCdm` を探し、それが最新であることを確認し、`APP_DATA/Google/Chrome/WidevineCDM/VERSION/_platform_specific/PLATFORM_ARCH/`ディレクトリからすべてのプラグインバイナリを探します。
|
||||
|
||||
@@ -30,6 +30,7 @@ Electron에 대해 자주 묻는 질문이 있습니다. 이슈를 생성하기
|
||||
* [개발자 도구 확장 기능](tutorial/devtools-extension.md)
|
||||
* [Pepper 플래시 플러그인 사용하기](tutorial/using-pepper-flash-plugin.md)
|
||||
* [Widevine CDM 플러그인 사용하기](tutorial/using-widevine-cdm-plugin.md)
|
||||
* [Headless CI 시스템에서 테스팅하기 (Travis, Jenkins)](tutorial/testing-on-headless-ci.md)
|
||||
|
||||
## 튜토리얼
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ Linux와 Windows에서는 `Command`키가 없으므로 작동하지 않습니다
|
||||
* `Control` (단축어 `Ctrl`)
|
||||
* `CommandOrControl` (단축어 `CmdOrCtrl`)
|
||||
* `Alt`
|
||||
* `Option`
|
||||
* `AltGr`
|
||||
* `Shift`
|
||||
* `Super`
|
||||
|
||||
@@ -43,5 +45,6 @@ Linux와 Windows에서는 `Command`키가 없으므로 작동하지 않습니다
|
||||
* `Escape` (단축어 `Esc`)
|
||||
* `VolumeUp`, `VolumeDown` 그리고 `VolumeMute`
|
||||
* `MediaNextTrack`, `MediaPreviousTrack`, `MediaStop` 그리고 `MediaPlayPause`
|
||||
* `PrintScreen`
|
||||
|
||||
__키코드는 `단축어`로도 사용할 수 있습니다__
|
||||
|
||||
@@ -164,7 +164,7 @@ Returns:
|
||||
기본 동작을 방지하고 인증을 승인할 수 있습니다.
|
||||
|
||||
```javascript
|
||||
session.on('certificate-error', function(event, webContents, url, error, certificate, callback) {
|
||||
app.on('certificate-error', function(event, webContents, url, error, certificate, callback) {
|
||||
if (url == "https://github.com") {
|
||||
// Verification logic.
|
||||
event.preventDefault();
|
||||
@@ -236,6 +236,10 @@ app.on('login', function(event, webContents, request, authInfo, callback) {
|
||||
|
||||
GPU가 작동하던 중 크래시가 일어났을 때 발생하는 이벤트입니다.
|
||||
|
||||
### Event: 'platform-theme-changed' _OS X_
|
||||
|
||||
시스템의 다크 모드 테마가 토글되면 발생하는 이벤트입니다.
|
||||
|
||||
## Methods
|
||||
|
||||
`app` 객체는 다음과 같은 메서드를 가지고 있습니다:
|
||||
@@ -252,14 +256,6 @@ GPU가 작동하던 중 크래시가 일어났을 때 발생하는 이벤트입
|
||||
`beforeunload` 이벤트 핸들러에서 `false`를 반환했을 때 윈도우 종료가 취소 될 수
|
||||
있습니다.
|
||||
|
||||
### `app.hide()` _OS X_
|
||||
|
||||
최소화를 하지 않고 어플리케이션의 모든 윈도우들을 숨깁니다.
|
||||
|
||||
### `app.show()` _OS X_
|
||||
|
||||
숨긴 어플리케이션 윈도우들을 다시 보이게 만듭니다. 자동으로 포커스되지 않습니다.
|
||||
|
||||
### `app.exit(exitCode)`
|
||||
|
||||
* `exitCode` Integer
|
||||
@@ -269,6 +265,19 @@ GPU가 작동하던 중 크래시가 일어났을 때 발생하는 이벤트입
|
||||
모든 윈도우는 사용자의 동의 여부에 상관없이 즉시 종료되며 `before-quit` 이벤트와
|
||||
`will-quit` 이벤트가 발생하지 않습니다.
|
||||
|
||||
### `app.focus()`
|
||||
|
||||
Linux에선, 첫 번째로 보여지는 윈도우가 포커스됩니다. OS X에선, 어플리케이션을 활성화
|
||||
앱 상태로 만듭니다. Windows에선, 어플리케이션의 첫 윈도우에 포커스 됩니다.
|
||||
|
||||
### `app.hide()` _OS X_
|
||||
|
||||
최소화를 하지 않고 어플리케이션의 모든 윈도우들을 숨깁니다.
|
||||
|
||||
### `app.show()` _OS X_
|
||||
|
||||
숨긴 어플리케이션 윈도우들을 다시 보이게 만듭니다. 자동으로 포커스되지 않습니다.
|
||||
|
||||
### `app.getAppPath()`
|
||||
|
||||
현재 어플리케이션의 디렉터리를 반환합니다.
|
||||
@@ -471,6 +480,11 @@ if (browserOptions.transparent) {
|
||||
}
|
||||
```
|
||||
|
||||
### `app.isDarkMode()` _OS X_
|
||||
|
||||
이 메서드는 시스템이 다크 모드 상태인 경우 `true`를 반환하고 아닐 경우 `false`를
|
||||
반환합니다.
|
||||
|
||||
### `app.commandLine.appendSwitch(switch[, value])`
|
||||
|
||||
Chrominum의 명령줄에 스위치를 추가합니다. `value`는 추가적인 값을 뜻하며 옵션입니다.
|
||||
|
||||
@@ -59,8 +59,8 @@ win.show();
|
||||
* `alwaysOnTop` Boolean - 윈도우이 언제나 다른 창들 위에 유지되는지 여부.
|
||||
기본값은 `false`입니다.
|
||||
* `fullscreen` Boolean - 윈도우의 전체화면 활성화 여부. 이 속성을 명시적으로
|
||||
`false`로 지정했을 경우, OS X에선 전체화면 버튼이 숨겨지거나 비활성화되고,
|
||||
Windows에선 최대화 버튼이 비활성화됩니다. 기본값은 `false` 입니다.
|
||||
`false`로 지정했을 경우, OS X에선 전체화면 버튼이 숨겨지거나 비활성됩니다. 기본값은
|
||||
`false` 입니다.
|
||||
* `fullscreenable` Boolean - OS X의 최대화/줌 버튼이 전체화면 모드 또는 윈도우
|
||||
최대화를 토글할 수 있게 할지 여부입니다. 기본값은 `true` 입니다.
|
||||
* `skipTaskbar` Boolean - 작업표시줄 어플리케이션 아이콘 표시 스킵 여부. 기본값은
|
||||
@@ -240,6 +240,14 @@ window.onbeforeunload = function(e) {
|
||||
|
||||
윈도우가 포커스를 가졌을 때 발생하는 이벤트입니다.
|
||||
|
||||
### Event: 'show'
|
||||
|
||||
윈도우가 보여진 상태일 때 발생하는 이벤트입니다.
|
||||
|
||||
### Event: 'hide'
|
||||
|
||||
윈도우가 숨겨진 상태일 때 발생하는 이벤트입니다.
|
||||
|
||||
### Event: 'maximize'
|
||||
|
||||
윈도우가 최대화됐을 때 발생하는 이벤트입니다.
|
||||
@@ -575,17 +583,17 @@ var win = new BrowserWindow({ width: 800, height: 600 });
|
||||
사용자에 의해 윈도우를 최대화시킬 수 있는지 여부를 반환합니다. Linux에선 항상 `true`를
|
||||
반환합니다.
|
||||
|
||||
### `win.setFullScreenable(fullscreenable)` _OS X_
|
||||
### `win.setFullScreenable(fullscreenable)`
|
||||
|
||||
* `fullscreenable` Boolean
|
||||
|
||||
최대화/줌 버튼이 전체화면 모드 또는 윈도우 최대화를 토글할 수 있게 할지 여부를
|
||||
지정합니다. Windows와 Linux에선 아무 일도 일어나지 않습니다.
|
||||
지정합니다.
|
||||
|
||||
### `win.isFullScreenable()` _OS X_
|
||||
### `win.isFullScreenable()`
|
||||
|
||||
최대화/줌 버튼이 전체화면 모드 또는 윈도우 최대화를 토글할 수 있게 할지 여부를
|
||||
반환합니다. Windows와 Linux에선 항상 `true`를 반환합니다.
|
||||
반환합니다.
|
||||
|
||||
### `win.setClosable(closable)` _OS X_ _Windows_
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ var template = [
|
||||
];
|
||||
|
||||
if (process.platform == 'darwin') {
|
||||
var name = require('electron').app.getName();
|
||||
var name = require('electron').remote.app.getName();
|
||||
template.unshift({
|
||||
label: name,
|
||||
submenu: [
|
||||
@@ -223,7 +223,9 @@ Linux에선 각 창의 상단에 표시됩니다.
|
||||
`action`을 어플리케이션의 first responder에 전달합니다. 이 메서드는 Cocoa 메뉴
|
||||
동작을 에뮬레이트 하는데 사용되며 보통 `MenuItem`의 `role` 속성에 사용됩니다.
|
||||
|
||||
**참고:** 이 메서드는 OS X에서만 사용할 수 있습니다.
|
||||
OS X의 네이티브 액션에 대해 자세히 알아보려면
|
||||
[OS X Cocoa Event Handling Guide](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/EventOverview/EventArchitecture/EventArchitecture.html#//apple_ref/doc/uid/10000060i-CH3-SW7)
|
||||
문서를 참고하세요.
|
||||
|
||||
### `Menu.buildFromTemplate(template)`
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ app.on('ready', function() {
|
||||
## 분리 할당
|
||||
|
||||
만약 CoffeeScript나 Babel을 사용하고 있다면, 빌트인 모듈을 사용할 때
|
||||
[분리 할당][desctructuring-assignment]을 통해 직관적으로 사용할 수 있습니다:
|
||||
[분리 할당][destructuring-assignment]을 통해 직관적으로 사용할 수 있습니다:
|
||||
|
||||
```javascript
|
||||
const {app, BrowserWindow} = require('electron')
|
||||
@@ -78,5 +78,5 @@ require('electron').hideInternalModules()
|
||||
```
|
||||
|
||||
[gui]: https://en.wikipedia.org/wiki/Graphical_user_interface
|
||||
[desctructuring-assignment]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
|
||||
[destructuring-assignment]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
|
||||
[issue-387]: https://github.com/atom/electron/issues/387
|
||||
|
||||
@@ -421,10 +421,12 @@ var currentURL = win.webContents.getURL();
|
||||
|
||||
CSS 코드를 현재 웹 페이지에 삽입합니다.
|
||||
|
||||
### `webContents.executeJavaScript(code[, userGesture])`
|
||||
### `webContents.executeJavaScript(code[, userGesture, callback])`
|
||||
|
||||
* `code` String
|
||||
* `userGesture` Boolean (optional)
|
||||
* `callback` Function (optional) - 스크립트의 실행이 완료되면 호출됩니다.
|
||||
* `result`
|
||||
|
||||
페이지에서 자바스크립트 코드를 실행합니다.
|
||||
|
||||
@@ -646,14 +648,14 @@ mainWindow.webContents.on('devtools-opened', function() {
|
||||
|
||||
개발자 도구가 열려있는지 여부를 반환합니다.
|
||||
|
||||
### `webContents.toggleDevTools()`
|
||||
|
||||
개발자 도구를 토글합니다.
|
||||
|
||||
### `webContents.isDevToolsFocused()`
|
||||
|
||||
개발자 도구에 포커스 되어있는지 여부를 반환합니다.
|
||||
|
||||
### `webContents.toggleDevTools()`
|
||||
|
||||
개발자 도구를 토글합니다.
|
||||
|
||||
### `webContents.inspectElement(x, y)`
|
||||
|
||||
* `x` Integer
|
||||
@@ -756,11 +758,8 @@ Input `event`를 웹 페이지로 전송합니다.
|
||||
|
||||
키보드 이벤트들에 대해서는 `event` 객체는 다음 속성들을 사용할 수 있습니다:
|
||||
|
||||
* `keyCode` Char or String (**required**) - 키보드 이벤트로 보내지는 문자. 단일
|
||||
UTF-8 문자를 사용할 수 있고 이벤트를 발생시키는 다음 키 중 하나를 포함할 수 있습니다:
|
||||
`enter`, `backspace`, `delete`, `tab`, `escape`, `control`, `alt`, `shift`,
|
||||
`end`, `home`, `insert`, `left`, `up`, `right`, `down`, `pageUp`, `pageDown`,
|
||||
`printScreen`
|
||||
* `keyCode` String (**required**) - 키보드 이벤트가 발생할 때 보내질 문자.
|
||||
[Accelerator](accelerator.md)의 올바른 키 코드만 사용해야 합니다.
|
||||
|
||||
마우스 이벤트들에 대해서는 `event` 객체는 다음 속성들을 사용할 수 있습니다:
|
||||
|
||||
@@ -832,6 +831,10 @@ win.webContents.on('did-finish-load', function() {
|
||||
|
||||
이 webContents에서 사용하는 [session](session.md) 객체를 반환합니다.
|
||||
|
||||
### `webContents.hostWebContents`
|
||||
|
||||
현재 `WebContents`를 소유하는 `WebContents`를 반환합니다.
|
||||
|
||||
### `webContents.devToolsWebContents`
|
||||
|
||||
이 `WebContents`에 대한 개발자 도구의 `WebContents`를 가져옵니다.
|
||||
|
||||
@@ -272,12 +272,14 @@ Webview에 웹 페이지 `url`을 로드합니다. `url`은 `http://`, `file://`
|
||||
|
||||
페이지에 CSS를 삽입합니다.
|
||||
|
||||
### `<webview>.executeJavaScript(code[, userGesture])`
|
||||
### `<webview>.executeJavaScript(code[, userGesture, callback])`
|
||||
|
||||
* `code` String
|
||||
* `userGesture` Boolean
|
||||
* `callback` Function (optional) - 스크립트의 실행이 완료되면 호출됩니다.
|
||||
* `result`
|
||||
|
||||
페이지에서 자바스크립트 `code`를 실행합니다.
|
||||
페이지에서 자바스크립트 코드를 실행합니다.
|
||||
|
||||
만약 `userGesture`가 `true`로 설정되어 있으면 페이지에 유저 제스쳐 컨텍스트를 만듭니다.
|
||||
이 옵션을 활성화 시키면 `requestFullScreen`와 같은 HTML API에서 유저의 승인을
|
||||
@@ -427,6 +429,10 @@ Webview 페이지를 PDF 형식으로 인쇄합니다.
|
||||
`event` 객체에 대해 자세히 알아보려면 [webContents.sendInputEvent](web-contents.md##webcontentssendinputeventevent)를
|
||||
참고하세요.
|
||||
|
||||
### `<webview>.getWebContents()`
|
||||
|
||||
이 `webview`에 해당하는 [WebContents](web-contents.md)를 반환합니다.
|
||||
|
||||
## DOM 이벤트
|
||||
|
||||
`webview` 태그는 다음과 같은 DOM 이벤트를 가지고 있습니다:
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
이 가이드는 Electron의 코딩 스타일에 관해 설명합니다.
|
||||
|
||||
`npm run lint`를 실행하여 `cpplint`와 `eslint`를 통해 어떤 코딩 스타일 이슈를 확인할
|
||||
수 있습니다.
|
||||
|
||||
## C++과 Python
|
||||
|
||||
C++과 Python 스크립트는 Chromium의
|
||||
@@ -18,17 +21,24 @@ C++ 코드는 많은 Chromium의 추상화와 타입을 사용합니다. 따라
|
||||
자동으로 메모리에서 할당을 해제합니다. 스마트 포인터와 같습니다) 그리고 로깅 메커니즘
|
||||
등을 언급하고 있습니다.
|
||||
|
||||
## CoffeeScript
|
||||
|
||||
CoffeeScript의 경우 GitHub의
|
||||
[스타일 가이드](https://github.com/styleguide/javascript)를 기본으로 따릅니다.
|
||||
그리고 추가로 다음 규칙을 따릅니다:
|
||||
## JavaScript
|
||||
|
||||
* 하드 탭(hard tabs) 대신 소프트 탭(2 spaces) 들여쓰기를 사용합니다.
|
||||
* 항상 구문의 끝은 `;`으로 마쳐야 합니다.
|
||||
* Google의 코딩 스타일에도 맞추기 위해 파일의 끝에는 **절대** 개행을 삽입해선 안됩니다.
|
||||
* 파일 이름의 공백은 `_`대신에 `-`을 사용하여야 합니다. 예를 들어
|
||||
`file_name.coffee`를 `file-name.coffee`로 고쳐야합니다. 왜냐하면
|
||||
`file_name.js`를 `file-name.js`로 고쳐야합니다. 왜냐하면
|
||||
[github/atom](https://github.com/github/atom)에서 사용되는 모듈의 이름은 보통
|
||||
`module-name` 형식이기 때문입니다. 이 규칙은 '.coffee' 파일에만 적용됩니다.
|
||||
`module-name` 형식이기 때문입니다. 이 규칙은 '.js' 파일에만 적용됩니다.
|
||||
* 적절한 곳에 새로운 ES6/ES2015 문법을 사용해도 됩니다.
|
||||
* [`const`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const)
|
||||
는 requires와 다른 상수에 사용합니다
|
||||
* [`let`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let)
|
||||
은 변수를 정의할 때 사용합니다
|
||||
* [Arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
|
||||
는 `function () { }` 표현 대신에 사용합니다
|
||||
* [Template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals)
|
||||
는 `+`로 문자열을 합치는 대신 사용합니다.
|
||||
|
||||
## API 이름
|
||||
|
||||
|
||||
@@ -239,22 +239,20 @@ __Audacious의 런처 숏컷:__
|
||||
|
||||

|
||||
|
||||
## Taskbar progress 기능 (Windows & Unity)
|
||||
## 작업 표시줄 안의 프로그래스 바 (Windows, OS X, Unity)
|
||||
|
||||
Windows에선 태스크바의 어플리케이션 버튼에 progress bar를 추가할 수 있습니다.
|
||||
Windows에선 작업 표시줄의 어플리케이션 버튼에 프로그래스 바를 추가할 수 있습니다.
|
||||
이 기능은 사용자가 어플리케이션의 창을 열지 않고도 어플리케이션의 작업의 상태 정보를
|
||||
시각적으로 보여줄 수 있도록 해줍니다.
|
||||
|
||||
또한 Unity DE도 런처에 progress bar를 부착할 수 있습니다.
|
||||
OS X에선 프로그래스바가 dock 아이콘의 일부에 표시됩니다.
|
||||
|
||||
__태스크바 버튼의 progress bar:__
|
||||
또한 Unity DE도 런처에 프로그래스 바를 부착할 수 있습니다.
|
||||
|
||||
__작업 표시줄 버튼의 프로그래스 바:__
|
||||
|
||||

|
||||
|
||||
__Unity 런처의 progress bar:__
|
||||
|
||||

|
||||
|
||||
이 기능은 [BrowserWindow.setProgressBar][setprogressbar] API를 사용하여 구현할 수
|
||||
있습니다:
|
||||
|
||||
|
||||
58
docs-translations/ko-KR/tutorial/testing-on-headless-ci.md
Normal file
58
docs-translations/ko-KR/tutorial/testing-on-headless-ci.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Headless CI 시스템에서 테스팅하기 (Travis, Jenkins) (Travis CI, Jenkins)
|
||||
|
||||
Chromium을 기반으로 한 Electron은 작업을 위해 디스플레이 드라이버가 필요합니다.
|
||||
만약 Chromium이 디스플레이 드라이버를 찾기 못한다면, Electron은 그대로 실행에
|
||||
실패할 것입니다. 따라서 실행하는 방법에 관계없이 모든 테스트를 실행하지 못하게 됩니다.
|
||||
Electron 기반 어플리케이션을 Travis, Circle, Jenkins 또는 유사한 시스템에서 테스팅을
|
||||
진행하려면 약간의 설정이 필요합니다. 요점만 말하자면, 가상 디스플레이 드라이버가
|
||||
필요합니다.
|
||||
|
||||
## 가상 디스플레이 드라이버 설정
|
||||
|
||||
먼저, [Xvfb](https://en.wikipedia.org/wiki/Xvfb)를 설치합니다. 이것은 X11
|
||||
디스플레이 서버 프로토콜의 구현이며 모든 그래픽 작업을 스크린 출력없이 인-메모리에서
|
||||
수행하는 가상 프레임버퍼입니다. 정확히 우리가 필요로 하는 것입니다.
|
||||
|
||||
그리고, 가상 xvfb 스크린을 생성하고 DISPLAY라고 불리우는 환경 변수를 지정합니다.
|
||||
Electron의 Chromium은 자동적으로 `$DISPLAY` 변수를 찾습니다. 따라서 앱의 추가적인
|
||||
다른 설정이 필요하지 않습니다. 이러한 작업은 Paul Betts의
|
||||
[xfvb-maybe](https://github.com/paulcbetts/xvfb-maybe)를 통해 자동화 할 수
|
||||
있습니다: `xfvb-maybe`를 테스트 커맨드 앞에 추가하고 현재 시스템에서 요구하면
|
||||
이 작은 툴이 자동적으로 xfvb를 설정합니다. Windows와 Mac OS X에선 간단히 아무 작업도
|
||||
하지 않습니다.
|
||||
|
||||
```
|
||||
## Windows와 OS X에선, 그저 electron-mocha를 호출합니다
|
||||
## Linux에선, 현재 headless 환경에 있는 경우
|
||||
## xvfb-run electron-mocha ./test/*.js와 같습니다
|
||||
xvfb-maybe electron-mocha ./test/*.js
|
||||
```
|
||||
|
||||
### Travis CI
|
||||
|
||||
Travis에선, `.travis.yml`이 대충 다음과 같이 되어야 합니다:
|
||||
|
||||
```
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- xvfb
|
||||
|
||||
install:
|
||||
- export DISPLAY=':99.0'
|
||||
- Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
|
||||
```
|
||||
|
||||
### Jenkins
|
||||
|
||||
Jenkins는 [Xfvb 플러그인이 존재합니다](https://wiki.jenkins-ci.org/display/JENKINS/Xvfb+Plugin).
|
||||
|
||||
### Circle CI
|
||||
|
||||
Circle CI는 멋지게도 이미 xvfb와 `$DISPLY` 변수가 준비되어 있습니다. 따라서
|
||||
[추가적인 설정이 필요하지](https://circleci.com/docs/environment#browsers) 않습니다.
|
||||
|
||||
### AppVeyor
|
||||
|
||||
AppVeyor는 Windows에서 작동하기 때문에 Selenium, Chromium, Electron과 그 비슷한
|
||||
툴들을 복잡한 과정 없이 모두 지원합니다. - 설정이 필요하지 않습니다.
|
||||
@@ -8,6 +8,10 @@ Electron은 라이센스상의 문제로 Widevine CDM 플러그인을 직접 제
|
||||
따라서 플러그인을 얻으려면 먼저 사용할 Electron 빌드의 아키텍쳐와 버전에 맞춰 공식
|
||||
Chrome 브라우저를 설치해야 합니다.
|
||||
|
||||
__참고:__ Chrome 브라우저의 메이저 버전은 Electron에서 사용하는 Chrome 버전과
|
||||
같습니다, 만약 그렇지 않다면 `navigator.plugins`가 로드됐더라도 정상적으로 작동하지
|
||||
않습니다.
|
||||
|
||||
### Windows & OS X
|
||||
|
||||
Chrome 브라우저에서 `chrome://components/`를 열고 `WidevineCdm`을 찾은 후 확실히
|
||||
|
||||
67
docs-translations/pt-BR/api/window-open.md
Normal file
67
docs-translations/pt-BR/api/window-open.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# The `window.open` function
|
||||
|
||||
Qunado `window.open` é chamado para criar uma nova janela de uma pagina web uma nova instância de `BrowserWindow` será criado para a `url` e um proxy será devolvido para o `windows.open`, para permitir que a página tenha limitado controle sobre ele.
|
||||
|
||||
O proxy tem funcionalidade limitada padrão implementada para ser compatível com as páginas web tradicionais.
|
||||
Para controle total da nova janela você deveria criar um `BrowserWindow` diretamente
|
||||
|
||||
|
||||
The newly created `BrowserWindow` will inherit parent window's options by
|
||||
default, to override inherited options you can set them in the `features`
|
||||
string.
|
||||
|
||||
O recém-criado `BrowserWindow` herdará as opções da janela pai por padrão, para substituir as opções herdadas você pode definilos no `features`(string).
|
||||
### `window.open(url[, frameName][, features])`
|
||||
|
||||
* `url` String
|
||||
* `frameName` String (opcional)
|
||||
* `features` String (opcional)
|
||||
|
||||
Cria uma nova janela e retorna uma instância da classe `BrowserWindowProxy'.
|
||||
|
||||
A string `features` segue o formato padrão do browser, mas cada recurso (feature) tem que ser um campo de opções do `BrowserWindow`.
|
||||
|
||||
### `window.opener.postMessage(message, targetOrigin)`
|
||||
|
||||
* `message` String
|
||||
* `targetOrigin` String
|
||||
|
||||
Envia uma mensagem para a janela pai com a origem especificada ou `*` preferência de origem não especificada.
|
||||
Sends a message to the parent window with the specified origin or `*`
|
||||
origin preference.
|
||||
|
||||
## Class: BrowserWindowProxy
|
||||
|
||||
O objeto `BrowserWindowProxy` é retornado de `window.open` e fornece uma funcionalidade limitada para a janela filha.
|
||||
|
||||
### `BrowserWindowProxy.blur()`
|
||||
|
||||
Remove o foco da janela filha.
|
||||
|
||||
### `BrowserWindowProxy.close()`
|
||||
|
||||
Forçadamente fecha a janela filha sem chamar o evento de descarregamento.
|
||||
|
||||
### `BrowserWindowProxy.closed`
|
||||
|
||||
Define como true após a janela filha ficar fechada.
|
||||
|
||||
### `BrowserWindowProxy.eval(code)`
|
||||
|
||||
* `code` String
|
||||
|
||||
Avalia o código na jánela filha.
|
||||
|
||||
### `BrowserWindowProxy.focus()`
|
||||
|
||||
Concentra-se a janela filha (traz a janela para frente)
|
||||
### `BrowserWindowProxy.postMessage(message, targetOrigin)`
|
||||
|
||||
* `message` String
|
||||
* `targetOrigin` String
|
||||
|
||||
Sends a message to the child window with the specified origin or `*` for no
|
||||
origin preference.
|
||||
|
||||
In addition to these methods, the child window implements `window.opener` object
|
||||
with no properties and a single method.
|
||||
@@ -1,13 +1,19 @@
|
||||
## 常见问题
|
||||
|
||||
+ [Electron 常见问题](faq/electron-faq.md)
|
||||
|
||||
## 向导
|
||||
|
||||
* [支持平台](tutorial/supported-platforms.md)
|
||||
* [应用部署](tutorial/application-distribution.md)
|
||||
* [应用打包](tutorial/application-packaging.md)
|
||||
* [使用原生模块](tutorial/using-native-node-modules.md)
|
||||
* [分发应用](tutorial/application-distribution.md)
|
||||
* [提交应用到 Mac App Store](tutorial/mac-app-store-submission-guide.md)
|
||||
* [打包应用](tutorial/application-packaging.md)
|
||||
* [使用 Node 原生模块](tutorial/using-native-node-modules.md)
|
||||
* [主进程调试](tutorial/debugging-main-process.md)
|
||||
* [使用 Selenium 和 WebDriver](tutorial/using-selenium-and-webdriver.md)
|
||||
* [调试工具扩展](tutorial/devtools-extension.md)
|
||||
* [使用 PepperFlash 插件](tutorial/using-pepper-flash-plugin.md)
|
||||
* [使用开发人员工具扩展](tutorial/devtools-extension.md)
|
||||
* [使用 Pepper Flash 插件](tutorial/using-pepper-flash-plugin.md)
|
||||
* [使用 Widevine CDM 插件](tutorial/using-widevine-cdm-plugin.md)
|
||||
|
||||
## 教程
|
||||
|
||||
@@ -19,53 +25,55 @@
|
||||
|
||||
* [简介](api/synopsis.md)
|
||||
* [进程对象](api/process.md)
|
||||
* [支持的Chrome命令行开关](api/chrome-command-line-switches.md)
|
||||
* [支持的 Chrome 命令行开关](api/chrome-command-line-switches.md)
|
||||
* [环境变量](api/environment-variables.md)
|
||||
|
||||
定制的DOM元素:
|
||||
自定义的 DOM 元素:
|
||||
|
||||
* [`File`对象](api/file-object.md)
|
||||
* [`<webview>`标签](api/web-view-tag.md)
|
||||
* [`window.open`函数](api/window-open.md)
|
||||
* [`File` 对象](api/file-object.md)
|
||||
* [`<webview>` 标签](api/web-view-tag.md)
|
||||
* [`window.open` 函数](api/window-open.md)
|
||||
|
||||
主进程可用的模块:
|
||||
在主进程内可用的模块:
|
||||
|
||||
* [app](api/app.md)
|
||||
* [auto-updater](api/auto-updater.md)
|
||||
* [browser-window](api/browser-window.md)
|
||||
* [content-tracing](api/content-tracing.md)
|
||||
* [autoUpdater](api/auto-updater.md)
|
||||
* [BrowserWindow](api/browser-window.md)
|
||||
* [contentTracing](api/content-tracing.md)
|
||||
* [dialog](api/dialog.md)
|
||||
* [global-shortcut](api/global-shortcut.md)
|
||||
* [ipc (main process)](api/ipc-main-process.md)
|
||||
* [menu](api/menu.md)
|
||||
* [menu-item](api/menu-item.md)
|
||||
* [power-monitor](api/power-monitor.md)
|
||||
* [power-save-blocker](api/power-save-blocker.md)
|
||||
* [globalShortcut](api/global-shortcut.md)
|
||||
* [ipcMain](api/ipc-main.md)
|
||||
* [Menu](api/menu.md)
|
||||
* [MenuItem](api/menu-item.md)
|
||||
* [powerMonitor](api/power-monitor.md)
|
||||
* [powerSaveBlocker](api/power-save-blocker.md)
|
||||
* [protocol](api/protocol.md)
|
||||
* [session](api/session.md)
|
||||
* [webContents](api/web-contents.md)
|
||||
* [tray](api/tray.md)
|
||||
* [Tray](api/tray.md)
|
||||
|
||||
渲染进程(网页)可用的模块:
|
||||
在渲染进程(网页)内可用的模块:
|
||||
|
||||
* [ipc (renderer)](api/ipc-renderer.md)
|
||||
* [desktopCapturer](api/desktop-capturer.md)
|
||||
* [ipcRenderer](api/ipc-renderer.md)
|
||||
* [remote](api/remote.md)
|
||||
* [web-frame](api/web-frame.md)
|
||||
* [webFrame](api/web-frame.md)
|
||||
|
||||
两种进程都可用的模块:
|
||||
在两种进程中都可用的模块:
|
||||
|
||||
* [clipboard](api/clipboard.md)
|
||||
* [crash-reporter](api/crash-reporter.md)
|
||||
* [native-image](api/native-image.md)
|
||||
* [crashReporter](api/crash-reporter.md)
|
||||
* [nativeImage](api/native-image.md)
|
||||
* [screen](api/screen.md)
|
||||
* [shell](api/shell.md)
|
||||
|
||||
## 开发
|
||||
|
||||
* [编码规范](development/coding-style.md)
|
||||
* [代码规范](development/coding-style.md)
|
||||
* [源码目录结构](development/source-code-directory-structure.md)
|
||||
* [与 NW.js (原名 node-webkit) 在技术上的差异](development/atom-shell-vs-node-webkit.md)
|
||||
* [构建系统概况](development/build-system-overview.md)
|
||||
* [构建步骤 (Mac)](development/build-instructions-mac.md)
|
||||
* [构建步骤 (Windows)](development/build-instructions-windows.md)
|
||||
* [构建步骤 (Linux)](development/build-instructions-linux.md)
|
||||
* [在调试中使用 SymbolServer](development/setting-up-symbol-server.md)
|
||||
* [与 NW.js(原 node-webkit)在技术上的差异](development/atom-shell-vs-node-webkit.md)
|
||||
* [构建系统概览](development/build-system-overview.md)
|
||||
* [构建步骤(Mac)](development/build-instructions-mac.md)
|
||||
* [构建步骤(Windows)](development/build-instructions-windows.md)
|
||||
* [构建步骤(Linux)](development/build-instructions-linux.md)
|
||||
* [在调试中使用 Symbol Server](development/setting-up-symbol-server.md)
|
||||
|
||||
@@ -1,46 +1,43 @@
|
||||
# Accelerator
|
||||
|
||||
An accelerator is a string that represents a keyboard shortcut. It can contain
|
||||
multiple modifiers and key codes, combined by the `+` character.
|
||||
一个 `Accelerator` 是一个表示某个快捷键组合的字符串。它包含了用 `+` 连接的若干个按键。
|
||||
|
||||
Examples:
|
||||
例如:
|
||||
|
||||
* `Command+A`
|
||||
* `Ctrl+Shift+Z`
|
||||
|
||||
## Platform notice
|
||||
## 运行平台相关的提示
|
||||
|
||||
On Linux and Windows, the `Command` key does not have any effect so
|
||||
use `CommandOrControl` which represents `Command` on OS X and `Control` on
|
||||
Linux and Windows to define some accelerators.
|
||||
在 Linux 和 Windows 上,`Command` 键并不存在,因此我们通常用 `CommandOrControl` 来表示“在 OS X 下为 `Command` 键,但在
|
||||
Linux 和 Windows 下为 `Control` 键。
|
||||
|
||||
The `Super` key is mapped to the `Windows` key on Windows and Linux and
|
||||
`Cmd` on OS X.
|
||||
`Super` 键是指 Linux 和 Windows 上的 `Windows` 键,但是在 OS X 下为 `Command` 键。
|
||||
|
||||
## Available modifiers
|
||||
## 可用的功能按键
|
||||
|
||||
* `Command` (or `Cmd` for short)
|
||||
* `Control` (or `Ctrl` for short)
|
||||
* `CommandOrControl` (or `CmdOrCtrl` for short)
|
||||
* `Command`(缩写为 `Cmd`)
|
||||
* `Control`(缩写为 `Ctrl`)
|
||||
* `CommandOrControl`(缩写为 `CmdOrCtrl`)
|
||||
* `Alt`
|
||||
* `Shift`
|
||||
* `Super`
|
||||
|
||||
## Available key codes
|
||||
## 可用的普通按键
|
||||
|
||||
* `0` to `9`
|
||||
* `A` to `Z`
|
||||
* `F1` to `F24`
|
||||
* Punctuations like `~`, `!`, `@`, `#`, `$`, etc.
|
||||
* `0` 到 `9`
|
||||
* `A` 到 `Z`
|
||||
* `F1` 到 `F24`
|
||||
* 类似与 `~`、`!`、`@`、`#`、`$` 的标点符号。
|
||||
* `Plus`
|
||||
* `Space`
|
||||
* `Backspace`
|
||||
* `Delete`
|
||||
* `Insert`
|
||||
* `Return` (or `Enter` as alias)
|
||||
* `Up`, `Down`, `Left` and `Right`
|
||||
* `Home` and `End`
|
||||
* `PageUp` and `PageDown`
|
||||
* `Escape` (or `Esc` for short)
|
||||
* `VolumeUp`, `VolumeDown` and `VolumeMute`
|
||||
* `MediaNextTrack`, `MediaPreviousTrack`, `MediaStop` and `MediaPlayPause`
|
||||
* `Return`(和 `Enter` 等同)
|
||||
* `Up`、`Down`、`Left` 和 `Right`
|
||||
* `Home` 和 `End`
|
||||
* `PageUp` 和 `PageDown`
|
||||
* `Escape`(缩写为 `Esc`)
|
||||
* `VolumeUp`、`VolumeDown` 和 `VolumeMute`
|
||||
* `MediaNextTrack`、`MediaPreviousTrack`、`MediaStop` 和 `MediaPlayPause`
|
||||
|
||||
@@ -11,11 +11,11 @@ app.on('window-all-closed', function() {
|
||||
});
|
||||
```
|
||||
|
||||
## 事件
|
||||
## 事件列表
|
||||
|
||||
`app` 对象会触发以下的事件:
|
||||
|
||||
### 事件: 'will-finish-launching'
|
||||
### 事件:'will-finish-launching'
|
||||
|
||||
当应用程序完成基础的启动的时候被触发。在 Windows 和 Linux 中,
|
||||
`will-finish-launching` 事件与 `ready` 事件是相同的; 在 OS X 中,
|
||||
@@ -24,11 +24,11 @@ app.on('window-all-closed', function() {
|
||||
|
||||
在大多数的情况下,你应该只在 `ready` 事件处理器中完成所有的业务。
|
||||
|
||||
### 事件: 'ready'
|
||||
### 事件:'ready'
|
||||
|
||||
当 Electron 完成初始化时被触发。
|
||||
|
||||
### 事件: 'window-all-closed'
|
||||
### 事件:'window-all-closed'
|
||||
|
||||
当所有的窗口都被关闭时触发。
|
||||
|
||||
@@ -36,20 +36,20 @@ app.on('window-all-closed', function() {
|
||||
或者开发者调用了 `app.quit()` ,Electron 将会先尝试关闭所有的窗口再触发 `will-quit` 事件,
|
||||
在这种情况下 `window-all-closed` 不会被触发。
|
||||
|
||||
### 事件: 'before-quit'
|
||||
### 事件:'before-quit'
|
||||
|
||||
返回:
|
||||
|
||||
* `event` 事件
|
||||
* `event` Event
|
||||
|
||||
在应用程序开始关闭它的窗口的时候被触发。
|
||||
调用 `event.preventDefault()` 将会阻止终止应用程序的默认行为。
|
||||
|
||||
### 事件: 'will-quit'
|
||||
### 事件:'will-quit'
|
||||
|
||||
返回:
|
||||
|
||||
* `event` 事件
|
||||
* `event` Event
|
||||
|
||||
当所有的窗口已经被关闭,应用即将退出时被触发。
|
||||
调用 `event.preventDefault()` 将会阻止终止应用程序的默认行为。
|
||||
@@ -57,20 +57,20 @@ app.on('window-all-closed', function() {
|
||||
你可以在 `window-all-closed` 事件的描述中看到 `will-quit` 事件
|
||||
和 `window-all-closed` 事件的区别。
|
||||
|
||||
### 事件: 'quit'
|
||||
### 事件:'quit'
|
||||
返回:
|
||||
|
||||
* `event` 事件
|
||||
* `exitCode` 整数
|
||||
* `event` Event
|
||||
* `exitCode` Integer
|
||||
|
||||
当应用程序正在退出时触发。
|
||||
|
||||
### 事件: 'open-file' _OS X_
|
||||
### 事件:'open-file' _OS X_
|
||||
|
||||
返回:
|
||||
|
||||
* `event` 事件
|
||||
* `path` 字符串
|
||||
* `event` Event
|
||||
* `path` String
|
||||
|
||||
当用户想要在应用中打开一个文件时触发。`open-file` 事件常常在应用已经打开并且系统想要再次使用应用打开文件时被触发。
|
||||
`open-file` 也会在一个文件被拖入 dock 且应用还没有运行的时候被触发。
|
||||
@@ -78,73 +78,74 @@ app.on('window-all-closed', function() {
|
||||
|
||||
如果你想处理这个事件,你应该调用 `event.preventDefault()` 。
|
||||
在 Windows系统中, 你需要通过解析 process.argv 来获取文件路径。
|
||||
### 事件: 'open-url' _OS X_
|
||||
|
||||
### 事件:'open-url' _OS X_
|
||||
|
||||
返回:
|
||||
|
||||
* `event` 事件
|
||||
* `url` 字符串
|
||||
* `event` Event
|
||||
* `url` String
|
||||
|
||||
当用户想要在应用中打开一个url的时候被触发。URL格式必须要提前标识才能被你的应用打开。
|
||||
|
||||
如果你想处理这个事件,你应该调用 `event.preventDefault()` 。
|
||||
|
||||
### 事件: 'activate' _OS X_
|
||||
### 事件:'activate' _OS X_
|
||||
|
||||
返回:
|
||||
|
||||
* `event` 事件
|
||||
* `hasVisibleWindows` 布尔值
|
||||
* `event` Event
|
||||
* `hasVisibleWindows` Boolean
|
||||
|
||||
当应用被激活时触发,常用于点击应用的 dock 图标的时候。
|
||||
|
||||
### 事件: 'browser-window-blur'
|
||||
### 事件:'browser-window-blur'
|
||||
|
||||
返回:
|
||||
|
||||
* `event` 事件
|
||||
* `window` 浏览器窗口
|
||||
* `event` Event
|
||||
* `window` BrowserWindow
|
||||
|
||||
当一个 [浏览器窗口](browser-window.md) 失去焦点的时候触发。
|
||||
当一个 [BrowserWindow](browser-window.md) 失去焦点的时候触发。
|
||||
|
||||
### 事件: 'browser-window-focus'
|
||||
### 事件:'browser-window-focus'
|
||||
|
||||
返回:
|
||||
|
||||
* `event` 事件
|
||||
* `window` 浏览器窗口
|
||||
* `event` Event
|
||||
* `window` BrowserWindow
|
||||
|
||||
当一个 [浏览器窗口](browser-window.md) 获得焦点的时候触发。
|
||||
当一个 [BrowserWindow](browser-window.md) 获得焦点的时候触发。
|
||||
|
||||
### 事件: 'browser-window-created'
|
||||
### 事件:'browser-window-created'
|
||||
|
||||
返回:
|
||||
|
||||
* `event` 事件
|
||||
* `window` 浏览器窗口
|
||||
* `event` Event
|
||||
* `window` BrowserWindow
|
||||
|
||||
当一个 [浏览器窗口](browser-window.md) 被创建的时候触发。
|
||||
当一个 [BrowserWindow](browser-window.md) 被创建的时候触发。
|
||||
|
||||
### 事件: 'certificate-error'
|
||||
### 事件:'certificate-error'
|
||||
|
||||
返回:
|
||||
|
||||
* `event` 事件
|
||||
* `webContents` [web组件](web-contents.md)
|
||||
* `url` 字符串
|
||||
* `certificateList` 对象
|
||||
* `data` PEM 编码数据
|
||||
* `issuerName` 发行者的公有名称
|
||||
* `callback` 函数
|
||||
* `event` Event
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
* `url` String - URL 地址
|
||||
* `error` String - 错误码
|
||||
* `certificate` Object
|
||||
* `data` Buffer - PEM 编码数据
|
||||
* `issuerName` String - 发行者的公有名称
|
||||
* `callback` Function
|
||||
|
||||
Emitted when failed to verify the `certificate` for `url`, to trust the
|
||||
certificate you should prevent the default behavior with
|
||||
`event.preventDefault()` and call `callback(true)`.
|
||||
当对 `url` 验证 `certificate` 证书失败的时候触发,如果需要信任这个证书,你需要阻止默认行为 `event.preventDefault()` 并且
|
||||
调用 `callback(true)`。
|
||||
|
||||
```javascript
|
||||
session.on('certificate-error', function(event, webContents, url, error, certificate, callback) {
|
||||
if (url == "https://github.com") {
|
||||
// Verification logic.
|
||||
// 验证逻辑。
|
||||
event.preventDefault();
|
||||
callback(true);
|
||||
} else {
|
||||
@@ -153,37 +154,37 @@ session.on('certificate-error', function(event, webContents, url, error, certifi
|
||||
});
|
||||
```
|
||||
|
||||
### 事件: 'select-client-certificate'
|
||||
### 事件:'select-client-certificate'
|
||||
|
||||
|
||||
返回:
|
||||
|
||||
* `event` 事件
|
||||
* `webContents` [web组件](web-contents.md)
|
||||
* `url` 字符串
|
||||
* `certificateList` 对象
|
||||
* `data` PEM 编码数据
|
||||
* `issuerName` 发行者的公有名称
|
||||
* `callback` 函数
|
||||
* `event` Event
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
* `url` String - URL 地址
|
||||
* `certificateList` [Object]
|
||||
* `data` Buffer - PEM 编码数据
|
||||
* `issuerName` String - 发行者的公有名称
|
||||
* `callback` Function
|
||||
|
||||
当一个客户端认证被请求的时候被触发。
|
||||
|
||||
The `url` corresponds to the navigation entry requesting the client certificate
|
||||
and `callback` needs to be called with an entry filtered from the list.
|
||||
Using `event.preventDefault()` prevents the application from using the first
|
||||
certificate from the store.
|
||||
`url` 指的是请求客户端认证的网页地址,调用 `callback` 时需要传入一个证书列表中的证书。
|
||||
|
||||
需要通过调用 `event.preventDefault()` 来防止应用自动使用第一个证书进行验证。如下所示:
|
||||
|
||||
```javascript
|
||||
app.on('select-certificate', function(event, host, url, list, callback) {
|
||||
event.preventDefault();
|
||||
callback(list[0]);
|
||||
})
|
||||
```
|
||||
### Event: 'login'
|
||||
### 事件: 'login'
|
||||
|
||||
Returns:
|
||||
返回:
|
||||
|
||||
* `event` Event
|
||||
* `webContents` [Web组件](web-contents.md)
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
* `request` Object
|
||||
* `method` String
|
||||
* `url` URL
|
||||
@@ -196,11 +197,10 @@ Returns:
|
||||
* `realm` String
|
||||
* `callback` Function
|
||||
|
||||
当 `webContents` 要做验证时被触发。
|
||||
当 `webContents` 要做进行一次 HTTP 登陆验证时被触发。
|
||||
|
||||
The default behavior is to cancel all authentications, to override this you
|
||||
should prevent the default behavior with `event.preventDefault()` and call
|
||||
`callback(username, password)` with the credentials.
|
||||
默认情况下,Electron 会取消所有的验证行为,如果需要重写这个行为,你需要用 `event.preventDefault()` 来阻止默认行为,并且
|
||||
用 `callback(username, password)` 来进行验证。
|
||||
|
||||
```javascript
|
||||
app.on('login', function(event, webContents, request, authInfo, callback) {
|
||||
@@ -208,22 +208,22 @@ app.on('login', function(event, webContents, request, authInfo, callback) {
|
||||
callback('username', 'secret');
|
||||
})
|
||||
```
|
||||
### 事件: 'gpu-process-crashed'
|
||||
### 事件:'gpu-process-crashed'
|
||||
|
||||
当GPU进程崩溃时触发。
|
||||
当 GPU 进程崩溃时触发。
|
||||
|
||||
## 方法
|
||||
## 方法列表
|
||||
|
||||
`app` 对象拥有以下的方法:
|
||||
|
||||
**提示:** 有的方法只能用于特定的操作系统。
|
||||
**请注意** 有的方法只能用于特定的操作系统。
|
||||
|
||||
### `app.quit()`
|
||||
|
||||
试图关掉所有的窗口。`before-quit` 事件将会被最先触发。如果所有的窗口都被成功关闭了,
|
||||
试图关掉所有的窗口。`before-quit` 事件将会最先被触发。如果所有的窗口都被成功关闭了,
|
||||
`will-quit` 事件将会被触发,默认下应用将会被关闭。
|
||||
|
||||
这个方法保证了所有的 `beforeunload` 和 `unload` 事件处理器被正确执行。会存在一个窗口被 `beforeunload` 事件处理器返回 `false` 取消退出的可能性。
|
||||
这个方法保证了所有的 `beforeunload` 和 `unload` 事件处理器被正确执行。假如一个窗口的 `beforeunload` 事件处理器返回 `false`,那么整个应用可能会取消退出。
|
||||
|
||||
### `app.hide()` _OS X_
|
||||
|
||||
@@ -241,30 +241,29 @@ app.on('login', function(event, webContents, request, authInfo, callback) {
|
||||
|
||||
所有的窗口会被立刻关闭,不会询问用户。`before-quit` 和 `will-quit` 这2个事件不会被触发
|
||||
|
||||
|
||||
### `app.getAppPath()`
|
||||
|
||||
返回当前应用所在的文件路径。
|
||||
|
||||
### `app.getPath(name)`
|
||||
|
||||
* `name` 字符串
|
||||
* `name` String
|
||||
|
||||
返回一个与 `name` 参数相关的特殊文件夹或文件路径。当失败时抛出一个 `Error` 。
|
||||
|
||||
你可以通过名称请求以下的路径:
|
||||
|
||||
* `home` 用户的 home 文件夹。
|
||||
* `appData` 所有用户的应用数据文件夹,默认对应:
|
||||
* `home` 用户的 home 文件夹(主目录)
|
||||
* `appData` 当前用户的应用数据文件夹,默认对应:
|
||||
* `%APPDATA%` Windows 中
|
||||
* `$XDG_CONFIG_HOME` or `~/.config` Linux 中
|
||||
* `~/Library/Application Support` OS X 中
|
||||
* `userData` 储存你应用程序设置文件的文件夹,默认是 `appData` 文件夹附加应用的名称。
|
||||
* `temp` 临时文件夹。
|
||||
* `userData` 储存你应用程序设置文件的文件夹,默认是 `appData` 文件夹附加应用的名称
|
||||
* `temp` 临时文件夹
|
||||
* `exe` 当前的可执行文件
|
||||
* `module` `libchromiumcontent` 库.
|
||||
* `desktop` 当前用户的桌面文件夹。
|
||||
* `documents` "我的文件夹"的路径.
|
||||
* `module` `libchromiumcontent` 库
|
||||
* `desktop` 当前用户的桌面文件夹
|
||||
* `documents` 用户文档目录的路径
|
||||
* `downloads` 用户下载目录的路径.
|
||||
* `music` 用户音乐目录的路径.
|
||||
* `pictures` 用户图片目录的路径.
|
||||
@@ -272,14 +271,14 @@ app.on('login', function(event, webContents, request, authInfo, callback) {
|
||||
|
||||
### `app.setPath(name, path)`
|
||||
|
||||
* `name` 字符串
|
||||
* `path` 字符串
|
||||
* `name` String
|
||||
* `path` String
|
||||
|
||||
重写 `path` 参数到一个特别的文件夹或者是一个和 `name` 参数有关系的文件。
|
||||
重写某个 `name` 的路径为 `path`,`path` 可以是一个文件夹或者一个文件,这个和 `name` 的类型有关。
|
||||
如果这个路径指向的文件夹不存在,这个文件夹将会被这个方法创建。
|
||||
如果错误则抛出 `Error` 。
|
||||
如果错误则会抛出 `Error`。
|
||||
|
||||
你只可以指向 `app.getPath` 中定义过 `name` 的路径。
|
||||
`name` 参数只能使用 `app.getPath` 中定义过 `name`。
|
||||
|
||||
默认情况下,网页的 cookie 和缓存都会储存在 `userData` 文件夹。
|
||||
如果你想要改变这个位置,你需要在 `app` 模块中的 `ready` 事件被触发之前重写 `userData` 的路径。
|
||||
@@ -293,22 +292,20 @@ app.on('login', function(event, webContents, request, authInfo, callback) {
|
||||
|
||||
返回当前应用程序的 `package.json` 文件中的名称。
|
||||
|
||||
通常 `name` 字段是一个短的小写字符串,其命名规则按照 npm 中的模块命名规则。你应该单独列举一个
|
||||
`productName` 字段,用于表示你的应用程序的完整名称,这个名称将会被 Electron 优先采用。
|
||||
由于 npm 的命名规则,通常 `name` 字段是一个短的小写字符串。但是应用名的完整名称通常是首字母大写的,你应该单独使用一个
|
||||
`productName` 字段,用于表示你的应用程序的完整名称。Electron 会优先使用这个字段作为应用名。
|
||||
|
||||
### `app.getLocale()`
|
||||
|
||||
返回当前应用程序的语言种类。
|
||||
|
||||
|
||||
返回当前应用程序的语言。
|
||||
|
||||
### `app.addRecentDocument(path)` _OS X_ _Windows_
|
||||
|
||||
* `path` 字符串
|
||||
* `path` String
|
||||
|
||||
为最近访问的文档列表中添加 `path` 。
|
||||
在最近访问的文档列表中添加 `path`。
|
||||
|
||||
这个列表由操作系统进行管理。在 Windows 中您可以通过任务条进行访问,在 OS X 中你可以通过dock 菜单进行访问。
|
||||
这个列表由操作系统进行管理。在 Windows 中您可以通过任务条进行访问,在 OS X 中你可以通过 dock 菜单进行访问。
|
||||
|
||||
### `app.clearRecentDocuments()` _OS X_ _Windows_
|
||||
|
||||
@@ -316,66 +313,55 @@ app.on('login', function(event, webContents, request, authInfo, callback) {
|
||||
|
||||
### `app.setUserTasks(tasks)` _Windows_
|
||||
|
||||
* `tasks` 由 `Task` 对象构成的数组
|
||||
* `tasks` [Task] - 一个由 Task 对象构成的数组
|
||||
|
||||
将 `tasks` 添加到 Windows 中 JumpList 功能的 [Tasks][tasks] 分类中。
|
||||
|
||||
`tasks` 中的 `Task` 对象格式如下:
|
||||
|
||||
`Task` 对象
|
||||
* `program` 字符串 - 执行程序的路径,通常你应该说明当前程序的路径为 `process.execPath` 字段。
|
||||
* `arguments` 字符串 - 当 `program` 执行时的命令行参数。
|
||||
* `title` 字符串 - JumpList 中显示的标题。
|
||||
* `description` 字符串 - 对这个任务的描述。
|
||||
* `iconPath` 字符串 - JumpList 中显示的 icon 的绝对路径,可以是一个任意包含一个icon的资源文件。你通常可以通过指明 `process.execPath` 来显示程序中的icon。
|
||||
* `iconIndex` 整数 - icon文件中的icon目录。如果一个icon文件包括了两个或多个icon,就需要设置这个值以确定icon。如果一个文件仅包含一个icon,那么这个值为0。
|
||||
`Task` Object
|
||||
* `program` String - 执行程序的路径,通常你应该说明当前程序的路径为 `process.execPath` 字段。
|
||||
* `arguments` String - 当 `program` 执行时的命令行参数。
|
||||
* `title` String - JumpList 中显示的标题。
|
||||
* `description` String - 对这个任务的描述。
|
||||
* `iconPath` String - JumpList 中显示的图标的绝对路径,可以是一个任意包含一个图标的资源文件。通常来说,你可以通过指明 `process.execPath` 来显示程序中的图标。
|
||||
* `iconIndex` Integer - 图标文件中的采用的图标位置。如果一个图标文件包括了多个图标,就需要设置这个值以确定使用的是哪一个图标。
|
||||
如果这个图标文件中只包含一个图标,那么这个值为 0。
|
||||
|
||||
### `app.allowNTLMCredentialsForAllDomains(allow)`
|
||||
|
||||
* `allow` Boolean
|
||||
|
||||
Dynamically sets whether to always send credentials for HTTP NTLM or Negotiate
|
||||
authentication - normally, Electron will only send NTLM/Kerberos credentials for
|
||||
URLs that fall under "Local Intranet" sites (i.e. are in the same domain as you).
|
||||
However, this detection often fails when corporate networks are badly configured,
|
||||
so this lets you co-opt this behavior and enable it for all URLs.
|
||||
动态设置是否总是为 HTTP NTLM 或 Negotiate 认证发送证书。通常来说,Electron 只会对本地网络(比如和你处在一个域中的计算机)发
|
||||
送 NTLM / Kerberos 证书。但是假如网络设置得不太好,可能这个自动探测会失效,所以你可以通过这个接口自定义 Electron 对所有 URL
|
||||
的行为。
|
||||
|
||||
### `app.makeSingleInstance(callback)`
|
||||
|
||||
* `callback` Function
|
||||
|
||||
This method makes your application a Single Instance Application - instead of
|
||||
allowing multiple instances of your app to run, this will ensure that only a
|
||||
single instance of your app is running, and other instances signal this
|
||||
instance and exit.
|
||||
这个方法可以让你的应用在同一时刻最多只会有一个实例,否则你的应用可以被运行多次并产生多个实例。你可以利用这个接口保证只有一个实例正
|
||||
常运行,其余的实例全部会被终止并退出。
|
||||
|
||||
`callback` will be called with `callback(argv, workingDirectory)` when a second
|
||||
instance has been executed. `argv` is an Array of the second instance's command
|
||||
line arguments, and `workingDirectory` is its current working directory. Usually
|
||||
applications respond to this by making their primary window focused and
|
||||
non-minimized.
|
||||
如果多个实例同时运行,那么第一个被运行的实例中 `callback` 会以 `callback(argv, workingDirectory)` 的形式被调用。其余的实例
|
||||
会被终止。
|
||||
`argv` 是一个包含了这个实例的命令行参数列表的数组,`workingDirectory` 是这个实例目前的运行目录。通常来说,我们会用通过将应用在
|
||||
主屏幕上激活,并且取消最小化,来提醒用户这个应用已经被打开了。
|
||||
|
||||
The `callback` is guaranteed to be executed after the `ready` event of `app`
|
||||
gets emitted.
|
||||
在 `app` 的 `ready` 事件后,`callback` 才有可能被调用。
|
||||
|
||||
This method returns `false` if your process is the primary instance of the
|
||||
application and your app should continue loading. And returns `true` if your
|
||||
process has sent its parameters to another instance, and you should immediately
|
||||
quit.
|
||||
如果当前实例为第一个实例,那么在这个方法将会返回 `false` 来保证它继续运行。否则将会返回 `true` 来让它立刻退出。
|
||||
|
||||
On OS X the system enforces single instance automatically when users try to open
|
||||
a second instance of your app in Finder, and the `open-file` and `open-url`
|
||||
events will be emitted for that. However when users start your app in command
|
||||
line the system's single instance machanism will be bypassed and you have to
|
||||
use this method to ensure single instance.
|
||||
在 OS X 中,如果用户通过 Finder、`open-file` 或者 `open-url` 打开应用,系统会强制确保只有一个实例在运行。但是如果用户是通过
|
||||
命令行打开,这个系统机制会被忽略,所以你仍然需要靠这个方法来保证应用为单实例运行的。
|
||||
|
||||
An example of activating the window of primary instance when a second instance
|
||||
starts:
|
||||
下面是一个简单的例子。我们可以通过这个例子了解如何确保应用为单实例运行状态。
|
||||
|
||||
```js
|
||||
var myWindow = null;
|
||||
|
||||
var shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory) {
|
||||
// Someone tried to run a second instance, we should focus our window.
|
||||
// 当另一个实例运行的时候,这里将会被调用,我们需要激活应用的窗口
|
||||
if (myWindow) {
|
||||
if (myWindow.isMinimized()) myWindow.restore();
|
||||
myWindow.focus();
|
||||
@@ -383,104 +369,109 @@ var shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory)
|
||||
return true;
|
||||
});
|
||||
|
||||
// 这个实例是多余的实例,需要退出
|
||||
if (shouldQuit) {
|
||||
app.quit();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create myWindow, load the rest of the app, etc...
|
||||
// 创建窗口、继续加载应用、应用逻辑等……
|
||||
app.on('ready', function() {
|
||||
});
|
||||
|
||||
```
|
||||
### `app.setAppUserModelId(id)` _Windows_
|
||||
|
||||
* `id` String
|
||||
|
||||
改变 [Application User Model ID][app-user-model-id] 的 `id`.
|
||||
改变当前应用的 [Application User Model ID][app-user-model-id] 为 `id`.
|
||||
|
||||
### `app.isAeroGlassEnabled()` _Windows_
|
||||
|
||||
This method returns `true` if [DWM composition](https://msdn.microsoft.com/en-us/library/windows/desktop/aa969540.aspx)
|
||||
(Aero Glass) is enabled, and `false` otherwise. You can use it to determine if
|
||||
you should create a transparent window or not (transparent windows won't work
|
||||
correctly when DWM composition is disabled).
|
||||
如果 [DWM composition](https://msdn.microsoft.com/en-us/library/windows/desktop/aa969540.aspx)(Aero Glass) 启用
|
||||
了,那么这个方法会返回 `true`,否则是 `false`。你可以用这个方法来决定是否要开启透明窗口特效,因为如果用户没开启 DWM,那么透明窗
|
||||
口特效是无效的。
|
||||
|
||||
Usage example:
|
||||
举个例子:
|
||||
|
||||
```js
|
||||
let browserOptions = {width: 1000, height: 800};
|
||||
|
||||
// Make the window transparent only if the platform supports it.
|
||||
// 只有平台支持的时候才使用透明窗口
|
||||
if (process.platform !== 'win32' || app.isAeroGlassEnabled()) {
|
||||
browserOptions.transparent = true;
|
||||
browserOptions.frame = false;
|
||||
}
|
||||
|
||||
// Create the window.
|
||||
// 创建窗口
|
||||
win = new BrowserWindow(browserOptions);
|
||||
|
||||
// Navigate.
|
||||
// 转到某个网页
|
||||
if (browserOptions.transparent) {
|
||||
win.loadURL('file://' + __dirname + '/index.html');
|
||||
} else {
|
||||
// No transparency, so we load a fallback that uses basic styles.
|
||||
// 没有透明特效,我们应该用某个只包含基本样式的替代解决方案。
|
||||
win.loadURL('file://' + __dirname + '/fallback.html');
|
||||
}
|
||||
```
|
||||
### `app.commandLine.appendSwitch(switch[, value])`
|
||||
|
||||
通过可选的参数 `value` 给 Chromium 命令行中添加一个开关。
|
||||
Append a switch (with optional `value`) to Chromium's command line.
|
||||
通过可选的参数 `value` 给 Chromium 中添加一个命令行开关。
|
||||
|
||||
**贴士:** 这不会影响 `process.argv` ,这个方法主要被开发者用于控制一些低层级的 Chromium 行为。
|
||||
**注意** 这个方法不会影响 `process.argv`,我们通常用这个方法控制一些底层 Chromium 行为。
|
||||
|
||||
### `app.commandLine.appendArgument(value)`
|
||||
|
||||
给 Chromium 命令行中加入一个参数。这个参数是当前正在被引用的。
|
||||
给 Chromium 中直接添加一个命令行参数,这个参数 `value` 的引号和格式必须正确。
|
||||
|
||||
**贴士:** 这不会影响 `process.argv`。
|
||||
**注意** 这个方法不会影响 `process.argv`。
|
||||
|
||||
### `app.dock.bounce([type])` _OS X_
|
||||
|
||||
* `type` 字符串 (可选的) - 可以是 `critical` 或 `informational`。默认下是 `informational`
|
||||
* `type` String - 可选参数,可以是 `critical` 或 `informational`。默认为 `informational`。
|
||||
|
||||
当输入 `critical` 时,dock 中的 icon 将会开始弹跳直到应用被激活或者这个请求被取消。
|
||||
当传入的是 `critical` 时,dock 中的应用将会开始弹跳,直到这个应用被激活或者这个请求被取消。
|
||||
|
||||
当输入 `informational` 时,dock 中的 icon 只会弹跳一秒钟。
|
||||
然而,这个请求仍然会激活,直到应用被激活或者请求被取消。
|
||||
当传入的是 `informational` 时,dock 中的图标只会弹跳一秒钟。但是,这个请求仍然会激活,直到应用被激活或者请求被取消。
|
||||
|
||||
返回一个表示这个请求的 ID。
|
||||
这个方法返回的返回值表示这个请求的 ID。
|
||||
|
||||
### `app.dock.cancelBounce(id)` _OS X_
|
||||
|
||||
* `id` 整数
|
||||
* `id` Integer
|
||||
|
||||
取消这个 `id` 对应的请求。
|
||||
|
||||
### `app.dock.setBadge(text)` _OS X_
|
||||
|
||||
* `text` 字符串
|
||||
* `text` String
|
||||
|
||||
设置 dock 中显示的字符。
|
||||
设置应用在 dock 中显示的字符串。
|
||||
|
||||
### `app.dock.getBadge()` _OS X_
|
||||
|
||||
返回 dock 中显示的字符。
|
||||
返回应用在 dock 中显示的字符串。
|
||||
|
||||
### `app.dock.hide()` _OS X_
|
||||
|
||||
隐藏 dock 中的 icon。
|
||||
隐藏应用在 dock 中的图标。
|
||||
|
||||
### `app.dock.show()` _OS X_
|
||||
|
||||
显示 dock 中的 icon。
|
||||
显示应用在 dock 中的图标。
|
||||
|
||||
### `app.dock.setMenu(menu)` _OS X_
|
||||
|
||||
* `menu` 菜单
|
||||
* `menu` [Menu](menu.md)
|
||||
|
||||
设置应用的 [dock 菜单][dock-menu].
|
||||
|
||||
### `app.dock.setIcon(image)` _OS X_
|
||||
|
||||
* `image` [NativeImage](native-image.md)
|
||||
|
||||
设置应用在 dock 中显示的图标。
|
||||
|
||||
[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
|
||||
|
||||
88
docs-translations/zh-CN/api/auto-updater.md
Normal file
88
docs-translations/zh-CN/api/auto-updater.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# autoUpdater
|
||||
|
||||
这个模块提供了一个到 `Squirrel` 自动更新框架的接口。
|
||||
|
||||
## 平台相关的提示
|
||||
|
||||
虽然 `autoUpdater` 模块提供了一套各平台通用的接口,但是在每个平台间依然会有一些微小的差异。
|
||||
|
||||
### OS X
|
||||
|
||||
在 OS X 上,`autoUpdater` 模块依靠的是内置的 [Squirrel.Mac][squirrel-mac],这意味着你不需要依靠其他的设置就能使用。关于
|
||||
更新服务器的配置,你可以通过阅读 [Server Support][server-support] 这篇文章来了解。
|
||||
|
||||
### Windows
|
||||
|
||||
在 Windows 上,你必须使用安装程序将你的应用装到用户的计算机上,所以比较推荐的方法是用 [grunt-electron-installer][installer] 这个模块来自动生成一个 Windows 安装向导。
|
||||
|
||||
Squirrel 自动生成的安装向导会生成一个带 [Application User Model ID][app-user-model-id] 的快捷方式。
|
||||
Application User Model ID 的格式是 `com.squirrel.PACKAGE_ID.YOUR_EXE_WITHOUT_DOT_EXE`, 比如
|
||||
像 `com.squirrel.slack.Slack` 和 `com.squirrel.code.Code` 这样的。你应该在自己的应用中使用 `app.setAppUserModelId` 方法设置相同的 API,不然 Windows 将不能正确地把你的应用固定在任务栏上。
|
||||
|
||||
服务器端的配置和 OS X 也是不一样的,你可以阅读 [Squirrel.Windows][squirrel-windows] 这个文档来获得详细信息。
|
||||
|
||||
### Linux
|
||||
|
||||
Linux 下没有任何的自动更新支持,所以我们推荐用各个 Linux 发行版的包管理器来分发你的应用。
|
||||
|
||||
## 事件列表
|
||||
|
||||
`autoUpdater` 对象会触发以下的事件:
|
||||
|
||||
### 事件:'error'
|
||||
|
||||
返回:
|
||||
|
||||
* `error` Error
|
||||
|
||||
当更新发生错误的时候触发。
|
||||
|
||||
### 事件:'checking-for-update'
|
||||
|
||||
当开始检查更新的时候触发。
|
||||
|
||||
### 事件:'update-available'
|
||||
|
||||
当发现一个可用更新的时候触发,更新包下载会自动开始。
|
||||
|
||||
### 事件:'update-not-available'
|
||||
|
||||
当没有可用更新的时候触发。
|
||||
|
||||
### 事件:'update-downloaded'
|
||||
|
||||
返回:
|
||||
|
||||
* `event` Event
|
||||
* `releaseNotes` String - 新版本更新公告
|
||||
* `releaseName` String - 新的版本号
|
||||
* `releaseDate` Date - 新版本发布的日期
|
||||
* `updateURL` String - 更新地址
|
||||
|
||||
在更新下载完成的时候触发。
|
||||
|
||||
在 Windows 上只有 `releaseName` 是有效的。
|
||||
|
||||
## 方法列表
|
||||
|
||||
`autoUpdater` 对象有以下的方法:
|
||||
|
||||
### `autoUpdater.setFeedURL(url)`
|
||||
|
||||
* `url` String
|
||||
|
||||
设置检查更新的 `url`,并且初始化自动更新。这个 `url` 一旦设置就无法更改。
|
||||
|
||||
### `autoUpdater.checkForUpdates()`
|
||||
|
||||
向服务端查询现在是否有可用的更新。在调用这个方法之前,必须要先调用 `setFeedURL`。
|
||||
|
||||
### `autoUpdater.quitAndInstall()`
|
||||
|
||||
在下载完成后,重启当前的应用并且安装更新。这个方法应该仅在 `update-downloaded` 事件触发后被调用。
|
||||
|
||||
[squirrel-mac]: https://github.com/Squirrel/Squirrel.Mac
|
||||
[server-support]: https://github.com/Squirrel/Squirrel.Mac#server-support
|
||||
[squirrel-windows]: https://github.com/Squirrel/Squirrel.Windows
|
||||
[installer]: https://github.com/atom/grunt-electron-installer
|
||||
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx
|
||||
761
docs-translations/zh-CN/api/browser-window.md
Normal file
761
docs-translations/zh-CN/api/browser-window.md
Normal file
@@ -0,0 +1,761 @@
|
||||
# BrowserWindow
|
||||
|
||||
`BrowserWindow` 类让你有创建一个浏览器窗口的权力。例如:
|
||||
|
||||
```javascript
|
||||
// In the main process.
|
||||
const BrowserWindow = require('electron').BrowserWindow;
|
||||
|
||||
// Or in the renderer process.
|
||||
const BrowserWindow = require('electron').remote.BrowserWindow;
|
||||
|
||||
var win = new BrowserWindow({ width: 800, height: 600, show: false });
|
||||
win.on('closed', function() {
|
||||
win = null;
|
||||
});
|
||||
|
||||
win.loadURL('https://github.com');
|
||||
win.show();
|
||||
```
|
||||
|
||||
你也可以不通过chrome创建窗口,使用
|
||||
[Frameless Window](frameless-window.md) API.
|
||||
|
||||
## Class: BrowserWindow
|
||||
|
||||
`BrowserWindow` 是一个
|
||||
[EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter).
|
||||
|
||||
通过 `options` 可以创建一个具有本质属性的 `BrowserWindow` .
|
||||
|
||||
### `new BrowserWindow([options])`
|
||||
|
||||
* `options` Object
|
||||
* `width` Integer - 窗口宽度,单位像素. 默认是 `800`.
|
||||
* `height` Integer - 窗口高度,单位像素. 默认是 `600`.
|
||||
* `x` Integer - 窗口相对于屏幕的左偏移位置.默认居中.
|
||||
* `y` Integer - 窗口相对于屏幕的顶部偏移位置.默认居中.
|
||||
* `useContentSize` Boolean - `width` 和 `height` 使用web网页size, 这意味着实际窗口的size应该包括窗口框架的size,稍微会大一点,默认为 `false`.
|
||||
* `center` Boolean - 窗口屏幕居中.
|
||||
* `minWidth` Integer - 窗口最小宽度,默认为 `0`.
|
||||
* `minHeight` Integer - 窗口最小高度,默认为 `0`.
|
||||
* `maxWidth` Integer - 窗口最大宽度,默认无限制.
|
||||
* `maxHeight` Integer - 窗口最大高度,默认无限制.
|
||||
* `resizable` Boolean - 是否可以改变窗口size,默认为 `true`.
|
||||
* `movable` Boolean - 窗口是否可以拖动. 在 Linux 上无效. 默认为 `true`.
|
||||
* `minimizable` Boolean - 窗口是否可以最小化. 在 Linux 上无效. 默认为 `true`.
|
||||
* `maximizable` Boolean - 窗口是否可以最大化. 在 Linux 上无效. 默认为 `true`.
|
||||
* `closable` Boolean - 窗口是否可以关闭. 在 Linux 上无效. 默认为 `true`.
|
||||
* `alwaysOnTop` Boolean - 窗口是否总是显示在其他窗口之前. 在 Linux 上无效. 默认为 `false`.
|
||||
* `fullscreen` Boolean - 窗口是否可以全屏幕. 当明确设置值为When `false` ,全屏化按钮将会隐藏,在 OS X 将禁用. 默认 `false`.
|
||||
* `fullscreenable` Boolean - 在 OS X 上,全屏化按钮是否可用,默认为 `true`.
|
||||
* `skipTaskbar` Boolean - 是否在人物栏中显示窗口. 默认是`false`.
|
||||
* `kiosk` Boolean - kiosk 方式. 默认为 `false`.
|
||||
* `title` String - 窗口默认title. 默认 `"Electron"`.
|
||||
* `icon` [NativeImage](native-image.md) - 窗口图标, 如果不设置,窗口将使用可用的默认图标.
|
||||
* `show` Boolean - 窗口创建的时候是否显示. 默认为 `true`.
|
||||
* `frame` Boolean - 指定 `false` 来创建一个
|
||||
[Frameless Window](frameless-window.md). 默认为 `true`.
|
||||
* `acceptFirstMouse` Boolean - 是否允许单击web view来激活窗口 . 默认为 `false`.
|
||||
* `disableAutoHideCursor` Boolean - 当 typing 时是否隐藏鼠标.默认 `false`.
|
||||
* `autoHideMenuBar` Boolean - 除非点击 `Alt`,否则隐藏菜单栏.默认为 `false`.
|
||||
* `enableLargerThanScreen` Boolean - 是否允许允许改变窗口大小大于屏幕. 默认是 `false`.
|
||||
* `backgroundColor` String -窗口的 background color 值为十六进制,如 `#66CD00` 或 `#FFF` 或 `#80FFFFFF` (支持透明度). 默认为在 Linux 和 Windows 上为
|
||||
`#000` (黑色) , Mac上为 `#FFF`(或透明).
|
||||
* `hasShadow` Boolean - 窗口是否有阴影. 只在 OS X 上有效. 默认为 `true`.
|
||||
* `darkTheme` Boolean - 为窗口使用 dark 主题, 只在一些拥有 GTK+3 桌面环境上有效. 默认为 `false`.
|
||||
* `transparent` Boolean - 窗口 [透明](frameless-window.md).
|
||||
默认为 `false`.
|
||||
* `type` String - 窗口type, 默认普通窗口. 下面查看更多.
|
||||
* `titleBarStyle` String - 窗口标题栏样式. 下面查看更多.
|
||||
* `webPreferences` Object - 设置界面特性. 下面查看更多.
|
||||
|
||||
`type` 的值和效果不同平台展示效果不同,具体:
|
||||
|
||||
* Linux, 可用值为 `desktop`, `dock`, `toolbar`, `splash`,
|
||||
`notification`.
|
||||
* OS X, 可用值为 `desktop`, `textured`.
|
||||
* `textured` type 添加金属梯度效果
|
||||
(`NSTexturedBackgroundWindowMask`).
|
||||
* `desktop` 设置窗口在桌面背景窗口水平
|
||||
(`kCGDesktopWindowLevel - 1`). 注意桌面窗口不可聚焦, 不可不支持键盘和鼠标事件, 但是可以使用 `globalShortcut` 来解决输入问题.
|
||||
|
||||
`titleBarStyle` 只在 OS X 10.10 Yosemite 或更新版本上支持.
|
||||
可用值:
|
||||
|
||||
* `default` 以及无值, 显示在 Mac 标题栏上为不透明的标准灰色.
|
||||
* `hidden` 隐藏标题栏,内容充满整个窗口, 然后它依然在左上角,仍然受标准窗口控制.
|
||||
* `hidden-inset`主体隐藏,显示小的控制按钮在窗口边缘.
|
||||
|
||||
`webPreferences` 参数是个对象,它的属性:
|
||||
|
||||
* `nodeIntegration` Boolean - 是否完整支持node. 默认为 `true`.
|
||||
* `preload` String - 界面的其它脚本运行之前预先加载一个指定脚本. 这个脚本将一直可以使用 node APIs 无论 node integration 是否开启. 脚本路径为绝对路径.
|
||||
当 node integration 关闭, 预加载的脚本将从全局范围重新引入node的全局引用标志. 查看例子
|
||||
[here](process.md#event-loaded).
|
||||
* `session` [Session](session.md#class-session) - 设置界面session. 而不是直接忽略session对象 , 也可用 `partition` 来代替, 它接受一个 partition 字符串. 当同时使用 `session` 和 `partition`, `session` 优先级更高.
|
||||
默认使用默认 session.
|
||||
* `partition` String - 通过session的partition字符串来设置界面session. 如果 `partition` 以 `persist:` 开头, 这个界面将会为所有界面使用相同的 `partition`. 如果没有 `persist:` 前缀, 界面使用历史session. 通过分享同一个 `partition`, 所有界面使用相同的session. 默认使用默认 session.
|
||||
* `zoomFactor` Number - 界面默认缩放值, `3.0` 表示
|
||||
`300%`. 默认 `1.0`.
|
||||
* `javascript` Boolean - 开启javascript支持. 默认为`true`.
|
||||
* `webSecurity` Boolean - 当设置为 `false`, 它将禁用相同地方的规则 (通常测试服), 并且如果有2个非用户设置的参数,就设置
|
||||
`allowDisplayingInsecureContent` 和 `allowRunningInsecureContent` 的值为
|
||||
`true`. 默认为 `true`.
|
||||
* `allowDisplayingInsecureContent` Boolean -允许一个使用 https的界面来展示由 http URLs 传过来的资源. 默认`false`.
|
||||
* `allowRunningInsecureContent` Boolean - Boolean -允许一个使用 https的界面来渲染由 http URLs 提交的html,css,javascript. 默认为 `false`.
|
||||
* `images` Boolean - 开启图片使用支持. 默认 `true`.
|
||||
* `textAreasAreResizable` Boolean - textArea 可以编辑. 默认为 `true`.
|
||||
* `webgl` Boolean - 开启 WebGL 支持. 默认为 `true`.
|
||||
* `webaudio` Boolean - 开启 WebAudio 支持. 默认为 `true`.
|
||||
* `plugins` Boolean - 是否开启插件支持. 默认为 `false`.
|
||||
* `experimentalFeatures` Boolean - 开启 Chromium 的 可测试 特性.
|
||||
默认为 `false`.
|
||||
* `experimentalCanvasFeatures` Boolean - 开启 Chromium 的 canvas 可测试特性. 默认为 `false`.
|
||||
* `directWrite` Boolean - 开启窗口的 DirectWrite font 渲染系统. 默认为 `true`.
|
||||
* `blinkFeatures` String - 以 `,` 分隔的特性列表, 如
|
||||
`CSSVariables,KeyboardEventKey`. 被支持的所有特性可在 [setFeatureEnabledFromString][blink-feature-string]
|
||||
中找到.
|
||||
* `defaultFontFamily` Object - 设置 font-family 默认字体.
|
||||
* `standard` String - 默认为 `Times New Roman`.
|
||||
* `serif` String - 默认为 `Times New Roman`.
|
||||
* `sansSerif` String - 默认为 `Arial`.
|
||||
* `monospace` String - 默认为 `Courier New`.
|
||||
* `defaultFontSize` Integer - 默认为 `16`.
|
||||
* `defaultMonospaceFontSize` Integer - 默认为 `13`.
|
||||
* `minimumFontSize` Integer - 默认为 `0`.
|
||||
* `defaultEncoding` String - 默认为 `ISO-8859-1`.
|
||||
|
||||
## 事件
|
||||
|
||||
`BrowserWindow` 对象可触发下列事件:
|
||||
|
||||
**注意:** 一些事件只能在特定os环境中触发,已经尽可能地标出.
|
||||
|
||||
### Event: 'page-title-updated'
|
||||
|
||||
返回:
|
||||
|
||||
* `event` Event
|
||||
|
||||
当文档改变标题时触发,使用 `event.preventDefault()` 可以阻止原窗口的标题改变.
|
||||
|
||||
### Event: 'close'
|
||||
|
||||
返回:
|
||||
|
||||
* `event` Event
|
||||
|
||||
在窗口要关闭的时候触发. 它在DOM的 `beforeunload` and `unload` 事件之前触发.使用 `event.preventDefault()` 可以取消这个操作
|
||||
|
||||
通常你想通过 `beforeunload` 处理器来决定是否关闭窗口,但是它也会在窗口重载的时候被触发. 在 Electron 中,返回一个空的字符串或 `false` 可以取消关闭.例如:
|
||||
|
||||
```javascript
|
||||
window.onbeforeunload = function(e) {
|
||||
console.log('I do not want to be closed');
|
||||
|
||||
// Unlike usual browsers, in which a string should be returned and the user is
|
||||
// prompted to confirm the page unload, Electron gives developers more options.
|
||||
// Returning empty string or false would prevent the unloading now.
|
||||
// You can also use the dialog API to let the user confirm closing the application.
|
||||
e.returnValue = false;
|
||||
};
|
||||
```
|
||||
|
||||
### Event: 'closed'
|
||||
|
||||
当窗口已经关闭的时候触发.当你接收到这个事件的时候,你应当删除对已经关闭的窗口的引用对象和避免再次使用它.
|
||||
|
||||
### Event: 'unresponsive'
|
||||
|
||||
在界面卡死的时候触发事件.
|
||||
|
||||
### Event: 'responsive'
|
||||
|
||||
在界面恢复卡死的时候触发.
|
||||
|
||||
### Event: 'blur'
|
||||
|
||||
在窗口失去焦点的时候触发.
|
||||
|
||||
### Event: 'focus'
|
||||
|
||||
在窗口获得焦点的时候触发.
|
||||
|
||||
### Event: 'maximize'
|
||||
|
||||
在窗口最大化的时候触发.
|
||||
|
||||
### Event: 'unmaximize'
|
||||
|
||||
在窗口退出最大化的时候触发.
|
||||
|
||||
### Event: 'minimize'
|
||||
|
||||
在窗口最小化的时候触发.
|
||||
|
||||
### Event: 'restore'
|
||||
|
||||
在窗口从最小化恢复的时候触发.
|
||||
|
||||
### Event: 'resize'
|
||||
|
||||
在窗口size改变的时候触发.
|
||||
|
||||
### Event: 'move'
|
||||
|
||||
在窗口移动的时候触发.
|
||||
|
||||
注意:在 OS X 中别名为 `moved`.
|
||||
|
||||
### Event: 'moved' _OS X_
|
||||
|
||||
在窗口移动的时候触发.
|
||||
|
||||
### Event: 'enter-full-screen'
|
||||
|
||||
在的窗口进入全屏状态时候触发.
|
||||
|
||||
### Event: 'leave-full-screen'
|
||||
|
||||
在的窗口退出全屏状态时候触发.
|
||||
|
||||
### Event: 'enter-html-full-screen'
|
||||
|
||||
在的窗口通过 html api 进入全屏状态时候触发.
|
||||
|
||||
### Event: 'leave-html-full-screen'
|
||||
|
||||
在的窗口通过 html api 退出全屏状态时候触发.
|
||||
|
||||
### Event: 'app-command' _Windows_
|
||||
|
||||
在请求一个[App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx)的时候触发.
|
||||
典型的是键盘媒体或浏览器命令, Windows上的 "Back" 按钮用作鼠标也会触发.
|
||||
|
||||
```js
|
||||
someWindow.on('app-command', function(e, cmd) {
|
||||
// Navigate the window back when the user hits their mouse back button
|
||||
if (cmd === 'browser-backward' && someWindow.webContents.canGoBack()) {
|
||||
someWindow.webContents.goBack();
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Event: 'scroll-touch-begin' _OS X_
|
||||
|
||||
在滚动条事件开始的时候触发.
|
||||
|
||||
### Event: 'scroll-touch-end' _OS X_
|
||||
|
||||
在滚动条事件结束的时候触发.
|
||||
|
||||
## 方法
|
||||
|
||||
`BrowserWindow` 对象有如下方法:
|
||||
|
||||
### `BrowserWindow.getAllWindows()`
|
||||
|
||||
返回一个所有已经打开了窗口的对象数组.
|
||||
|
||||
### `BrowserWindow.getFocusedWindow()`
|
||||
|
||||
返回应用当前获得焦点窗口,如果没有就返回 `null`.
|
||||
|
||||
### `BrowserWindow.fromWebContents(webContents)`
|
||||
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
|
||||
根据 `webContents` 查找窗口.
|
||||
|
||||
### `BrowserWindow.fromId(id)`
|
||||
|
||||
* `id` Integer
|
||||
|
||||
根据 id 查找窗口.
|
||||
|
||||
### `BrowserWindow.addDevToolsExtension(path)`
|
||||
|
||||
* `path` String
|
||||
|
||||
添加位于 `path` 的开发者工具栏扩展,并且返回扩展项的名字.
|
||||
|
||||
这个扩展会被添加到历史,所以只需要使用这个API一次,这个api不可用作编程使用.
|
||||
|
||||
### `BrowserWindow.removeDevToolsExtension(name)`
|
||||
|
||||
* `name` String
|
||||
|
||||
删除开发者工具栏名为 `name` 的扩展.
|
||||
|
||||
## 实例属性
|
||||
|
||||
使用 `new BrowserWindow` 创建的实例对象,有如下属性:
|
||||
|
||||
```javascript
|
||||
// In this example `win` is our instance
|
||||
var win = new BrowserWindow({ width: 800, height: 600 });
|
||||
```
|
||||
|
||||
### `win.webContents`
|
||||
|
||||
这个窗口的 `WebContents` 对象,所有与界面相关的事件和方法都通过它完成的.
|
||||
|
||||
查看 [`webContents` documentation](web-contents.md) 的方法和事件.
|
||||
|
||||
### `win.id`
|
||||
|
||||
窗口的唯一id.
|
||||
|
||||
## 实例方法
|
||||
|
||||
使用 `new BrowserWindow` 创建的实例对象,有如下方法:
|
||||
|
||||
**注意:** 一些方法只能在特定os环境中调用,已经尽可能地标出.
|
||||
|
||||
### `win.destroy()`
|
||||
|
||||
强制关闭窗口, `unload` and `beforeunload` 不会触发,并且 `close` 也不会触发, 但是它保证了 `closed` 触发.
|
||||
|
||||
### `win.close()`
|
||||
|
||||
尝试关闭窗口,这与用户点击关闭按钮的效果一样. 虽然网页可能会取消关闭,查看 [close event](#event-close).
|
||||
|
||||
### `win.focus()`
|
||||
|
||||
窗口获得焦点.
|
||||
|
||||
### `win.isFocused()`
|
||||
|
||||
返回 boolean, 窗口是否获得焦点.
|
||||
|
||||
### `win.show()`
|
||||
|
||||
展示并且使窗口获得焦点.
|
||||
|
||||
### `win.showInactive()`
|
||||
|
||||
展示窗口但是不获得焦点.
|
||||
|
||||
### `win.hide()`
|
||||
|
||||
隐藏窗口.
|
||||
|
||||
### `win.isVisible()`
|
||||
|
||||
返回 boolean, 窗口是否可见.
|
||||
|
||||
### `win.maximize()`
|
||||
|
||||
窗口最大化.
|
||||
|
||||
### `win.unmaximize()`
|
||||
|
||||
取消窗口最大化.
|
||||
|
||||
### `win.isMaximized()`
|
||||
|
||||
返回 boolean, 窗口是否最大化.
|
||||
|
||||
### `win.minimize()`
|
||||
|
||||
窗口最小化. 在一些os中,它将在dock中显示.
|
||||
|
||||
### `win.restore()`
|
||||
|
||||
将最小化的窗口恢复为之前的状态.
|
||||
|
||||
### `win.isMinimized()`
|
||||
|
||||
返回 boolean, 窗口是否最小化.
|
||||
|
||||
### `win.setFullScreen(flag)`
|
||||
|
||||
* `flag` Boolean
|
||||
|
||||
设置是否全屏.
|
||||
|
||||
### `win.isFullScreen()`
|
||||
|
||||
返回 boolean, 窗口是否全屏化.
|
||||
|
||||
### `win.setAspectRatio(aspectRatio[, extraSize])` _OS X_
|
||||
|
||||
* `aspectRatio` 维持部分视图内容窗口的高宽比值.
|
||||
* `extraSize` Object (可选) - 维持高宽比值时不包含的额外size.
|
||||
* `width` Integer
|
||||
* `height` Integer
|
||||
|
||||
由一个窗口来维持高宽比值. `extraSize` 允许开发者使用它,它的单位为像素,不包含在 `aspectRatio` 中.这个 API 可用来区分窗口的size和内容的size .
|
||||
|
||||
想象一个普通可控的HD video 播放器窗口. 假如左边缘有15控制像素,右边缘有25控制像素,在播放器下面有50控制像素.为了在播放器内保持一个 16:9 的高宽比例,我们可以调用这个api传入参数16/9 and
|
||||
[ 40, 50 ].第二个参数不管网页中的额外的宽度和高度在什么位置,只要它们存在就行.只需要把网页中的所有额外的高度和宽度加起来就行.
|
||||
|
||||
### `win.setBounds(options[, animate])`
|
||||
|
||||
* `options` Object
|
||||
* `x` Integer
|
||||
* `y` Integer
|
||||
* `width` Integer
|
||||
* `height` Integer
|
||||
* `animate` Boolean (可选) _OS X_
|
||||
|
||||
重新设置窗口的宽高值,并且移动到指定的 `x`, `y` 位置.
|
||||
|
||||
### `win.getBounds()`
|
||||
|
||||
返回一个对象,它包含了窗口的宽,高,x坐标,y坐标.
|
||||
|
||||
### `win.setSize(width, height[, animate])`
|
||||
|
||||
* `width` Integer
|
||||
* `height` Integer
|
||||
* `animate` Boolean (可选) _OS X_
|
||||
|
||||
重新设置窗口的宽高值.
|
||||
|
||||
### `win.getSize()`
|
||||
|
||||
返回一个数组,它包含了窗口的宽,高.
|
||||
|
||||
### `win.setContentSize(width, height[, animate])`
|
||||
|
||||
* `width` Integer
|
||||
* `height` Integer
|
||||
* `animate` Boolean (可选) _OS X_
|
||||
|
||||
重新设置窗口客户端的宽高值(例如网页界面).
|
||||
|
||||
### `win.getContentSize()`
|
||||
|
||||
返回一个数组,它包含了窗口客户端的宽,高.
|
||||
|
||||
### `win.setMinimumSize(width, height)`
|
||||
|
||||
* `width` Integer
|
||||
* `height` Integer
|
||||
|
||||
设置窗口最小化的宽高值.
|
||||
|
||||
### `win.getMinimumSize()`
|
||||
|
||||
返回一个数组,它包含了窗口最小化的宽,高.
|
||||
|
||||
### `win.setMaximumSize(width, height)`
|
||||
|
||||
* `width` Integer
|
||||
* `height` Integer
|
||||
|
||||
设置窗口最大化的宽高值.
|
||||
|
||||
### `win.getMaximumSize()`
|
||||
|
||||
返回一个数组,它包含了窗口最大化的宽,高.
|
||||
|
||||
### `win.setResizable(resizable)`
|
||||
|
||||
* `resizable` Boolean
|
||||
|
||||
设置窗口是否可以被用户改变size.
|
||||
|
||||
### `win.isResizable()`
|
||||
|
||||
返回 boolean,窗口是否可以被用户改变size.
|
||||
|
||||
### `win.setMovable(movable)` _OS X_ _Windows_
|
||||
|
||||
* `movable` Boolean
|
||||
|
||||
设置窗口是否可以被用户拖动. Linux 无效.
|
||||
|
||||
### `win.isMovable()` _OS X_ _Windows_
|
||||
|
||||
返回 boolean,窗口是否可以被用户拖动. Linux 总是返回 `true`.
|
||||
|
||||
### `win.setMinimizable(minimizable)` _OS X_ _Windows_
|
||||
|
||||
* `minimizable` Boolean
|
||||
|
||||
设置窗口是否可以最小化. Linux 无效.
|
||||
|
||||
### `win.isMinimizable()` _OS X_ _Windows_
|
||||
|
||||
返回 boolean,窗口是否可以最小化. Linux 总是返回 `true`.
|
||||
|
||||
### `win.setMaximizable(maximizable)` _OS X_ _Windows_
|
||||
|
||||
* `maximizable` Boolean
|
||||
|
||||
设置窗口是否可以最大化. Linux 无效.
|
||||
|
||||
### `win.isMaximizable()` _OS X_ _Windows_
|
||||
|
||||
返回 boolean,窗口是否可以最大化. Linux 总是返回 `true`.
|
||||
|
||||
### `win.setFullScreenable(fullscreenable)`
|
||||
|
||||
* `fullscreenable` Boolean
|
||||
|
||||
设置点击最大化按钮是否可以全屏或最大化窗口.
|
||||
|
||||
### `win.isFullScreenable()`
|
||||
|
||||
返回 boolean,点击最大化按钮是否可以全屏或最大化窗口.
|
||||
|
||||
### `win.setClosable(closable)` _OS X_ _Windows_
|
||||
|
||||
* `closable` Boolean
|
||||
|
||||
设置窗口是否可以人为关闭. Linux 无效.
|
||||
|
||||
### `win.isClosable()` _OS X_ _Windows_
|
||||
|
||||
返回 boolean,窗口是否可以人为关闭. Linux 总是返回 `true`.
|
||||
|
||||
### `win.setAlwaysOnTop(flag)`
|
||||
|
||||
* `flag` Boolean
|
||||
|
||||
是否设置这个窗口始终在其他窗口之上.设置之后,这个窗口仍然是一个普通的窗口,不是一个不可以获得焦点的工具箱窗口.
|
||||
|
||||
### `win.isAlwaysOnTop()`
|
||||
|
||||
返回 boolean,当前窗口是否始终在其它窗口之前.
|
||||
|
||||
### `win.center()`
|
||||
|
||||
窗口居中.
|
||||
|
||||
### `win.setPosition(x, y[, animate])`
|
||||
|
||||
* `x` Integer
|
||||
* `y` Integer
|
||||
* `animate` Boolean (可选) _OS X_
|
||||
|
||||
移动窗口到对应的 `x` and `y` 坐标.
|
||||
|
||||
### `win.getPosition()`
|
||||
|
||||
返回一个包含当前窗口位置的数组.
|
||||
|
||||
### `win.setTitle(title)`
|
||||
|
||||
* `title` String
|
||||
|
||||
改变原窗口的title.
|
||||
|
||||
### `win.getTitle()`
|
||||
|
||||
返回原窗口的title.
|
||||
|
||||
**注意:** 界面title可能和窗口title不相同.
|
||||
|
||||
### `win.flashFrame(flag)`
|
||||
|
||||
* `flag` Boolean
|
||||
|
||||
开始或停止显示窗口来获得用户的关注.
|
||||
|
||||
### `win.setSkipTaskbar(skip)`
|
||||
|
||||
* `skip` Boolean
|
||||
|
||||
让窗口不在任务栏中显示.
|
||||
|
||||
### `win.setKiosk(flag)`
|
||||
|
||||
* `flag` Boolean
|
||||
|
||||
进入或离开 kiosk 模式.
|
||||
|
||||
### `win.isKiosk()`
|
||||
|
||||
返回 boolean,是否进入或离开 kiosk 模式.
|
||||
|
||||
### `win.getNativeWindowHandle()`
|
||||
|
||||
以 `Buffer` 形式返回这个具体平台的窗口的句柄.
|
||||
|
||||
windows上句柄类型为 `HWND` ,OS X `NSView*` , Linux `Window`.
|
||||
|
||||
### `win.hookWindowMessage(message, callback)` _Windows_
|
||||
|
||||
* `message` Integer
|
||||
* `callback` Function
|
||||
|
||||
拦截windows 消息,在 WndProc 接收到消息时触发 `callback`函数.
|
||||
|
||||
### `win.isWindowMessageHooked(message)` _Windows_
|
||||
|
||||
* `message` Integer
|
||||
|
||||
返回 `true` or `false` 来代表是否拦截到消息.
|
||||
|
||||
### `win.unhookWindowMessage(message)` _Windows_
|
||||
|
||||
* `message` Integer
|
||||
|
||||
不拦截窗口消息.
|
||||
|
||||
### `win.unhookAllWindowMessages()` _Windows_
|
||||
|
||||
窗口消息全部不拦截.
|
||||
|
||||
### `win.setRepresentedFilename(filename)` _OS X_
|
||||
|
||||
* `filename` String
|
||||
|
||||
设置窗口当前文件路径,并且将这个文件的图标放在窗口标题栏上.
|
||||
|
||||
### `win.getRepresentedFilename()` _OS X_
|
||||
|
||||
获取窗口当前文件路径.
|
||||
|
||||
### `win.setDocumentEdited(edited)` _OS X_
|
||||
|
||||
* `edited` Boolean
|
||||
|
||||
明确指出窗口文档是否可以编辑,如果可以编辑则将标题栏的图标变成灰色.
|
||||
|
||||
### `win.isDocumentEdited()` _OS X_
|
||||
|
||||
返回 boolean,当前窗口文档是否可编辑.
|
||||
|
||||
### `win.focusOnWebView()`
|
||||
|
||||
### `win.blurWebView()`
|
||||
|
||||
### `win.capturePage([rect, ]callback)`
|
||||
|
||||
* `rect` Object (可选) - 捕获Page位置
|
||||
* `x` Integer
|
||||
* `y` Integer
|
||||
* `width` Integer
|
||||
* `height` Integer
|
||||
* `callback` Function
|
||||
|
||||
捕获 `rect` 中的page 的快照.完成后将调用回调函数 `callback` 并返回 `image` . `image` 是存储了快照信息的[NativeImage](native-image.md)实例.如果不设置 `rect` 则将捕获所有可见page.
|
||||
|
||||
### `win.print([options])`
|
||||
|
||||
类似 `webContents.print([options])`
|
||||
|
||||
### `win.printToPDF(options, callback)`
|
||||
|
||||
类似 `webContents.printToPDF(options, callback)`
|
||||
|
||||
### `win.loadURL(url[, options])`
|
||||
|
||||
类似 `webContents.loadURL(url[, options])`.
|
||||
|
||||
### `win.reload()`
|
||||
|
||||
类似 `webContents.reload`.
|
||||
|
||||
### `win.setMenu(menu)` _Linux_ _Windows_
|
||||
|
||||
* `menu` Menu
|
||||
|
||||
设置菜单栏的 `menu` ,设置它为 `null` 则表示不设置菜单栏.
|
||||
|
||||
### `win.setProgressBar(progress)`
|
||||
|
||||
* `progress` Double
|
||||
|
||||
在进度条中设置进度值,有效范围 [0, 1.0].
|
||||
|
||||
当进度小于0时则不显示进度;
|
||||
当进度大于0时显示结果不确定.
|
||||
|
||||
在libux上,只支持Unity桌面环境,需要指明 `*.desktop` 文件并且在 `package.json` 中添加文件名字.默认它为 `app.getName().desktop`.
|
||||
|
||||
### `win.setOverlayIcon(overlay, description)` _Windows 7+_
|
||||
|
||||
* `overlay` [NativeImage](native-image.md) - 在底部任务栏右边显示图标.
|
||||
* `description` String - 描述.
|
||||
|
||||
向当前任务栏添加一个 16 x 16 像素的图标,通常用来覆盖一些应用的状态,或者直接来提示用户.
|
||||
|
||||
### `win.setHasShadow(hasShadow)` _OS X_
|
||||
|
||||
* `hasShadow` (Boolean)
|
||||
|
||||
设置窗口是否应该有阴影.在Windows和Linux系统无效.
|
||||
|
||||
### `win.hasShadow()` _OS X_
|
||||
|
||||
返回 boolean,设置窗口是否有阴影.在Windows和Linux系统始终返回
|
||||
`true`.
|
||||
|
||||
### `win.setThumbarButtons(buttons)` _Windows 7+_
|
||||
|
||||
* `buttons` Array
|
||||
|
||||
在窗口的任务栏button布局出为缩略图添加一个有特殊button的缩略图工具栏. 返回一个 `Boolean` 对象来指示是否成功添加这个缩略图工具栏.
|
||||
|
||||
因为空间有限,缩略图工具栏上的 button 数量不应该超过7个.一旦设置了,由于平台限制,就不能移动它了.但是你可使用一个空数组来调用api来清除 buttons .
|
||||
|
||||
所有 `buttons` 是一个 `Button` 对象数组:
|
||||
|
||||
* `Button` Object
|
||||
* `icon` [NativeImage](native-image.md) - 在工具栏上显示的图标.
|
||||
* `click` Function
|
||||
* `tooltip` String (可选) - tooltip 文字.
|
||||
* `flags` Array (可选) - 控制button的状态和行为. 默认它是 `['enabled']`.
|
||||
|
||||
`flags` 是一个数组,它包含下面这些 `String`s:
|
||||
|
||||
* `enabled` - button 为激活状态并且开放给用户.
|
||||
* `disabled` -button 不可用. 目前它有一个可见的状态来表示它不会响应你的行为.
|
||||
* `dismissonclick` - 点击button,这个缩略窗口直接关闭.
|
||||
* `nobackground` - 不绘制边框,仅仅使用图像.
|
||||
* `hidden` - button 对用户不可见.
|
||||
* `noninteractive` - button 可用但是不可响应; 也不显示按下的状态. 它的值意味着这是一个在通知单使用 button 的实例.
|
||||
|
||||
### `win.showDefinitionForSelection()` _OS X_
|
||||
|
||||
在界面查找选中文字时显示弹出字典.
|
||||
|
||||
### `win.setAutoHideMenuBar(hide)`
|
||||
|
||||
* `hide` Boolean
|
||||
|
||||
设置窗口的菜单栏是否可以自动隐藏. 一旦设置了,只有当用户按下 `Alt` 键时则显示.
|
||||
|
||||
如果菜单栏已经可见,调用 `setAutoHideMenuBar(true)` 则不会立刻隐藏.
|
||||
|
||||
### `win.isMenuBarAutoHide()`
|
||||
|
||||
返回 boolean,窗口的菜单栏是否可以自动隐藏.
|
||||
|
||||
### `win.setMenuBarVisibility(visible)`
|
||||
|
||||
* `visible` Boolean
|
||||
|
||||
设置菜单栏是否可见.如果菜单栏自动隐藏,用户仍然可以按下 `Alt` 键来显示.
|
||||
|
||||
### `win.isMenuBarVisible()`
|
||||
|
||||
返回 boolean,菜单栏是否可见.
|
||||
|
||||
### `win.setVisibleOnAllWorkspaces(visible)`
|
||||
|
||||
* `visible` Boolean
|
||||
|
||||
设置窗口是否在所有地方都可见.
|
||||
|
||||
**注意:** 这个api 在windows无效.
|
||||
|
||||
### `win.isVisibleOnAllWorkspaces()`
|
||||
|
||||
返回 boolean,窗口是否在所有地方都可见.
|
||||
|
||||
**注意:** 在 windows上始终返回 false.
|
||||
|
||||
### `win.setIgnoreMouseEvents(ignore)` _OS X_
|
||||
|
||||
* `ignore` Boolean
|
||||
|
||||
忽略窗口的所有鼠标事件.
|
||||
|
||||
[blink-feature-string]: https://code.google.com/p/chromium/codesearch#chromium/src/out/Debug/gen/blink/platform/RuntimeEnabledFeatures.cpp&sq=package:chromium&type=cs&l=527
|
||||
140
docs-translations/zh-CN/api/chrome-command-line-switches.md
Normal file
140
docs-translations/zh-CN/api/chrome-command-line-switches.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# 支持的 Chrome 命令行开关
|
||||
|
||||
这页列出了Chrome浏览器和Electron支持的命令行开关. 你也可以在[app][app]模块的[ready][ready]事件发出之前使用[app.commandLine.appendSwitch][append-switch] 来添加它们到你应用的main脚本里面:
|
||||
|
||||
```javascript
|
||||
const app = require('electron').app;
|
||||
app.commandLine.appendSwitch('remote-debugging-port', '8315');
|
||||
app.commandLine.appendSwitch('host-rules', 'MAP * 127.0.0.1');
|
||||
|
||||
app.on('ready', function() {
|
||||
// Your code here
|
||||
});
|
||||
```
|
||||
|
||||
## --client-certificate=`path`
|
||||
|
||||
设置客户端的证书文件 `path` .
|
||||
|
||||
## --ignore-connections-limit=`domains`
|
||||
|
||||
忽略用 `,` 分隔的 `domains` 列表的连接限制.
|
||||
|
||||
## --disable-http-cache
|
||||
|
||||
禁用 HTTP 请求.
|
||||
|
||||
## --remote-debugging-port=`port`
|
||||
|
||||
在指定的 `端口` 通过 HTTP 开启远程调试.
|
||||
|
||||
## --js-flags=`flags`
|
||||
|
||||
指定引擎过渡到 JS 引擎.
|
||||
|
||||
在启动Electron时,如果你想在主进程中激活 `flags` ,它将被转换.
|
||||
|
||||
```bash
|
||||
$ electron --js-flags="--harmony_proxies --harmony_collections" your-app
|
||||
```
|
||||
|
||||
## --proxy-server=`address:port`
|
||||
|
||||
使用一个特定的代理服务器,它将比系统设置的优先级更高.这个开关只有在使用 HTTP 协议时有效,它包含 HTTPS 和 WebSocket 请求. 值得注意的是,不是所有的代理服务器都支持 HTTPS 和 WebSocket 请求.
|
||||
|
||||
## --proxy-bypass-list=`hosts`
|
||||
|
||||
让 Electron 使用(原文:bypass) 提供的以 semi-colon 分隔的hosts列表的代理服务器.这个开关只有在使用 `--proxy-server` 时有效.
|
||||
|
||||
例如:
|
||||
|
||||
```javascript
|
||||
app.commandLine.appendSwitch('proxy-bypass-list', '<local>;*.google.com;*foo.com;1.2.3.4:5678')
|
||||
```
|
||||
|
||||
|
||||
将会为所有的hosts使用代理服务器,除了本地地址 (`localhost`,
|
||||
`127.0.0.1` etc.), `google.com` 子域, 以 `foo.com` 结尾的hosts,和所有类似 `1.2.3.4:5678`的.
|
||||
|
||||
## --proxy-pac-url=`url`
|
||||
|
||||
在指定的 `url` 上使用 PAC 脚本.
|
||||
|
||||
## --no-proxy-server
|
||||
|
||||
不使用代理服务并且总是使用直接连接.忽略所有的合理代理标志.
|
||||
|
||||
## --host-rules=`rules`
|
||||
|
||||
一个逗号分隔的 `rule` 列表来控制主机名如何映射.
|
||||
|
||||
例如:
|
||||
|
||||
* `MAP * 127.0.0.1` 强制所有主机名映射到 127.0.0.1
|
||||
* `MAP *.google.com proxy` 强制所有 google.com 子域 使用 "proxy".
|
||||
* `MAP test.com [::1]:77` 强制 "test.com" 使用 IPv6 回环地址. 也强制使用端口 77.
|
||||
* `MAP * baz, EXCLUDE www.google.com` 重新全部映射到 "baz", 除了
|
||||
"www.google.com".
|
||||
|
||||
这些映射适用于终端网络请求
|
||||
(TCP 连接
|
||||
和 主机解析 以直接连接的方式, 和 `CONNECT` 以代理连接, 还有 终端 host 使用 `SOCKS` 代理连接).
|
||||
|
||||
## --host-resolver-rules=`rules`
|
||||
|
||||
类似 `--host-rules` ,但是 `rules` 只适合主机解析.
|
||||
|
||||
## --ignore-certificate-errors
|
||||
|
||||
忽略与证书相关的错误.
|
||||
|
||||
## --ppapi-flash-path=`path`
|
||||
|
||||
设置Pepper Flash插件的路径 `path` .
|
||||
|
||||
## --ppapi-flash-version=`version`
|
||||
|
||||
设置Pepper Flash插件版本号.
|
||||
|
||||
## --log-net-log=`path`
|
||||
|
||||
使网络日志事件能够被读写到 `path`.
|
||||
|
||||
## --ssl-version-fallback-min=`version`
|
||||
|
||||
设置最简化的 SSL/TLS 版本号 ("tls1", "tls1.1" or "tls1.2"),TLS 可接受回退.
|
||||
|
||||
## --cipher-suite-blacklist=`cipher_suites`
|
||||
|
||||
指定逗号分隔的 SSL 密码套件 列表实效.
|
||||
|
||||
## --disable-renderer-backgrounding
|
||||
|
||||
防止 Chromium 降低隐藏的渲染进程优先级.
|
||||
|
||||
这个标志对所有渲染进程全局有效,如果你只想在一个窗口中禁止使用,你可以采用 hack 方法[playing silent audio][play-silent-audio].
|
||||
|
||||
## --enable-logging
|
||||
|
||||
打印 Chromium 信息输出到控制台.
|
||||
|
||||
如果在用户应用加载完成之前解析`app.commandLine.appendSwitch` ,这个开关将实效,但是你可以设置 `ELECTRON_ENABLE_LOGGING` 环境变量来达到相同的效果.
|
||||
|
||||
## --v=`log_level`
|
||||
|
||||
设置默认最大活跃 V-logging 标准; 默认为 0.通常 V-logging 标准值为肯定值.
|
||||
|
||||
这个开关只有在 `--enable-logging` 开启时有效.
|
||||
|
||||
## --vmodule=`pattern`
|
||||
|
||||
赋予每个模块最大的 V-logging levels 来覆盖 `--v` 给的值.E.g. `my_module=2,foo*=3` 会改变所有源文件 `my_module.*` and `foo*.*` 的代码中的 logging level .
|
||||
|
||||
任何包含向前的(forward slash)或者向后的(backward slash)模式将被测试用于阻止整个路径名,并且不仅是E.g模块.`*/foo/bar/*=2` 将会改变所有在 `foo/bar` 下的源文件代码中的 logging level .
|
||||
|
||||
这个开关只有在 `--enable-logging` 开启时有效.
|
||||
|
||||
[app]: app.md
|
||||
[append-switch]: app.md#appcommandlineappendswitchswitch-value
|
||||
[ready]: app.md#event-ready
|
||||
[play-silent-audio]: https://github.com/atom/atom/pull/9485/files
|
||||
129
docs-translations/zh-CN/api/content-tracing.md
Normal file
129
docs-translations/zh-CN/api/content-tracing.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# contentTracing
|
||||
|
||||
`content-tracing` 模块是用来收集由底层的Chromium content 模块 产生的搜索数据. 这个模块不具备web接口,所有需要我们在chrome浏览器中添加 `chrome://tracing/` 来加载生成文件从而查看结果.
|
||||
|
||||
```javascript
|
||||
const contentTracing = require('electron').contentTracing;
|
||||
|
||||
const options = {
|
||||
categoryFilter: '*',
|
||||
traceOptions: 'record-until-full,enable-sampling'
|
||||
}
|
||||
|
||||
contentTracing.startRecording(options, function() {
|
||||
console.log('Tracing started');
|
||||
|
||||
setTimeout(function() {
|
||||
contentTracing.stopRecording('', function(path) {
|
||||
console.log('Tracing data recorded to ' + path);
|
||||
});
|
||||
}, 5000);
|
||||
});
|
||||
```
|
||||
|
||||
## 方法
|
||||
|
||||
`content-tracing` 模块的方法如下:
|
||||
|
||||
### `contentTracing.getCategories(callback)`
|
||||
|
||||
* `callback` Function
|
||||
|
||||
获得一组分类组. 分类组可以更改为新的代码路径。
|
||||
|
||||
一旦所有的子进程都接受到了`getCategories`方法请求, 分类组将调用 `callback`.
|
||||
|
||||
### `contentTracing.startRecording(options, callback)`
|
||||
|
||||
* `options` Object
|
||||
* `categoryFilter` String
|
||||
* `traceOptions` String
|
||||
* `callback` Function
|
||||
|
||||
开始向所有进程进行记录.(recording)
|
||||
|
||||
一旦收到可以开始记录的请求,记录将会立马启动并且在子进程是异步记录听的. 当所有的子进程都收到 `startRecording` 请求的时候,`callback` 将会被调用.
|
||||
|
||||
`categoryFilter`是一个过滤器,它用来控制那些分类组应该被用来查找.过滤器应当有一个可选的 `-` 前缀来排除匹配的分类组.不允许同一个列表既是包含又是排斥.
|
||||
|
||||
例子:
|
||||
|
||||
* `test_MyTest*`,
|
||||
* `test_MyTest*,test_OtherStuff`,
|
||||
* `"-excluded_category1,-excluded_category2`
|
||||
|
||||
`traceOptions` 控制着哪种查找应该被启动,这是一个用逗号分隔的列表.可用参数如下:
|
||||
|
||||
* `record-until-full`
|
||||
* `record-continuously`
|
||||
* `trace-to-console`
|
||||
* `enable-sampling`
|
||||
* `enable-systrace`
|
||||
|
||||
前3个参数是来查找记录模块,并且以后都互斥.如果在`traceOptions` 中超过一个跟踪
|
||||
记录模式,那最后一个的优先级最高.如果没有指明跟踪
|
||||
记录模式,那么它默认为 `record-until-full`.
|
||||
|
||||
在 `traceOptions` 中的参数被解析应用之前,查找参数初始化默认为 (`record_mode` 设置为
|
||||
`record-until-full`, `enable_sampling` 和 `enable_systrace` 设置为 `false`).
|
||||
|
||||
### `contentTracing.stopRecording(resultFilePath, callback)`
|
||||
|
||||
* `resultFilePath` String
|
||||
* `callback` Function
|
||||
|
||||
停止对所有子进程的记录.
|
||||
|
||||
子进程通常缓存查找数据,并且仅仅将数据截取和发送给主进程.这有利于在通过 IPC 发送查找数据之前减小查找时的运行开销,这样做很有价值.因此,发送查找数据,我们应当异步通知所有子进程来截取任何待查找的数据.
|
||||
|
||||
一旦所有子进程接收到了 `stopRecording` 请求,将调用 `callback` ,并且返回一个包含查找数据的文件.
|
||||
|
||||
如果 `resultFilePath` 不为空,那么将把查找数据写入其中,否则写入一个临时文件.实际文件路径如果不为空,则将调用 `callback` .
|
||||
|
||||
### `contentTracing.startMonitoring(options, callback)`
|
||||
|
||||
* `options` Object
|
||||
* `categoryFilter` String
|
||||
* `traceOptions` String
|
||||
* `callback` Function
|
||||
|
||||
开始向所有进程进行监听.(monitoring)
|
||||
|
||||
一旦收到可以开始监听的请求,记录将会立马启动并且在子进程是异步记监听的. 当所有的子进程都收到 `startMonitoring` 请求的时候,`callback` 将会被调用.
|
||||
|
||||
### `contentTracing.stopMonitoring(callback)`
|
||||
|
||||
* `callback` Function
|
||||
|
||||
停止对所有子进程的监听.
|
||||
|
||||
一旦所有子进程接收到了 `stopMonitoring` 请求,将调用 `callback` .
|
||||
|
||||
### `contentTracing.captureMonitoringSnapshot(resultFilePath, callback)`
|
||||
|
||||
* `resultFilePath` String
|
||||
* `callback` Function
|
||||
|
||||
获取当前监听的查找数据.
|
||||
|
||||
子进程通常缓存查找数据,并且仅仅将数据截取和发送给主进程.因为如果直接通过 IPC 来发送查找数据的代价昂贵,我们宁愿避免不必要的查找运行开销.因此,为了停止查找,我们应当异步通知所有子进程来截取任何待查找的数据.
|
||||
|
||||
一旦所有子进程接收到了 `captureMonitoringSnapshot` 请求,将调用 `callback` ,并且返回一个包含查找数据的文件.
|
||||
|
||||
### `contentTracing.getTraceBufferUsage(callback)`
|
||||
|
||||
* `callback` Function
|
||||
|
||||
通过查找 buffer 进程来获取百分比最大使用量.当确定了TraceBufferUsage 的值确定的时候,就调用 `callback` .
|
||||
|
||||
### `contentTracing.setWatchEvent(categoryName, eventName, callback)`
|
||||
|
||||
* `categoryName` String
|
||||
* `eventName` String
|
||||
* `callback` Function
|
||||
|
||||
任意时刻在任何进程上指定事件发生时将调用 `callback` .
|
||||
|
||||
### `contentTracing.cancelWatchEvent()`
|
||||
|
||||
取消 watch 事件. 如果启动查找,这或许会造成 watch 事件的回调函数 出错.
|
||||
94
docs-translations/zh-CN/api/dialog.md
Normal file
94
docs-translations/zh-CN/api/dialog.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# dialog
|
||||
|
||||
`dialog` 模块提供了api来展示原生的系统对话框,例如打开文件框,alert框,所以web应用可以给用户带来跟系统应用相同的体验.
|
||||
|
||||
对话框例子,展示了选择文件和目录:
|
||||
|
||||
```javascript
|
||||
var win = ...; // BrowserWindow in which to show the dialog
|
||||
const dialog = require('electron').dialog;
|
||||
console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', 'multiSelections' ]}));
|
||||
```
|
||||
|
||||
**OS X 上的注意事项**: 如果你想像sheets一样展示对话框,只需要在`browserWindow` 参数中提供一个 `BrowserWindow` 的引用对象.
|
||||
|
||||
## 方法
|
||||
|
||||
`dialog` 模块有以下方法:
|
||||
|
||||
### `dialog.showOpenDialog([browserWindow, ]options[, callback])`
|
||||
|
||||
* `browserWindow` BrowserWindow (可选)
|
||||
* `options` Object
|
||||
* `title` String
|
||||
* `defaultPath` String
|
||||
* `filters` Array
|
||||
* `properties` Array - 包含了对话框的特性值, 可以包含 `openFile`, `openDirectory`, `multiSelections` and
|
||||
`createDirectory`
|
||||
* `callback` Function (可选)
|
||||
|
||||
成功使用这个方法的话,就返回一个可供用户选择的文件路径数组,失败返回 `undefined`.
|
||||
|
||||
`filters` 当需要限定用户的行为的时候,指定一个文件数组给用户展示或选择. 例如:
|
||||
|
||||
```javascript
|
||||
{
|
||||
filters: [
|
||||
{ name: 'Images', extensions: ['jpg', 'png', 'gif'] },
|
||||
{ name: 'Movies', extensions: ['mkv', 'avi', 'mp4'] },
|
||||
{ name: 'Custom File Type', extensions: ['as'] },
|
||||
{ name: 'All Files', extensions: ['*'] }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`extensions` 数组应当只包含扩展名,不应该包含通配符或'.'号 (例如
|
||||
`'png'` 正确,但是 `'.png'` 和 `'*.png'` 不正确). 展示全部文件的话, 使用
|
||||
`'*'` 通配符 (不支持其他通配符).
|
||||
|
||||
如果 `callback` 被调用, 将异步调用 API ,并且结果将用过 `callback(filenames)` 展示.
|
||||
|
||||
**注意:** 在 Windows 和 Linux ,一个打开的 dialog 不能既是文件选择框又是目录选择框, 所以如果在这些平台上设置 `properties` 的值为
|
||||
`['openFile', 'openDirectory']` , 将展示一个目录选择框.
|
||||
|
||||
### `dialog.showSaveDialog([browserWindow, ]options[, callback])`
|
||||
|
||||
* `browserWindow` BrowserWindow (可选)
|
||||
* `options` Object
|
||||
* `title` String
|
||||
* `defaultPath` String
|
||||
* `filters` Array
|
||||
* `callback` Function (可选)
|
||||
|
||||
成功使用这个方法的话,就返回一个可供用户选择的文件路径数组,失败返回 `undefined`.
|
||||
|
||||
`filters` 指定展示一个文件类型数组, 例子
|
||||
`dialog.showOpenDialog` .
|
||||
|
||||
如果 `callback` 被调用, 将异步调用 API ,并且结果将用过 `callback(filenames)` 展示.
|
||||
|
||||
### `dialog.showMessageBox([browserWindow, ]options[, callback])`
|
||||
|
||||
* `browserWindow` BrowserWindow (可选)
|
||||
* `options` Object
|
||||
* `type` String - 可以是 `"none"`, `"info"`, `"error"`, `"question"` 或
|
||||
`"warning"`. 在 Windows, "question" 与 "info" 展示图标相同, 除非你使用 "icon" 参数.
|
||||
* `buttons` Array - buttons 内容,数组.
|
||||
* `defaultId` Integer - 在message box 对话框打开的时候,设置默认button选中,值为在 buttons 数组中的button索引.
|
||||
* `title` String - message box 的标题,一些平台不显示.
|
||||
* `message` String - message box 内容.
|
||||
* `detail` String - 额外信息.
|
||||
* `icon` [NativeImage](native-image.md)
|
||||
* `cancelId` Integer - 当用户关闭对话框的时候,不是通过点击对话框的button,就返回值.默认值为对应 "cancel" 或 "no" 标签button 的索引值, 或者如果没有这种button,就返回0. 在 OS X 和 Windows 上, "Cancel" button 的索引值将一直是 `cancelId`, 不管之前是不是特别指出的.
|
||||
* `noLink` Boolean - 在 Windows ,Electron 将尝试识别哪个button 是普通 button (如 "Cancel" 或 "Yes"), 然后再对话框中以链接命令(command links)方式展现其它的 button . 这能让对话框展示得很炫酷.如果你不喜欢这种效果,你可以设置 `noLink` 为 `true`.
|
||||
* `callback` Function
|
||||
|
||||
展示 message box, 它会阻塞进程,直到 message box 关闭为止.返回点击按钮的索引值.
|
||||
|
||||
如果 `callback` 被调用, 将异步调用 API ,并且结果将用过 `callback(response)` 展示.
|
||||
|
||||
### `dialog.showErrorBox(title, content)`
|
||||
|
||||
展示一个传统的包含错误信息的对话框.
|
||||
|
||||
在 `app` 模块触发 `ready` 事件之前,这个 api 可以被安全调用,通常它被用来在启动的早期阶段报告错误. 在 Linux 上,如果在 `app` 模块触发 `ready` 事件之前调用,message 将会被触发显示stderr,并且没有实际GUI 框显示.
|
||||
53
docs-translations/zh-CN/api/environment-variables.md
Normal file
53
docs-translations/zh-CN/api/environment-variables.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# 环境变量
|
||||
|
||||
一些 Electron 的行为受到环境变量的控制,因为他们的初始化比命令行和应用代码更早.
|
||||
|
||||
POSIX shells 的例子:
|
||||
|
||||
```bash
|
||||
$ export ELECTRON_ENABLE_LOGGING=true
|
||||
$ electron
|
||||
```
|
||||
|
||||
Windows 控制台:
|
||||
|
||||
```powershell
|
||||
> set ELECTRON_ENABLE_LOGGING=true
|
||||
> electron
|
||||
```
|
||||
|
||||
## `ELECTRON_RUN_AS_NODE`
|
||||
|
||||
类似node.js普通进程启动方式.
|
||||
|
||||
## `ELECTRON_ENABLE_LOGGING`
|
||||
|
||||
打印 Chrome 的内部日志到控制台.
|
||||
|
||||
## `ELECTRON_LOG_ASAR_READS`
|
||||
|
||||
当 Electron 读取 ASA 文档,把 read offset 和文档路径做日志记录到系统 `tmpdir`.结果文件将提供给 ASAR 模块来优化文档组织.
|
||||
|
||||
## `ELECTRON_ENABLE_STACK_DUMPING`
|
||||
|
||||
当 Electron 崩溃的时候,打印堆栈记录到控制台.
|
||||
|
||||
如果 `crashReporter` 已经启动那么这个环境变量实效.
|
||||
|
||||
## `ELECTRON_DEFAULT_ERROR_MODE` _Windows_
|
||||
|
||||
当 Electron 崩溃的时候,显示windows的崩溃对话框.
|
||||
|
||||
如果 `crashReporter` 已经启动那么这个环境变量实效.
|
||||
|
||||
## `ELECTRON_NO_ATTACH_CONSOLE` _Windows_
|
||||
|
||||
不可使用当前控制台.
|
||||
|
||||
## `ELECTRON_FORCE_WINDOW_MENU_BAR` _Linux_
|
||||
|
||||
不可再 Linux 上使用全局菜单栏.
|
||||
|
||||
## `ELECTRON_HIDE_INTERNAL_MODULES`
|
||||
|
||||
关闭旧的内置模块如 `require('ipc')` 的通用模块.
|
||||
57
docs-translations/zh-CN/api/menu-item.md
Normal file
57
docs-translations/zh-CN/api/menu-item.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# 菜单项
|
||||
菜单项模块允许你向应用或[menu][1]添加选项。
|
||||
|
||||
查看[menu][1]例子。
|
||||
|
||||
## 类:MenuItem
|
||||
使用下面的方法创建一个新的 `MenuItem`
|
||||
|
||||
###new MenuItem(options)
|
||||
* `options` Object
|
||||
* `click` Function - 当菜单项被点击的时候,使用 `click(menuItem,browserWindow)` 调用
|
||||
* `role` String - 定义菜单项的行为,在指定 `click` 属性时将会被忽略
|
||||
* `type` String - 取值 `normal`,`separator`,`checkbox`or`radio`
|
||||
* `label` String
|
||||
* `sublabel` String
|
||||
* `accelerator` [Accelerator][2]
|
||||
* `icon` [NativeImage][3]
|
||||
* `enabled` Boolean
|
||||
* `visible` Boolean
|
||||
* `checked` Boolean
|
||||
* `submenu` Menu - 应当作为 `submenu` 菜单项的特定类型,当它作为 `type: 'submenu'` 菜单项的特定类型时可以忽略。如果它的值不是 `Menu`,将自动转为 `Menu.buildFromTemplate`。
|
||||
* `id` String - 标志一个菜单的唯一性。如果被定义使用,它将被用作这个菜单项的参考位置属性。
|
||||
* `position` String - 定义给定的菜单的具体指定位置信息。
|
||||
|
||||
在创建菜单项时,如果有匹配的方法,建议指定 `role` 属性,不需要人为操作它的行为,这样菜单使用可以给用户最好的体验。
|
||||
|
||||
|
||||
`role`属性值可以为:
|
||||
|
||||
* `undo`
|
||||
* `redo`
|
||||
* `cut`
|
||||
* `copy`
|
||||
* `paste`
|
||||
* `selectall`
|
||||
* `minimize` - 最小化当前窗口
|
||||
* `close` - 关闭当前窗口
|
||||
|
||||
在 OS X 上,`role` 还可以有以下值:
|
||||
|
||||
* `about` - 匹配 `orderFrontStandardAboutPanel` 行为
|
||||
* `hide` - 匹配 `hide` 行为
|
||||
* `hideothers` - 匹配 `hideOtherApplications` 行为
|
||||
* `unhide` - 匹配 `unhideAllApplications` 行为
|
||||
* `front` - 匹配 `arrangeInFront` 行为
|
||||
* `window` - "Window" 菜单项
|
||||
* `help` - "Help" 菜单项
|
||||
* `services` - "Services" 菜单项
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[1]:https://github.com/heyunjiang/electron/blob/master/docs-translations/zh-CN/api/menu.md
|
||||
[2]:https://github.com/heyunjiang/electron/blob/master/docs/api/accelerator.md
|
||||
[3]:https://github.com/heyunjiang/electron/blob/master/docs/api/native-image.md
|
||||
48
docs-translations/zh-CN/api/process.md
Normal file
48
docs-translations/zh-CN/api/process.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# 进程
|
||||
|
||||
Electron 中的 `process` 对象 与 upstream node 中的有以下的不同点:
|
||||
|
||||
* `process.type` String - 进程类型, 可以是 `browser` (i.e. main process)
|
||||
或 `renderer`.
|
||||
* `process.versions['electron']` String - Electron的版本.
|
||||
* `process.versions['chrome']` String - Chromium的版本.
|
||||
* `process.resourcesPath` String - JavaScript源代码路径.
|
||||
* `process.mas` Boolean - 在Mac App Store 创建, 它的值为 `true`, 在其它的地方值为 `undefined`.
|
||||
|
||||
## 事件
|
||||
|
||||
### 事件: 'loaded'
|
||||
|
||||
在Electron已经加载了其内部预置脚本和它准备加载主进程或渲染进程的时候触发.
|
||||
|
||||
当node被完全关闭的时候,它可以被预加载脚本使用来添加(原文: removed)与node无关的全局符号来回退到全局范围:
|
||||
|
||||
```js
|
||||
// preload.js
|
||||
var _setImmediate = setImmediate;
|
||||
var _clearImmediate = clearImmediate;
|
||||
process.once('loaded', function() {
|
||||
global.setImmediate = _setImmediate;
|
||||
global.clearImmediate = _clearImmediate;
|
||||
});
|
||||
```
|
||||
|
||||
## 属性
|
||||
|
||||
### `process.noAsar`
|
||||
|
||||
设置它为 `true` 可以使 `asar` 文件在node的内置模块中实效.
|
||||
|
||||
## 方法
|
||||
|
||||
`process` 对象有如下方法:
|
||||
|
||||
### `process.hang()`
|
||||
|
||||
使当前进程的主线成挂起.
|
||||
|
||||
### `process.setFdLimit(maxDescriptors)` _OS X_ _Linux_
|
||||
|
||||
* `maxDescriptors` Integer
|
||||
|
||||
设置文件描述符软限制于 `maxDescriptors` 或硬限制与os, 无论它是否低于当前进程.
|
||||
71
docs-translations/zh-CN/api/synopsis.md
Normal file
71
docs-translations/zh-CN/api/synopsis.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# 简介
|
||||
|
||||
所有的[Node.js's built-in modules][1]在Electron中都可用,并且所有的node的第三方组件也可以放心使用(包括[自身的模块][2])。
|
||||
|
||||
Electron也提供了一些额外的内置组件来开发传统桌面应用。一些组件只可以在主进程中使用,一些只可以在渲染进程中使用,但是也有部分可以在这2种进程中都可使用。
|
||||
|
||||
基本规则:GUI模块或者系统底层的模块只可以在主进程中使用。要使用这些模块,你应当很熟悉[主进程vs渲染进程][3]脚本的概念。
|
||||
|
||||
主进程脚本看起来像个普通的nodejs脚本
|
||||
|
||||
```javascript
|
||||
const electron = require('electron');
|
||||
const app = electron.app;
|
||||
const BrowserWindow = electron.BrowserWindow;
|
||||
|
||||
var window = null;
|
||||
|
||||
app.on('ready', function() {
|
||||
window = new BrowserWindow({width: 800, height: 600});
|
||||
window.loadURL('https://github.com');
|
||||
});
|
||||
```
|
||||
|
||||
渲染进程和传统的web界面一样,除了它具有使用node模块的能力:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
const remote = require('electron').remote;
|
||||
console.log(remote.app.getVersion());
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
如果想运行应用,参考 `Run your app` 。
|
||||
|
||||
## 解构任务
|
||||
|
||||
如果你使用的是CoffeeScript或Babel,你可以使用[destructuring assignment][4]来让使用内置模块更简单:
|
||||
|
||||
```javascript
|
||||
const {app, BrowserWindow} = require('electron');
|
||||
```
|
||||
|
||||
然而如果你使用的是普通的JavaScript,你就需要等到Chrome支持ES6了。
|
||||
|
||||
##使用内置模块时禁用旧样式
|
||||
|
||||
在版本v0.35.0之前,所有的内置模块都需要按造 `require('module-name')` 形式来使用,虽然它有很多[弊端][5],我们仍然在老的应用中友好的支持它。
|
||||
|
||||
为了完整的禁用旧样式,你可以设置环境变量 `ELECTRON_HIDE_INTERNAL_MODULES ` :
|
||||
|
||||
```javascript
|
||||
process.env.ELECTRON_HIDE_INTERNAL_MODULES = 'true'
|
||||
```
|
||||
|
||||
或者调用 `hideInternalModules` API:
|
||||
|
||||
```javascript
|
||||
require('electron').hideInternalModules()
|
||||
```
|
||||
|
||||
|
||||
[1]:http://nodejs.org/api/
|
||||
[2]:https://github.com/heyunjiang/electron/blob/master/docs/tutorial/using-native-node-modules.md
|
||||
[3]:https://github.com/heyunjiang/electron/blob/master/docs/tutorial/quick-start.md#the-main-process
|
||||
[4]:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
|
||||
[5]:https://github.com/atom/electron/issues/387
|
||||
690
docs-translations/zh-CN/api/web-view-tag.md
Normal file
690
docs-translations/zh-CN/api/web-view-tag.md
Normal file
@@ -0,0 +1,690 @@
|
||||
# `<webview>` 标签
|
||||
|
||||
使用 `webview` 标签来把 'guest' 内容(例如 web pages )嵌入到你的 Electron app 中. guest内容包含在 `webview` 容器中.一个嵌入你应用的page控制着guest内容如何布局摆放和表达含义.
|
||||
|
||||
与 `iframe` 不同, `webview` 和你的应用运行的是不同的进程. 它不拥有渲染进程的权限,并且应用和嵌入内容之间的交互全部都是异步的.因为这能保证应用的安全性不受嵌入内容的影响.
|
||||
|
||||
## 例子
|
||||
|
||||
把一个 web page 嵌入到你的app,首先添加 `webview` 标签到你的app待嵌入page(展示 guest content). 在一个最简单的 `webview` 中,它包含了 web page 的文件路径和一个控制 `webview` 容器展示效果的css样式:
|
||||
|
||||
```html
|
||||
<webview id="foo" src="https://www.github.com/" style="display:inline-block; width:640px; height:480px"></webview>
|
||||
```
|
||||
|
||||
如果想随时控制 guest 内容,可以添加 JavaScript 脚本来监听 `webview` 事件使用 `webview` 方法来做出响应. 这里是2个事件监听的例子:一个监听 web page 准备加载,另一个监听 web page 停止加载,并且在加载的时候显示一条 "loading..." 信息:
|
||||
|
||||
```html
|
||||
<script>
|
||||
onload = function() {
|
||||
var webview = document.getElementById("foo");
|
||||
var indicator = document.querySelector(".indicator");
|
||||
|
||||
var loadstart = function() {
|
||||
indicator.innerText = "loading...";
|
||||
}
|
||||
var loadstop = function() {
|
||||
indicator.innerText = "";
|
||||
}
|
||||
webview.addEventListener("did-start-loading", loadstart);
|
||||
webview.addEventListener("did-stop-loading", loadstop);
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
## 标签属性
|
||||
|
||||
`webview` 标签有下面一些属性 :
|
||||
|
||||
### `src`
|
||||
|
||||
```html
|
||||
<webview src="https://www.github.com/"></webview>
|
||||
```
|
||||
|
||||
将一个可用的url做为这个属性的初始值添加到顶部导航.
|
||||
|
||||
如果把当前页的src添加进去将加载当前page.
|
||||
|
||||
`src`同样可以填 data urls,例如
|
||||
`data:text/plain,Hello, world!`.
|
||||
|
||||
### `autosize`
|
||||
|
||||
```html
|
||||
<webview src="https://www.github.com/" autosize="on" minwidth="576" minheight="432"></webview>
|
||||
```
|
||||
|
||||
如果这个属性的值为 "on" , `webview` 容器将会根据属性`minwidth`, `minheight`, `maxwidth`, 和
|
||||
`maxheight` 的值在它们之间自适应. 只有在 `autosize` 开启的时候这个约束才会有效. 当 `autosize` 开启的时候, `webview` 容器的 size 只能在上面那四个属性值之间.
|
||||
|
||||
### `nodeintegration`
|
||||
|
||||
```html
|
||||
<webview src="http://www.google.com/" nodeintegration></webview>
|
||||
```
|
||||
|
||||
如果设置了这个属性, `webview` 中的 guest page 将整合node,并且拥有可以使用系统底层的资源,例如 `require` 和 `process` .
|
||||
|
||||
### `plugins`
|
||||
|
||||
```html
|
||||
<webview src="https://www.github.com/" plugins></webview>
|
||||
```
|
||||
|
||||
如果这个属性的值为 "on" , `webview` 中的 guest page 就可以使用浏览器插件。
|
||||
|
||||
### `preload`
|
||||
|
||||
```html
|
||||
<webview src="https://www.github.com/" preload="./test.js"></webview>
|
||||
```
|
||||
|
||||
在 guest page 中的其他脚本执行之前预加载一个指定的脚本。规定预加载脚本的url须如 `file:` 或者 `asar:`,因为它在是 guest page 中通过通过 `require` 命令加载的。
|
||||
|
||||
如果 guest page 没有整合 node ,这个脚本将试图使用真个 Node APIs ,但是在这个脚本执行完毕时,之前由node插入的全局对象会被删除。
|
||||
|
||||
|
||||
### `httpreferrer`
|
||||
|
||||
```html
|
||||
<webview src="https://www.github.com/" httpreferrer="http://cheng.guru"></webview>
|
||||
```
|
||||
|
||||
为 guest page 设置 referrer URL。
|
||||
|
||||
### `useragent`
|
||||
|
||||
```html
|
||||
<webview src="https://www.github.com/" useragent="Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko"></webview>
|
||||
```
|
||||
|
||||
在 guest page 加载之前为其设置用户代理。如果页面已经加载了,可以使用 `setUserAgent` 方法来改变用户代理。
|
||||
|
||||
### `disablewebsecurity`
|
||||
|
||||
```html
|
||||
<webview src="https://www.github.com/" disablewebsecurity></webview>
|
||||
```
|
||||
|
||||
如果这个属性的值为 "on" , guest page会禁用web安全控制.
|
||||
|
||||
### partition
|
||||
|
||||
```html
|
||||
<webview src="https://github.com" partition="persist:github"></webview>
|
||||
<webview src="http://electron.atom.io" partition="electron"></webview>
|
||||
```
|
||||
|
||||
为page设置session。如果初始值为 `partition` ,这个 page 将会为app中的所有 page 应用同一个持续有效的 session。如果没有 `persist:` 前缀, 这个 page 将会使用一个历史 session 。通过分配使用相同的 `partition`, 所有的page都可以分享相同的session。如果 `partition` 没有设置,那app将使用默认的session.
|
||||
|
||||
这个值只能在在第一个渲染进程之前设置修改,之后修改的话会无效并且抛出一个DOM异常.
|
||||
|
||||
### `allowpopups`
|
||||
|
||||
```html
|
||||
<webview src="https://www.github.com/" allowpopups></webview>
|
||||
```
|
||||
|
||||
如果这个属性的值为 "on" ,将允许 guest page 打开一个新窗口。
|
||||
|
||||
### `blinkfeatures`
|
||||
|
||||
```html
|
||||
<webview src="https://www.github.com/" blinkfeatures="PreciseMemoryInfo, CSSVariables"></webview>
|
||||
```
|
||||
|
||||
这个属性的值为一个用逗号分隔的列表,它的值指定特性被启用。你可以从[setFeatureEnabledFromString][blink-feature-string]函数找到完整的支持特性。
|
||||
|
||||
## 方法
|
||||
|
||||
`webview` 的方法集合:
|
||||
|
||||
**注意:** webview 元素必须在使用这些方法之前加载完毕。
|
||||
|
||||
**例如**
|
||||
|
||||
```javascript
|
||||
webview.addEventListener("dom-ready", function() {
|
||||
webview.openDevTools();
|
||||
});
|
||||
```
|
||||
|
||||
### `<webview>.loadURL(url[, options])`
|
||||
|
||||
* `url` URL
|
||||
* `options` Object (可选)
|
||||
* `httpReferrer` String - 一个http类型的url.
|
||||
* `userAgent` String -用于发起请求的用户代理.
|
||||
* `extraHeaders` String - 额外的headers,用 "\n"分隔.
|
||||
|
||||
加载 webview 中的 `url`,`url` 必须包含协议前缀,例如 `http://` 或 `file://`.
|
||||
|
||||
### `<webview>.getURL()`
|
||||
|
||||
从 guest page 中返回 url.
|
||||
|
||||
### `<webview>.getTitle()`
|
||||
|
||||
从 guest page 中返回 title.
|
||||
|
||||
### `<webview>.isLoading()`
|
||||
|
||||
返回一个 guest page 是否仍在加载资源的布尔值.
|
||||
|
||||
### `<webview>.isWaitingForResponse()`
|
||||
|
||||
返回一个 guest page 是否正在等待page的主要资源做出回应的布尔值.
|
||||
|
||||
|
||||
### `<webview>.stop()`
|
||||
|
||||
停止渲染.
|
||||
|
||||
### `<webview>.reload()`
|
||||
|
||||
重新加载 guest page.
|
||||
|
||||
### `<webview>.reloadIgnoringCache()`
|
||||
|
||||
忽视缓存,重新加载 guest page.
|
||||
|
||||
### `<webview>.canGoBack()`
|
||||
|
||||
返回一个 guest page 是否能够回退的布尔值.
|
||||
|
||||
### `<webview>.canGoForward()`
|
||||
|
||||
返回一个 guest page 是否能够前进的布尔值.
|
||||
|
||||
### `<webview>.canGoToOffset(offset)`
|
||||
|
||||
* `offset` Integer
|
||||
|
||||
返回一个 guest page 是否能够前进到 `offset` 的布尔值.
|
||||
|
||||
### `<webview>.clearHistory()`
|
||||
|
||||
清除导航历史.
|
||||
|
||||
### `<webview>.goBack()`
|
||||
|
||||
guest page 回退.
|
||||
|
||||
### `<webview>.goForward()`
|
||||
|
||||
guest page 前进.
|
||||
|
||||
### `<webview>.goToIndex(index)`
|
||||
|
||||
* `index` Integer
|
||||
|
||||
guest page 导航到指定的绝对位置.
|
||||
|
||||
### `<webview>.goToOffset(offset)`
|
||||
|
||||
* `offset` Integer
|
||||
|
||||
guest page 导航到指定的相对位置.
|
||||
|
||||
### `<webview>.isCrashed()`
|
||||
|
||||
返回一个 渲染进程是否崩溃 的布尔值.
|
||||
|
||||
### `<webview>.setUserAgent(userAgent)`
|
||||
|
||||
* `userAgent` String
|
||||
|
||||
重新设置用户代理.
|
||||
|
||||
### `<webview>.getUserAgent()`
|
||||
|
||||
返回用户代理名字,返回类型:`String`.
|
||||
|
||||
### `<webview>.insertCSS(css)`
|
||||
|
||||
* `css` String
|
||||
|
||||
插入css.
|
||||
|
||||
### `<webview>.executeJavaScript(code, userGesture, callback)`
|
||||
|
||||
* `code` String
|
||||
* `userGesture` Boolean - 默认 `false`.
|
||||
* `callback` Function (可选) - 回调函数.
|
||||
* `result`
|
||||
|
||||
评估 `code` ,如果 `userGesture` 值为 true ,它将在这个page里面创建用户手势. HTML APIs ,如 `requestFullScreen`,它需要用户响应,那么将自动通过这个参数优化.
|
||||
|
||||
### `<webview>.openDevTools()`
|
||||
|
||||
为 guest page 打开开发工具调试窗口.
|
||||
|
||||
### `<webview>.closeDevTools()`
|
||||
|
||||
为 guest page 关闭开发工具调试窗口.
|
||||
|
||||
### `<webview>.isDevToolsOpened()`
|
||||
|
||||
返回一个 guest page 是否打开了开发工具调试窗口的布尔值.
|
||||
|
||||
### `<webview>.isDevToolsFocused()`
|
||||
|
||||
返回一个 guest page 是否聚焦了开发工具调试窗口的布尔值.
|
||||
|
||||
### `<webview>.inspectElement(x, y)`
|
||||
|
||||
* `x` Integer
|
||||
* `y` Integer
|
||||
|
||||
开始检查 guest page 在 (`x`, `y`) 位置的元素.
|
||||
|
||||
### `<webview>.inspectServiceWorker()`
|
||||
|
||||
在 guest page 中为服务人员打开开发工具.
|
||||
|
||||
### `<webview>.setAudioMuted(muted)`
|
||||
|
||||
* `muted` Boolean
|
||||
设置 guest page 流畅(muted).
|
||||
|
||||
### `<webview>.isAudioMuted()`
|
||||
|
||||
返回一个 guest page 是否流畅的布尔值.
|
||||
|
||||
### `<webview>.undo()`
|
||||
|
||||
在page中编辑执行 `undo` 命令.
|
||||
|
||||
### `<webview>.redo()`
|
||||
|
||||
在page中编辑执行 `redo` 命令.
|
||||
|
||||
### `<webview>.cut()`
|
||||
|
||||
在page中编辑执行 `cut` 命令.
|
||||
|
||||
### `<webview>.copy()`
|
||||
|
||||
在page中编辑执行 `copy` 命令.
|
||||
|
||||
### `<webview>.paste()`
|
||||
|
||||
在page中编辑执行 `paste` 命令.
|
||||
|
||||
### `<webview>.pasteAndMatchStyle()`
|
||||
|
||||
在page中编辑执行 `pasteAndMatchStyle` 命令.
|
||||
|
||||
### `<webview>.delete()`
|
||||
|
||||
在page中编辑执行 `delete` 命令.
|
||||
|
||||
### `<webview>.selectAll()`
|
||||
|
||||
在page中编辑执行 `selectAll` 命令.
|
||||
|
||||
### `<webview>.unselect()`
|
||||
|
||||
在page中编辑执行 `unselect` 命令.
|
||||
|
||||
### `<webview>.replace(text)`
|
||||
|
||||
* `text` String
|
||||
|
||||
在page中编辑执行 `replace` 命令.
|
||||
|
||||
### `<webview>.replaceMisspelling(text)`
|
||||
|
||||
* `text` String
|
||||
|
||||
在page中编辑执行 `replaceMisspelling` 命令.
|
||||
|
||||
### `<webview>.insertText(text)`
|
||||
|
||||
* `text` String
|
||||
|
||||
插入文本.
|
||||
|
||||
### `<webview>.findInPage(text[, options])`
|
||||
|
||||
* `text` String - 搜索内容,不能为空.
|
||||
* `options` Object (可选)
|
||||
* `forward` Boolean - 向前或向后, 默认为 `true`.
|
||||
* `findNext` Boolean - 是否查找的第一个结果,
|
||||
默认为 `false`.
|
||||
* `matchCase` Boolean - 是否区分大小写,
|
||||
默认为 `false`.
|
||||
* `wordStart` Boolean - 是否只查找首字母.
|
||||
默认为 `false`.
|
||||
* `medialCapitalAsWordStart` Boolean - 当配合 `wordStart`的时候,接受一个文字中的匹配项,要求匹配项是以大写字母开头后面跟小写字母或者没有字母。可以接受一些其他单词内部匹配, 默认为 `false`.
|
||||
|
||||
发起一个请求来寻找页面中的所有匹配 `text` 的地方并且返回一个 `Integer`来表示这个请求用的请求Id. 这个请求结果可以通过订阅[`found-in-page`](web-view-tag.md#event-found-in-page) 事件来取得.
|
||||
|
||||
### `<webview>.stopFindInPage(action)`
|
||||
|
||||
* `action` String - 指定一个行为来接替停止
|
||||
[`<webview>.findInPage`](web-view-tag.md#webviewtagfindinpage) 请求.
|
||||
* `clearSelection` - 转变为一个普通的 selection.
|
||||
* `keepSelection` - 清除 selection.
|
||||
* `activateSelection` - 聚焦并点击 selection node.
|
||||
|
||||
使用 `action` 停止 `findInPage` 请求.
|
||||
|
||||
### `<webview>.print([options])`
|
||||
|
||||
打印输出 `webview` 的 web page. 类似 `webContents.print([options])`.
|
||||
|
||||
### `<webview>.printToPDF(options, callback)`
|
||||
|
||||
以pdf格式打印输出 `webview` 的 web page. 类似 `webContents.printToPDF(options, callback)`.
|
||||
|
||||
### `<webview>.send(channel[, arg1][, arg2][, ...])`
|
||||
|
||||
* `channel` String
|
||||
* `arg` (可选)
|
||||
|
||||
通过 `channel` 向渲染进程发出异步消息,你也可以发送任意的参数。
|
||||
渲染进程通过`ipcRenderer` 模块监听 `channel` 事件来控制消息.
|
||||
|
||||
例子
|
||||
[webContents.send](web-contents.md#webcontentssendchannel-args).
|
||||
|
||||
### `<webview>.sendInputEvent(event)`
|
||||
|
||||
* `event` Object
|
||||
|
||||
向 page 发送输入事件.
|
||||
|
||||
查看 [webContents.sendInputEvent](web-contents.md##webcontentssendinputeventevent)
|
||||
关于 `event` 对象的相信介绍.
|
||||
|
||||
### `<webview>.getWebContents()`
|
||||
|
||||
返回和这个 `webview` 相关的 [WebContents](web-contents.md).
|
||||
|
||||
## DOM 事件
|
||||
|
||||
`webview` 可用下面的 DOM 事件:
|
||||
|
||||
### Event: 'load-commit'
|
||||
|
||||
返回:
|
||||
|
||||
* `url` String
|
||||
* `isMainFrame` Boolean
|
||||
|
||||
加载完成触发. 这个包含当前文档的导航和副框架的文档加载,但是不包含异步资源加载.
|
||||
|
||||
### Event: 'did-finish-load'
|
||||
|
||||
在导航加载完成时触发,也就是tab 的 spinner停止spinning,并且加载事件处理.
|
||||
|
||||
### Event: 'did-fail-load'
|
||||
|
||||
Returns:
|
||||
|
||||
* `errorCode` Integer
|
||||
* `errorDescription` String
|
||||
* `validatedURL` String
|
||||
|
||||
类似 `did-finish-load` ,在加载失败或取消是触发,例如提出 `window.stop()`.
|
||||
|
||||
### Event: 'did-frame-finish-load'
|
||||
|
||||
返回:
|
||||
|
||||
* `isMainFrame` Boolean
|
||||
|
||||
当一个 frame 完成 加载时触发.
|
||||
|
||||
### Event: 'did-start-loading'
|
||||
|
||||
开始加载时触发.
|
||||
|
||||
### Event: 'did-stop-loading'
|
||||
|
||||
停止家在时触发.
|
||||
|
||||
### Event: 'did-get-response-details'
|
||||
|
||||
返回:
|
||||
|
||||
* `status` Boolean
|
||||
* `newURL` String
|
||||
* `originalURL` String
|
||||
* `httpResponseCode` Integer
|
||||
* `requestMethod` String
|
||||
* `referrer` String
|
||||
* `headers` Object
|
||||
|
||||
当获得返回详情的时候触发.
|
||||
|
||||
`status` 指示 socket 连接来下载资源.
|
||||
|
||||
### Event: 'did-get-redirect-request'
|
||||
|
||||
返回:
|
||||
|
||||
* `oldURL` String
|
||||
* `newURL` String
|
||||
* `isMainFrame` Boolean
|
||||
|
||||
当重定向请求资源被接收的时候触发.
|
||||
|
||||
### Event: 'dom-ready'
|
||||
|
||||
当指定的frame文档加载完毕时触发.
|
||||
|
||||
### Event: 'page-title-updated'
|
||||
|
||||
返回:
|
||||
|
||||
* `title` String
|
||||
* `explicitSet` Boolean
|
||||
|
||||
当导航中的页面title被设置时触发.
|
||||
在title通过文档路径异步加载时`explicitSet`为false.
|
||||
|
||||
### Event: 'page-favicon-updated'
|
||||
|
||||
返回:
|
||||
|
||||
* `favicons` Array - Array of URLs.
|
||||
|
||||
当page收到了图标url时触发.
|
||||
|
||||
### Event: 'enter-html-full-screen'
|
||||
|
||||
当通过HTML API使界面进入全屏时触发.
|
||||
|
||||
### Event: 'leave-html-full-screen'
|
||||
|
||||
当通过HTML API使界面退出全屏时触发.
|
||||
|
||||
### Event: 'console-message'
|
||||
|
||||
返回:
|
||||
|
||||
* `level` Integer
|
||||
* `message` String
|
||||
* `line` Integer
|
||||
* `sourceId` String
|
||||
|
||||
当客户端输出控制台信息的时候触发.
|
||||
|
||||
下面示例代码将所有信息输出到内置控制台,没有考虑到输出等级和其他属性。
|
||||
|
||||
```javascript
|
||||
webview.addEventListener('console-message', function(e) {
|
||||
console.log('Guest page logged a message:', e.message);
|
||||
});
|
||||
```
|
||||
|
||||
### Event: 'found-in-page'
|
||||
|
||||
返回:
|
||||
|
||||
* `result` Object
|
||||
* `requestId` Integer
|
||||
* `finalUpdate` Boolean - 指明下面是否还有更多的回应.
|
||||
* `matches` Integer (optional) - 匹配数量.
|
||||
* `selectionArea` Object (optional) - 整合第一个匹配域.
|
||||
|
||||
在请求[`webview.findInPage`](web-view-tag.md#webviewtagfindinpage)结果有效时触发.
|
||||
|
||||
```javascript
|
||||
webview.addEventListener('found-in-page', function(e) {
|
||||
if (e.result.finalUpdate)
|
||||
webview.stopFindInPage("keepSelection");
|
||||
});
|
||||
|
||||
const rquestId = webview.findInPage("test");
|
||||
```
|
||||
|
||||
### Event: 'new-window'
|
||||
|
||||
返回:
|
||||
|
||||
* `url` String
|
||||
* `frameName` String
|
||||
* `disposition` String - 可以为 `default`, `foreground-tab`, `background-tab`,
|
||||
`new-window` 和 `other`.
|
||||
* `options` Object - 参数应该被用作创建新的
|
||||
`BrowserWindow`.
|
||||
|
||||
在 guest page 试图打开一个新的浏览器窗口时触发.
|
||||
|
||||
下面示例代码在系统默认浏览器中打开了一个新的url.
|
||||
|
||||
```javascript
|
||||
webview.addEventListener('new-window', function(e) {
|
||||
require('electron').shell.openExternal(e.url);
|
||||
});
|
||||
```
|
||||
|
||||
### Event: 'will-navigate'
|
||||
|
||||
返回:
|
||||
|
||||
* `url` String
|
||||
|
||||
当用户或page尝试开始导航时触发.
|
||||
它能在 `window.location` 变化或者用户点击连接的时候触发.
|
||||
|
||||
这个事件在以 APIS 编程方式开始导航时不会触发,例如 `<webview>.loadURL` 和 `<webview>.back`.
|
||||
|
||||
在页面内部导航跳转也将不回触发这个事件,例如点击锚链接或更新 `window.location.hash`.使用 `did-navigate-in-page` 来实现页内跳转事件.
|
||||
|
||||
使用 `event.preventDefault()` 并不会起什么用.
|
||||
|
||||
### Event: 'did-navigate'
|
||||
|
||||
返回:
|
||||
|
||||
* `url` String
|
||||
|
||||
当导航结束时触发.
|
||||
|
||||
在页面内部导航跳转也将不回触发这个事件,例如点击锚链接或更新 `window.location.hash`.使用 `did-navigate-in-page` 来实现页内跳转事件.
|
||||
|
||||
### Event: 'did-navigate-in-page'
|
||||
|
||||
返回:
|
||||
|
||||
* `url` String
|
||||
|
||||
当页内导航发生时触发.
|
||||
当业内导航发生时,page url改变了,但是不会跳出 page . 例如在锚链接被电击或DOM `hashchange` 事件发生时触发.
|
||||
|
||||
### Event: 'close'
|
||||
|
||||
在 guest page试图关闭自己的时候触发.
|
||||
|
||||
下面的示例代码指示了在客户端试图关闭自己的时候将改变导航连接为`about:blank`.
|
||||
|
||||
```javascript
|
||||
webview.addEventListener('close', function() {
|
||||
webview.src = 'about:blank';
|
||||
});
|
||||
```
|
||||
|
||||
### Event: 'ipc-message'
|
||||
|
||||
返回:
|
||||
|
||||
* `channel` String
|
||||
* `args` Array
|
||||
|
||||
在 guest page 向嵌入页发送一个异步消息的时候触发.
|
||||
|
||||
你可以很简单的使用 `sendToHost` 方法和 `ipc-message` 事件在 guest page 和 嵌入页(embedder page)之间通信:
|
||||
|
||||
```javascript
|
||||
// In embedder page.
|
||||
webview.addEventListener('ipc-message', function(event) {
|
||||
console.log(event.channel);
|
||||
// Prints "pong"
|
||||
});
|
||||
webview.send('ping');
|
||||
```
|
||||
|
||||
```javascript
|
||||
// In guest page.
|
||||
var ipcRenderer = require('electron').ipcRenderer;
|
||||
ipcRenderer.on('ping', function() {
|
||||
ipcRenderer.sendToHost('pong');
|
||||
});
|
||||
```
|
||||
|
||||
### Event: 'crashed'
|
||||
|
||||
在渲染进程崩溃的时候触发.
|
||||
|
||||
### Event: 'gpu-crashed'
|
||||
|
||||
在GPU进程崩溃的时候触发.
|
||||
|
||||
### Event: 'plugin-crashed'
|
||||
|
||||
返回:
|
||||
|
||||
* `name` String
|
||||
* `version` String
|
||||
|
||||
在插件进程崩溃的时候触发.
|
||||
|
||||
### Event: 'destroyed'
|
||||
|
||||
在界面内容销毁的时候触发.
|
||||
|
||||
### Event: 'media-started-playing'
|
||||
|
||||
在媒体准备播放的时候触发.
|
||||
|
||||
### Event: 'media-paused'
|
||||
|
||||
在媒体暂停播放或播放放毕的时候触发.
|
||||
|
||||
### Event: 'did-change-theme-color'
|
||||
|
||||
在页面的主体色改变的时候触发.
|
||||
在使用 meta 标签的时候这就很常见了:
|
||||
|
||||
```html
|
||||
<meta name='theme-color' content='#ff0000'>
|
||||
```
|
||||
|
||||
### Event: 'devtools-opened'
|
||||
|
||||
在开发者工具打开的时候触发.
|
||||
|
||||
### Event: 'devtools-closed'
|
||||
|
||||
在开发者工具关闭的时候触发.
|
||||
|
||||
### Event: 'devtools-focused'
|
||||
|
||||
在开发者工具获取焦点的时候触发.
|
||||
|
||||
[blink-feature-string]: https://code.google.com/p/chromium/codesearch#chromium/src/out/Debug/gen/blink/platform/RuntimeEnabledFeatures.cpp&sq=package:chromium&type=cs&l=527
|
||||
60
docs-translations/zh-CN/api/window-open.md
Normal file
60
docs-translations/zh-CN/api/window-open.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# `window.open` 函数
|
||||
|
||||
当在界面中使用 `window.open` 来创建一个新的窗口时候,将会创建一个 `BrowserWindow` 的实例,并且将返回一个标识,这个界面通过标识来对这个新的窗口进行有限的控制.
|
||||
|
||||
这个标识对传统的web界面来说,通过它能对子窗口进行有限的功能性兼容控制.
|
||||
想要完全的控制这个窗口,可以直接创建一个 `BrowserWindow` .
|
||||
|
||||
新创建的 `BrowserWindow` 默认为继承父窗口的属性参数,想重写属性的话可以在 `features` 中设置他们.
|
||||
|
||||
### `window.open(url[, frameName][, features])`
|
||||
|
||||
* `url` String
|
||||
* `frameName` String (可选)
|
||||
* `features` String (可选)
|
||||
|
||||
创建一个新的window并且返回一个 `BrowserWindowProxy` 类的实例.
|
||||
|
||||
`features` 遵循标准浏览器的格式,但是每个feature 应该作为 `BrowserWindow` 参数的一个字段.
|
||||
|
||||
### `window.opener.postMessage(message, targetOrigin)`
|
||||
|
||||
* `message` String
|
||||
* `targetOrigin` String
|
||||
|
||||
通过指定位置或用 `*` 来代替没有明确位置来向父窗口发送信息.
|
||||
|
||||
## Class: BrowserWindowProxy
|
||||
|
||||
`BrowserWindowProxy` 由`window.open` 创建返回,并且提供了对子窗口的有限功能性控制.
|
||||
|
||||
### `BrowserWindowProxy.blur()`
|
||||
|
||||
子窗口的失去焦点.
|
||||
### `BrowserWindowProxy.close()`
|
||||
|
||||
强行关闭子窗口,忽略卸载事件.
|
||||
|
||||
### `BrowserWindowProxy.closed`
|
||||
|
||||
在子窗口关闭之后恢复正常.
|
||||
|
||||
### `BrowserWindowProxy.eval(code)`
|
||||
|
||||
* `code` String
|
||||
|
||||
评估子窗口的代码.
|
||||
|
||||
### `BrowserWindowProxy.focus()`
|
||||
|
||||
子窗口获得焦点(让其显示在最前).
|
||||
|
||||
### `BrowserWindowProxy.postMessage(message, targetOrigin)`
|
||||
|
||||
* `message` String
|
||||
* `targetOrigin` String
|
||||
|
||||
|
||||
通过指定位置或用 `*` 来代替没有明确位置来向子窗口发送信息.
|
||||
|
||||
除了这些方法,子窗口还可以无特性和使用单一方法来实现 `window.opener` 对象.
|
||||
139
docs-translations/zh-CN/faq/electron-faq.md
Normal file
139
docs-translations/zh-CN/faq/electron-faq.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# Electron 常见问题
|
||||
|
||||
## Electron 会在什么时候升级到最新版本的 Chrome?
|
||||
|
||||
通常来说,在稳定版的 Chrome 发布后两周内,我们会更新 Electron 内的 Chrome 版本。
|
||||
|
||||
我们只会使用 stable 版本的 Chrome。但如果在 beta 或 dev 版本中有一个重要的更新,我们会把补丁应用到现版本的 Chrome 上。
|
||||
|
||||
## Electron 会在什么时候升级到最新版本的 Node.js?
|
||||
|
||||
我们通常会在最新版的 Node.js 发布后一个月左右将 Electron 更新到这个版本的 Node.js。我们通过这种方式来避免新版本的 Node.js
|
||||
带来的 bug(这种 bug 太常见了)。
|
||||
|
||||
Node.js 的新特性通常是由新版本的 V8 带来的。由于 Electron 使用的是 Chrome 浏览器中附带的 V8 引擎,所以 Electron 内往往已经
|
||||
有了部分新版本 Node.js 才有的崭新特性。
|
||||
|
||||
## 如何在两个网页间共享数据?
|
||||
|
||||
在两个网页(渲染进程)间共享数据最简单的方法是使用浏览器中已经实现的 HTML5 API,比较好的方案是用 [Storage API][storage],
|
||||
[`localStorage`][local-storage],[`sessionStorage`][session-storage] 或者 [IndexedDB][indexed-db]。
|
||||
|
||||
你还可以用 Electron 内的 IPC 机制实现。将数据存在主进程的某个全局变量中,然后在多个渲染进程中使用 `remote` 模块来访问它。
|
||||
|
||||
```javascript
|
||||
// 在主进程中
|
||||
global.sharedObject = {
|
||||
someProperty: 'default value'
|
||||
};
|
||||
```
|
||||
|
||||
```javascript
|
||||
// 在第一个页面中
|
||||
require('remote').getGlobal('sharedObject').someProperty = 'new value';
|
||||
```
|
||||
|
||||
```javascript
|
||||
// 在第二个页面中
|
||||
console.log(require('remote').getGlobal('sharedObject').someProperty);
|
||||
```
|
||||
|
||||
## 为什么应用的窗口、托盘在一段时间后不见了?
|
||||
|
||||
这通常是因为用来存放窗口、托盘的变量被垃圾收集了。
|
||||
|
||||
你可以参考以下两篇文章来了解为什么会遇到这个问题。
|
||||
|
||||
* [内存管理][memory-management]
|
||||
* [变量作用域][variable-scope]
|
||||
|
||||
如果你只是要一个快速的修复方案,你可以用下面的方式改变变量的作用域,防止这个变量被垃圾收集。
|
||||
|
||||
从
|
||||
|
||||
```javascript
|
||||
app.on('ready', function() {
|
||||
var tray = new Tray('/path/to/icon.png');
|
||||
})
|
||||
```
|
||||
|
||||
改为
|
||||
|
||||
```javascript
|
||||
var tray = null;
|
||||
app.on('ready', function() {
|
||||
tray = new Tray('/path/to/icon.png');
|
||||
})
|
||||
```
|
||||
|
||||
## 在 Electron 中,我为什么不能用 jQuery、RequireJS、Meteor、AngularJS?
|
||||
|
||||
因为 Electron 在运行环境中引入了 Node.js,所以在 DOM 中有一些额外的变量,比如 `module`、`exports` 和 `require`。这导致
|
||||
了许多库不能正常运行,因为它们也需要将同名的变量加入运行环境中。
|
||||
|
||||
我们可以通过禁用 Node.js 来解决这个问题,用如下的方式:
|
||||
|
||||
```javascript
|
||||
// 在主进程中
|
||||
var mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
nodeIntegration: false
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
假如你依然需要使用 Node.js 和 Electron 提供的 API,你需要在引入那些库之前将这些变量重命名,比如:
|
||||
|
||||
```html
|
||||
<head>
|
||||
<script>
|
||||
// 重命名 Electron 提供的 require
|
||||
window.nodeRequire = require;
|
||||
delete window.require;
|
||||
delete window.exports;
|
||||
delete window.module;
|
||||
</script>
|
||||
<script type="text/javascript" src="jquery.js"></script>
|
||||
</head>
|
||||
```
|
||||
|
||||
## 为什么 `require('electron').xxx` 的结果是 undefined?
|
||||
|
||||
在使用 Electron 的提供的模块时,你可能会遇到和以下类似的错误:
|
||||
|
||||
```
|
||||
> require('electron').webFrame.setZoomFactor(1.0);
|
||||
Uncaught TypeError: Cannot read property 'setZoomLevel' of undefined
|
||||
```
|
||||
|
||||
这是因为你在项目中或者在全局中安装了[npm 上获取的 `electron` 模块][electron-module],它把 Electron 的内置模块覆写了。
|
||||
|
||||
你可以通过以下方式输出 `electron` 模块的路径来确认你是否使用了正确的模块。
|
||||
|
||||
```javascript
|
||||
console.log(require.resolve('electron'));
|
||||
```
|
||||
|
||||
确认以下它是不是像下面这样的:
|
||||
|
||||
```
|
||||
"/path/to/Electron.app/Contents/Resources/atom.asar/renderer/api/lib/exports/electron.js"
|
||||
```
|
||||
|
||||
假如输出的路径类似于 `node_modules/electron/index.js`,那么你需要移除或者重命名 npm 上的 `electron` 模块。
|
||||
|
||||
```bash
|
||||
npm uninstall electron
|
||||
npm uninstall -g electron
|
||||
```
|
||||
|
||||
如果你依然遇到了这个问题,你可能需要检查一下拼写或者是否在错误的进程中调用了这个模块。比如,
|
||||
`require('electron').app` 只能在主进程中使用, 然而 `require('electron').webFrame` 只能在渲染进程中使用。
|
||||
|
||||
[memory-management]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management
|
||||
[variable-scope]: https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx
|
||||
[electron-module]: https://www.npmjs.com/package/electron
|
||||
[storage]: https://developer.mozilla.org/en-US/docs/Web/API/Storage
|
||||
[local-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
|
||||
[session-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage
|
||||
[indexed-db]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
|
||||
@@ -1,6 +1,7 @@
|
||||
# 应用部署
|
||||
|
||||
为了使用Electron部署你的应用程序,你存放应用程序的文件夹需要叫做 `app` 并且需要放在 Electron 的资源文件夹下(在 OS X 中是指 `Electron.app/Contents/Resources/`,在 Linux 和 Windows 中是指 `resources/`)
|
||||
为了使用 Electron 部署你的应用程序,你存放应用程序的文件夹需要叫做 `app` 并且需要放在 Electron 的
|
||||
资源文件夹下(在 OS X 中是指 `Electron.app/Contents/Resources/`,在 Linux 和 Windows 中是指 `resources/`)
|
||||
就像这样:
|
||||
|
||||
在 OS X 中:
|
||||
@@ -56,7 +57,7 @@ electron/resources/
|
||||
|
||||
你可以将 `electron.exe` 改成任意你喜欢的名字,然后可以使用像
|
||||
[rcedit](https://github.com/atom/rcedit)
|
||||
编辑它的icon和其他信息。
|
||||
编辑它的 icon 和其他信息。
|
||||
|
||||
### OS X
|
||||
|
||||
|
||||
@@ -1,34 +1,38 @@
|
||||
# 应用打包
|
||||
|
||||
为舒缓Windows下路径名过长的问题[issues](https://github.com/joyent/node/issues/6960), 也略对`require`加速以及简单隐匿你的源代码, 你可以通过极小的源代码改动将你的应用打包成[asar][asar].
|
||||
为舒缓 Windows 下路径名过长的问题[issues](https://github.com/joyent/node/issues/6960),
|
||||
也略对 `require` 加速以及简单隐匿你的源代码,你可以通过极小的源代码改动将你的应用打包成 [asar][asar]。
|
||||
|
||||
## 生成`asar`包
|
||||
## 生成 `asar` 包
|
||||
|
||||
[asar][asar]是一种将多个文件合并成一个文件的类tar风格的归档格式。 Electron可以无需解压,即从其中读取任意文件内容。
|
||||
[asar][asar] 是一种将多个文件合并成一个文件的类 tar 风格的归档格式。
|
||||
Electron 可以无需解压,即从其中读取任意文件内容。
|
||||
|
||||
参照如下步骤将你的应用打包成`asar`:
|
||||
参照如下步骤将你的应用打包成 `asar`:
|
||||
|
||||
### 1. 安装asar
|
||||
### 1. 安装 asar
|
||||
|
||||
```bash
|
||||
$ npm install -g asar
|
||||
```
|
||||
|
||||
### 2. 用`asar pack`打包
|
||||
### 2. 用 `asar pack` 打包
|
||||
|
||||
```bash
|
||||
$ asar pack your-app app.asar
|
||||
```
|
||||
|
||||
## 使用`asar`包
|
||||
## 使用 `asar` 包
|
||||
|
||||
在Electron中有两类APIs:Node.js提供的Node APIs和Chromium提供的Web APIs。这两种APIs都支持从`asar`包中读取文件。
|
||||
在 Electron 中有两类 APIs:Node.js 提供的 Node API 和 Chromium 提供的 Web API。
|
||||
这两种 API 都支持从 `asar` 包中读取文件。
|
||||
|
||||
### Node API
|
||||
|
||||
由于Electron中打了特别补丁, Node APIs中如`fs.readFile`或者`require`之类的方法可以将`asar`视之为虚拟文件夹,读取`asar`里面的文件就和从真实的文件系统中读取一样。
|
||||
由于 Electron 中打了特别补丁, Node API 中如 `fs.readFile` 或者 `require` 之类
|
||||
的方法可以将 `asar` 视之为虚拟文件夹,读取 `asar` 里面的文件就和从真实的文件系统中读取一样。
|
||||
|
||||
例如,假设我们在`/path/to`文件夹下有个`example.asar`包:
|
||||
例如,假设我们在 `/path/to` 文件夹下有个 `example.asar` 包:
|
||||
|
||||
```bash
|
||||
$ asar list /path/to/example.asar
|
||||
@@ -40,27 +44,27 @@ $ asar list /path/to/example.asar
|
||||
/static/jquery.min.js
|
||||
```
|
||||
|
||||
从`asar`包读取一个文件:
|
||||
从 `asar` 包读取一个文件:
|
||||
|
||||
```javascript
|
||||
const fs = require('fs');
|
||||
fs.readFileSync('/path/to/example.asar/file.txt');
|
||||
```
|
||||
|
||||
列出`asar`包中根目录下的所有文件:
|
||||
列出 `asar` 包中根目录下的所有文件:
|
||||
|
||||
```javascript
|
||||
const fs = require('fs');
|
||||
fs.readdirSync('/path/to/example.asar');
|
||||
```
|
||||
|
||||
使用`asar`包中的一个模块:
|
||||
使用 `asar` 包中的一个模块:
|
||||
|
||||
```javascript
|
||||
require('/path/to/example.asar/dir/module.js');
|
||||
```
|
||||
|
||||
你也可以使用`BrowserWindow`来显示一个`asar`包里的web页面:
|
||||
你也可以使用 `BrowserWindow` 来显示一个 `asar` 包里的 web 页面:
|
||||
|
||||
```javascript
|
||||
const BrowserWindow = require('electron').BrowserWindow;
|
||||
@@ -70,9 +74,9 @@ win.loadURL('file:///path/to/example.asar/static/index.html');
|
||||
|
||||
### Web API
|
||||
|
||||
在Web页面里,用`file:`协议可以获取`asar`包中文件。和Node API一样,视`asar`包如虚拟文件夹。
|
||||
在 Web 页面里,用 `file:` 协议可以获取 `asar` 包中文件。和 Node API 一样,视 `asar` 包如虚拟文件夹。
|
||||
|
||||
例如,用`$.get`获取文件:
|
||||
例如,用 `$.get` 获取文件:
|
||||
|
||||
```html
|
||||
<script>
|
||||
@@ -83,32 +87,36 @@ $.get('file:///path/to/example.asar/file.txt', function(data) {
|
||||
</script>
|
||||
```
|
||||
|
||||
### 像“文件”那样处理`asar`包
|
||||
### 像“文件”那样处理 `asar` 包
|
||||
|
||||
有些场景,如:核查`asar`包的校验和,我们需要像读取“文件”那样读取`asar`包的内容(而不是当成虚拟文件夹)。你可以使用内置的`original-fs`(提供和`fs`一样的APIs)模块来读取`asar`包的真实信息。
|
||||
有些场景,如:核查 `asar` 包的校验和,我们需要像读取“文件”那样读取 `asar` 包的内容(而不是当成虚拟文件夹)。
|
||||
你可以使用内置的 `original-fs` (提供和 `fs` 一样的 API)模块来读取 `asar` 包的真实信息。
|
||||
|
||||
```javascript
|
||||
var originalFs = require('original-fs');
|
||||
originalFs.readFileSync('/path/to/example.asar');
|
||||
```
|
||||
|
||||
## Node API缺陷
|
||||
## Node API 缺陷
|
||||
|
||||
尽管我们已经尽了最大努力使得`asar`包在Node API下的应用尽可能的趋向于真实的目录结构,但仍有一些底层Node API我们无法保证其正常工作。
|
||||
尽管我们已经尽了最大努力使得 `asar` 包在 Node API 下的应用尽可能的趋向于真实的目录结构,但仍有一些底层 Node API 我们无法保证其正常工作。
|
||||
|
||||
### `asar`包是只读的
|
||||
### `asar` 包是只读的
|
||||
|
||||
`asar`包中的内容不可更改,所以Node APIs里那些可以用来修改文件的方法在对待`asar`包时都无法正常工作。
|
||||
`asar` 包中的内容不可更改,所以 Node APIs 里那些可以用来修改文件的方法在对待 `asar` 包时都无法正常工作。
|
||||
|
||||
### Working Directory在`asar`包中无效
|
||||
### Working Directory 在 `asar` 包中无效
|
||||
|
||||
尽管`asar`包是虚拟文件夹,但其实并没有真实的目录架构对应在文件系统里,所以你不可能将working Directory设置成`asar`包里的一个文件夹。将`asar`中的文件夹以`cwd`形式作为参数传入一些API中也会报错。
|
||||
尽管 `asar` 包是虚拟文件夹,但其实并没有真实的目录架构对应在文件系统里,所以你不可能将 working Directory
|
||||
设置成 `asar` 包里的一个文件夹。将 `asar` 中的文件夹以 `cwd` 形式作为参数传入一些 API 中也会报错。
|
||||
|
||||
### API中的额外“开箱”
|
||||
### API 中的额外“开箱”
|
||||
|
||||
大部分`fs`API可以无需解压即从`asar`包中读取文件或者文件的信息,但是在处理一些依赖真实文件路径的底层系统方法时,Electron会将所需文件解压到临时目录下,然后将临时目录下的真实文件路径传给底层系统方法使其正常工作。 对于这类API,耗费会略多一些。
|
||||
大部分 `fs` API 可以无需解压即从 `asar` 包中读取文件或者文件的信息,但是在处理一些依赖真实文件路径的底层
|
||||
系统方法时,Electron 会将所需文件解压到临时目录下,然后将临时目录下的真实文件路径传给底层系统方法使其正
|
||||
常工作。 对于这类API,耗费会略多一些。
|
||||
|
||||
以下是一些需要额外解压的APIs:
|
||||
以下是一些需要额外解压的 API:
|
||||
|
||||
* `child_process.execFile`
|
||||
* `child_process.execFileSync`
|
||||
@@ -116,26 +124,32 @@ originalFs.readFileSync('/path/to/example.asar');
|
||||
* `fs.openSync`
|
||||
* `process.dlopen` - `require`native模块时用到
|
||||
|
||||
### `fs.stat`获取的stat信息不可靠
|
||||
### `fs.stat` 获取的 stat 信息不可靠
|
||||
|
||||
对`asar`包中的文件取`fs.stat`,返回的`Stats`对象不是精确值,因为这些文件不是真实存在于文件系统里。所以除了文件大小和文件类型以外,你不应该依赖`Stats`对象的值。
|
||||
对 `asar` 包中的文件取 `fs.stat`,返回的 `Stats` 对象不是精确值,因为这些文件不是真实存在于文件系
|
||||
统里。所以除了文件大小和文件类型以外,你不应该依赖 `Stats` 对象的值。
|
||||
|
||||
### 执行`asar`包中的程序
|
||||
### 执行 `asar` 包中的程序
|
||||
|
||||
Node中有一些可以执行程序的API,如`child_process.exec`,`child_process.spawn`和`child_process.execFile`等,但只有`execFile`可以执行`asar`包中的程序。
|
||||
Node 中有一些可以执行程序的 API,如 `child_process.exec`,`child_process.spawn` 和 `child_process.execFile` 等,
|
||||
但只有 `execFile` 可以执行 `asar` 包中的程序。
|
||||
|
||||
因为`exec`和`spawn`允许`command`替代`file`作为输入,而`command`是需要在shell下执行的,目前没有可靠的方法来判断`command`中是否在操作一个`asar`包中的文件,而且即便可以判断,我们依旧无法保证可以在无任何副作用的情况下替换`command`中的文件路径。
|
||||
因为 `exec` 和 `spawn` 允许 `command` 替代 `file` 作为输入,而 `command` 是需要在 shell 下执行的,目前没有
|
||||
可靠的方法来判断 `command` 中是否在操作一个 `asar` 包中的文件,而且即便可以判断,我们依旧无法保证可以在无任何
|
||||
副作用的情况下替换 `command` 中的文件路径。
|
||||
|
||||
## 打包时排除文件
|
||||
|
||||
如上所述,一些Node API会在调用时将文件解压到文件系统中,除了效率问题外,也有可能引起杀毒软件的注意!
|
||||
如上所述,一些 Node API 会在调用时将文件解压到文件系统中,除了效率问题外,也有可能引起杀毒软件的注意!
|
||||
|
||||
为解决这个问题,你可以在生成`asar`包时使用`--unpack`选项来排除一些文件,使其不打包到`asar`包中,下面是如何排除一些用作共享用途的native模块的方法:
|
||||
为解决这个问题,你可以在生成 `asar` 包时使用 `--unpack` 选项来排除一些文件,使其不打包到 `asar` 包中,
|
||||
下面是如何排除一些用作共享用途的 native 模块的方法:
|
||||
|
||||
```bash
|
||||
$ asar pack app app.asar --unpack *.node
|
||||
```
|
||||
|
||||
经过上述命令后,除了生成的`app.asar`包以外,还有一个包含了排除文件的`app.asar.unpacked`文件夹,你需要将这个文件夹一起拷贝,提供给用户。
|
||||
经过上述命令后,除了生成的 `app.asar` 包以外,还有一个包含了排除文件的 `app.asar.unpacked` 文件夹,
|
||||
你需要将这个文件夹一起拷贝,提供给用户。
|
||||
|
||||
[asar]: https://github.com/atom/asar
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 主进程调试
|
||||
|
||||
浏览器窗口的开发工具仅能调试渲染器的进程脚本(比如web 页面)。为了提供一个可以调试主进程
|
||||
浏览器窗口的开发工具仅能调试渲染器的进程脚本(比如 web 页面)。为了提供一个可以调试主进程
|
||||
的方法,Electron 提供了 `--debug` 和 `--debug-brk` 开关。
|
||||
|
||||
## 命令行开关
|
||||
@@ -18,16 +18,31 @@
|
||||
|
||||
## 使用 node-inspector 来调试
|
||||
|
||||
__备注:__ Electron 使用 node v0.11.13 版本,目前对 node-inspector支持的不是特别好,
|
||||
__备注:__ Electron 目前对 node-inspector 支持的不是特别好,
|
||||
如果你通过 node-inspector 的 console 来检查 `process` 对象,主进程就会崩溃。
|
||||
|
||||
### 1. 开始 [node-inspector][node-inspector] 服务
|
||||
### 1. 确认你已经安装了 [node-gyp 所需工具](https://github.com/nodejs/node-gyp#installation)
|
||||
|
||||
### 2. 安装 [node-inspector][node-inspector]
|
||||
|
||||
```bash
|
||||
$ node-inspector
|
||||
$ npm install node-inspector
|
||||
```
|
||||
|
||||
### 2. 打开 Electron 的调试模式
|
||||
### 3. 安装 `node-pre-gyp` 的一个修订版
|
||||
|
||||
```bash
|
||||
$ npm install git+https://git@github.com/enlight/node-pre-gyp.git#detect-electron-runtime-in-find
|
||||
```
|
||||
|
||||
### 4. 为 Electron 重新编译 `node-inspector` `v8` 模块(将 target 参数修改为你的 Electron 的版本号)
|
||||
|
||||
```bash
|
||||
$ node_modules/.bin/node-pre-gyp --target=0.36.2 --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.2 --runtime=electron --fallback-to-build --directory node_modules/v8-profiler/ --dist-url=https://atom.io/download/atom-shell reinstall
|
||||
```
|
||||
|
||||
### 5. 打开 Electron 的调试模式
|
||||
|
||||
你也可以用调试参数来运行 Electron :
|
||||
|
||||
@@ -41,7 +56,13 @@ $ electron --debug=5858 your/app
|
||||
$ electron --debug-brk=5858 your/app
|
||||
```
|
||||
|
||||
### 3. 加载调试器界面
|
||||
### 6. 使用 Electron 开启 [node-inspector][node-inspector] 服务
|
||||
|
||||
```bash
|
||||
$ ELECTRON_RUN_AS_NODE=true path/to/electron.exe node_modules/node-inspector/bin/inspector.js
|
||||
```
|
||||
|
||||
### 7. 加载调试器界面
|
||||
|
||||
在 Chrome 中打开 http://127.0.0.1:8080/debug?ws=127.0.0.1:8080&port=5858
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# DevTools扩展
|
||||
|
||||
为了使调试更容易,Electron原生支持[Chrome DevTools Extension][devtools-extension]。
|
||||
为了使调试更容易,Electron 原生支持 [Chrome DevTools Extension][devtools-extension]。
|
||||
|
||||
对于大多数DevTools的扩展,你可以直接下载源码,然后通过`BrowserWindow.addDevToolsExtension`API加载它们。Electron会记住已经加载了哪些扩展,所以你不需要每次创建一个新window时都调用`BrowserWindow.addDevToolsExtension`API。
|
||||
对于大多数DevTools的扩展,你可以直接下载源码,然后通过 `BrowserWindow.addDevToolsExtension` API 加载它们。Electron会记住已经加载了哪些扩展,所以你不需要每次创建一个新window时都调用 `BrowserWindow.addDevToolsExtension` API。
|
||||
|
||||
** 注:React DevTools目前不能直接工作,详情留意[https://github.com/atom/electron/issues/915](https://github.com/atom/electron/issues/915) **
|
||||
** 注:React DevTools目前不能直接工作,详情留意 [https://github.com/atom/electron/issues/915](https://github.com/atom/electron/issues/915) **
|
||||
|
||||
例如,要用[React DevTools Extension](https://github.com/facebook/react-devtools),你得先下载他的源码:
|
||||
|
||||
@@ -13,33 +13,33 @@ $ cd /some-directory
|
||||
$ git clone --recursive https://github.com/facebook/react-devtools.git
|
||||
```
|
||||
|
||||
参考[`react-devtools/shells/chrome/Readme.md`](https://github.com/facebook/react-devtools/blob/master/shells/chrome/Readme.md)来编译这个扩展源码。
|
||||
参考 [`react-devtools/shells/chrome/Readme.md`](https://github.com/facebook/react-devtools/blob/master/shells/chrome/Readme.md) 来编译这个扩展源码。
|
||||
|
||||
然后你就可以在任意页面的DevTools里加载React DevTools了,通过控制台输入如下命令加载扩展:
|
||||
然后你就可以在任意页面的 DevTools 里加载 React DevTools 了,通过控制台输入如下命令加载扩展:
|
||||
|
||||
```javascript
|
||||
const BrowserWindow = require('electron').remote.BrowserWindow;
|
||||
BrowserWindow.addDevToolsExtension('/some-directory/react-devtools/shells/chrome');
|
||||
```
|
||||
|
||||
要卸载扩展,可以调用`BrowserWindow.removeDevToolsExtension`API(扩展名作为参数传入),该扩展在下次打开DevTools时就不会加载了:
|
||||
要卸载扩展,可以调用 `BrowserWindow.removeDevToolsExtension` API (扩展名作为参数传入),该扩展在下次打开DevTools时就不会加载了:
|
||||
|
||||
```javascript
|
||||
BrowserWindow.removeDevToolsExtension('React Developer Tools');
|
||||
```
|
||||
|
||||
## DevTools扩展的格式
|
||||
## DevTools 扩展的格式
|
||||
|
||||
理论上,Electron可以加载所有为chrome浏览器编写的DevTools扩展,但它们必须存放在文件夹里。那些以`crx`形式发布的扩展是不能被加载的,除非你把它们解压到一个文件夹里。
|
||||
理论上,Electron 可以加载所有为 chrome 浏览器编写的 DevTools 扩展,但它们必须存放在文件夹里。那些以 `crx` 形式发布的扩展是不能被加载的,除非你把它们解压到一个文件夹里。
|
||||
|
||||
## 后台运行(background pages)
|
||||
|
||||
Electron目前并不支持chrome扩展里的后台运行(background pages)功能,所以那些依赖此特性的DevTools扩展在Electron里可能无法正常工作。
|
||||
Electron 目前并不支持 chrome 扩展里的后台运行(background pages)功能,所以那些依赖此特性的 DevTools 扩展在 Electron 里可能无法正常工作。
|
||||
|
||||
## `chrome.*` APIs
|
||||
|
||||
有些chrome扩展使用了`chrome.*`APIs,而且这些扩展在Electron中需要额外实现一些代码才能使用,所以并不是所有的这类扩展都已经在Electron中实现完毕了。
|
||||
有些 chrome 扩展使用了 `chrome.*`APIs,而且这些扩展在 Electron 中需要额外实现一些代码才能使用,所以并不是所有的这类扩展都已经在 Electron 中实现完毕了。
|
||||
|
||||
考虑到并非所有的`chrome.*`APIs都实现完毕,如果DevTools正在使用除了`chrome.devtools.*`之外的其它APIs,这个扩展很可能无法正常工作。你可以通过报告这个扩展的异常信息,这样做方便我们对该扩展的支持。
|
||||
考虑到并非所有的 `chrome.*`APIs 都实现完毕,如果 DevTools 正在使用除了 `chrome.devtools.*` 之外的其它 APIs,这个扩展很可能无法正常工作。你可以通过报告这个扩展的异常信息,这样做方便我们对该扩展的支持。
|
||||
|
||||
[devtools-extension]: https://developer.chrome.com/extensions/devtools
|
||||
|
||||
@@ -20,7 +20,7 @@ Ubuntu 12.04 下编译的,`arm` 版的二进制文件是在 ARM v7(硬浮点
|
||||
Debian Wheezy 版本的 NEON)下完成的。
|
||||
|
||||
预编译二进制文件是否能够运行,取决于其中是否包括了编译平台链接的库,所以只有 Ubuntu 12.04
|
||||
可以保证正常工作,但是以下的平台也被证实可以运行 Electron的预编译版本:
|
||||
可以保证正常工作,但是以下的平台也被证实可以运行 Electron 的预编译版本:
|
||||
|
||||
* Ubuntu 12.04 及更新
|
||||
* Fedora 21
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# 使用原生模块
|
||||
|
||||
Electron同样也支持原生模块,但由于和官方的Node相比使用了不同的V8引擎,如果你想编译原生模块,则需要手动设置Electron的headers的位置。
|
||||
Electron 同样也支持原生模块,但由于和官方的 Node 相比使用了不同的 V8 引擎,如果你想编译原生模块,则需要手动设置 Electron 的 headers 的位置。
|
||||
|
||||
## 原生Node模块的兼容性
|
||||
|
||||
当Node开始换新的V8引擎版本时,原生模块可能“坏”掉。为确保一切工作正常,你需要检查你想要使用的原生模块是否被Electron内置的Node支持。你可以在[这里](https://github.com/atom/electron/releases)查看Electron内置的Node版本,或者使用`process.version`(参考:[快速入门](https://github.com/atom/electron/blob/master/docs/tutorial/quick-start.md))查看。
|
||||
当 Node 开始换新的V8引擎版本时,原生模块可能“坏”掉。为确保一切工作正常,你需要检查你想要使用的原生模块是否被 Electron 内置的 Node 支持。你可以在[这里](https://github.com/atom/electron/releases)查看 Electron 内置的 Node 版本,或者使用 `process.version` (参考:[快速入门](https://github.com/atom/electron/blob/master/docs/tutorial/quick-start.md))查看。
|
||||
|
||||
考虑到[NAN](https://github.com/nodejs/nan/)可以使你的开发更容易对多版本Node的支持,建议使用它来开发你自己的模块。你也可以使用[NAN](https://github.com/nodejs/nan/)来移植旧的模块到新的Node版本,以使它们可以在新的Electron下良好工作。
|
||||
考虑到 [NAN](https://github.com/nodejs/nan/) 可以使你的开发更容易对多版本 Node 的支持,建议使用它来开发你自己的模块。你也可以使用 [NAN](https://github.com/nodejs/nan/) 来移植旧的模块到新的 Nod e版本,以使它们可以在新的 Electron 下良好工作。
|
||||
|
||||
## 如何安装原生模块
|
||||
|
||||
@@ -14,7 +14,7 @@ Electron同样也支持原生模块,但由于和官方的Node相比使用了
|
||||
|
||||
### 最简单方式
|
||||
|
||||
最简单的方式就是通过[`electron-rebuild`](https://github.com/paulcbetts/electron-rebuild)包重新编译原生模块,它帮你自动完成了下载headers、编译原生模块等步骤:
|
||||
最简单的方式就是通过 [`electron-rebuild`](https://github.com/paulcbetts/electron-rebuild) 包重新编译原生模块,它帮你自动完成了下载 headers、编译原生模块等步骤:
|
||||
|
||||
```sh
|
||||
npm install --save-dev electron-rebuild
|
||||
@@ -26,9 +26,9 @@ npm install --save-dev electron-rebuild
|
||||
.\node_modules\.bin\electron-rebuild.cmd
|
||||
```
|
||||
|
||||
### 通过npm安装
|
||||
### 通过 npm 安装
|
||||
|
||||
你当然也可以通过`npm`安装原生模块。大部分步骤和安装普通模块时一样,除了以下一些系统环境变量你需要自己操作:
|
||||
你当然也可以通过 `npm` 安装原生模块。大部分步骤和安装普通模块时一样,除了以下一些系统环境变量你需要自己操作:
|
||||
|
||||
```bash
|
||||
export npm_config_disturl=https://atom.io/download/atom-shell
|
||||
@@ -38,16 +38,19 @@ export npm_config_runtime=electron
|
||||
HOME=~/.electron-gyp npm install module-name
|
||||
```
|
||||
|
||||
### 通过node-gyp安装
|
||||
### 通过 node-gyp 安装
|
||||
|
||||
你需要告诉`node-gyp`去哪下载Electron的headers,以及下载什么版本:
|
||||
你需要告诉 `node-gyp` 去哪下载 Electron 的 headers,以及下载什么版本:
|
||||
|
||||
```bash
|
||||
$ cd /path-to-module/
|
||||
$ HOME=~/.electron-gyp node-gyp rebuild --target=0.29.1 --arch=x64 --dist-url=https://atom.io/download/atom-shell
|
||||
```
|
||||
|
||||
`HOME=~/.electron-gyp`设置了去哪找开发时的headers。
|
||||
`--target=0.29.1`设置了Electron的版本
|
||||
`--dist-url=...`设置了Electron的headers的下载地址
|
||||
`--arch=x64`设置了该模块为适配64bit操作系统而编译
|
||||
`HOME=~/.electron-gyp` 设置去哪找开发时的 headers。
|
||||
|
||||
`--target=0.29.1` 设置了 Electron 的版本
|
||||
|
||||
`--dist-url=...` 设置了 Electron 的 headers 的下载地址
|
||||
|
||||
`--arch=x64` 设置了该模块为适配64位操作系统而编译
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# 使用 Pepper Flash 插件
|
||||
|
||||
Electron 现在支持 Pepper Flash 插件。要在 Electron 里面使用 Pepper Flash 插件,你需
|
||||
要手动设置 Pepper Flash 的路径和在你的应用里启用 Pepper Flash。
|
||||
|
||||
## 保留一份 Flash 插件的副本
|
||||
|
||||
在 OS X 和 Linux 上,你可以在 Chrome 浏览器的 `chrome://plugins` 页面上找到 Pepper
|
||||
Flash 的插件信息。插件的路径和版本会对 Election 对其的支持有帮助。你也可以把插件
|
||||
复制到另一个路径以保留一份副本。
|
||||
|
||||
## 添加插件在 Electron 里的开关
|
||||
|
||||
你可以直接在命令行中用 `--ppapi-flash-path` 和 `ppapi-flash-version` 或者
|
||||
在 app 的准备事件前调用 `app.commandLine.appendSwitch` 这个 method。同时,
|
||||
添加 `browser-window` 的插件开关。
|
||||
例如:
|
||||
|
||||
```javascript
|
||||
// Specify flash path. 设置 flash 路径
|
||||
// On Windows, it might be /path/to/pepflashplayer.dll
|
||||
// On OS X, /path/to/PepperFlashPlayer.plugin
|
||||
// On Linux, /path/to/libpepflashplayer.so
|
||||
app.commandLine.appendSwitch('ppapi-flash-path', '/path/to/libpepflashplayer.so');
|
||||
|
||||
// Specify flash version, for example, v17.0.0.169 设置版本号
|
||||
app.commandLine.appendSwitch('ppapi-flash-version', '17.0.0.169');
|
||||
|
||||
app.on('ready', function() {
|
||||
mainWindow = new BrowserWindow({
|
||||
'width': 800,
|
||||
'height': 600,
|
||||
'web-preferences': {
|
||||
'plugins': true
|
||||
}
|
||||
});
|
||||
mainWindow.loadURL('file://' + __dirname + '/index.html');
|
||||
// Something else
|
||||
});
|
||||
```
|
||||
|
||||
## 使用 `<webview>` 标签启用插件
|
||||
|
||||
在 `<webview>` 标签里添加 `plugins` 属性。
|
||||
|
||||
```html
|
||||
<webview src="http://www.adobe.com/software/flash/about/" plugins></webview>
|
||||
```
|
||||
@@ -1,18 +1,18 @@
|
||||
# 使用Selenium和WebDriver
|
||||
# 使用 Selenium 和 WebDriver
|
||||
|
||||
引自[ChromeDriver - WebDriver for Chrome][chrome-driver]:
|
||||
|
||||
> WebDriver是一款开源的支持多浏览器的自动化测试工具。它提供了操作网页、用户输入、JavaScript执行等能力。ChromeDriver是一个实现了WebDriver与Chromium联接协议的独立服务。它也是由开发了Chromium和WebDriver的团队开发的。
|
||||
> WebDriver 是一款开源的支持多浏览器的自动化测试工具。它提供了操作网页、用户输入、JavaScript 执行等能力。ChromeDriver 是一个实现了 WebDriver 与 Chromium 联接协议的独立服务。它也是由开发了 Chromium 和 WebDriver 的团队开发的。
|
||||
|
||||
为了能够使`chromedriver`和Electron一起正常工作,我们需要告诉它Electron在哪,并且让它相信Electron就是Chrome浏览器。
|
||||
为了能够使 `chromedriver` 和 Electron 一起正常工作,我们需要告诉它 Electron 在哪,并且让它相信 Electron 就是 Chrome 浏览器。
|
||||
|
||||
## 通过WebDriverJs配置
|
||||
## 通过 WebDriverJs 配置
|
||||
|
||||
[WebDriverJs](https://code.google.com/p/selenium/wiki/WebDriverJs) 是一个可以配合WebDriver做测试的node模块,我们会用它来做个演示。
|
||||
[WebDriverJs](https://code.google.com/p/selenium/wiki/WebDriverJs) 是一个可以配合 WebDriver 做测试的 node 模块,我们会用它来做个演示。
|
||||
|
||||
### 1. 启动ChromeDriver
|
||||
### 1. 启动 ChromeDriver
|
||||
|
||||
首先,你要下载`chromedriver`,然后运行以下命令:
|
||||
首先,你要下载 `chromedriver`,然后运行以下命令:
|
||||
|
||||
```bash
|
||||
$ ./chromedriver
|
||||
@@ -20,17 +20,17 @@ Starting ChromeDriver (v2.10.291558) on port 9515
|
||||
Only local connections are allowed.
|
||||
```
|
||||
|
||||
记住`9515`这个端口号,我们后面会用到
|
||||
记住 `9515` 这个端口号,我们后面会用到
|
||||
|
||||
### 2. 安装WebDriverJS
|
||||
### 2. 安装 WebDriverJS
|
||||
|
||||
```bash
|
||||
$ npm install selenium-webdriver
|
||||
```
|
||||
|
||||
### 3. 联接到ChromeDriver
|
||||
### 3. 联接到 ChromeDriver
|
||||
|
||||
在Electron下使用`selenium-webdriver`和其平时的用法并没有大的差异,只是你需要手动设置连接ChromeDriver,以及Electron的路径:
|
||||
在 Electron 下使用 `selenium-webdriver` 和其平时的用法并没有大的差异,只是你需要手动设置连接 ChromeDriver,以及 Electron 的路径:
|
||||
|
||||
```javascript
|
||||
const webdriver = require('selenium-webdriver');
|
||||
@@ -59,13 +59,13 @@ driver.wait(function() {
|
||||
driver.quit();
|
||||
```
|
||||
|
||||
## 通过WebdriverIO配置
|
||||
## 通过 WebdriverIO 配置
|
||||
|
||||
[WebdriverIO](http://webdriver.io/)也是一个配合WebDriver用来测试的node模块
|
||||
[WebdriverIO](http://webdriver.io/) 也是一个配合 WebDriver 用来测试的 node 模块
|
||||
|
||||
### 1. 启动ChromeDriver
|
||||
### 1. 启动 ChromeDriver
|
||||
|
||||
首先,下载`chromedriver`,然后运行以下命令:
|
||||
首先,下载 `chromedriver`,然后运行以下命令:
|
||||
|
||||
```bash
|
||||
$ chromedriver --url-base=wd/hub --port=9515
|
||||
@@ -73,15 +73,15 @@ Starting ChromeDriver (v2.10.291558) on port 9515
|
||||
Only local connections are allowed.
|
||||
```
|
||||
|
||||
记住`9515`端口,后面会用到
|
||||
记住 `9515` 端口,后面会用到
|
||||
|
||||
### 2. 安装WebdriverIO
|
||||
### 2. 安装 WebdriverIO
|
||||
|
||||
```bash
|
||||
$ npm install webdriverio
|
||||
```
|
||||
|
||||
### 3. 连接到ChromeDriver
|
||||
### 3. 连接到 ChromeDriver
|
||||
|
||||
```javascript
|
||||
const webdriverio = require('webdriverio');
|
||||
@@ -112,8 +112,8 @@ client
|
||||
|
||||
## 工作流程
|
||||
|
||||
无需重新编译Electron,只要把app的源码放到[Electron的资源目录](https://github.com/atom/electron/blob/master/docs/tutorial/application-distribution.md)里就可直接开始测试了。
|
||||
无需重新编译 Electron,只要把 app 的源码放到 [Electron的资源目录](https://github.com/atom/electron/blob/master/docs/tutorial/application-distribution.md) 里就可直接开始测试了。
|
||||
|
||||
当然,你也可以在运行Electron时传入参数指定你app的所在文件夹。这步可以免去你拷贝-粘贴你的app到Electron的资源目录。
|
||||
当然,你也可以在运行 Electron 时传入参数指定你 app 的所在文件夹。这步可以免去你拷贝-粘贴你的 app 到 Electron 的资源目录。
|
||||
|
||||
[chrome-driver]: https://sites.google.com/a/chromium.org/chromedriver/
|
||||
|
||||
@@ -26,6 +26,7 @@ an issue:
|
||||
* [DevTools Extension](tutorial/devtools-extension.md)
|
||||
* [Using Pepper Flash Plugin](tutorial/using-pepper-flash-plugin.md)
|
||||
* [Using Widevine CDM Plugin](tutorial/using-widevine-cdm-plugin.md)
|
||||
* [Testing on Headless CI Systems (Travis, Jenkins)](tutorial/testing-on-headless-ci.md)
|
||||
|
||||
## Tutorials
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ The `Super` key is mapped to the `Windows` key on Windows and Linux and
|
||||
* `Control` (or `Ctrl` for short)
|
||||
* `CommandOrControl` (or `CmdOrCtrl` for short)
|
||||
* `Alt`
|
||||
* `Option`
|
||||
* `AltGr`
|
||||
* `Shift`
|
||||
* `Super`
|
||||
|
||||
@@ -44,3 +46,4 @@ The `Super` key is mapped to the `Windows` key on Windows and Linux and
|
||||
* `Escape` (or `Esc` for short)
|
||||
* `VolumeUp`, `VolumeDown` and `VolumeMute`
|
||||
* `MediaNextTrack`, `MediaPreviousTrack`, `MediaStop` and `MediaPlayPause`
|
||||
* `PrintScreen`
|
||||
|
||||
@@ -156,7 +156,7 @@ certificate you should prevent the default behavior with
|
||||
`event.preventDefault()` and call `callback(true)`.
|
||||
|
||||
```javascript
|
||||
session.on('certificate-error', function(event, webContents, url, error, certificate, callback) {
|
||||
app.on('certificate-error', function(event, webContents, url, error, certificate, callback) {
|
||||
if (url == "https://github.com") {
|
||||
// Verification logic.
|
||||
event.preventDefault();
|
||||
@@ -228,6 +228,10 @@ app.on('login', function(event, webContents, request, authInfo, callback) {
|
||||
|
||||
Emitted when the gpu process crashes.
|
||||
|
||||
### Event: 'platform-theme-changed' _OS X_
|
||||
|
||||
Emitted when the system's Dark Mode theme is toggled.
|
||||
|
||||
## Methods
|
||||
|
||||
The `app` object has the following methods:
|
||||
@@ -244,14 +248,6 @@ This method guarantees that all `beforeunload` and `unload` event handlers are
|
||||
correctly executed. It is possible that a window cancels the quitting by
|
||||
returning `false` in the `beforeunload` event handler.
|
||||
|
||||
### `app.hide()` _OS X_
|
||||
|
||||
Hides all application windows without minimizing them.
|
||||
|
||||
### `app.show()` _OS X_
|
||||
|
||||
Shows application windows after they were hidden. Does not automatically focus them.
|
||||
|
||||
### `app.exit(exitCode)`
|
||||
|
||||
* `exitCode` Integer
|
||||
@@ -261,6 +257,19 @@ Exits immediately with `exitCode`.
|
||||
All windows will be closed immediately without asking user and the `before-quit`
|
||||
and `will-quit` events will not be emitted.
|
||||
|
||||
### `app.focus()`
|
||||
|
||||
On Linux, focuses on the first visible window. On OS X, makes the application
|
||||
the active app. On Windows, focuses on the application's first window.
|
||||
|
||||
### `app.hide()` _OS X_
|
||||
|
||||
Hides all application windows without minimizing them.
|
||||
|
||||
### `app.show()` _OS X_
|
||||
|
||||
Shows application windows after they were hidden. Does not automatically focus them.
|
||||
|
||||
### `app.getAppPath()`
|
||||
|
||||
Returns the current application directory.
|
||||
@@ -461,6 +470,10 @@ if (browserOptions.transparent) {
|
||||
}
|
||||
```
|
||||
|
||||
### `app.isDarkMode()` _OS X_
|
||||
|
||||
This method returns `true` if the system is in Dark Mode, and `false` otherwise.
|
||||
|
||||
### `app.commandLine.appendSwitch(switch[, value])`
|
||||
|
||||
Append a switch (with optional `value`) to Chromium's command line.
|
||||
|
||||
@@ -58,9 +58,8 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
* `alwaysOnTop` Boolean - Whether the window should always stay on top of
|
||||
other windows. Default is `false`.
|
||||
* `fullscreen` Boolean - Whether the window should show in fullscreen. When
|
||||
explicitly set to `false` the fullscreen button will be hidden or disabled
|
||||
on OS X, or the maximize button will be disabled on Windows. Default is
|
||||
`false`.
|
||||
explicity set to `false` the fullscreen button will be hidden or disabled
|
||||
on OS X. Default is `false`.
|
||||
* `fullscreenable` Boolean - Whether the maximize/zoom button on OS X should
|
||||
toggle full screen mode or maximize window. Default is `true`.
|
||||
* `skipTaskbar` Boolean - Whether to show the window in taskbar. Default is
|
||||
@@ -246,6 +245,14 @@ Emitted when the window loses focus.
|
||||
|
||||
Emitted when the window gains focus.
|
||||
|
||||
### Event: 'show'
|
||||
|
||||
Emitted when the window is shown.
|
||||
|
||||
### Event: 'hide'
|
||||
|
||||
Emitted when the window is hidden.
|
||||
|
||||
### Event: 'maximize'
|
||||
|
||||
Emitted when window is maximized.
|
||||
@@ -398,6 +405,10 @@ the [close event](#event-close).
|
||||
|
||||
Focus on the window.
|
||||
|
||||
### `win.blur()`
|
||||
|
||||
Remove focus on the window.
|
||||
|
||||
### `win.isFocused()`
|
||||
|
||||
Returns a boolean, whether the window is focused.
|
||||
@@ -582,17 +593,17 @@ nothing.
|
||||
Returns whether the window can be manually maximized by user. On Linux always
|
||||
returns `true`.
|
||||
|
||||
### `win.setFullScreenable(fullscreenable)` _OS X_
|
||||
### `win.setFullScreenable(fullscreenable)`
|
||||
|
||||
* `fullscreenable` Boolean
|
||||
|
||||
Sets whether the maximize/zoom window button toggles fullscreen mode or
|
||||
maximizes the window. On Windows and Linux does nothing.
|
||||
maximizes the window.
|
||||
|
||||
### `win.isFullScreenable()` _OS X_
|
||||
### `win.isFullScreenable()`
|
||||
|
||||
Returns whether the maximize/zoom window button toggles fullscreen mode or
|
||||
maximizes the window. On Windows and Linux always returns `true`.
|
||||
maximizes the window.
|
||||
|
||||
### `win.setClosable(closable)` _OS X_ _Windows_
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ var template = [
|
||||
];
|
||||
|
||||
if (process.platform == 'darwin') {
|
||||
var name = require('electron').app.getName();
|
||||
var name = require('electron').remote.app.getName();
|
||||
template.unshift({
|
||||
label: name,
|
||||
submenu: [
|
||||
@@ -227,6 +227,9 @@ Sends the `action` to the first responder of application. This is used for
|
||||
emulating default Cocoa menu behaviors, usually you would just use the
|
||||
`role` property of `MenuItem`.
|
||||
|
||||
See the [OS X Cocoa Event Handling Guide](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/EventOverview/EventArchitecture/EventArchitecture.html#//apple_ref/doc/uid/10000060i-CH3-SW7)
|
||||
for more information on OS X's native actions.
|
||||
|
||||
### `Menu.buildFromTemplate(template)`
|
||||
|
||||
* `template` Array
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user