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
|
||||
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
|
||||
|
||||
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(
|
||||
content::WebContents* source,
|
||||
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);
|
||||
} else if (type_ == WEB_VIEW && guest_delegate_) {
|
||||
// Send the unhandled keyboard events back to the embedder.
|
||||
|
|
|
@ -48,6 +48,8 @@ class CommonWebContentsDelegate
|
|||
|
||||
NativeWindow* owner_window() const { return owner_window_.get(); }
|
||||
|
||||
bool is_html_fullscreen() const { return html_fullscreen_; }
|
||||
|
||||
protected:
|
||||
// content::WebContentsDelegate:
|
||||
content::WebContents* OpenURLFromTab(
|
||||
|
|
|
@ -30,6 +30,10 @@ guestInstances = {}
|
|||
embedderElementsMap = {}
|
||||
reverseEmbedderElementsMap = {}
|
||||
|
||||
# Moves the last element of array to the first one.
|
||||
moveLastToFirst = (list) ->
|
||||
list.unshift list.pop()
|
||||
|
||||
# Generate guestInstanceId.
|
||||
getNextInstanceId = (webContents) ->
|
||||
++nextInstanceId
|
||||
|
@ -46,7 +50,13 @@ createGuest = (embedder, params) ->
|
|||
destroyEvents = ['destroyed', 'crashed', 'did-navigate-to-different-page']
|
||||
destroy = ->
|
||||
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', ->
|
||||
embedder.removeListener event, destroy for event in destroyEvents
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@ namespace {
|
|||
// Makes sure that .jpg also shows .JPG.
|
||||
gboolean FileFilterCaseInsensitive(const GtkFileFilterInfo* file_info,
|
||||
std::string* file_extension) {
|
||||
// Makes .* file extension matches all file types.
|
||||
if (*file_extension == ".*")
|
||||
return true;
|
||||
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) {
|
||||
const Filter& filter = filters[i];
|
||||
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::SysUTF8ToCFStringRef(filter.second[j]));
|
||||
[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& detail,
|
||||
const gfx::ImageSkia& icon) {
|
||||
TASKDIALOG_FLAGS flags = TDF_SIZE_TO_CONTENT; // show all content.
|
||||
if (cancel_id != 0)
|
||||
flags |= TDF_ALLOW_DIALOG_CANCELLATION; // allow dialog to be cancelled.
|
||||
TASKDIALOG_FLAGS flags =
|
||||
TDF_SIZE_TO_CONTENT | // Show all content.
|
||||
TDF_ALLOW_DIALOG_CANCELLATION; // Allow canceling the dialog.
|
||||
|
||||
TASKDIALOGCONFIG config = { 0 };
|
||||
config.cbSize = sizeof(config);
|
||||
|
|
|
@ -80,12 +80,15 @@ window.alert = (message, title='') ->
|
|||
buttons = ['OK']
|
||||
message = message.toString()
|
||||
dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons}
|
||||
# Alert should always return undefined.
|
||||
return
|
||||
|
||||
# And the confirm().
|
||||
window.confirm = (message, title='') ->
|
||||
dialog = remote.require 'dialog'
|
||||
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().
|
||||
window.prompt = ->
|
||||
|
|
|
@ -11,7 +11,9 @@ var dialog = require('dialog');
|
|||
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])
|
||||
|
||||
|
@ -36,17 +38,22 @@ selected, an example is:
|
|||
filters: [
|
||||
{ name: 'Images', extensions: ['jpg', 'png', 'gif'] },
|
||||
{ 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
|
||||
would be passed via `callback(filenames)`
|
||||
|
||||
**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
|
||||
`['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])
|
||||
|
||||
|
@ -70,7 +77,9 @@ will be passed via `callback(filename)`
|
|||
|
||||
* `browserWindow` BrowserWindow
|
||||
* `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
|
||||
* `title` String - Title of the message box, some platforms will not show it
|
||||
* `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 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
|
||||
|
||||
For CoffeeScript, we follow GitHub's [Style
|
||||
|
|
|
@ -70,6 +70,53 @@ driver.wait(function() {
|
|||
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
|
||||
|
||||
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",
|
||||
"devDependencies": {
|
||||
"asar": "0.5.0",
|
||||
"asar": "0.7.x",
|
||||
"coffee-script": "^1.9.2",
|
||||
"coffeelint": "^1.9.4",
|
||||
"request": "*",
|
||||
|
|
|
@ -5,6 +5,13 @@ remote = require 'remote'
|
|||
|
||||
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', ->
|
||||
fixtures = path.join __dirname, 'fixtures'
|
||||
|
||||
|
@ -19,8 +26,8 @@ describe 'ipc module', ->
|
|||
assert.equal a.id, 1127
|
||||
|
||||
it 'should search module from the user app', ->
|
||||
assert.equal 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.filename), path.resolve(__dirname, 'static', 'main.js')
|
||||
comparePaths path.normalize(remote.process.mainModule.paths[0]), path.resolve(__dirname, 'static', 'node_modules')
|
||||
|
||||
describe 'remote.createFunctionWithReturnValue', ->
|
||||
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