mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
195 Commits
v1.8.1
...
v1.8.2-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
306b627090 | ||
|
|
90e7d7e112 | ||
|
|
7be79613b8 | ||
|
|
cf12d31875 | ||
|
|
32f92f7a90 | ||
|
|
392f4b44f0 | ||
|
|
a65ab1d5a7 | ||
|
|
57537ea10e | ||
|
|
51cbd977f0 | ||
|
|
392e88db34 | ||
|
|
0a0897ef28 | ||
|
|
5b193bad4b | ||
|
|
c647b0c65e | ||
|
|
9193720789 | ||
|
|
3208a77bf3 | ||
|
|
cbda307ebf | ||
|
|
0358862066 | ||
|
|
d901504ea9 | ||
|
|
4dc74776c1 | ||
|
|
71f13620d3 | ||
|
|
a914d3c534 | ||
|
|
242a55aa60 | ||
|
|
9045171ad7 | ||
|
|
e5797a57a7 | ||
|
|
3a571bbdb4 | ||
|
|
f40cc5ab54 | ||
|
|
60e614b10c | ||
|
|
f57b619097 | ||
|
|
4c9d432bd9 | ||
|
|
7b8dc38e88 | ||
|
|
bce7d37086 | ||
|
|
13b9b5c0c0 | ||
|
|
cf6e3ca087 | ||
|
|
bdf3552be6 | ||
|
|
26220f2b31 | ||
|
|
f2a1f0124d | ||
|
|
2b510d7a06 | ||
|
|
d07529feca | ||
|
|
6381f28847 | ||
|
|
af99e65876 | ||
|
|
6fa9249062 | ||
|
|
06d782279c | ||
|
|
88616df2e5 | ||
|
|
c51ac6048d | ||
|
|
30abdbccf8 | ||
|
|
66df065e31 | ||
|
|
ed25941c65 | ||
|
|
2c7787900f | ||
|
|
9308c96f95 | ||
|
|
4ffb6c5f75 | ||
|
|
b5ba8699f3 | ||
|
|
19ac2179fb | ||
|
|
1e6d51642c | ||
|
|
878813f968 | ||
|
|
d7e5855ebf | ||
|
|
a48219ecf2 | ||
|
|
995dccc726 | ||
|
|
0572b395ba | ||
|
|
6e08682a7f | ||
|
|
000ea8febd | ||
|
|
b02691cebd | ||
|
|
909fc98e1b | ||
|
|
53d138505a | ||
|
|
e655222d2f | ||
|
|
d096fc8acf | ||
|
|
48be4e765a | ||
|
|
841763326a | ||
|
|
2ed2aedb00 | ||
|
|
767a178bd1 | ||
|
|
ec610cd97b | ||
|
|
e027ba9c47 | ||
|
|
d350134c4f | ||
|
|
b8a58d0fce | ||
|
|
1d25d58c26 | ||
|
|
c85b159d46 | ||
|
|
77d4927e8b | ||
|
|
2bd8877be3 | ||
|
|
242e097e9b | ||
|
|
443c30890b | ||
|
|
61e606bedc | ||
|
|
bedb8ca191 | ||
|
|
35eea8bea5 | ||
|
|
66827755e7 | ||
|
|
85ef1ee21f | ||
|
|
e5d4574d3a | ||
|
|
a1347f67a1 | ||
|
|
c9da806c84 | ||
|
|
a45b1625fc | ||
|
|
1761d5da06 | ||
|
|
63749e281d | ||
|
|
11ac780caf | ||
|
|
31eb83223b | ||
|
|
7062a6e55d | ||
|
|
5e6b683cfb | ||
|
|
8e1945f768 | ||
|
|
0ae12c2b3d | ||
|
|
54563dc94c | ||
|
|
f81e4ec972 | ||
|
|
d7aa0b0ddb | ||
|
|
e098f414e4 | ||
|
|
f8f21815eb | ||
|
|
80e6a64e47 | ||
|
|
bb71b09452 | ||
|
|
4342480473 | ||
|
|
0b205019b6 | ||
|
|
ee519b7552 | ||
|
|
fae918be59 | ||
|
|
b77fe4ca12 | ||
|
|
3a0de7e24a | ||
|
|
44572dce7d | ||
|
|
ba6f01a109 | ||
|
|
9f55e162a3 | ||
|
|
d51a8accee | ||
|
|
cd411a5c36 | ||
|
|
fe7c827e30 | ||
|
|
cc80930e2b | ||
|
|
d20ce404ef | ||
|
|
2d269fb7f1 | ||
|
|
15bfb86eec | ||
|
|
8c5bb5969c | ||
|
|
a337b12877 | ||
|
|
4e05d24d1b | ||
|
|
5c94e23004 | ||
|
|
587c49f6b1 | ||
|
|
211688453c | ||
|
|
5e7a45d6da | ||
|
|
f72c72f4d4 | ||
|
|
028bab0320 | ||
|
|
ee2168b94d | ||
|
|
c4de658964 | ||
|
|
9fcf7eb27c | ||
|
|
6131a523dc | ||
|
|
93e40ee79c | ||
|
|
150a4797a4 | ||
|
|
745fa707dd | ||
|
|
09b93aa164 | ||
|
|
1bb042a661 | ||
|
|
32ad59de26 | ||
|
|
d594092675 | ||
|
|
7570ec9d39 | ||
|
|
3f73e000ee | ||
|
|
7df5182901 | ||
|
|
7c1c8f323c | ||
|
|
68d35dbeb1 | ||
|
|
7a163ef0cc | ||
|
|
b77467ca8f | ||
|
|
e8ec1a6ed4 | ||
|
|
bf2b6b3ac4 | ||
|
|
56581b416d | ||
|
|
a2f178b664 | ||
|
|
01ca3ae07f | ||
|
|
cc6803b358 | ||
|
|
33394f76d4 | ||
|
|
f0048d54b0 | ||
|
|
0cc1ebc021 | ||
|
|
3ad1cccb1d | ||
|
|
9f895879bf | ||
|
|
9db9ffd3e4 | ||
|
|
0ca53420d5 | ||
|
|
6932a42b0a | ||
|
|
b1e6845409 | ||
|
|
96f1a25bbd | ||
|
|
e7bb553d3b | ||
|
|
7f2c4a9e06 | ||
|
|
c620d0de05 | ||
|
|
0dfadf7c09 | ||
|
|
911e266e9a | ||
|
|
223942bf99 | ||
|
|
94f46c9059 | ||
|
|
fc443a8c2c | ||
|
|
e05f6102c2 | ||
|
|
d2d4b4cc23 | ||
|
|
c1c8f7b0f1 | ||
|
|
2353fdb400 | ||
|
|
e81cf74b39 | ||
|
|
e096b5ce83 | ||
|
|
3de008035a | ||
|
|
f026bbb454 | ||
|
|
5ef4caf8ab | ||
|
|
2915617c5c | ||
|
|
0f34967648 | ||
|
|
89246f3714 | ||
|
|
24913a5ef9 | ||
|
|
2289d085fa | ||
|
|
ff97817668 | ||
|
|
0bcc5d37ab | ||
|
|
564ca27679 | ||
|
|
9fecf4b2f7 | ||
|
|
4fb800a899 | ||
|
|
a81ea1ffde | ||
|
|
c56d8b4fe9 | ||
|
|
a936430fd5 | ||
|
|
b54804d449 | ||
|
|
74c970c25f | ||
|
|
8fe675e56c |
25
.github/stale.yml
vendored
Normal file
25
.github/stale.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 45
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- fixme/bug
|
||||
- fixme/crash
|
||||
- fixme/regression
|
||||
- fixme/security
|
||||
- blocked
|
||||
- blocking-stable
|
||||
- needs-review
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity and is not currently prioritized. It will be closed
|
||||
in a week if no further activity occurs :)
|
||||
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: >
|
||||
If you still think this issue is relevant, please ping a maintainer or
|
||||
leave a comment!
|
||||
@@ -14,6 +14,7 @@ propose changes to this document in a pull request.
|
||||
|
||||
## Submitting Issues
|
||||
|
||||
### Creating Issues
|
||||
* You can create an issue [here](https://github.com/electron/electron/issues/new),
|
||||
but before doing that please read the notes below and include as many details as
|
||||
possible with your report. If you can, please include:
|
||||
@@ -27,6 +28,15 @@ possible with your report. If you can, please include:
|
||||
* Perform a [cursory search](https://github.com/electron/electron/issues?utf8=✓&q=is%3Aissue+)
|
||||
to see if a similar issue has already been submitted
|
||||
|
||||
### Issue Maintenance and Closure
|
||||
* If an issue is inactive for 45 days (no activity of any kind), it will be
|
||||
marked for closure with `stale`.
|
||||
* If after this label is applied, no further activity occurs in the next 7 days,
|
||||
the issue will be closed.
|
||||
* If an issue has been closed and you still feel it's relevant, feel free to
|
||||
ping a maintainer or add a comment!
|
||||
|
||||
|
||||
## Submitting Pull Requests
|
||||
|
||||
* Include screenshots and animated GIFs in your pull request whenever possible.
|
||||
|
||||
@@ -375,6 +375,8 @@ int GetPathConstant(const std::string& name) {
|
||||
return brightray::DIR_CACHE;
|
||||
else if (name == "userCache")
|
||||
return brightray::DIR_USER_CACHE;
|
||||
else if (name == "logs")
|
||||
return brightray::DIR_APP_LOGS;
|
||||
else if (name == "home")
|
||||
return base::DIR_HOME;
|
||||
else if (name == "temp")
|
||||
|
||||
@@ -212,6 +212,7 @@ struct Converter<atom::VerifyRequestParams> {
|
||||
dict.Set("hostname", val.hostname);
|
||||
dict.Set("certificate", val.certificate);
|
||||
dict.Set("verificationResult", val.default_result);
|
||||
dict.Set("errorCode", val.error_code);
|
||||
return dict.GetHandle();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -67,6 +67,7 @@ void SystemPreferences::BuildPrototype(
|
||||
&SystemPreferences::UnsubscribeLocalNotification)
|
||||
.SetMethod("getUserDefault", &SystemPreferences::GetUserDefault)
|
||||
.SetMethod("setUserDefault", &SystemPreferences::SetUserDefault)
|
||||
.SetMethod("removeUserDefault", &SystemPreferences::RemoveUserDefault)
|
||||
.SetMethod("isSwipeTrackingFromScrollEventsEnabled",
|
||||
&SystemPreferences::IsSwipeTrackingFromScrollEventsEnabled)
|
||||
#endif
|
||||
|
||||
@@ -76,6 +76,7 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences>
|
||||
void SetUserDefault(const std::string& name,
|
||||
const std::string& type,
|
||||
mate::Arguments* args);
|
||||
void RemoveUserDefault(const std::string& name);
|
||||
bool IsSwipeTrackingFromScrollEventsEnabled();
|
||||
#endif
|
||||
bool IsDarkMode();
|
||||
|
||||
@@ -229,6 +229,11 @@ void SystemPreferences::SetUserDefault(const std::string& name,
|
||||
}
|
||||
}
|
||||
|
||||
void SystemPreferences::RemoveUserDefault(const std::string& name) {
|
||||
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults removeObjectForKey:base::SysUTF8ToNSString(name)];
|
||||
}
|
||||
|
||||
bool SystemPreferences::IsDarkMode() {
|
||||
NSString* mode = [[NSUserDefaults standardUserDefaults]
|
||||
stringForKey:@"AppleInterfaceStyle"];
|
||||
|
||||
@@ -86,8 +86,10 @@ mate::WrappableBase* Tray::New(mate::Handle<NativeImage> image,
|
||||
return new Tray(args->isolate(), args->GetThis(), image);
|
||||
}
|
||||
|
||||
void Tray::OnClicked(const gfx::Rect& bounds, int modifiers) {
|
||||
EmitWithFlags("click", modifiers, bounds);
|
||||
void Tray::OnClicked(const gfx::Rect& bounds,
|
||||
const gfx::Point& location,
|
||||
int modifiers) {
|
||||
EmitWithFlags("click", modifiers, bounds, location);
|
||||
}
|
||||
|
||||
void Tray::OnDoubleClicked(const gfx::Rect& bounds, int modifiers) {
|
||||
@@ -130,6 +132,10 @@ void Tray::OnMouseExited(const gfx::Point& location, int modifiers) {
|
||||
EmitWithFlags("mouse-leave", modifiers, location);
|
||||
}
|
||||
|
||||
void Tray::OnMouseMoved(const gfx::Point& location, int modifiers) {
|
||||
EmitWithFlags("mouse-move", modifiers, location);
|
||||
}
|
||||
|
||||
void Tray::OnDragEntered() {
|
||||
Emit("drag-enter");
|
||||
}
|
||||
|
||||
@@ -47,7 +47,9 @@ class Tray : public mate::TrackableObject<Tray>,
|
||||
~Tray() override;
|
||||
|
||||
// TrayIconObserver:
|
||||
void OnClicked(const gfx::Rect& bounds, int modifiers) override;
|
||||
void OnClicked(const gfx::Rect& bounds,
|
||||
const gfx::Point& location,
|
||||
int modifiers) override;
|
||||
void OnDoubleClicked(const gfx::Rect& bounds, int modifiers) override;
|
||||
void OnRightClicked(const gfx::Rect& bounds, int modifiers) override;
|
||||
void OnBalloonShow() override;
|
||||
@@ -61,6 +63,7 @@ class Tray : public mate::TrackableObject<Tray>,
|
||||
void OnDragEnded() override;
|
||||
void OnMouseEntered(const gfx::Point& location, int modifiers) override;
|
||||
void OnMouseExited(const gfx::Point& location, int modifiers) override;
|
||||
void OnMouseMoved(const gfx::Point& location, int modifiers) override;
|
||||
|
||||
void SetImage(v8::Isolate* isolate, mate::Handle<NativeImage> image);
|
||||
void SetPressedImage(v8::Isolate* isolate, mate::Handle<NativeImage> image);
|
||||
|
||||
@@ -631,6 +631,14 @@ bool Window::HasShadow() {
|
||||
return window_->HasShadow();
|
||||
}
|
||||
|
||||
void Window::SetOpacity(const double opacity) {
|
||||
window_->SetOpacity(opacity);
|
||||
}
|
||||
|
||||
double Window::GetOpacity() {
|
||||
return window_->GetOpacity();
|
||||
}
|
||||
|
||||
void Window::FocusOnWebView() {
|
||||
window_->FocusOnWebView();
|
||||
}
|
||||
@@ -938,6 +946,10 @@ void Window::ToggleTabBar() {
|
||||
window_->ToggleTabBar();
|
||||
}
|
||||
|
||||
void Window::AddTabbedWindow(NativeWindow* window) {
|
||||
window_->AddTabbedWindow(window);
|
||||
}
|
||||
|
||||
void Window::SetVibrancy(mate::Arguments* args) {
|
||||
std::string type;
|
||||
|
||||
@@ -1056,6 +1068,8 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("setBackgroundColor", &Window::SetBackgroundColor)
|
||||
.SetMethod("setHasShadow", &Window::SetHasShadow)
|
||||
.SetMethod("hasShadow", &Window::HasShadow)
|
||||
.SetMethod("setOpacity", &Window::SetOpacity)
|
||||
.SetMethod("getOpacity", &Window::GetOpacity)
|
||||
.SetMethod("setRepresentedFilename", &Window::SetRepresentedFilename)
|
||||
.SetMethod("getRepresentedFilename", &Window::GetRepresentedFilename)
|
||||
.SetMethod("setDocumentEdited", &Window::SetDocumentEdited)
|
||||
@@ -1085,6 +1099,7 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("selectNextTab", &Window::SelectNextTab)
|
||||
.SetMethod("moveTabToNewWindow", &Window::MoveTabToNewWindow)
|
||||
.SetMethod("toggleTabBar", &Window::ToggleTabBar)
|
||||
.SetMethod("addTabbedWindow", &Window::AddTabbedWindow)
|
||||
#endif
|
||||
.SetMethod("setVibrancy", &Window::SetVibrancy)
|
||||
.SetMethod("_setTouchBarItems", &Window::SetTouchBar)
|
||||
|
||||
@@ -161,6 +161,8 @@ class Window : public mate::TrackableObject<Window>,
|
||||
void SetBackgroundColor(const std::string& color_name);
|
||||
void SetHasShadow(bool has_shadow);
|
||||
bool HasShadow();
|
||||
void SetOpacity(const double opacity);
|
||||
double GetOpacity();
|
||||
void FocusOnWebView();
|
||||
void BlurWebView();
|
||||
bool IsWebViewFocused();
|
||||
@@ -219,6 +221,7 @@ class Window : public mate::TrackableObject<Window>,
|
||||
void MergeAllWindows();
|
||||
void MoveTabToNewWindow();
|
||||
void ToggleTabBar();
|
||||
void AddTabbedWindow(NativeWindow* window);
|
||||
|
||||
void SetVibrancy(mate::Arguments* args);
|
||||
void SetTouchBar(const std::vector<mate::PersistentDictionary>& items);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "base/supports_user_data.h"
|
||||
|
||||
namespace mate {
|
||||
@@ -46,16 +47,19 @@ void TrackableObjectBase::Destroy() {
|
||||
}
|
||||
|
||||
void TrackableObjectBase::AttachAsUserData(base::SupportsUserData* wrapped) {
|
||||
wrapped->SetUserData(kTrackedObjectKey, new IDUserData(weak_map_id_));
|
||||
wrapped->SetUserData(kTrackedObjectKey,
|
||||
base::MakeUnique<IDUserData>(weak_map_id_));
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t TrackableObjectBase::GetIDFromWrappedClass(base::SupportsUserData* w) {
|
||||
auto id = static_cast<IDUserData*>(w->GetUserData(kTrackedObjectKey));
|
||||
if (id)
|
||||
return *id;
|
||||
else
|
||||
return 0;
|
||||
int32_t TrackableObjectBase::GetIDFromWrappedClass(
|
||||
base::SupportsUserData* wrapped) {
|
||||
if (wrapped) {
|
||||
auto id = static_cast<IDUserData*>(wrapped->GetUserData(kTrackedObjectKey));
|
||||
if (id)
|
||||
return *id;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -4,16 +4,62 @@
|
||||
|
||||
#include "atom/browser/browser.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#include "atom/common/atom_version.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/environment.h"
|
||||
#include "base/process/launch.h"
|
||||
#include "brightray/common/application_info.h"
|
||||
|
||||
#if defined(USE_X11)
|
||||
#include "chrome/browser/ui/libgtkui/gtk_util.h"
|
||||
#include "chrome/browser/ui/libgtkui/unity_service.h"
|
||||
#endif
|
||||
|
||||
namespace atom {
|
||||
|
||||
const char kXdgSettings[] = "xdg-settings";
|
||||
const char kXdgSettingsDefaultSchemeHandler[] = "default-url-scheme-handler";
|
||||
|
||||
bool LaunchXdgUtility(const std::vector<std::string>& argv, int* exit_code) {
|
||||
*exit_code = EXIT_FAILURE;
|
||||
int devnull = open("/dev/null", O_RDONLY);
|
||||
if (devnull < 0) return false;
|
||||
|
||||
base::LaunchOptions options;
|
||||
|
||||
base::FileHandleMappingVector remap;
|
||||
remap.push_back(std::make_pair(devnull, STDIN_FILENO));
|
||||
options.fds_to_remap = &remap;
|
||||
|
||||
base::Process process = base::LaunchProcess(argv, options);
|
||||
close(devnull);
|
||||
|
||||
if (!process.IsValid()) return false;
|
||||
return process.WaitForExit(exit_code);
|
||||
}
|
||||
|
||||
bool SetDefaultWebClient(const std::string& protocol) {
|
||||
std::unique_ptr<base::Environment> env(base::Environment::Create());
|
||||
|
||||
std::vector<std::string> argv;
|
||||
argv.push_back(kXdgSettings);
|
||||
argv.push_back("set");
|
||||
if (!protocol.empty()) {
|
||||
argv.push_back(kXdgSettingsDefaultSchemeHandler);
|
||||
argv.push_back(protocol);
|
||||
}
|
||||
argv.push_back(libgtkui::GetDesktopName(env.get()));
|
||||
|
||||
int exit_code;
|
||||
bool ran_ok = LaunchXdgUtility(argv, &exit_code);
|
||||
return ran_ok && exit_code == EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void Browser::Focus() {
|
||||
// Focus on the first visible window.
|
||||
for (const auto& window : WindowList::GetWindows()) {
|
||||
@@ -33,18 +79,40 @@ void Browser::ClearRecentDocuments() {
|
||||
void Browser::SetAppUserModelID(const base::string16& name) {
|
||||
}
|
||||
|
||||
bool Browser::RemoveAsDefaultProtocolClient(const std::string& protocol,
|
||||
mate::Arguments* args) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Browser::SetAsDefaultProtocolClient(const std::string& protocol,
|
||||
mate::Arguments* args) {
|
||||
return false;
|
||||
return SetDefaultWebClient(protocol);
|
||||
}
|
||||
|
||||
bool Browser::IsDefaultProtocolClient(const std::string& protocol,
|
||||
mate::Arguments* args) {
|
||||
std::unique_ptr<base::Environment> env(base::Environment::Create());
|
||||
|
||||
if (protocol.empty()) return false;
|
||||
|
||||
std::vector<std::string> argv;
|
||||
argv.push_back(kXdgSettings);
|
||||
argv.push_back("check");
|
||||
argv.push_back(kXdgSettingsDefaultSchemeHandler);
|
||||
argv.push_back(protocol);
|
||||
argv.push_back(libgtkui::GetDesktopName(env.get()));
|
||||
|
||||
std::string reply;
|
||||
int success_code;
|
||||
bool ran_ok = base::GetAppOutputWithExitCode(base::CommandLine(argv),
|
||||
&reply, &success_code);
|
||||
|
||||
if (!ran_ok || success_code != EXIT_SUCCESS) return false;
|
||||
|
||||
// Allow any reply that starts with "yes".
|
||||
return base::StartsWith(reply, "yes", base::CompareCase::SENSITIVE)
|
||||
? true
|
||||
: false;
|
||||
}
|
||||
|
||||
// Todo implement
|
||||
bool Browser::RemoveAsDefaultProtocolClient(const std::string& protocol,
|
||||
mate::Arguments* args) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,12 @@ const NSAutoresizingMaskOptions kDefaultAutoResizingMask =
|
||||
- (void)mouseDown:(NSEvent *)event
|
||||
{
|
||||
if ([self.window respondsToSelector:@selector(performWindowDragWithEvent)]) {
|
||||
// According to Google, using performWindowDragWithEvent:
|
||||
// does not generate a NSWindowWillMoveNotification. Hence post one.
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
postNotificationName:NSWindowWillMoveNotification
|
||||
object:self];
|
||||
|
||||
[self.window performWindowDragWithEvent:event];
|
||||
return;
|
||||
}
|
||||
@@ -68,13 +74,45 @@ const NSAutoresizingMaskOptions kDefaultAutoResizingMask =
|
||||
NSPoint newOrigin;
|
||||
|
||||
NSRect screenFrame = [[NSScreen mainScreen] frame];
|
||||
NSSize screenSize = screenFrame.size;
|
||||
NSRect windowFrame = [self.window frame];
|
||||
NSSize windowSize = windowFrame.size;
|
||||
|
||||
newOrigin.x = currentLocation.x - self.initialLocation.x;
|
||||
newOrigin.y = currentLocation.y - self.initialLocation.y;
|
||||
|
||||
BOOL inMenuBar = (newOrigin.y + windowSize.height) > (screenFrame.origin.y + screenSize.height);
|
||||
BOOL screenAboveMainScreen = false;
|
||||
|
||||
if (inMenuBar) {
|
||||
for (NSScreen *screen in [NSScreen screens]) {
|
||||
NSRect currentScreenFrame = [screen frame];
|
||||
BOOL isHigher = currentScreenFrame.origin.y > screenFrame.origin.y;
|
||||
|
||||
// If there's another screen that is generally above the current screen,
|
||||
// we'll draw a new rectangle that is just above the current screen. If the
|
||||
// "higher" screen intersects with this rectangle, we'll allow drawing above
|
||||
// the menubar.
|
||||
if (isHigher) {
|
||||
NSRect aboveScreenRect = NSMakeRect(
|
||||
screenFrame.origin.x,
|
||||
screenFrame.origin.y + screenFrame.size.height - 10,
|
||||
screenFrame.size.width,
|
||||
200
|
||||
);
|
||||
|
||||
BOOL screenAboveIntersects = NSIntersectsRect(currentScreenFrame, aboveScreenRect);
|
||||
|
||||
if (screenAboveIntersects) {
|
||||
screenAboveMainScreen = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Don't let window get dragged up under the menu bar
|
||||
if ((newOrigin.y + windowFrame.size.height) > (screenFrame.origin.y + screenFrame.size.height)) {
|
||||
if (inMenuBar && !screenAboveMainScreen) {
|
||||
newOrigin.y = screenFrame.origin.y + (screenFrame.size.height - windowFrame.size.height);
|
||||
}
|
||||
|
||||
|
||||
@@ -159,6 +159,10 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
|
||||
if (options.Get(options::kHasShadow, &has_shadow)) {
|
||||
SetHasShadow(has_shadow);
|
||||
}
|
||||
double opacity;
|
||||
if (options.Get(options::kOpacity, &opacity)) {
|
||||
SetOpacity(opacity);
|
||||
}
|
||||
bool top;
|
||||
if (options.Get(options::kAlwaysOnTop, &top) && top) {
|
||||
SetAlwaysOnTop(true);
|
||||
@@ -351,6 +355,9 @@ void NativeWindow::MoveTabToNewWindow() {
|
||||
void NativeWindow::ToggleTabBar() {
|
||||
}
|
||||
|
||||
void NativeWindow::AddTabbedWindow(NativeWindow* window) {
|
||||
}
|
||||
|
||||
void NativeWindow::SetVibrancy(const std::string& filename) {
|
||||
}
|
||||
|
||||
|
||||
@@ -141,6 +141,8 @@ class NativeWindow : public base::SupportsUserData,
|
||||
virtual void SetBackgroundColor(const std::string& color_name) = 0;
|
||||
virtual void SetHasShadow(bool has_shadow) = 0;
|
||||
virtual bool HasShadow() = 0;
|
||||
virtual void SetOpacity(const double opacity) = 0;
|
||||
virtual double GetOpacity() = 0;
|
||||
virtual void SetRepresentedFilename(const std::string& filename);
|
||||
virtual std::string GetRepresentedFilename();
|
||||
virtual void SetDocumentEdited(bool edited);
|
||||
@@ -190,6 +192,7 @@ class NativeWindow : public base::SupportsUserData,
|
||||
virtual void MergeAllWindows();
|
||||
virtual void MoveTabToNewWindow();
|
||||
virtual void ToggleTabBar();
|
||||
virtual void AddTabbedWindow(NativeWindow* window);
|
||||
|
||||
// Webview APIs.
|
||||
virtual void FocusOnWebView();
|
||||
|
||||
@@ -83,6 +83,8 @@ class NativeWindowMac : public NativeWindow,
|
||||
void SetBackgroundColor(const std::string& color_name) override;
|
||||
void SetHasShadow(bool has_shadow) override;
|
||||
bool HasShadow() override;
|
||||
void SetOpacity(const double opacity) override;
|
||||
double GetOpacity() override;
|
||||
void SetRepresentedFilename(const std::string& filename) override;
|
||||
std::string GetRepresentedFilename() override;
|
||||
void SetDocumentEdited(bool edited) override;
|
||||
@@ -108,6 +110,7 @@ class NativeWindowMac : public NativeWindow,
|
||||
void MergeAllWindows() override;
|
||||
void MoveTabToNewWindow() override;
|
||||
void ToggleTabBar() override;
|
||||
void AddTabbedWindow(NativeWindow* window) override;
|
||||
|
||||
void SetVibrancy(const std::string& type) override;
|
||||
void SetTouchBar(
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "atom/browser/native_window_mac.h"
|
||||
|
||||
#include <AvailabilityMacros.h>
|
||||
#include <Quartz/Quartz.h>
|
||||
#include <string>
|
||||
|
||||
@@ -465,7 +466,7 @@ bool ScopedDisableResize::disable_resize_ = false;
|
||||
|
||||
@end
|
||||
|
||||
#if !defined(MAC_OS_X_VERSION_10_12)
|
||||
#if !defined(AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER)
|
||||
|
||||
enum {
|
||||
NSWindowTabbingModeDisallowed = 2
|
||||
@@ -474,6 +475,7 @@ enum {
|
||||
@interface NSWindow (SierraSDK)
|
||||
- (void)setTabbingMode:(NSInteger)mode;
|
||||
- (void)setTabbingIdentifier:(NSString*)identifier;
|
||||
- (void)addTabbedWindow:(NSWindow*)window ordered:(NSWindowOrderingMode)ordered;
|
||||
- (IBAction)selectPreviousTab:(id)sender;
|
||||
- (IBAction)selectNextTab:(id)sender;
|
||||
- (IBAction)mergeAllWindows:(id)sender;
|
||||
@@ -481,7 +483,7 @@ enum {
|
||||
- (IBAction)toggleTabBar:(id)sender;
|
||||
@end
|
||||
|
||||
#endif // MAC_OS_X_VERSION_10_12
|
||||
#endif
|
||||
|
||||
@interface AtomNSWindow : EventDispatchingWindow<QLPreviewPanelDataSource, QLPreviewPanelDelegate, NSTouchBarDelegate> {
|
||||
@private
|
||||
@@ -1503,6 +1505,14 @@ bool NativeWindowMac::HasShadow() {
|
||||
return [window_ hasShadow];
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetOpacity(const double opacity) {
|
||||
[window_ setAlphaValue:opacity];
|
||||
}
|
||||
|
||||
double NativeWindowMac::GetOpacity() {
|
||||
return [window_ alphaValue];
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetRepresentedFilename(const std::string& filename) {
|
||||
[window_ setRepresentedFilename:base::SysUTF8ToNSString(filename)];
|
||||
}
|
||||
@@ -1649,6 +1659,12 @@ void NativeWindowMac::ToggleTabBar() {
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindowMac::AddTabbedWindow(NativeWindow* window) {
|
||||
if ([window_ respondsToSelector:@selector(addTabbedWindow:ordered:)]) {
|
||||
[window_ addTabbedWindow:window->GetNativeWindow() ordered:NSWindowAbove];
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetVibrancy(const std::string& type) {
|
||||
if (!base::mac::IsAtLeastOS10_10()) return;
|
||||
|
||||
|
||||
@@ -814,6 +814,24 @@ bool NativeWindowViews::HasShadow() {
|
||||
!= wm::ShadowElevation::NONE;
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetOpacity(const double opacity) {
|
||||
#if defined(OS_WIN)
|
||||
HWND hwnd = GetAcceleratedWidget();
|
||||
if (!layered_) {
|
||||
LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
|
||||
ex_style |= WS_EX_LAYERED;
|
||||
::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style);
|
||||
layered_ = true;
|
||||
}
|
||||
::SetLayeredWindowAttributes(hwnd, 0, opacity * 255, LWA_ALPHA);
|
||||
#endif
|
||||
opacity_ = opacity;
|
||||
}
|
||||
|
||||
double NativeWindowViews::GetOpacity() {
|
||||
return opacity_;
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetIgnoreMouseEvents(bool ignore, bool forward) {
|
||||
#if defined(OS_WIN)
|
||||
LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);
|
||||
@@ -821,6 +839,8 @@ void NativeWindowViews::SetIgnoreMouseEvents(bool ignore, bool forward) {
|
||||
ex_style |= (WS_EX_TRANSPARENT | WS_EX_LAYERED);
|
||||
else
|
||||
ex_style &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED);
|
||||
if (layered_)
|
||||
ex_style |= WS_EX_LAYERED;
|
||||
::SetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE, ex_style);
|
||||
|
||||
// Forwarding is always disabled when not ignoring mouse messages.
|
||||
|
||||
@@ -104,6 +104,8 @@ class NativeWindowViews : public NativeWindow,
|
||||
void SetBackgroundColor(const std::string& color_name) override;
|
||||
void SetHasShadow(bool has_shadow) override;
|
||||
bool HasShadow() override;
|
||||
void SetOpacity(const double opacity) override;
|
||||
double GetOpacity() override;
|
||||
void SetIgnoreMouseEvents(bool ignore, bool forward) override;
|
||||
void SetContentProtection(bool enable) override;
|
||||
void SetFocusable(bool focusable) override;
|
||||
@@ -274,6 +276,7 @@ class NativeWindowViews : public NativeWindow,
|
||||
static HHOOK mouse_hook_;
|
||||
bool forwarding_mouse_messages_ = false;
|
||||
HWND legacy_window_ = NULL;
|
||||
bool layered_ = false;
|
||||
#endif
|
||||
|
||||
// Handles unhandled keyboard messages coming back from the renderer process.
|
||||
@@ -293,6 +296,7 @@ class NativeWindowViews : public NativeWindow,
|
||||
bool fullscreenable_;
|
||||
std::string title_;
|
||||
gfx::Size widget_size_;
|
||||
double opacity_ = 1.0;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(NativeWindowViews);
|
||||
};
|
||||
|
||||
@@ -92,6 +92,7 @@ class CertVerifierRequest : public AtomCertVerifier::Request {
|
||||
std::unique_ptr<VerifyRequestParams> request(new VerifyRequestParams());
|
||||
request->hostname = params_.hostname();
|
||||
request->default_result = net::ErrorToString(error);
|
||||
request->error_code = error;
|
||||
request->certificate = params_.certificate();
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::UI, FROM_HERE,
|
||||
|
||||
@@ -19,6 +19,7 @@ class CertVerifierRequest;
|
||||
struct VerifyRequestParams {
|
||||
std::string hostname;
|
||||
std::string default_result;
|
||||
int error_code;
|
||||
scoped_refptr<net::X509Certificate> certificate;
|
||||
};
|
||||
|
||||
|
||||
@@ -82,8 +82,12 @@ void ToDictionary(base::DictionaryValue* details, net::URLRequest* request) {
|
||||
int frame_id = info->GetRenderFrameID();
|
||||
auto* webContents = content::WebContents::FromRenderFrameHost(
|
||||
content::RenderFrameHost::FromID(process_id, frame_id));
|
||||
details->SetInteger("webContentsId",
|
||||
atom::api::WebContents::GetIDFromWrappedClass(webContents));
|
||||
int webContentsId = atom::api::WebContents::GetIDFromWrappedClass(
|
||||
webContents);
|
||||
|
||||
// webContentsId must be greater than zero
|
||||
if (webContentsId)
|
||||
details->SetInteger("webContentsId", webContentsId);
|
||||
details->SetString("resourceType",
|
||||
ResourceTypeToString(info->GetResourceType()));
|
||||
} else {
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>electron.icns</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.8.1</string>
|
||||
<string>1.8.2</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.8.1</string>
|
||||
<string>1.8.2</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.developer-tools</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
||||
@@ -56,8 +56,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,8,1,0
|
||||
PRODUCTVERSION 1,8,1,0
|
||||
FILEVERSION 1,8,2,1
|
||||
PRODUCTVERSION 1,8,2,1
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -74,12 +74,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Electron"
|
||||
VALUE "FileVersion", "1.8.1"
|
||||
VALUE "FileVersion", "1.8.2"
|
||||
VALUE "InternalName", "electron.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "electron.exe"
|
||||
VALUE "ProductName", "Electron"
|
||||
VALUE "ProductVersion", "1.8.1"
|
||||
VALUE "ProductVersion", "1.8.2"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
|
||||
@@ -143,6 +143,7 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
||||
}
|
||||
|
||||
- (void)setEscapeTouchBarItem:(const mate::PersistentDictionary&)item forTouchBar:(NSTouchBar*)touchBar {
|
||||
if (![touchBar respondsToSelector:@selector(escapeKeyReplacementItemIdentifier)]) return;
|
||||
std::string type;
|
||||
std::string item_id;
|
||||
NSTouchBarItemIdentifier identifier = nil;
|
||||
|
||||
@@ -34,9 +34,11 @@ gfx::Rect TrayIcon::GetBounds() {
|
||||
return gfx::Rect();
|
||||
}
|
||||
|
||||
void TrayIcon::NotifyClicked(const gfx::Rect& bounds, int modifiers) {
|
||||
void TrayIcon::NotifyClicked(const gfx::Rect& bounds,
|
||||
const gfx::Point& location,
|
||||
int modifiers) {
|
||||
for (TrayIconObserver& observer : observers_)
|
||||
observer.OnClicked(bounds, modifiers);
|
||||
observer.OnClicked(bounds, location, modifiers);
|
||||
}
|
||||
|
||||
void TrayIcon::NotifyDoubleClicked(const gfx::Rect& bounds, int modifiers) {
|
||||
@@ -89,6 +91,11 @@ void TrayIcon::NotifyMouseExited(const gfx::Point& location, int modifiers) {
|
||||
observer.OnMouseExited(location, modifiers);
|
||||
}
|
||||
|
||||
void TrayIcon::NotifyMouseMoved(const gfx::Point& location, int modifiers) {
|
||||
for (TrayIconObserver& observer : observers_)
|
||||
observer.OnMouseMoved(location, modifiers);
|
||||
}
|
||||
|
||||
void TrayIcon::NotifyDragEntered() {
|
||||
for (TrayIconObserver& observer : observers_)
|
||||
observer.OnDragEntered();
|
||||
|
||||
@@ -70,7 +70,9 @@ class TrayIcon {
|
||||
void AddObserver(TrayIconObserver* obs) { observers_.AddObserver(obs); }
|
||||
void RemoveObserver(TrayIconObserver* obs) { observers_.RemoveObserver(obs); }
|
||||
|
||||
void NotifyClicked(const gfx::Rect& = gfx::Rect(), int modifiers = 0);
|
||||
void NotifyClicked(const gfx::Rect& = gfx::Rect(),
|
||||
const gfx::Point& location = gfx::Point(),
|
||||
int modifiers = 0);
|
||||
void NotifyDoubleClicked(const gfx::Rect& = gfx::Rect(), int modifiers = 0);
|
||||
void NotifyBalloonShow();
|
||||
void NotifyBalloonClicked();
|
||||
@@ -87,6 +89,8 @@ class TrayIcon {
|
||||
int modifiers = 0);
|
||||
void NotifyMouseExited(const gfx::Point& location = gfx::Point(),
|
||||
int modifiers = 0);
|
||||
void NotifyMouseMoved(const gfx::Point& location = gfx::Point(),
|
||||
int modifiers = 0);
|
||||
|
||||
protected:
|
||||
TrayIcon();
|
||||
|
||||
@@ -57,10 +57,10 @@ const CGFloat kVerticalTitleMargin = 2;
|
||||
// Finalize setup by sizing our views
|
||||
[self updateDimensions];
|
||||
|
||||
// Add NSTrackingArea for listening to mouseEnter and mouseExit events
|
||||
// Add NSTrackingArea for listening to mouseEnter, mouseExit, and mouseMove events
|
||||
auto trackingArea = [[[NSTrackingArea alloc]
|
||||
initWithRect:[self bounds]
|
||||
options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways
|
||||
options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveAlways
|
||||
owner:self
|
||||
userInfo:nil] autorelease];
|
||||
[self addTrackingArea:trackingArea];
|
||||
@@ -249,6 +249,7 @@ const CGFloat kVerticalTitleMargin = 2;
|
||||
if (event.clickCount == 1)
|
||||
trayIcon_->NotifyClicked(
|
||||
gfx::ScreenRectFromNSRect(event.window.frame),
|
||||
gfx::ScreenPointFromNSPoint([event locationInWindow]),
|
||||
ui::EventFlagsFromModifiers([event modifierFlags]));
|
||||
|
||||
// Double click event.
|
||||
@@ -307,6 +308,12 @@ const CGFloat kVerticalTitleMargin = 2;
|
||||
ui::EventFlagsFromModifiers([event modifierFlags]));
|
||||
}
|
||||
|
||||
- (void)mouseMoved:(NSEvent*)event {
|
||||
trayIcon_->NotifyMouseMoved(
|
||||
gfx::ScreenPointFromNSPoint([event locationInWindow]),
|
||||
ui::EventFlagsFromModifiers([event modifierFlags]));
|
||||
}
|
||||
|
||||
- (void)draggingExited:(id <NSDraggingInfo>)sender {
|
||||
trayIcon_->NotifyDragExited();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,9 @@ namespace atom {
|
||||
|
||||
class TrayIconObserver {
|
||||
public:
|
||||
virtual void OnClicked(const gfx::Rect& bounds, int modifiers) {}
|
||||
virtual void OnClicked(const gfx::Rect& bounds,
|
||||
const gfx::Point& location,
|
||||
int modifiers) {}
|
||||
virtual void OnDoubleClicked(const gfx::Rect& bounds, int modifiers) {}
|
||||
virtual void OnBalloonShow() {}
|
||||
virtual void OnBalloonClicked() {}
|
||||
@@ -31,6 +33,7 @@ class TrayIconObserver {
|
||||
virtual void OnDragEnded() {}
|
||||
virtual void OnMouseEntered(const gfx::Point& location, int modifiers) {}
|
||||
virtual void OnMouseExited(const gfx::Point& location, int modifiers) {}
|
||||
virtual void OnMouseMoved(const gfx::Point& location, int modifiers) {}
|
||||
|
||||
protected:
|
||||
virtual ~TrayIconObserver() {}
|
||||
|
||||
@@ -55,7 +55,9 @@ void NotifyIcon::HandleClickEvent(int modifiers,
|
||||
if (double_button_click) // double left click
|
||||
NotifyDoubleClicked(bounds, modifiers);
|
||||
else // single left click
|
||||
NotifyClicked(bounds, modifiers);
|
||||
NotifyClicked(bounds,
|
||||
display::Screen::GetScreen()->GetCursorScreenPoint(),
|
||||
modifiers);
|
||||
return;
|
||||
} else if (!double_button_click) { // single right click
|
||||
if (menu_model_)
|
||||
|
||||
@@ -541,6 +541,13 @@ mate::Handle<NativeImage> NativeImage::CreateFromDataURL(
|
||||
return CreateEmpty(isolate);
|
||||
}
|
||||
|
||||
#if !defined(OS_MACOSX)
|
||||
mate::Handle<NativeImage> NativeImage::CreateFromNamedImage(
|
||||
mate::Arguments* args, const std::string& name) {
|
||||
return CreateEmpty(args->isolate());
|
||||
}
|
||||
#endif
|
||||
|
||||
// static
|
||||
void NativeImage::BuildPrototype(
|
||||
v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> prototype) {
|
||||
@@ -609,6 +616,8 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
dict.SetMethod("createFromBuffer", &atom::api::NativeImage::CreateFromBuffer);
|
||||
dict.SetMethod("createFromDataURL",
|
||||
&atom::api::NativeImage::CreateFromDataURL);
|
||||
dict.SetMethod("createFromNamedImage",
|
||||
&atom::api::NativeImage::CreateFromNamedImage);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -53,6 +53,8 @@ class NativeImage : public mate::Wrappable<NativeImage> {
|
||||
mate::Arguments* args, v8::Local<v8::Value> buffer);
|
||||
static mate::Handle<NativeImage> CreateFromDataURL(
|
||||
v8::Isolate* isolate, const GURL& url);
|
||||
static mate::Handle<NativeImage> CreateFromNamedImage(
|
||||
mate::Arguments* args, const std::string& name);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
@@ -6,10 +6,56 @@
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "ui/gfx/color_utils.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
#include "ui/gfx/image/image_skia.h"
|
||||
#include "ui/gfx/image/image_skia_operations.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
NSData* bufferFromNSImage(NSImage* image) {
|
||||
CGImageRef ref = [image CGImageForProposedRect:nil context:nil hints:nil];
|
||||
NSBitmapImageRep* rep = [[NSBitmapImageRep alloc] initWithCGImage:ref];
|
||||
[rep setSize:[image size]];
|
||||
return [rep representationUsingType:NSPNGFileType properties:[[NSDictionary alloc] init]];
|
||||
}
|
||||
|
||||
double safeShift(double in, double def) {
|
||||
if (in >= 0 || in <= 1 || in == def) return in;
|
||||
return def;
|
||||
}
|
||||
|
||||
mate::Handle<NativeImage> NativeImage::CreateFromNamedImage(
|
||||
mate::Arguments* args, const std::string& name) {
|
||||
@autoreleasepool {
|
||||
std::vector<double> hsl_shift;
|
||||
NSImage* image = [NSImage imageNamed:base::SysUTF8ToNSString(name)];
|
||||
if (!image.valid) {
|
||||
return CreateEmpty(args->isolate());
|
||||
}
|
||||
|
||||
NSData* png_data = bufferFromNSImage(image);
|
||||
|
||||
if (args->GetNext(&hsl_shift) && hsl_shift.size() == 3) {
|
||||
gfx::Image gfx_image = gfx::Image::CreateFrom1xPNGBytes(
|
||||
reinterpret_cast<const unsigned char*>((char *) [png_data bytes]), [png_data length]);
|
||||
color_utils::HSL shift = {
|
||||
safeShift(hsl_shift[0], -1),
|
||||
safeShift(hsl_shift[1], 0.5),
|
||||
safeShift(hsl_shift[2], 0.5)
|
||||
};
|
||||
png_data = bufferFromNSImage(gfx::Image(
|
||||
gfx::ImageSkiaOperations::CreateHSLShiftedImage(
|
||||
gfx_image.AsImageSkia(), shift)).CopyNSImage());
|
||||
}
|
||||
|
||||
return CreateFromPNG(args->isolate(), (char *) [png_data bytes], [png_data length]);
|
||||
}
|
||||
}
|
||||
|
||||
void NativeImage::SetTemplateImage(bool setAsTemplate) {
|
||||
[image_.AsNSImage() setTemplate:setAsTemplate];
|
||||
}
|
||||
|
||||
@@ -188,7 +188,14 @@ v8::Local<v8::Value> AtomBindings::GetCPUUsage(v8::Isolate* isolate) {
|
||||
int processor_count = base::SysInfo::NumberOfProcessors();
|
||||
dict.Set("percentCPUUsage",
|
||||
metrics_->GetPlatformIndependentCPUUsage() / processor_count);
|
||||
|
||||
// NB: This will throw NOTIMPLEMENTED() on Windows
|
||||
// For backwards compatibility, we'll return 0
|
||||
#if !defined(OS_WIN)
|
||||
dict.Set("idleWakeupsPerSecond", metrics_->GetIdleWakeupsPerSecond());
|
||||
#else
|
||||
dict.Set("idleWakeupsPerSecond", 0);
|
||||
#endif
|
||||
|
||||
return dict.GetHandle();
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#define ATOM_MAJOR_VERSION 1
|
||||
#define ATOM_MINOR_VERSION 8
|
||||
#define ATOM_PATCH_VERSION 1
|
||||
#define ATOM_PATCH_VERSION 2
|
||||
|
||||
#define ATOM_VERSION_IS_RELEASE 1
|
||||
|
||||
|
||||
@@ -86,6 +86,9 @@ const char kBackgroundColor[] = "backgroundColor";
|
||||
// Whether the window should have a shadow.
|
||||
const char kHasShadow[] = "hasShadow";
|
||||
|
||||
// Browser window opacity
|
||||
const char kOpacity[] = "opacity";
|
||||
|
||||
// Whether the window can be activated.
|
||||
const char kFocusable[] = "focusable";
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ extern const char kDisableAutoHideCursor[];
|
||||
extern const char kStandardWindow[];
|
||||
extern const char kBackgroundColor[];
|
||||
extern const char kHasShadow[];
|
||||
extern const char kOpacity[];
|
||||
extern const char kFocusable[];
|
||||
extern const char kWebPreferences[];
|
||||
extern const char kVibrancyType[];
|
||||
|
||||
@@ -22,6 +22,7 @@ enum {
|
||||
|
||||
DIR_USER_DATA = PATH_START, // Directory where user data can be written.
|
||||
DIR_USER_CACHE, // Directory where user cache can be written.
|
||||
DIR_APP_LOGS, // Directory where app logs live
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
DIR_APP_DATA, // Application Data directory under the user profile.
|
||||
|
||||
@@ -4,6 +4,13 @@
|
||||
|
||||
#include "brightray/browser/browser_main_parts.h"
|
||||
|
||||
#if defined(OSX_POSIX)
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <string>
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/feature_list.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
@@ -11,6 +18,7 @@
|
||||
#include "brightray/browser/browser_context.h"
|
||||
#include "brightray/browser/devtools_manager_delegate.h"
|
||||
#include "brightray/browser/web_ui_controller_factory.h"
|
||||
#include "brightray/common/application_info.h"
|
||||
#include "brightray/common/main_delegate.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
@@ -156,11 +164,26 @@ BrowserMainParts::BrowserMainParts() {
|
||||
BrowserMainParts::~BrowserMainParts() {
|
||||
}
|
||||
|
||||
#if defined(OS_WIN) || defined(OS_LINUX)
|
||||
void OverrideAppLogsPath() {
|
||||
#if defined(OS_WIN)
|
||||
std::wstring app_name = base::UTF8ToWide(GetApplicationName());
|
||||
std::wstring log_path = L"%HOMEDRIVE%%HOMEPATH%\\AppData\\Roaming\\";
|
||||
std::wstring app_log_path = log_path + app_name + L"\\logs";
|
||||
#else
|
||||
std::string app_name = GetApplicationName();
|
||||
std::string home_path = std::string(getenv("HOME"));
|
||||
std::string app_log_path = home_path + "/.config/" + app_name + "/logs";
|
||||
#endif
|
||||
PathService::Override(DIR_APP_LOGS, base::FilePath(app_log_path));
|
||||
}
|
||||
#endif
|
||||
|
||||
void BrowserMainParts::PreEarlyInitialization() {
|
||||
std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
|
||||
feature_list->InitializeFromCommandLine("", "");
|
||||
base::FeatureList::SetInstance(std::move(feature_list));
|
||||
|
||||
OverrideAppLogsPath();
|
||||
#if defined(USE_X11)
|
||||
views::LinuxUI::SetInstance(BuildGtkUi());
|
||||
OverrideLinuxAppDataPath();
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/path_service.h"
|
||||
#include "brightray/browser/brightray_paths.h"
|
||||
#include "content/public/browser/browser_main_parts.h"
|
||||
#include "ui/views/layout/layout_provider.h"
|
||||
|
||||
@@ -45,6 +47,7 @@ class BrowserMainParts : public content::BrowserMainParts {
|
||||
private:
|
||||
#if defined(OS_MACOSX)
|
||||
void InitializeMainNib();
|
||||
void OverrideAppLogsPath();
|
||||
#endif
|
||||
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
|
||||
@@ -6,6 +6,16 @@
|
||||
|
||||
namespace brightray {
|
||||
|
||||
void BrowserMainParts::OverrideAppLogsPath() {
|
||||
base::FilePath path;
|
||||
NSString* bundleName = [[[NSBundle mainBundle] infoDictionary]
|
||||
objectForKey:@"CFBundleName"];
|
||||
NSString* logsPath = [NSString stringWithFormat:@"Library/Logs/%@",bundleName];
|
||||
NSString* libraryPath = [NSHomeDirectory() stringByAppendingPathComponent:logsPath];
|
||||
|
||||
PathService::Override(DIR_APP_LOGS, base::FilePath([libraryPath UTF8String]));
|
||||
}
|
||||
|
||||
// Replicates NSApplicationMain, but doesn't start a run loop.
|
||||
void BrowserMainParts::InitializeMainNib() {
|
||||
auto infoDictionary = base::mac::OuterBundle().infoDictionary;
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
namespace brightray {
|
||||
|
||||
int g_identifier_ = 1;
|
||||
|
||||
CocoaNotification::CocoaNotification(NotificationDelegate* delegate,
|
||||
NotificationPresenter* presenter)
|
||||
: Notification(delegate, presenter) {
|
||||
@@ -29,6 +31,8 @@ void CocoaNotification::Show(const NotificationOptions& options) {
|
||||
[notification_ setTitle:base::SysUTF16ToNSString(options.title)];
|
||||
[notification_ setSubtitle:base::SysUTF16ToNSString(options.subtitle)];
|
||||
[notification_ setInformativeText:base::SysUTF16ToNSString(options.msg)];
|
||||
[notification_ setIdentifier:[NSString stringWithFormat:@"%s%d", "ElectronNotification", g_identifier_]];
|
||||
g_identifier_++;
|
||||
|
||||
if ([notification_ respondsToSelector:@selector(setContentImage:)] &&
|
||||
!options.icon.drawsNothing()) {
|
||||
|
||||
@@ -18,7 +18,8 @@ CocoaNotification* NotificationPresenterMac::GetNotification(
|
||||
NSUserNotification* ns_notification) {
|
||||
for (Notification* notification : notifications()) {
|
||||
auto native_notification = static_cast<CocoaNotification*>(notification);
|
||||
if ([native_notification->notification() isEqual:ns_notification])
|
||||
if ([native_notification->notification().identifier
|
||||
isEqual:ns_notification.identifier])
|
||||
return native_notification;
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
@@ -21,8 +21,8 @@ struct NotificationData {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline T ScaleForDpi(T value, unsigned dpi) {
|
||||
return value * dpi / 96;
|
||||
constexpr T ScaleForDpi(T value, unsigned dpi, unsigned source_dpi = 96) {
|
||||
return value * dpi / source_dpi;
|
||||
}
|
||||
|
||||
struct ScreenMetrics {
|
||||
|
||||
@@ -137,19 +137,21 @@ void DesktopNotificationController::InitializeFonts() {
|
||||
if (!body_font_) {
|
||||
NONCLIENTMETRICS metrics = { sizeof(metrics) };
|
||||
if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &metrics, 0)) {
|
||||
auto baseHeight = metrics.lfMessageFont.lfHeight;
|
||||
auto base_height = metrics.lfMessageFont.lfHeight;
|
||||
|
||||
HDC hdc = GetDC(NULL);
|
||||
auto dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
|
||||
auto base_dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
|
||||
ReleaseDC(NULL, hdc);
|
||||
|
||||
ScreenMetrics scr;
|
||||
|
||||
metrics.lfMessageFont.lfHeight =
|
||||
(LONG)ScaleForDpi(baseHeight * 1.1f, dpi_y);
|
||||
(LONG)ScaleForDpi(base_height * 1.1f, scr.dpi_y, base_dpi_y);
|
||||
body_font_ = CreateFontIndirect(&metrics.lfMessageFont);
|
||||
|
||||
if (caption_font_) DeleteFont(caption_font_);
|
||||
metrics.lfMessageFont.lfHeight =
|
||||
(LONG)ScaleForDpi(baseHeight * 1.4f, dpi_y);
|
||||
(LONG)ScaleForDpi(base_height * 1.4f, scr.dpi_y, base_dpi_y);
|
||||
caption_font_ = CreateFontIndirect(&metrics.lfMessageFont);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ app.on('window-all-closed', () => {
|
||||
exports.load = (appUrl) => {
|
||||
app.on('ready', () => {
|
||||
const options = {
|
||||
width: 800,
|
||||
width: 900,
|
||||
height: 600,
|
||||
autoHideMenuBar: true,
|
||||
backgroundColor: '#FFFFFF',
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -7,21 +7,28 @@ const url = require('url')
|
||||
|
||||
// Parse command line options.
|
||||
const argv = process.argv.slice(1)
|
||||
const option = { file: null, help: null, version: null, abi: null, webdriver: null, modules: [] }
|
||||
|
||||
const option = {
|
||||
file: null,
|
||||
help: null,
|
||||
default: null,
|
||||
version: null,
|
||||
webdriver: null,
|
||||
modules: []
|
||||
}
|
||||
|
||||
for (let i = 0; i < argv.length; i++) {
|
||||
if (argv[i] === '--version' || argv[i] === '-v') {
|
||||
option.version = true
|
||||
break
|
||||
} else if (argv[i] === '--abi') {
|
||||
option.abi = true
|
||||
break
|
||||
} else if (argv[i].match(/^--app=/)) {
|
||||
option.file = argv[i].split('=')[1]
|
||||
break
|
||||
} else if (argv[i] === '--help' || argv[i] === '-h') {
|
||||
option.help = true
|
||||
} else if (argv[i] === '--default' || argv[i] === '-d') {
|
||||
option.default = true
|
||||
break
|
||||
} else if (argv[i] === '--interactive' || argv[i] === '-i') {
|
||||
} else if (argv[i] === '--interactive' || argv[i] === '-i' ||
|
||||
argv[i] === '-repl' || argv[i] === '-r') {
|
||||
option.interactive = true
|
||||
} else if (argv[i] === '--test-type=webdriver') {
|
||||
option.webdriver = true
|
||||
@@ -190,22 +197,19 @@ app.once('ready', () => {
|
||||
}
|
||||
]
|
||||
})
|
||||
template[1].submenu.push(
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Speech',
|
||||
submenu: [
|
||||
{
|
||||
role: 'startspeaking'
|
||||
},
|
||||
{
|
||||
role: 'stopspeaking'
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
template[1].submenu.push({
|
||||
type: 'separator'
|
||||
}, {
|
||||
label: 'Speech',
|
||||
submenu: [
|
||||
{
|
||||
role: 'startspeaking'
|
||||
},
|
||||
{
|
||||
role: 'stopspeaking'
|
||||
}
|
||||
]
|
||||
})
|
||||
template[3].submenu = [
|
||||
{
|
||||
role: 'close'
|
||||
@@ -226,11 +230,9 @@ app.once('ready', () => {
|
||||
} else {
|
||||
template.unshift({
|
||||
label: 'File',
|
||||
submenu: [
|
||||
{
|
||||
role: 'quit'
|
||||
}
|
||||
]
|
||||
submenu: [{
|
||||
role: 'quit'
|
||||
}]
|
||||
})
|
||||
}
|
||||
|
||||
@@ -327,16 +329,17 @@ if (option.file && !option.webdriver) {
|
||||
} else if (option.version) {
|
||||
console.log('v' + process.versions.electron)
|
||||
process.exit(0)
|
||||
} else if (option.abi) {
|
||||
console.log(process.versions.modules)
|
||||
process.exit(0)
|
||||
} else if (option.help) {
|
||||
const helpMessage = `Electron ${process.versions.electron} - Build cross platform desktop apps with JavaScript, HTML, and CSS
|
||||
|
||||
} else if (option.default) {
|
||||
const indexPath = path.join(__dirname, '/index.html')
|
||||
loadApplicationByUrl(`file://${indexPath}`)
|
||||
} else if (option.interactive) {
|
||||
startRepl()
|
||||
} else {
|
||||
const welcomeMessage = `
|
||||
Electron ${process.versions.electron} - Build cross platform desktop apps with JavaScript, HTML, and CSS
|
||||
Usage: electron [options] [path]
|
||||
|
||||
A path to an Electron app may be specified. The path must be one of the following:
|
||||
|
||||
A path to an Electron app may be specified. It must be one of the following:
|
||||
- index.js file.
|
||||
- Folder containing a package.json file.
|
||||
- Folder containing an index.js file.
|
||||
@@ -344,16 +347,12 @@ if (option.file && !option.webdriver) {
|
||||
- http://, https://, or file:// URL.
|
||||
|
||||
Options:
|
||||
-h, --help Print this usage message.
|
||||
-d, --default Run the default bundled Electron app.
|
||||
-i, --interactive Open a REPL to the main process.
|
||||
-r, --require Module to preload (option can be repeated)
|
||||
-v, --version Print the version.
|
||||
--abi Print the application binary interface.`
|
||||
console.log(helpMessage)
|
||||
process.exit(0)
|
||||
} else if (option.interactive) {
|
||||
startRepl()
|
||||
} else {
|
||||
-v, --version Print the version.`
|
||||
|
||||
console.log(welcomeMessage)
|
||||
const indexPath = path.join(__dirname, '/index.html')
|
||||
loadApplicationByUrl(`file://${indexPath}`)
|
||||
}
|
||||
|
||||
@@ -1,45 +1,22 @@
|
||||
const {remote, shell} = require('electron')
|
||||
const {execFile} = require('child_process')
|
||||
const path = require('path')
|
||||
const URL = require('url')
|
||||
const electronPath = path.relative(process.cwd(), remote.process.execPath)
|
||||
|
||||
const {execPath} = remote.process
|
||||
Array.from(document.querySelectorAll('a[href]')).forEach(link => {
|
||||
// safely add `?utm_source=default_app
|
||||
let url = URL.parse(link.getAttribute('href'), true)
|
||||
url.query = Object.assign(url.query, {utm_source: 'default_app'})
|
||||
url = URL.format(url)
|
||||
|
||||
document.onclick = function (e) {
|
||||
e.preventDefault()
|
||||
if (e.target.tagName === 'A') {
|
||||
shell.openExternal(e.target.href)
|
||||
}
|
||||
return false
|
||||
}
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault()
|
||||
shell.openExternal(url)
|
||||
})
|
||||
})
|
||||
|
||||
document.ondragover = document.ondrop = function (e) {
|
||||
e.preventDefault()
|
||||
return false
|
||||
}
|
||||
|
||||
const holder = document.getElementById('holder')
|
||||
holder.ondragover = function () {
|
||||
this.className = 'hover'
|
||||
return false
|
||||
}
|
||||
|
||||
holder.ondragleave = holder.ondragend = function () {
|
||||
this.className = ''
|
||||
return false
|
||||
}
|
||||
|
||||
holder.ondrop = function (e) {
|
||||
this.className = ''
|
||||
e.preventDefault()
|
||||
|
||||
const file = e.dataTransfer.files[0]
|
||||
execFile(execPath, [file.path], {
|
||||
detached: true, stdio: 'ignore'
|
||||
}).unref()
|
||||
return false
|
||||
}
|
||||
|
||||
const version = process.versions.electron
|
||||
document.querySelector('.header-version').innerText = version
|
||||
document.querySelector('.command-example').innerText = `${execPath} path-to-your-app`
|
||||
document.querySelector('.quick-start-link').href = `https://github.com/electron/electron/blob/v${version}/docs/tutorial/quick-start.md`
|
||||
document.querySelector('.docs-link').href = `https://github.com/electron/electron/tree/v${version}/docs#readme`
|
||||
document.querySelector('.electron-version').innerText = `Electron v${process.versions.electron}`
|
||||
document.querySelector('.chrome-version').innerText = `Chromium v${process.versions.chrome}`
|
||||
document.querySelector('.node-version').innerText = `Node v${process.versions.node}`
|
||||
document.querySelector('.v8-version').innerText = `v8 v${process.versions.v8}`
|
||||
document.querySelector('.command-example').innerText = `${electronPath} path-to-app`
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
반드시 사용하는 Electron 버전과 문서 버전을 일치시켜야 합니다. 버전 숫자는 문서
|
||||
페이지 URL에 포함되어 있습니다. 만약 그렇지 않다면, 아마 개발 브랜치의 문서일
|
||||
것이며 당신의 Electron 버전과 호환되지 않는 API 변경을 포함할 것 입니다.
|
||||
이전 버전 문서는 깃허브에서 [태그로 열어]
|
||||
(https://github.com/electron/electron/tree/v1.4.0) 볼 수 있습니다.
|
||||
이전 버전 문서는 깃허브에서 [태그로 열어](https://github.com/electron/electron/tree/v1.4.0) 볼 수 있습니다.
|
||||
"branches/tags 변경" 드롭다운을 열고 해당 버전의 태그를 선택하세요.
|
||||
|
||||
**역자주:** 한국어 번역 문서는 `atom.io`에 반영되어 있지 않습니다. 한국어 번역
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
## 이슈 제출
|
||||
|
||||
* [여기](https://github.com/electron/electron/issues/new)에서 새로운 이슈를 만들 수
|
||||
있습니다. 하지만 이슈를 작성하기 전에 아래의 항목들을 숙지하고 가능한한 이슈 보고에
|
||||
있습니다. 하지만 이슈를 작성하기 전에 아래의 항목들을 숙지하고 가능한 한 이슈 보고에
|
||||
대해 최대한 많은 정보와 자세한 설명을 포함해야 합니다. 가능하다면 다음 항목을 포함해야
|
||||
합니다:
|
||||
* 사용하고 있는 Electron의 버전
|
||||
@@ -28,9 +28,9 @@
|
||||
|
||||
## Pull Request 하기
|
||||
|
||||
* 가능한한 스크린샷과 GIF 애니메이션 이미지를 pull request에 추가
|
||||
* 가능한 한 스크린샷과 GIF 애니메이션 이미지를 pull request에 추가
|
||||
* JavaScript, C++과 Python등
|
||||
[참조 문서에 정의된 코딩스타일](/docs-translations/ko-KR/development/coding-style.md)을
|
||||
[참조 문서에 정의된 코딩 스타일](/docs-translations/ko-KR/development/coding-style.md)을
|
||||
준수
|
||||
* [문서 스타일 가이드](/docs-translations/ko-KR/styleguide.md)에 따라 문서를
|
||||
[Markdown](https://daringfireball.net/projects/markdown) 형식으로 작성.
|
||||
|
||||
@@ -42,7 +42,7 @@ npm install electron --save-dev
|
||||
## 참조 문서
|
||||
|
||||
[Docs](https://github.com/electron/electron/tree/master/docs-translations/ko-KR/README.md)에
|
||||
개발 지침과 API 레퍼런스가 있습니다. Electron을 빌드 하는 방법과 프로젝트에 기여하는법
|
||||
개발 지침과 API 레퍼런스가 있습니다. Electron을 빌드 하는 방법과 프로젝트에 기여하는 법
|
||||
또한 문서에 포함되어 있으니 참고하시기 바랍니다.
|
||||
|
||||
## 참조 문서 (번역)
|
||||
|
||||
@@ -36,7 +36,7 @@ Existem muitas perguntas comuns que são feitas, verifique antes de criar uma is
|
||||
* [Processos](api/process.md)
|
||||
* [Aceleradores (Teclas de Atalho)](api/accelerator.md)
|
||||
* [Parâmetros CLI suportados (Chrome)](../../docs/api/chrome-command-line-switches.md)
|
||||
* [Variáveis de Ambiente](../../docs/api/environment-variables.md)
|
||||
* [Variáveis de Ambiente](../../docs-translations/pt-BR/api/environment-variables.md)
|
||||
|
||||
### Elementos DOM Personalizados:
|
||||
|
||||
|
||||
91
docs-translations/pt-BR/api/environment-variables.md
Normal file
91
docs-translations/pt-BR/api/environment-variables.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# Variáveis de ambiente
|
||||
|
||||
> Controla as configurações e comportamento sem modificar o código
|
||||
|
||||
Certos comportamentos do Electron são controlados por variáveis de ambiente que
|
||||
são inicializadas antes do código do aplicativo e da chamada da linha de comando.
|
||||
|
||||
Exemplo no POSIX shell:
|
||||
|
||||
```bash
|
||||
$ export ELECTRON_ENABLE_LOGGING=true
|
||||
$ electron
|
||||
```
|
||||
|
||||
Exemplo no prompt de comando do Windows:
|
||||
|
||||
```powershell
|
||||
> set ELECTRON_ENABLE_LOGGING=true
|
||||
> electron
|
||||
```
|
||||
|
||||
## Variáveis de produção
|
||||
|
||||
As seguintes variáveis de ambiente são destinadas principalmente para o uso
|
||||
em tempo de execução, empacotadas nas aplicações Electron.
|
||||
|
||||
### `GOOGLE_API_KEY`
|
||||
|
||||
O Electron já vem com uma chave para API inclusa para fazer requisições para
|
||||
o serviço de geolocalização do Google. Por causa da chave da API vir inclusa
|
||||
em cada versão do Electron, frequentemente excede a cota de uso. Para contornar
|
||||
isso, você pode informar sua própria chave da API do Google nas variáveis de
|
||||
ambiente. Informe o código no seu arquivo principal, antes do browser
|
||||
ser aberto, isso fará com que a aplicação use-o para fazer as requisições:
|
||||
|
||||
```javascript
|
||||
process.env.GOOGLE_API_KEY = 'YOUR_KEY_HERE'
|
||||
```
|
||||
|
||||
Para maiores instruções de como conseguir uma chave da API do Google, visite
|
||||
[essa página](https://www.chromium.org/developers/how-tos/api-keys).
|
||||
|
||||
Por padrão, a mais recente chave da API do Google pode não ser permitida para
|
||||
fazer requisições de geolocalização. Para habilitar as requisições, acesse
|
||||
[essa página](https://console.developers.google.com/apis/api/geolocation/overview).
|
||||
|
||||
### `ELECTRON_NO_ASAR`
|
||||
|
||||
Desabilita o suporte ASAR. Essa variável é suportada somente em processos
|
||||
filhos bifurcados e gerados a partir de processos que definem
|
||||
`ELECTRON_RUN_AS_NODE`.
|
||||
|
||||
### `ELECTRON_RUN_AS_NODE`
|
||||
|
||||
Inicia o processo como um processo padrão de Node.js.
|
||||
|
||||
### `ELECTRON_NO_ATTACH_CONSOLE` _Windows_
|
||||
|
||||
Não anexa a janela à sessão atual do console.
|
||||
|
||||
### `ELECTRON_FORCE_WINDOW_MENU_BAR` _Linux_
|
||||
|
||||
Não usa a barra de menu global do Linux.
|
||||
|
||||
## Variáveis de desenvolvimento
|
||||
|
||||
As seguintes variáveis de ambiente são destinadas principalmente ao
|
||||
desenvolvimento e o processo de debug.
|
||||
|
||||
|
||||
### `ELECTRON_ENABLE_LOGGING`
|
||||
|
||||
Imprime os logs internos do Chrome no terminal.
|
||||
|
||||
### `ELECTRON_LOG_ASAR_READS`
|
||||
|
||||
Quando o Electron lê um arquivo ASAR, registra o deslocamento e o caminho
|
||||
do arquivo no sistema `tmpdir`. O arquivo resultante pode ser fornecido
|
||||
ao módulo ASAR para otimizar a organização dos arquivos.
|
||||
|
||||
### `ELECTRON_ENABLE_STACK_DUMPING`
|
||||
|
||||
Imprime o stack trace no terminal quando o Electron trava.
|
||||
|
||||
Essa variável de ambiente não funcionará se o `crashReporter` for iniciado.
|
||||
|
||||
### `ELECTRON_DEFAULT_ERROR_MODE` _Windows_
|
||||
|
||||
Exibe a janela de erro do Windows quando o Electron trava.
|
||||
|
||||
Essa variável de ambiente não funcionará se o `crashReporter` for iniciado.
|
||||
109
docs-translations/zh-CN/api/notification.md
Normal file
109
docs-translations/zh-CN/api/notification.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# 通知
|
||||
|
||||
> 创建系统桌面通知
|
||||
|
||||
进程: [Main](../glossary.md#main-process)
|
||||
|
||||
## 在渲染器进程中使用
|
||||
|
||||
如果你想要从渲染器进程显示通知,则应使用 [HTML5 Notification API](../tutorial/notifications.md)
|
||||
|
||||
## 类: Notification
|
||||
|
||||
> 创建系统桌面通知
|
||||
|
||||
进程: [Main](../glossary.md#main-process)
|
||||
|
||||
`Notification` 是一个
|
||||
[EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter).
|
||||
|
||||
它通过由 `options ` 设置的原生属性创建一个新的 `Notification`.
|
||||
|
||||
### 静态方法
|
||||
|
||||
`Notification` 类具有以下静态方法:
|
||||
|
||||
#### `Notification.isSupported()`
|
||||
|
||||
返回 `Boolean` - 无论当前系统是否支持桌面通知
|
||||
|
||||
### `new Notification([options])` _实验性_
|
||||
|
||||
* `options` 对象
|
||||
* `title` 字符串 - 通知的标题,显示在通知窗口的顶部.
|
||||
* `subtitle` 字符串 - (可选) 通知的副标题,将显示在标题下方. _macOS_
|
||||
* `body` 字符串 - 通知的正文,将显示在标题或副标题下方.
|
||||
* `silent` 布尔 - (可选) 是否在显示通知时发出系统通知提示音.
|
||||
* `icon` [NativeImage](native-image.md) - (可选) 通知所使用的图标
|
||||
* `hasReply` 布尔 - (可选) 是否在通知中添加内联的回复选项. _macOS_
|
||||
* `replyPlaceholder` 字符串 - (可选) 在内联输入字段中的提示占位符. _macOS_
|
||||
* `sound` 字符串 - (可选) 显示通知时要播放的声音文件的名称. _macOS_
|
||||
* `actions` [NotificationAction[]](structures/notification-action.md) - (可选) 添加到通知中的操作. 请阅读 `NotificationAction` 文档中的可用操作和限制. _macOS_
|
||||
|
||||
|
||||
### 实例事件
|
||||
|
||||
使用 `new Notification` 创建的对象会发出以下事件:
|
||||
|
||||
**注意:** 某些事件仅在特定的操作系统上可用,请参照标签标示。
|
||||
|
||||
#### 事件: 'show'
|
||||
|
||||
返回:
|
||||
|
||||
* `event` 事件
|
||||
|
||||
当向用户显示通知时发出. 注意这可以被多次触发, 因为通知可以通过 `show()` 方法多次显示.
|
||||
|
||||
#### 事件: 'click'
|
||||
|
||||
返回:
|
||||
|
||||
* `event` 事件
|
||||
|
||||
当用户点击通知时发出.
|
||||
|
||||
#### 事件: 'close'
|
||||
|
||||
返回:
|
||||
|
||||
* `event` 事件
|
||||
|
||||
当用户手动关闭通知时发出.
|
||||
|
||||
在关闭所有通知的情况下,不能保证会发送此事件.
|
||||
|
||||
#### 事件: 'reply' _macOS_
|
||||
|
||||
返回:
|
||||
|
||||
* `event` 事件
|
||||
* `reply` 字符串 - 用户输入到内联回复字段的字符串.
|
||||
|
||||
当用户点击 `hasReply: true` 的通知上的 “回复” 按钮时发出.
|
||||
|
||||
#### Event: 'action' _macOS_
|
||||
|
||||
返回:
|
||||
|
||||
* `event` 事件
|
||||
* `index` Number - The index of the action that was activated
|
||||
|
||||
### 实例方法
|
||||
|
||||
使用 `new Notification` 创建的对象具有以下实例方法:
|
||||
|
||||
#### `notification.show()`
|
||||
|
||||
立即向用户显示通知. 请注意这不同于 HTML5 Notification 的实现, 简单地实例化一个 `new Notification` 不会立即向用户显示, 你需要在操作系统显示之前调用此方法.
|
||||
|
||||
### 播放声音
|
||||
|
||||
在 macOS 上, 你可以在显示通知时指定要播放的声音的名称. 除了自定义声音文件, 可以使用任意默认声音 (在 “系统偏好设置” > “声音” 下) . 同时确保声音文件被复制到应用程序包下 (例如`YourApp.app/Contents/Resources`), 或以下位置之一:
|
||||
|
||||
* `~/Library/Sounds`
|
||||
* `/Library/Sounds`
|
||||
* `/Network/Library/Sounds`
|
||||
* `/System/Library/Sounds`
|
||||
|
||||
查看 [`NSSound`](https://developer.apple.com/documentation/appkit/nssound) 文档获取更多信息.
|
||||
@@ -0,0 +1,19 @@
|
||||
# NotificationAction 对象
|
||||
|
||||
* `type` 字符串 - 动作的类型, 可以是 `button`.
|
||||
* `text` 字符串 - (可选) 指定动作的标签.
|
||||
|
||||
## 平台 / 动作 支持
|
||||
|
||||
| 动作类型 | 平台支持 | `text`用法 | 默认 `text` | 限制 |
|
||||
|-------------|------------------|-----------------|----------------|-------------|
|
||||
| `button` | macOS | 用作按钮的标签 | "Show" | 最多只有一个按钮,如果仅提供多个,则仅使用最后一个按钮。 此操作也与 `hasReply` 不兼容,如果 `hasReply` 为 `true` ,将被忽略。 |
|
||||
|
||||
### macOS 上的按钮支持
|
||||
|
||||
为了让额外的通知按钮在 MacOS 上工作,您的应用程序必须符合以下条件。
|
||||
|
||||
* 应用程序已签名。
|
||||
* 在 `info.plist` 中,将应用程序的 `NSUserNotificationAlertStyle` 设为 `alert` 。
|
||||
|
||||
如果这些要求中的任何一个都不符合,按钮就不会出现。
|
||||
@@ -180,7 +180,7 @@ $ ./script/build.py -c R
|
||||
|
||||
### 环境变量
|
||||
|
||||
除了 `CC` 及 `CXX`, 你还可以设置以下环境变量来自定以编译配置:
|
||||
除了 `CC` 及 `CXX`, 你还可以设置以下环境变量来自定义编译配置:
|
||||
|
||||
* `CPPFLAGS`
|
||||
* `CPPFLAGS_host`
|
||||
|
||||
57
docs-translations/zh-CN/tutorial/notifications.md
Normal file
57
docs-translations/zh-CN/tutorial/notifications.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# 通知 (Windows, Linux, macOS)
|
||||
|
||||
所有三个操作系统都提供了应用程序向用户发送通知的手段。Electron允许开发者使用 [HTML5 Notification API](https://notifications.spec.whatwg.org/) 发送通知,并使用当前运行的操作系统的本地通知 API 来显示它。
|
||||
|
||||
**注意:** 由于这是一个 HTML5 API,它只能在渲染器进程中使用。 如果你想在主进程中显示通知,请查看 [Notification](../api/notification.md) 模块.
|
||||
|
||||
```javascript
|
||||
let myNotification = new Notification('标题', {
|
||||
body: '通知正文内容'
|
||||
})
|
||||
|
||||
myNotification.onclick = () => {
|
||||
console.log('通知被点击')
|
||||
}
|
||||
```
|
||||
|
||||
虽然操作系统的代码和用户体验相似,但依然存在微妙的差异。
|
||||
|
||||
## Windows
|
||||
|
||||
* 在 Windows 10 上, 通知 "仅能运行".
|
||||
* 在 Windows 8.1 和 Windows 8 上, 你的应用程序的快捷方式,[Application User Model ID][app-user-model-id],必须安装到 “开始” 屏幕。但是请注意,它不需要被固定到开始屏幕。
|
||||
* 在 Windows 7 上, 通知通过视觉上类似于较新系统原生的一个自定义的实现来工作。
|
||||
|
||||
此外,在Windows 8中,通知正文的最大长度为250个字符,Windows团队建议将通知保留为200个字符。 然而,Windows 10中已经删除了这个限制,但是Windows团队要求开发人员合理使用。 尝试将大量文本发送到API(数千个字符)可能会导致不稳定。
|
||||
|
||||
### 高级通知
|
||||
|
||||
Windows 的更高版本允许高级通知,自定义模板,图像和其他灵活元素。 要发送这些通知(来自主进程或渲染器进程),请使用用户区模块 [electron-windows-notifications](https://github.com/felixrieseberg/electron-windows-notifications) 来用原生节点附件发送 `ToastNotification` 和 `TileNotification` 对象。
|
||||
|
||||
虽然包含按钮的通知只能使用 `electron-windows-notifications`,但处理回复则需要使用[`electron-windows-interactive-notifications`](https://github.com/felixrieseberg/electron-windows-interactive-notifications),这有助于注册所需的COM组件,并使用输入的用户数据调用Electron应用程序。
|
||||
|
||||
### 免打扰模式 / 演示模式
|
||||
|
||||
要检测是否允许发送通知,请使用用户区模块 [electron-notification-state](https://github.com/felixrieseberg/electron-notification-state)。
|
||||
|
||||
这样,您可以提前确定 Windows 是否会将通知忽略。
|
||||
|
||||
## macOS
|
||||
|
||||
macOS上的通知是最直接的,但你应该注意 [苹果关于通知的人机接口指南](https://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/OSXHIGuidelines/NotificationCenter.html).
|
||||
|
||||
请注意,通知的大小限制为256个字节,如果超过该限制,则会被截断。
|
||||
|
||||
### 高级通知
|
||||
|
||||
后来的 macOS 版本允许有一个输入字段的通知,允许用户快速回复通知。为了通过输入字段发送通知,请使用用户区模块 [node-mac-notifier](https://github.com/CharlieHess/node-mac-notifier)。
|
||||
|
||||
### 勿扰 / 会话状态
|
||||
|
||||
要检测是否允许发送通知,请使用用户区模块 [electron-notification-state](https://github.com/felixrieseberg/electron-notification-state).
|
||||
|
||||
这样可以提前检测是否显示通知。
|
||||
|
||||
## Linux
|
||||
|
||||
通知使用 `libnotify` 发送,可以在 [Desktop Notifications Specification] [notification-spec] 之后的任何桌面环境中显示通知,包括 Cinnamon, Enlightenment, Unity, GNOME, KDE.
|
||||
4
docs-translations/zh-TW/api/structures/crash-report.md
Normal file
4
docs-translations/zh-TW/api/structures/crash-report.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# CrashReport 物件
|
||||
|
||||
* `date` 字串
|
||||
* `ID` 整數
|
||||
4
docs-translations/zh-TW/api/structures/point.md
Normal file
4
docs-translations/zh-TW/api/structures/point.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# Point 物件
|
||||
|
||||
* `x` 數字
|
||||
* `y` 數字
|
||||
4
docs-translations/zh-TW/api/structures/size.md
Normal file
4
docs-translations/zh-TW/api/structures/size.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# Size 物件
|
||||
|
||||
* `width` 數字
|
||||
* `height` 數字
|
||||
4
docs-translations/zh-TW/api/structures/upload-blob.md
Normal file
4
docs-translations/zh-TW/api/structures/upload-blob.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# UploadBlob 物件
|
||||
|
||||
* `type` 字串 - 應為 `blob` 。
|
||||
* `blobUUID` 字串 - 此上傳資料的 UUID 。
|
||||
11
docs-translations/zh-TW/development/v8-development.md
Normal file
11
docs-translations/zh-TW/development/v8-development.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# V8 開發
|
||||
|
||||
> 一些有關於學習與使用 V8 的收集資源
|
||||
|
||||
* [V8 追蹤](https://github.com/v8/v8/wiki/Tracing-V8)
|
||||
* [V8 性能分析](https://github.com/v8/v8/wiki/V8-Profiler) - 介紹一些有用的性能分析參數: `--prof`,`--trace-ic`,`--trace-opt`,`--trace-deopt`,`--print-bytecode`,`--print-opt-code`
|
||||
* [V8 設計理念](https://docs.google.com/document/d/11T2CRex9hXxoJwbYqVQ32yIPMh0uouUZLdyrtmMoL44/edit?ts=56f27d9d#heading=h.6jz9dj3bnr8t)
|
||||
* [編譯器最佳化](https://github.com/v8/v8/wiki/TurboFan)
|
||||
* [V8 GDB 除錯](https://github.com/v8/v8/wiki/GDB-JIT-Interface)
|
||||
|
||||
[Chromium Development](chromium-development.md) 裡有更多資訊。
|
||||
82
docs-translations/zh-TW/tutorial/updates.md
Normal file
82
docs-translations/zh-TW/tutorial/updates.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# 更新應用程式
|
||||
|
||||
有很多種方式能夠更新 Electron 應用程式,其中最簡單也最正式的一種是使用 [Squirrel](https://github.com/Squirrel) 框架,以及 Electron's [自動更新](../api/auto-updater.md)模組。
|
||||
|
||||
## 部署更新伺服器
|
||||
|
||||
首先,您需要部署一個伺服器讓[自動更新](../api/auto-updater.md)模組能夠下載更新檔案。
|
||||
|
||||
您可以選擇以下幾種服務:
|
||||
|
||||
- [Hazel](https://github.com/zeit/hazel) – Simple update server for open-source
|
||||
apps. Pulls from
|
||||
[GitHub Releases](https://help.github.com/articles/creating-releases/)
|
||||
and can be deployed for free on [Now](https://zeit.co/now).
|
||||
- [Nuts](https://github.com/GitbookIO/nuts) – Also uses
|
||||
[GitHub Releases](https://help.github.com/articles/creating-releases/),
|
||||
but caches app updates on disk and supports private repositories.
|
||||
- [electron-release-server](https://github.com/ArekSredzki/electron-release-server) –
|
||||
Provides a dashboard for handling releases
|
||||
|
||||
如果您的應用程式是使用 [electron-builder][electron-builder-lib] 打包,您可以使用 [electron-updater] 模組,它不需要部署伺服器且允許從靜態網址下載,例如 S3 或 GitHub 。
|
||||
|
||||
## 在您的應用程式中實作更新
|
||||
|
||||
當您部署好更新伺服器後,在您的程式碼中引用必要的模組,以下的程式碼將以 [Hazel](https://github.com/zeit/hazel) 服務為範例。
|
||||
|
||||
**重要:** 請確認以下的程式碼只會在您打包後的應用程式內執行,且不在開發環境中,您可以使用 [electron-is-dev](https://github.com/sindresorhus/electron-is-dev) 來確認當前環境。
|
||||
|
||||
```js
|
||||
const {app, autoUpdater, dialog} = require('electron')
|
||||
```
|
||||
|
||||
接下來,構造更新伺服器網址並傳入 [autoUpdater](../api/auto-updater.md) :
|
||||
|
||||
```js
|
||||
const server = 'https://your-deployment-url.com'
|
||||
const feed = `${server}/update/${process.platform}/${app.getVersion()}`
|
||||
|
||||
autoUpdater.setFeedURL(feed)
|
||||
```
|
||||
|
||||
最後,檢查更新,以下的範例將會每分鐘檢查一次。
|
||||
|
||||
```js
|
||||
setInterval(() => {
|
||||
autoUpdater.checkForUpdates()
|
||||
}, 60000)
|
||||
```
|
||||
|
||||
當你[打包](../tutorial/application-distribution.md)您的應用程式後,應用程式將會收到每次您在 [GitHub Release](https://help.github.com/articles/creating-releases/) 的更新檔案。
|
||||
|
||||
## 應用更新
|
||||
|
||||
現在您已為應用程式部署了一個基礎的更新機制,為了要確保所有的用戶都會收到更新通知,您可以使用 autoUpdater API [events](../api/auto-updater.md#events) 來實作:
|
||||
|
||||
```js
|
||||
autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
|
||||
const dialogOpts = {
|
||||
type: 'info',
|
||||
buttons: ['Restart', 'Later'],
|
||||
title: 'Application Update',
|
||||
message: process.platform === 'win32' ? releaseNotes : releaseName,
|
||||
detail: 'A new version has been downloaded. Restart the application to apply the updates.'
|
||||
}
|
||||
|
||||
dialog.showMessageBox(dialogOpts, (response) => {
|
||||
if (response === 0) autoUpdater.quitAndInstall()
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
同時確認所有的錯誤都有被[處理](../api/auto-updater.md#event-error),以下將以記錄錯誤至 `stderr` 為範例:
|
||||
|
||||
```js
|
||||
autoUpdater.on('error', message => {
|
||||
console.error('There was a problem updating the application')
|
||||
console.error(message)
|
||||
})
|
||||
```
|
||||
|
||||
[electron-builder-lib]: https://github.com/electron-userland/electron-builder
|
||||
[electron-updater]: https://www.electron.build/auto-update
|
||||
@@ -458,6 +458,7 @@ You can request the following paths by the name:
|
||||
* `music` Directory for a user's music.
|
||||
* `pictures` Directory for a user's pictures.
|
||||
* `videos` Directory for a user's videos.
|
||||
* `logs` Directory for your app's log folder.
|
||||
* `pepperFlashSystemPlugin` Full path to the system version of the Pepper Flash plugin.
|
||||
|
||||
### `app.getFileIcon(path[, options], callback)`
|
||||
@@ -542,7 +543,7 @@ bar, and on macOS you can visit it from dock menu.
|
||||
|
||||
Clears the recent documents list.
|
||||
|
||||
### `app.setAsDefaultProtocolClient(protocol[, path, args])` _macOS_ _Windows_
|
||||
### `app.setAsDefaultProtocolClient(protocol[, path, args])`
|
||||
|
||||
* `protocol` String - The name of your protocol, without `://`. If you want your
|
||||
app to handle `electron://` links, call this method with `electron` as the
|
||||
|
||||
@@ -205,6 +205,8 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
`#FFF` (white).
|
||||
* `hasShadow` Boolean (optional) - Whether window should have a shadow. This is only
|
||||
implemented on macOS. Default is `true`.
|
||||
* `opacity` Number (optional) - Set the initial opacity of the window, between 0.0 (fully
|
||||
transparent) and 1.0 (fully opaque). This is only implemented on Windows and macOS.
|
||||
* `darkTheme` Boolean (optional) - Forces using dark theme for the window, only works on
|
||||
some GTK+3 desktop environments. Default is `false`.
|
||||
* `transparent` Boolean (optional) - Makes the window [transparent](frameless-window.md).
|
||||
@@ -1206,6 +1208,16 @@ Returns `Boolean` - Whether the window has a shadow.
|
||||
On Windows and Linux always returns
|
||||
`true`.
|
||||
|
||||
#### `win.setOpacity(opacity)` _Windows_ _macOS_
|
||||
|
||||
* `opacity` Number - between 0.0 (fully transparent) and 1.0 (fully opaque)
|
||||
|
||||
Sets the opacity of the window. On Linux does nothing.
|
||||
|
||||
#### `win.getOpacity()` _Windows_ _macOS_
|
||||
|
||||
Returns `Number` - between 0.0 (fully transparent) and 1.0 (fully opaque)
|
||||
|
||||
#### `win.setThumbarButtons(buttons)` _Windows_
|
||||
|
||||
* `buttons` [ThumbarButton[]](structures/thumbar-button.md)
|
||||
@@ -1401,6 +1413,12 @@ there is more than one tab in the current window.
|
||||
Toggles the visibility of the tab bar if native tabs are enabled and
|
||||
there is only one tab in the current window.
|
||||
|
||||
#### `win.addTabbedWindow(browserWindow)` _macOS_
|
||||
|
||||
* `browserWindow` BrowserWindow
|
||||
|
||||
Adds a window as a tab on this window, after the tab for the window instance.
|
||||
|
||||
#### `win.setVibrancy(type)` _macOS_
|
||||
|
||||
* `type` String - Can be `appearance-based`, `light`, `dark`, `titlebar`,
|
||||
@@ -1428,7 +1446,7 @@ removed in future Electron releases.
|
||||
**Note:** The BrowserView API is currently experimental and may change or be
|
||||
removed in future Electron releases.
|
||||
|
||||
[blink-feature-string]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5?l=62
|
||||
[blink-feature-string]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/runtime_enabled_features.json5?l=70
|
||||
[page-visibility-api]: https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
|
||||
[quick-look]: https://en.wikipedia.org/wiki/Quick_Look
|
||||
[vibrancy-docs]: https://developer.apple.com/reference/appkit/nsvisualeffectview?language=objc
|
||||
|
||||
@@ -74,6 +74,14 @@ and replies by setting `event.returnValue`.
|
||||
**Note:** Sending a synchronous message will block the whole renderer process,
|
||||
unless you know what you are doing you should never use it.
|
||||
|
||||
### `ipcRenderer.sendTo(windowId, channel, [, arg1][, arg2][, ...])`
|
||||
|
||||
* `windowId` Number
|
||||
* `channel` String
|
||||
* `...args` any[]
|
||||
|
||||
Sends a message to a window with `windowid` via `channel`
|
||||
|
||||
### `ipcRenderer.sendToHost(channel[, arg1][, arg2][, ...])`
|
||||
|
||||
* `channel` String
|
||||
|
||||
@@ -157,6 +157,34 @@ Returns `NativeImage`
|
||||
|
||||
Creates a new `NativeImage` instance from `dataURL`.
|
||||
|
||||
### `nativeImage.createFromNamedImage(imageName[, hslShift])` _macOS_
|
||||
|
||||
* `imageName` String
|
||||
* `hslShift` Number[]
|
||||
|
||||
Returns `NativeImage`
|
||||
|
||||
Creates a new `NativeImage` instance from the NSImage that maps to the
|
||||
given image name. See [`NSImageName`](https://developer.apple.com/documentation/appkit/nsimagename?language=objc)
|
||||
for a list of possible values.
|
||||
|
||||
The `hslShift` is applied to the image with the following rules
|
||||
* `hsl_shift[0]` (hue): The absolute hue value for the image - 0 and 1 map
|
||||
to 0 and 360 on the hue color wheel (red).
|
||||
* `hsl_shift[1]` (saturation): A saturation shift for the image, with the
|
||||
following key values:
|
||||
0 = remove all color.
|
||||
0.5 = leave unchanged.
|
||||
1 = fully saturate the image.
|
||||
* `hsl_shift[2]` (lightness): A lightness shift for the image, with the
|
||||
following key values:
|
||||
0 = remove all lightness (make all pixels black).
|
||||
0.5 = leave unchanged.
|
||||
1 = full lightness (make all pixels white).
|
||||
|
||||
This means that `[-1, 0, 1]` will make the image completely white and
|
||||
`[-1, 1, 0]` will make the image completely black.
|
||||
|
||||
## Class: NativeImage
|
||||
|
||||
> Natively wrap images such as tray, dock, and application icons.
|
||||
|
||||
@@ -34,7 +34,7 @@ Returns `Boolean` - Whether or not desktop notifications are supported on the cu
|
||||
* `subtitle` String - (optional) A subtitle for the notification, which will be displayed below the title. _macOS_
|
||||
* `body` String - The body text of the notification, which will be displayed below the title or subtitle
|
||||
* `silent` Boolean - (optional) Whether or not to emit an OS notification noise when showing the notification
|
||||
* `icon` [NativeImage](native-image.md) - (optional) An icon to use in the notification
|
||||
* `icon` (String | [NativeImage](native-image.md)) - (optional) An icon to use in the notification
|
||||
* `hasReply` Boolean - (optional) Whether or not to add an inline reply option to the notification. _macOS_
|
||||
* `replyPlaceholder` String - (optional) The placeholder to write in the inline reply input field. _macOS_
|
||||
* `sound` String - (optional) The name of the sound file to play when the notification is shown. _macOS_
|
||||
|
||||
@@ -253,7 +253,8 @@ the original network configuration.
|
||||
* `request` Object
|
||||
* `hostname` String
|
||||
* `certificate` [Certificate](structures/certificate.md)
|
||||
* `error` String - Verification result from chromium.
|
||||
* `verificationResult` String - Verification result from chromium.
|
||||
* `errorCode` Integer - Error code.
|
||||
* `callback` Function
|
||||
* `verificationResult` Integer - Value can be one of certificate error codes
|
||||
from [here](https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h).
|
||||
|
||||
@@ -36,7 +36,7 @@ Open the given file in the desktop's default manner.
|
||||
|
||||
### `shell.openExternal(url[, options, callback])`
|
||||
|
||||
* `url` String
|
||||
* `url` String - max 2081 characters on windows, or the function returns false
|
||||
* `options` Object (optional) _macOS_
|
||||
* `activate` Boolean - `true` to bring the opened application to the
|
||||
foreground. The default is `true`.
|
||||
|
||||
@@ -3,4 +3,5 @@
|
||||
* `percentCPUUsage` Number - Percentage of CPU used since the last call to getCPUUsage.
|
||||
First call returns 0.
|
||||
* `idleWakeupsPerSecond` Number - The number of average idle cpu wakeups per second
|
||||
since the last call to getCPUUsage. First call returns 0.
|
||||
since the last call to getCPUUsage. First call returns 0. Will always return 0 on
|
||||
Windows.
|
||||
|
||||
@@ -112,9 +112,9 @@ Same as `unsubscribeNotification`, but removes the subscriber from `NSNotificati
|
||||
* `type` String - Can be `string`, `boolean`, `integer`, `float`, `double`,
|
||||
`url`, `array`, `dictionary`
|
||||
|
||||
Returns `any` - The value of `key` in system preferences.
|
||||
Returns `any` - The value of `key` in `NSUserDefaults`.
|
||||
|
||||
This API uses `NSUserDefaults` on macOS. Some popular `key` and `type`s are:
|
||||
Some popular `key` and `type`s are:
|
||||
|
||||
* `AppleInterfaceStyle`: `string`
|
||||
* `AppleAquaColorVariant`: `integer`
|
||||
@@ -130,15 +130,22 @@ This API uses `NSUserDefaults` on macOS. Some popular `key` and `type`s are:
|
||||
* `type` String - See [`getUserDefault`][#systempreferencesgetuserdefaultkey-type-macos]
|
||||
* `value` String
|
||||
|
||||
Set the value of `key` in system preferences.
|
||||
Set the value of `key` in `NSUserDefaults`.
|
||||
|
||||
Note that `type` should match actual type of `value`. An exception is thrown
|
||||
if they don't.
|
||||
|
||||
This API uses `NSUserDefaults` on macOS. Some popular `key` and `type`s are:
|
||||
Some popular `key` and `type`s are:
|
||||
|
||||
* `ApplePressAndHoldEnabled`: `boolean`
|
||||
|
||||
### `systemPreferences.removeUserDefault(key)` _macOS_
|
||||
|
||||
* `key` String
|
||||
|
||||
Removes the `key` in `NSUserDefaults`. This can be used to restore the default
|
||||
or global value of a `key` previously set with `setUserDefault`.
|
||||
|
||||
### `systemPreferences.isAeroGlassEnabled()` _Windows_
|
||||
|
||||
Returns `Boolean` - `true` if [DWM composition][dwm-composition] (Aero Glass) is
|
||||
|
||||
@@ -76,6 +76,7 @@ The `Tray` module emits the following events:
|
||||
* `ctrlKey` Boolean
|
||||
* `metaKey` Boolean
|
||||
* `bounds` [Rectangle](structures/rectangle.md) - The bounds of tray icon
|
||||
* `position` [Point](structures/point.md) - The position of the event
|
||||
|
||||
Emitted when the tray icon is clicked.
|
||||
|
||||
@@ -166,6 +167,17 @@ Emitted when the mouse enters the tray icon.
|
||||
|
||||
Emitted when the mouse exits the tray icon.
|
||||
|
||||
#### Event: 'mouse-move' _macOS_
|
||||
|
||||
* `event` Event
|
||||
* `altKey` Boolean
|
||||
* `shiftKey` Boolean
|
||||
* `ctrlKey` Boolean
|
||||
* `metaKey` Boolean
|
||||
* `position` [Point](structures/point.md) - The position of the event
|
||||
|
||||
Emitted when the mouse moves in the tray icon.
|
||||
|
||||
### Instance Methods
|
||||
|
||||
The `Tray` class has the following methods:
|
||||
|
||||
@@ -896,10 +896,10 @@ Inserts `text` to the focused element.
|
||||
uppercase letter followed by a lowercase or non-letter.
|
||||
Accepts several other intra-word matches, defaults to `false`.
|
||||
|
||||
Starts a request to find all matches for the `text` in the web page and returns
|
||||
an `Integer` representing the request id used for the request. The result of
|
||||
the request can be obtained by subscribing to
|
||||
[`found-in-page`](web-contents.md#event-found-in-page) event.
|
||||
Returns `Integer` - The request id used for the request.
|
||||
|
||||
Starts a request to find all matches for the `text` in the web page. The result of the request
|
||||
can be obtained by subscribing to [`found-in-page`](web-contents.md#event-found-in-page) event.
|
||||
|
||||
#### `contents.stopFindInPage(action)`
|
||||
|
||||
|
||||
@@ -520,9 +520,10 @@ Inserts `text` to the focused element.
|
||||
uppercase letter followed by a lowercase or non-letter.
|
||||
Accepts several other intra-word matches, defaults to `false`.
|
||||
|
||||
Starts a request to find all matches for the `text` in the web page and returns an `Integer`
|
||||
representing the request id used for the request. The result of the request can be
|
||||
obtained by subscribing to [`found-in-page`](webview-tag.md#event-found-in-page) event.
|
||||
Returns `Integer` - The request id used for the request.
|
||||
|
||||
Starts a request to find all matches for the `text` in the web page. The result of the request
|
||||
can be obtained by subscribing to [`found-in-page`](webview-tag.md#event-found-in-page) event.
|
||||
|
||||
### `<webview>.stopFindInPage(action)`
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ Electron a completely separate product from NW.js:
|
||||
|
||||
__1. Entry of Application__
|
||||
|
||||
In NW.js the main entry point of an application is a web page. You specify a
|
||||
main page URL in the `package.json` and it is opened in a browser window as
|
||||
the application's main window.
|
||||
In NW.js the main entry point of an application is a web page or a JS script. You specify a
|
||||
html or js file in the `package.json` and it is opened in a browser window as
|
||||
the application's main window (in case of an html entrypoint) or the script is executed.
|
||||
|
||||
In Electron, the entry point is a JavaScript script. Instead of
|
||||
providing a URL directly, you manually create a browser window and load
|
||||
|
||||
@@ -6,7 +6,7 @@ Follow the guidelines below for building Electron on Windows.
|
||||
|
||||
* Windows 7 / Server 2008 R2 or higher
|
||||
* Visual Studio 2015 Update 3 - [download VS 2015 Community Edition for
|
||||
free](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx)
|
||||
free](https://www.visualstudio.com/vs/older-downloads/)
|
||||
* [Python 2.7](http://www.python.org/download/releases/2.7/)
|
||||
* [Node.js](http://nodejs.org/download/)
|
||||
* [Git](http://git-scm.com)
|
||||
|
||||
@@ -2,25 +2,15 @@
|
||||
|
||||
This document describes the process for releasing a new version of Electron.
|
||||
|
||||
## Create a backport branch
|
||||
|
||||
If you're about release a new major or minor version of Electron like `1.8.0`,
|
||||
`1.9.0`, or `2.0.0`, first create a branch from the most recent minor release
|
||||
for later backports:
|
||||
|
||||
Assuming you're about to publish `1.8.0`, and the highest `1.7` release was
|
||||
`1.7.6`:
|
||||
|
||||
```sh
|
||||
git checkout -b 1-7-x v1.7.6
|
||||
git push origin HEAD
|
||||
```
|
||||
## Find out what version change is needed
|
||||
Is this a major, minor, patch, or beta version change? Read the [Version Change Rules](../tutorial/electron-versioning.md#version-change-rules) to find out.
|
||||
|
||||
## Create a temporary branch
|
||||
|
||||
Create a new branch from `master`. Name it `release` or anything you like.
|
||||
- **If releasing beta,** create a new branch from `master`.
|
||||
- **If releasing a stable version,** create a new branch from the beta branch you're stablizing.
|
||||
|
||||
Note: If you are creating a backport release, you'll check out `1-6-x`, `1-7-x`, etc instead of `master`.
|
||||
Name the new branch `release` or anything you like.
|
||||
|
||||
```sh
|
||||
git checkout master
|
||||
@@ -38,17 +28,22 @@ make sure there are no drafts.
|
||||
|
||||
## Bump the version
|
||||
|
||||
Run the `bump-version` script, passing `major`, `minor`, or `patch` as an argument:
|
||||
Run the `bump-version` script with arguments according to your need:
|
||||
- `--bump=[major|minor|patch|beta]` to increment one of the version numbers, or
|
||||
- `--stable` to indicate this is a stable version, or
|
||||
- `--version={version}` to set version number directly.
|
||||
|
||||
**Note**: you can use both `--bump` and `--stable` simultaneously.
|
||||
|
||||
There is also a `dry-run` flag you can use to make sure the version number generated is correct before committing.
|
||||
|
||||
```sh
|
||||
npm run bump-version -- patch
|
||||
npm run bump-version -- --bump=patch --stable
|
||||
git push origin HEAD
|
||||
```
|
||||
|
||||
This will bump the version number in several files. See [this bump commit] for an example.
|
||||
|
||||
Most releases will be `patch` level. Upgrades to Chrome or other major changes should use `minor`. For more info, see [electron-versioning].
|
||||
|
||||
## Wait for builds :hourglass_flowing_sand:
|
||||
|
||||
The presence of the word [`Bump`](https://github.com/electron/electron/blob/7961a97d7ddbed657c6c867cc8426e02c236c077/script/cibuild-linux#L3-L6) in the commit message created by the `bump-version` script
|
||||
@@ -56,8 +51,9 @@ will [trigger the release process](https://github.com/electron/electron/blob/796
|
||||
|
||||
To monitor the build progress, see the following pages:
|
||||
|
||||
- [208.52.191.140:8080/view/All/builds](http://208.52.191.140:8080/view/All/builds) for Mac and Windows
|
||||
- [jenkins.githubapp.com/label/chromium/](https://jenkins.githubapp.com/label/chromium/) for Linux
|
||||
- [208.52.191.140:8080/view/All/builds](http://208.52.191.140:8080/view/All/builds) for Mac
|
||||
- [circleci.com/gh/electron](https://circleci.com/gh/electron) for Linux
|
||||
- [windows-ci.electronjs.org/project/AppVeyor/electron](https://windows-ci.electronjs.org/project/AppVeyor/electron) for Windows
|
||||
|
||||
## Compile release notes
|
||||
|
||||
@@ -65,7 +61,6 @@ Writing release notes is a good way to keep yourself busy while the builds are r
|
||||
For prior art, see existing releases on [the releases page].
|
||||
|
||||
Tips:
|
||||
|
||||
- Each listed item should reference a PR on electron/electron, not an issue, nor a PR from another repo like libcc.
|
||||
- No need to use link markup when referencing PRs. Strings like `#123` will automatically be converted to links on github.com.
|
||||
- To see the version of Chromium, V8, and Node in every version of Electron, visit [atom.io/download/electron/index.json](https://atom.io/download/electron/index.json).
|
||||
@@ -90,6 +85,16 @@ For a `patch` release, use the following format:
|
||||
### Windows
|
||||
|
||||
* Fixed a Windows thing. #1234
|
||||
```
|
||||
|
||||
### Minor releases
|
||||
|
||||
For a `minor` release, e.g. `1.8.0`, use this format:
|
||||
|
||||
```
|
||||
## Upgrades
|
||||
|
||||
- Upgraded from Node `oldVersion` to `newVersion`. #123
|
||||
|
||||
## API Changes
|
||||
|
||||
@@ -108,33 +113,50 @@ For a `patch` release, use the following format:
|
||||
* Changed a Windows thing. #123
|
||||
```
|
||||
|
||||
### Minor releases
|
||||
|
||||
For a `minor` release (which is normally a Chromium update, and possibly also a Node update), e.g. `1.8.0`, use this format:
|
||||
|
||||
### Major releases
|
||||
```
|
||||
**Note:** This is a beta release. This is the first release running on upgraded versions of Chrome/Node.js/V8 and most likely will have have some instability and/or regressions.
|
||||
|
||||
Please file new issues for any bugs you find in it.
|
||||
|
||||
This release is published to [npm](https://www.npmjs.com/package/electron) under the `beta` tag and can be installed via `npm install electron@beta`.
|
||||
|
||||
## Upgrades
|
||||
|
||||
- Upgraded from Chrome `oldVersion` to `newVersion`. #123
|
||||
- Upgraded from Chromium `oldVersion` to `newVersion`. #123
|
||||
- Upgraded from Node `oldVersion` to `newVersion`. #123
|
||||
- Upgraded from v8 `oldVersion` to `newVersion`. #9116
|
||||
|
||||
## Breaking API changes
|
||||
|
||||
* Changed a thing. #123
|
||||
|
||||
### Linux
|
||||
|
||||
* Changed a Linux thing. #123
|
||||
|
||||
### macOS
|
||||
|
||||
* Changed a macOS thing. #123
|
||||
|
||||
### Windows
|
||||
|
||||
* Changed a Windows thing. #123
|
||||
|
||||
## Other Changes
|
||||
|
||||
- Some other change. #123
|
||||
```
|
||||
|
||||
### Beta releases
|
||||
Use the same formats as the ones suggested above, but add the following note at the beginning of the changelog:
|
||||
```
|
||||
**Note:** This is a beta release and most likely will have have some instability and/or regressions.
|
||||
|
||||
Please file new issues for any bugs you find in it.
|
||||
|
||||
This release is published to [npm](https://www.npmjs.com/package/electron) under the `beta` tag and can be installed via `npm install electron@beta`.
|
||||
```
|
||||
|
||||
|
||||
## Edit the release draft
|
||||
|
||||
1. Visit [the releases page] and you'll see a new draft release with placeholder release notes.
|
||||
1. Edit the release and add release notes.
|
||||
1. Ensure the `prerelease` checkbox is checked. This should happen automatically for Electron versions >=1.7
|
||||
1. Uncheck the `prerelease` checkbox if you're publishing a stable release; leave it checked for beta releases.
|
||||
1. Click 'Save draft'. **Do not click 'Publish release'!**
|
||||
1. Wait for all builds to pass before proceeding.
|
||||
|
||||
@@ -201,44 +223,13 @@ git push origin :release # delete remote branch
|
||||
[this bump commit]: https://github.com/electron/electron/commit/78ec1b8f89b3886b856377a1756a51617bc33f5a
|
||||
[electron-versioning]: /docs/tutorial/electron-versioning.md
|
||||
|
||||
## Promote a release on npm
|
||||
|
||||
New releases are published to npm with the `beta` tag. Every release should
|
||||
eventually get promoted to stable unless there's a good reason not to.
|
||||
|
||||
Releases are normally given around two weeks in the wild before being promoted.
|
||||
Before promoting a release, check to see if there are any bug reports
|
||||
against that version, e.g. issues labeled with `version/1.7.x`.
|
||||
|
||||
It's also good to ask users in Slack if they're using the beta versions successfully.
|
||||
|
||||
To see what's beta and stable at any given time:
|
||||
|
||||
```
|
||||
$ npm dist-tag ls electron
|
||||
beta: 1.7.5
|
||||
latest: 1.6.11
|
||||
```
|
||||
|
||||
To promote a beta version to stable (aka `latest`):
|
||||
|
||||
```
|
||||
npm dist-tag add electron@1.2.3 latest
|
||||
```
|
||||
|
||||
Then edit the release on GitGub:
|
||||
|
||||
1. Remove `beta` from the release name: electron v1.7.5 ~~beta~~
|
||||
1. Uncheck the `prerelease` checkbox.
|
||||
1. Click "Update release"
|
||||
|
||||
## Fix missing binaries of a release manually
|
||||
|
||||
In the case of a corrupted release with broken CI machines, we might have to
|
||||
re-upload the binaries for an already published release.
|
||||
|
||||
The first step is to go to the
|
||||
[Releases](https://github.com/electron/electron/releases) page and delete the
|
||||
The first step is to go to the
|
||||
[Releases](https://github.com/electron/electron/releases) page and delete the
|
||||
corrupted binaries with the `SHASUMS256.txt` checksum file.
|
||||
|
||||
Then manually create distributions for each platform and upload them:
|
||||
@@ -261,4 +252,4 @@ file:
|
||||
|
||||
```sh
|
||||
npm run release
|
||||
```
|
||||
```
|
||||
|
||||
97
docs/images/tutorial-release-schedule.svg
Normal file
97
docs/images/tutorial-release-schedule.svg
Normal file
@@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" standalone="yes"?>
|
||||
<svg width="520" height="220" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<marker id="arrow" viewBox="-1 0 12 10" refX="10.5" refY="5" markerWidth="8" markerHeight="8" orient="auto">
|
||||
<path d="M 0 0 L 10 5 L 0 10"/>
|
||||
</marker>
|
||||
<g transform="translate(0,40)">
|
||||
<!-- master -->
|
||||
<text x="60" y="30" text-anchor="end" alignment-baseline="middle">master</text>
|
||||
<path d="M70 30 H 500" stroke-width="2" stroke="black"/>
|
||||
<!-- v2.0 -->
|
||||
<g>
|
||||
<path d="M100 30 l 20 30 H 200" stroke-width="2" stroke="black" fill="transparent"/>
|
||||
<text x="110" y="60" text-anchor="end" alignment-baseline="middle">2.0</text>
|
||||
<circle cx="120" cy="60" r="5"/>
|
||||
<text x="110" y="60" text-anchor="end" alignment-baseline="middle" transform="rotate(-60 120,60)">v2.0.0-beta0</text>
|
||||
<circle cx="200" cy="60" r="5"/>
|
||||
<text x="190" y="60" text-anchor="end" alignment-baseline="middle" transform="rotate(-60 200,60)">v2.0.0</text>
|
||||
</g>
|
||||
<!-- v2.1 -->
|
||||
<g transform="translate(130,0)">
|
||||
<path d="M100 30 l 20 30 H 200" stroke-width="2" stroke="black" fill="transparent"/>
|
||||
<text x="110" y="60" text-anchor="end" alignment-baseline="middle">2.1</text>
|
||||
<circle cx="120" cy="60" r="5"/>
|
||||
<text x="110" y="60" text-anchor="end" alignment-baseline="middle" transform="rotate(-60 120,60)">v2.1.0-beta0</text>
|
||||
<circle cx="160" cy="60" r="5"/>
|
||||
<text x="150" y="60" text-anchor="end" alignment-baseline="middle" transform="rotate(-60 160,60)">v2.1.0-beta1</text>
|
||||
<circle cx="200" cy="60" r="5"/>
|
||||
<text x="190" y="60" text-anchor="end" alignment-baseline="middle" transform="rotate(-60 200,60)">v2.1.0</text>
|
||||
</g>
|
||||
<!-- v3.0 -->
|
||||
<g transform="translate(260,0)">
|
||||
<path d="M100 30 l 20 30 H 200" stroke-width="2" stroke="black" fill="transparent"/>
|
||||
<text x="110" y="60" text-anchor="end" alignment-baseline="middle">3.0</text>
|
||||
<circle cx="120" cy="60" r="5"/>
|
||||
<text x="110" y="60" text-anchor="end" alignment-baseline="middle" transform="rotate(-60 120,60)">v3.0.0-beta0</text>
|
||||
<circle cx="200" cy="60" r="5"/>
|
||||
<text x="190" y="60" text-anchor="end" alignment-baseline="middle" transform="rotate(-60 200,60)">v3.0.0</text>
|
||||
</g>
|
||||
<!-- Bug fixes -->
|
||||
<g transform="translate(160,30)">
|
||||
<circle cx="0" cy="0" r="3"/>
|
||||
<text x="10" y="0" text-anchor="start" alignment-baseline="middle" transform="rotate(-60 0,0)">bug fix</text>
|
||||
<path d="M0 0 l0,30" marker-end="url(#arrow)" stroke-dasharray="2,2" stroke="#000"/>
|
||||
</g>
|
||||
<g transform="translate(260,30)">
|
||||
<circle cx="0" cy="0" r="3"/>
|
||||
<text x="10" y="0" text-anchor="start" alignment-baseline="middle" transform="rotate(-60 0,0)">bug fix</text>
|
||||
<path d="M0 0 l0,30" marker-end="url(#arrow)" stroke-dasharray="2,2" stroke="#000"/>
|
||||
</g>
|
||||
<g transform="translate(280,30)">
|
||||
<circle cx="0" cy="0" r="3"/>
|
||||
<text x="10" y="0" text-anchor="start" alignment-baseline="middle" transform="rotate(-60 0,0)">bug fix</text>
|
||||
<path d="M0 0 l0,30" marker-end="url(#arrow)" stroke-dasharray="2,2" stroke="#000"/>
|
||||
</g>
|
||||
<g transform="translate(400,30)">
|
||||
<circle cx="0" cy="0" r="3"/>
|
||||
<text x="10" y="0" text-anchor="start" alignment-baseline="middle" transform="rotate(-60 0,0)">bug fix</text>
|
||||
<path d="M0 0 l0,30" marker-end="url(#arrow)" stroke-dasharray="2,2" stroke="#000"/>
|
||||
</g>
|
||||
<g transform="translate(430,30)">
|
||||
<circle cx="0" cy="0" r="3"/>
|
||||
<text x="10" y="0" text-anchor="start" alignment-baseline="middle" transform="rotate(-60 0,0)">bug fix</text>
|
||||
<path d="M0 0 l0,30" marker-end="url(#arrow)" stroke-dasharray="2,2" stroke="#000"/>
|
||||
</g>
|
||||
<!-- Features -->
|
||||
<g transform="translate(130,30)">
|
||||
<circle cx="0" cy="0" r="3"/>
|
||||
<text x="10" y="0" text-anchor="start" alignment-baseline="middle" transform="rotate(-60 0,0)">feature</text>
|
||||
</g>
|
||||
<g transform="translate(200,30)">
|
||||
<circle cx="0" cy="0" r="3"/>
|
||||
<text x="10" y="0" text-anchor="start" alignment-baseline="middle" transform="rotate(-60 0,0)">feature</text>
|
||||
</g>
|
||||
<g transform="translate(340,30)">
|
||||
<circle cx="0" cy="0" r="3"/>
|
||||
<text x="10" y="0" text-anchor="start" alignment-baseline="middle" transform="rotate(-60 0,0)">feature</text>
|
||||
</g>
|
||||
<!-- Chromium update -->
|
||||
<g transform="translate(310,30)">
|
||||
<circle cx="0" cy="0" r="3"/>
|
||||
<text x="10" y="0" text-anchor="start" alignment-baseline="middle" transform="rotate(-60 0,0)"><tspan>chromium</tspan><tspan dy="10" x="10">update</tspan></text>
|
||||
</g>
|
||||
<!-- Timeline -->
|
||||
<g transform="translate(100,160)">
|
||||
<text x="50" y="0" text-anchor="middle" alignment-baseline="text-after-edge">~1 week</text>
|
||||
<path d="M0 0 l0 10 l0 -5 H100l0 -5l0 10" stroke-width="2" stroke="black" fill="transparent"/>
|
||||
</g>
|
||||
<g transform="translate(230,160)">
|
||||
<text x="50" y="0" text-anchor="middle" alignment-baseline="text-after-edge">~1 week</text>
|
||||
<path d="M0 0 l0 10 l0 -5 H100l0 -5l0 10" stroke-width="2" stroke="black" fill="transparent"/>
|
||||
</g>
|
||||
<g transform="translate(360,160)">
|
||||
<text x="50" y="0" text-anchor="middle" alignment-baseline="text-after-edge">~1 week</text>
|
||||
<path d="M0 0 l0 10 l0 -5 H100l0 -5l0 10" stroke-width="2" stroke="black" fill="transparent"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.3 KiB |
@@ -1,9 +1,9 @@
|
||||
# Electron Versioning
|
||||
|
||||
If you've been using Node and npm for a while, you are probably aware of [Semantic Versioning], or SemVer for short. It's a convention for specifying version numbers for software that helps communicate intentions to the users of your software.
|
||||
|
||||
## Overview of Semantic Versioning
|
||||
|
||||
If you've been using Node and npm for a while, you are probably aware of [Semantic Versioning], or SemVer for short. It's a convention for specifying version numbers for software that helps communicate intentions to the users of your software.
|
||||
|
||||
Semantic versions are always made up of three numbers:
|
||||
|
||||
```
|
||||
@@ -22,34 +22,99 @@ A simple mnemonic for remembering this scheme is as follows:
|
||||
breaking.feature.fix
|
||||
```
|
||||
|
||||
## Electron Versioning
|
||||
## Before Version 2
|
||||
|
||||
Due to its dependency on Node and Chromium, it is not possible for the Electron
|
||||
project to adhere to a SemVer policy. **You should therefore always
|
||||
reference a specific version of Electron.**
|
||||
Before version 2 of Electron we didn't follow SemVer, instead the following was used:
|
||||
|
||||
Electron version numbers are bumped using the following rules:
|
||||
- **Major**: Breaking changes to Electron's API
|
||||
- **Minor**: Major Chrome, minor node or "significant" Electron changes
|
||||
- **Patch**: New features and bug fixes
|
||||
|
||||
* **Major** is for breaking changes in Electron's API. If you upgrade from `0.37.0`
|
||||
to `1.0.0`, you will have to make changes to your app.
|
||||
* **Minor** is for major Chrome and minor Node upgrades, or significant Electron
|
||||
changes. If you upgrade from `1.5.0` to `1.6.0`, your app is supposed to
|
||||
still work, but you might have to work around small changes.
|
||||
* **Patch** is for new features and bug fixes. If you upgrade from `1.6.2` to
|
||||
`1.6.3`, your app will continue to work as-is.
|
||||
This system had a number of drawbacks, such as:
|
||||
|
||||
We recommend that you set a fixed version when installing Electron from npm:
|
||||
- New bugs could be introduced into a new patch version because patch versions added features
|
||||
- It didn't follow SemVer so it could confuse consumers
|
||||
- It wasn't clear what the differences between stable and beta builds were
|
||||
- The lack of a formalized stabilization process and release schedule lead to sporadic releases and betas that could last several months
|
||||
|
||||
```sh
|
||||
npm install electron --save-exact --save-dev
|
||||
## Version 2 and Beyond
|
||||
|
||||
From version 2.0.0, Electron will attempt to adhere to SemVer and follow a
|
||||
release schedule and stabilization process similar to that of Chromium.
|
||||
|
||||
### Version Change Rules
|
||||
|
||||
Here are the general rules that apply when releasing new versions:
|
||||
|
||||
| Type of change | Version increase
|
||||
|---|---
|
||||
| Chromium version update | Major
|
||||
| Node *major* version update | Major
|
||||
| Electron breaking API change | Major
|
||||
| Any other changes deemed "risky" | Major
|
||||
| Node *minor* version update | Minor
|
||||
| Electron non-breaking API change | Minor
|
||||
| Electron bug fix | Patch
|
||||
|
||||
When you install an npm module with the `--save` or `--save-dev` flags, it
|
||||
will be prefixed with a caret `^` in package.json:
|
||||
|
||||
```json
|
||||
{
|
||||
"devDependencies": {
|
||||
"electron": "^2.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `--save-exact` flag will add `electron` to your `package.json` file without
|
||||
using a `^` or `~`, e.g. `1.6.2` instead of `^1.6.2`. This practice ensures that
|
||||
all upgrades of Electron are a manual operation made by you, the developer.
|
||||
The [caret semver range](https://docs.npmjs.com/misc/semver#caret-ranges-123-025-004)
|
||||
allows minor- and patch-level changes to be installed, i.e. non-breaking
|
||||
features and bug fixes.
|
||||
|
||||
Alternatively, you can use the `~` prefix in your SemVer range, like `~1.6.2`.
|
||||
This will lock your major and minor version, but allow new patch versions to
|
||||
be installed.
|
||||
Alternatively, a more conservative approach is to use the
|
||||
[tilde semver range](https://docs.npmjs.com/misc/semver#tilde-ranges-123-12-1)
|
||||
`~`, which will only allow patch-level upgrades, i.e. bug fixes.
|
||||
|
||||
|
||||
### The Release Schedule
|
||||
|
||||
**Note: The schedule outlined here is _aspirational_. We are not yet cutting
|
||||
releases at a weekly cadence, but we hope to get there eventually.**
|
||||
|
||||
<img style="width:100%;margin:20px 0;" src="../images/tutorial-release-schedule.svg">
|
||||
|
||||
Here are some important points to call out:
|
||||
|
||||
- A new release is performed approximately weekly.
|
||||
- Minor versions are branched off of master for stabilization.
|
||||
- The stabilization period is approximately weekly.
|
||||
- Important bug fixes are cherry-picked to stabilization branches after landing
|
||||
in master.
|
||||
- Features are not cherry picked; a minor version should only get *more stable*
|
||||
with its patch versions.
|
||||
- There is little difference in the release schedule between a major and minor
|
||||
release, other than the risk/effort it may take for third parties to adopt
|
||||
- Chromium updates will be performed as fast as the team can manage. In an ideal
|
||||
world this would happen every 6 weeks to align with
|
||||
[Chromium's release schedule][Chromium release].
|
||||
- Excluding exceptional circumstances, only the previous stable build will
|
||||
get backported bug fixes.
|
||||
|
||||
### The Beta Process
|
||||
|
||||
Electron relies on its consumers getting involved in stabilization. The short
|
||||
target stabilization period and rapid release cadence was designed for shipping
|
||||
security and bug fixes out fast and to encourage the automation of testing.
|
||||
|
||||
You can install the beta by specifying the `beta` dist tag when installing via
|
||||
npm:
|
||||
|
||||
```
|
||||
npm install electron@beta
|
||||
```
|
||||
|
||||
[Semantic Versioning]: http://semver.org
|
||||
[pre-release identifier]: http://semver.org/#spec-item-9
|
||||
[npm dist tag]: https://docs.npmjs.com/cli/dist-tag
|
||||
[normal version]: http://semver.org/#spec-item-2
|
||||
[Chromium release]: https://www.chromium.org/developers/calendar
|
||||
@@ -7,12 +7,11 @@ The preferred method is to install Electron as a development dependency in your
|
||||
app:
|
||||
|
||||
```sh
|
||||
npm install electron --save-dev --save-exact
|
||||
npm install electron --save-dev
|
||||
```
|
||||
|
||||
The `--save-exact` flag is recommended as Electron does not follow semantic
|
||||
versioning. See the
|
||||
[versioning doc](https://electron.atom.io/docs/tutorial/electron-versioning/)
|
||||
See the
|
||||
[Electron versioning doc](https://electron.atom.io/docs/tutorial/electron-versioning/)
|
||||
for info on how to manage Electron versions in your apps.
|
||||
|
||||
## Global Installation
|
||||
|
||||
@@ -85,3 +85,5 @@ Notifications are sent using `libnotify` which can show notifications on any
|
||||
desktop environment that follows [Desktop Notifications
|
||||
Specification][notification-spec], including Cinnamon, Enlightenment, Unity,
|
||||
GNOME, KDE.
|
||||
|
||||
[notification-spec]: https://developer.gnome.org/notification-spec/
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
# Online/Offline Event Detection
|
||||
|
||||
Online and offline event detection can be implemented in the renderer process
|
||||
using standard HTML5 APIs, as shown in the following example.
|
||||
[Online and offline event](https://developer.mozilla.org/en-US/docs/Online_and_offline_events) detection can be implemented in the renderer process using the [`navigator.onLine`](http://html5index.org/Offline%20-%20NavigatorOnLine.html) attribute, part of standard HTML5 API.
|
||||
The `navigator.onLine` attribute returns `false` if any network requests are guaranteed to fail i.e. definitely offline (disconnected from the network). It returns `true` in all other cases.
|
||||
Since all other conditions return `true`, one has to be mindful of getting false positives, as we cannot assume `true` value necessarily means that Electron can access the internet. Such as in cases where the computer is running a virtualization software that has virtual ethernet adapters that are always “connected.”
|
||||
Therefore, if you really want to determine the internet access status of Electron,
|
||||
you should develop additional means for checking.
|
||||
|
||||
Example:
|
||||
|
||||
_main.js_
|
||||
|
||||
@@ -78,13 +83,3 @@ _online-status.html_
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
**NOTE:** If Electron is not able to connect to a local area network (LAN) or
|
||||
a router, it is considered offline; all other conditions return `true`.
|
||||
So while you can assume that Electron is offline when `navigator.onLine`
|
||||
returns a `false` value, you cannot assume that a `true` value necessarily
|
||||
means that Electron can access the internet. You could be getting false
|
||||
positives, such as in cases where the computer is running a virtualization
|
||||
software that has virtual ethernet adapters that are always "connected."
|
||||
Therefore, if you really want to determine the internet access status of Electron,
|
||||
you should develop additional means for checking.
|
||||
|
||||
@@ -187,6 +187,12 @@ $ ./node_modules/.bin/electron .
|
||||
$ .\node_modules\.bin\electron .
|
||||
```
|
||||
|
||||
#### Node v8.2.0 and later
|
||||
|
||||
```
|
||||
$ npx electron .
|
||||
```
|
||||
|
||||
### Manually Downloaded Electron Binary
|
||||
|
||||
If you downloaded Electron manually, you can also use the included
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
'product_name%': 'Electron',
|
||||
'company_name%': 'GitHub, Inc',
|
||||
'company_abbr%': 'github',
|
||||
'version%': '1.8.1',
|
||||
'version%': '1.8.2-beta.1',
|
||||
'js2c_input_dir': '<(SHARED_INTERMEDIATE_DIR)/js2c',
|
||||
},
|
||||
'includes': [
|
||||
|
||||
@@ -129,6 +129,17 @@ if (nodeIntegration === 'true') {
|
||||
}
|
||||
}
|
||||
|
||||
if (window.location.protocol === 'https:' ||
|
||||
window.location.protocol === 'http:' ||
|
||||
window.location.protocol === 'ftp:') {
|
||||
let warning = 'This renderer process has Node.js integration enabled '
|
||||
warning += 'and attempted to load remote content. This exposes users of this app to severe '
|
||||
warning += 'security risks.\n'
|
||||
warning += 'For more information and help, consult https://electron.atom.io/docs/tutorial/security/'
|
||||
|
||||
console.warn('%cElectron Security Warning', 'font-weight: bold;', warning)
|
||||
}
|
||||
|
||||
// Redirect window.onerror to uncaughtException.
|
||||
window.onerror = function (message, filename, lineno, colno, error) {
|
||||
if (global.process.listeners('uncaughtException').length > 0) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// maintainer note - x.y.z-ab version in package.json -> x.y.z
|
||||
var version = require('./package').version.replace(/-.*/, '')
|
||||
var version = require('./package').version
|
||||
|
||||
var fs = require('fs')
|
||||
var os = require('os')
|
||||
@@ -30,7 +29,7 @@ download({
|
||||
arch: process.env.npm_config_arch,
|
||||
strictSSL: process.env.npm_config_strict_ssl === 'true',
|
||||
force: process.env.force_no_cache === 'true',
|
||||
quiet: ['info', 'verbose', 'silly', 'http'].indexOf(process.env.npm_config_loglevel) === -1
|
||||
quiet: process.env.npm_config_loglevel === 'silent' || process.env.CI
|
||||
}, extractFile)
|
||||
|
||||
// unzips and makes path.txt point at the correct executable
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "1.8.1",
|
||||
"version": "1.8.2-beta.1",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import argparse
|
||||
|
||||
from lib.util import execute, get_electron_version, parse_version, scoped_cwd
|
||||
|
||||
@@ -11,28 +12,83 @@ SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2 or sys.argv[1] == '-h':
|
||||
print 'Usage: bump-version.py [<version> | major | minor | patch]'
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Bump version numbers. Must specify at least one of the three'
|
||||
+' options:\n'
|
||||
+' --bump=patch to increment patch version, or\n'
|
||||
+' --stable to promote current beta to stable, or\n'
|
||||
+' --version={version} to set version number directly\n'
|
||||
+'Note that you can use both --bump and --stable '
|
||||
+'simultaneously.',
|
||||
formatter_class=argparse.RawTextHelpFormatter
|
||||
)
|
||||
parser.add_argument(
|
||||
'--version',
|
||||
default=None,
|
||||
dest='new_version',
|
||||
help='new version number'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--bump',
|
||||
action='store',
|
||||
default=None,
|
||||
dest='bump',
|
||||
help='increment [major | minor | patch | beta]'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--stable',
|
||||
action='store_true',
|
||||
default= False,
|
||||
dest='stable',
|
||||
help='promote to stable (i.e. remove `-beta.x` suffix)'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--dry-run',
|
||||
action='store_true',
|
||||
default= False,
|
||||
dest='dry_run',
|
||||
help='just to check that version number is correct'
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.new_version == None and args.bump == None and args.stable == False:
|
||||
parser.print_help()
|
||||
return 1
|
||||
|
||||
option = sys.argv[1]
|
||||
increments = ['major', 'minor', 'patch', 'build']
|
||||
if option in increments:
|
||||
version = get_electron_version()
|
||||
versions = parse_version(version.split('-')[0])
|
||||
versions = increase_version(versions, increments.index(option))
|
||||
else:
|
||||
versions = parse_version(option)
|
||||
increments = ['major', 'minor', 'patch', 'beta']
|
||||
|
||||
curr_version = get_electron_version()
|
||||
versions = parse_version(re.sub('-beta', '', curr_version))
|
||||
|
||||
if args.bump in increments:
|
||||
versions = increase_version(versions, increments.index(args.bump))
|
||||
if versions[3] == '0':
|
||||
# beta starts at 1
|
||||
versions = increase_version(versions, increments.index('beta'))
|
||||
|
||||
if args.stable == True:
|
||||
versions[3] = '0'
|
||||
|
||||
if args.new_version != None:
|
||||
versions = parse_version(re.sub('-beta', '', args.new_version))
|
||||
|
||||
version = '.'.join(versions[:3])
|
||||
suffix = '' if versions[3] == '0' else '-beta.' + versions[3]
|
||||
|
||||
if args.dry_run:
|
||||
print 'new version number would be: {0}\n'.format(version + suffix)
|
||||
return 0
|
||||
|
||||
|
||||
with scoped_cwd(SOURCE_ROOT):
|
||||
update_electron_gyp(version)
|
||||
update_electron_gyp(version, suffix)
|
||||
update_win_rc(version, versions)
|
||||
update_version_h(versions)
|
||||
update_info_plist(version)
|
||||
update_package_json(version)
|
||||
tag_version(version)
|
||||
update_package_json(version, suffix)
|
||||
tag_version(version, suffix)
|
||||
|
||||
|
||||
def increase_version(versions, index):
|
||||
@@ -42,14 +98,14 @@ def increase_version(versions, index):
|
||||
return versions
|
||||
|
||||
|
||||
def update_electron_gyp(version):
|
||||
pattern = re.compile(" *'version%' *: *'[0-9.]+'")
|
||||
def update_electron_gyp(version, suffix):
|
||||
pattern = re.compile(" *'version%' *: *'[0-9.]+(-beta[0-9.]*)?'")
|
||||
with open('electron.gyp', 'r') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
for i in range(0, len(lines)):
|
||||
if pattern.match(lines[i]):
|
||||
lines[i] = " 'version%': '{0}',\n".format(version)
|
||||
lines[i] = " 'version%': '{0}',\n".format(version + suffix)
|
||||
with open('electron.gyp', 'w') as f:
|
||||
f.write(''.join(lines))
|
||||
return
|
||||
@@ -114,7 +170,7 @@ def update_info_plist(version):
|
||||
f.write(''.join(lines))
|
||||
|
||||
|
||||
def update_package_json(version):
|
||||
def update_package_json(version, suffix):
|
||||
package_json = 'package.json'
|
||||
with open(package_json, 'r') as f:
|
||||
lines = f.readlines()
|
||||
@@ -122,15 +178,15 @@ def update_package_json(version):
|
||||
for i in range(0, len(lines)):
|
||||
line = lines[i];
|
||||
if 'version' in line:
|
||||
lines[i] = ' "version": "{0}",\n'.format(version)
|
||||
lines[i] = ' "version": "{0}",\n'.format(version + suffix)
|
||||
break
|
||||
|
||||
with open(package_json, 'w') as f:
|
||||
f.write(''.join(lines))
|
||||
|
||||
|
||||
def tag_version(version):
|
||||
execute(['git', 'commit', '-a', '-m', 'Bump v{0}'.format(version)])
|
||||
def tag_version(version, suffix):
|
||||
execute(['git', 'commit', '-a', '-m', 'Bump v{0}'.format(version + suffix)])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
10
script/cpplint.py
vendored
10
script/cpplint.py
vendored
@@ -38,6 +38,10 @@ SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
|
||||
|
||||
|
||||
def main():
|
||||
if not os.path.isfile(cpplint_path()):
|
||||
print("[INFO] Skipping cpplint, dependencies has not been bootstrapped")
|
||||
return
|
||||
|
||||
os.chdir(SOURCE_ROOT)
|
||||
atom_files = list_files('atom',
|
||||
['app', 'browser', 'common', 'renderer', 'utility'],
|
||||
@@ -60,9 +64,13 @@ def list_files(parent, directories, filters):
|
||||
|
||||
|
||||
def call_cpplint(files):
|
||||
cpplint = os.path.join(SOURCE_ROOT, 'vendor', 'depot_tools', 'cpplint.py')
|
||||
cpplint = cpplint_path()
|
||||
execute([sys.executable, cpplint] + files)
|
||||
|
||||
|
||||
def cpplint_path():
|
||||
return os.path.join(SOURCE_ROOT, 'vendor', 'depot_tools', 'cpplint.py')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
||||
@@ -24,7 +24,6 @@ github.repos.getReleases({owner: 'electron', repo: 'electron'})
|
||||
const draft = drafts[0]
|
||||
|
||||
check(draft.tag_name === `v${pkg.version}`, `draft release version matches local package.json (v${pkg.version})`)
|
||||
check(draft.prerelease, 'draft is a prerelease')
|
||||
check(draft.body.length > 50 && !draft.body.includes('(placeholder)'), 'draft has release notes')
|
||||
|
||||
const requiredAssets = assetsForVersion(draft.tag_name).sort()
|
||||
|
||||
@@ -2,6 +2,10 @@ const GitHub = require('github')
|
||||
const github = new GitHub()
|
||||
github.authenticate({type: 'token', token: process.env.ELECTRON_GITHUB_TOKEN})
|
||||
|
||||
if (process.argv.length < 5) {
|
||||
console.log('Usage: upload-to-github filePath fileName releaseId')
|
||||
process.exit(1)
|
||||
}
|
||||
let filePath = process.argv[2]
|
||||
let fileName = process.argv[3]
|
||||
let releaseId = process.argv[4]
|
||||
@@ -13,9 +17,35 @@ let githubOpts = {
|
||||
filePath: filePath,
|
||||
name: fileName
|
||||
}
|
||||
github.repos.uploadAsset(githubOpts).then(() => {
|
||||
process.exit()
|
||||
}).catch((err) => {
|
||||
console.log(`Error uploading ${fileName} to GitHub:`, err)
|
||||
process.exitCode = 1
|
||||
})
|
||||
|
||||
let retry = 0
|
||||
|
||||
function uploadToGitHub () {
|
||||
github.repos.uploadAsset(githubOpts).then(() => {
|
||||
console.log(`Successfully uploaded ${fileName} to GitHub.`)
|
||||
process.exit()
|
||||
}).catch((err) => {
|
||||
if (retry < 4) {
|
||||
console.log(`Error uploading ${fileName} to GitHub, will retry. Error was:`, err)
|
||||
retry++
|
||||
github.repos.getAssets(githubOpts).then(assets => {
|
||||
let existingAssets = assets.data.filter(asset => asset.name === fileName)
|
||||
if (existingAssets.length > 0) {
|
||||
console.log(`${fileName} already exists; will delete before retrying upload.`)
|
||||
github.repos.deleteAsset({
|
||||
owner: 'electron',
|
||||
repo: 'electron',
|
||||
id: existingAssets[0].id
|
||||
}).then(uploadToGitHub).catch(uploadToGitHub)
|
||||
} else {
|
||||
uploadToGitHub()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
console.log(`Error retrying uploading ${fileName} to GitHub:`, err)
|
||||
process.exitCode = 1
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
uploadToGitHub()
|
||||
|
||||
@@ -709,6 +709,19 @@ describe('BrowserWindow module', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('BrowserWindow.addTabbedWindow()', function (done) {
|
||||
it('does not throw', function () {
|
||||
if (process.platform !== 'darwin') {
|
||||
return
|
||||
}
|
||||
const tabbedWindow = new BrowserWindow({})
|
||||
assert.doesNotThrow(() => {
|
||||
w.addTabbedWindow(tabbedWindow)
|
||||
})
|
||||
closeWindow(tabbedWindow).then(done)
|
||||
})
|
||||
})
|
||||
|
||||
describe('BrowserWindow.setVibrancy(type)', function () {
|
||||
it('allows setting, changing, and removing the vibrancy', function () {
|
||||
assert.doesNotThrow(function () {
|
||||
@@ -795,6 +808,30 @@ describe('BrowserWindow module', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('BrowserWindow.setOpacity(opacity)', function () {
|
||||
it('make window with initial opacity', function () {
|
||||
w.destroy()
|
||||
w = new BrowserWindow({
|
||||
show: false,
|
||||
width: 400,
|
||||
height: 400,
|
||||
opacity: 0.5
|
||||
})
|
||||
assert.equal(w.getOpacity(), 0.5)
|
||||
})
|
||||
|
||||
it('allows setting the opacity', function () {
|
||||
assert.doesNotThrow(function () {
|
||||
w.setOpacity(0.0)
|
||||
assert.equal(w.getOpacity(), 0.0)
|
||||
w.setOpacity(0.5)
|
||||
assert.equal(w.getOpacity(), 0.5)
|
||||
w.setOpacity(1.0)
|
||||
assert.equal(w.getOpacity(), 1.0)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('"useContentSize" option', function () {
|
||||
it('make window created with content size when used', function () {
|
||||
w.destroy()
|
||||
|
||||
@@ -190,6 +190,34 @@ describe('nativeImage module', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('createFromNamedImage(name)', () => {
|
||||
it('returns empty for invalid options', () => {
|
||||
const image = nativeImage.createFromNamedImage('totally_not_real')
|
||||
assert(image.isEmpty())
|
||||
})
|
||||
|
||||
it('returns empty on non-darwin platforms', () => {
|
||||
if (process.platform === 'darwin') return
|
||||
|
||||
const image = nativeImage.createFromNamedImage('NSActionTemplate')
|
||||
assert(image.isEmpty())
|
||||
})
|
||||
|
||||
it('returns a valid image on darwin', () => {
|
||||
if (process.platform !== 'darwin') return
|
||||
|
||||
const image = nativeImage.createFromNamedImage('NSActionTemplate')
|
||||
assert(!image.isEmpty())
|
||||
})
|
||||
|
||||
it('returns allows an HSL shift for a valid image on darwin', () => {
|
||||
if (process.platform !== 'darwin') return
|
||||
|
||||
const image = nativeImage.createFromNamedImage('NSActionTemplate', [0.5, 0.2, 0.8])
|
||||
assert(!image.isEmpty())
|
||||
})
|
||||
})
|
||||
|
||||
describe('resize(options)', () => {
|
||||
it('returns a resized image', () => {
|
||||
const image = nativeImage.createFromPath(path.join(__dirname, 'fixtures', 'assets', 'logo.png'))
|
||||
|
||||
@@ -572,8 +572,9 @@ describe('session module', function () {
|
||||
})
|
||||
|
||||
it('accepts the request when the callback is called with 0', function (done) {
|
||||
session.defaultSession.setCertificateVerifyProc(function ({hostname, certificate, verificationResult}, callback) {
|
||||
session.defaultSession.setCertificateVerifyProc(function ({hostname, certificate, verificationResult, errorCode}, callback) {
|
||||
assert(['net::ERR_CERT_AUTHORITY_INVALID', 'net::ERR_CERT_COMMON_NAME_INVALID'].includes(verificationResult), verificationResult)
|
||||
assert([-202, -200].includes(errorCode), errorCode)
|
||||
callback(0)
|
||||
})
|
||||
|
||||
|
||||
@@ -100,6 +100,23 @@ describe('systemPreferences module', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('systemPreferences.setUserDefault(key, type, value)', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
return
|
||||
}
|
||||
|
||||
it('removes keys', () => {
|
||||
const KEY = 'SystemPreferencesTest'
|
||||
systemPreferences.setUserDefault(KEY, 'string', 'foo')
|
||||
systemPreferences.removeUserDefault(KEY)
|
||||
assert.equal(systemPreferences.getUserDefault(KEY, 'string'), '')
|
||||
})
|
||||
|
||||
it('does not throw for missing keys', () => {
|
||||
systemPreferences.removeUserDefault('some-missing-key')
|
||||
})
|
||||
})
|
||||
|
||||
describe('systemPreferences.isInvertedColorScheme()', function () {
|
||||
it('returns a boolean', function () {
|
||||
assert.equal(typeof systemPreferences.isInvertedColorScheme(), 'boolean')
|
||||
|
||||
@@ -117,7 +117,7 @@ def GetSharedLibraryDependenciesLinux(binary):
|
||||
for line in ldd.splitlines():
|
||||
m = lib_re.match(line)
|
||||
if m:
|
||||
result.append(m.group(1))
|
||||
result.append(os.path.realpath(m.group(1)))
|
||||
return result
|
||||
|
||||
|
||||
|
||||
2
vendor/libchromiumcontent
vendored
2
vendor/libchromiumcontent
vendored
Submodule vendor/libchromiumcontent updated: f9506cc6fb...01de61a555
Reference in New Issue
Block a user