Compare commits

..

211 Commits

Author SHA1 Message Date
Cheng Zhao
40066ca343 Bump v0.36.12 2016-03-27 10:40:57 +09:00
Cheng Zhao
6671e78f5d Run callback of setDestructor immediately when GC happens
Fix #4733.
2016-03-27 10:40:44 +09:00
Cheng Zhao
0480e32f99 Update brightray: fix crash when using notification on Windows 2016-03-27 10:40:03 +09:00
Cheng Zhao
ead94b7b1f Bump v0.36.11 2016-03-11 20:09:19 +09:00
Plusb Preco
288ef13fb5 📝 Update Korean docs as upstream
[ci skip]

📝 Update Korean docs as upstream

[ci skip]
2016-03-11 19:37:03 +09:00
Cheng Zhao
4765445b4f Merge pull request #4752 from yucheng-inc/master
translations   zh-CN    doc
2016-03-11 19:36:41 +09:00
Cheng Zhao
03ec5ced05 Merge pull request #4751 from maxbeatty/window-blur
Add blur method to window
2016-03-11 19:15:51 +09:00
scycbx
e2e18200fb Merge pull request #5 from heyunjiang/master
update && add
2016-03-11 15:45:26 +08:00
heyunjiang
328583575d modify again and add dialog.md 2016-03-11 15:09:08 +08:00
Max Beatty
704b8335aa Add blur method to window ref #4724 2016-03-10 21:45:51 -08:00
heyunjiang
d25d1f3f8b add content-tracing && update browser-window 2016-03-11 11:53:04 +08:00
Cheng Zhao
abd466ee4a Merge pull request #4700 from ArekSredzki/async-document-hidden
Cache browser visibility state & emit visibilitychange event on change
2016-03-11 10:19:06 +09:00
Arek Sredzki
fcc1f4d7ed Finalized browser-window show & hide events, added tests & fixed os x implementation 2016-03-10 13:51:31 -08:00
Arek Sredzki
c1267b2320 Added 'show' & 'hide' events to browser-window, fixed visibilitychange event in renderer 2016-03-10 13:51:31 -08:00
Arek Sredzki
ee61ab2d26 Cache browser visibility state & emit visibilitychange event on change
Fixes #3788
2016-03-10 13:51:31 -08:00
heyunjiang
0ec7f35c24 finish browser-window first 2016-03-10 23:12:57 +08:00
Cheng Zhao
377a8eefb2 Merge pull request #4722 from atom/colocate-js
[WIP] Colocate JavaScript in root lib folder
2016-03-10 17:05:34 +09:00
Cheng Zhao
1ee4caae2d Merge pull request #4736 from preco21/patch-7
Docs: Adjust 80 chars per line
2016-03-10 16:55:10 +09:00
Plusb Preco
ebf509bbe4 📝 Adjust 80 chars per line
[ci skip]
2016-03-10 16:54:07 +09:00
Plusb Preco
4c45c80fb4 📝 Update as upstream 2016-03-10 16:36:50 +09:00
Cheng Zhao
b40a0e6e0c Merge pull request #4725 from phamdaniel/doc-app-focus
Document 'app.focus()'
2016-03-10 16:29:33 +09:00
heyunjiang
51f60d8d73 add window.open 2016-03-09 23:23:22 +08:00
Daniel Pham
0b8c2545b9 📝 Document 'app.focus()'
[ci skip]
2016-03-09 09:03:38 -05:00
Cheng Zhao
5efb88e7ea Merge pull request #4723 from yucheng-inc/master
translations   zh-CN    doc
2016-03-09 21:45:40 +09:00
heyunjiang
937668097a web-view-tag first finish 2016-03-09 17:00:01 +08:00
wujingke
da0a1eac24 Merge pull request #3 from heyunjiang/master
api doc 4th
2016-03-09 09:35:24 +08:00
Kevin Sawicki
c3b058cea3 Update path to ipc.js 2016-03-08 11:22:58 -08:00
Kevin Sawicki
2e9fd7ce77 Update common api path 2016-03-08 11:22:13 -08:00
Kevin Sawicki
4c9f5b71f7 Run eslint over lib folder 2016-03-08 11:14:22 -08:00
Kevin Sawicki
418efbe660 Remove unneeded resolve calls 2016-03-08 11:14:22 -08:00
Kevin Sawicki
006c77a00f Update requires paths 2016-03-08 11:14:22 -08:00
Kevin Sawicki
f109591d03 Look for JS in lib dir 2016-03-08 11:14:21 -08:00
Kevin Sawicki
c47ad29124 Move default_app to root of repo 2016-03-08 11:14:21 -08:00
Kevin Sawicki
6e3cb9e8eb Update paths for new JS location 2016-03-08 11:14:21 -08:00
Kevin Sawicki
70aa9b06ee Move JavaScript to root lib/ folder 2016-03-08 11:14:21 -08:00
heyunjiang
c8a2246952 complete command line switch && add enviroment variables 2016-03-08 20:40:54 +08:00
heyunjiang
d35996b4a0 position modify 2016-03-08 19:57:53 +08:00
Cheng Zhao
a9c40de393 Merge pull request #4680 from atom/resizable-linux
Respect initial resizable window option on Linux
2016-03-08 19:46:40 +09:00
Cheng Zhao
549cccfce4 Merge pull request #4715 from dongjoon-hyun/fix_typos_in_comments
Fix typos in comments.
2016-03-08 19:45:05 +09:00
Cheng Zhao
1da75f5c18 Merge pull request #4712 from atom/mq-map-selectors-to-roles
Map missing selectors to roles
2016-03-08 19:44:26 +09:00
Cheng Zhao
68c413c391 Merge pull request #4674 from atom/normalize-native-image-paths
Normalize native image paths
2016-03-08 18:59:56 +09:00
wujingke
83111ad84c Merge pull request #2 from heyunjiang/master
add api doc begin 2.5
2016-03-08 16:36:32 +08:00
heyunjiang
89328c873c add api doc begin 2.5 2016-03-08 16:30:09 +08:00
Dongjoon Hyun
0c92d44077 Fix typos in comments. 2016-03-07 20:22:03 -08:00
wujingke
6f221cb6b1 Merge pull request #1 from heyunjiang/master
menuItem add
2016-03-08 11:01:55 +08:00
heyunjiang
11f64b714d menuItem add 2016-03-08 10:47:23 +08:00
Kevin Sawicki
4c23e3950a Add missing semicolon 2016-03-07 16:45:15 -08:00
Kevin Sawicki
44376374b0 path -> paths 2016-03-07 16:45:14 -08:00
Kevin Sawicki
022c2c0d8c absolute_path -> normalize_path 2016-03-07 16:45:14 -08:00
Kevin Sawicki
0dba0b9cad MakePathAbsolute -> NormalizePath 2016-03-07 16:45:14 -08:00
Kevin Sawicki
97930fcd84 Add specs for more image path cases 2016-03-07 16:45:14 -08:00
Kevin Sawicki
9c88a5c1ab Check ReferencesParent before calling MakeAbsoluteFilePath 2016-03-07 16:45:14 -08:00
Kevin Sawicki
7692edf50e Assert image size as well 2016-03-07 16:45:14 -08:00
Kevin Sawicki
8215d661ca Add api- prefix to spec 2016-03-07 16:45:14 -08:00
Kevin Sawicki
8f820e09be Use template string and arrow functions 2016-03-07 16:45:14 -08:00
Kevin Sawicki
145d5abe80 Mention explicit using original path on failures 2016-03-07 16:45:14 -08:00
Kevin Sawicki
b90c0c7895 Use MakeAbsoluteFilePath when creating native image from path 2016-03-07 16:45:13 -08:00
Kevin Sawicki
dda7740399 Add failing spec for native image path normalization 2016-03-07 16:45:13 -08:00
Kevin Sawicki
3f4455a79d Merge pull request #4713 from atom/mq-doc-actions
Link to OS X Cocoa Event Handling guide on actions
2016-03-07 16:40:23 -08:00
Machisté N. Quintana
f47851f1e7 📝 🎨 Hard wrap 2016-03-07 16:19:00 -08:00
Machisté N. Quintana
eb064240f8 📝 Link to OS X Cocoa Event Handling guide on actions 2016-03-07 16:11:58 -08:00
Kevin Sawicki
7b881ebc23 Merge pull request #4711 from atom/realpath-asar-unpacked-specs
Add specs for realpath of unpacked asar path
2016-03-07 16:10:50 -08:00
Machisté N. Quintana
2bfc7aa152 Add mapping for performZoom 2016-03-07 16:01:46 -08:00
Machisté N. Quintana
eae5cc9d2c 🎨 [ci skip] 2016-03-07 15:53:09 -08:00
Machisté N. Quintana
03434f45bb Map webContents.delete to role 2016-03-07 15:50:33 -08:00
Machisté N. Quintana
4ded709307 Map selectors for delete and pasteAndMatchStyle to roles 2016-03-07 15:42:32 -08:00
Kevin Sawicki
4b6639c9fd Add missing done param 2016-03-07 15:30:33 -08:00
Kevin Sawicki
4b65610d40 Add specs for realpath of unpacked asar path 2016-03-07 15:27:21 -08:00
Kevin Sawicki
755c1f5238 Merge pull request #4706 from atom/update-styleguide
Remove CoffeeScript from styleguide
2016-03-07 13:59:07 -08:00
Kevin Sawicki
04c8bc38b2 Tweak lint sentence 2016-03-07 13:58:49 -08:00
Kevin Sawicki
ad3f4a26fd Restore setting resizable property from ctor on Windows 2016-03-07 13:53:57 -08:00
Kevin Sawicki
7de37859f0 Set resizable on Linux from InitWithOptions 2016-03-07 13:48:33 -08:00
Kevin Sawicki
993b878925 🎨 2016-03-07 10:37:01 -08:00
Kevin Sawicki
38acc7090b Contrain size in ctor on non-resizable windows 2016-03-07 10:11:30 -08:00
Kevin Sawicki
4ec79d5d18 Add Linux exclusion to describe 2016-03-07 09:53:20 -08:00
Kevin Sawicki
1c68aae43e Mention npm run lint 2016-03-07 09:46:05 -08:00
Kevin Sawicki
686af28f54 Mention indent and semicolons 2016-03-07 09:45:13 -08:00
Kevin Sawicki
6725523042 Remove CoffeeScript from styleguide 2016-03-07 09:43:04 -08:00
Cheng Zhao
aa8dbbf6b6 Merge pull request #4695 from dongjoon-hyun/fix_link_name
Fix link name.
2016-03-07 10:31:49 +09:00
Cheng Zhao
0e2ac2d802 Merge pull request #4646 from phamdaniel/dark-mode
Add API to check OSX's Dark theme
2016-03-07 09:53:03 +09:00
Daniel Pham
68b453770b 🍎 Rename 'isDarkModeEnabled' to 'isDarkMode' 2016-03-06 10:55:47 -05:00
Cheng Zhao
2a0be28111 Merge pull request #4682 from phamdaniel/ismaximized
Fix `isMaximized()` in window for when resizable is set to false on OSX
2016-03-06 19:23:46 +09:00
Dongjoon Hyun
f9f20957a4 Fix link name. 2016-03-05 23:28:39 -08:00
Cheng Zhao
d93ccd47a8 Merge pull request #4670 from atom/cmd-backtick-order
Use sendAction for cycling windows
2016-03-06 16:17:38 +09:00
Cheng Zhao
e152b8850c Merge pull request #4665 from christoth/christoth-webview-flexbox
Use flexbox layout for browserplugin
2016-03-06 15:36:20 +09:00
Cheng Zhao
5bb2c2c5c9 Merge pull request #4666 from SLiNv/zh-CN-documentation
Add Pepper Flash doc and match doc style
2016-03-06 15:36:05 +09:00
Cheng Zhao
816b10d8f3 Merge pull request #4694 from atom/common-accelerator
Remove duplicated keyboard code
2016-03-06 15:31:59 +09:00
Cheng Zhao
b7a40f3097 docs: Add missing key codes 2016-03-06 15:12:04 +09:00
Cheng Zhao
2515425cd5 Remove duplicated keyboard code 2016-03-06 15:04:05 +09:00
Cheng Zhao
a0c39c64cc Merge pull request #4686 from atom/fullscreen-logic
Improve fullscreen related logic code
2016-03-05 22:20:43 +09:00
Cheng Zhao
114801d412 Remove the duplicate logic on OS X 2016-03-05 21:54:41 +09:00
Cheng Zhao
2be368bded SetFullScreen should not work at all when not fullscreenable
This follows the logic of OS X.
2016-03-05 21:38:06 +09:00
Cheng Zhao
f5d79677fa Merge branch 'will-fullscreen' of https://github.com/MaxWhere/electron 2016-03-05 21:30:41 +09:00
Cheng Zhao
5f95fea3e2 docs: OS X also has progress bar 2016-03-05 21:20:02 +09:00
Cheng Zhao
c0b87c1a62 Merge pull request #4656 from princejwesley/menu-item-click
Add platform predicate for menu item action
2016-03-05 21:13:59 +09:00
Cheng Zhao
054c55a9bb Merge pull request #4683 from atom/fix-select-certificate
Fix passing certificate to select-client-certificate's callback
2016-03-05 19:47:27 +09:00
Cheng Zhao
23b92ef9ec Fix passing certificate to select-client-certificate's callback 2016-03-05 18:57:46 +09:00
Daniel Pham
d5f5cdb45a :apple:Fix 'isMaximized()' for non resizable windows 2016-03-05 01:39:48 -05:00
Cheng Zhao
33978455b8 Bump v0.36.10 2016-03-05 12:00:06 +09:00
Cheng Zhao
2bd167663d Merge pull request #4678 from atom/writable-member-functions
Make remote member functions writable/configurable
2016-03-05 11:56:56 +09:00
Kevin Sawicki
bda5bb4a74 Add missing semicolon 2016-03-04 16:15:04 -08:00
Kevin Sawicki
67edcc8f91 Initially set resizable property on Linux 2016-03-04 16:12:58 -08:00
Kevin Sawicki
73f6162f5c Enable resizable spec on Linux 2016-03-04 16:12:14 -08:00
Kevin Sawicki
fe9e026f9e getObjectMemebers -> getObjectMembers 2016-03-04 15:57:21 -08:00
Kevin Sawicki
3230927f10 Mention deleting 2016-03-04 15:56:18 -08:00
Kevin Sawicki
f460d81dd0 Allow remote member functions to be deleted 2016-03-04 15:51:17 -08:00
Kevin Sawicki
610a503188 Make member functions writable 2016-03-04 15:49:46 -08:00
Kevin Sawicki
a9e22801e9 Add failing spec for reassigning remote function 2016-03-04 15:44:50 -08:00
Kevin Sawicki
ee1f69062e Merge pull request #4675 from atom/report-error-in-enumerate-devices-spec
Always call done callback in enumerateDevices spec
2016-03-04 14:42:21 -08:00
Kevin Sawicki
20e9a87158 Don't run mediaDevices spec on Linux CI 2016-03-04 13:23:12 -08:00
Kevin Sawicki
a4e04e6083 Always call done callback 2016-03-04 12:29:50 -08:00
Daniel Pham
63294892f0 Rename dark-mode-changed to platform-theme-changed 2016-03-03 23:58:58 -05:00
Kevin Sawicki
be67dca686 Use _cycleWindows selector to implement cmd-` 2016-03-03 20:53:58 -08:00
Daniel Pham
b1eefbdcd9 Simplify the isDarkModeEnabled check 2016-03-03 23:48:30 -05:00
christoth
fed77d1837 Use flexbox layout for browserplugin 2016-03-03 17:22:20 -05:00
Victor Zhu
b46fc8bc4c Add Pepper Flash doc and match doc style
- Add Pepper Flash plugin documentation
- Use and  match the same documentaion style for other CN docs.
- Fix some typos and grammar.
2016-03-03 15:42:14 -05:00
Cheng Zhao
b4c48664f8 Merge pull request #4635 from akameco/master
Fix JP docs tranlation
2016-03-03 21:00:46 +09:00
Plusb Preco
b6958e5221 Update as upstream
[ci skip]
2016-03-03 20:56:46 +09:00
Prince J Wesley
f02affbc18 🐛 Add platform predicate for menu item action 2016-03-03 08:38:32 +05:30
Cheng Zhao
46c6233b62 Merge pull request #4630 from preco21/patch-6
Docs: Cleanup docs
2016-03-03 11:37:48 +09:00
Cheng Zhao
d6144d63fb Merge pull request #4629 from RacioN/master
Update docs-translations/jp/README.md tranlation.
2016-03-03 11:32:40 +09:00
Daniel Pham
c4049cb393 🍎 Add 'dark-mode-changed' event to app api 2016-03-01 15:43:38 -05:00
Daniel Pham
eaac67ac60 🍎 Add 'isDarkModeEnabled' to app api 2016-03-01 13:12:21 -05:00
akameco
9c7bb0b370 Fix JP docs tranlation 2016-03-01 01:41:46 +09:00
Plusb Preco
24ae9b0ea9 Cleanup docs
* Adjust 80 chars per line
* Line feed after header
2016-02-29 01:38:32 +09:00
RacioN
2d11b1d9eb Update read me tranlation 2016-02-28 20:55:47 +09:00
RacioN
e3dde12c45 Update read me tranlation 2016-02-28 20:50:16 +09:00
RacioN
681a772f5f Add list 2016-02-28 20:42:14 +09:00
Cheng Zhao
5839d7dcd5 Merge pull request #4623 from parro-it/patch-1
Removed duplicate `isDevToolsFocused` entry
2016-02-28 10:41:27 +08:00
brenca
a06392459e Making fullsceenable work on Linux 2016-02-27 22:37:42 +01:00
Andrea Parodi
fd11b7e7db Removed duplicate isDevToolsFocused entry 2016-02-27 20:34:51 +01:00
Heilig Benedek
bb42c85df8 resolve update conflicts 2016-02-27 03:23:10 +01:00
Heilig Benedek
bb0ac688b2 Reverted SetFullscreenable disabling maximize button on Windows and removed that from the docs. 2016-02-27 03:07:53 +01:00
Cheng Zhao
7de97a55f7 Merge pull request #4609 from MaxWhere/framesubscriber-fix
🐎 framesubscriber speed and quality improvement
2016-02-26 23:21:42 +08:00
Cheng Zhao
b25c8ca621 Merge pull request #4616 from deepak1556/media_device_enumeration_patch
browser: allow enumeration of media device labels
2016-02-26 22:07:35 +08:00
Cheng Zhao
db46e9c203 Merge pull request #4596 from felixrieseberg/ci-docs
Add Headless CI Tutorial
2016-02-26 21:32:03 +08:00
Cheng Zhao
ebfc127628 Merge pull request #4522 from deepak1556/async_execute_javascript_patch
webContents: provide responses for executeJavscript method
2016-02-26 21:17:47 +08:00
gellert
070772b4b9 Added special key identifiers for OSX and Windows 2016-02-26 20:22:46 +08:00
Cheng Zhao
d9ad51e989 Merge pull request #4607 from rglyall/master
Fix Menu template API example
2016-02-26 20:13:40 +08:00
Robo
fce641aab6 browser: allow enumeration of media device labels 2016-02-26 16:31:20 +05:30
Cheng Zhao
a21e095a59 Merge pull request #4515 from deepak1556/ipc_value_conversion_patch
ipc: allow passing date instances
2016-02-26 16:16:33 +08:00
Cheng Zhao
a67b29d8d2 Bump v0.36.9 2016-02-26 02:18:27 +00:00
Cheng Zhao
795ac86266 Merge pull request #4608 from atom/harfbuzz
Use harfbuzz 1.06
2016-02-26 09:51:13 +08:00
Cheng Zhao
8a744255fa Update libchromiumcontent, use harfbuzz 1.06
Close #4513.
2016-02-26 09:23:39 +08:00
Felix Rieseberg
a3b8e81c21 📝 Add Headless CI Tutorial 2016-02-25 17:14:43 -08:00
Heilig Benedek
4bfa03e5f4 Removed an include no longer needed 2016-02-26 02:13:17 +01:00
Heilig Benedek
3f0d598a59 Merge atom/master 2016-02-26 02:05:57 +01:00
Robo
1235907835 run webframe methods for webview in its context 2016-02-26 05:14:45 +05:30
Heilig Benedek
9a0372b61b Removed size_ since it's not needed anymore 2016-02-25 23:48:58 +01:00
Robert Lyall
6f45678e9c Fix Menu template API example 2016-02-25 18:28:03 +00:00
Cheng Zhao
0ea80f674b Merge pull request #4595 from dongjoon-hyun/rename_function_filter_accelerator
Rename function `FilterAccecelator` to `FilterAccelerator` in `submenu.cc`
2016-02-25 21:18:57 +08:00
Cheng Zhao
316e6850ae Merge pull request #4592 from miniak/fix-url-request-converter-crash
Fix crash in mate::Converter<const net::URLRequest*>::ToV8
2016-02-25 21:11:43 +08:00
Robo
8386baf267 add spec 2016-02-25 11:46:30 +05:30
Robo
a734326907 track async api requests 2016-02-25 11:45:59 +05:30
Robo
2b547bd44a webContents: provide responses for executeJavscript method 2016-02-25 11:45:59 +05:30
Robo
a1a17b7ee8 use v8::Object::Get 2016-02-25 11:21:21 +05:30
Cheng Zhao
d00490271b Merge pull request #4518 from deepak1556/webview_host_window_patch
webview: api to get host browser window
2016-02-25 12:26:53 +08:00
Dongjoon Hyun
fee56df400 Rename function FilterAccecelator to FilterAccelerator in submenu_button.cc. 2016-02-24 11:15:21 -08:00
Milan Burda
d2b48b2aa7 Fix crash in mate::Converter<const net::URLRequest*>::ToV8
The net::URLRequest::url() method calls vector<GURL>::back(), which is undefined when the url_chain is empty
2016-02-24 14:01:26 +01:00
Robo
467870deb6 use builtin method 2016-02-24 16:30:23 +05:30
Robo
6fcc197db8 webview: api to get webcontents and associated host webcontents 2016-02-24 11:55:15 +05:30
Cheng Zhao
f3c7965cea Merge pull request #4588 from atom/fix-protocol-crash
Revert  #4551
2016-02-24 13:48:33 +08:00
Cheng Zhao
8ff30a2abc Revert "protocol: respect requests from partition"
This reverts commit 85800256de.
2016-02-24 13:25:30 +08:00
Cheng Zhao
bb1e4c2208 Revert "add docs"
This reverts commit bdfc19ad20.
2016-02-24 13:25:22 +08:00
Cheng Zhao
820c72af55 Merge pull request #4560 from magicae/magica-translate-docs-to-zh_CN
docs: update zh-CN docs translation [WIP]
2016-02-24 13:06:17 +08:00
Cheng Zhao
a63193c826 Merge pull request #4551 from deepak1556/protocol_session_patch
protocol: respect requests from partition
2016-02-24 12:03:37 +08:00
Cheng Zhao
3a3a95b0a9 Merge pull request #4581 from atom/linux-menu-fix
Notify the global menu bar when window is mapped
2016-02-23 20:41:50 +08:00
Robo
367d12402a ipc: allow passing date instances 2016-02-23 16:23:15 +05:30
Cheng Zhao
49f995925c Notify the global menu bar when window is mapped 2016-02-23 15:43:32 +08:00
Robo
bdfc19ad20 add docs 2016-02-23 12:54:20 +05:30
Cheng Zhao
1b3b35926a Merge pull request #4580 from kanatapple/master
docs: update jp doc ipc-renderer.md
2016-02-23 15:11:07 +08:00
Yasunari Fujieda
23268531ae docs: update jp doc ipc-renderer.md 2016-02-23 15:10:38 +09:00
Cheng Zhao
f47ae3c02f Merge pull request #4579 from jin5354/master
docs: update zh-CN doc debugging-main-process.md
2016-02-23 14:08:46 +08:00
Cheng Zhao
9c6ab6f1e0 Merge pull request #4566 from yamatoya/master
Update as upstream
2016-02-23 13:39:34 +08:00
jin5354
331bc42d57 docs: update zh-CN doc debugging-main-process.md
update zh-CN doc debugging-main-process.md to be up-to-date with
English ver.
2016-02-23 10:00:28 +08:00
Heilig Benedek
39bb670719 Revert will-enter-full-screen event, matching osx fullscreen: false behaviour on windows instead 2016-02-22 10:23:56 +01:00
Cheng Zhao
537ead8917 Merge pull request #4570 from atom/cleanup-remote
Cleanup code of remote module
2016-02-22 16:10:55 +08:00
Cheng Zhao
96b2705bd3 Fix render-view-deleted being emitted twice 2016-02-22 15:24:19 +08:00
Cheng Zhao
6753fcc1b4 Get rid of the ATOM_BROWSER_RELEASE_RENDER_VIEW event 2016-02-22 15:24:19 +08:00
Cheng Zhao
593a79ce20 Separate renderer functions by renderer process ID
Close #4324.
2016-02-22 15:24:18 +08:00
Cheng Zhao
d4c954870a Remove a few CoffeeScript generated junks 2016-02-22 15:24:18 +08:00
Cheng Zhao
59d6e7d6ef ObjectsRegistry no longer needs to send events 2016-02-22 15:24:18 +08:00
Cheng Zhao
2b04af4349 No longer need to count the references in webContents
All remote objects are now cached in renderer process, so there is
always only one reference to one remote object for each webContents.
2016-02-22 15:24:18 +08:00
Cheng Zhao
fe7462b352 No longer needs cache for methods of remote
Refs #4517.
2016-02-22 13:05:58 +08:00
Cheng Zhao
c65cfadd09 v8Util.createObjectWithName is no longer used 2016-02-22 13:05:58 +08:00
Cheng Zhao
34658473c9 Merge pull request #4568 from atom/remote-proto
Keep prototype chain in remote objects
2016-02-22 13:04:34 +08:00
Cheng Zhao
f610e332b3 spec: Tests for remote ES6 class 2016-02-22 12:35:51 +08:00
Cheng Zhao
67324ce732 Keep the prototype chain in remote objects 2016-02-22 12:35:51 +08:00
Takahito Yamatoya
9e1da8f097 Update as upstream 2016-02-22 00:59:18 +09:00
Cheng Zhao
361b9cad0f Merge pull request #4564 from dongjoon-hyun/rename_const_persist_prefix
Rename constant `PERSIST_PERFIX` to `PERSIST_PREFIX` in `session.js`.
2016-02-21 21:53:41 +08:00
Plusb Preco
f63532fa95 📝 Update as upstream
[ci skip]
2016-02-21 21:15:36 +08:00
Cheng Zhao
4a47deafc2 Merge pull request #4558 from cesine/update/deps
a new version of asar is out 0.10.0
2016-02-21 19:04:06 +08:00
Cheng Zhao
cad26fa606 Merge pull request #4517 from deepak1556/remote_browser_window_patch
remote: return webcontents instance from cache
2016-02-21 17:54:48 +08:00
Dongjoon Hyun
078c7bf8ab Rename constant PERSIST_PERFIX to PERSIST_PREFIX in session.js. 2016-02-21 00:16:53 -08:00
Magica
a05e98f463 Translate auto-updater.md in commit 45739ce434 2016-02-21 14:09:34 +08:00
Magica
f64dc5f57d Translate app.md in commit 45739ce434 2016-02-21 13:49:51 +08:00
Magica
1db72f8010 Translate accelerator.md of 45739ce434 2016-02-20 18:51:04 +08:00
Magica
060d06d396 Translate electron-faq.md#45739ce434ec3c3eb190d35d3948b702b54706cd 2016-02-20 17:00:58 +08:00
Magica
a737e15ddb Update README.md to 45739ce434 2016-02-20 16:09:56 +08:00
cesine
e45e246027 a new version of asar is out 0.10.0 2016-02-19 23:24:56 -05:00
Kevin Sawicki
45739ce434 Merge pull request #4547 from Rafaelgfirmino/master
Translated
2016-02-19 11:22:15 -08:00
Kevin Sawicki
777ff450cf Merge pull request #4543 from baconface/patch-2
Changed session to app to reflect rest of document
2016-02-19 11:21:10 -08:00
Robo
85800256de protocol: respect requests from partition 2016-02-19 19:39:01 +05:30
Rafael G Firmino
632c18ab37 Translated 2016-02-18 22:51:23 -02:00
Brad Metcalf
2a6fcf48e5 Changed session to app to reflect rest of document 2016-02-18 13:41:22 -06:00
Robo
0d77fd4a2c remote: return webcontents instance from cache 2016-02-18 17:40:10 +05:30
Heilig Benedek
2610aa60e9 🎨 lint fix 2016-02-18 01:19:41 +01:00
Heilig Benedek
7bf17f2541 Improved frame subscriber - now we only use framesubscription events as an event, and we copy from the backing store directly (instead of accessing it through a videoframe) 2016-02-18 01:15:00 +01:00
Heilig Benedek
157a290e38 📝 Adding documentation for will-enter-full-screen event 2016-02-09 02:41:19 +01:00
gellert
664f95a7b4 fixes osx request call 2016-02-09 01:39:27 +01:00
Heilig Benedek
a8ae14e94f Introducing a will-enter-full-screen event that's cancellable 2016-02-09 01:17:05 +01:00
177 changed files with 4450 additions and 1178 deletions

View File

@@ -71,8 +71,9 @@ API 레퍼런스가 있습니다. Electron을 빌드 하는 방법과 프로젝
- Atom 포럼의 [`electron`](http://discuss.atom.io/c/electron) 카테고리
- Freenode 채팅의 `#atom-shell` 채널
- Slack의 [`Atom`](http://atom-slack.herokuapp.com/) 채널
- [`electron-br`](https://electron-br.slack.com) *(브라질 포르투갈어)* 커뮤니티
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(한국)* 커뮤니티
- [`electron-br`](https://electron-br.slack.com) *(브라질)* 커뮤니티
- [`electron-kr`](http://www.meetup.com/electron-kr/) *(한국)* 커뮤니티
- [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(일본)* 커뮤니티
[awesome-electron](https://github.com/sindresorhus/awesome-electron) 프로젝트에
커뮤니티가 운영중인 유용한 예제 어플리케이션과 도구, 리소스가 있으니 한번 참고해 보시기

View File

@@ -4,7 +4,7 @@
'product_name%': 'Electron',
'company_name%': 'GitHub, Inc',
'company_abbr%': 'github',
'version%': '0.36.8',
'version%': '0.36.12',
},
'includes': [
'filenames.gypi',
@@ -69,7 +69,7 @@
{
'destination': '<(PRODUCT_DIR)/<(product_name).app/Contents/Resources',
'files': [
'atom/browser/default_app',
'default_app',
],
},
],
@@ -171,7 +171,7 @@
{
'destination': '<(PRODUCT_DIR)/resources',
'files': [
'atom/browser/default_app',
'default_app',
]
},
],
@@ -212,7 +212,7 @@
{
'destination': '<(PRODUCT_DIR)/resources',
'files': [
'atom/browser/default_app',
'default_app',
]
},
],

View File

@@ -132,19 +132,20 @@ void OnClientCertificateSelected(
std::shared_ptr<content::ClientCertificateDelegate> delegate,
mate::Arguments* args) {
mate::Dictionary cert_data;
if (!(args->Length() == 1 && args->GetNext(&cert_data))) {
if (!args->GetNext(&cert_data)) {
args->ThrowError();
return;
}
std::string encoded_data;
cert_data.Get("data", &encoded_data);
v8::Local<v8::Object> data;
if (!cert_data.Get("data", &data))
return;
auto certs =
net::X509Certificate::CreateCertificateListFromBytes(
encoded_data.data(), encoded_data.size(),
net::X509Certificate::FORMAT_AUTO);
delegate->ContinueWithCertificate(certs[0].get());
auto certs = net::X509Certificate::CreateCertificateListFromBytes(
node::Buffer::Data(data), node::Buffer::Length(data),
net::X509Certificate::FORMAT_AUTO);
if (certs.size() > 0)
delegate->ContinueWithCertificate(certs[0].get());
}
void PassLoginInformation(scoped_refptr<LoginHandler> login_handler,
@@ -282,6 +283,12 @@ void App::OnGpuProcessCrashed(base::TerminationStatus exit_code) {
Emit("gpu-process-crashed");
}
#if defined(OS_MACOSX)
void App::OnPlatformThemeChanged() {
Emit("platform-theme-changed");
}
#endif
base::FilePath App::GetPath(mate::Arguments* args, const std::string& name) {
bool succeed = false;
base::FilePath path;
@@ -370,6 +377,8 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
#if defined(OS_MACOSX)
.SetMethod("hide", base::Bind(&Browser::Hide, browser))
.SetMethod("show", base::Bind(&Browser::Show, browser))
.SetMethod("isDarkMode",
base::Bind(&Browser::IsDarkMode, browser))
#endif
#if defined(OS_WIN)
.SetMethod("setUserTasks",

View File

@@ -71,6 +71,10 @@ class App : public AtomBrowserClient::Delegate,
// content::GpuDataManagerObserver:
void OnGpuProcessCrashed(base::TerminationStatus exit_code) override;
#if defined(OS_MACOSX)
void OnPlatformThemeChanged() override;
#endif
// mate::Wrappable:
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;

View File

@@ -218,7 +218,8 @@ WebContents::WebContents(content::WebContents* web_contents)
WebContents::WebContents(v8::Isolate* isolate,
const mate::Dictionary& options)
: request_id_(0) {
: embedder_(nullptr),
request_id_(0) {
// Whether it is a guest WebContents.
bool is_guest = false;
options.Get("isGuest", &is_guest);
@@ -273,10 +274,10 @@ WebContents::WebContents(v8::Isolate* isolate,
guest_delegate_->Initialize(this);
NativeWindow* owner_window = nullptr;
WebContents* embedder = nullptr;
if (options.Get("embedder", &embedder) && embedder) {
if (options.Get("embedder", &embedder_) && embedder_) {
// New WebContents's owner_window is the embedder's owner_window.
auto relay = NativeWindowRelay::FromWebContents(embedder->web_contents());
auto relay =
NativeWindowRelay::FromWebContents(embedder_->web_contents());
if (relay)
owner_window = relay->window.get();
}
@@ -296,6 +297,7 @@ WebContents::~WebContents() {
// The WebContentsDestroyed will not be called automatically because we
// unsubscribe from webContents before destroying it. So we have to manually
// call it here to make sure "destroyed" event is emitted.
RenderViewDeleted(web_contents()->GetRenderViewHost());
WebContentsDestroyed();
}
}
@@ -461,6 +463,13 @@ void WebContents::FindReply(content::WebContents* web_contents,
}
}
bool WebContents::CheckMediaAccessPermission(
content::WebContents* web_contents,
const GURL& security_origin,
content::MediaStreamType type) {
return true;
}
void WebContents::RequestMediaAccessPermission(
content::WebContents* web_contents,
const content::MediaStreamRequest& request,
@@ -485,17 +494,7 @@ void WebContents::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
}
void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
int process_id = render_view_host->GetProcess()->GetID();
Emit("render-view-deleted", process_id);
// process.emit('ATOM_BROWSER_RELEASE_RENDER_VIEW', processId);
// Tell the rpc server that a render view has been deleted and we need to
// release all objects owned by it.
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
node::Environment* env = node::Environment::GetCurrent(isolate());
mate::EmitEvent(isolate(), env->process_object(),
"ATOM_BROWSER_RELEASE_RENDER_VIEW", process_id);
Emit("render-view-deleted", render_view_host->GetProcess()->GetID());
}
void WebContents::RenderProcessGone(base::TerminationStatus status) {
@@ -675,9 +674,6 @@ bool WebContents::OnMessageReceived(const IPC::Message& message) {
// be destroyed on close, and WebContentsDestroyed would be called for it, so
// we need to make sure the api::WebContents is also deleted.
void WebContents::WebContentsDestroyed() {
// The RenderViewDeleted was not called when the WebContents is destroyed.
RenderViewDeleted(web_contents()->GetRenderViewHost());
// This event is only for internal use, which is emitted when WebContents is
// being destroyed.
Emit("will-destroy");
@@ -1073,7 +1069,7 @@ void WebContents::BeginFrameSubscription(
const auto view = web_contents()->GetRenderWidgetHostView();
if (view) {
scoped_ptr<FrameSubscriber> frame_subscriber(new FrameSubscriber(
isolate(), view->GetVisibleViewportSize(), callback));
isolate(), view, callback));
view->BeginFrameSubscription(frame_subscriber.Pass());
}
}
@@ -1128,6 +1124,12 @@ v8::Local<v8::Value> WebContents::Session(v8::Isolate* isolate) {
return v8::Local<v8::Value>::New(isolate, session_);
}
content::WebContents* WebContents::HostWebContents() {
if (!embedder_)
return nullptr;
return embedder_->web_contents();
}
v8::Local<v8::Value> WebContents::DevToolsWebContents(v8::Isolate* isolate) {
if (devtools_web_contents_.IsEmpty())
return v8::Null(isolate);
@@ -1211,6 +1213,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
.SetMethod("addWorkSpace", &WebContents::AddWorkSpace)
.SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace)
.SetProperty("session", &WebContents::Session)
.SetProperty("hostWebContents", &WebContents::HostWebContents)
.SetProperty("devToolsWebContents", &WebContents::DevToolsWebContents)
.SetProperty("debugger", &WebContents::Debugger);
}

View File

@@ -147,6 +147,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
// Properties.
v8::Local<v8::Value> Session(v8::Isolate* isolate);
content::WebContents* HostWebContents();
v8::Local<v8::Value> DevToolsWebContents(v8::Isolate* isolate);
v8::Local<v8::Value> Debugger(v8::Isolate* isolate);
@@ -201,6 +202,10 @@ class WebContents : public mate::TrackableObject<WebContents>,
const gfx::Rect& selection_rect,
int active_match_ordinal,
bool final_update) override;
bool CheckMediaAccessPermission(
content::WebContents* web_contents,
const GURL& security_origin,
content::MediaStreamType type) override;
void RequestMediaAccessPermission(
content::WebContents* web_contents,
const content::MediaStreamRequest& request,
@@ -287,6 +292,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
scoped_ptr<WebViewGuestDelegate> guest_delegate_;
// The host webcontents that may contain this webcontents.
WebContents* embedder_;
// The type of current WebContents.
Type type_;

View File

@@ -191,6 +191,14 @@ void Window::OnWindowFocus() {
Emit("focus");
}
void Window::OnWindowShow() {
Emit("show");
}
void Window::OnWindowHide() {
Emit("hide");
}
void Window::OnWindowMaximize() {
Emit("maximize");
}
@@ -294,6 +302,10 @@ void Window::Focus() {
window_->Focus(true);
}
void Window::Blur() {
window_->Focus(false);
}
bool Window::IsFocused() {
return window_->IsFocused();
}
@@ -688,6 +700,7 @@ void Window::BuildPrototype(v8::Isolate* isolate,
.MakeDestroyable()
.SetMethod("close", &Window::Close)
.SetMethod("focus", &Window::Focus)
.SetMethod("blur", &Window::Blur)
.SetMethod("isFocused", &Window::IsFocused)
.SetMethod("show", &Window::Show)
.SetMethod("showInactive", &Window::ShowInactive)

View File

@@ -58,6 +58,8 @@ class Window : public mate::TrackableObject<Window>,
void OnWindowClosed() override;
void OnWindowBlur() override;
void OnWindowFocus() override;
void OnWindowShow() override;
void OnWindowHide() override;
void OnWindowMaximize() override;
void OnWindowUnmaximize() override;
void OnWindowMinimize() override;
@@ -83,6 +85,7 @@ class Window : public mate::TrackableObject<Window>,
// APIs for NativeWindow.
void Close();
void Focus();
void Blur();
bool IsFocused();
void Show();
void ShowInactive();

View File

@@ -4,19 +4,18 @@
#include "atom/browser/api/frame_subscriber.h"
#include "atom/common/node_includes.h"
#include "base/bind.h"
#include "media/base/video_frame.h"
#include "media/base/yuv_convert.h"
#include "atom/common/node_includes.h"
#include "content/public/browser/render_widget_host.h"
namespace atom {
namespace api {
FrameSubscriber::FrameSubscriber(v8::Isolate* isolate,
const gfx::Size& size,
content::RenderWidgetHostView* view,
const FrameCaptureCallback& callback)
: isolate_(isolate), size_(size), callback_(callback), weak_factory_(this) {
: isolate_(isolate), view_(view), callback_(callback), weak_factory_(this) {
}
bool FrameSubscriber::ShouldCaptureFrame(
@@ -24,39 +23,39 @@ bool FrameSubscriber::ShouldCaptureFrame(
base::TimeTicks present_time,
scoped_refptr<media::VideoFrame>* storage,
DeliverFrameCallback* callback) {
*storage = media::VideoFrame::CreateFrame(
media::PIXEL_FORMAT_YV12,
size_, gfx::Rect(size_), size_, base::TimeDelta());
*callback = base::Bind(&FrameSubscriber::OnFrameDelivered,
weak_factory_.GetWeakPtr(), *storage);
return true;
const auto host = view_ ? view_->GetRenderWidgetHost() : nullptr;
if (!view_ || !host)
return false;
const auto size = view_->GetVisibleViewportSize();
host->CopyFromBackingStore(
gfx::Rect(size),
size,
base::Bind(&FrameSubscriber::OnFrameDelivered,
weak_factory_.GetWeakPtr(), callback_),
kBGRA_8888_SkColorType);
return false;
}
void FrameSubscriber::OnFrameDelivered(
scoped_refptr<media::VideoFrame> frame, base::TimeTicks, bool result) {
if (!result)
void FrameSubscriber::OnFrameDelivered(const FrameCaptureCallback& callback,
const SkBitmap& bitmap, content::ReadbackResponse response) {
if (bitmap.computeSize64() == 0)
return;
v8::Locker locker(isolate_);
v8::HandleScope handle_scope(isolate_);
gfx::Rect rect = frame->visible_rect();
size_t rgb_arr_size = rect.width() * rect.height() * 4;
size_t rgb_arr_size = bitmap.width() * bitmap.height() *
bitmap.bytesPerPixel();
v8::MaybeLocal<v8::Object> buffer = node::Buffer::New(isolate_, rgb_arr_size);
if (buffer.IsEmpty())
return;
// Convert a frame of YUV to 32 bit ARGB.
media::ConvertYUVToRGB32(frame->data(media::VideoFrame::kYPlane),
frame->data(media::VideoFrame::kUPlane),
frame->data(media::VideoFrame::kVPlane),
reinterpret_cast<uint8*>(
node::Buffer::Data(buffer.ToLocalChecked())),
rect.width(), rect.height(),
frame->stride(media::VideoFrame::kYPlane),
frame->stride(media::VideoFrame::kUVPlane),
rect.width() * 4,
media::YV12);
bitmap.copyPixelsTo(
reinterpret_cast<uint8*>(node::Buffer::Data(buffer.ToLocalChecked())),
rgb_arr_size);
callback_.Run(buffer.ToLocalChecked());
}

View File

@@ -7,7 +7,10 @@
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
#include "content/public/browser/readback_types.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/size.h"
#include "v8/include/v8.h"
@@ -20,7 +23,7 @@ class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber {
using FrameCaptureCallback = base::Callback<void(v8::Local<v8::Value>)>;
FrameSubscriber(v8::Isolate* isolate,
const gfx::Size& size,
content::RenderWidgetHostView* view,
const FrameCaptureCallback& callback);
bool ShouldCaptureFrame(const gfx::Rect& damage_rect,
@@ -29,11 +32,11 @@ class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber {
DeliverFrameCallback* callback) override;
private:
void OnFrameDelivered(
scoped_refptr<media::VideoFrame> frame, base::TimeTicks, bool);
void OnFrameDelivered(const FrameCaptureCallback& callback,
const SkBitmap& bitmap, content::ReadbackResponse response);
v8::Isolate* isolate_;
gfx::Size size_;
content::RenderWidgetHostView* view_;
FrameCaptureCallback callback_;
base::WeakPtrFactory<FrameSubscriber> weak_factory_;

View File

@@ -31,7 +31,7 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
static AtomBrowserMainParts* Get();
// Sets the exit code, will fail if the the message loop is not ready.
// Sets the exit code, will fail if the message loop is not ready.
bool SetExitCode(int code);
// Gets the exit code

View File

@@ -181,4 +181,8 @@ void Browser::OnWindowAllClosed() {
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnWindowAllClosed());
}
void Browser::PlatformThemeChanged() {
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnPlatformThemeChanged());
}
} // namespace atom

View File

@@ -83,6 +83,9 @@ class Browser : public WindowListObserver {
// Show the application.
void Show();
// Check if the system is in Dark Mode.
bool IsDarkMode();
// Bounce the dock icon.
enum BounceType {
BOUNCE_CRITICAL = 0,
@@ -142,6 +145,9 @@ class Browser : public WindowListObserver {
// Request basic auth login.
void RequestLogin(LoginHandler* login_handler);
// Tell the application that plaform's theme changed.
void PlatformThemeChanged();
void AddObserver(BrowserObserver* obs) {
observers_.AddObserver(obs);
}

View File

@@ -26,6 +26,11 @@ void Browser::Show() {
[[AtomApplication sharedApplication] unhide:nil];
}
bool Browser::IsDarkMode() {
NSString *mode = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
return [mode isEqualToString: @"Dark"];
}
void Browser::AddRecentDocument(const base::FilePath& path) {
NSString* path_string = base::mac::FilePathToNSString(path);
if (!path_string)

View File

@@ -45,6 +45,8 @@ class BrowserObserver {
// The browser requests HTTP login.
virtual void OnLogin(LoginHandler* login_handler) {}
virtual void OnPlatformThemeChanged() {}
protected:
virtual ~BrowserObserver() {}
};

View File

@@ -1,109 +0,0 @@
'use strict';
const EventEmitter = require('events').EventEmitter;
const v8Util = process.atomBinding('v8_util');
class ObjectsRegistry extends EventEmitter {
constructor() {
super();
this.setMaxListeners(Number.MAX_VALUE);
this.nextId = 0;
// Stores all objects by ref-counting.
// (id) => {object, count}
this.storage = {};
// Stores the IDs of objects referenced by WebContents.
// (webContentsId) => {(id) => (count)}
this.owners = {};
}
// Register a new object, the object would be kept referenced until you release
// it explicitly.
add(webContentsId, obj) {
var base, base1, id;
id = this.saveToStorage(obj);
// Remember the owner.
if ((base = this.owners)[webContentsId] == null) {
base[webContentsId] = {};
}
if ((base1 = this.owners[webContentsId])[id] == null) {
base1[id] = 0;
}
this.owners[webContentsId][id]++;
// Returns object's id
return id;
}
// Get an object according to its ID.
get(id) {
var ref;
return (ref = this.storage[id]) != null ? ref.object : void 0;
}
// Dereference an object according to its ID.
remove(webContentsId, id) {
var pointer;
this.dereference(id, 1);
// Also reduce the count in owner.
pointer = this.owners[webContentsId];
if (pointer == null) {
return;
}
--pointer[id];
if (pointer[id] === 0) {
return delete pointer[id];
}
}
// Clear all references to objects refrenced by the WebContents.
clear(webContentsId) {
var count, id, ref;
this.emit("clear-" + webContentsId);
if (this.owners[webContentsId] == null) {
return;
}
ref = this.owners[webContentsId];
for (id in ref) {
count = ref[id];
this.dereference(id, count);
}
return delete this.owners[webContentsId];
}
// Private: Saves the object into storage and assigns an ID for it.
saveToStorage(object) {
var id;
id = v8Util.getHiddenValue(object, 'atomId');
if (!id) {
id = ++this.nextId;
this.storage[id] = {
count: 0,
object: object
};
v8Util.setHiddenValue(object, 'atomId', id);
}
++this.storage[id].count;
return id;
}
// Private: Dereference the object from store.
dereference(id, count) {
var pointer;
pointer = this.storage[id];
if (pointer == null) {
return;
}
pointer.count -= count;
if (pointer.count === 0) {
v8Util.deleteHiddenValue(pointer.object, 'atomId');
return delete this.storage[id];
}
}
}
module.exports = new ObjectsRegistry;

View File

@@ -24,6 +24,9 @@
// Don't add the "Enter Full Screen" menu item automatically.
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"NSFullScreenMenuItemEverywhere"];
// Add observer to monitor the system's Dark Mode theme.
[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(platformThemeChanged:) name:@"AppleInterfaceThemeChangedNotification" object:nil];
atom::Browser::Get()->WillFinishLaunching();
}
@@ -59,4 +62,8 @@
return flag;
}
- (void)platformThemeChanged:(NSNotification *)notify {
atom::Browser::Get()->PlatformThemeChanged();
}
@end

View File

@@ -115,6 +115,12 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
} else {
SetSizeConstraints(size_constraints);
}
#if defined(USE_X11)
bool resizable;
if (options.Get(options::kResizable, &resizable)) {
SetResizable(resizable);
}
#endif
#if defined(OS_WIN) || defined(USE_X11)
bool closable;
if (options.Get(options::kClosable, &closable)) {
@@ -133,12 +139,17 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
if (options.Get(options::kAlwaysOnTop, &top) && top) {
SetAlwaysOnTop(true);
}
#if defined(OS_MACOSX) || defined(OS_WIN)
bool fullscreen;
if (options.Get(options::kFullscreen, &fullscreen) && fullscreen) {
// Disable fullscreen button if 'fullscreen' is specified to false.
bool fullscreenable = true;
bool fullscreen = false;
if (options.Get(options::kFullscreen, &fullscreen) && !fullscreen)
fullscreenable = false;
// Overriden by 'fullscreenable'.
options.Get(options::kFullScreenable, &fullscreenable);
SetFullScreenable(fullscreenable);
if (fullscreen) {
SetFullScreen(true);
}
#endif
bool skip;
if (options.Get(options::kSkipTaskbar, &skip) && skip) {
SetSkipTaskbar(skip);
@@ -417,6 +428,14 @@ void NativeWindow::NotifyWindowFocus() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowFocus());
}
void NativeWindow::NotifyWindowShow() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowShow());
}
void NativeWindow::NotifyWindowHide() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowHide());
}
void NativeWindow::NotifyWindowMaximize() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowMaximize());
}

View File

@@ -210,6 +210,8 @@ class NativeWindow : public base::SupportsUserData,
void NotifyWindowClosed();
void NotifyWindowBlur();
void NotifyWindowFocus();
void NotifyWindowShow();
void NotifyWindowHide();
void NotifyWindowMaximize();
void NotifyWindowUnmaximize();
void NotifyWindowMinimize();

View File

@@ -79,6 +79,21 @@ bool ScopedDisableResize::disable_resize_ = false;
return self;
}
- (void)windowDidChangeOcclusionState:(NSNotification *)notification {
// notification.object is the window that changed its state.
// It's safe to use self.window instead if you don't assign one delegate to many windows
NSWindow *window = notification.object;
// check occlusion binary flag
if (window.occlusionState & NSWindowOcclusionStateVisible) {
// The app is visible
shell_->NotifyWindowShow();
} else {
// The app is not visible
shell_->NotifyWindowHide();
}
}
- (void)windowDidBecomeMain:(NSNotification*)notification {
content::WebContents* web_contents = shell_->web_contents();
if (!web_contents)
@@ -482,19 +497,9 @@ NativeWindowMac::NativeWindowMac(
options.Get(options::kDisableAutoHideCursor, &disableAutoHideCursor);
[window_ setDisableAutoHideCursor:disableAutoHideCursor];
// Disable fullscreen button when 'fullscreenable' is false or 'fullscreen'
// is specified to false.
bool fullscreenable = true;
options.Get(options::kFullScreenable, &fullscreenable);
bool fullscreen = false;
if (options.Get(options::kFullscreen, &fullscreen) && !fullscreen)
fullscreenable = false;
SetFullScreenable(fullscreenable);
// Disable zoom button if window is not resizable
if (!maximizable) {
// Disable zoom button if window is not resizable.
if (!maximizable)
SetMaximizable(false);
}
NSView* view = inspectable_web_contents()->GetView()->GetNativeView();
[view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
@@ -583,7 +588,16 @@ void NativeWindowMac::Unmaximize() {
}
bool NativeWindowMac::IsMaximized() {
return [window_ isZoomed];
if (([window_ styleMask] & NSResizableWindowMask) != 0) {
return [window_ isZoomed];
} else {
NSRect rectScreen = [[NSScreen mainScreen] visibleFrame];
NSRect rectWindow = [window_ frame];
return (rectScreen.origin.x == rectWindow.origin.x &&
rectScreen.origin.y == rectWindow.origin.y &&
rectScreen.size.width == rectWindow.size.width &&
rectScreen.size.height == rectWindow.size.height);
}
}
void NativeWindowMac::Minimize() {
@@ -896,21 +910,11 @@ void NativeWindowMac::HandleKeyboardEvent(
// Handle the cmd+~ shortcut.
if ((event.os_event.modifierFlags & NSCommandKeyMask) /* cmd */ &&
(event.os_event.keyCode == 50 /* ~ */)) {
// Switch to next visible window.
NSArray* windows = [NSApp windows];
NSIndexSet* indexes = [windows indexesOfObjectsPassingTest:
^BOOL(id window, NSUInteger idx, BOOL* stop) {
return [window isVisible];
}];
if ([indexes count] == 0)
return;
NSUInteger current = [windows indexOfObject:event.os_event.window];
if (current == NSNotFound) // Some faked event.
return;
NSUInteger next = [indexes indexGreaterThanIndex:current];
if (next == NSNotFound)
next = [indexes firstIndex];
[[windows objectAtIndex:next] makeKeyAndOrderFront:nil];
if (event.os_event.modifierFlags & NSShiftKeyMask) {
[NSApp sendAction:@selector(_cycleWindowsReversed:) to:nil from:nil];
} else {
[NSApp sendAction:@selector(_cycleWindows:) to:nil from:nil];
}
}
}
}

View File

@@ -42,6 +42,12 @@ class NativeWindowObserver {
// Called when window gains focus.
virtual void OnWindowFocus() {}
// Called when window is shown.
virtual void OnWindowShow() {}
// Called when window is hidden.
virtual void OnWindowHide() {}
// Called when window state changed.
virtual void OnWindowMaximize() {}
virtual void OnWindowUnmaximize() {}

View File

@@ -117,7 +117,8 @@ NativeWindowViews::NativeWindowViews(
movable_(true),
resizable_(true),
maximizable_(true),
minimizable_(true) {
minimizable_(true),
fullscreenable_(true) {
options.Get(options::kTitle, &title_);
options.Get(options::kAutoHideMenuBar, &menu_bar_autohide_);
@@ -300,14 +301,35 @@ bool NativeWindowViews::IsFocused() {
void NativeWindowViews::Show() {
window_->native_widget_private()->ShowWithWindowState(GetRestoredState());
NotifyWindowShow();
#if defined(USE_X11)
if (global_menu_bar_)
global_menu_bar_->OnWindowMapped();
#endif
}
void NativeWindowViews::ShowInactive() {
window_->ShowInactive();
NotifyWindowShow();
#if defined(USE_X11)
if (global_menu_bar_)
global_menu_bar_->OnWindowMapped();
#endif
}
void NativeWindowViews::Hide() {
window_->Hide();
NotifyWindowHide();
#if defined(USE_X11)
if (global_menu_bar_)
global_menu_bar_->OnWindowUnmapped();
#endif
}
bool NativeWindowViews::IsVisible() {
@@ -347,6 +369,9 @@ bool NativeWindowViews::IsMinimized() {
}
void NativeWindowViews::SetFullScreen(bool fullscreen) {
if (!IsFullScreenable())
return;
#if defined(OS_WIN)
// There is no native fullscreen state on Windows.
if (fullscreen) {
@@ -490,11 +515,12 @@ bool NativeWindowViews::IsMaximizable() {
#endif
}
void NativeWindowViews::SetFullScreenable(bool maximizable) {
void NativeWindowViews::SetFullScreenable(bool fullscreenable) {
fullscreenable_ = fullscreenable;
}
bool NativeWindowViews::IsFullScreenable() {
return true;
return fullscreenable_;
}
void NativeWindowViews::SetClosable(bool closable) {

View File

@@ -212,6 +212,7 @@ class NativeWindowViews : public NativeWindow,
bool resizable_;
bool maximizable_;
bool minimizable_;
bool fullscreenable_;
std::string title_;
gfx::Size widget_size_;

View File

@@ -17,9 +17,9 @@
<key>CFBundleIconFile</key>
<string>atom.icns</string>
<key>CFBundleVersion</key>
<string>0.36.8</string>
<string>0.36.12</string>
<key>CFBundleShortVersionString</key>
<string>0.36.8</string>
<string>0.36.12</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>LSMinimumSystemVersion</key>

View File

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

View File

@@ -18,13 +18,12 @@
namespace accelerator_util {
bool StringToAccelerator(const std::string& description,
bool StringToAccelerator(const std::string& shortcut,
ui::Accelerator* accelerator) {
if (!base::IsStringASCII(description)) {
if (!base::IsStringASCII(shortcut)) {
LOG(ERROR) << "The accelerator string can only contain ASCII characters";
return false;
}
std::string shortcut(base::ToLowerASCII(description));
std::vector<std::string> tokens = base::SplitString(
shortcut, "+", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
@@ -33,95 +32,35 @@ bool StringToAccelerator(const std::string& description,
int modifiers = ui::EF_NONE;
ui::KeyboardCode key = ui::VKEY_UNKNOWN;
for (size_t i = 0; i < tokens.size(); i++) {
// We use straight comparing instead of map because the accelerator tends
// to be correct and usually only uses few special tokens.
if (tokens[i].size() == 1) {
bool shifted = false;
key = atom::KeyboardCodeFromCharCode(tokens[i][0], &shifted);
if (shifted)
bool shifted = false;
ui::KeyboardCode code = atom::KeyboardCodeFromStr(tokens[i], &shifted);
if (shifted)
modifiers |= ui::EF_SHIFT_DOWN;
switch (code) {
// The token can be a modifier.
case ui::VKEY_SHIFT:
modifiers |= ui::EF_SHIFT_DOWN;
} else if (tokens[i] == "ctrl" || tokens[i] == "control") {
modifiers |= ui::EF_CONTROL_DOWN;
} else if (tokens[i] == "super") {
modifiers |= ui::EF_COMMAND_DOWN;
#if defined(OS_MACOSX)
} else if (tokens[i] == "cmd" || tokens[i] == "command") {
modifiers |= ui::EF_COMMAND_DOWN;
#endif
} else if (tokens[i] == "commandorcontrol" || tokens[i] == "cmdorctrl") {
#if defined(OS_MACOSX)
modifiers |= ui::EF_COMMAND_DOWN;
#else
modifiers |= ui::EF_CONTROL_DOWN;
#endif
} else if (tokens[i] == "alt") {
modifiers |= ui::EF_ALT_DOWN;
} else if (tokens[i] == "shift") {
modifiers |= ui::EF_SHIFT_DOWN;
} else if (tokens[i] == "plus") {
modifiers |= ui::EF_SHIFT_DOWN;
key = ui::VKEY_OEM_PLUS;
} else if (tokens[i] == "tab") {
key = ui::VKEY_TAB;
} else if (tokens[i] == "space") {
key = ui::VKEY_SPACE;
} else if (tokens[i] == "backspace") {
key = ui::VKEY_BACK;
} else if (tokens[i] == "delete") {
key = ui::VKEY_DELETE;
} else if (tokens[i] == "insert") {
key = ui::VKEY_INSERT;
} else if (tokens[i] == "enter" || tokens[i] == "return") {
key = ui::VKEY_RETURN;
} else if (tokens[i] == "up") {
key = ui::VKEY_UP;
} else if (tokens[i] == "down") {
key = ui::VKEY_DOWN;
} else if (tokens[i] == "left") {
key = ui::VKEY_LEFT;
} else if (tokens[i] == "right") {
key = ui::VKEY_RIGHT;
} else if (tokens[i] == "home") {
key = ui::VKEY_HOME;
} else if (tokens[i] == "end") {
key = ui::VKEY_END;
} else if (tokens[i] == "pageup") {
key = ui::VKEY_PRIOR;
} else if (tokens[i] == "pagedown") {
key = ui::VKEY_NEXT;
} else if (tokens[i] == "esc" || tokens[i] == "escape") {
key = ui::VKEY_ESCAPE;
} else if (tokens[i] == "volumemute") {
key = ui::VKEY_VOLUME_MUTE;
} else if (tokens[i] == "volumeup") {
key = ui::VKEY_VOLUME_UP;
} else if (tokens[i] == "volumedown") {
key = ui::VKEY_VOLUME_DOWN;
} else if (tokens[i] == "medianexttrack") {
key = ui::VKEY_MEDIA_NEXT_TRACK;
} else if (tokens[i] == "mediaprevioustrack") {
key = ui::VKEY_MEDIA_PREV_TRACK;
} else if (tokens[i] == "mediastop") {
key = ui::VKEY_MEDIA_STOP;
} else if (tokens[i] == "mediaplaypause") {
key = ui::VKEY_MEDIA_PLAY_PAUSE;
} else if (tokens[i].size() > 1 && tokens[i][0] == 'f') {
// F1 - F24.
int n;
if (base::StringToInt(tokens[i].c_str() + 1, &n) && n > 0 && n < 25) {
key = static_cast<ui::KeyboardCode>(ui::VKEY_F1 + n - 1);
} else {
LOG(WARNING) << tokens[i] << "is not available on keyboard";
return false;
}
} else {
LOG(WARNING) << "Invalid accelerator token: " << tokens[i];
return false;
break;
case ui::VKEY_CONTROL:
modifiers |= ui::EF_CONTROL_DOWN;
break;
case ui::VKEY_MENU:
modifiers |= ui::EF_ALT_DOWN;
break;
case ui::VKEY_COMMAND:
modifiers |= ui::EF_COMMAND_DOWN;
break;
case ui::VKEY_ALTGR:
modifiers |= ui::EF_ALTGR_DOWN;
break;
// Or it is a normal key.
default:
key = code;
}
}
if (key == ui::VKEY_UNKNOWN) {
LOG(WARNING) << "The accelerator doesn't contain a valid key";
LOG(WARNING) << shortcut << " doesn't contain a valid key";
return false;
}

View File

@@ -32,9 +32,12 @@ Role kRolesMap[] = {
{ @selector(cut:), "cut" },
{ @selector(copy:), "copy" },
{ @selector(paste:), "paste" },
{ @selector(delete:), "delete" },
{ @selector(pasteAndMatchStyle:), "paste-and-match-style" },
{ @selector(selectAll:), "selectall" },
{ @selector(performMiniaturize:), "minimize" },
{ @selector(performClose:), "close" },
{ @selector(performZoom:), "zoom" },
};
} // namespace

View File

@@ -210,6 +210,14 @@ void GlobalMenuBarX11::InitServer(gfx::AcceleratedWidget xid) {
server_ = server_new(path.c_str());
}
void GlobalMenuBarX11::OnWindowMapped() {
GlobalMenuBarRegistrarX11::GetInstance()->OnWindowMapped(xid_);
}
void GlobalMenuBarX11::OnWindowUnmapped() {
GlobalMenuBarRegistrarX11::GetInstance()->OnWindowUnmapped(xid_);
}
void GlobalMenuBarX11::BuildMenuFromModel(ui::MenuModel* model,
DbusmenuMenuitem* parent) {
for (int i = 0; i < model->GetItemCount(); ++i) {

View File

@@ -40,12 +40,16 @@ class GlobalMenuBarX11 {
explicit GlobalMenuBarX11(NativeWindowViews* window);
virtual ~GlobalMenuBarX11();
// Creates the object path for DbusemenuServer which is attached to |xid|.
// Creates the object path for DbusmenuServer which is attached to |xid|.
static std::string GetPathForWindow(gfx::AcceleratedWidget xid);
void SetMenu(ui::MenuModel* menu_model);
bool IsServerStarted() const;
// Called by NativeWindow when it show/hides.
void OnWindowMapped();
void OnWindowUnmapped();
private:
// Creates a DbusmenuServer.
void InitServer(gfx::AcceleratedWidget xid);

View File

@@ -15,7 +15,7 @@ namespace atom {
namespace {
// Filter out the "&" in menu label.
base::string16 FilterAccecelator(const base::string16& label) {
base::string16 FilterAccelerator(const base::string16& label) {
base::string16 out;
base::RemoveChars(label, base::ASCIIToUTF16("&").c_str(), &out);
return out;
@@ -26,7 +26,7 @@ base::string16 FilterAccecelator(const base::string16& label) {
SubmenuButton::SubmenuButton(views::ButtonListener* listener,
const base::string16& title,
views::MenuButtonListener* menu_button_listener)
: views::MenuButton(listener, FilterAccecelator(title),
: views::MenuButton(listener, FilterAccelerator(title),
menu_button_listener, false),
accelerator_(0),
show_underline_(false),

View File

@@ -13,6 +13,7 @@
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/node_includes.h"
#include "base/base64.h"
#include "base/files/file_util.h"
#include "base/strings/string_util.h"
#include "base/strings/pattern.h"
#include "native_mate/dictionary.h"
@@ -119,6 +120,20 @@ bool PopulateImageSkiaRepsFromPath(gfx::ImageSkia* image,
return succeed;
}
base::FilePath NormalizePath(const base::FilePath& path) {
if (!path.ReferencesParent()) {
return path;
}
base::FilePath absolute_path = MakeAbsoluteFilePath(path);
// MakeAbsoluteFilePath returns an empty path on failures so use original path
if (absolute_path.empty()) {
return path;
} else {
return absolute_path;
}
}
#if defined(OS_MACOSX)
bool IsTemplateFilename(const base::FilePath& path) {
return (base::MatchPattern(path.value(), "*Template.*") ||
@@ -254,17 +269,19 @@ mate::Handle<NativeImage> NativeImage::CreateFromJPEG(
mate::Handle<NativeImage> NativeImage::CreateFromPath(
v8::Isolate* isolate, const base::FilePath& path) {
gfx::ImageSkia image_skia;
if (path.MatchesExtension(FILE_PATH_LITERAL(".ico"))) {
base::FilePath image_path = NormalizePath(path);
if (image_path.MatchesExtension(FILE_PATH_LITERAL(".ico"))) {
#if defined(OS_WIN)
ReadImageSkiaFromICO(&image_skia, path);
ReadImageSkiaFromICO(&image_skia, image_path);
#endif
} else {
PopulateImageSkiaRepsFromPath(&image_skia, path);
PopulateImageSkiaRepsFromPath(&image_skia, image_path);
}
gfx::Image image(image_skia);
mate::Handle<NativeImage> handle = Create(isolate, image);
#if defined(OS_MACOSX)
if (IsTemplateFilename(path))
if (IsTemplateFilename(image_path))
handle->SetTemplateImage(true);
#endif
return handle;

View File

@@ -2,49 +2,15 @@
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include <map>
#include <string>
#include "atom/common/api/object_life_monitor.h"
#include "atom/common/node_includes.h"
#include "base/stl_util.h"
#include "native_mate/dictionary.h"
#include "v8/include/v8-profiler.h"
namespace {
// A Persistent that can be copied and will not free itself.
template<class T>
struct LeakedPersistentTraits {
typedef v8::Persistent<T, LeakedPersistentTraits<T> > LeakedPersistent;
static const bool kResetInDestructor = false;
template<class S, class M>
static V8_INLINE void Copy(const v8::Persistent<S, M>& source,
LeakedPersistent* dest) {
// do nothing, just allow copy
}
};
// The handles are leaked on purpose.
using FunctionTemplateHandle =
LeakedPersistentTraits<v8::FunctionTemplate>::LeakedPersistent;
std::map<std::string, FunctionTemplateHandle> function_templates_;
v8::Local<v8::Object> CreateObjectWithName(v8::Isolate* isolate,
const std::string& name) {
if (name == "Object")
return v8::Object::New(isolate);
if (ContainsKey(function_templates_, name))
return v8::Local<v8::FunctionTemplate>::New(
isolate, function_templates_[name])->GetFunction()->NewInstance();
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
t->SetClassName(mate::StringToV8(isolate, name));
function_templates_[name] = FunctionTemplateHandle(isolate, t);
return t->GetFunction()->NewInstance();
}
v8::Local<v8::Value> GetHiddenValue(v8::Local<v8::Object> object,
v8::Local<v8::String> key) {
return object->GetHiddenValue(key);
@@ -78,7 +44,6 @@ void TakeHeapSnapshot(v8::Isolate* isolate) {
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
v8::Local<v8::Context> context, void* priv) {
mate::Dictionary dict(context->GetIsolate(), exports);
dict.SetMethod("createObjectWithName", &CreateObjectWithName);
dict.SetMethod("getHiddenValue", &GetHiddenValue);
dict.SetMethod("setHiddenValue", &SetHiddenValue);
dict.SetMethod("deleteHiddenValue", &DeleteHiddenValue);

View File

@@ -31,16 +31,16 @@ ObjectLifeMonitor::ObjectLifeMonitor(v8::Isolate* isolate,
// static
void ObjectLifeMonitor::OnObjectGC(
const v8::WeakCallbackInfo<ObjectLifeMonitor>& data) {
// Usually FirstWeakCallback should do nothing other than reset |object_|
// and then set a second weak callback to run later. We can sidestep that,
// because posting a task to the current message loop is all but free - but
// DO NOT add any more work to this method. The only acceptable place to add
// code is RunCallback.
ObjectLifeMonitor* self = data.GetParameter();
self->target_.Reset();
base::MessageLoop::current()->PostTask(
FROM_HERE, base::Bind(&ObjectLifeMonitor::RunCallback,
self->weak_ptr_factory_.GetWeakPtr()));
self->RunCallback();
data.SetSecondPassCallback(Free);
}
// static
void ObjectLifeMonitor::Free(
const v8::WeakCallbackInfo<ObjectLifeMonitor>& data) {
delete data.GetParameter();
}
void ObjectLifeMonitor::RunCallback() {
@@ -50,7 +50,6 @@ void ObjectLifeMonitor::RunCallback() {
v8::Context::Scope context_scope(context);
v8::Local<v8::Function>::New(isolate_, destructor_)->Call(
context->Global(), 0, nullptr);
delete this;
}
} // namespace atom

View File

@@ -23,6 +23,7 @@ class ObjectLifeMonitor {
v8::Local<v8::Function> destructor);
static void OnObjectGC(const v8::WeakCallbackInfo<ObjectLifeMonitor>& data);
static void Free(const v8::WeakCallbackInfo<ObjectLifeMonitor>& data);
void RunCallback();

View File

@@ -7,7 +7,7 @@
#define ATOM_MAJOR_VERSION 0
#define ATOM_MINOR_VERSION 36
#define ATOM_PATCH_VERSION 8
#define ATOM_PATCH_VERSION 12
#define ATOM_VERSION_IS_RELEASE 1

View File

@@ -211,7 +211,7 @@ bool CrashService::Initialize(const base::string16& application_name,
std::wstring pipe_name = kTestPipeName;
int max_reports = -1;
// The checkpoint file allows CrashReportSender to enforce the the maximum
// The checkpoint file allows CrashReportSender to enforce the maximum
// reports per day quota. Does not seem to serve any other purpose.
base::FilePath checkpoint_path = operating_dir.Append(kCheckPointFile);

View File

@@ -3,12 +3,19 @@
// found in the LICENSE file.
#include <string>
#include "atom/common/keyboard_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
namespace atom {
// Return key code of the char.
namespace {
// Return key code of the char, and also determine whether the SHIFT key is
// pressed.
ui::KeyboardCode KeyboardCodeFromCharCode(base::char16 c, bool* shifted) {
c = base::ToLowerASCII(c);
*shifted = false;
switch (c) {
case 0x08: return ui::VKEY_BACK;
@@ -72,28 +79,98 @@ ui::KeyboardCode KeyboardCodeFromCharCode(base::char16 c, bool* shifted) {
}
}
// Return key code of the char.
ui::KeyboardCode KeyboardCodeFromKeyIdentifier(const std::string& chr) {
if (chr == "enter") return ui::VKEY_RETURN;
if (chr == "backspace") return ui::VKEY_BACK;
if (chr == "delete") return ui::VKEY_DELETE;
if (chr == "tab") return ui::VKEY_TAB;
if (chr == "escape") return ui::VKEY_ESCAPE;
if (chr == "control") return ui::VKEY_CONTROL;
if (chr == "alt") return ui::VKEY_MENU;
if (chr == "shift") return ui::VKEY_SHIFT;
if (chr == "end") return ui::VKEY_END;
if (chr == "home") return ui::VKEY_HOME;
if (chr == "insert") return ui::VKEY_INSERT;
if (chr == "left") return ui::VKEY_LEFT;
if (chr == "up") return ui::VKEY_UP;
if (chr == "right") return ui::VKEY_RIGHT;
if (chr == "down") return ui::VKEY_DOWN;
if (chr == "pageup") return ui::VKEY_PRIOR;
if (chr == "pagedown") return ui::VKEY_NEXT;
if (chr == "printscreen") return ui::VKEY_SNAPSHOT;
// Return key code represented by |str|.
ui::KeyboardCode KeyboardCodeFromKeyIdentifier(const std::string& s,
bool* shifted) {
std::string str = base::ToLowerASCII(s);
if (str == "ctrl" || str == "control") {
return ui::VKEY_CONTROL;
} else if (str == "super" || str == "cmd" || str == "command" ||
str == "meta") {
return ui::VKEY_COMMAND;
} else if (str == "commandorcontrol" || str == "cmdorctrl") {
#if defined(OS_MACOSX)
return ui::VKEY_COMMAND;
#else
return ui::VKEY_CONTROL;
#endif
} else if (str == "alt" || str == "option") {
return ui::VKEY_MENU;
} else if (str == "shift") {
return ui::VKEY_SHIFT;
} else if (str == "altgr") {
return ui::VKEY_ALTGR;
} else if (str == "plus") {
*shifted = true;
return ui::VKEY_OEM_PLUS;
} else if (str == "tab") {
return ui::VKEY_TAB;
} else if (str == "space") {
return ui::VKEY_SPACE;
} else if (str == "backspace") {
return ui::VKEY_BACK;
} else if (str == "delete") {
return ui::VKEY_DELETE;
} else if (str == "insert") {
return ui::VKEY_INSERT;
} else if (str == "enter" || str == "return") {
return ui::VKEY_RETURN;
} else if (str == "up") {
return ui::VKEY_UP;
} else if (str == "down") {
return ui::VKEY_DOWN;
} else if (str == "left") {
return ui::VKEY_LEFT;
} else if (str == "right") {
return ui::VKEY_RIGHT;
} else if (str == "home") {
return ui::VKEY_HOME;
} else if (str == "end") {
return ui::VKEY_END;
} else if (str == "pageup") {
return ui::VKEY_PRIOR;
} else if (str == "pagedown") {
return ui::VKEY_NEXT;
} else if (str == "esc" || str == "escape") {
return ui::VKEY_ESCAPE;
} else if (str == "volumemute") {
return ui::VKEY_VOLUME_MUTE;
} else if (str == "volumeup") {
return ui::VKEY_VOLUME_UP;
} else if (str == "volumedown") {
return ui::VKEY_VOLUME_DOWN;
} else if (str == "medianexttrack") {
return ui::VKEY_MEDIA_NEXT_TRACK;
} else if (str == "mediaprevioustrack") {
return ui::VKEY_MEDIA_PREV_TRACK;
} else if (str == "mediastop") {
return ui::VKEY_MEDIA_STOP;
} else if (str == "mediaplaypause") {
return ui::VKEY_MEDIA_PLAY_PAUSE;
} else if (str == "printscreen") {
return ui::VKEY_SNAPSHOT;
} else if (str.size() > 1 && str[0] == 'f') {
// F1 - F24.
int n;
if (base::StringToInt(str.c_str() + 1, &n) && n > 0 && n < 25) {
return static_cast<ui::KeyboardCode>(ui::VKEY_F1 + n - 1);
} else {
LOG(WARNING) << str << "is not available on keyboard";
return ui::VKEY_UNKNOWN;
}
} else {
LOG(WARNING) << "Invalid accelerator token: " << str;
return ui::VKEY_UNKNOWN;
}
}
return ui::VKEY_UNKNOWN;
} // namespace
ui::KeyboardCode KeyboardCodeFromStr(const std::string& str, bool* shifted) {
if (str.size() == 1)
return KeyboardCodeFromCharCode(str[0], shifted);
else
return KeyboardCodeFromKeyIdentifier(str, shifted);
}
} // namespace atom

View File

@@ -6,17 +6,14 @@
#define ATOM_COMMON_KEYBOARD_UTIL_H_
#include <string>
#include "ui/events/keycodes/keyboard_codes.h"
#include "base/strings/string_util.h"
namespace atom {
// Return key code of the char, and also determine whether the SHIFT key is
// Return key code of the |str|, and also determine whether the SHIFT key is
// pressed.
ui::KeyboardCode KeyboardCodeFromCharCode(base::char16 c, bool* shifted);
// Return key code of the char from a string representation of the char
ui::KeyboardCode KeyboardCodeFromKeyIdentifier(const std::string& chr);
ui::KeyboardCode KeyboardCodeFromStr(const std::string& str, bool* shifted);
} // namespace atom

View File

@@ -159,25 +159,22 @@ bool Converter<blink::WebKeyboardEvent>::FromV8(
return false;
if (!ConvertFromV8(isolate, val, static_cast<blink::WebInputEvent*>(out)))
return false;
base::char16 code;
std::string identifier;
bool shifted = false;
if (dict.Get("keyCode", &code))
out->windowsKeyCode = atom::KeyboardCodeFromCharCode(code, &shifted);
else if (dict.Get("keyCode", &identifier))
out->windowsKeyCode = atom::KeyboardCodeFromKeyIdentifier(
base::ToLowerASCII(identifier));
std::string str;
bool shifted = false;
if (dict.Get("keyCode", &str))
out->windowsKeyCode = atom::KeyboardCodeFromStr(str, &shifted);
else
return false;
if (shifted)
out->modifiers |= blink::WebInputEvent::ShiftKey;
out->setKeyIdentifierFromWindowsKeyCode();
if (out->type == blink::WebInputEvent::Char ||
out->type == blink::WebInputEvent::RawKeyDown) {
out->text[0] = code;
out->unmodifiedText[0] = code;
if ((out->type == blink::WebInputEvent::Char ||
out->type == blink::WebInputEvent::RawKeyDown) &&
str.size() == 1) {
out->text[0] = str[0];
out->unmodifiedText[0] = str[0];
}
return true;
}

View File

@@ -173,6 +173,8 @@ bool Converter<content::StopFindAction>::FromV8(
// static
v8::Local<v8::Value> Converter<content::WebContents*>::ToV8(
v8::Isolate* isolate, content::WebContents* val) {
if (!val)
return v8::Null(isolate);
return atom::api::WebContents::CreateFrom(isolate, val).ToV8();
}

View File

@@ -27,7 +27,9 @@ v8::Local<v8::Value> Converter<const net::URLRequest*>::ToV8(
v8::Isolate* isolate, const net::URLRequest* val) {
scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
dict->SetString("method", val->method());
dict->SetStringWithoutPathExpansion("url", val->url().spec());
std::string url;
if (!val->url_chain().empty()) url = val->url().spec();
dict->SetStringWithoutPathExpansion("url", url);
dict->SetString("referrer", val->referrer());
scoped_ptr<base::ListValue> list(new base::ListValue);
atom::GetUploadData(list.get(), val);

View File

@@ -76,15 +76,10 @@ class V8ValueConverter::FromV8ValueState {
};
V8ValueConverter::V8ValueConverter()
: date_allowed_(false),
reg_exp_allowed_(false),
: reg_exp_allowed_(false),
function_allowed_(false),
strip_null_from_objects_(false) {}
void V8ValueConverter::SetDateAllowed(bool val) {
date_allowed_ = val;
}
void V8ValueConverter::SetRegExpAllowed(bool val) {
reg_exp_allowed_ = val;
}
@@ -243,12 +238,17 @@ base::Value* V8ValueConverter::FromV8ValueImpl(
return NULL;
if (val->IsDate()) {
if (!date_allowed_)
// JSON.stringify would convert this to a string, but an object is more
// consistent within this class.
return FromV8Object(val->ToObject(), state, isolate);
v8::Date* date = v8::Date::Cast(*val);
return new base::FundamentalValue(date->NumberValue() / 1000.0);
v8::Local<v8::Value> toISOString =
date->Get(v8::String::NewFromUtf8(isolate, "toISOString"));
if (toISOString->IsFunction()) {
v8::Local<v8::Value> result =
toISOString.As<v8::Function>()->Call(val, 0, nullptr);
if (!result.IsEmpty()) {
v8::String::Utf8Value utf8(result->ToString());
return new base::StringValue(std::string(*utf8, utf8.length()));
}
}
}
if (val->IsRegExp()) {

View File

@@ -22,7 +22,6 @@ class V8ValueConverter {
public:
V8ValueConverter();
void SetDateAllowed(bool val);
void SetRegExpAllowed(bool val);
void SetFunctionAllowed(bool val);
void SetStripNullFromObjects(bool val);
@@ -58,9 +57,6 @@ class V8ValueConverter {
FromV8ValueState* state,
v8::Isolate* isolate) const;
// If true, we will convert Date JavaScript objects to doubles.
bool date_allowed_;
// If true, we will convert RegExp JavaScript objects to string.
bool reg_exp_allowed_;

View File

@@ -165,7 +165,6 @@ node::Environment* NodeBindings::CreateEnvironment(
base::FilePath script_path =
resources_path.Append(FILE_PATH_LITERAL("atom.asar"))
.Append(process_type)
.Append(FILE_PATH_LITERAL("lib"))
.Append(FILE_PATH_LITERAL("init.js"));
std::string script_path_str = script_path.AsUTF8Unsafe();
args.insert(args.begin() + 1, script_path_str.c_str());

View File

@@ -15,7 +15,7 @@
#include "native_mate/object_template_builder.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
#include "third_party/WebKit/public/web/WebScriptExecutionCallback.h"
#include "third_party/WebKit/public/web/WebScriptSource.h"
#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
#include "third_party/WebKit/public/web/WebView.h"
@@ -26,6 +26,34 @@ namespace atom {
namespace api {
namespace {
class ScriptExecutionCallback : public blink::WebScriptExecutionCallback {
public:
using CompletionCallback =
base::Callback<void(
const v8::Local<v8::Value>& result)>;
explicit ScriptExecutionCallback(const CompletionCallback& callback)
: callback_(callback) {}
~ScriptExecutionCallback() {}
void completed(
const blink::WebVector<v8::Local<v8::Value>>& result) override {
if (!callback_.is_null() && !result.isEmpty() && !result[0].IsEmpty())
// Right now only single results per frame is supported.
callback_.Run(result[0]);
delete this;
}
private:
CompletionCallback callback_;
DISALLOW_COPY_AND_ASSIGN(ScriptExecutionCallback);
};
} // namespace
WebFrame::WebFrame()
: web_frame_(blink::WebLocalFrame::frameForCurrentContext()) {
}
@@ -124,9 +152,14 @@ void WebFrame::ExecuteJavaScript(const base::string16& code,
mate::Arguments* args) {
bool has_user_gesture = false;
args->GetNext(&has_user_gesture);
scoped_ptr<blink::WebScopedUserGesture> gesture(
has_user_gesture ? new blink::WebScopedUserGesture : nullptr);
web_frame_->executeScriptAndReturnValue(blink::WebScriptSource(code));
ScriptExecutionCallback::CompletionCallback completion_callback;
args->GetNext(&completion_callback);
scoped_ptr<blink::WebScriptExecutionCallback> callback(
new ScriptExecutionCallback(completion_callback));
web_frame_->requestExecuteScriptAndReturnValue(
blink::WebScriptSource(code),
has_user_gesture,
callback.release());
}
mate::ObjectTemplateBuilder WebFrame::GetObjectTemplateBuilder(

View File

@@ -32,7 +32,7 @@ enum NotificationType {
NOTIFICATION_BROWSER_CLOSING,
// This message is sent after a window has been closed. The source is a
// Source<Browser> containing the affected Browser. No details are exptected.
// Source<Browser> containing the affected Browser. No details are expected.
NOTIFICATION_BROWSER_CLOSED,
// This message is sent when closing a browser has been cancelled, either by
@@ -411,7 +411,7 @@ enum NotificationType {
// the source is a Profile.
NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
// An error occured while attempting to load an extension. The details are a
// An error occurred while attempting to load an extension. The details are a
// string with details about why the load failed.
NOTIFICATION_EXTENSION_LOAD_ERROR,
@@ -434,7 +434,7 @@ enum NotificationType {
// The details are an InstalledExtensionInfo, and the source is a Profile.
NOTIFICATION_EXTENSION_INSTALLED,
// An error occured during extension install. The details are a string with
// An error occurred during extension install. The details are a string with
// details about why the install failed.
NOTIFICATION_EXTENSION_INSTALL_ERROR,
@@ -625,7 +625,7 @@ enum NotificationType {
// TabSpecificContentSettings object, there are no details.
NOTIFICATION_COLLECTED_COOKIES_SHOWN,
// Sent when a non-default setting in the the notification content settings
// Sent when a non-default setting in the notification content settings
// map has changed. The source is the DesktopNotificationService, the
// details are None.
NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED,
@@ -776,7 +776,7 @@ enum NotificationType {
NOTIFICATION_USER_LIST_CHANGED,
// Sent when the screen lock state has changed. The source is
// ScreenLocker and the details is a bool specifing that the
// ScreenLocker and the details is a bool specifying that the
// screen is locked. When details is a false, the source object
// is being deleted, so the receiver shouldn't use the screen locker
// object.
@@ -838,7 +838,7 @@ enum NotificationType {
// which was installed.
NOTIFICATION_APP_INSTALLED_TO_NTP,
// Similar to NOTIFICATION_APP_INSTALLED_TO_NTP but used to nofity ash AppList
// Similar to NOTIFICATION_APP_INSTALLED_TO_NTP but used to notify ash AppList
// about installed app. Source is the profile in which the app is installed
// and Details is the string ID of the extension.
NOTIFICATION_APP_INSTALLED_TO_APPLIST,

View File

@@ -3,6 +3,7 @@
そうでない場合、おそらくご使用の Electron のバージョンと互換性のない API 変更を含んだ development ブランチのドキュメントを使っているものと思われます。
その場合、atom.io の [available versions](http://electron.atom.io/docs/) リストにある別のバージョンのドキュメントに切り替えることができます。また GitHub で閲覧している場合、"Switch branches/tags" ドロップダウンを開いて、バージョンに対応したタグを選ぶこともできます。
_リンクになっていないリストは未翻訳のものです。_
## FAQ
頻繁に聞かれる質問がありますので、issueを作成する前にこれをチェックしてください。
@@ -31,3 +32,57 @@
## API リファレンス
* [概要](api/synopsis.md)
* [Process Object](api/process.md)
* [サポートしているChromeコマンドラインスイッチ](api/chrome-command-line-switches.md)
* [環境変数](api/environment-variables.md)
### カスタムDOM要素:
* [`File` Object](api/file-object.md)
* `<webview>` Tag
* [`window.open` 関数](api/window-open.md)
### Main Processのモジュール:
* [app](api/app.md)
* [autoUpdater](api/auto-updater.md)
* BrowserWindow
* [フレームの無いウィンドウ](api/frameless-window.md)
* [contentTracing](api/content-tracing.md)
* [dialog](api/dialog.md)
* [globalShortcut](api/global-shortcut.md)
* [ipcMain](api/ipc-main.md)
* [Menu](api/menu.md)
* [MenuItem](api/menu-item.md)
* [powerMonitor](api/power-monitor.md)
* [powerSaveBlocker](api/power-save-blocker.md)
* [protocol](api/protocol.md)
* [session](api/session.md)
* webContents
* [Tray](api/tray.md)
### Renderer Processのモジュール (Web Page):
* [desktopCapturer](api/desktop-capturer.md)
* [ipcRenderer](api/ipc-renderer.md)
* [remote](api/remote.md)
* [webFrame](api/web-frame.md)
### 両方のProcessのモジュール :
* [clipboard](api/clipboard.md)
* [crashReporter](api/crash-reporter.md)
* [nativeImage](api/native-image.md)
* [screen](api/screen.md)
* [shell](api/shell.md)
## 開発
* Coding Style
* Source Code Directory Structure
* Technical Differences to NW.js (formerly node-webkit)
* Build System Overview
* Build Instructions (OS X)
* Build Instructions (Windows)
* Build Instructions (Linux)
* Setting Up Symbol Server in debugger

View File

@@ -378,6 +378,7 @@ if (browserOptions.transparent) {
// No transparency, so we load a fallback that uses basic styles.
win.loadURL('file://' + __dirname + '/fallback.html');
}
```
### `app.commandLine.appendSwitch(switch[, value])`

View File

@@ -52,7 +52,7 @@
* `channel` String - イベント名
* `arg` (optional)
`channel`経由でメインプロセスに同期にイベントを送信し、任意の引数を送信できます。
`channel`経由でメインプロセスに同期にイベントを送信し、任意の引数を送信できます。
メインプロセスは`ipcMain``channel`を受信することでハンドルし、 `event.returnValue`を設定してリプライします。

View File

@@ -135,7 +135,7 @@ var template = [
];
if (process.platform == 'darwin') {
var name = require('electron').app.getName();
var name = require('electron').remote.app.getName();
template.unshift({
label: name,
submenu: [

View File

@@ -12,6 +12,27 @@ Node.js の新しいバージョンがリリースされたとき、私たちは
通常、Node.js の新しい機能は V8 のアップグレードによってもたらされますが、Electron は Chrome ブラウザーに搭載されている V8 を使用しているので、新しい Node.js に入ったばかりのピカピカに新しい JavaScript 機能は Electron ではたいてい既に導入されています。
## ウェブページ間のデータを共有する方法は?
ウェブページレンダラープロセス間のデータを共有するために最も単純な方法は、ブラウザで、すでに提供されているHTML5 APIを使用することです。もっとも良い方法は、[Storage API][storage]、[`localStorage`][local-storage]、[`sessionStorage`][session-storage]、[IndexedDB][indexed-db]です。
```javascript
// In the main process.
global.sharedObject = {
someProperty: 'default value'
};
```
```javascript
// In page 1.
require('remote').getGlobal('sharedObject').someProperty = 'new value';
```
```javascript
// In page 2.
console.log(require('remote').getGlobal('sharedObject').someProperty);
```
## 何分か経つと、アプリの Window/tray が消えてしまいます
これは、Window/trayを格納するのに使用している変数がガベージコレクトされたときに発生します。
@@ -104,3 +125,7 @@ npm uninstall -g electron
[memory-management]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management
[variable-scope]: https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx
[electron-module]: https://www.npmjs.com/package/electron
[storage]: https://developer.mozilla.org/en-US/docs/Web/API/Storage
[local-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
[session-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage
[indexed-db]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API

View File

@@ -210,6 +210,23 @@ var window = new BrowserWindow({...});
window.setProgressBar(0.5);
```
## タスクバーでアイコンをオーバーレイする (Windows)
Windowsで、タスクバーボタンはアプリケーションステータスを表示するために小さなオーバーレイを使うことができます。MSDNから引用します。
> アイコン オーバーレイは、状況に応じた状態通知として機能し、通知領域に状態アイコンを個別に表示する必要性をなくして、情報をユーザーに伝えることを目的としています。たとえば、現在、通知領域に表示される Microsoft Office Outlook の新着メールの通知は、タスク バー ボタンのオーバーレイとして表示できるようになります。ここでも、開発サイクルの間に、アプリケーションに最適な方法を決定する必要があります。アイコン オーバーレイは、重要で長期にわたる状態や通知 (ネットワークの状態、メッセンジャーの状態、新着メールなど) を提供することを目的としています。ユーザーに対して、絶えず変化するオーバーレイやアニメーションを表示しないようにしてください。
__タスクバーボタンでのオーバーレイ:__
![Overlay on taskbar button](https://i-msdn.sec.s-msft.com/dynimg/IC420441.png)
ウィンドウでオーバーレイアイコンを設定するために、[BrowserWindow.setOverlayIcon][setoverlayicon] APIを使用できます。
```javascript
var window = new BrowserWindow({...});
window.setOverlayIcon('path/to/overlay.png', 'Description for overlay');
```
## Windowのファイル表示 (OS X)
OS Xでは、ウィンドウがrepresented fileを設定でき、タイトルバー上にファイルのアイコンを表示でき、タイトル上でCommand-クリックまたはControl-クリックをすると、パスがポップアップ表示されます。
@@ -228,15 +245,16 @@ window.setRepresentedFilename('/etc/passwd');
window.setDocumentEdited(true);
```
[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath
[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments
[setusertaskstasks]: ../api/app.md#appsetusertaskstasks
[setprogressbar]: ../api/browser-window.md#browserwindowsetprogressbarprogress
[setrepresentedfilename]: ../api/browser-window.md#browserwindowsetrepresentedfilenamefilename
[setdocumentedited]: ../api/browser-window.md#browserwindowsetdocumenteditededited
[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath-os-x-windows
[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments-os-x-windows
[setusertaskstasks]: ../api/app.md#appsetusertaskstasks-windows
[setprogressbar]: ../api/browser-window.md#winsetprogressbarprogress
[setoverlayicon]: ../api/browser-window.md#winsetoverlayiconoverlay-description-windows-7
[setrepresentedfilename]: ../api/browser-window.md#winsetrepresentedfilenamefilename-os-x
[setdocumentedited]: ../api/browser-window.md#winsetdocumenteditededited-os-x
[app-registration]: http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121(v=vs.85).aspx
[unity-launcher]: https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher
[setthumbarbuttons]: ../api/browser-window.md#browserwindowsetthumbarbuttonsbuttons
[setthumbarbuttons]: ../api/browser-window.md#winsetthumbarbuttonsbuttons-windows-7
[tray-balloon]: ../api/tray.md#traydisplayballoonoptions-windows
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx
[notification-spec]: https://developer.gnome.org/notification-spec/

View File

@@ -24,6 +24,8 @@ Electron はウェブページを表示させるために Chromium を使用し
Electron では、メインプロセスとレンダラープロセスとのコミュニケーションをするために [ipc](../api/ipc-renderer.md) モジュールを提供しています。またそれと、RPC 形式の通信を行う [remote](../api/remote.md) モジュールもあります。
Electron では、メインプロセスとレンダラープロセスとのコミュニケーションをするには幾つかのほうほうがあります。メッセージを送信する[`ipcRenderer`](../api/ipc-renderer.md)モジュールと[`ipcMain`](../api/ipc-main.md)モジュールのように、RPC 形式の通信を行う[remote](../api/remote.md)モジュールです。[ウェブページ間のデータを共有する方法][share-data]にFAQエントリーがあります。
## Electronアプリを作成する
一般的に Electron アプリの構成は次のようになります:
@@ -169,3 +171,5 @@ $ cd electron-quick-start
# Install dependencies and run the app
$ npm install && npm start
```
[share-data]: ../faq/electron-faq.md#how-to-share-data-between-web-pages

View File

@@ -41,7 +41,7 @@ var driver = new webdriver.Builder()
.withCapabilities({
chromeOptions: {
// Here is the path to your Electron binary.
binary: '/Path-to-Your-App.app/Contents/MacOS/Atom',
binary: '/Path-to-Your-App.app/Contents/MacOS/Electron',
}
})
.forBrowser('electron')

View File

@@ -6,6 +6,8 @@ Electronで、Chromeブラウザーに同梱される Widevine CDMプラグイ
Electronは、ライセンス的な理由でWidevine CDMプラグインは同梱されません。Widevine CDMプラグインを取得するために、最初に、使用するElectronビルドのChromバージョンとアーキテクチャを合わせた公式のChromeブラウザーをインストールする必要があります。
__Note:__ Chromeブラウザの主要バージョンは、Electronが使用するChromeバージョンと同じでなければなりません。そうでなければ、プラグインは、`navigator.plugins`経由でロードされて表示されるにも関わらず動作しません。
### Windows & OS X
Chromeブラウザーで、`chrome://components/`を開き、 `WidevineCdm` を探し、それが最新であることを確認し、`APP_DATA/Google/Chrome/WidevineCDM/VERSION/_platform_specific/PLATFORM_ARCH/`ディレクトリからすべてのプラグインバイナリを探します。

View File

@@ -30,6 +30,7 @@ Electron에 대해 자주 묻는 질문이 있습니다. 이슈를 생성하기
* [개발자 도구 확장 기능](tutorial/devtools-extension.md)
* [Pepper 플래시 플러그인 사용하기](tutorial/using-pepper-flash-plugin.md)
* [Widevine CDM 플러그인 사용하기](tutorial/using-widevine-cdm-plugin.md)
* [Headless CI 시스템에서 테스팅하기 (Travis, Jenkins)](tutorial/testing-on-headless-ci.md)
## 튜토리얼

View File

@@ -22,6 +22,8 @@ Linux와 Windows에서는 `Command`키가 없으므로 작동하지 않습니다
* `Control` (단축어 `Ctrl`)
* `CommandOrControl` (단축어 `CmdOrCtrl`)
* `Alt`
* `Option`
* `AltGr`
* `Shift`
* `Super`
@@ -43,5 +45,6 @@ Linux와 Windows에서는 `Command`키가 없으므로 작동하지 않습니다
* `Escape` (단축어 `Esc`)
* `VolumeUp`, `VolumeDown` 그리고 `VolumeMute`
* `MediaNextTrack`, `MediaPreviousTrack`, `MediaStop` 그리고 `MediaPlayPause`
* `PrintScreen`
__키코드는 `단축어`로도 사용할 수 있습니다__

View File

@@ -164,7 +164,7 @@ Returns:
기본 동작을 방지하고 인증을 승인할 수 있습니다.
```javascript
session.on('certificate-error', function(event, webContents, url, error, certificate, callback) {
app.on('certificate-error', function(event, webContents, url, error, certificate, callback) {
if (url == "https://github.com") {
// Verification logic.
event.preventDefault();
@@ -236,6 +236,10 @@ app.on('login', function(event, webContents, request, authInfo, callback) {
GPU가 작동하던 중 크래시가 일어났을 때 발생하는 이벤트입니다.
### Event: 'platform-theme-changed' _OS X_
시스템의 다크 모드 테마가 토글되면 발생하는 이벤트입니다.
## Methods
`app` 객체는 다음과 같은 메서드를 가지고 있습니다:
@@ -252,14 +256,6 @@ GPU가 작동하던 중 크래시가 일어났을 때 발생하는 이벤트입
`beforeunload` 이벤트 핸들러에서 `false`를 반환했을 때 윈도우 종료가 취소 될 수
있습니다.
### `app.hide()` _OS X_
최소화를 하지 않고 어플리케이션의 모든 윈도우들을 숨깁니다.
### `app.show()` _OS X_
숨긴 어플리케이션 윈도우들을 다시 보이게 만듭니다. 자동으로 포커스되지 않습니다.
### `app.exit(exitCode)`
* `exitCode` Integer
@@ -269,6 +265,19 @@ GPU가 작동하던 중 크래시가 일어났을 때 발생하는 이벤트입
모든 윈도우는 사용자의 동의 여부에 상관없이 즉시 종료되며 `before-quit` 이벤트와
`will-quit` 이벤트가 발생하지 않습니다.
### `app.focus()`
Linux에선, 첫 번째로 보여지는 윈도우가 포커스됩니다. OS X에선, 어플리케이션을 활성화
앱 상태로 만듭니다. Windows에선, 어플리케이션의 첫 윈도우에 포커스 됩니다.
### `app.hide()` _OS X_
최소화를 하지 않고 어플리케이션의 모든 윈도우들을 숨깁니다.
### `app.show()` _OS X_
숨긴 어플리케이션 윈도우들을 다시 보이게 만듭니다. 자동으로 포커스되지 않습니다.
### `app.getAppPath()`
현재 어플리케이션의 디렉터리를 반환합니다.
@@ -471,6 +480,11 @@ if (browserOptions.transparent) {
}
```
### `app.isDarkMode()` _OS X_
이 메서드는 시스템이 다크 모드 상태인 경우 `true`를 반환하고 아닐 경우 `false`
반환합니다.
### `app.commandLine.appendSwitch(switch[, value])`
Chrominum의 명령줄에 스위치를 추가합니다. `value`는 추가적인 값을 뜻하며 옵션입니다.

View File

@@ -59,8 +59,8 @@ win.show();
* `alwaysOnTop` Boolean - 윈도우이 언제나 다른 창들 위에 유지되는지 여부.
기본값은 `false`입니다.
* `fullscreen` Boolean - 윈도우의 전체화면 활성화 여부. 이 속성을 명시적으로
`false`로 지정했을 경우, OS X에선 전체화면 버튼이 숨겨지거나 비활성화되고,
Windows에선 최대화 버튼이 비활성화됩니다. 기본값은 `false` 입니다.
`false`로 지정했을 경우, OS X에선 전체화면 버튼이 숨겨지거나 비활성됩니다. 기본값은
`false` 입니다.
* `fullscreenable` Boolean - OS X의 최대화/줌 버튼이 전체화면 모드 또는 윈도우
최대화를 토글할 수 있게 할지 여부입니다. 기본값은 `true` 입니다.
* `skipTaskbar` Boolean - 작업표시줄 어플리케이션 아이콘 표시 스킵 여부. 기본값은
@@ -240,6 +240,14 @@ window.onbeforeunload = function(e) {
윈도우가 포커스를 가졌을 때 발생하는 이벤트입니다.
### Event: 'show'
윈도우가 보여진 상태일 때 발생하는 이벤트입니다.
### Event: 'hide'
윈도우가 숨겨진 상태일 때 발생하는 이벤트입니다.
### Event: 'maximize'
윈도우가 최대화됐을 때 발생하는 이벤트입니다.
@@ -575,17 +583,17 @@ var win = new BrowserWindow({ width: 800, height: 600 });
사용자에 의해 윈도우를 최대화시킬 수 있는지 여부를 반환합니다. Linux에선 항상 `true`
반환합니다.
### `win.setFullScreenable(fullscreenable)` _OS X_
### `win.setFullScreenable(fullscreenable)`
* `fullscreenable` Boolean
최대화/줌 버튼이 전체화면 모드 또는 윈도우 최대화를 토글할 수 있게 할지 여부를
지정합니다. Windows와 Linux에선 아무 일도 일어나지 않습니다.
지정합니다.
### `win.isFullScreenable()` _OS X_
### `win.isFullScreenable()`
최대화/줌 버튼이 전체화면 모드 또는 윈도우 최대화를 토글할 수 있게 할지 여부를
반환합니다. Windows와 Linux에선 항상 `true`반환합니다.
반환합니다.
### `win.setClosable(closable)` _OS X_ _Windows_

View File

@@ -140,7 +140,7 @@ var template = [
];
if (process.platform == 'darwin') {
var name = require('electron').app.getName();
var name = require('electron').remote.app.getName();
template.unshift({
label: name,
submenu: [
@@ -223,7 +223,9 @@ Linux에선 각 창의 상단에 표시됩니다.
`action`을 어플리케이션의 first responder에 전달합니다. 이 메서드는 Cocoa 메뉴
동작을 에뮬레이트 하는데 사용되며 보통 `MenuItem``role` 속성에 사용됩니다.
**참고:** 이 메서드는 OS X에서만 사용할 수 있습니다.
OS X의 네이티브 액션에 대해 자세히 알아보려면
[OS X Cocoa Event Handling Guide](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/EventOverview/EventArchitecture/EventArchitecture.html#//apple_ref/doc/uid/10000060i-CH3-SW7)
문서를 참고하세요.
### `Menu.buildFromTemplate(template)`

View File

@@ -49,7 +49,7 @@ app.on('ready', function() {
## 분리 할당
만약 CoffeeScript나 Babel을 사용하고 있다면, 빌트인 모듈을 사용할 때
[분리 할당][desctructuring-assignment]을 통해 직관적으로 사용할 수 있습니다:
[분리 할당][destructuring-assignment]을 통해 직관적으로 사용할 수 있습니다:
```javascript
const {app, BrowserWindow} = require('electron')
@@ -78,5 +78,5 @@ require('electron').hideInternalModules()
```
[gui]: https://en.wikipedia.org/wiki/Graphical_user_interface
[desctructuring-assignment]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
[destructuring-assignment]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
[issue-387]: https://github.com/atom/electron/issues/387

View File

@@ -421,10 +421,12 @@ var currentURL = win.webContents.getURL();
CSS 코드를 현재 웹 페이지에 삽입합니다.
### `webContents.executeJavaScript(code[, userGesture])`
### `webContents.executeJavaScript(code[, userGesture, callback])`
* `code` String
* `userGesture` Boolean (optional)
* `callback` Function (optional) - 스크립트의 실행이 완료되면 호출됩니다.
* `result`
페이지에서 자바스크립트 코드를 실행합니다.
@@ -646,14 +648,14 @@ mainWindow.webContents.on('devtools-opened', function() {
개발자 도구가 열려있는지 여부를 반환합니다.
### `webContents.toggleDevTools()`
개발자 도구를 토글합니다.
### `webContents.isDevToolsFocused()`
개발자 도구에 포커스 되어있는지 여부를 반환합니다.
### `webContents.toggleDevTools()`
개발자 도구를 토글합니다.
### `webContents.inspectElement(x, y)`
* `x` Integer
@@ -756,11 +758,8 @@ Input `event`를 웹 페이지로 전송합니다.
키보드 이벤트들에 대해서는 `event` 객체는 다음 속성들을 사용할 수 있습니다:
* `keyCode` Char or String (**required**) - 키보드 이벤트 보내지는 문자. 단일
UTF-8 문자를 사용할 수 있고 이벤트를 발생시키는 다음 키 중 하나를 포함할 수 있습니다:
`enter`, `backspace`, `delete`, `tab`, `escape`, `control`, `alt`, `shift`,
`end`, `home`, `insert`, `left`, `up`, `right`, `down`, `pageUp`, `pageDown`,
`printScreen`
* `keyCode` String (**required**) - 키보드 이벤트가 발생할 때 보내 문자.
[Accelerator](accelerator.md)의 올바른 키 코드만 사용해야 합니다.
마우스 이벤트들에 대해서는 `event` 객체는 다음 속성들을 사용할 수 있습니다:
@@ -832,6 +831,10 @@ win.webContents.on('did-finish-load', function() {
이 webContents에서 사용하는 [session](session.md) 객체를 반환합니다.
### `webContents.hostWebContents`
현재 `WebContents`를 소유하는 `WebContents`를 반환합니다.
### `webContents.devToolsWebContents`
`WebContents`에 대한 개발자 도구의 `WebContents`를 가져옵니다.

View File

@@ -272,12 +272,14 @@ Webview에 웹 페이지 `url`을 로드합니다. `url`은 `http://`, `file://`
페이지에 CSS를 삽입합니다.
### `<webview>.executeJavaScript(code[, userGesture])`
### `<webview>.executeJavaScript(code[, userGesture, callback])`
* `code` String
* `userGesture` Boolean
* `callback` Function (optional) - 스크립트의 실행이 완료되면 호출됩니다.
* `result`
페이지에서 자바스크립트 `code`를 실행합니다.
페이지에서 자바스크립트 코드를 실행합니다.
만약 `userGesture``true`로 설정되어 있으면 페이지에 유저 제스쳐 컨텍스트를 만듭니다.
이 옵션을 활성화 시키면 `requestFullScreen`와 같은 HTML API에서 유저의 승인을
@@ -427,6 +429,10 @@ Webview 페이지를 PDF 형식으로 인쇄합니다.
`event` 객체에 대해 자세히 알아보려면 [webContents.sendInputEvent](web-contents.md##webcontentssendinputeventevent)를
참고하세요.
### `<webview>.getWebContents()`
`webview`에 해당하는 [WebContents](web-contents.md)를 반환합니다.
## DOM 이벤트
`webview` 태그는 다음과 같은 DOM 이벤트를 가지고 있습니다:

View File

@@ -2,6 +2,9 @@
이 가이드는 Electron의 코딩 스타일에 관해 설명합니다.
`npm run lint`를 실행하여 `cpplint``eslint`를 통해 어떤 코딩 스타일 이슈를 확인할
수 있습니다.
## C++과 Python
C++과 Python 스크립트는 Chromium의
@@ -18,17 +21,24 @@ C++ 코드는 많은 Chromium의 추상화와 타입을 사용합니다. 따라
자동으로 메모리에서 할당을 해제합니다. 스마트 포인터와 같습니다) 그리고 로깅 메커니즘
등을 언급하고 있습니다.
## CoffeeScript
CoffeeScript의 경우 GitHub의
[스타일 가이드](https://github.com/styleguide/javascript)를 기본으로 따릅니다.
그리고 추가로 다음 규칙을 따릅니다:
## JavaScript
* 하드 탭(hard tabs) 대신 소프트 탭(2 spaces) 들여쓰기를 사용합니다.
* 항상 구문의 끝은 `;`으로 마쳐야 합니다.
* Google의 코딩 스타일에도 맞추기 위해 파일의 끝에는 **절대** 개행을 삽입해선 안됩니다.
* 파일 이름의 공백은 `_`대신에 `-`을 사용하여야 합니다. 예를 들어
`file_name.coffee``file-name.coffee`로 고쳐야합니다. 왜냐하면
`file_name.js``file-name.js`로 고쳐야합니다. 왜냐하면
[github/atom](https://github.com/github/atom)에서 사용되는 모듈의 이름은 보통
`module-name` 형식이기 때문입니다. 이 규칙은 '.coffee' 파일에만 적용됩니다.
`module-name` 형식이기 때문입니다. 이 규칙은 '.js' 파일에만 적용됩니다.
* 적절한 곳에 새로운 ES6/ES2015 문법을 사용해도 됩니다.
* [`const`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const)
는 requires와 다른 상수에 사용합니다
* [`let`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let)
은 변수를 정의할 때 사용합니다
* [Arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
`function () { }` 표현 대신에 사용합니다
* [Template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals)
`+`로 문자열을 합치는 대신 사용합니다.
## API 이름

View File

@@ -239,22 +239,20 @@ __Audacious의 런처 숏컷:__
![audacious](https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles?action=AttachFile&do=get&target=shortcuts.png)
## Taskbar progress 기능 (Windows & Unity)
## 작업 표시줄 안의 프로그래스 바 (Windows, OS X, Unity)
Windows에선 태스크바의 어플리케이션 버튼에 progress bar를 추가할 수 있습니다.
Windows에선 작업 표시줄의 어플리케이션 버튼에 프로그래스 바를 추가할 수 있습니다.
이 기능은 사용자가 어플리케이션의 창을 열지 않고도 어플리케이션의 작업의 상태 정보를
시각적으로 보여줄 수 있도록 해줍니다.
또한 Unity DE도 런처에 progress bar를 부착할 수 있습니다.
OS X에선 프로그래스바가 dock 아이콘의 일부에 표시됩니다.
__태스크바 버튼의 progress bar:__
또한 Unity DE도 런처에 프로그래스 바를 부착할 수 있습니다.
__작업 표시줄 버튼의 프로그래스 바:__
![Taskbar Progress Bar](https://cloud.githubusercontent.com/assets/639601/5081682/16691fda-6f0e-11e4-9676-49b6418f1264.png)
__Unity 런처의 progress bar:__
![Unity Launcher](https://cloud.githubusercontent.com/assets/639601/5081747/4a0a589e-6f0f-11e4-803f-91594716a546.png)
이 기능은 [BrowserWindow.setProgressBar][setprogressbar] API를 사용하여 구현할 수
있습니다:

View File

@@ -0,0 +1,58 @@
# Headless CI 시스템에서 테스팅하기 (Travis, Jenkins) (Travis CI, Jenkins)
Chromium을 기반으로 한 Electron은 작업을 위해 디스플레이 드라이버가 필요합니다.
만약 Chromium이 디스플레이 드라이버를 찾기 못한다면, Electron은 그대로 실행에
실패할 것입니다. 따라서 실행하는 방법에 관계없이 모든 테스트를 실행하지 못하게 됩니다.
Electron 기반 어플리케이션을 Travis, Circle, Jenkins 또는 유사한 시스템에서 테스팅을
진행하려면 약간의 설정이 필요합니다. 요점만 말하자면, 가상 디스플레이 드라이버가
필요합니다.
## 가상 디스플레이 드라이버 설정
먼저, [Xvfb](https://en.wikipedia.org/wiki/Xvfb)를 설치합니다. 이것은 X11
디스플레이 서버 프로토콜의 구현이며 모든 그래픽 작업을 스크린 출력없이 인-메모리에서
수행하는 가상 프레임버퍼입니다. 정확히 우리가 필요로 하는 것입니다.
그리고, 가상 xvfb 스크린을 생성하고 DISPLAY라고 불리우는 환경 변수를 지정합니다.
Electron의 Chromium은 자동적으로 `$DISPLAY` 변수를 찾습니다. 따라서 앱의 추가적인
다른 설정이 필요하지 않습니다. 이러한 작업은 Paul Betts의
[xfvb-maybe](https://github.com/paulcbetts/xvfb-maybe)를 통해 자동화 할 수
있습니다: `xfvb-maybe`를 테스트 커맨드 앞에 추가하고 현재 시스템에서 요구하면
이 작은 툴이 자동적으로 xfvb를 설정합니다. Windows와 Mac OS X에선 간단히 아무 작업도
하지 않습니다.
```
## Windows와 OS X에선, 그저 electron-mocha를 호출합니다
## Linux에선, 현재 headless 환경에 있는 경우
## xvfb-run electron-mocha ./test/*.js와 같습니다
xvfb-maybe electron-mocha ./test/*.js
```
### Travis CI
Travis에선, `.travis.yml`이 대충 다음과 같이 되어야 합니다:
```
addons:
apt:
packages:
- xvfb
install:
- export DISPLAY=':99.0'
- Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
```
### Jenkins
Jenkins는 [Xfvb 플러그인이 존재합니다](https://wiki.jenkins-ci.org/display/JENKINS/Xvfb+Plugin).
### Circle CI
Circle CI는 멋지게도 이미 xvfb와 `$DISPLY` 변수가 준비되어 있습니다. 따라서
[추가적인 설정이 필요하지](https://circleci.com/docs/environment#browsers) 않습니다.
### AppVeyor
AppVeyor는 Windows에서 작동하기 때문에 Selenium, Chromium, Electron과 그 비슷한
툴들을 복잡한 과정 없이 모두 지원합니다. - 설정이 필요하지 않습니다.

View File

@@ -8,6 +8,10 @@ Electron은 라이센스상의 문제로 Widevine CDM 플러그인을 직접 제
따라서 플러그인을 얻으려면 먼저 사용할 Electron 빌드의 아키텍쳐와 버전에 맞춰 공식
Chrome 브라우저를 설치해야 합니다.
__참고:__ Chrome 브라우저의 메이저 버전은 Electron에서 사용하는 Chrome 버전과
같습니다, 만약 그렇지 않다면 `navigator.plugins`가 로드됐더라도 정상적으로 작동하지
않습니다.
### Windows & OS X
Chrome 브라우저에서 `chrome://components/`를 열고 `WidevineCdm`을 찾은 후 확실히

View File

@@ -0,0 +1,67 @@
# The `window.open` function
Qunado `window.open` é chamado para criar uma nova janela de uma pagina web uma nova instância de `BrowserWindow` será criado para a `url` e um proxy será devolvido para o `windows.open`, para permitir que a página tenha limitado controle sobre ele.
O proxy tem funcionalidade limitada padrão implementada para ser compatível com as páginas web tradicionais.
Para controle total da nova janela você deveria criar um `BrowserWindow` diretamente
The newly created `BrowserWindow` will inherit parent window's options by
default, to override inherited options you can set them in the `features`
string.
O recém-criado `BrowserWindow` herdará as opções da janela pai por padrão, para substituir as opções herdadas você pode definilos no `features`(string).
### `window.open(url[, frameName][, features])`
* `url` String
* `frameName` String (opcional)
* `features` String (opcional)
Cria uma nova janela e retorna uma instância da classe `BrowserWindowProxy'.
A string `features` segue o formato padrão do browser, mas cada recurso (feature) tem que ser um campo de opções do `BrowserWindow`.
### `window.opener.postMessage(message, targetOrigin)`
* `message` String
* `targetOrigin` String
Envia uma mensagem para a janela pai com a origem especificada ou `*` preferência de origem não especificada.
Sends a message to the parent window with the specified origin or `*`
origin preference.
## Class: BrowserWindowProxy
O objeto `BrowserWindowProxy` é retornado de `window.open` e fornece uma funcionalidade limitada para a janela filha.
### `BrowserWindowProxy.blur()`
Remove o foco da janela filha.
### `BrowserWindowProxy.close()`
Forçadamente fecha a janela filha sem chamar o evento de descarregamento.
### `BrowserWindowProxy.closed`
Define como true após a janela filha ficar fechada.
### `BrowserWindowProxy.eval(code)`
* `code` String
Avalia o código na jánela filha.
### `BrowserWindowProxy.focus()`
Concentra-se a janela filha (traz a janela para frente)
### `BrowserWindowProxy.postMessage(message, targetOrigin)`
* `message` String
* `targetOrigin` String
Sends a message to the child window with the specified origin or `*` for no
origin preference.
In addition to these methods, the child window implements `window.opener` object
with no properties and a single method.

View File

@@ -1,13 +1,19 @@
## 常见问题
+ [Electron 常见问题](faq/electron-faq.md)
## 向导
* [支持平台](tutorial/supported-platforms.md)
* [应用部署](tutorial/application-distribution.md)
* [应用打包](tutorial/application-packaging.md)
* [使用原生模块](tutorial/using-native-node-modules.md)
* [分发应用](tutorial/application-distribution.md)
* [提交应用到 Mac App Store](tutorial/mac-app-store-submission-guide.md)
* [打包应用](tutorial/application-packaging.md)
* [使用 Node 原生模块](tutorial/using-native-node-modules.md)
* [主进程调试](tutorial/debugging-main-process.md)
* [使用 Selenium 和 WebDriver](tutorial/using-selenium-and-webdriver.md)
* [调试工具扩展](tutorial/devtools-extension.md)
* [使用 PepperFlash 插件](tutorial/using-pepper-flash-plugin.md)
* [使用开发人员工具扩展](tutorial/devtools-extension.md)
* [使用 Pepper Flash 插件](tutorial/using-pepper-flash-plugin.md)
* [使用 Widevine CDM 插件](tutorial/using-widevine-cdm-plugin.md)
## 教程
@@ -19,53 +25,55 @@
* [简介](api/synopsis.md)
* [进程对象](api/process.md)
* [支持的Chrome命令行开关](api/chrome-command-line-switches.md)
* [支持的 Chrome 命令行开关](api/chrome-command-line-switches.md)
* [环境变量](api/environment-variables.md)
定制的DOM元素:
自定义的 DOM 元素:
* [`File`对象](api/file-object.md)
* [`<webview>`标签](api/web-view-tag.md)
* [`window.open`函数](api/window-open.md)
* [`File` 对象](api/file-object.md)
* [`<webview>` 标签](api/web-view-tag.md)
* [`window.open` 函数](api/window-open.md)
主进程可用的模块:
主进程可用的模块:
* [app](api/app.md)
* [auto-updater](api/auto-updater.md)
* [browser-window](api/browser-window.md)
* [content-tracing](api/content-tracing.md)
* [autoUpdater](api/auto-updater.md)
* [BrowserWindow](api/browser-window.md)
* [contentTracing](api/content-tracing.md)
* [dialog](api/dialog.md)
* [global-shortcut](api/global-shortcut.md)
* [ipc (main process)](api/ipc-main-process.md)
* [menu](api/menu.md)
* [menu-item](api/menu-item.md)
* [power-monitor](api/power-monitor.md)
* [power-save-blocker](api/power-save-blocker.md)
* [globalShortcut](api/global-shortcut.md)
* [ipcMain](api/ipc-main.md)
* [Menu](api/menu.md)
* [MenuItem](api/menu-item.md)
* [powerMonitor](api/power-monitor.md)
* [powerSaveBlocker](api/power-save-blocker.md)
* [protocol](api/protocol.md)
* [session](api/session.md)
* [webContents](api/web-contents.md)
* [tray](api/tray.md)
* [Tray](api/tray.md)
渲染进程(网页)可用的模块:
渲染进程网页)内可用的模块:
* [ipc (renderer)](api/ipc-renderer.md)
* [desktopCapturer](api/desktop-capturer.md)
* [ipcRenderer](api/ipc-renderer.md)
* [remote](api/remote.md)
* [web-frame](api/web-frame.md)
* [webFrame](api/web-frame.md)
两种进程都可用的模块:
两种进程都可用的模块:
* [clipboard](api/clipboard.md)
* [crash-reporter](api/crash-reporter.md)
* [native-image](api/native-image.md)
* [crashReporter](api/crash-reporter.md)
* [nativeImage](api/native-image.md)
* [screen](api/screen.md)
* [shell](api/shell.md)
## 开发
* [码规范](development/coding-style.md)
* [码规范](development/coding-style.md)
* [源码目录结构](development/source-code-directory-structure.md)
* [与 NW.js (原名 node-webkit) 在技术上的差异](development/atom-shell-vs-node-webkit.md)
* [构建系统概](development/build-system-overview.md)
* [构建步骤 (Mac)](development/build-instructions-mac.md)
* [构建步骤 (Windows)](development/build-instructions-windows.md)
* [构建步骤 (Linux)](development/build-instructions-linux.md)
* [在调试中使用 SymbolServer](development/setting-up-symbol-server.md)
* [与 NW.js(原 node-webkit在技术上的差异](development/atom-shell-vs-node-webkit.md)
* [构建系统概](development/build-system-overview.md)
* [构建步骤Mac](development/build-instructions-mac.md)
* [构建步骤Windows](development/build-instructions-windows.md)
* [构建步骤Linux](development/build-instructions-linux.md)
* [在调试中使用 Symbol Server](development/setting-up-symbol-server.md)

View File

@@ -1,46 +1,43 @@
# Accelerator
An accelerator is a string that represents a keyboard shortcut. It can contain
multiple modifiers and key codes, combined by the `+` character.
一个 `Accelerator` 是一个表示某个快捷键组合的字符串。它包含了用 `+` 连接的若干个按键。
Examples:
例如:
* `Command+A`
* `Ctrl+Shift+Z`
## Platform notice
## 运行平台相关的提示
On Linux and Windows, the `Command` key does not have any effect so
use `CommandOrControl` which represents `Command` on OS X and `Control` on
Linux and Windows to define some accelerators.
Linux Windows 上,`Command` 键并不存在,因此我们通常用 `CommandOrControl` 来表示“在 OS X 下为 `Command` 键,但在
Linux 和 Windows 下为 `Control` 键。
The `Super` key is mapped to the `Windows` key on Windows and Linux and
`Cmd` on OS X.
`Super` 键是指 Linux 和 Windows 上的 `Windows` 键,但是在 OS X 下为 `Command` 键。
## Available modifiers
## 可用的功能按键
* `Command` (or `Cmd` for short)
* `Control` (or `Ctrl` for short)
* `CommandOrControl` (or `CmdOrCtrl` for short)
* `Command`(缩写为 `Cmd`
* `Control`(缩写为 `Ctrl`
* `CommandOrControl`(缩写为 `CmdOrCtrl`
* `Alt`
* `Shift`
* `Super`
## Available key codes
## 可用的普通按键
* `0` to `9`
* `A` to `Z`
* `F1` to `F24`
* Punctuations like `~`, `!`, `@`, `#`, `$`, etc.
* `0` `9`
* `A` `Z`
* `F1` `F24`
* 类似与 `~``!``@``#``$` 的标点符号。
* `Plus`
* `Space`
* `Backspace`
* `Delete`
* `Insert`
* `Return` (or `Enter` as alias)
* `Up`, `Down`, `Left` and `Right`
* `Home` and `End`
* `PageUp` and `PageDown`
* `Escape` (or `Esc` for short)
* `VolumeUp`, `VolumeDown` and `VolumeMute`
* `MediaNextTrack`, `MediaPreviousTrack`, `MediaStop` and `MediaPlayPause`
* `Return`(和 `Enter` 等同)
* `Up``Down``Left` `Right`
* `Home` `End`
* `PageUp` `PageDown`
* `Escape`(缩写为 `Esc`
* `VolumeUp``VolumeDown` `VolumeMute`
* `MediaNextTrack``MediaPreviousTrack``MediaStop` `MediaPlayPause`

View File

@@ -11,11 +11,11 @@ app.on('window-all-closed', function() {
});
```
## 事件
## 事件列表
`app` 对象会触发以下的事件:
### 事件: 'will-finish-launching'
### 事件:'will-finish-launching'
当应用程序完成基础的启动的时候被触发。在 Windows 和 Linux 中,
`will-finish-launching` 事件与 `ready` 事件是相同的; 在 OS X 中,
@@ -24,11 +24,11 @@ app.on('window-all-closed', function() {
在大多数的情况下,你应该只在 `ready` 事件处理器中完成所有的业务。
### 事件: 'ready'
### 事件:'ready'
当 Electron 完成初始化时被触发。
### 事件: 'window-all-closed'
### 事件:'window-all-closed'
当所有的窗口都被关闭时触发。
@@ -36,20 +36,20 @@ app.on('window-all-closed', function() {
或者开发者调用了 `app.quit()` Electron 将会先尝试关闭所有的窗口再触发 `will-quit` 事件,
在这种情况下 `window-all-closed` 不会被触发。
### 事件: 'before-quit'
### 事件:'before-quit'
返回:
* `event` 事件
* `event` Event
在应用程序开始关闭它的窗口的时候被触发。
调用 `event.preventDefault()` 将会阻止终止应用程序的默认行为。
### 事件: 'will-quit'
### 事件:'will-quit'
返回:
* `event` 事件
* `event` Event
当所有的窗口已经被关闭,应用即将退出时被触发。
调用 `event.preventDefault()` 将会阻止终止应用程序的默认行为。
@@ -57,20 +57,20 @@ app.on('window-all-closed', function() {
你可以在 `window-all-closed` 事件的描述中看到 `will-quit` 事件
`window-all-closed` 事件的区别。
### 事件: 'quit'
### 事件:'quit'
返回:
* `event` 事件
* `exitCode` 整数
* `event` Event
* `exitCode` Integer
当应用程序正在退出时触发。
### 事件: 'open-file' _OS X_
### 事件:'open-file' _OS X_
返回:
* `event` 事件
* `path` 字符串
* `event` Event
* `path` String
当用户想要在应用中打开一个文件时触发。`open-file` 事件常常在应用已经打开并且系统想要再次使用应用打开文件时被触发。
`open-file` 也会在一个文件被拖入 dock 且应用还没有运行的时候被触发。
@@ -78,73 +78,74 @@ app.on('window-all-closed', function() {
如果你想处理这个事件,你应该调用 `event.preventDefault()`
在 Windows系统中, 你需要通过解析 process.argv 来获取文件路径。
### 事件: 'open-url' _OS X_
### 事件:'open-url' _OS X_
返回:
* `event` 事件
* `url` 字符串
* `event` Event
* `url` String
当用户想要在应用中打开一个url的时候被触发。URL格式必须要提前标识才能被你的应用打开。
如果你想处理这个事件,你应该调用 `event.preventDefault()`
### 事件: 'activate' _OS X_
### 事件:'activate' _OS X_
返回:
* `event` 事件
* `hasVisibleWindows` 布尔值
* `event` Event
* `hasVisibleWindows` Boolean
当应用被激活时触发,常用于点击应用的 dock 图标的时候。
### 事件: 'browser-window-blur'
### 事件:'browser-window-blur'
返回:
* `event` 事件
* `window` 浏览器窗口
* `event` Event
* `window` BrowserWindow
当一个 [浏览器窗口](browser-window.md) 失去焦点的时候触发。
当一个 [BrowserWindow](browser-window.md) 失去焦点的时候触发。
### 事件: 'browser-window-focus'
### 事件:'browser-window-focus'
返回:
* `event` 事件
* `window` 浏览器窗口
* `event` Event
* `window` BrowserWindow
当一个 [浏览器窗口](browser-window.md) 获得焦点的时候触发。
当一个 [BrowserWindow](browser-window.md) 获得焦点的时候触发。
### 事件: 'browser-window-created'
### 事件:'browser-window-created'
返回:
* `event` 事件
* `window` 浏览器窗口
* `event` Event
* `window` BrowserWindow
当一个 [浏览器窗口](browser-window.md) 被创建的时候触发。
当一个 [BrowserWindow](browser-window.md) 被创建的时候触发。
### 事件: 'certificate-error'
### 事件:'certificate-error'
返回:
* `event` 事件
* `webContents` [web组件](web-contents.md)
* `url` 字符串
* `certificateList` 对象
* `data` PEM 编码数据
* `issuerName` 发行者的公有名称
* `callback` 函数
* `event` Event
* `webContents` [WebContents](web-contents.md)
* `url` String - URL 地址
* `error` String - 错误码
* `certificate` Object
* `data` Buffer - PEM 编码数据
* `issuerName` String - 发行者的公有名称
* `callback` Function
Emitted when failed to verify the `certificate` for `url`, to trust the
certificate you should prevent the default behavior with
`event.preventDefault()` and call `callback(true)`.
当对 `url` 验证 `certificate` 证书失败的时候触发,如果需要信任这个证书,你需要阻止默认行为 `event.preventDefault()` 并且
调用 `callback(true)`
```javascript
session.on('certificate-error', function(event, webContents, url, error, certificate, callback) {
if (url == "https://github.com") {
// Verification logic.
// 验证逻辑。
event.preventDefault();
callback(true);
} else {
@@ -153,37 +154,37 @@ session.on('certificate-error', function(event, webContents, url, error, certifi
});
```
### 事件: 'select-client-certificate'
### 事件:'select-client-certificate'
返回:
* `event` 事件
* `webContents` [web组件](web-contents.md)
* `url` 字符串
* `certificateList` 对象
* `data` PEM 编码数据
* `issuerName` 发行者的公有名称
* `callback` 函数
* `event` Event
* `webContents` [WebContents](web-contents.md)
* `url` String - URL 地址
* `certificateList` [Object]
* `data` Buffer - PEM 编码数据
* `issuerName` String - 发行者的公有名称
* `callback` Function
当一个客户端认证被请求的时候被触发。
The `url` corresponds to the navigation entry requesting the client certificate
and `callback` needs to be called with an entry filtered from the list.
Using `event.preventDefault()` prevents the application from using the first
certificate from the store.
`url` 指的是请求客户端认证的网页地址,调用 `callback` 时需要传入一个证书列表中的证书。
需要通过调用 `event.preventDefault()` 来防止应用自动使用第一个证书进行验证。如下所示:
```javascript
app.on('select-certificate', function(event, host, url, list, callback) {
event.preventDefault();
callback(list[0]);
})
```
### Event: 'login'
### 事件: 'login'
Returns:
返回:
* `event` Event
* `webContents` [Web组件](web-contents.md)
* `webContents` [WebContents](web-contents.md)
* `request` Object
* `method` String
* `url` URL
@@ -196,11 +197,10 @@ Returns:
* `realm` String
* `callback` Function
`webContents` 要做验证时被触发。
`webContents` 要做进行一次 HTTP 登陆验证时被触发。
The default behavior is to cancel all authentications, to override this you
should prevent the default behavior with `event.preventDefault()` and call
`callback(username, password)` with the credentials.
默认情况下Electron 会取消所有的验证行为,如果需要重写这个行为,你需要用 `event.preventDefault()` 来阻止默认行为,并且
`callback(username, password)` 来进行验证。
```javascript
app.on('login', function(event, webContents, request, authInfo, callback) {
@@ -208,22 +208,22 @@ app.on('login', function(event, webContents, request, authInfo, callback) {
callback('username', 'secret');
})
```
### 事件: 'gpu-process-crashed'
### 事件:'gpu-process-crashed'
当GPU进程崩溃时触发。
GPU 进程崩溃时触发。
## 方法
## 方法列表
`app` 对象拥有以下的方法:
**提示:** 有的方法只能用于特定的操作系统。
**请注意** 有的方法只能用于特定的操作系统。
### `app.quit()`
试图关掉所有的窗口。`before-quit` 事件将会最先触发。如果所有的窗口都被成功关闭了,
试图关掉所有的窗口。`before-quit` 事件将会最先触发。如果所有的窗口都被成功关闭了,
`will-quit` 事件将会被触发,默认下应用将会被关闭。
这个方法保证了所有的 `beforeunload``unload` 事件处理器被正确执行。会存在一个窗口 `beforeunload` 事件处理器返回 `false` 取消退出的可能性
这个方法保证了所有的 `beforeunload``unload` 事件处理器被正确执行。假如一个窗口 `beforeunload` 事件处理器返回 `false`,那么整个应用可能会取消退出
### `app.hide()` _OS X_
@@ -241,30 +241,29 @@ app.on('login', function(event, webContents, request, authInfo, callback) {
所有的窗口会被立刻关闭,不会询问用户。`before-quit``will-quit` 这2个事件不会被触发
### `app.getAppPath()`
返回当前应用所在的文件路径。
### `app.getPath(name)`
* `name` 字符串
* `name` String
返回一个与 `name` 参数相关的特殊文件夹或文件路径。当失败时抛出一个 `Error`
你可以通过名称请求以下的路径:
* `home` 用户的 home 文件夹
* `appData` 所有用户的应用数据文件夹,默认对应:
* `home` 用户的 home 文件夹(主目录)
* `appData` 当前用户的应用数据文件夹,默认对应:
* `%APPDATA%` Windows 中
* `$XDG_CONFIG_HOME` or `~/.config` Linux 中
* `~/Library/Application Support` OS X 中
* `userData` 储存你应用程序设置文件的文件夹,默认是 `appData` 文件夹附加应用的名称
* `temp` 临时文件夹
* `userData` 储存你应用程序设置文件的文件夹,默认是 `appData` 文件夹附加应用的名称
* `temp` 临时文件夹
* `exe` 当前的可执行文件
* `module` `libchromiumcontent`.
* `desktop` 当前用户的桌面文件夹
* `documents` "我的文件夹"的路径.
* `module` `libchromiumcontent`
* `desktop` 当前用户的桌面文件夹
* `documents` 用户文档目录的路径
* `downloads` 用户下载目录的路径.
* `music` 用户音乐目录的路径.
* `pictures` 用户图片目录的路径.
@@ -272,14 +271,14 @@ app.on('login', function(event, webContents, request, authInfo, callback) {
### `app.setPath(name, path)`
* `name` 字符串
* `path` 字符串
* `name` String
* `path` String
重写 `path` 参数到一个特别的文件夹或者一个和 `name` 参数有关系的文件
重写某个 `name` 的路径为 `path``path` 可以是一个文件夹或者一个文件,这个`name` 的类型有关
如果这个路径指向的文件夹不存在,这个文件夹将会被这个方法创建。
如果错误则抛出 `Error`
如果错误则抛出 `Error`
你只可以指向 `app.getPath` 中定义过 `name` 的路径
`name` 参数只能使用 `app.getPath` 中定义过 `name`
默认情况下,网页的 cookie 和缓存都会储存在 `userData` 文件夹。
如果你想要改变这个位置,你需要在 `app` 模块中的 `ready` 事件被触发之前重写 `userData` 的路径。
@@ -293,22 +292,20 @@ app.on('login', function(event, webContents, request, authInfo, callback) {
返回当前应用程序的 `package.json` 文件中的名称。
通常 `name` 字段是一个短的小写字符串,其命名规则按照 npm 中的模块命名规则。你应该单独列举一个
`productName` 字段,用于表示你的应用程序的完整名称,这个名称将会被 Electron 优先采用
由于 npm 的命名规则,通常 `name` 字段是一个短的小写字符串。但是应用名的完整名称通常是首字母大写的,你应该单独使用一个
`productName` 字段,用于表示你的应用程序的完整名称Electron 优先使用这个字段作为应用名
### `app.getLocale()`
返回当前应用程序的语言种类
返回当前应用程序的语言。
### `app.addRecentDocument(path)` _OS X_ _Windows_
* `path` 字符串
* `path` String
最近访问的文档列表中添加 `path`
最近访问的文档列表中添加 `path`
这个列表由操作系统进行管理。在 Windows 中您可以通过任务条进行访问,在 OS X 中你可以通过dock 菜单进行访问。
这个列表由操作系统进行管理。在 Windows 中您可以通过任务条进行访问,在 OS X 中你可以通过 dock 菜单进行访问。
### `app.clearRecentDocuments()` _OS X_ _Windows_
@@ -316,66 +313,55 @@ app.on('login', function(event, webContents, request, authInfo, callback) {
### `app.setUserTasks(tasks)` _Windows_
* `tasks``Task` 对象构成的数组
* `tasks` [Task] - 一个由 Task 对象构成的数组
`tasks` 添加到 Windows 中 JumpList 功能的 [Tasks][tasks] 分类中。
`tasks` 中的 `Task` 对象格式如下:
`Task` 对象
* `program` 字符串 - 执行程序的路径,通常你应该说明当前程序的路径为 `process.execPath` 字段。
* `arguments` 字符串 - 当 `program` 执行时的命令行参数。
* `title` 字符串 - JumpList 中显示的标题。
* `description` 字符串 - 对这个任务的描述。
* `iconPath` 字符串 - JumpList 中显示的 icon 的绝对路径,可以是一个任意包含一个icon的资源文件。通常可以通过指明 `process.execPath` 来显示程序中的icon
* `iconIndex` 整数 - icon文件中的icon目录。如果一个icon文件包括了两个或多个icon,就需要设置这个值以确定icon。如果一个文件仅包含一个icon那么这个值为0
`Task` Object
* `program` String - 执行程序的路径,通常你应该说明当前程序的路径为 `process.execPath` 字段。
* `arguments` String - 当 `program` 执行时的命令行参数。
* `title` String - JumpList 中显示的标题。
* `description` String - 对这个任务的描述。
* `iconPath` String - JumpList 中显示的图标的绝对路径,可以是一个任意包含一个图标的资源文件。通常来说,你可以通过指明 `process.execPath` 来显示程序中的图标
* `iconIndex` Integer - 图标文件中的采用的图标位置。如果一个图标文件包括了多个图标,就需要设置这个值以确定使用的是哪一个图标
如果这个图标文件中只包含一个图标,那么这个值为 0。
### `app.allowNTLMCredentialsForAllDomains(allow)`
* `allow` Boolean
Dynamically sets whether to always send credentials for HTTP NTLM or Negotiate
authentication - normally, Electron will only send NTLM/Kerberos credentials for
URLs that fall under "Local Intranet" sites (i.e. are in the same domain as you).
However, this detection often fails when corporate networks are badly configured,
so this lets you co-opt this behavior and enable it for all URLs.
动态设置是否总是为 HTTP NTLM Negotiate 认证发送证书。通常来说Electron 只会对本地网络(比如和你处在一个域中的计算机)发
NTLM / Kerberos 证书。但是假如网络设置得不太好,可能这个自动探测会失效,所以你可以通过这个接口自定义 Electron 对所有 URL
的行为。
### `app.makeSingleInstance(callback)`
* `callback` Function
This method makes your application a Single Instance Application - instead of
allowing multiple instances of your app to run, this will ensure that only a
single instance of your app is running, and other instances signal this
instance and exit.
这个方法可以让你的应用在同一时刻最多只会有一个实例,否则你的应用可以被运行多次并产生多个实例。你可以利用这个接口保证只有一个实例正
常运行,其余的实例全部会被终止并退出。
`callback` will be called with `callback(argv, workingDirectory)` when a second
instance has been executed. `argv` is an Array of the second instance's command
line arguments, and `workingDirectory` is its current working directory. Usually
applications respond to this by making their primary window focused and
non-minimized.
如果多个实例同时运行,那么第一个被运行的实例中 `callback` 会以 `callback(argv, workingDirectory)` 的形式被调用。其余的实例
会被终止。
`argv` 是一个包含了这个实例的命令行参数列表的数组,`workingDirectory` 是这个实例目前的运行目录。通常来说,我们会用通过将应用在
主屏幕上激活,并且取消最小化,来提醒用户这个应用已经被打开了。
The `callback` is guaranteed to be executed after the `ready` event of `app`
gets emitted.
`app``ready` 事件后,`callback` 才有可能被调用。
This method returns `false` if your process is the primary instance of the
application and your app should continue loading. And returns `true` if your
process has sent its parameters to another instance, and you should immediately
quit.
如果当前实例为第一个实例,那么在这个方法将会返回 `false` 来保证它继续运行。否则将会返回 `true` 来让它立刻退出。
On OS X the system enforces single instance automatically when users try to open
a second instance of your app in Finder, and the `open-file` and `open-url`
events will be emitted for that. However when users start your app in command
line the system's single instance machanism will be bypassed and you have to
use this method to ensure single instance.
OS X 中,如果用户通过 Finder、`open-file` 或者 `open-url` 打开应用,系统会强制确保只有一个实例在运行。但是如果用户是通过
命令行打开,这个系统机制会被忽略,所以你仍然需要靠这个方法来保证应用为单实例运行的。
An example of activating the window of primary instance when a second instance
starts:
下面是一个简单的例子。我们可以通过这个例子了解如何确保应用为单实例运行状态。
```js
var myWindow = null;
var shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory) {
// Someone tried to run a second instance, we should focus our window.
// 当另一个实例运行的时候,这里将会被调用,我们需要激活应用的窗口
if (myWindow) {
if (myWindow.isMinimized()) myWindow.restore();
myWindow.focus();
@@ -383,104 +369,109 @@ var shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory)
return true;
});
// 这个实例是多余的实例,需要退出
if (shouldQuit) {
app.quit();
return;
}
// Create myWindow, load the rest of the app, etc...
// 创建窗口、继续加载应用、应用逻辑等……
app.on('ready', function() {
});
```
### `app.setAppUserModelId(id)` _Windows_
* `id` String
改变 [Application User Model ID][app-user-model-id] `id`.
改变当前应用的 [Application User Model ID][app-user-model-id] `id`.
### `app.isAeroGlassEnabled()` _Windows_
This method returns `true` if [DWM composition](https://msdn.microsoft.com/en-us/library/windows/desktop/aa969540.aspx)
(Aero Glass) is enabled, and `false` otherwise. You can use it to determine if
you should create a transparent window or not (transparent windows won't work
correctly when DWM composition is disabled).
如果 [DWM composition](https://msdn.microsoft.com/en-us/library/windows/desktop/aa969540.aspx)(Aero Glass) 启用
了,那么这个方法会返回 `true`,否则是 `false`。你可以用这个方法来决定是否要开启透明窗口特效,因为如果用户没开启 DWM那么透明窗
口特效是无效的。
Usage example:
举个例子:
```js
let browserOptions = {width: 1000, height: 800};
// Make the window transparent only if the platform supports it.
// 只有平台支持的时候才使用透明窗口
if (process.platform !== 'win32' || app.isAeroGlassEnabled()) {
browserOptions.transparent = true;
browserOptions.frame = false;
}
// Create the window.
// 创建窗口
win = new BrowserWindow(browserOptions);
// Navigate.
// 转到某个网页
if (browserOptions.transparent) {
win.loadURL('file://' + __dirname + '/index.html');
} else {
// No transparency, so we load a fallback that uses basic styles.
// 没有透明特效,我们应该用某个只包含基本样式的替代解决方案。
win.loadURL('file://' + __dirname + '/fallback.html');
}
```
### `app.commandLine.appendSwitch(switch[, value])`
通过可选的参数 `value` 给 Chromium 命令行中添加一个开关。
Append a switch (with optional `value`) to Chromium's command line.
通过可选的参数 `value` 给 Chromium 中添加一个命令行开关。
**贴士:** 这不会影响 `process.argv` ,这个方法主要被开发者用于控制一些低层级的 Chromium 行为。
**注意**个方法不会影响 `process.argv`,我们通常用这个方法控制一些底层 Chromium 行为。
### `app.commandLine.appendArgument(value)`
给 Chromium 命令行中加入一个参数这个参数是当前正在被引用的
给 Chromium 中直接添加一个命令行参数这个参数 `value` 的引号和格式必须正确
**贴士:** 这不会影响 `process.argv`
**注意**个方法不会影响 `process.argv`
### `app.dock.bounce([type])` _OS X_
* `type` 字符串 (可选的) - 可以是 `critical``informational`。默认下是 `informational`
* `type` String - 可选参数,可以是 `critical``informational`。默认 `informational`
输入 `critical`dock 中的 icon 将会开始弹跳直到应用被激活或者这个请求被取消。
传入的是 `critical`dock 中的应用将会开始弹跳直到这个应用被激活或者这个请求被取消。
输入 `informational`dock 中的 icon 只会弹跳一秒钟。
然而,这个请求仍然会激活,直到应用被激活或者请求被取消。
传入的是 `informational`dock 中的图标只会弹跳一秒钟。但是,这个请求仍然会激活,直到应用被激活或者请求被取消。
返回一个表示这个请求的 ID。
这个方法返回的返回值表示这个请求的 ID。
### `app.dock.cancelBounce(id)` _OS X_
* `id` 整数
* `id` Integer
取消这个 `id` 对应的请求。
### `app.dock.setBadge(text)` _OS X_
* `text` 字符串
* `text` String
设置 dock 中显示的字符。
设置应用在 dock 中显示的字符
### `app.dock.getBadge()` _OS X_
返回 dock 中显示的字符。
返回应用在 dock 中显示的字符
### `app.dock.hide()` _OS X_
隐藏 dock 中的 icon
隐藏应用在 dock 中的图标
### `app.dock.show()` _OS X_
显示 dock 中的 icon
显示应用在 dock 中的图标
### `app.dock.setMenu(menu)` _OS X_
* `menu` 菜单
* `menu` [Menu](menu.md)
设置应用的 [dock 菜单][dock-menu].
### `app.dock.setIcon(image)` _OS X_
* `image` [NativeImage](native-image.md)
设置应用在 dock 中显示的图标。
[dock-menu]:https://developer.apple.com/library/mac/documentation/Carbon/Conceptual/customizing_docktile/concepts/dockconcepts.html#//apple_ref/doc/uid/TP30000986-CH2-TPXREF103
[tasks]:http://msdn.microsoft.com/en-us/library/windows/desktop/dd378460(v=vs.85).aspx#tasks
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx

View File

@@ -0,0 +1,88 @@
# autoUpdater
这个模块提供了一个到 `Squirrel` 自动更新框架的接口。
## 平台相关的提示
虽然 `autoUpdater` 模块提供了一套各平台通用的接口,但是在每个平台间依然会有一些微小的差异。
### OS X
在 OS X 上,`autoUpdater` 模块依靠的是内置的 [Squirrel.Mac][squirrel-mac],这意味着你不需要依靠其他的设置就能使用。关于
更新服务器的配置,你可以通过阅读 [Server Support][server-support] 这篇文章来了解。
### Windows
在 Windows 上,你必须使用安装程序将你的应用装到用户的计算机上,所以比较推荐的方法是用 [grunt-electron-installer][installer] 这个模块来自动生成一个 Windows 安装向导。
Squirrel 自动生成的安装向导会生成一个带 [Application User Model ID][app-user-model-id] 的快捷方式。
Application User Model ID 的格式是 `com.squirrel.PACKAGE_ID.YOUR_EXE_WITHOUT_DOT_EXE`, 比如
`com.squirrel.slack.Slack``com.squirrel.code.Code` 这样的。你应该在自己的应用中使用 `app.setAppUserModelId` 方法设置相同的 API不然 Windows 将不能正确地把你的应用固定在任务栏上。
服务器端的配置和 OS X 也是不一样的,你可以阅读 [Squirrel.Windows][squirrel-windows] 这个文档来获得详细信息。
### Linux
Linux 下没有任何的自动更新支持,所以我们推荐用各个 Linux 发行版的包管理器来分发你的应用。
## 事件列表
`autoUpdater` 对象会触发以下的事件:
### 事件:'error'
返回:
* `error` Error
当更新发生错误的时候触发。
### 事件:'checking-for-update'
当开始检查更新的时候触发。
### 事件:'update-available'
当发现一个可用更新的时候触发,更新包下载会自动开始。
### 事件:'update-not-available'
当没有可用更新的时候触发。
### 事件:'update-downloaded'
返回:
* `event` Event
* `releaseNotes` String - 新版本更新公告
* `releaseName` String - 新的版本号
* `releaseDate` Date - 新版本发布的日期
* `updateURL` String - 更新地址
在更新下载完成的时候触发。
在 Windows 上只有 `releaseName` 是有效的。
## 方法列表
`autoUpdater` 对象有以下的方法:
### `autoUpdater.setFeedURL(url)`
* `url` String
设置检查更新的 `url`,并且初始化自动更新。这个 `url` 一旦设置就无法更改。
### `autoUpdater.checkForUpdates()`
向服务端查询现在是否有可用的更新。在调用这个方法之前,必须要先调用 `setFeedURL`
### `autoUpdater.quitAndInstall()`
在下载完成后,重启当前的应用并且安装更新。这个方法应该仅在 `update-downloaded` 事件触发后被调用。
[squirrel-mac]: https://github.com/Squirrel/Squirrel.Mac
[server-support]: https://github.com/Squirrel/Squirrel.Mac#server-support
[squirrel-windows]: https://github.com/Squirrel/Squirrel.Windows
[installer]: https://github.com/atom/grunt-electron-installer
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx

View File

@@ -0,0 +1,761 @@
# BrowserWindow
`BrowserWindow` 类让你有创建一个浏览器窗口的权力。例如:
```javascript
// In the main process.
const BrowserWindow = require('electron').BrowserWindow;
// Or in the renderer process.
const BrowserWindow = require('electron').remote.BrowserWindow;
var win = new BrowserWindow({ width: 800, height: 600, show: false });
win.on('closed', function() {
win = null;
});
win.loadURL('https://github.com');
win.show();
```
你也可以不通过chrome创建窗口使用
[Frameless Window](frameless-window.md) API.
## Class: BrowserWindow
`BrowserWindow` 是一个
[EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter).
通过 `options` 可以创建一个具有本质属性的 `BrowserWindow` .
### `new BrowserWindow([options])`
* `options` Object
* `width` Integer - 窗口宽度,单位像素. 默认是 `800`.
* `height` Integer - 窗口高度,单位像素. 默认是 `600`.
* `x` Integer - 窗口相对于屏幕的左偏移位置.默认居中.
* `y` Integer - 窗口相对于屏幕的顶部偏移位置.默认居中.
* `useContentSize` Boolean - `width``height` 使用web网页size, 这意味着实际窗口的size应该包括窗口框架的size稍微会大一点默认为 `false`.
* `center` Boolean - 窗口屏幕居中.
* `minWidth` Integer - 窗口最小宽度,默认为 `0`.
* `minHeight` Integer - 窗口最小高度,默认为 `0`.
* `maxWidth` Integer - 窗口最大宽度,默认无限制.
* `maxHeight` Integer - 窗口最大高度,默认无限制.
* `resizable` Boolean - 是否可以改变窗口size默认为 `true`.
* `movable` Boolean - 窗口是否可以拖动. 在 Linux 上无效. 默认为 `true`.
* `minimizable` Boolean - 窗口是否可以最小化. 在 Linux 上无效. 默认为 `true`.
* `maximizable` Boolean - 窗口是否可以最大化. 在 Linux 上无效. 默认为 `true`.
* `closable` Boolean - 窗口是否可以关闭. 在 Linux 上无效. 默认为 `true`.
* `alwaysOnTop` Boolean - 窗口是否总是显示在其他窗口之前. 在 Linux 上无效. 默认为 `false`.
* `fullscreen` Boolean - 窗口是否可以全屏幕. 当明确设置值为When `false` ,全屏化按钮将会隐藏,在 OS X 将禁用. 默认 `false`.
* `fullscreenable` Boolean - 在 OS X 上,全屏化按钮是否可用,默认为 `true`.
* `skipTaskbar` Boolean - 是否在人物栏中显示窗口. 默认是`false`.
* `kiosk` Boolean - kiosk 方式. 默认为 `false`.
* `title` String - 窗口默认title. 默认 `"Electron"`.
* `icon` [NativeImage](native-image.md) - 窗口图标, 如果不设置,窗口将使用可用的默认图标.
* `show` Boolean - 窗口创建的时候是否显示. 默认为 `true`.
* `frame` Boolean - 指定 `false` 来创建一个
[Frameless Window](frameless-window.md). 默认为 `true`.
* `acceptFirstMouse` Boolean - 是否允许单击web view来激活窗口 . 默认为 `false`.
* `disableAutoHideCursor` Boolean - 当 typing 时是否隐藏鼠标.默认 `false`.
* `autoHideMenuBar` Boolean - 除非点击 `Alt`,否则隐藏菜单栏.默认为 `false`.
* `enableLargerThanScreen` Boolean - 是否允许允许改变窗口大小大于屏幕. 默认是 `false`.
* `backgroundColor` String -窗口的 background color 值为十六进制,如 `#66CD00``#FFF``#80FFFFFF` (支持透明度). 默认为在 Linux 和 Windows 上为
`#000` (黑色) , Mac上为 `#FFF`(或透明).
* `hasShadow` Boolean - 窗口是否有阴影. 只在 OS X 上有效. 默认为 `true`.
* `darkTheme` Boolean - 为窗口使用 dark 主题, 只在一些拥有 GTK+3 桌面环境上有效. 默认为 `false`.
* `transparent` Boolean - 窗口 [透明](frameless-window.md).
默认为 `false`.
* `type` String - 窗口type, 默认普通窗口. 下面查看更多.
* `titleBarStyle` String - 窗口标题栏样式. 下面查看更多.
* `webPreferences` Object - 设置界面特性. 下面查看更多.
`type` 的值和效果不同平台展示效果不同,具体:
* Linux, 可用值为 `desktop`, `dock`, `toolbar`, `splash`,
`notification`.
* OS X, 可用值为 `desktop`, `textured`.
* `textured` type 添加金属梯度效果
(`NSTexturedBackgroundWindowMask`).
* `desktop` 设置窗口在桌面背景窗口水平
(`kCGDesktopWindowLevel - 1`). 注意桌面窗口不可聚焦, 不可不支持键盘和鼠标事件, 但是可以使用 `globalShortcut` 来解决输入问题.
`titleBarStyle` 只在 OS X 10.10 Yosemite 或更新版本上支持.
可用值:
* `default` 以及无值, 显示在 Mac 标题栏上为不透明的标准灰色.
* `hidden` 隐藏标题栏,内容充满整个窗口, 然后它依然在左上角,仍然受标准窗口控制.
* `hidden-inset`主体隐藏,显示小的控制按钮在窗口边缘.
`webPreferences` 参数是个对象,它的属性:
* `nodeIntegration` Boolean - 是否完整支持node. 默认为 `true`.
* `preload` String - 界面的其它脚本运行之前预先加载一个指定脚本. 这个脚本将一直可以使用 node APIs 无论 node integration 是否开启. 脚本路径为绝对路径.
当 node integration 关闭, 预加载的脚本将从全局范围重新引入node的全局引用标志. 查看例子
[here](process.md#event-loaded).
* `session` [Session](session.md#class-session) - 设置界面session. 而不是直接忽略session对象 , 也可用 `partition` 来代替, 它接受一个 partition 字符串. 当同时使用 `session``partition`, `session` 优先级更高.
默认使用默认 session.
* `partition` String - 通过session的partition字符串来设置界面session. 如果 `partition``persist:` 开头, 这个界面将会为所有界面使用相同的 `partition`. 如果没有 `persist:` 前缀, 界面使用历史session. 通过分享同一个 `partition`, 所有界面使用相同的session. 默认使用默认 session.
* `zoomFactor` Number - 界面默认缩放值, `3.0` 表示
`300%`. 默认 `1.0`.
* `javascript` Boolean - 开启javascript支持. 默认为`true`.
* `webSecurity` Boolean - 当设置为 `false`, 它将禁用相同地方的规则 (通常测试服), 并且如果有2个非用户设置的参数就设置
`allowDisplayingInsecureContent``allowRunningInsecureContent` 的值为
`true`. 默认为 `true`.
* `allowDisplayingInsecureContent` Boolean -允许一个使用 https的界面来展示由 http URLs 传过来的资源. 默认`false`.
* `allowRunningInsecureContent` Boolean - Boolean -允许一个使用 https的界面来渲染由 http URLs 提交的html,css,javascript. 默认为 `false`.
* `images` Boolean - 开启图片使用支持. 默认 `true`.
* `textAreasAreResizable` Boolean - textArea 可以编辑. 默认为 `true`.
* `webgl` Boolean - 开启 WebGL 支持. 默认为 `true`.
* `webaudio` Boolean - 开启 WebAudio 支持. 默认为 `true`.
* `plugins` Boolean - 是否开启插件支持. 默认为 `false`.
* `experimentalFeatures` Boolean - 开启 Chromium 的 可测试 特性.
默认为 `false`.
* `experimentalCanvasFeatures` Boolean - 开启 Chromium 的 canvas 可测试特性. 默认为 `false`.
* `directWrite` Boolean - 开启窗口的 DirectWrite font 渲染系统. 默认为 `true`.
* `blinkFeatures` String - 以 `,` 分隔的特性列表, 如
`CSSVariables,KeyboardEventKey`. 被支持的所有特性可在 [setFeatureEnabledFromString][blink-feature-string]
中找到.
* `defaultFontFamily` Object - 设置 font-family 默认字体.
* `standard` String - 默认为 `Times New Roman`.
* `serif` String - 默认为 `Times New Roman`.
* `sansSerif` String - 默认为 `Arial`.
* `monospace` String - 默认为 `Courier New`.
* `defaultFontSize` Integer - 默认为 `16`.
* `defaultMonospaceFontSize` Integer - 默认为 `13`.
* `minimumFontSize` Integer - 默认为 `0`.
* `defaultEncoding` String - 默认为 `ISO-8859-1`.
## 事件
`BrowserWindow` 对象可触发下列事件:
**注意:** 一些事件只能在特定os环境中触发已经尽可能地标出.
### Event: 'page-title-updated'
返回:
* `event` Event
当文档改变标题时触发,使用 `event.preventDefault()` 可以阻止原窗口的标题改变.
### Event: 'close'
返回:
* `event` Event
在窗口要关闭的时候触发. 它在DOM的 `beforeunload` and `unload` 事件之前触发.使用 `event.preventDefault()` 可以取消这个操作
通常你想通过 `beforeunload` 处理器来决定是否关闭窗口,但是它也会在窗口重载的时候被触发. 在 Electron 中,返回一个空的字符串或 `false` 可以取消关闭.例如:
```javascript
window.onbeforeunload = function(e) {
console.log('I do not want to be closed');
// Unlike usual browsers, in which a string should be returned and the user is
// prompted to confirm the page unload, Electron gives developers more options.
// Returning empty string or false would prevent the unloading now.
// You can also use the dialog API to let the user confirm closing the application.
e.returnValue = false;
};
```
### Event: 'closed'
当窗口已经关闭的时候触发.当你接收到这个事件的时候,你应当删除对已经关闭的窗口的引用对象和避免再次使用它.
### Event: 'unresponsive'
在界面卡死的时候触发事件.
### Event: 'responsive'
在界面恢复卡死的时候触发.
### Event: 'blur'
在窗口失去焦点的时候触发.
### Event: 'focus'
在窗口获得焦点的时候触发.
### Event: 'maximize'
在窗口最大化的时候触发.
### Event: 'unmaximize'
在窗口退出最大化的时候触发.
### Event: 'minimize'
在窗口最小化的时候触发.
### Event: 'restore'
在窗口从最小化恢复的时候触发.
### Event: 'resize'
在窗口size改变的时候触发.
### Event: 'move'
在窗口移动的时候触发.
注意:在 OS X 中别名为 `moved`.
### Event: 'moved' _OS X_
在窗口移动的时候触发.
### Event: 'enter-full-screen'
在的窗口进入全屏状态时候触发.
### Event: 'leave-full-screen'
在的窗口退出全屏状态时候触发.
### Event: 'enter-html-full-screen'
在的窗口通过 html api 进入全屏状态时候触发.
### Event: 'leave-html-full-screen'
在的窗口通过 html api 退出全屏状态时候触发.
### Event: 'app-command' _Windows_
在请求一个[App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx)的时候触发.
典型的是键盘媒体或浏览器命令, Windows上的 "Back" 按钮用作鼠标也会触发.
```js
someWindow.on('app-command', function(e, cmd) {
// Navigate the window back when the user hits their mouse back button
if (cmd === 'browser-backward' && someWindow.webContents.canGoBack()) {
someWindow.webContents.goBack();
}
});
```
### Event: 'scroll-touch-begin' _OS X_
在滚动条事件开始的时候触发.
### Event: 'scroll-touch-end' _OS X_
在滚动条事件结束的时候触发.
## 方法
`BrowserWindow` 对象有如下方法:
### `BrowserWindow.getAllWindows()`
返回一个所有已经打开了窗口的对象数组.
### `BrowserWindow.getFocusedWindow()`
返回应用当前获得焦点窗口,如果没有就返回 `null`.
### `BrowserWindow.fromWebContents(webContents)`
* `webContents` [WebContents](web-contents.md)
根据 `webContents` 查找窗口.
### `BrowserWindow.fromId(id)`
* `id` Integer
根据 id 查找窗口.
### `BrowserWindow.addDevToolsExtension(path)`
* `path` String
添加位于 `path` 的开发者工具栏扩展,并且返回扩展项的名字.
这个扩展会被添加到历史所以只需要使用这个API一次这个api不可用作编程使用.
### `BrowserWindow.removeDevToolsExtension(name)`
* `name` String
删除开发者工具栏名为 `name` 的扩展.
## 实例属性
使用 `new BrowserWindow` 创建的实例对象,有如下属性:
```javascript
// In this example `win` is our instance
var win = new BrowserWindow({ width: 800, height: 600 });
```
### `win.webContents`
这个窗口的 `WebContents` 对象,所有与界面相关的事件和方法都通过它完成的.
查看 [`webContents` documentation](web-contents.md) 的方法和事件.
### `win.id`
窗口的唯一id.
## 实例方法
使用 `new BrowserWindow` 创建的实例对象,有如下方法:
**注意:** 一些方法只能在特定os环境中调用已经尽可能地标出.
### `win.destroy()`
强制关闭窗口, `unload` and `beforeunload` 不会触发,并且 `close` 也不会触发, 但是它保证了 `closed` 触发.
### `win.close()`
尝试关闭窗口,这与用户点击关闭按钮的效果一样. 虽然网页可能会取消关闭,查看 [close event](#event-close).
### `win.focus()`
窗口获得焦点.
### `win.isFocused()`
返回 boolean, 窗口是否获得焦点.
### `win.show()`
展示并且使窗口获得焦点.
### `win.showInactive()`
展示窗口但是不获得焦点.
### `win.hide()`
隐藏窗口.
### `win.isVisible()`
返回 boolean, 窗口是否可见.
### `win.maximize()`
窗口最大化.
### `win.unmaximize()`
取消窗口最大化.
### `win.isMaximized()`
返回 boolean, 窗口是否最大化.
### `win.minimize()`
窗口最小化. 在一些os中它将在dock中显示.
### `win.restore()`
将最小化的窗口恢复为之前的状态.
### `win.isMinimized()`
返回 boolean, 窗口是否最小化.
### `win.setFullScreen(flag)`
* `flag` Boolean
设置是否全屏.
### `win.isFullScreen()`
返回 boolean, 窗口是否全屏化.
### `win.setAspectRatio(aspectRatio[, extraSize])` _OS X_
* `aspectRatio` 维持部分视图内容窗口的高宽比值.
* `extraSize` Object (可选) - 维持高宽比值时不包含的额外size.
* `width` Integer
* `height` Integer
由一个窗口来维持高宽比值. `extraSize` 允许开发者使用它,它的单位为像素,不包含在 `aspectRatio` 中.这个 API 可用来区分窗口的size和内容的size .
想象一个普通可控的HD video 播放器窗口. 假如左边缘有15控制像素右边缘有25控制像素在播放器下面有50控制像素.为了在播放器内保持一个 16:9 的高宽比例我们可以调用这个api传入参数16/9 and
[ 40, 50 ].第二个参数不管网页中的额外的宽度和高度在什么位置,只要它们存在就行.只需要把网页中的所有额外的高度和宽度加起来就行.
### `win.setBounds(options[, animate])`
* `options` Object
* `x` Integer
* `y` Integer
* `width` Integer
* `height` Integer
* `animate` Boolean (可选) _OS X_
重新设置窗口的宽高值,并且移动到指定的 `x`, `y` 位置.
### `win.getBounds()`
返回一个对象它包含了窗口的宽x坐标y坐标.
### `win.setSize(width, height[, animate])`
* `width` Integer
* `height` Integer
* `animate` Boolean (可选) _OS X_
重新设置窗口的宽高值.
### `win.getSize()`
返回一个数组,它包含了窗口的宽,高.
### `win.setContentSize(width, height[, animate])`
* `width` Integer
* `height` Integer
* `animate` Boolean (可选) _OS X_
重新设置窗口客户端的宽高值(例如网页界面).
### `win.getContentSize()`
返回一个数组,它包含了窗口客户端的宽,高.
### `win.setMinimumSize(width, height)`
* `width` Integer
* `height` Integer
设置窗口最小化的宽高值.
### `win.getMinimumSize()`
返回一个数组,它包含了窗口最小化的宽,高.
### `win.setMaximumSize(width, height)`
* `width` Integer
* `height` Integer
设置窗口最大化的宽高值.
### `win.getMaximumSize()`
返回一个数组,它包含了窗口最大化的宽,高.
### `win.setResizable(resizable)`
* `resizable` Boolean
设置窗口是否可以被用户改变size.
### `win.isResizable()`
返回 boolean,窗口是否可以被用户改变size.
### `win.setMovable(movable)` _OS X_ _Windows_
* `movable` Boolean
设置窗口是否可以被用户拖动. Linux 无效.
### `win.isMovable()` _OS X_ _Windows_
返回 boolean,窗口是否可以被用户拖动. Linux 总是返回 `true`.
### `win.setMinimizable(minimizable)` _OS X_ _Windows_
* `minimizable` Boolean
设置窗口是否可以最小化. Linux 无效.
### `win.isMinimizable()` _OS X_ _Windows_
返回 boolean,窗口是否可以最小化. Linux 总是返回 `true`.
### `win.setMaximizable(maximizable)` _OS X_ _Windows_
* `maximizable` Boolean
设置窗口是否可以最大化. Linux 无效.
### `win.isMaximizable()` _OS X_ _Windows_
返回 boolean,窗口是否可以最大化. Linux 总是返回 `true`.
### `win.setFullScreenable(fullscreenable)`
* `fullscreenable` Boolean
设置点击最大化按钮是否可以全屏或最大化窗口.
### `win.isFullScreenable()`
返回 boolean,点击最大化按钮是否可以全屏或最大化窗口.
### `win.setClosable(closable)` _OS X_ _Windows_
* `closable` Boolean
设置窗口是否可以人为关闭. Linux 无效.
### `win.isClosable()` _OS X_ _Windows_
返回 boolean,窗口是否可以人为关闭. Linux 总是返回 `true`.
### `win.setAlwaysOnTop(flag)`
* `flag` Boolean
是否设置这个窗口始终在其他窗口之上.设置之后,这个窗口仍然是一个普通的窗口,不是一个不可以获得焦点的工具箱窗口.
### `win.isAlwaysOnTop()`
返回 boolean,当前窗口是否始终在其它窗口之前.
### `win.center()`
窗口居中.
### `win.setPosition(x, y[, animate])`
* `x` Integer
* `y` Integer
* `animate` Boolean (可选) _OS X_
移动窗口到对应的 `x` and `y` 坐标.
### `win.getPosition()`
返回一个包含当前窗口位置的数组.
### `win.setTitle(title)`
* `title` String
改变原窗口的title.
### `win.getTitle()`
返回原窗口的title.
**注意:** 界面title可能和窗口title不相同.
### `win.flashFrame(flag)`
* `flag` Boolean
开始或停止显示窗口来获得用户的关注.
### `win.setSkipTaskbar(skip)`
* `skip` Boolean
让窗口不在任务栏中显示.
### `win.setKiosk(flag)`
* `flag` Boolean
进入或离开 kiosk 模式.
### `win.isKiosk()`
返回 boolean,是否进入或离开 kiosk 模式.
### `win.getNativeWindowHandle()`
`Buffer` 形式返回这个具体平台的窗口的句柄.
windows上句柄类型为 `HWND` OS X `NSView*` Linux `Window`.
### `win.hookWindowMessage(message, callback)` _Windows_
* `message` Integer
* `callback` Function
拦截windows 消息,在 WndProc 接收到消息时触发 `callback`函数.
### `win.isWindowMessageHooked(message)` _Windows_
* `message` Integer
返回 `true` or `false` 来代表是否拦截到消息.
### `win.unhookWindowMessage(message)` _Windows_
* `message` Integer
不拦截窗口消息.
### `win.unhookAllWindowMessages()` _Windows_
窗口消息全部不拦截.
### `win.setRepresentedFilename(filename)` _OS X_
* `filename` String
设置窗口当前文件路径,并且将这个文件的图标放在窗口标题栏上.
### `win.getRepresentedFilename()` _OS X_
获取窗口当前文件路径.
### `win.setDocumentEdited(edited)` _OS X_
* `edited` Boolean
明确指出窗口文档是否可以编辑,如果可以编辑则将标题栏的图标变成灰色.
### `win.isDocumentEdited()` _OS X_
返回 boolean,当前窗口文档是否可编辑.
### `win.focusOnWebView()`
### `win.blurWebView()`
### `win.capturePage([rect, ]callback)`
* `rect` Object (可选) - 捕获Page位置
* `x` Integer
* `y` Integer
* `width` Integer
* `height` Integer
* `callback` Function
捕获 `rect` 中的page 的快照.完成后将调用回调函数 `callback` 并返回 `image` . `image` 是存储了快照信息的[NativeImage](native-image.md)实例.如果不设置 `rect` 则将捕获所有可见page.
### `win.print([options])`
类似 `webContents.print([options])`
### `win.printToPDF(options, callback)`
类似 `webContents.printToPDF(options, callback)`
### `win.loadURL(url[, options])`
类似 `webContents.loadURL(url[, options])`.
### `win.reload()`
类似 `webContents.reload`.
### `win.setMenu(menu)` _Linux_ _Windows_
* `menu` Menu
设置菜单栏的 `menu` ,设置它为 `null` 则表示不设置菜单栏.
### `win.setProgressBar(progress)`
* `progress` Double
在进度条中设置进度值,有效范围 [0, 1.0].
当进度小于0时则不显示进度;
当进度大于0时显示结果不确定.
在libux上只支持Unity桌面环境需要指明 `*.desktop` 文件并且在 `package.json` 中添加文件名字.默认它为 `app.getName().desktop`.
### `win.setOverlayIcon(overlay, description)` _Windows 7+_
* `overlay` [NativeImage](native-image.md) - 在底部任务栏右边显示图标.
* `description` String - 描述.
向当前任务栏添加一个 16 x 16 像素的图标,通常用来覆盖一些应用的状态,或者直接来提示用户.
### `win.setHasShadow(hasShadow)` _OS X_
* `hasShadow` (Boolean)
设置窗口是否应该有阴影.在Windows和Linux系统无效.
### `win.hasShadow()` _OS X_
返回 boolean,设置窗口是否有阴影.在Windows和Linux系统始终返回
`true`.
### `win.setThumbarButtons(buttons)` _Windows 7+_
* `buttons` Array
在窗口的任务栏button布局出为缩略图添加一个有特殊button的缩略图工具栏. 返回一个 `Boolean` 对象来指示是否成功添加这个缩略图工具栏.
因为空间有限,缩略图工具栏上的 button 数量不应该超过7个.一旦设置了,由于平台限制,就不能移动它了.但是你可使用一个空数组来调用api来清除 buttons .
所有 `buttons` 是一个 `Button` 对象数组:
* `Button` Object
* `icon` [NativeImage](native-image.md) - 在工具栏上显示的图标.
* `click` Function
* `tooltip` String (可选) - tooltip 文字.
* `flags` Array (可选) - 控制button的状态和行为. 默认它是 `['enabled']`.
`flags` 是一个数组,它包含下面这些 `String`s:
* `enabled` - button 为激活状态并且开放给用户.
* `disabled` -button 不可用. 目前它有一个可见的状态来表示它不会响应你的行为.
* `dismissonclick` - 点击button这个缩略窗口直接关闭.
* `nobackground` - 不绘制边框,仅仅使用图像.
* `hidden` - button 对用户不可见.
* `noninteractive` - button 可用但是不可响应; 也不显示按下的状态. 它的值意味着这是一个在通知单使用 button 的实例.
### `win.showDefinitionForSelection()` _OS X_
在界面查找选中文字时显示弹出字典.
### `win.setAutoHideMenuBar(hide)`
* `hide` Boolean
设置窗口的菜单栏是否可以自动隐藏. 一旦设置了,只有当用户按下 `Alt` 键时则显示.
如果菜单栏已经可见,调用 `setAutoHideMenuBar(true)` 则不会立刻隐藏.
### `win.isMenuBarAutoHide()`
返回 boolean,窗口的菜单栏是否可以自动隐藏.
### `win.setMenuBarVisibility(visible)`
* `visible` Boolean
设置菜单栏是否可见.如果菜单栏自动隐藏,用户仍然可以按下 `Alt` 键来显示.
### `win.isMenuBarVisible()`
返回 boolean,菜单栏是否可见.
### `win.setVisibleOnAllWorkspaces(visible)`
* `visible` Boolean
设置窗口是否在所有地方都可见.
**注意:** 这个api 在windows无效.
### `win.isVisibleOnAllWorkspaces()`
返回 boolean,窗口是否在所有地方都可见.
**注意:** 在 windows上始终返回 false.
### `win.setIgnoreMouseEvents(ignore)` _OS X_
* `ignore` Boolean
忽略窗口的所有鼠标事件.
[blink-feature-string]: https://code.google.com/p/chromium/codesearch#chromium/src/out/Debug/gen/blink/platform/RuntimeEnabledFeatures.cpp&sq=package:chromium&type=cs&l=527

View File

@@ -0,0 +1,140 @@
# 支持的 Chrome 命令行开关
这页列出了Chrome浏览器和Electron支持的命令行开关. 你也可以在[app][app]模块的[ready][ready]事件发出之前使用[app.commandLine.appendSwitch][append-switch] 来添加它们到你应用的main脚本里面:
```javascript
const app = require('electron').app;
app.commandLine.appendSwitch('remote-debugging-port', '8315');
app.commandLine.appendSwitch('host-rules', 'MAP * 127.0.0.1');
app.on('ready', function() {
// Your code here
});
```
## --client-certificate=`path`
设置客户端的证书文件 `path` .
## --ignore-connections-limit=`domains`
忽略用 `,` 分隔的 `domains` 列表的连接限制.
## --disable-http-cache
禁用 HTTP 请求.
## --remote-debugging-port=`port`
在指定的 `端口` 通过 HTTP 开启远程调试.
## --js-flags=`flags`
指定引擎过渡到 JS 引擎.
在启动Electron时如果你想在主进程中激活 `flags` ,它将被转换.
```bash
$ electron --js-flags="--harmony_proxies --harmony_collections" your-app
```
## --proxy-server=`address:port`
使用一个特定的代理服务器,它将比系统设置的优先级更高.这个开关只有在使用 HTTP 协议时有效,它包含 HTTPS 和 WebSocket 请求. 值得注意的是,不是所有的代理服务器都支持 HTTPS 和 WebSocket 请求.
## --proxy-bypass-list=`hosts`
让 Electron 使用(原文:bypass) 提供的以 semi-colon 分隔的hosts列表的代理服务器.这个开关只有在使用 `--proxy-server` 时有效.
例如:
```javascript
app.commandLine.appendSwitch('proxy-bypass-list', '<local>;*.google.com;*foo.com;1.2.3.4:5678')
```
将会为所有的hosts使用代理服务器除了本地地址 (`localhost`,
`127.0.0.1` etc.), `google.com` 子域, 以 `foo.com` 结尾的hosts和所有类似 `1.2.3.4:5678`的.
## --proxy-pac-url=`url`
在指定的 `url` 上使用 PAC 脚本.
## --no-proxy-server
不使用代理服务并且总是使用直接连接.忽略所有的合理代理标志.
## --host-rules=`rules`
一个逗号分隔的 `rule` 列表来控制主机名如何映射.
例如:
* `MAP * 127.0.0.1` 强制所有主机名映射到 127.0.0.1
* `MAP *.google.com proxy` 强制所有 google.com 子域 使用 "proxy".
* `MAP test.com [::1]:77` 强制 "test.com" 使用 IPv6 回环地址. 也强制使用端口 77.
* `MAP * baz, EXCLUDE www.google.com` 重新全部映射到 "baz", 除了
"www.google.com".
这些映射适用于终端网络请求
(TCP 连接
和 主机解析 以直接连接的方式, 和 `CONNECT` 以代理连接, 还有 终端 host 使用 `SOCKS` 代理连接).
## --host-resolver-rules=`rules`
类似 `--host-rules` ,但是 `rules` 只适合主机解析.
## --ignore-certificate-errors
忽略与证书相关的错误.
## --ppapi-flash-path=`path`
设置Pepper Flash插件的路径 `path` .
## --ppapi-flash-version=`version`
设置Pepper Flash插件版本号.
## --log-net-log=`path`
使网络日志事件能够被读写到 `path`.
## --ssl-version-fallback-min=`version`
设置最简化的 SSL/TLS 版本号 ("tls1", "tls1.1" or "tls1.2")TLS 可接受回退.
## --cipher-suite-blacklist=`cipher_suites`
指定逗号分隔的 SSL 密码套件 列表实效.
## --disable-renderer-backgrounding
防止 Chromium 降低隐藏的渲染进程优先级.
这个标志对所有渲染进程全局有效,如果你只想在一个窗口中禁止使用,你可以采用 hack 方法[playing silent audio][play-silent-audio].
## --enable-logging
打印 Chromium 信息输出到控制台.
如果在用户应用加载完成之前解析`app.commandLine.appendSwitch` ,这个开关将实效,但是你可以设置 `ELECTRON_ENABLE_LOGGING` 环境变量来达到相同的效果.
## --v=`log_level`
设置默认最大活跃 V-logging 标准; 默认为 0.通常 V-logging 标准值为肯定值.
这个开关只有在 `--enable-logging` 开启时有效.
## --vmodule=`pattern`
赋予每个模块最大的 V-logging levels 来覆盖 `--v` 给的值.E.g. `my_module=2,foo*=3` 会改变所有源文件 `my_module.*` and `foo*.*` 的代码中的 logging level .
任何包含向前的(forward slash)或者向后的(backward slash)模式将被测试用于阻止整个路径名并且不仅是E.g模块.`*/foo/bar/*=2` 将会改变所有在 `foo/bar` 下的源文件代码中的 logging level .
这个开关只有在 `--enable-logging` 开启时有效.
[app]: app.md
[append-switch]: app.md#appcommandlineappendswitchswitch-value
[ready]: app.md#event-ready
[play-silent-audio]: https://github.com/atom/atom/pull/9485/files

View File

@@ -0,0 +1,129 @@
# contentTracing
`content-tracing` 模块是用来收集由底层的Chromium content 模块 产生的搜索数据. 这个模块不具备web接口所有需要我们在chrome浏览器中添加 `chrome://tracing/` 来加载生成文件从而查看结果.
```javascript
const contentTracing = require('electron').contentTracing;
const options = {
categoryFilter: '*',
traceOptions: 'record-until-full,enable-sampling'
}
contentTracing.startRecording(options, function() {
console.log('Tracing started');
setTimeout(function() {
contentTracing.stopRecording('', function(path) {
console.log('Tracing data recorded to ' + path);
});
}, 5000);
});
```
## 方法
`content-tracing` 模块的方法如下:
### `contentTracing.getCategories(callback)`
* `callback` Function
获得一组分类组. 分类组可以更改为新的代码路径。
一旦所有的子进程都接受到了`getCategories`方法请求, 分类组将调用 `callback`.
### `contentTracing.startRecording(options, callback)`
* `options` Object
* `categoryFilter` String
* `traceOptions` String
* `callback` Function
开始向所有进程进行记录.(recording)
一旦收到可以开始记录的请求,记录将会立马启动并且在子进程是异步记录听的. 当所有的子进程都收到 `startRecording` 请求的时候,`callback` 将会被调用.
`categoryFilter`是一个过滤器,它用来控制那些分类组应该被用来查找.过滤器应当有一个可选的 `-` 前缀来排除匹配的分类组.不允许同一个列表既是包含又是排斥.
例子:
* `test_MyTest*`,
* `test_MyTest*,test_OtherStuff`,
* `"-excluded_category1,-excluded_category2`
`traceOptions` 控制着哪种查找应该被启动,这是一个用逗号分隔的列表.可用参数如下:
* `record-until-full`
* `record-continuously`
* `trace-to-console`
* `enable-sampling`
* `enable-systrace`
前3个参数是来查找记录模块并且以后都互斥.如果在`traceOptions` 中超过一个跟踪
记录模式,那最后一个的优先级最高.如果没有指明跟踪
记录模式,那么它默认为 `record-until-full`.
`traceOptions` 中的参数被解析应用之前,查找参数初始化默认为 (`record_mode` 设置为
`record-until-full`, `enable_sampling``enable_systrace` 设置为 `false`).
### `contentTracing.stopRecording(resultFilePath, callback)`
* `resultFilePath` String
* `callback` Function
停止对所有子进程的记录.
子进程通常缓存查找数据,并且仅仅将数据截取和发送给主进程.这有利于在通过 IPC 发送查找数据之前减小查找时的运行开销,这样做很有价值.因此,发送查找数据,我们应当异步通知所有子进程来截取任何待查找的数据.
一旦所有子进程接收到了 `stopRecording` 请求,将调用 `callback` ,并且返回一个包含查找数据的文件.
如果 `resultFilePath` 不为空,那么将把查找数据写入其中,否则写入一个临时文件.实际文件路径如果不为空,则将调用 `callback` .
### `contentTracing.startMonitoring(options, callback)`
* `options` Object
* `categoryFilter` String
* `traceOptions` String
* `callback` Function
开始向所有进程进行监听.(monitoring)
一旦收到可以开始监听的请求,记录将会立马启动并且在子进程是异步记监听的. 当所有的子进程都收到 `startMonitoring` 请求的时候,`callback` 将会被调用.
### `contentTracing.stopMonitoring(callback)`
* `callback` Function
停止对所有子进程的监听.
一旦所有子进程接收到了 `stopMonitoring` 请求,将调用 `callback` .
### `contentTracing.captureMonitoringSnapshot(resultFilePath, callback)`
* `resultFilePath` String
* `callback` Function
获取当前监听的查找数据.
子进程通常缓存查找数据,并且仅仅将数据截取和发送给主进程.因为如果直接通过 IPC 来发送查找数据的代价昂贵,我们宁愿避免不必要的查找运行开销.因此,为了停止查找,我们应当异步通知所有子进程来截取任何待查找的数据.
一旦所有子进程接收到了 `captureMonitoringSnapshot` 请求,将调用 `callback` ,并且返回一个包含查找数据的文件.
### `contentTracing.getTraceBufferUsage(callback)`
* `callback` Function
通过查找 buffer 进程来获取百分比最大使用量.当确定了TraceBufferUsage 的值确定的时候,就调用 `callback` .
### `contentTracing.setWatchEvent(categoryName, eventName, callback)`
* `categoryName` String
* `eventName` String
* `callback` Function
任意时刻在任何进程上指定事件发生时将调用 `callback` .
### `contentTracing.cancelWatchEvent()`
取消 watch 事件. 如果启动查找,这或许会造成 watch 事件的回调函数 出错.

View File

@@ -0,0 +1,94 @@
# dialog
`dialog` 模块提供了api来展示原生的系统对话框例如打开文件框alert框所以web应用可以给用户带来跟系统应用相同的体验.
对话框例子,展示了选择文件和目录:
```javascript
var win = ...; // BrowserWindow in which to show the dialog
const dialog = require('electron').dialog;
console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', 'multiSelections' ]}));
```
**OS X 上的注意事项**: 如果你想像sheets一样展示对话框只需要在`browserWindow` 参数中提供一个 `BrowserWindow` 的引用对象.
## 方法
`dialog` 模块有以下方法:
### `dialog.showOpenDialog([browserWindow, ]options[, callback])`
* `browserWindow` BrowserWindow (可选)
* `options` Object
* `title` String
* `defaultPath` String
* `filters` Array
* `properties` Array - 包含了对话框的特性值, 可以包含 `openFile`, `openDirectory`, `multiSelections` and
`createDirectory`
* `callback` Function (可选)
成功使用这个方法的话,就返回一个可供用户选择的文件路径数组,失败返回 `undefined`.
`filters` 当需要限定用户的行为的时候,指定一个文件数组给用户展示或选择. 例如:
```javascript
{
filters: [
{ name: 'Images', extensions: ['jpg', 'png', 'gif'] },
{ name: 'Movies', extensions: ['mkv', 'avi', 'mp4'] },
{ name: 'Custom File Type', extensions: ['as'] },
{ name: 'All Files', extensions: ['*'] }
]
}
```
`extensions` 数组应当只包含扩展名,不应该包含通配符或'.'号 (例如
`'png'` 正确,但是 `'.png'``'*.png'` 不正确). 展示全部文件的话, 使用
`'*'` 通配符 (不支持其他通配符).
如果 `callback` 被调用, 将异步调用 API ,并且结果将用过 `callback(filenames)` 展示.
**注意:** 在 Windows 和 Linux ,一个打开的 dialog 不能既是文件选择框又是目录选择框, 所以如果在这些平台上设置 `properties` 的值为
`['openFile', 'openDirectory']` , 将展示一个目录选择框.
### `dialog.showSaveDialog([browserWindow, ]options[, callback])`
* `browserWindow` BrowserWindow (可选)
* `options` Object
* `title` String
* `defaultPath` String
* `filters` Array
* `callback` Function (可选)
成功使用这个方法的话,就返回一个可供用户选择的文件路径数组,失败返回 `undefined`.
`filters` 指定展示一个文件类型数组, 例子
`dialog.showOpenDialog` .
如果 `callback` 被调用, 将异步调用 API ,并且结果将用过 `callback(filenames)` 展示.
### `dialog.showMessageBox([browserWindow, ]options[, callback])`
* `browserWindow` BrowserWindow (可选)
* `options` Object
* `type` String - 可以是 `"none"`, `"info"`, `"error"`, `"question"`
`"warning"`. 在 Windows, "question" 与 "info" 展示图标相同, 除非你使用 "icon" 参数.
* `buttons` Array - buttons 内容,数组.
* `defaultId` Integer - 在message box 对话框打开的时候设置默认button选中值为在 buttons 数组中的button索引.
* `title` String - message box 的标题,一些平台不显示.
* `message` String - message box 内容.
* `detail` String - 额外信息.
* `icon` [NativeImage](native-image.md)
* `cancelId` Integer - 当用户关闭对话框的时候不是通过点击对话框的button就返回值.默认值为对应 "cancel" 或 "no" 标签button 的索引值, 或者如果没有这种button就返回0. 在 OS X 和 Windows 上, "Cancel" button 的索引值将一直是 `cancelId`, 不管之前是不是特别指出的.
* `noLink` Boolean - 在 Windows Electron 将尝试识别哪个button 是普通 button (如 "Cancel" 或 "Yes"), 然后再对话框中以链接命令(command links)方式展现其它的 button . 这能让对话框展示得很炫酷.如果你不喜欢这种效果,你可以设置 `noLink``true`.
* `callback` Function
展示 message box, 它会阻塞进程,直到 message box 关闭为止.返回点击按钮的索引值.
如果 `callback` 被调用, 将异步调用 API ,并且结果将用过 `callback(response)` 展示.
### `dialog.showErrorBox(title, content)`
展示一个传统的包含错误信息的对话框.
`app` 模块触发 `ready` 事件之前,这个 api 可以被安全调用,通常它被用来在启动的早期阶段报告错误. 在 Linux 上,如果在 `app` 模块触发 `ready` 事件之前调用message 将会被触发显示stderr并且没有实际GUI 框显示.

View File

@@ -0,0 +1,53 @@
# 环境变量
一些 Electron 的行为受到环境变量的控制,因为他们的初始化比命令行和应用代码更早.
POSIX shells 的例子:
```bash
$ export ELECTRON_ENABLE_LOGGING=true
$ electron
```
Windows 控制台:
```powershell
> set ELECTRON_ENABLE_LOGGING=true
> electron
```
## `ELECTRON_RUN_AS_NODE`
类似node.js普通进程启动方式.
## `ELECTRON_ENABLE_LOGGING`
打印 Chrome 的内部日志到控制台.
## `ELECTRON_LOG_ASAR_READS`
当 Electron 读取 ASA 文档,把 read offset 和文档路径做日志记录到系统 `tmpdir`.结果文件将提供给 ASAR 模块来优化文档组织.
## `ELECTRON_ENABLE_STACK_DUMPING`
当 Electron 崩溃的时候,打印堆栈记录到控制台.
如果 `crashReporter` 已经启动那么这个环境变量实效.
## `ELECTRON_DEFAULT_ERROR_MODE` _Windows_
当 Electron 崩溃的时候显示windows的崩溃对话框.
如果 `crashReporter` 已经启动那么这个环境变量实效.
## `ELECTRON_NO_ATTACH_CONSOLE` _Windows_
不可使用当前控制台.
## `ELECTRON_FORCE_WINDOW_MENU_BAR` _Linux_
不可再 Linux 上使用全局菜单栏.
## `ELECTRON_HIDE_INTERNAL_MODULES`
关闭旧的内置模块如 `require('ipc')` 的通用模块.

View File

@@ -0,0 +1,57 @@
# 菜单项
菜单项模块允许你向应用或[menu][1]添加选项。
查看[menu][1]例子。
## 类MenuItem
使用下面的方法创建一个新的 `MenuItem`
###new MenuItem(options)
* `options` Object
* `click` Function - 当菜单项被点击的时候,使用 `click(menuItem,browserWindow)` 调用
* `role` String - 定义菜单项的行为,在指定 `click` 属性时将会被忽略
* `type` String - 取值 `normal``separator``checkbox`or`radio`
* `label` String
* `sublabel` String
* `accelerator` [Accelerator][2]
* `icon` [NativeImage][3]
* `enabled` Boolean
* `visible` Boolean
* `checked` Boolean
* `submenu` Menu - 应当作为 `submenu` 菜单项的特定类型,当它作为 `type: 'submenu'` 菜单项的特定类型时可以忽略。如果它的值不是 `Menu`,将自动转为 `Menu.buildFromTemplate`
* `id` String - 标志一个菜单的唯一性。如果被定义使用,它将被用作这个菜单项的参考位置属性。
* `position` String - 定义给定的菜单的具体指定位置信息。
在创建菜单项时,如果有匹配的方法,建议指定 `role` 属性,不需要人为操作它的行为,这样菜单使用可以给用户最好的体验。
`role`属性值可以为:
* `undo`
* `redo`
* `cut`
* `copy`
* `paste`
* `selectall`
* `minimize` - 最小化当前窗口
* `close` - 关闭当前窗口
在 OS X 上,`role` 还可以有以下值:
* `about` - 匹配 `orderFrontStandardAboutPanel` 行为
* `hide` - 匹配 `hide` 行为
* `hideothers` - 匹配 `hideOtherApplications` 行为
* `unhide` - 匹配 `unhideAllApplications` 行为
* `front` - 匹配 `arrangeInFront` 行为
* `window` - "Window" 菜单项
* `help` - "Help" 菜单项
* `services` - "Services" 菜单项
[1]:https://github.com/heyunjiang/electron/blob/master/docs-translations/zh-CN/api/menu.md
[2]:https://github.com/heyunjiang/electron/blob/master/docs/api/accelerator.md
[3]:https://github.com/heyunjiang/electron/blob/master/docs/api/native-image.md

View File

@@ -0,0 +1,48 @@
# 进程
Electron 中的 `process` 对象 与 upstream node 中的有以下的不同点:
* `process.type` String - 进程类型, 可以是 `browser` (i.e. main process)
`renderer`.
* `process.versions['electron']` String - Electron的版本.
* `process.versions['chrome']` String - Chromium的版本.
* `process.resourcesPath` String - JavaScript源代码路径.
* `process.mas` Boolean - 在Mac App Store 创建, 它的值为 `true`, 在其它的地方值为 `undefined`.
## 事件
### 事件: 'loaded'
在Electron已经加载了其内部预置脚本和它准备加载主进程或渲染进程的时候触发.
当node被完全关闭的时候它可以被预加载脚本使用来添加(原文: removed)与node无关的全局符号来回退到全局范围:
```js
// preload.js
var _setImmediate = setImmediate;
var _clearImmediate = clearImmediate;
process.once('loaded', function() {
global.setImmediate = _setImmediate;
global.clearImmediate = _clearImmediate;
});
```
## 属性
### `process.noAsar`
设置它为 `true` 可以使 `asar` 文件在node的内置模块中实效.
## 方法
`process` 对象有如下方法:
### `process.hang()`
使当前进程的主线成挂起.
### `process.setFdLimit(maxDescriptors)` _OS X_ _Linux_
* `maxDescriptors` Integer
设置文件描述符软限制于 `maxDescriptors` 或硬限制与os, 无论它是否低于当前进程.

View File

@@ -0,0 +1,71 @@
# 简介
所有的[Node.js's built-in modules][1]在Electron中都可用并且所有的node的第三方组件也可以放心使用包括[自身的模块][2])。
Electron也提供了一些额外的内置组件来开发传统桌面应用。一些组件只可以在主进程中使用一些只可以在渲染进程中使用但是也有部分可以在这2种进程中都可使用。
基本规则GUI模块或者系统底层的模块只可以在主进程中使用。要使用这些模块你应当很熟悉[主进程vs渲染进程][3]脚本的概念。
主进程脚本看起来像个普通的nodejs脚本
```javascript
const electron = require('electron');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
var window = null;
app.on('ready', function() {
window = new BrowserWindow({width: 800, height: 600});
window.loadURL('https://github.com');
});
```
渲染进程和传统的web界面一样除了它具有使用node模块的能力
```html
<!DOCTYPE html>
<html>
<body>
<script>
const remote = require('electron').remote;
console.log(remote.app.getVersion());
</script>
</body>
</html>
```
如果想运行应用,参考 `Run your app`
## 解构任务
如果你使用的是CoffeeScript或Babel你可以使用[destructuring assignment][4]来让使用内置模块更简单:
```javascript
const {app, BrowserWindow} = require('electron');
```
然而如果你使用的是普通的JavaScript你就需要等到Chrome支持ES6了。
##使用内置模块时禁用旧样式
在版本v0.35.0之前,所有的内置模块都需要按造 `require('module-name')` 形式来使用,虽然它有很多[弊端][5],我们仍然在老的应用中友好的支持它。
为了完整的禁用旧样式,你可以设置环境变量 `ELECTRON_HIDE_INTERNAL_MODULES ` :
```javascript
process.env.ELECTRON_HIDE_INTERNAL_MODULES = 'true'
```
或者调用 `hideInternalModules` API:
```javascript
require('electron').hideInternalModules()
```
[1]:http://nodejs.org/api/
[2]:https://github.com/heyunjiang/electron/blob/master/docs/tutorial/using-native-node-modules.md
[3]:https://github.com/heyunjiang/electron/blob/master/docs/tutorial/quick-start.md#the-main-process
[4]:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
[5]:https://github.com/atom/electron/issues/387

View File

@@ -0,0 +1,690 @@
# `<webview>` 标签
使用 `webview` 标签来把 'guest' 内容(例如 web pages )嵌入到你的 Electron app 中. guest内容包含在 `webview` 容器中.一个嵌入你应用的page控制着guest内容如何布局摆放和表达含义.
`iframe` 不同, `webview` 和你的应用运行的是不同的进程. 它不拥有渲染进程的权限,并且应用和嵌入内容之间的交互全部都是异步的.因为这能保证应用的安全性不受嵌入内容的影响.
## 例子
把一个 web page 嵌入到你的app首先添加 `webview` 标签到你的app待嵌入page(展示 guest content). 在一个最简单的 `webview` 中,它包含了 web page 的文件路径和一个控制 `webview` 容器展示效果的css样式:
```html
<webview id="foo" src="https://www.github.com/" style="display:inline-block; width:640px; height:480px"></webview>
```
如果想随时控制 guest 内容,可以添加 JavaScript 脚本来监听 `webview` 事件使用 `webview` 方法来做出响应. 这里是2个事件监听的例子一个监听 web page 准备加载,另一个监听 web page 停止加载,并且在加载的时候显示一条 "loading..." 信息:
```html
<script>
onload = function() {
var webview = document.getElementById("foo");
var indicator = document.querySelector(".indicator");
var loadstart = function() {
indicator.innerText = "loading...";
}
var loadstop = function() {
indicator.innerText = "";
}
webview.addEventListener("did-start-loading", loadstart);
webview.addEventListener("did-stop-loading", loadstop);
}
</script>
```
## 标签属性
`webview` 标签有下面一些属性 :
### `src`
```html
<webview src="https://www.github.com/"></webview>
```
将一个可用的url做为这个属性的初始值添加到顶部导航.
如果把当前页的src添加进去将加载当前page.
`src`同样可以填 data urls例如
`data:text/plain,Hello, world!`.
### `autosize`
```html
<webview src="https://www.github.com/" autosize="on" minwidth="576" minheight="432"></webview>
```
如果这个属性的值为 "on" `webview` 容器将会根据属性`minwidth`, `minheight`, `maxwidth`, 和
`maxheight` 的值在它们之间自适应. 只有在 `autosize` 开启的时候这个约束才会有效. 当 `autosize` 开启的时候, `webview` 容器的 size 只能在上面那四个属性值之间.
### `nodeintegration`
```html
<webview src="http://www.google.com/" nodeintegration></webview>
```
如果设置了这个属性, `webview` 中的 guest page 将整合node并且拥有可以使用系统底层的资源例如 `require``process` .
### `plugins`
```html
<webview src="https://www.github.com/" plugins></webview>
```
如果这个属性的值为 "on" `webview` 中的 guest page 就可以使用浏览器插件。
### `preload`
```html
<webview src="https://www.github.com/" preload="./test.js"></webview>
```
在 guest page 中的其他脚本执行之前预加载一个指定的脚本。规定预加载脚本的url须如 `file:` 或者 `asar:`,因为它在是 guest page 中通过通过 `require` 命令加载的。
如果 guest page 没有整合 node ,这个脚本将试图使用真个 Node APIs 但是在这个脚本执行完毕时之前由node插入的全局对象会被删除。
### `httpreferrer`
```html
<webview src="https://www.github.com/" httpreferrer="http://cheng.guru"></webview>
```
为 guest page 设置 referrer URL。
### `useragent`
```html
<webview src="https://www.github.com/" useragent="Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko"></webview>
```
在 guest page 加载之前为其设置用户代理。如果页面已经加载了,可以使用 `setUserAgent` 方法来改变用户代理。
### `disablewebsecurity`
```html
<webview src="https://www.github.com/" disablewebsecurity></webview>
```
如果这个属性的值为 "on" guest page会禁用web安全控制.
### partition
```html
<webview src="https://github.com" partition="persist:github"></webview>
<webview src="http://electron.atom.io" partition="electron"></webview>
```
为page设置session。如果初始值为 `partition` ,这个 page 将会为app中的所有 page 应用同一个持续有效的 session。如果没有 `persist:` 前缀, 这个 page 将会使用一个历史 session 。通过分配使用相同的 `partition`, 所有的page都可以分享相同的session。如果 `partition` 没有设置那app将使用默认的session.
这个值只能在在第一个渲染进程之前设置修改之后修改的话会无效并且抛出一个DOM异常.
### `allowpopups`
```html
<webview src="https://www.github.com/" allowpopups></webview>
```
如果这个属性的值为 "on" ,将允许 guest page 打开一个新窗口。
### `blinkfeatures`
```html
<webview src="https://www.github.com/" blinkfeatures="PreciseMemoryInfo, CSSVariables"></webview>
```
这个属性的值为一个用逗号分隔的列表,它的值指定特性被启用。你可以从[setFeatureEnabledFromString][blink-feature-string]函数找到完整的支持特性。
## 方法
`webview` 的方法集合:
**注意:** webview 元素必须在使用这些方法之前加载完毕。
**例如**
```javascript
webview.addEventListener("dom-ready", function() {
webview.openDevTools();
});
```
### `<webview>.loadURL(url[, options])`
* `url` URL
* `options` Object (可选)
* `httpReferrer` String - 一个http类型的url.
* `userAgent` String -用于发起请求的用户代理.
* `extraHeaders` String - 额外的headers,用 "\n"分隔.
加载 webview 中的 `url``url` 必须包含协议前缀,例如 `http://``file://`.
### `<webview>.getURL()`
从 guest page 中返回 url.
### `<webview>.getTitle()`
从 guest page 中返回 title.
### `<webview>.isLoading()`
返回一个 guest page 是否仍在加载资源的布尔值.
### `<webview>.isWaitingForResponse()`
返回一个 guest page 是否正在等待page的主要资源做出回应的布尔值.
### `<webview>.stop()`
停止渲染.
### `<webview>.reload()`
重新加载 guest page.
### `<webview>.reloadIgnoringCache()`
忽视缓存,重新加载 guest page.
### `<webview>.canGoBack()`
返回一个 guest page 是否能够回退的布尔值.
### `<webview>.canGoForward()`
返回一个 guest page 是否能够前进的布尔值.
### `<webview>.canGoToOffset(offset)`
* `offset` Integer
返回一个 guest page 是否能够前进到 `offset` 的布尔值.
### `<webview>.clearHistory()`
清除导航历史.
### `<webview>.goBack()`
guest page 回退.
### `<webview>.goForward()`
guest page 前进.
### `<webview>.goToIndex(index)`
* `index` Integer
guest page 导航到指定的绝对位置.
### `<webview>.goToOffset(offset)`
* `offset` Integer
guest page 导航到指定的相对位置.
### `<webview>.isCrashed()`
返回一个 渲染进程是否崩溃 的布尔值.
### `<webview>.setUserAgent(userAgent)`
* `userAgent` String
重新设置用户代理.
### `<webview>.getUserAgent()`
返回用户代理名字,返回类型:`String`.
### `<webview>.insertCSS(css)`
* `css` String
插入css.
### `<webview>.executeJavaScript(code, userGesture, callback)`
* `code` String
* `userGesture` Boolean - 默认 `false`.
* `callback` Function (可选) - 回调函数.
* `result`
评估 `code` ,如果 `userGesture` 值为 true 它将在这个page里面创建用户手势. HTML APIs ,如 `requestFullScreen`,它需要用户响应,那么将自动通过这个参数优化.
### `<webview>.openDevTools()`
为 guest page 打开开发工具调试窗口.
### `<webview>.closeDevTools()`
为 guest page 关闭开发工具调试窗口.
### `<webview>.isDevToolsOpened()`
返回一个 guest page 是否打开了开发工具调试窗口的布尔值.
### `<webview>.isDevToolsFocused()`
返回一个 guest page 是否聚焦了开发工具调试窗口的布尔值.
### `<webview>.inspectElement(x, y)`
* `x` Integer
* `y` Integer
开始检查 guest page 在 (`x`, `y`) 位置的元素.
### `<webview>.inspectServiceWorker()`
在 guest page 中为服务人员打开开发工具.
### `<webview>.setAudioMuted(muted)`
* `muted` Boolean
设置 guest page 流畅(muted).
### `<webview>.isAudioMuted()`
返回一个 guest page 是否流畅的布尔值.
### `<webview>.undo()`
在page中编辑执行 `undo` 命令.
### `<webview>.redo()`
在page中编辑执行 `redo` 命令.
### `<webview>.cut()`
在page中编辑执行 `cut` 命令.
### `<webview>.copy()`
在page中编辑执行 `copy` 命令.
### `<webview>.paste()`
在page中编辑执行 `paste` 命令.
### `<webview>.pasteAndMatchStyle()`
在page中编辑执行 `pasteAndMatchStyle` 命令.
### `<webview>.delete()`
在page中编辑执行 `delete` 命令.
### `<webview>.selectAll()`
在page中编辑执行 `selectAll` 命令.
### `<webview>.unselect()`
在page中编辑执行 `unselect` 命令.
### `<webview>.replace(text)`
* `text` String
在page中编辑执行 `replace` 命令.
### `<webview>.replaceMisspelling(text)`
* `text` String
在page中编辑执行 `replaceMisspelling` 命令.
### `<webview>.insertText(text)`
* `text` String
插入文本.
### `<webview>.findInPage(text[, options])`
* `text` String - 搜索内容,不能为空.
* `options` Object (可选)
* `forward` Boolean - 向前或向后, 默认为 `true`.
* `findNext` Boolean - 是否查找的第一个结果,
默认为 `false`.
* `matchCase` Boolean - 是否区分大小写,
默认为 `false`.
* `wordStart` Boolean - 是否只查找首字母.
默认为 `false`.
* `medialCapitalAsWordStart` Boolean - 当配合 `wordStart`的时候,接受一个文字中的匹配项,要求匹配项是以大写字母开头后面跟小写字母或者没有字母。可以接受一些其他单词内部匹配, 默认为 `false`.
发起一个请求来寻找页面中的所有匹配 `text` 的地方并且返回一个 `Integer`来表示这个请求用的请求Id. 这个请求结果可以通过订阅[`found-in-page`](web-view-tag.md#event-found-in-page) 事件来取得.
### `<webview>.stopFindInPage(action)`
* `action` String - 指定一个行为来接替停止
[`<webview>.findInPage`](web-view-tag.md#webviewtagfindinpage) 请求.
* `clearSelection` - 转变为一个普通的 selection.
* `keepSelection` - 清除 selection.
* `activateSelection` - 聚焦并点击 selection node.
使用 `action` 停止 `findInPage` 请求.
### `<webview>.print([options])`
打印输出 `webview` 的 web page. 类似 `webContents.print([options])`.
### `<webview>.printToPDF(options, callback)`
以pdf格式打印输出 `webview` 的 web page. 类似 `webContents.printToPDF(options, callback)`.
### `<webview>.send(channel[, arg1][, arg2][, ...])`
* `channel` String
* `arg` (可选)
通过 `channel` 向渲染进程发出异步消息,你也可以发送任意的参数。
渲染进程通过`ipcRenderer` 模块监听 `channel` 事件来控制消息.
例子
[webContents.send](web-contents.md#webcontentssendchannel-args).
### `<webview>.sendInputEvent(event)`
* `event` Object
向 page 发送输入事件.
查看 [webContents.sendInputEvent](web-contents.md##webcontentssendinputeventevent)
关于 `event` 对象的相信介绍.
### `<webview>.getWebContents()`
返回和这个 `webview` 相关的 [WebContents](web-contents.md).
## DOM 事件
`webview` 可用下面的 DOM 事件:
### Event: 'load-commit'
返回:
* `url` String
* `isMainFrame` Boolean
加载完成触发. 这个包含当前文档的导航和副框架的文档加载,但是不包含异步资源加载.
### Event: 'did-finish-load'
在导航加载完成时触发也就是tab 的 spinner停止spinning并且加载事件处理.
### Event: 'did-fail-load'
Returns:
* `errorCode` Integer
* `errorDescription` String
* `validatedURL` String
类似 `did-finish-load` ,在加载失败或取消是触发,例如提出 `window.stop()`.
### Event: 'did-frame-finish-load'
返回:
* `isMainFrame` Boolean
当一个 frame 完成 加载时触发.
### Event: 'did-start-loading'
开始加载时触发.
### Event: 'did-stop-loading'
停止家在时触发.
### Event: 'did-get-response-details'
返回:
* `status` Boolean
* `newURL` String
* `originalURL` String
* `httpResponseCode` Integer
* `requestMethod` String
* `referrer` String
* `headers` Object
当获得返回详情的时候触发.
`status` 指示 socket 连接来下载资源.
### Event: 'did-get-redirect-request'
返回:
* `oldURL` String
* `newURL` String
* `isMainFrame` Boolean
当重定向请求资源被接收的时候触发.
### Event: 'dom-ready'
当指定的frame文档加载完毕时触发.
### Event: 'page-title-updated'
返回:
* `title` String
* `explicitSet` Boolean
当导航中的页面title被设置时触发.
在title通过文档路径异步加载时`explicitSet`为false.
### Event: 'page-favicon-updated'
返回:
* `favicons` Array - Array of URLs.
当page收到了图标url时触发.
### Event: 'enter-html-full-screen'
当通过HTML API使界面进入全屏时触发.
### Event: 'leave-html-full-screen'
当通过HTML API使界面退出全屏时触发.
### Event: 'console-message'
返回:
* `level` Integer
* `message` String
* `line` Integer
* `sourceId` String
当客户端输出控制台信息的时候触发.
下面示例代码将所有信息输出到内置控制台,没有考虑到输出等级和其他属性。
```javascript
webview.addEventListener('console-message', function(e) {
console.log('Guest page logged a message:', e.message);
});
```
### Event: 'found-in-page'
返回:
* `result` Object
* `requestId` Integer
* `finalUpdate` Boolean - 指明下面是否还有更多的回应.
* `matches` Integer (optional) - 匹配数量.
* `selectionArea` Object (optional) - 整合第一个匹配域.
在请求[`webview.findInPage`](web-view-tag.md#webviewtagfindinpage)结果有效时触发.
```javascript
webview.addEventListener('found-in-page', function(e) {
if (e.result.finalUpdate)
webview.stopFindInPage("keepSelection");
});
const rquestId = webview.findInPage("test");
```
### Event: 'new-window'
返回:
* `url` String
* `frameName` String
* `disposition` String - 可以为 `default`, `foreground-tab`, `background-tab`,
`new-window``other`.
* `options` Object - 参数应该被用作创建新的
`BrowserWindow`.
在 guest page 试图打开一个新的浏览器窗口时触发.
下面示例代码在系统默认浏览器中打开了一个新的url.
```javascript
webview.addEventListener('new-window', function(e) {
require('electron').shell.openExternal(e.url);
});
```
### Event: 'will-navigate'
返回:
* `url` String
当用户或page尝试开始导航时触发.
它能在 `window.location` 变化或者用户点击连接的时候触发.
这个事件在以 APIS 编程方式开始导航时不会触发,例如 `<webview>.loadURL``<webview>.back`.
在页面内部导航跳转也将不回触发这个事件,例如点击锚链接或更新 `window.location.hash`.使用 `did-navigate-in-page` 来实现页内跳转事件.
使用 `event.preventDefault()` 并不会起什么用.
### Event: 'did-navigate'
返回:
* `url` String
当导航结束时触发.
在页面内部导航跳转也将不回触发这个事件,例如点击锚链接或更新 `window.location.hash`.使用 `did-navigate-in-page` 来实现页内跳转事件.
### Event: 'did-navigate-in-page'
返回:
* `url` String
当页内导航发生时触发.
当业内导航发生时page url改变了但是不会跳出 page . 例如在锚链接被电击或DOM `hashchange` 事件发生时触发.
### Event: 'close'
在 guest page试图关闭自己的时候触发.
下面的示例代码指示了在客户端试图关闭自己的时候将改变导航连接为`about:blank`.
```javascript
webview.addEventListener('close', function() {
webview.src = 'about:blank';
});
```
### Event: 'ipc-message'
返回:
* `channel` String
* `args` Array
在 guest page 向嵌入页发送一个异步消息的时候触发.
你可以很简单的使用 `sendToHost` 方法和 `ipc-message` 事件在 guest page 和 嵌入页(embedder page)之间通信:
```javascript
// In embedder page.
webview.addEventListener('ipc-message', function(event) {
console.log(event.channel);
// Prints "pong"
});
webview.send('ping');
```
```javascript
// In guest page.
var ipcRenderer = require('electron').ipcRenderer;
ipcRenderer.on('ping', function() {
ipcRenderer.sendToHost('pong');
});
```
### Event: 'crashed'
在渲染进程崩溃的时候触发.
### Event: 'gpu-crashed'
在GPU进程崩溃的时候触发.
### Event: 'plugin-crashed'
返回:
* `name` String
* `version` String
在插件进程崩溃的时候触发.
### Event: 'destroyed'
在界面内容销毁的时候触发.
### Event: 'media-started-playing'
在媒体准备播放的时候触发.
### Event: 'media-paused'
在媒体暂停播放或播放放毕的时候触发.
### Event: 'did-change-theme-color'
在页面的主体色改变的时候触发.
在使用 meta 标签的时候这就很常见了:
```html
<meta name='theme-color' content='#ff0000'>
```
### Event: 'devtools-opened'
在开发者工具打开的时候触发.
### Event: 'devtools-closed'
在开发者工具关闭的时候触发.
### Event: 'devtools-focused'
在开发者工具获取焦点的时候触发.
[blink-feature-string]: https://code.google.com/p/chromium/codesearch#chromium/src/out/Debug/gen/blink/platform/RuntimeEnabledFeatures.cpp&sq=package:chromium&type=cs&l=527

View File

@@ -0,0 +1,60 @@
# `window.open` 函数
当在界面中使用 `window.open` 来创建一个新的窗口时候,将会创建一个 `BrowserWindow` 的实例,并且将返回一个标识,这个界面通过标识来对这个新的窗口进行有限的控制.
这个标识对传统的web界面来说通过它能对子窗口进行有限的功能性兼容控制.
想要完全的控制这个窗口,可以直接创建一个 `BrowserWindow` .
新创建的 `BrowserWindow` 默认为继承父窗口的属性参数,想重写属性的话可以在 `features` 中设置他们.
### `window.open(url[, frameName][, features])`
* `url` String
* `frameName` String (可选)
* `features` String (可选)
创建一个新的window并且返回一个 `BrowserWindowProxy` 类的实例.
`features` 遵循标准浏览器的格式但是每个feature 应该作为 `BrowserWindow` 参数的一个字段.
### `window.opener.postMessage(message, targetOrigin)`
* `message` String
* `targetOrigin` String
通过指定位置或用 `*` 来代替没有明确位置来向父窗口发送信息.
## Class: BrowserWindowProxy
`BrowserWindowProxy``window.open` 创建返回,并且提供了对子窗口的有限功能性控制.
### `BrowserWindowProxy.blur()`
子窗口的失去焦点.
### `BrowserWindowProxy.close()`
强行关闭子窗口,忽略卸载事件.
### `BrowserWindowProxy.closed`
在子窗口关闭之后恢复正常.
### `BrowserWindowProxy.eval(code)`
* `code` String
评估子窗口的代码.
### `BrowserWindowProxy.focus()`
子窗口获得焦点(让其显示在最前).
### `BrowserWindowProxy.postMessage(message, targetOrigin)`
* `message` String
* `targetOrigin` String
通过指定位置或用 `*` 来代替没有明确位置来向子窗口发送信息.
除了这些方法,子窗口还可以无特性和使用单一方法来实现 `window.opener` 对象.

View File

@@ -0,0 +1,139 @@
# Electron 常见问题
## Electron 会在什么时候升级到最新版本的 Chrome
通常来说,在稳定版的 Chrome 发布后两周内,我们会更新 Electron 内的 Chrome 版本。
我们只会使用 stable 版本的 Chrome。但如果在 beta 或 dev 版本中有一个重要的更新,我们会把补丁应用到现版本的 Chrome 上。
## Electron 会在什么时候升级到最新版本的 Node.js
我们通常会在最新版的 Node.js 发布后一个月左右将 Electron 更新到这个版本的 Node.js。我们通过这种方式来避免新版本的 Node.js
带来的 bug这种 bug 太常见了)。
Node.js 的新特性通常是由新版本的 V8 带来的。由于 Electron 使用的是 Chrome 浏览器中附带的 V8 引擎,所以 Electron 内往往已经
有了部分新版本 Node.js 才有的崭新特性。
## 如何在两个网页间共享数据?
在两个网页(渲染进程)间共享数据最简单的方法是使用浏览器中已经实现的 HTML5 API比较好的方案是用 [Storage API][storage]
[`localStorage`][local-storage][`sessionStorage`][session-storage] 或者 [IndexedDB][indexed-db]。
你还可以用 Electron 内的 IPC 机制实现。将数据存在主进程的某个全局变量中,然后在多个渲染进程中使用 `remote` 模块来访问它。
```javascript
// 在主进程中
global.sharedObject = {
someProperty: 'default value'
};
```
```javascript
// 在第一个页面中
require('remote').getGlobal('sharedObject').someProperty = 'new value';
```
```javascript
// 在第二个页面中
console.log(require('remote').getGlobal('sharedObject').someProperty);
```
## 为什么应用的窗口、托盘在一段时间后不见了?
这通常是因为用来存放窗口、托盘的变量被垃圾收集了。
你可以参考以下两篇文章来了解为什么会遇到这个问题。
* [内存管理][memory-management]
* [变量作用域][variable-scope]
如果你只是要一个快速的修复方案,你可以用下面的方式改变变量的作用域,防止这个变量被垃圾收集。
```javascript
app.on('ready', function() {
var tray = new Tray('/path/to/icon.png');
})
```
改为
```javascript
var tray = null;
app.on('ready', function() {
tray = new Tray('/path/to/icon.png');
})
```
## 在 Electron 中,我为什么不能用 jQuery、RequireJS、Meteor、AngularJS
因为 Electron 在运行环境中引入了 Node.js所以在 DOM 中有一些额外的变量,比如 `module``exports``require`。这导致
了许多库不能正常运行,因为它们也需要将同名的变量加入运行环境中。
我们可以通过禁用 Node.js 来解决这个问题,用如下的方式:
```javascript
// 在主进程中
var mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: false
}
});
```
假如你依然需要使用 Node.js 和 Electron 提供的 API你需要在引入那些库之前将这些变量重命名比如
```html
<head>
<script>
// 重命名 Electron 提供的 require
window.nodeRequire = require;
delete window.require;
delete window.exports;
delete window.module;
</script>
<script type="text/javascript" src="jquery.js"></script>
</head>
```
## 为什么 `require('electron').xxx` 的结果是 undefined
在使用 Electron 的提供的模块时,你可能会遇到和以下类似的错误:
```
> require('electron').webFrame.setZoomFactor(1.0);
Uncaught TypeError: Cannot read property 'setZoomLevel' of undefined
```
这是因为你在项目中或者在全局中安装了[npm 上获取的 `electron` 模块][electron-module],它把 Electron 的内置模块覆写了。
你可以通过以下方式输出 `electron` 模块的路径来确认你是否使用了正确的模块。
```javascript
console.log(require.resolve('electron'));
```
确认以下它是不是像下面这样的:
```
"/path/to/Electron.app/Contents/Resources/atom.asar/renderer/api/lib/exports/electron.js"
```
假如输出的路径类似于 `node_modules/electron/index.js`,那么你需要移除或者重命名 npm 上的 `electron` 模块。
```bash
npm uninstall electron
npm uninstall -g electron
```
如果你依然遇到了这个问题,你可能需要检查一下拼写或者是否在错误的进程中调用了这个模块。比如,
`require('electron').app` 只能在主进程中使用, 然而 `require('electron').webFrame` 只能在渲染进程中使用。
[memory-management]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management
[variable-scope]: https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx
[electron-module]: https://www.npmjs.com/package/electron
[storage]: https://developer.mozilla.org/en-US/docs/Web/API/Storage
[local-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
[session-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage
[indexed-db]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API

View File

@@ -1,6 +1,7 @@
# 应用部署
为了使用Electron部署你的应用程序你存放应用程序的文件夹需要叫做 `app` 并且需要放在 Electron 的资源文件夹下(在 OS X 中是指 `Electron.app/Contents/Resources/`,在 Linux 和 Windows 中是指 `resources/`
为了使用 Electron 部署你的应用程序,你存放应用程序的文件夹需要叫做 `app` 并且需要放在 Electron 的
资源文件夹下(在 OS X 中是指 `Electron.app/Contents/Resources/`,在 Linux 和 Windows 中是指 `resources/`
就像这样:
在 OS X 中:
@@ -56,7 +57,7 @@ electron/resources/
你可以将 `electron.exe` 改成任意你喜欢的名字,然后可以使用像
[rcedit](https://github.com/atom/rcedit)
编辑它的icon和其他信息。
编辑它的 icon 和其他信息。
### OS X

View File

@@ -1,34 +1,38 @@
# 应用打包
为舒缓Windows下路径名过长的问题[issues](https://github.com/joyent/node/issues/6960), 也略对`require`加速以及简单隐匿你的源代码, 你可以通过极小的源代码改动将你的应用打包成[asar][asar].
为舒缓 Windows 下路径名过长的问题[issues](https://github.com/joyent/node/issues/6960)
也略对 `require` 加速以及简单隐匿你的源代码,你可以通过极小的源代码改动将你的应用打包成 [asar][asar]。
## 生成`asar`包
## 生成 `asar`
[asar][asar]是一种将多个文件合并成一个文件的类tar风格的归档格式。 Electron可以无需解压即从其中读取任意文件内容。
[asar][asar] 是一种将多个文件合并成一个文件的类 tar 风格的归档格式。
Electron 可以无需解压,即从其中读取任意文件内容。
参照如下步骤将你的应用打包成`asar`
参照如下步骤将你的应用打包成 `asar`
### 1. 安装asar
### 1. 安装 asar
```bash
$ npm install -g asar
```
### 2. 用`asar pack`打包
### 2. 用 `asar pack` 打包
```bash
$ asar pack your-app app.asar
```
## 使用`asar`包
## 使用 `asar`
在Electron中有两类APIsNode.js提供的Node APIs和Chromium提供的Web APIs。这两种APIs都支持从`asar`包中读取文件
Electron 中有两类 APIsNode.js 提供的 Node APIChromium 提供的 Web API。
这两种 API 都支持从 `asar` 包中读取文件。
### Node API
由于Electron中打了特别补丁 Node APIs中如`fs.readFile`或者`require`之类的方法可以将`asar`视之为虚拟文件夹,读取`asar`里面的文件就和从真实的文件系统中读取一样。
由于 Electron 中打了特别补丁, Node API 中如 `fs.readFile` 或者 `require` 之类
的方法可以将 `asar` 视之为虚拟文件夹,读取 `asar` 里面的文件就和从真实的文件系统中读取一样。
例如,假设我们在`/path/to`文件夹下有个`example.asar`包:
例如,假设我们在 `/path/to` 文件夹下有个 `example.asar` 包:
```bash
$ asar list /path/to/example.asar
@@ -40,27 +44,27 @@ $ asar list /path/to/example.asar
/static/jquery.min.js
```
`asar`包读取一个文件:
`asar` 包读取一个文件:
```javascript
const fs = require('fs');
fs.readFileSync('/path/to/example.asar/file.txt');
```
列出`asar`包中根目录下的所有文件:
列出 `asar` 包中根目录下的所有文件:
```javascript
const fs = require('fs');
fs.readdirSync('/path/to/example.asar');
```
使用`asar`包中的一个模块:
使用 `asar` 包中的一个模块:
```javascript
require('/path/to/example.asar/dir/module.js');
```
你也可以使用`BrowserWindow`来显示一个`asar`包里的web页面
你也可以使用 `BrowserWindow` 来显示一个 `asar` 包里的 web 页面:
```javascript
const BrowserWindow = require('electron').BrowserWindow;
@@ -70,9 +74,9 @@ win.loadURL('file:///path/to/example.asar/static/index.html');
### Web API
在Web页面里`file:`协议可以获取`asar`包中文件。和Node API一样`asar`包如虚拟文件夹。
Web 页面里,用 `file:` 协议可以获取 `asar` 包中文件。和 Node API 一样,视 `asar` 包如虚拟文件夹。
例如,用`$.get`获取文件:
例如,用 `$.get` 获取文件:
```html
<script>
@@ -83,32 +87,36 @@ $.get('file:///path/to/example.asar/file.txt', function(data) {
</script>
```
### 像“文件”那样处理`asar`包
### 像“文件”那样处理 `asar`
有些场景,如:核查`asar`包的校验和,我们需要像读取“文件”那样读取`asar`包的内容(而不是当成虚拟文件夹)。你可以使用内置的`original-fs`(提供和`fs`一样的APIs)模块来读取`asar`包的真实信息。
有些场景,如:核查 `asar` 包的校验和,我们需要像读取“文件”那样读取 `asar` 包的内容(而不是当成虚拟文件夹)。
你可以使用内置的 `original-fs` (提供和 `fs` 一样的 API模块来读取 `asar` 包的真实信息。
```javascript
var originalFs = require('original-fs');
originalFs.readFileSync('/path/to/example.asar');
```
## Node API缺陷
## Node API 缺陷
尽管我们已经尽了最大努力使得`asar`包在Node API下的应用尽可能的趋向于真实的目录结构但仍有一些底层Node API我们无法保证其正常工作。
尽管我们已经尽了最大努力使得 `asar` 包在 Node API 下的应用尽可能的趋向于真实的目录结构,但仍有一些底层 Node API 我们无法保证其正常工作。
### `asar`包是只读的
### `asar` 包是只读的
`asar`包中的内容不可更改所以Node APIs里那些可以用来修改文件的方法在对待`asar`包时都无法正常工作。
`asar` 包中的内容不可更改,所以 Node APIs 里那些可以用来修改文件的方法在对待 `asar` 包时都无法正常工作。
### Working Directory`asar`包中无效
### Working Directory`asar` 包中无效
尽管`asar`包是虚拟文件夹但其实并没有真实的目录架构对应在文件系统里所以你不可能将working Directory设置成`asar`包里的一个文件夹。将`asar`中的文件夹以`cwd`形式作为参数传入一些API中也会报错。
尽管 `asar` 包是虚拟文件夹,但其实并没有真实的目录架构对应在文件系统里,所以你不可能将 working Directory
设置成 `asar` 包里的一个文件夹。将 `asar` 中的文件夹以 `cwd` 形式作为参数传入一些 API 中也会报错。
### API中的额外“开箱”
### API 中的额外“开箱”
大部分`fs`API可以无需解压即从`asar`包中读取文件或者文件的信息,但是在处理一些依赖真实文件路径的底层系统方法时Electron会将所需文件解压到临时目录下然后将临时目录下的真实文件路径传给底层系统方法使其正常工作。 对于这类API耗费会略多一些。
大部分 `fs` API 可以无需解压即从 `asar` 包中读取文件或者文件的信息,但是在处理一些依赖真实文件路径的底层
系统方法时Electron 会将所需文件解压到临时目录下,然后将临时目录下的真实文件路径传给底层系统方法使其正
常工作。 对于这类API耗费会略多一些。
以下是一些需要额外解压的APIs
以下是一些需要额外解压的 API
* `child_process.execFile`
* `child_process.execFileSync`
@@ -116,26 +124,32 @@ originalFs.readFileSync('/path/to/example.asar');
* `fs.openSync`
* `process.dlopen` - `require`native模块时用到
### `fs.stat`获取的stat信息不可靠
### `fs.stat` 获取的 stat 信息不可靠
`asar`包中的文件取`fs.stat`,返回的`Stats`对象不是精确值,因为这些文件不是真实存在于文件系统里。所以除了文件大小和文件类型以外,你不应该依赖`Stats`对象的值。
`asar` 包中的文件取 `fs.stat`,返回的 `Stats` 对象不是精确值,因为这些文件不是真实存在于文件系
统里。所以除了文件大小和文件类型以外,你不应该依赖 `Stats` 对象的值。
### 执行`asar`包中的程序
### 执行 `asar` 包中的程序
Node中有一些可以执行程序的API`child_process.exec``child_process.spawn``child_process.execFile`等,但只有`execFile`可以执行`asar`包中的程序。
Node 中有一些可以执行程序的 API `child_process.exec``child_process.spawn``child_process.execFile` 等,
但只有 `execFile` 可以执行 `asar` 包中的程序。
因为`exec``spawn`允许`command`替代`file`作为输入,而`command`是需要在shell下执行的目前没有可靠的方法来判断`command`中是否在操作一个`asar`包中的文件,而且即便可以判断,我们依旧无法保证可以在无任何副作用的情况下替换`command`中的文件路径。
因为 `exec``spawn` 允许 `command` 替代 `file` 作为输入,而 `command` 是需要在 shell 下执行的,目前没有
可靠的方法来判断 `command` 中是否在操作一个 `asar` 包中的文件,而且即便可以判断,我们依旧无法保证可以在无任何
副作用的情况下替换 `command` 中的文件路径。
## 打包时排除文件
如上所述一些Node API会在调用时将文件解压到文件系统中除了效率问题外也有可能引起杀毒软件的注意
如上所述,一些 Node API 会在调用时将文件解压到文件系统中,除了效率问题外,也有可能引起杀毒软件的注意!
为解决这个问题,你可以在生成`asar`包时使用`--unpack`选项来排除一些文件,使其不打包到`asar`包中,下面是如何排除一些用作共享用途的native模块的方法
为解决这个问题,你可以在生成 `asar` 包时使用 `--unpack` 选项来排除一些文件,使其不打包到 `asar` 包中,
下面是如何排除一些用作共享用途的 native 模块的方法:
```bash
$ asar pack app app.asar --unpack *.node
```
经过上述命令后,除了生成的`app.asar`包以外,还有一个包含了排除文件的`app.asar.unpacked`文件夹,你需要将这个文件夹一起拷贝,提供给用户。
经过上述命令后,除了生成的 `app.asar` 包以外,还有一个包含了排除文件的 `app.asar.unpacked` 文件夹,
你需要将这个文件夹一起拷贝,提供给用户。
[asar]: https://github.com/atom/asar

View File

@@ -1,6 +1,6 @@
# 主进程调试
浏览器窗口的开发工具仅能调试渲染器的进程脚本比如web 页面)。为了提供一个可以调试主进程
浏览器窗口的开发工具仅能调试渲染器的进程脚本(比如 web 页面)。为了提供一个可以调试主进程
的方法Electron 提供了 `--debug``--debug-brk` 开关。
## 命令行开关
@@ -18,16 +18,31 @@
## 使用 node-inspector 来调试
__备注__ Electron 使用 node v0.11.13 版本,目前对 node-inspector支持的不是特别好
__备注__ Electron 目前对 node-inspector 支持的不是特别好,
如果你通过 node-inspector 的 console 来检查 `process` 对象,主进程就会崩溃。
### 1. 开始 [node-inspector][node-inspector] 服务
### 1. 确认你已经安装了 [node-gyp 所需工具](https://github.com/nodejs/node-gyp#installation)
### 2. 安装 [node-inspector][node-inspector]
```bash
$ node-inspector
$ npm install node-inspector
```
### 2. 打开 Electron 的调试模式
### 3. 安装 `node-pre-gyp` 的一个修订版
```bash
$ npm install git+https://git@github.com/enlight/node-pre-gyp.git#detect-electron-runtime-in-find
```
### 4. 为 Electron 重新编译 `node-inspector` `v8` 模块(将 target 参数修改为你的 Electron 的版本号)
```bash
$ node_modules/.bin/node-pre-gyp --target=0.36.2 --runtime=electron --fallback-to-build --directory node_modules/v8-debug/ --dist-url=https://atom.io/download/atom-shell reinstall
$ node_modules/.bin/node-pre-gyp --target=0.36.2 --runtime=electron --fallback-to-build --directory node_modules/v8-profiler/ --dist-url=https://atom.io/download/atom-shell reinstall
```
### 5. 打开 Electron 的调试模式
你也可以用调试参数来运行 Electron
@@ -41,7 +56,13 @@ $ electron --debug=5858 your/app
$ electron --debug-brk=5858 your/app
```
### 3. 加载调试器界面
### 6. 使用 Electron 开启 [node-inspector][node-inspector] 服务
```bash
$ ELECTRON_RUN_AS_NODE=true path/to/electron.exe node_modules/node-inspector/bin/inspector.js
```
### 7. 加载调试器界面
在 Chrome 中打开 http://127.0.0.1:8080/debug?ws=127.0.0.1:8080&port=5858

View File

@@ -1,10 +1,10 @@
# DevTools扩展
为了使调试更容易Electron原生支持[Chrome DevTools Extension][devtools-extension]。
为了使调试更容易Electron 原生支持 [Chrome DevTools Extension][devtools-extension]。
对于大多数DevTools的扩展你可以直接下载源码然后通过`BrowserWindow.addDevToolsExtension`API加载它们。Electron会记住已经加载了哪些扩展所以你不需要每次创建一个新window时都调用`BrowserWindow.addDevToolsExtension`API。
对于大多数DevTools的扩展你可以直接下载源码然后通过 `BrowserWindow.addDevToolsExtension` API 加载它们。Electron会记住已经加载了哪些扩展所以你不需要每次创建一个新window时都调用 `BrowserWindow.addDevToolsExtension` API。
**React DevTools目前不能直接工作详情留意[https://github.com/atom/electron/issues/915](https://github.com/atom/electron/issues/915) **
**React DevTools目前不能直接工作详情留意 [https://github.com/atom/electron/issues/915](https://github.com/atom/electron/issues/915) **
例如,要用[React DevTools Extension](https://github.com/facebook/react-devtools),你得先下载他的源码:
@@ -13,33 +13,33 @@ $ cd /some-directory
$ git clone --recursive https://github.com/facebook/react-devtools.git
```
参考[`react-devtools/shells/chrome/Readme.md`](https://github.com/facebook/react-devtools/blob/master/shells/chrome/Readme.md)来编译这个扩展源码。
参考 [`react-devtools/shells/chrome/Readme.md`](https://github.com/facebook/react-devtools/blob/master/shells/chrome/Readme.md) 来编译这个扩展源码。
然后你就可以在任意页面的DevTools里加载React DevTools了通过控制台输入如下命令加载扩展
然后你就可以在任意页面的 DevTools 里加载 React DevTools 了,通过控制台输入如下命令加载扩展:
```javascript
const BrowserWindow = require('electron').remote.BrowserWindow;
BrowserWindow.addDevToolsExtension('/some-directory/react-devtools/shells/chrome');
```
要卸载扩展,可以调用`BrowserWindow.removeDevToolsExtension`API(扩展名作为参数传入)该扩展在下次打开DevTools时就不会加载了
要卸载扩展,可以调用 `BrowserWindow.removeDevToolsExtension` API (扩展名作为参数传入)该扩展在下次打开DevTools时就不会加载了
```javascript
BrowserWindow.removeDevToolsExtension('React Developer Tools');
```
## DevTools扩展的格式
## DevTools 扩展的格式
理论上Electron可以加载所有为chrome浏览器编写的DevTools扩展但它们必须存放在文件夹里。那些以`crx`形式发布的扩展是不能被加载的,除非你把它们解压到一个文件夹里。
理论上Electron 可以加载所有为 chrome 浏览器编写的 DevTools 扩展,但它们必须存放在文件夹里。那些以 `crx` 形式发布的扩展是不能被加载的,除非你把它们解压到一个文件夹里。
## 后台运行(background pages)
Electron目前并不支持chrome扩展里的后台运行(background pages)功能所以那些依赖此特性的DevTools扩展在Electron里可能无法正常工作。
Electron 目前并不支持 chrome 扩展里的后台运行(background pages)功能,所以那些依赖此特性的 DevTools 扩展在 Electron 里可能无法正常工作。
## `chrome.*` APIs
有些chrome扩展使用了`chrome.*`APIs而且这些扩展在Electron中需要额外实现一些代码才能使用所以并不是所有的这类扩展都已经在Electron中实现完毕了。
有些 chrome 扩展使用了 `chrome.*`APIs而且这些扩展在 Electron 中需要额外实现一些代码才能使用,所以并不是所有的这类扩展都已经在 Electron 中实现完毕了。
考虑到并非所有的`chrome.*`APIs都实现完毕如果DevTools正在使用除了`chrome.devtools.*`之外的其它APIs这个扩展很可能无法正常工作。你可以通过报告这个扩展的异常信息这样做方便我们对该扩展的支持。
考虑到并非所有的 `chrome.*`APIs 都实现完毕,如果 DevTools 正在使用除了 `chrome.devtools.*` 之外的其它 APIs这个扩展很可能无法正常工作。你可以通过报告这个扩展的异常信息这样做方便我们对该扩展的支持。
[devtools-extension]: https://developer.chrome.com/extensions/devtools

View File

@@ -20,7 +20,7 @@ Ubuntu 12.04 下编译的,`arm` 版的二进制文件是在 ARM v7硬浮点
Debian Wheezy 版本的 NEON下完成的。
预编译二进制文件是否能够运行,取决于其中是否包括了编译平台链接的库,所以只有 Ubuntu 12.04
可以保证正常工作,但是以下的平台也被证实可以运行 Electron的预编译版本
可以保证正常工作,但是以下的平台也被证实可以运行 Electron 的预编译版本:
* Ubuntu 12.04 及更新
* Fedora 21

View File

@@ -1,12 +1,12 @@
# 使用原生模块
Electron同样也支持原生模块但由于和官方的Node相比使用了不同的V8引擎如果你想编译原生模块则需要手动设置Electronheaders的位置。
Electron 同样也支持原生模块,但由于和官方的 Node 相比使用了不同的 V8 引擎,如果你想编译原生模块,则需要手动设置 Electronheaders 的位置。
## 原生Node模块的兼容性
当Node开始换新的V8引擎版本时原生模块可能“坏”掉。为确保一切工作正常你需要检查你想要使用的原生模块是否被Electron内置的Node支持。你可以在[这里](https://github.com/atom/electron/releases)查看Electron内置的Node版本或者使用`process.version`(参考:[快速入门](https://github.com/atom/electron/blob/master/docs/tutorial/quick-start.md))查看。
Node 开始换新的V8引擎版本时原生模块可能“坏”掉。为确保一切工作正常你需要检查你想要使用的原生模块是否被 Electron 内置的 Node 支持。你可以在[这里](https://github.com/atom/electron/releases)查看 Electron 内置的 Node 版本,或者使用 `process.version` (参考:[快速入门](https://github.com/atom/electron/blob/master/docs/tutorial/quick-start.md))查看。
考虑到[NAN](https://github.com/nodejs/nan/)可以使你的开发更容易对多版本Node的支持建议使用它来开发你自己的模块。你也可以使用[NAN](https://github.com/nodejs/nan/)来移植旧的模块到新的Node版本以使它们可以在新的Electron下良好工作。
考虑到 [NAN](https://github.com/nodejs/nan/) 可以使你的开发更容易对多版本 Node 的支持,建议使用它来开发你自己的模块。你也可以使用 [NAN](https://github.com/nodejs/nan/) 来移植旧的模块到新的 Nod e版本以使它们可以在新的 Electron 下良好工作。
## 如何安装原生模块
@@ -14,7 +14,7 @@ Electron同样也支持原生模块但由于和官方的Node相比使用了
### 最简单方式
最简单的方式就是通过[`electron-rebuild`](https://github.com/paulcbetts/electron-rebuild)包重新编译原生模块它帮你自动完成了下载headers、编译原生模块等步骤
最简单的方式就是通过 [`electron-rebuild`](https://github.com/paulcbetts/electron-rebuild) 包重新编译原生模块,它帮你自动完成了下载 headers、编译原生模块等步骤
```sh
npm install --save-dev electron-rebuild
@@ -26,9 +26,9 @@ npm install --save-dev electron-rebuild
.\node_modules\.bin\electron-rebuild.cmd
```
### 通过npm安装
### 通过 npm 安装
你当然也可以通过`npm`安装原生模块。大部分步骤和安装普通模块时一样,除了以下一些系统环境变量你需要自己操作:
你当然也可以通过 `npm` 安装原生模块。大部分步骤和安装普通模块时一样,除了以下一些系统环境变量你需要自己操作:
```bash
export npm_config_disturl=https://atom.io/download/atom-shell
@@ -38,16 +38,19 @@ export npm_config_runtime=electron
HOME=~/.electron-gyp npm install module-name
```
### 通过node-gyp安装
### 通过 node-gyp 安装
你需要告诉`node-gyp`去哪下载Electronheaders以及下载什么版本
你需要告诉 `node-gyp` 去哪下载 Electronheaders以及下载什么版本
```bash
$ cd /path-to-module/
$ HOME=~/.electron-gyp node-gyp rebuild --target=0.29.1 --arch=x64 --dist-url=https://atom.io/download/atom-shell
```
`HOME=~/.electron-gyp`设置去哪找开发时的headers。
`--target=0.29.1`设置了Electron的版本
`--dist-url=...`设置了Electron的headers的下载地址
`--arch=x64`设置了该模块为适配64bit操作系统而编译
`HOME=~/.electron-gyp` 设置去哪找开发时的 headers。
`--target=0.29.1` 设置了 Electron 的版本
`--dist-url=...` 设置了 Electron 的 headers 的下载地址
`--arch=x64` 设置了该模块为适配64位操作系统而编译

View File

@@ -0,0 +1,48 @@
# 使用 Pepper Flash 插件
Electron 现在支持 Pepper Flash 插件。要在 Electron 里面使用 Pepper Flash 插件,你需
要手动设置 Pepper Flash 的路径和在你的应用里启用 Pepper Flash。
## 保留一份 Flash 插件的副本
在 OS X 和 Linux 上,你可以在 Chrome 浏览器的 `chrome://plugins` 页面上找到 Pepper
Flash 的插件信息。插件的路径和版本会对 Election 对其的支持有帮助。你也可以把插件
复制到另一个路径以保留一份副本。
## 添加插件在 Electron 里的开关
你可以直接在命令行中用 `--ppapi-flash-path``ppapi-flash-version` 或者
在 app 的准备事件前调用 `app.commandLine.appendSwitch` 这个 method。同时
添加 `browser-window` 的插件开关。
例如:
```javascript
// Specify flash path. 设置 flash 路径
// On Windows, it might be /path/to/pepflashplayer.dll
// On OS X, /path/to/PepperFlashPlayer.plugin
// On Linux, /path/to/libpepflashplayer.so
app.commandLine.appendSwitch('ppapi-flash-path', '/path/to/libpepflashplayer.so');
// Specify flash version, for example, v17.0.0.169 设置版本号
app.commandLine.appendSwitch('ppapi-flash-version', '17.0.0.169');
app.on('ready', function() {
mainWindow = new BrowserWindow({
'width': 800,
'height': 600,
'web-preferences': {
'plugins': true
}
});
mainWindow.loadURL('file://' + __dirname + '/index.html');
// Something else
});
```
## 使用 `<webview>` 标签启用插件
`<webview>` 标签里添加 `plugins` 属性。
```html
<webview src="http://www.adobe.com/software/flash/about/" plugins></webview>
```

View File

@@ -1,18 +1,18 @@
# 使用SeleniumWebDriver
# 使用 SeleniumWebDriver
引自[ChromeDriver - WebDriver for Chrome][chrome-driver]:
> WebDriver是一款开源的支持多浏览器的自动化测试工具。它提供了操作网页、用户输入、JavaScript执行等能力。ChromeDriver是一个实现了WebDriverChromium联接协议的独立服务。它也是由开发了ChromiumWebDriver的团队开发的。
> WebDriver 是一款开源的支持多浏览器的自动化测试工具。它提供了操作网页、用户输入、JavaScript 执行等能力。ChromeDriver 是一个实现了 WebDriverChromium 联接协议的独立服务。它也是由开发了 ChromiumWebDriver 的团队开发的。
为了能够使`chromedriver`Electron一起正常工作我们需要告诉它Electron在哪并且让它相信Electron就是Chrome浏览器。
为了能够使 `chromedriver`Electron 一起正常工作,我们需要告诉它 Electron 在哪,并且让它相信 Electron 就是 Chrome 浏览器。
## 通过WebDriverJs配置
## 通过 WebDriverJs 配置
[WebDriverJs](https://code.google.com/p/selenium/wiki/WebDriverJs) 是一个可以配合WebDriver做测试的node模块我们会用它来做个演示。
[WebDriverJs](https://code.google.com/p/selenium/wiki/WebDriverJs) 是一个可以配合 WebDriver 做测试的 node 模块,我们会用它来做个演示。
### 1. 启动ChromeDriver
### 1. 启动 ChromeDriver
首先,你要下载`chromedriver`,然后运行以下命令:
首先,你要下载 `chromedriver`,然后运行以下命令:
```bash
$ ./chromedriver
@@ -20,17 +20,17 @@ Starting ChromeDriver (v2.10.291558) on port 9515
Only local connections are allowed.
```
记住`9515`这个端口号,我们后面会用到
记住 `9515` 这个端口号,我们后面会用到
### 2. 安装WebDriverJS
### 2. 安装 WebDriverJS
```bash
$ npm install selenium-webdriver
```
### 3. 联接到ChromeDriver
### 3. 联接到 ChromeDriver
在Electron下使用`selenium-webdriver`和其平时的用法并没有大的差异只是你需要手动设置连接ChromeDriver以及Electron的路径
Electron 下使用 `selenium-webdriver` 和其平时的用法并没有大的差异,只是你需要手动设置连接 ChromeDriver以及 Electron 的路径:
```javascript
const webdriver = require('selenium-webdriver');
@@ -59,13 +59,13 @@ driver.wait(function() {
driver.quit();
```
## 通过WebdriverIO配置
## 通过 WebdriverIO 配置
[WebdriverIO](http://webdriver.io/)也是一个配合WebDriver用来测试的node模块
[WebdriverIO](http://webdriver.io/) 也是一个配合 WebDriver 用来测试的 node 模块
### 1. 启动ChromeDriver
### 1. 启动 ChromeDriver
首先,下载`chromedriver`,然后运行以下命令:
首先,下载 `chromedriver`,然后运行以下命令:
```bash
$ chromedriver --url-base=wd/hub --port=9515
@@ -73,15 +73,15 @@ Starting ChromeDriver (v2.10.291558) on port 9515
Only local connections are allowed.
```
记住`9515`端口,后面会用到
记住 `9515` 端口,后面会用到
### 2. 安装WebdriverIO
### 2. 安装 WebdriverIO
```bash
$ npm install webdriverio
```
### 3. 连接到ChromeDriver
### 3. 连接到 ChromeDriver
```javascript
const webdriverio = require('webdriverio');
@@ -112,8 +112,8 @@ client
## 工作流程
无需重新编译Electron只要把app的源码放到[Electron的资源目录](https://github.com/atom/electron/blob/master/docs/tutorial/application-distribution.md)里就可直接开始测试了。
无需重新编译 Electron只要把 app 的源码放到 [Electron的资源目录](https://github.com/atom/electron/blob/master/docs/tutorial/application-distribution.md) 里就可直接开始测试了。
当然你也可以在运行Electron时传入参数指定你app的所在文件夹。这步可以免去你拷贝粘贴你的appElectron的资源目录。
当然,你也可以在运行 Electron 时传入参数指定你 app 的所在文件夹。这步可以免去你拷贝-粘贴你的 appElectron 的资源目录。
[chrome-driver]: https://sites.google.com/a/chromium.org/chromedriver/

View File

@@ -26,6 +26,7 @@ an issue:
* [DevTools Extension](tutorial/devtools-extension.md)
* [Using Pepper Flash Plugin](tutorial/using-pepper-flash-plugin.md)
* [Using Widevine CDM Plugin](tutorial/using-widevine-cdm-plugin.md)
* [Testing on Headless CI Systems (Travis, Jenkins)](tutorial/testing-on-headless-ci.md)
## Tutorials

View File

@@ -23,6 +23,8 @@ The `Super` key is mapped to the `Windows` key on Windows and Linux and
* `Control` (or `Ctrl` for short)
* `CommandOrControl` (or `CmdOrCtrl` for short)
* `Alt`
* `Option`
* `AltGr`
* `Shift`
* `Super`
@@ -44,3 +46,4 @@ The `Super` key is mapped to the `Windows` key on Windows and Linux and
* `Escape` (or `Esc` for short)
* `VolumeUp`, `VolumeDown` and `VolumeMute`
* `MediaNextTrack`, `MediaPreviousTrack`, `MediaStop` and `MediaPlayPause`
* `PrintScreen`

View File

@@ -156,7 +156,7 @@ certificate you should prevent the default behavior with
`event.preventDefault()` and call `callback(true)`.
```javascript
session.on('certificate-error', function(event, webContents, url, error, certificate, callback) {
app.on('certificate-error', function(event, webContents, url, error, certificate, callback) {
if (url == "https://github.com") {
// Verification logic.
event.preventDefault();
@@ -228,6 +228,10 @@ app.on('login', function(event, webContents, request, authInfo, callback) {
Emitted when the gpu process crashes.
### Event: 'platform-theme-changed' _OS X_
Emitted when the system's Dark Mode theme is toggled.
## Methods
The `app` object has the following methods:
@@ -244,14 +248,6 @@ This method guarantees that all `beforeunload` and `unload` event handlers are
correctly executed. It is possible that a window cancels the quitting by
returning `false` in the `beforeunload` event handler.
### `app.hide()` _OS X_
Hides all application windows without minimizing them.
### `app.show()` _OS X_
Shows application windows after they were hidden. Does not automatically focus them.
### `app.exit(exitCode)`
* `exitCode` Integer
@@ -261,6 +257,19 @@ Exits immediately with `exitCode`.
All windows will be closed immediately without asking user and the `before-quit`
and `will-quit` events will not be emitted.
### `app.focus()`
On Linux, focuses on the first visible window. On OS X, makes the application
the active app. On Windows, focuses on the application's first window.
### `app.hide()` _OS X_
Hides all application windows without minimizing them.
### `app.show()` _OS X_
Shows application windows after they were hidden. Does not automatically focus them.
### `app.getAppPath()`
Returns the current application directory.
@@ -461,6 +470,10 @@ if (browserOptions.transparent) {
}
```
### `app.isDarkMode()` _OS X_
This method returns `true` if the system is in Dark Mode, and `false` otherwise.
### `app.commandLine.appendSwitch(switch[, value])`
Append a switch (with optional `value`) to Chromium's command line.

View File

@@ -58,9 +58,8 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
* `alwaysOnTop` Boolean - Whether the window should always stay on top of
other windows. Default is `false`.
* `fullscreen` Boolean - Whether the window should show in fullscreen. When
explicitly set to `false` the fullscreen button will be hidden or disabled
on OS X, or the maximize button will be disabled on Windows. Default is
`false`.
explicity set to `false` the fullscreen button will be hidden or disabled
on OS X. Default is `false`.
* `fullscreenable` Boolean - Whether the maximize/zoom button on OS X should
toggle full screen mode or maximize window. Default is `true`.
* `skipTaskbar` Boolean - Whether to show the window in taskbar. Default is
@@ -246,6 +245,14 @@ Emitted when the window loses focus.
Emitted when the window gains focus.
### Event: 'show'
Emitted when the window is shown.
### Event: 'hide'
Emitted when the window is hidden.
### Event: 'maximize'
Emitted when window is maximized.
@@ -398,6 +405,10 @@ the [close event](#event-close).
Focus on the window.
### `win.blur()`
Remove focus on the window.
### `win.isFocused()`
Returns a boolean, whether the window is focused.
@@ -582,17 +593,17 @@ nothing.
Returns whether the window can be manually maximized by user. On Linux always
returns `true`.
### `win.setFullScreenable(fullscreenable)` _OS X_
### `win.setFullScreenable(fullscreenable)`
* `fullscreenable` Boolean
Sets whether the maximize/zoom window button toggles fullscreen mode or
maximizes the window. On Windows and Linux does nothing.
maximizes the window.
### `win.isFullScreenable()` _OS X_
### `win.isFullScreenable()`
Returns whether the maximize/zoom window button toggles fullscreen mode or
maximizes the window. On Windows and Linux always returns `true`.
maximizes the window.
### `win.setClosable(closable)` _OS X_ _Windows_

View File

@@ -143,7 +143,7 @@ var template = [
];
if (process.platform == 'darwin') {
var name = require('electron').app.getName();
var name = require('electron').remote.app.getName();
template.unshift({
label: name,
submenu: [
@@ -227,6 +227,9 @@ Sends the `action` to the first responder of application. This is used for
emulating default Cocoa menu behaviors, usually you would just use the
`role` property of `MenuItem`.
See the [OS X Cocoa Event Handling Guide](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/EventOverview/EventArchitecture/EventArchitecture.html#//apple_ref/doc/uid/10000060i-CH3-SW7)
for more information on OS X's native actions.
### `Menu.buildFromTemplate(template)`
* `template` Array

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