Merge branch 'master' into jl-std-docs-2
This commit is contained in:
commit
f4783772c5
72 changed files with 118 additions and 15 deletions
|
@ -43,6 +43,12 @@ Guides and the API reference are located in the
|
||||||
[docs](https://github.com/atom/electron/tree/master/docs) directory. It also
|
[docs](https://github.com/atom/electron/tree/master/docs) directory. It also
|
||||||
contains documents describing how to build and contribute to Electron.
|
contains documents describing how to build and contribute to Electron.
|
||||||
|
|
||||||
|
## Documentation Translations
|
||||||
|
|
||||||
|
- [Korean](https://github.com/atom/electron/tree/master/docs-translations/ko)
|
||||||
|
- [Japanese](https://github.com/atom/electron/tree/master/docs-translations/jp)
|
||||||
|
- [Spanish](https://github.com/atom/electron/tree/master/docs-translations/es)
|
||||||
|
|
||||||
## Community
|
## Community
|
||||||
|
|
||||||
There is an [`electron` category on the Atom forums](http://discuss.atom.io/category/electron)
|
There is an [`electron` category on the Atom forums](http://discuss.atom.io/category/electron)
|
||||||
|
|
|
@ -277,7 +277,10 @@ bool WebContents::IsPopupOrPanel(const content::WebContents* source) const {
|
||||||
void WebContents::HandleKeyboardEvent(
|
void WebContents::HandleKeyboardEvent(
|
||||||
content::WebContents* source,
|
content::WebContents* source,
|
||||||
const content::NativeWebKeyboardEvent& event) {
|
const content::NativeWebKeyboardEvent& event) {
|
||||||
if (type_ == BROWSER_WINDOW) {
|
if (event.windowsKeyCode == ui::VKEY_ESCAPE && is_html_fullscreen()) {
|
||||||
|
// Escape exits tabbed fullscreen mode.
|
||||||
|
ExitFullscreenModeForTab(source);
|
||||||
|
} else if (type_ == BROWSER_WINDOW) {
|
||||||
owner_window()->HandleKeyboardEvent(source, event);
|
owner_window()->HandleKeyboardEvent(source, event);
|
||||||
} else if (type_ == WEB_VIEW && guest_delegate_) {
|
} else if (type_ == WEB_VIEW && guest_delegate_) {
|
||||||
// Send the unhandled keyboard events back to the embedder.
|
// Send the unhandled keyboard events back to the embedder.
|
||||||
|
|
|
@ -48,6 +48,8 @@ class CommonWebContentsDelegate
|
||||||
|
|
||||||
NativeWindow* owner_window() const { return owner_window_.get(); }
|
NativeWindow* owner_window() const { return owner_window_.get(); }
|
||||||
|
|
||||||
|
bool is_html_fullscreen() const { return html_fullscreen_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// content::WebContentsDelegate:
|
// content::WebContentsDelegate:
|
||||||
content::WebContents* OpenURLFromTab(
|
content::WebContents* OpenURLFromTab(
|
||||||
|
|
|
@ -30,6 +30,10 @@ guestInstances = {}
|
||||||
embedderElementsMap = {}
|
embedderElementsMap = {}
|
||||||
reverseEmbedderElementsMap = {}
|
reverseEmbedderElementsMap = {}
|
||||||
|
|
||||||
|
# Moves the last element of array to the first one.
|
||||||
|
moveLastToFirst = (list) ->
|
||||||
|
list.unshift list.pop()
|
||||||
|
|
||||||
# Generate guestInstanceId.
|
# Generate guestInstanceId.
|
||||||
getNextInstanceId = (webContents) ->
|
getNextInstanceId = (webContents) ->
|
||||||
++nextInstanceId
|
++nextInstanceId
|
||||||
|
@ -46,7 +50,13 @@ createGuest = (embedder, params) ->
|
||||||
destroyEvents = ['destroyed', 'crashed', 'did-navigate-to-different-page']
|
destroyEvents = ['destroyed', 'crashed', 'did-navigate-to-different-page']
|
||||||
destroy = ->
|
destroy = ->
|
||||||
destroyGuest embedder, id if guestInstances[id]?
|
destroyGuest embedder, id if guestInstances[id]?
|
||||||
embedder.once event, destroy for event in destroyEvents
|
for event in destroyEvents
|
||||||
|
embedder.once event, destroy
|
||||||
|
# Users might also listen to the crashed event, so We must ensure the guest
|
||||||
|
# is destroyed before users' listener gets called. It is done by moving our
|
||||||
|
# listener to the first one in queue.
|
||||||
|
listeners = embedder._events[event]
|
||||||
|
moveLastToFirst listeners if Array.isArray listeners
|
||||||
guest.once 'destroyed', ->
|
guest.once 'destroyed', ->
|
||||||
embedder.removeListener event, destroy for event in destroyEvents
|
embedder.removeListener event, destroy for event in destroyEvents
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,9 @@ namespace {
|
||||||
// Makes sure that .jpg also shows .JPG.
|
// Makes sure that .jpg also shows .JPG.
|
||||||
gboolean FileFilterCaseInsensitive(const GtkFileFilterInfo* file_info,
|
gboolean FileFilterCaseInsensitive(const GtkFileFilterInfo* file_info,
|
||||||
std::string* file_extension) {
|
std::string* file_extension) {
|
||||||
|
// Makes .* file extension matches all file types.
|
||||||
|
if (*file_extension == ".*")
|
||||||
|
return true;
|
||||||
return EndsWith(file_info->filename, *file_extension, false);
|
return EndsWith(file_info->filename, *file_extension, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,12 @@ void SetAllowedFileTypes(NSSavePanel* dialog, const Filters& filters) {
|
||||||
for (size_t i = 0; i < filters.size(); ++i) {
|
for (size_t i = 0; i < filters.size(); ++i) {
|
||||||
const Filter& filter = filters[i];
|
const Filter& filter = filters[i];
|
||||||
for (size_t j = 0; j < filter.second.size(); ++j) {
|
for (size_t j = 0; j < filter.second.size(); ++j) {
|
||||||
|
// If we meet a '*' file extension, we allow all the file types and no
|
||||||
|
// need to set the specified file types.
|
||||||
|
if (filter.second[j] == "*") {
|
||||||
|
[dialog setAllowsOtherFileTypes:YES];
|
||||||
|
return;
|
||||||
|
}
|
||||||
base::ScopedCFTypeRef<CFStringRef> ext_cf(
|
base::ScopedCFTypeRef<CFStringRef> ext_cf(
|
||||||
base::SysUTF8ToCFStringRef(filter.second[j]));
|
base::SysUTF8ToCFStringRef(filter.second[j]));
|
||||||
[file_type_set addObject:base::mac::CFToNSCast(ext_cf.get())];
|
[file_type_set addObject:base::mac::CFToNSCast(ext_cf.get())];
|
||||||
|
|
|
@ -78,9 +78,9 @@ int ShowMessageBoxUTF16(HWND parent,
|
||||||
const base::string16& message,
|
const base::string16& message,
|
||||||
const base::string16& detail,
|
const base::string16& detail,
|
||||||
const gfx::ImageSkia& icon) {
|
const gfx::ImageSkia& icon) {
|
||||||
TASKDIALOG_FLAGS flags = TDF_SIZE_TO_CONTENT; // show all content.
|
TASKDIALOG_FLAGS flags =
|
||||||
if (cancel_id != 0)
|
TDF_SIZE_TO_CONTENT | // Show all content.
|
||||||
flags |= TDF_ALLOW_DIALOG_CANCELLATION; // allow dialog to be cancelled.
|
TDF_ALLOW_DIALOG_CANCELLATION; // Allow canceling the dialog.
|
||||||
|
|
||||||
TASKDIALOGCONFIG config = { 0 };
|
TASKDIALOGCONFIG config = { 0 };
|
||||||
config.cbSize = sizeof(config);
|
config.cbSize = sizeof(config);
|
||||||
|
|
|
@ -80,12 +80,15 @@ window.alert = (message, title='') ->
|
||||||
buttons = ['OK']
|
buttons = ['OK']
|
||||||
message = message.toString()
|
message = message.toString()
|
||||||
dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons}
|
dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons}
|
||||||
|
# Alert should always return undefined.
|
||||||
|
return
|
||||||
|
|
||||||
# And the confirm().
|
# And the confirm().
|
||||||
window.confirm = (message, title='') ->
|
window.confirm = (message, title='') ->
|
||||||
dialog = remote.require 'dialog'
|
dialog = remote.require 'dialog'
|
||||||
buttons = ['OK', 'Cancel']
|
buttons = ['OK', 'Cancel']
|
||||||
not dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons}
|
cancelId = 1
|
||||||
|
not dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons, cancelId}
|
||||||
|
|
||||||
# But we do not support prompt().
|
# But we do not support prompt().
|
||||||
window.prompt = ->
|
window.prompt = ->
|
||||||
|
|
|
@ -11,7 +11,9 @@ var dialog = require('dialog');
|
||||||
console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', 'multiSelections' ]}));
|
console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', 'multiSelections' ]}));
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note for OS X**: If you want to present dialogs as sheets, the only thing you have to do is provide a `BrowserWindow` reference in the `browserWindow` parameter.
|
**Note for OS X**: If you want to present dialogs as sheets, the only thing you
|
||||||
|
have to do is provide a `BrowserWindow` reference in the `browserWindow`
|
||||||
|
parameter.
|
||||||
|
|
||||||
## dialog.showOpenDialog([browserWindow], [options], [callback])
|
## dialog.showOpenDialog([browserWindow], [options], [callback])
|
||||||
|
|
||||||
|
@ -36,17 +38,22 @@ selected, an example is:
|
||||||
filters: [
|
filters: [
|
||||||
{ name: 'Images', extensions: ['jpg', 'png', 'gif'] },
|
{ name: 'Images', extensions: ['jpg', 'png', 'gif'] },
|
||||||
{ name: 'Movies', extensions: ['mkv', 'avi', 'mp4'] },
|
{ name: 'Movies', extensions: ['mkv', 'avi', 'mp4'] },
|
||||||
{ name: 'Custom File Type', extensions: ['as'] }
|
{ name: 'Custom File Type', extensions: ['as'] },
|
||||||
|
{ name: 'All Files', extensions: ['*'] }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
The `extensions` array should contain extensions without wildcards or dots (e.g.
|
||||||
|
`'png'` is good, `'.png'` and `'*.png'` are bad). To show all files, use the
|
||||||
|
`'*'` wildcard (no other wildcard is supported).
|
||||||
|
|
||||||
If a `callback` is passed, the API call would be asynchronous and the result
|
If a `callback` is passed, the API call would be asynchronous and the result
|
||||||
would be passed via `callback(filenames)`
|
would be passed via `callback(filenames)`
|
||||||
|
|
||||||
**Note:** On Windows and Linux, an open dialog can not be both a file selector
|
**Note:** On Windows and Linux, an open dialog can not be both a file selector
|
||||||
and a directory selector, so if you set `properties` to
|
and a directory selector, so if you set `properties` to
|
||||||
`['openFile', 'openDirectory']` on these platforms, a directory selector will be shown.
|
`['openFile', 'openDirectory']` on these platforms, a directory selector will be
|
||||||
|
shown.
|
||||||
|
|
||||||
## dialog.showSaveDialog([browserWindow], [options], [callback])
|
## dialog.showSaveDialog([browserWindow], [options], [callback])
|
||||||
|
|
||||||
|
@ -70,7 +77,9 @@ will be passed via `callback(filename)`
|
||||||
|
|
||||||
* `browserWindow` BrowserWindow
|
* `browserWindow` BrowserWindow
|
||||||
* `options` Object
|
* `options` Object
|
||||||
* `type` String - Can be `"none"`, `"info"`, `"error"`, `"question"` or `"warning"`. On Windows, "question" displays the same icon as "info", unless if you set an icon using the "icon" option
|
* `type` String - Can be `"none"`, `"info"`, `"error"`, `"question"` or
|
||||||
|
`"warning"`. On Windows, "question" displays the same icon as "info", unless
|
||||||
|
if you set an icon using the "icon" option
|
||||||
* `buttons` Array - Array of texts for buttons
|
* `buttons` Array - Array of texts for buttons
|
||||||
* `title` String - Title of the message box, some platforms will not show it
|
* `title` String - Title of the message box, some platforms will not show it
|
||||||
* `message` String - Content of the message box
|
* `message` String - Content of the message box
|
||||||
|
|
|
@ -8,6 +8,13 @@ script `script/cpplint.py` to check whether all files confirm.
|
||||||
|
|
||||||
The python's version we are using now is Python 2.7.
|
The python's version we are using now is Python 2.7.
|
||||||
|
|
||||||
|
The C++ code uses a lot of Chromium's abstractions and types, so it's
|
||||||
|
recommended to get acquainted with them. A good place to start is
|
||||||
|
Chromium's [Important Abstractions and Data Structures]
|
||||||
|
(https://www.chromium.org/developers/coding-style/important-abstractions-and-data-structures)
|
||||||
|
document. The document mentions some special types, scoped types (that
|
||||||
|
automatically release their memory when going out of scope), logging mechanisms etc.
|
||||||
|
|
||||||
## CoffeeScript
|
## CoffeeScript
|
||||||
|
|
||||||
For CoffeeScript, we follow GitHub's [Style
|
For CoffeeScript, we follow GitHub's [Style
|
||||||
|
|
|
@ -70,6 +70,53 @@ driver.wait(function() {
|
||||||
driver.quit();
|
driver.quit();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Setting up with WebdriverIO
|
||||||
|
|
||||||
|
[WebdriverIO](http://webdriver.io/) provides a Node package for testing with web driver.
|
||||||
|
|
||||||
|
### 1. Start chrome driver
|
||||||
|
|
||||||
|
First you need to download the `chromedriver` binary, and run it:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ chromedriver --url-base=/wd/hub --port=9515
|
||||||
|
Starting ChromeDriver (v2.10.291558) on port 9515
|
||||||
|
Only local connections are allowed.
|
||||||
|
```
|
||||||
|
|
||||||
|
Remember the port number `9515`, which will be used later
|
||||||
|
|
||||||
|
### 2. Install WebdriverIO
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ npm install webdriverio
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Connect to chrome driver
|
||||||
|
```javascript
|
||||||
|
var webdriverio = require('webdriverio');
|
||||||
|
var options = {
|
||||||
|
host: "localhost", // Use localhost as chrome driver server
|
||||||
|
port: 9515, // "9515" is the port opened by chrome driver.
|
||||||
|
desiredCapabilities: {
|
||||||
|
browserName: 'chrome',
|
||||||
|
chromeOptions: {binary: '/Path-to-Your-App.app/Electron'} // Path to your Electron binary.
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var client = webdriverio.remote(options);
|
||||||
|
|
||||||
|
client
|
||||||
|
.init()
|
||||||
|
.url('http://google.com')
|
||||||
|
.setValue('#q', 'webdriverio')
|
||||||
|
.click('#btnG')
|
||||||
|
.getTitle().then(function(title) {
|
||||||
|
console.log('Title was: ' + title);
|
||||||
|
})
|
||||||
|
.end();
|
||||||
|
```
|
||||||
|
|
||||||
## Workflow
|
## Workflow
|
||||||
|
|
||||||
To test your application without rebuilding Electron, simply [place](https://github.com/atom/electron/blob/master/docs/tutorial/application-distribution.md) your app source into Electron's resource directory.
|
To test your application without rebuilding Electron, simply [place](https://github.com/atom/electron/blob/master/docs/tutorial/application-distribution.md) your app source into Electron's resource directory.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "electron",
|
"name": "electron",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"asar": "0.5.0",
|
"asar": "0.7.x",
|
||||||
"coffee-script": "^1.9.2",
|
"coffee-script": "^1.9.2",
|
||||||
"coffeelint": "^1.9.4",
|
"coffeelint": "^1.9.4",
|
||||||
"request": "*",
|
"request": "*",
|
||||||
|
|
|
@ -5,6 +5,13 @@ remote = require 'remote'
|
||||||
|
|
||||||
BrowserWindow = remote.require 'browser-window'
|
BrowserWindow = remote.require 'browser-window'
|
||||||
|
|
||||||
|
comparePaths = (path1, path2) ->
|
||||||
|
if process.platform is 'win32'
|
||||||
|
# Paths in Windows are case insensitive.
|
||||||
|
path1 = path1.toLowerCase()
|
||||||
|
path2 = path2.toLowerCase()
|
||||||
|
assert.equal path1, path2
|
||||||
|
|
||||||
describe 'ipc module', ->
|
describe 'ipc module', ->
|
||||||
fixtures = path.join __dirname, 'fixtures'
|
fixtures = path.join __dirname, 'fixtures'
|
||||||
|
|
||||||
|
@ -19,8 +26,8 @@ describe 'ipc module', ->
|
||||||
assert.equal a.id, 1127
|
assert.equal a.id, 1127
|
||||||
|
|
||||||
it 'should search module from the user app', ->
|
it 'should search module from the user app', ->
|
||||||
assert.equal path.normalize(remote.process.mainModule.filename), path.resolve(__dirname, 'static', 'main.js')
|
comparePaths path.normalize(remote.process.mainModule.filename), path.resolve(__dirname, 'static', 'main.js')
|
||||||
assert.equal path.normalize(remote.process.mainModule.paths[0]), path.resolve(__dirname, 'static', 'node_modules')
|
comparePaths path.normalize(remote.process.mainModule.paths[0]), path.resolve(__dirname, 'static', 'node_modules')
|
||||||
|
|
||||||
describe 'remote.createFunctionWithReturnValue', ->
|
describe 'remote.createFunctionWithReturnValue', ->
|
||||||
it 'should be called in browser synchronously', ->
|
it 'should be called in browser synchronously', ->
|
||||||
|
|
2
vendor/brightray
vendored
2
vendor/brightray
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 939a7b814282a6433b8d7e3c9cfc74451360c07f
|
Subproject commit 5b2a73c68a986780e67eb2e738327d35c7c1c21e
|
2
vendor/node
vendored
2
vendor/node
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 205b013ac86e5500678a791cd54f305580fa4f4b
|
Subproject commit b9b6dd9f3fc095e66a3b89d3efd50f7c576da2c8
|
Loading…
Reference in a new issue