Compare commits

...

189 Commits

Author SHA1 Message Date
Cheng Zhao
a840799b46 Bump v0.15.8. 2014-08-18 09:49:08 +00:00
Cheng Zhao
c8ef79817a Merge pull request #585 from atom/menubar_underline
Support specifying accelerator for menu bar items by adding "&" in label
2014-08-18 16:31:22 +08:00
Cheng Zhao
29abba824d A little cleanup. 2014-08-18 16:19:23 +08:00
Cheng Zhao
6ccec45c61 views: Fix activating lower case accelerators. 2014-08-18 16:05:41 +08:00
Cheng Zhao
1dabd20d99 win: Underline's color tends to be a little lighter. 2014-08-18 15:41:57 +08:00
Cheng Zhao
fedb08899c views: Fix calculating underline's position. 2014-08-18 15:36:29 +08:00
Cheng Zhao
b8bfe8a9ad views: Always hide accelerator when submenu is activated. 2014-08-18 14:58:52 +08:00
Cheng Zhao
a230daa998 views: Pressing "Alt+Key" should bring up the menu bar. 2014-08-18 14:52:44 +08:00
Cheng Zhao
ba41634ad6 views: Show menubar's submenu when "Alt+Key" is pressed. 2014-08-18 14:42:21 +08:00
Cheng Zhao
e9536508a5 views: Show menubar's accelerator when "Alt" is pressed. 2014-08-18 14:12:12 +08:00
Cheng Zhao
965f2b1b6b views: Draw underline in menu bar for accelerators. 2014-08-18 13:36:00 +08:00
Cheng Zhao
e25417ab31 linux: Use "fg" of GtkStyle as text color, fixes #555. 2014-08-18 10:29:21 +08:00
Cheng Zhao
48c227c263 Upgrade libchromium for the accelerator fix. 2014-08-17 21:21:28 +08:00
Cheng Zhao
cbd6541e9a views: Fix compilation error. 2014-08-17 12:57:22 +08:00
Cheng Zhao
2a9f5a5fb8 Add "enable-larger-than-screen" option for BrowserWindow.
From now on BrowserWindow can only be resized larger than screen or
moved out of screen when this option is set to "true".

Fixes #582.
2014-08-17 12:23:00 +08:00
Cheng Zhao
78afa29ade Little formating on app.getDataPath. 2014-08-17 11:33:55 +08:00
Cheng Zhao
73bb05e530 mac: Make "Text to Speech" work, fixes atom/atom#3288. 2014-08-17 11:30:26 +08:00
Cheng Zhao
8cc23aca8d Upgrade to Chrome 36.0.1985.143. 2014-08-17 11:30:26 +08:00
Cheng Zhao
f96c6e4bd7 Merge pull request #578 from cornedor/appdata
Fixed  #442 added app.getDataPath()
2014-08-16 20:34:01 +08:00
Corné Dorrestijn
3afb4e017c Added the getDataPath function to the app api docs 2014-08-15 17:29:36 +02:00
Corne Dorrestijn
54ee12308d reused converted and fixed indentation 2014-08-15 16:52:16 +02:00
Cheng Zhao
fd09f13c9b Bump v0.15.7. 2014-08-15 15:07:11 +08:00
Cheng Zhao
86dd8e2dfa docs: Document the chrome command switches we support. 2014-08-15 13:06:52 +08:00
Cheng Zhao
1b70ca2098 Initialize job factory as early as possible.
Fixes atom/atom#3255.
2014-08-15 11:35:13 +08:00
Cheng Zhao
e8d1c69ea8 Enable the spec of testing crash of protocol module. 2014-08-15 11:08:06 +08:00
Cheng Zhao
1883da463f Merge pull request #577 from cornedor/verbose
Added verbose mode to the bootstrap script. Closes #574
2014-08-15 10:40:30 +08:00
Corne Dorrestijn
e9879a3e4b Removed whitespace and added vector import 2014-08-13 14:24:35 +02:00
Corne Dorrestijn
dec05988f4 Fixes for windows 2014-08-13 14:16:55 +02:00
Cheng Zhao
4087062798 Remove old symbols when generating symbols. 2014-08-13 20:08:07 +08:00
Cheng Zhao
31135321c0 Bump v0.15.6. 2014-08-13 18:19:38 +08:00
Cheng Zhao
226cbda7a6 Avoid creating our own URLRequestContextGetter. 2014-08-13 17:40:31 +08:00
Cheng Zhao
66ef1a067d Merge pull request #576 from atom/geolocation
Implement geolocation API
2014-08-13 14:53:07 +08:00
Cheng Zhao
8a7efcdcd2 Fix compilation error on Linux. 2014-08-13 14:43:21 +08:00
Cheng Zhao
adb8fb59bd Add network provider for google geolocation api. 2014-08-13 13:28:05 +08:00
Cheng Zhao
0ca9e8ee82 Add access token store. 2014-08-13 12:12:43 +08:00
Cheng Zhao
e7647ba183 mac: Fix crash when checking for update, fixes #575. 2014-08-13 11:28:19 +08:00
Corne Dorrestijn
be6599807d Added getAppData function to the app api 2014-08-12 17:01:56 +02:00
Cheng Zhao
a8ca0329b4 win: Show minimize button for unresizable window, fixes #411. 2014-08-12 22:58:19 +08:00
Corne Dorrestijn
6d9a88f415 Fixed inconsistent newlines 2014-08-12 14:28:18 +02:00
Corne Dorrestijn
0018d4b705 Added a verbose mode to the bootstrap script 2014-08-12 14:23:59 +02:00
Cheng Zhao
72e8b2882f Upgrade libchromiumcontent.
* Fix unresponsive event when in beforeunload handler.
* Compile with clang 3.4 under Linux.
2014-08-12 20:17:30 +08:00
Cheng Zhao
89539ca15e Update brightray. 2014-08-11 23:23:27 +08:00
Cheng Zhao
175d052a28 linux: Enable tests on window size.
After upgraded to Chrome36, those tests have become stable.
2014-08-11 21:00:04 +08:00
Cheng Zhao
d1a93a5135 views: Set a default maximum window size.
It is required to make the window able to be resized larger than the
screen.
2014-08-11 20:36:53 +08:00
Cheng Zhao
f96485f950 linux: Fix error when generating symbols.
Somehow strip would return 1 when a directory is passed, so we have to
wrap it in a script to avoid the error.
2014-08-11 11:08:29 +00:00
Cheng Zhao
79dfb2d2f3 Bump v0.15.5. 2014-08-11 17:44:16 +08:00
Cheng Zhao
de7ff0f944 Merge pull request #573 from atom/resource-dispatcher-delegate
Enable removing the X-Frame-Options header for frames
2014-08-11 16:31:35 +08:00
Cheng Zhao
80c77ef3a8 Fix cpplint warning. 2014-08-11 15:56:23 +08:00
Cheng Zhao
cad9580796 docs: Move security info from browser-window to web-security. 2014-08-11 15:37:44 +08:00
Cheng Zhao
253789353f docs: Add document on overriding X-Frame-Options. 2014-08-11 15:25:26 +08:00
Cheng Zhao
73262be2c2 Filter out x-frame-options header on user's request. 2014-08-11 15:03:57 +08:00
Cheng Zhao
0ad4c3ca93 Add custom ResourceDispatcherHostDelegate. 2014-08-11 14:08:23 +08:00
Cheng Zhao
b26e3a9629 Merge pull request #572 from atom/window-larger-than-screen
Enable window to be resized larger than screen
2014-08-11 12:17:48 +08:00
Cheng Zhao
c55f6d82d8 Update brightray for devtools experiments. 2014-08-11 10:52:54 +08:00
Cheng Zhao
4b90c02420 mac: Override system's default on resizing window no larger than screen. 2014-08-11 10:24:36 +08:00
Cheng Zhao
d4fb1c1f8c Add spec for resizing window larger than screen. 2014-08-11 10:22:56 +08:00
Cheng Zhao
445fe158cc Store window icon as ImageSkia. 2014-08-11 10:06:46 +08:00
Cheng Zhao
a696f06a23 Restructure headers of native_window. 2014-08-11 10:01:05 +08:00
Cheng Zhao
c019f13e8c docs: Update prerequisities in Windows build instructions. 2014-08-11 09:39:03 +08:00
Cheng Zhao
b4f00f3b40 Update with new ScopedPersistent interface. 2014-08-10 21:19:07 +08:00
Cheng Zhao
f60d8066f8 Use the function converter from native_mate. 2014-08-10 19:14:20 +08:00
Cheng Zhao
b8d5aa586e Merge pull request #567 from atom/linux-ci
Add Linux CI
2014-08-09 10:24:18 +08:00
Cheng Zhao
eeff20f1bc linux: Start xvfb in CI. 2014-08-09 09:59:06 +08:00
Cheng Zhao
9035ffff55 linux: Don't set CXX to clang when building node modules. 2014-08-09 09:24:17 +08:00
Cheng Zhao
ca522f06d3 linux: Do "apt-get update" in CI. 2014-08-08 23:53:58 +08:00
Cheng Zhao
7f534652a6 linux: Install all necessary deps on CI. 2014-08-08 23:41:11 +08:00
Cheng Zhao
b93564894c Make script quit when error happens in child processes. 2014-08-08 23:23:56 +08:00
Cheng Zhao
54b8a62920 linux: Install libgnome-keyring-dev on travis CI. 2014-08-08 23:10:20 +08:00
Cheng Zhao
bcfba96d29 Set compiler to gcc. 2014-08-08 22:38:35 +08:00
Cheng Zhao
8e21530550 Use travis-ci's multi-os feature. 2014-08-08 22:12:24 +08:00
Cheng Zhao
a4f59bc04e Merge pull request #565 from atom/deepak1556-appveyor_setup
Appveyor setup
2014-08-08 22:06:55 +08:00
Cheng Zhao
a378a719e9 Don't run tests. 2014-08-08 21:31:51 +08:00
Cheng Zhao
441ee0d978 Update brightray. 2014-08-08 20:41:24 +08:00
Cheng Zhao
8d7a59161a win: Don't call pylint in CI. 2014-08-08 17:38:22 +08:00
Cheng Zhao
d175a99811 Fix pylint warning. 2014-08-08 17:32:00 +08:00
Cheng Zhao
724b29d6d4 win: Fix calling lint scripts with win32 python. 2014-08-08 16:41:10 +08:00
Cheng Zhao
336908eba0 win: Use absolute path for ATL. 2014-08-08 15:45:24 +08:00
Cheng Zhao
0f5d929c09 win: Build with downloaded ATL instead of the ATL shipped by WDK. 2014-08-08 14:56:48 +08:00
Cheng Zhao
c4b0170a0a views: Only toggle menu bar when auto-hide-menu-bar is turned on. 2014-08-08 14:30:43 +08:00
Cheng Zhao
936860edd5 Merge pull request #564 from sryze/patch-1
Open output file in binary mode in download()
2014-08-08 14:27:26 +08:00
Cheng Zhao
1cadc9221a win: Download ATL binaries. 2014-08-08 14:18:09 +08:00
Sergey Zolotarev
4890eebd3a Open output file in binary mode in download()
This fixes #553.
2014-08-08 13:08:01 +07:00
Cheng Zhao
3a65942b97 Make node version switching faster. 2014-08-08 11:35:08 +08:00
Cheng Zhao
e06c558a86 Add lint scripts. 2014-08-08 10:58:26 +08:00
Cheng Zhao
0a0a408bf8 Upgrade to apm@0.89.0 2014-08-08 09:52:57 +08:00
Cheng Zhao
c9702b56e2 Build only Debug version. 2014-08-08 08:39:37 +08:00
Cheng Zhao
279eb23b38 No need of project_id in appveyor.yml. 2014-08-07 23:52:08 +08:00
Cheng Zhao
8eb650ce03 Merge branch 'appveyor_setup' of https://github.com/deepak1556/atom-shell into deepak1556-appveyor_setup
Conflicts:
	script/lib/util.py
2014-08-07 22:31:48 +08:00
Cheng Zhao
7f9ac88c31 Bump v0.15.4. 2014-08-07 19:42:08 +08:00
Cheng Zhao
424a00cf29 Don't set interval too short.
Otherwise it could be possible that the callback executes for multiple
times before it is cleared.
2014-08-07 19:40:41 +08:00
Cheng Zhao
3c078b4dab Merge pull request #558 from atom/menubar-autohide
Allow window menu bar to be hidden
2014-08-07 19:31:58 +08:00
Cheng Zhao
8cc49ffa80 menu_bar_show_ => menu_bar_visible_ 2014-08-07 16:48:30 +08:00
Cheng Zhao
58a09f6495 linux: Fix detecting Alt modifier. 2014-08-07 16:46:50 +08:00
Cheng Zhao
c2885f77c9 views: Focus on web view when window is focused. 2014-08-07 16:46:48 +08:00
Cheng Zhao
5d5a3138bc views: Toggle the menu bar only when a single Alt is released. 2014-08-07 15:54:05 +08:00
Cheng Zhao
09f9d0729c views: Show menu when "Alt" is up. 2014-08-07 15:07:34 +08:00
Cheng Zhao
3d989b6736 win: Fix the key code of Alt. 2014-08-07 15:02:27 +08:00
Cheng Zhao
daa00e6539 views: Add some asserts and comments. 2014-08-07 14:48:02 +08:00
Cheng Zhao
382dbb500c Also fix setInterval for #481. 2014-08-07 14:23:28 +08:00
Cheng Zhao
92d6fd641f views: Hide menu bar when web view is clicked. 2014-08-07 14:14:43 +08:00
Cheng Zhao
f219e7f0dd views: Switching to other window should hide the menubar. 2014-08-07 14:02:03 +08:00
Cheng Zhao
8a9e1824c3 views: Add support for auto-hide menubar. 2014-08-07 13:47:58 +08:00
Cheng Zhao
b139d97f3d Update brightray for devtools focus fix. 2014-08-07 10:52:17 +08:00
Cheng Zhao
d29efb7f81 Force updating timeout when setTimeout is called, fixes #481. 2014-08-07 10:37:38 +08:00
Cheng Zhao
53cedc6e5d Add spec for #481. 2014-08-07 10:37:38 +08:00
Cheng Zhao
4f4aabef7a Bump v0.15.3. 2014-08-06 23:37:51 +08:00
Cheng Zhao
a888e4b960 linux: Only use global menu bar under Unity.
Fixes atom/atom#3182.
2014-08-06 23:34:16 +08:00
Cheng Zhao
15c31ad1ba Create .version after all files have been downloaded. 2014-08-06 23:16:42 +08:00
Cheng Zhao
196be5291d Merge pull request #552 from atom/dialog-filters
Add support for extension filters for file dialogs
2014-08-06 22:02:22 +08:00
Cheng Zhao
fe9f94555b win: Implement the filters option. 2014-08-06 21:51:36 +08:00
Cheng Zhao
47e0a61dd8 docs: Document the filters option. 2014-08-06 15:00:31 +08:00
Cheng Zhao
5ba324ca9a gtk: Implement the filters option. 2014-08-06 14:49:02 +08:00
Cheng Zhao
0721b34847 mac: Implement the filters option. 2014-08-06 13:58:42 +08:00
Cheng Zhao
dc257f1f86 Add "filters" parameter for file dialogs. 2014-08-06 13:58:42 +08:00
Cheng Zhao
dfe111b95a Add support for multiple DPI images, fixes #541. 2014-08-06 13:56:49 +08:00
Cheng Zhao
a76ae8cd35 docs: Remove the outdated 32bit note in linux build instructions. 2014-08-05 22:44:21 +08:00
Cheng Zhao
866e20b4be Merge pull request #549 from cornedor/master
Add troubleshooting information for #500
2014-08-05 22:40:00 +08:00
Cheng Zhao
d25645ba67 win: Make BrowserWindow.setResizable change window frame dynamically. 2014-08-05 20:41:26 +08:00
Corné Dorrestijn
ad1efa67bc Add troubleshooting information for #500 2014-08-05 13:33:38 +02:00
Cheng Zhao
cbb14f5ca2 win: Disable the LegacyRenderWidgetHostHWND, fixes #506. 2014-08-05 18:49:55 +08:00
Cheng Zhao
a8cd101ff5 win: Fix window frame when DWM is disabled, closes #519. 2014-08-05 18:17:14 +08:00
Cheng Zhao
009e0790fe linux: Draw menubar text and background with native theme, fixes #540. 2014-08-05 18:05:34 +08:00
Cheng Zhao
d31ebb71db Fix cpplint warnings. 2014-08-05 08:46:06 +08:00
Cheng Zhao
2125a0be82 docs: Sort modules in alphabet sequence. 2014-08-05 00:05:26 +08:00
Cheng Zhao
6dc01945af Make Accelerator a standalone JS type.
This makes menu and global-shortcut share the same code on accelerator.
2014-08-05 00:03:58 +08:00
Cheng Zhao
28b9df24a6 Don't create junk file when posting crash report.
Fixes atom/atom#3166.
2014-08-04 22:58:34 +08:00
Cheng Zhao
94b4ceb8ce Bump v0.15.2. 2014-08-04 21:14:07 +08:00
Cheng Zhao
e3eaf909a5 Use the global_shortcut_listener_x11 from chrome36.
This fixes compilation error on Linux.
2014-08-04 12:52:42 +00:00
Cheng Zhao
33580f66df Run user's main script before everything is initialized, fixes #543. 2014-08-04 20:51:08 +08:00
Cheng Zhao
139316b975 Upgrade brightray, fix #498.
Previous 476f545 was using the wrong commit of brightray which didn't
actually contain the fix.
2014-08-04 20:51:07 +08:00
Cheng Zhao
8fe8cd46b9 Merge pull request #544 from hokein/master
📝 Update global-shortcut API document.
2014-08-04 20:12:26 +08:00
Cheng Zhao
e3118359ad Destroy web contents when window is closed.
Previously this was reverted because of Chromium's spammy error
loggings, but it also causes the renderer process not to exit when the
page has been closed. After fixing the spammy error logging, we can now
bring this back.

Fixes atom/atom#3141.
2014-08-04 14:55:08 +08:00
Haojian Wu
681de1b048 📝 Update global-shortcut API document. 2014-08-04 10:11:00 +08:00
Cheng Zhao
4880096f3d Restructure the update.py. 2014-08-03 23:13:04 +08:00
Cheng Zhao
9c038a2402 Merge pull request #534 from hokein/hotkey
Implement global shortcut API, fixes #439
2014-08-03 22:34:59 +08:00
Cheng Zhao
c4d9dc91a6 Merge pull request #537 from springmeyer/patch-1
fix node to build with target_arch=x64 on linux
2014-08-03 21:55:39 +08:00
Dane Springmeyer
16428baea2 make pylint happy 2014-07-31 11:58:45 -07:00
Dane Springmeyer
4cd3119125 fix indent 2014-07-31 11:22:22 -07:00
Dane Springmeyer
191b1aa719 only default to 64 bit build on darwin and 64bit linux
- maintains default to 32 bit on windows
2014-07-31 10:20:33 -07:00
Haojian Wu
035679057e Update GlobalShortcut API design.
* Rename Shortcut API to GlobalShortcut for better suite.
* Implement the new design interfaces.
* Put the chromium related source code to the same directory as in chrome.
2014-07-31 20:58:43 +08:00
Cheng Zhao
fb4ec66b37 Bump v0.15.1. 2014-07-31 11:48:09 +00:00
Cheng Zhao
89f565906b mac: No need to set wantsLayer, it is already done in brightray. 2014-07-31 18:02:12 +08:00
Cheng Zhao
6a5f732bba mac: Emit focus/blur events after page has actually focus/blur-ed.
Otherwise the page would receive the blur event when it has not blured
yet.

Fixes atom/atom#3124.
2014-07-31 17:35:08 +08:00
Cheng Zhao
fba1772000 Don't mess up with browser process's execArgv, fixes #492. 2014-07-31 16:58:59 +08:00
Cheng Zhao
e62986b97d Add spec for #492. 2014-07-31 16:47:11 +08:00
Cheng Zhao
2e38bafdb1 Merge pull request #538 from atom/tracing-module
Add content-tracing module
2014-07-31 16:25:27 +08:00
Cheng Zhao
f3e49b0696 Fix typo. 2014-07-31 15:49:14 +08:00
Cheng Zhao
70aad83b07 Add docs on content-tracing module. 2014-07-31 15:40:40 +08:00
Cheng Zhao
10c862f0bb Add options defines. 2014-07-31 15:12:02 +08:00
Cheng Zhao
d993c92cea Add content-tracing module. 2014-07-31 15:11:34 +08:00
Cheng Zhao
546e4e431d Ship VS2012 redist DLLs.
Atom Shell has been built with VS2013 so we should not ship VS2010's DLLs.
2014-07-31 14:12:17 +08:00
Cheng Zhao
4a7e98e398 linux: Only use global application menubar on unity.
Fixes atom/atom#3114.
2014-07-31 13:11:03 +08:00
Cheng Zhao
ab4558ae32 Merge pull request #530 from atom/ks-vendor-dlls
Vendor Microsoft C/C++ dlls
2014-07-31 13:10:48 +08:00
Dane Springmeyer
978f73756b fix node to build with target_arch=x64 on linux
atom-shell on linux is incorrectly reporting `ia32` for `process.arch`.

This is happening because `-Dtarget_arch=ia32` is passed to ninja on linux inside `script/update.py` which leads to '-DARCH="ia32"' being set in the compile flags. I see that the current intention is to target 64 bit builds on linux (37275c64cd) and the binaries are in fact compiled as 64 bit despite this bug.  I guess ninja is somehow smartly ignoring the incorrect setting of the `-m32` flags at 6d772c3cda/common.gypi (L175-L178).

Until this is fixed it breaks usage of any node-pre-gyp packaged node addons because node-pre-gyp depends on process.arch being correct in order to require the right binary arch.
2014-07-30 20:51:23 -07:00
Cheng Zhao
5086873f78 mac: Guard against closed window, fixes #536. 2014-07-31 10:33:45 +08:00
Haojian Wu
b2217474c1 Nits: Fix code style. 2014-07-31 09:12:44 +08:00
Haojian Wu
9342d59a7c 📝 Shortcut API document. 2014-07-31 09:12:43 +08:00
Haojian Wu
ad827eee90 Emit failed message when fail to register shortcut. 2014-07-31 09:12:43 +08:00
Haojian Wu
a8034364ff linux: Implement global keyboard shortcut API. 2014-07-31 09:12:42 +08:00
Yeechan Lu
c2c5111d75 win: Implement global keyboard shortcut API. 2014-07-31 09:12:42 +08:00
Haojian Wu
4b3bd9c3cc mac: Implement global keyboard shortcut API. 2014-07-31 09:12:41 +08:00
Cheng Zhao
476f545a67 Update brightray, fixes #498. 2014-07-30 22:45:23 +08:00
Kevin Sawicki
16a1edb422 Vendor Microsoft C/C++ dlls 2014-07-29 09:45:35 -07:00
Cheng Zhao
474445fb7d Upgrade apm to 0.84. 2014-07-29 23:00:20 +08:00
Cheng Zhao
5db31517cb mac: Fix app.dock.show/hide, close #520. 2014-07-29 22:31:51 +08:00
Cheng Zhao
740e7fbf1a Bump v0.15.0. 2014-07-29 11:15:05 +08:00
Cheng Zhao
be5789b483 Merge pull request #524 from atom/chrome36
Upgrade to Chrome36
2014-07-29 11:13:50 +08:00
Cheng Zhao
1c415b0666 win: No more need to convert to DIP point for context menu. 2014-07-28 20:44:11 +08:00
Cheng Zhao
8dd7f81175 Fix building on Windows. 2014-07-28 20:32:10 +08:00
Cheng Zhao
87019a1a70 views: No need to destroy Widget, CloseNow already closed native window. 2014-07-28 20:28:54 +08:00
Cheng Zhao
10c52bd6a6 Fix building on Linux. 2014-07-28 20:28:53 +08:00
Cheng Zhao
c23c667c2d Update brightray to fix webrtc warning. 2014-07-28 20:28:52 +08:00
Cheng Zhao
ec4275ca13 Make sure window is closed before WebContents is destroyed.
Otherwise we would get "RawChannel fatal error".
2014-07-28 20:28:51 +08:00
Cheng Zhao
143bde007a Always enable harmony when node binding is on.
If we dont' do this we would have lots of "Extension or internal
compilation error." error, seems to be V8's bug.
2014-07-28 20:28:50 +08:00
Cheng Zhao
a6ede12cd7 Make sure javascript environment is initialized after ProxyResolverV8. 2014-07-28 20:28:50 +08:00
Cheng Zhao
7a89a08534 Update to new Chromium APIs. 2014-07-28 20:28:49 +08:00
Cheng Zhao
5ad203ad99 Upgrade to Chrome 36. 2014-07-28 20:28:48 +08:00
Cheng Zhao
82dcdc6314 Merge pull request #518 from HackPlan/menudpi
win: Fix tray context menu in high DPI mode
2014-07-28 18:53:16 +08:00
Cheng Zhao
371e38198f Merge pull request #516 from alexwhitman/patch-1
Fix isMinimized API documentation
2014-07-28 18:39:02 +08:00
Yeechan Lu
472a95e433 win: Fix tray context menu in high DPI mode 2014-07-27 15:50:04 +08:00
Cheng Zhao
b84226244d Bump v0.14.3. 2014-07-27 09:28:56 +08:00
Alex Whitman
e4290393af Fix isMinimized API documentation 2014-07-26 09:53:02 +01:00
Cheng Zhao
cab00a1450 views: Return restored bounds when window is minimized, fixes #473.
On Window the minimized window would have a fake bounds that is out of
the screen, which is not consistent to other platforms' behavior.
2014-07-26 14:20:50 +08:00
Cheng Zhao
ce50b38a75 Add BrowserWindow.isMaximized API. 2014-07-26 13:58:26 +08:00
Cheng Zhao
e8d59c4326 views: Fix showing window icon, closes #514. 2014-07-26 12:06:38 +08:00
Cheng Zhao
b9d64784bb win: Don't crash on invalid parameter error.
libuv relies on suppressing the invalid parameter error in
uv__get_osfhandle, and it could hanppen frequently.

Fixes #513.
2014-07-26 11:14:28 +08:00
Kevin Sawicki
ad3eac2e38 📝 Mention code signing is required for updates
Refs #512
2014-07-25 09:14:49 -07:00
Robo
58c56ce7ae specify mode for windows 2014-07-02 02:02:23 +05:30
Robo
66983c7f67 inital config setup for x86 2014-07-02 00:09:54 +05:30
127 changed files with 3222 additions and 1135 deletions

View File

@@ -1,4 +1,8 @@
language: objective-c
language: cpp
compiler: clang
os:
- linux
- osx
notifications:
email:

28
appveyor.yml Normal file
View File

@@ -0,0 +1,28 @@
# appveyor file
# http://www.appveyor.com/docs/appveyor-yml
version: "{build}"
init:
- git config --global core.autocrlf input
environment:
matrix:
- nodejs_version: 0.10
platform:
- x86
install:
- ps: Install-Product node $env:nodejs_version
- cmd: SET PATH=C:\Program Files (x86)\MSBuild\12.0\bin\;%PATH%
- cmd: SET PATH=C:\python27;%PATH%
- cmd: python script/bootstrap.py
- cmd: python script/build.py -c Debug
test_script:
- node --version
- npm --version
- cmd: python script/cpplint.py
- cmd: python script/coffeelint.py
build: off

View File

@@ -18,7 +18,9 @@
'atom/browser/api/lib/atom-delegate.coffee',
'atom/browser/api/lib/auto-updater.coffee',
'atom/browser/api/lib/browser-window.coffee',
'atom/browser/api/lib/content-tracing.coffee',
'atom/browser/api/lib/dialog.coffee',
'atom/browser/api/lib/global-shortcut.coffee',
'atom/browser/api/lib/ipc.coffee',
'atom/browser/api/lib/menu.coffee',
'atom/browser/api/lib/menu-item.coffee',
@@ -51,7 +53,10 @@
'atom/browser/api/atom_api_app.h',
'atom/browser/api/atom_api_auto_updater.cc',
'atom/browser/api/atom_api_auto_updater.h',
'atom/browser/api/atom_api_content_tracing.cc',
'atom/browser/api/atom_api_dialog.cc',
'atom/browser/api/atom_api_global_shortcut.cc',
'atom/browser/api/atom_api_global_shortcut.h',
'atom/browser/api/atom_api_menu.cc',
'atom/browser/api/atom_api_menu.h',
'atom/browser/api/atom_api_menu_views.cc',
@@ -78,6 +83,8 @@
'atom/browser/auto_updater_linux.cc',
'atom/browser/auto_updater_mac.mm',
'atom/browser/auto_updater_win.cc',
'atom/browser/atom_access_token_store.cc',
'atom/browser/atom_access_token_store.h',
'atom/browser/atom_browser_client.cc',
'atom/browser/atom_browser_client.h',
'atom/browser/atom_browser_context.cc',
@@ -87,12 +94,16 @@
'atom/browser/atom_browser_main_parts_mac.mm',
'atom/browser/atom_javascript_dialog_manager.cc',
'atom/browser/atom_javascript_dialog_manager.h',
'atom/browser/atom_resource_dispatcher_host_delegate.cc',
'atom/browser/atom_resource_dispatcher_host_delegate.h',
'atom/browser/browser.cc',
'atom/browser/browser.h',
'atom/browser/browser_linux.cc',
'atom/browser/browser_mac.mm',
'atom/browser/browser_win.cc',
'atom/browser/browser_observer.h',
'atom/browser/javascript_environment.cc',
'atom/browser/javascript_environment.h',
'atom/browser/mac/atom_application.h',
'atom/browser/mac/atom_application.mm',
'atom/browser/mac/atom_application_delegate.h',
@@ -106,8 +117,6 @@
'atom/browser/native_window_observer.h',
'atom/browser/net/adapter_request_job.cc',
'atom/browser/net/adapter_request_job.h',
'atom/browser/net/atom_url_request_context_getter.cc',
'atom/browser/net/atom_url_request_context_getter.h',
'atom/browser/net/atom_url_request_job_factory.cc',
'atom/browser/net/atom_url_request_job_factory.h',
'atom/browser/net/url_request_string_job.cc',
@@ -145,6 +154,8 @@
'atom/browser/ui/views/menu_delegate.h',
'atom/browser/ui/views/menu_layout.cc',
'atom/browser/ui/views/menu_layout.h',
'atom/browser/ui/views/submenu_button.cc',
'atom/browser/ui/views/submenu_button.h',
'atom/browser/ui/views/win_frame_view.cc',
'atom/browser/ui/views/win_frame_view.h',
'atom/browser/ui/win/notify_icon_host.cc',
@@ -168,8 +179,6 @@
'atom/common/api/atom_bindings.h',
'atom/common/api/object_life_monitor.cc',
'atom/common/api/object_life_monitor.h',
'atom/common/browser_v8_locker.cc',
'atom/common/browser_v8_locker.h',
'atom/common/crash_reporter/crash_reporter.cc',
'atom/common/crash_reporter/crash_reporter.h',
'atom/common/crash_reporter/crash_reporter_linux.cc',
@@ -187,8 +196,9 @@
'atom/common/draggable_region.cc',
'atom/common/draggable_region.h',
'atom/common/linux/application_info.cc',
'atom/common/native_mate_converters/accelerator_converter.cc',
'atom/common/native_mate_converters/accelerator_converter.h',
'atom/common/native_mate_converters/file_path_converter.h',
'atom/common/native_mate_converters/function_converter.h',
'atom/common/native_mate_converters/gurl_converter.h',
'atom/common/native_mate_converters/image_converter.cc',
'atom/common/native_mate_converters/image_converter.h',
@@ -221,6 +231,14 @@
'atom/renderer/atom_render_view_observer.h',
'atom/renderer/atom_renderer_client.cc',
'atom/renderer/atom_renderer_client.h',
'chromium_src/chrome/browser/extensions/global_shortcut_listener.cc',
'chromium_src/chrome/browser/extensions/global_shortcut_listener.h',
'chromium_src/chrome/browser/extensions/global_shortcut_listener_mac.mm',
'chromium_src/chrome/browser/extensions/global_shortcut_listener_mac.h',
'chromium_src/chrome/browser/extensions/global_shortcut_listener_x11.cc',
'chromium_src/chrome/browser/extensions/global_shortcut_listener_x11.h',
'chromium_src/chrome/browser/extensions/global_shortcut_listener_win.cc',
'chromium_src/chrome/browser/extensions/global_shortcut_listener_win.h',
'chromium_src/chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.cc',
'chromium_src/chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.h',
'chromium_src/chrome/browser/ui/libgtk2ui/gtk2_status_icon.cc',
@@ -377,6 +395,9 @@
'<(libchromiumcontent_resources_dir)/ui_resources_200_percent.pak',
'<(libchromiumcontent_resources_dir)/webkit_resources_200_percent.pak',
'external_binaries/d3dcompiler_43.dll',
'external_binaries/msvcp120.dll',
'external_binaries/msvcr120.dll',
'external_binaries/vccorlib120.dll',
'external_binaries/xinput1_3.dll',
],
},
@@ -617,7 +638,10 @@
# Gyp action requires a output file, add a fake one here.
'<(PRODUCT_DIR)/dummy_file',
],
'action': [ 'strip', '<@(_inputs)' ],
'action': [
'tools/posix/strip.sh',
'<@(_inputs)',
],
},
],
}], # OS=="linux"
@@ -780,5 +804,31 @@
}, # target generate_node_lib
],
}], # OS==win
# Using Visual Studio Express.
['msvs_express==1', {
'target_defaults': {
'defines!': [
'_SECURE_ATL',
],
'msvs_settings': {
'VCLibrarianTool': {
'AdditionalLibraryDirectories': [
'<(atom_source_root)/external_binaries/atl/lib',
],
},
'VCLinkerTool': {
'AdditionalLibraryDirectories': [
'<(atom_source_root)/external_binaries/atl/lib',
],
'AdditionalDependencies': [
'atls.lib',
],
},
},
'msvs_system_include_dirs': [
'<(atom_source_root)/external_binaries/atl/include',
],
},
}], # msvs_express==1
],
}

View File

@@ -74,6 +74,13 @@ void AtomMainDelegate::PreSandboxStartup() {
// Add a flag to mark the start of switches added by atom-shell.
command_line->AppendSwitch("atom-shell-switches-start");
#if defined(OS_WIN)
// Disable the LegacyRenderWidgetHostHWND, it made frameless windows unable
// to move and resize. We may consider enabling it again after upgraded to
// Chrome 38, which should have fixed the problem.
command_line->AppendSwitch(switches::kDisableLegacyIntermediateWindow);
#endif
// Disable renderer sandbox for most of node's functions.
command_line->AppendSwitch(switches::kNoSandbox);

View File

@@ -5,15 +5,23 @@
#include "atom/browser/api/atom_api_app.h"
#include <string>
#include <vector>
#include "base/values.h"
#include "base/command_line.h"
#include "base/environment.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "atom/browser/browser.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "atom/common/node_includes.h"
#if defined(OS_LINUX)
#include "base/nix/xdg_util.h"
#endif
using atom::Browser;
namespace atom {
@@ -60,6 +68,21 @@ void App::OnFinishLaunching() {
Emit("ready");
}
base::FilePath App::GetDataPath() {
base::FilePath path;
#if defined(OS_LINUX)
scoped_ptr<base::Environment> env(base::Environment::Create());
path = base::nix::GetXDGDirectory(env.get(),
base::nix::kXdgConfigHomeEnvVar,
base::nix::kDotConfigDir);
#else
CHECK(PathService::Get(base::DIR_APP_DATA, &path));
#endif
return path.Append(base::FilePath::FromUTF8Unsafe(
Browser::Get()->GetName()));
}
mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
Browser* browser = Browser::Get();
@@ -75,7 +98,8 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
.SetMethod("getName", base::Bind(&Browser::GetName,
base::Unretained(browser)))
.SetMethod("setName", base::Bind(&Browser::SetName,
base::Unretained(browser)));
base::Unretained(browser)))
.SetMethod("getDataPath", &App::GetDataPath);
}
// static

View File

@@ -10,6 +10,7 @@
#include "base/compiler_specific.h"
#include "atom/browser/api/event_emitter.h"
#include "atom/browser/browser_observer.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "native_mate/handle.h"
namespace atom {
@@ -34,6 +35,7 @@ class App : public mate::EventEmitter,
virtual void OnActivateWithNoOpenWindows() OVERRIDE;
virtual void OnWillFinishLaunching() OVERRIDE;
virtual void OnFinishLaunching() OVERRIDE;
virtual base::FilePath GetDataPath();
// mate::Wrappable implementations:
virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder(

View File

@@ -0,0 +1,77 @@
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include <set>
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "base/bind.h"
#include "content/public/browser/tracing_controller.h"
#include "native_mate/callback.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"
using content::TracingController;
namespace mate {
template<typename T>
struct Converter<std::set<T> > {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
const std::set<T>& val) {
v8::Handle<v8::Array> result = v8::Array::New(
isolate, static_cast<int>(val.size()));
typename std::set<T>::const_iterator it;
int i;
for (i = 0, it = val.begin(); it != val.end(); ++it, ++i)
result->Set(i, Converter<T>::ToV8(isolate, *it));
return result;
}
};
template<>
struct Converter<TracingController::Options> {
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
TracingController::Options* out) {
if (!val->IsNumber())
return false;
*out = static_cast<TracingController::Options>(val->IntegerValue());
return true;
}
};
} // namespace mate
namespace {
void Initialize(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> unused,
v8::Handle<v8::Context> context, void* priv) {
TracingController* controller = TracingController::GetInstance();
mate::Dictionary dict(context->GetIsolate(), exports);
dict.SetMethod("getCategories", base::Bind(
&TracingController::GetCategories, base::Unretained(controller)));
dict.SetMethod("startRecording", base::Bind(
&TracingController::EnableRecording, base::Unretained(controller)));
dict.SetMethod("stopRecording", base::Bind(
&TracingController::DisableRecording, base::Unretained(controller)));
dict.SetMethod("startMonitoring", base::Bind(
&TracingController::EnableMonitoring, base::Unretained(controller)));
dict.SetMethod("stopMonitoring", base::Bind(
&TracingController::DisableMonitoring, base::Unretained(controller)));
dict.SetMethod("captureMonitoringSnapshot", base::Bind(
&TracingController::CaptureMonitoringSnapshot,
base::Unretained(controller)));
dict.SetMethod("getTraceBufferPercentFull", base::Bind(
&TracingController::GetTraceBufferPercentFull,
base::Unretained(controller)));
dict.SetMethod("setWatchEvent", base::Bind(
&TracingController::SetWatchEvent, base::Unretained(controller)));
dict.SetMethod("cancelWatchEvent", base::Bind(
&TracingController::CancelWatchEvent, base::Unretained(controller)));
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_content_tracing, Initialize)

View File

@@ -3,19 +3,39 @@
// found in the LICENSE file.
#include <string>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "atom/browser/api/atom_api_window.h"
#include "atom/browser/native_window.h"
#include "atom/browser/ui/file_dialog.h"
#include "atom/browser/ui/message_box.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "atom/common/native_mate_converters/function_converter.h"
#include "native_mate/callback.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"
namespace mate {
template<>
struct Converter<file_dialog::Filter> {
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
file_dialog::Filter* out) {
mate::Dictionary dict(isolate);
if (!ConvertFromV8(isolate, val, &dict))
return false;
if (!dict.Get("name", &(out->first)))
return false;
if (!dict.Get("extensions", &(out->second)))
return false;
return true;
}
};
} // namespace mate
namespace {
void ShowMessageBox(int type,
@@ -41,6 +61,7 @@ void ShowMessageBox(int type,
void ShowOpenDialog(const std::string& title,
const base::FilePath& default_path,
const file_dialog::Filters& filters,
int properties,
atom::NativeWindow* window,
mate::Arguments* args) {
@@ -49,18 +70,19 @@ void ShowOpenDialog(const std::string& title,
if (mate::Converter<file_dialog::OpenDialogCallback>::FromV8(args->isolate(),
peek,
&callback)) {
file_dialog::ShowOpenDialog(window, title, default_path, properties,
callback);
file_dialog::ShowOpenDialog(window, title, default_path, filters,
properties, callback);
} else {
std::vector<base::FilePath> paths;
if (file_dialog::ShowOpenDialog(window, title, default_path, properties,
&paths))
if (file_dialog::ShowOpenDialog(window, title, default_path, filters,
properties, &paths))
args->Return(paths);
}
}
void ShowSaveDialog(const std::string& title,
const base::FilePath& default_path,
const file_dialog::Filters& filters,
atom::NativeWindow* window,
mate::Arguments* args) {
v8::Handle<v8::Value> peek = args->PeekNext();
@@ -68,10 +90,11 @@ void ShowSaveDialog(const std::string& title,
if (mate::Converter<file_dialog::SaveDialogCallback>::FromV8(args->isolate(),
peek,
&callback)) {
file_dialog::ShowSaveDialog(window, title, default_path, callback);
file_dialog::ShowSaveDialog(window, title, default_path, filters, callback);
} else {
base::FilePath path;
if (file_dialog::ShowSaveDialog(window, title, default_path, &path))
if (file_dialog::ShowSaveDialog(window, title, default_path, filters,
&path))
args->Return(path);
}
}

View File

@@ -0,0 +1,107 @@
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_global_shortcut.h"
#include <string>
#include "atom/common/native_mate_converters/accelerator_converter.h"
#include "base/stl_util.h"
#include "native_mate/callback.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"
using extensions::GlobalShortcutListener;
namespace atom {
namespace api {
GlobalShortcut::GlobalShortcut() {
}
GlobalShortcut::~GlobalShortcut() {
UnregisterAll();
}
void GlobalShortcut::OnKeyPressed(const ui::Accelerator& accelerator) {
if (accelerator_callback_map_.find(accelerator) ==
accelerator_callback_map_.end()) {
// This should never occur, because if it does, GlobalGlobalShortcutListener
// notifes us with wrong accelerator.
NOTREACHED();
return;
}
accelerator_callback_map_[accelerator].Run();
}
bool GlobalShortcut::Register(const ui::Accelerator& accelerator,
const base::Closure& callback) {
if (!GlobalShortcutListener::GetInstance()->RegisterAccelerator(
accelerator, this)) {
return false;
}
accelerator_callback_map_[accelerator] = callback;
return true;
}
void GlobalShortcut::Unregister(const ui::Accelerator& accelerator) {
if (!ContainsKey(accelerator_callback_map_, accelerator))
return;
accelerator_callback_map_.erase(accelerator);
GlobalShortcutListener::GetInstance()->UnregisterAccelerator(
accelerator, this);
}
bool GlobalShortcut::IsRegistered(const ui::Accelerator& accelerator) {
return ContainsKey(accelerator_callback_map_, accelerator);
}
void GlobalShortcut::UnregisterAll() {
accelerator_callback_map_.clear();
GlobalShortcutListener::GetInstance()->UnregisterAccelerators(this);
}
// static
mate::ObjectTemplateBuilder GlobalShortcut::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
return mate::ObjectTemplateBuilder(isolate)
.SetMethod("register",
base::Bind(&GlobalShortcut::Register,
base::Unretained(this)))
.SetMethod("isRegistered",
base::Bind(&GlobalShortcut::IsRegistered,
base::Unretained(this)))
.SetMethod("unregister",
base::Bind(&GlobalShortcut::Unregister,
base::Unretained(this)))
.SetMethod("unregisterAll",
base::Bind(&GlobalShortcut::UnregisterAll,
base::Unretained(this)));
}
// static
mate::Handle<GlobalShortcut> GlobalShortcut::Create(v8::Isolate* isolate) {
return CreateHandle(isolate, new GlobalShortcut);
}
} // namespace api
} // namespace atom
namespace {
void Initialize(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> unused,
v8::Handle<v8::Context> context, void* priv) {
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("globalShortcut", atom::api::GlobalShortcut::Create(isolate));
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_global_shortcut, Initialize)

View File

@@ -0,0 +1,55 @@
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_GLOBAL_SHORTCUT_H_
#define ATOM_BROWSER_API_ATOM_API_GLOBAL_SHORTCUT_H_
#include <map>
#include <string>
#include "base/callback.h"
#include "chrome/browser/extensions/global_shortcut_listener.h"
#include "native_mate/wrappable.h"
#include "native_mate/handle.h"
#include "ui/base/accelerators/accelerator.h"
namespace atom {
namespace api {
class GlobalShortcut : public extensions::GlobalShortcutListener::Observer,
public mate::Wrappable {
public:
static mate::Handle<GlobalShortcut> Create(v8::Isolate* isolate);
protected:
GlobalShortcut();
virtual ~GlobalShortcut();
// mate::Wrappable implementations:
virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) OVERRIDE;
private:
typedef std::map<ui::Accelerator, base::Closure> AcceleratorCallbackMap;
bool Register(const ui::Accelerator& accelerator,
const base::Closure& callback);
bool IsRegistered(const ui::Accelerator& accelerator);
void Unregister(const ui::Accelerator& accelerator);
void UnregisterAll();
// GlobalShortcutListener::Observer implementation.
virtual void OnKeyPressed(const ui::Accelerator& accelerator) OVERRIDE;
AcceleratorCallbackMap accelerator_callback_map_;
DISALLOW_COPY_AND_ASSIGN(GlobalShortcut);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_GLOBAL_SHORTCUT_H_

View File

@@ -5,7 +5,7 @@
#include "atom/browser/api/atom_api_menu.h"
#include "atom/browser/native_window.h"
#include "atom/browser/ui/accelerator_util.h"
#include "atom/common/native_mate_converters/accelerator_converter.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "native_mate/constructor.h"
#include "native_mate/dictionary.h"
@@ -92,12 +92,7 @@ bool Menu::GetAcceleratorForCommandId(int command_id,
GetWrapper(isolate),
"getAcceleratorForCommandId",
command_id);
if (shortcut->IsString()) {
std::string shortcut_str = mate::V8ToString(shortcut);
return accelerator_util::StringToAccelerator(shortcut_str, accelerator);
}
return false;
return mate::ConvertFromV8(isolate, shortcut, accelerator);
}
bool Menu::IsItemForCommandIdDynamic(int command_id) const {

View File

@@ -8,7 +8,6 @@
#include "base/message_loop/message_loop.h"
#include "base/strings/sys_string_conversions.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "atom/common/node_includes.h"
@@ -44,7 +43,7 @@ void MenuMac::Popup(Window* window) {
// Show the menu.
[NSMenu popUpContextMenu:[menu_controller menu]
withEvent:clickEvent
forView:web_contents->GetView()->GetContentNativeView()];
forView:web_contents->GetContentNativeView()];
}
// static

View File

@@ -8,10 +8,6 @@
#include "ui/gfx/screen.h"
#include "ui/views/controls/menu/menu_runner.h"
#if defined(OS_WIN)
#include "ui/gfx/win/dpi.h"
#endif
namespace atom {
namespace api {
@@ -21,16 +17,12 @@ MenuViews::MenuViews() {
void MenuViews::Popup(Window* window) {
gfx::Point cursor = gfx::Screen::GetNativeScreen()->GetCursorScreenPoint();
#if defined(OS_WIN)
cursor = gfx::win::ScreenToDIPPoint(cursor);
#endif
views::MenuRunner menu_runner(model());
ignore_result(menu_runner.RunMenuAt(
static_cast<NativeWindowViews*>(window->window())->widget(),
NULL,
gfx::Rect(cursor, gfx::Size()),
views::MenuItemView::TOPLEFT,
views::MENU_ANCHOR_TOPLEFT,
ui::MENU_SOURCE_MOUSE,
views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU));
}

View File

@@ -4,14 +4,12 @@
#include "atom/browser/api/atom_api_protocol.h"
#include "base/stl_util.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/net/adapter_request_job.h"
#include "atom/browser/net/atom_url_request_context_getter.h"
#include "atom/browser/net/atom_url_request_job_factory.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "atom/common/native_mate_converters/function_converter.h"
#include "content/public/browser/browser_thread.h"
#include "native_mate/callback.h"
#include "native_mate/dictionary.h"
#include "net/url_request/url_request_context.h"
@@ -152,8 +150,9 @@ class CustomProtocolHandler : public ProtocolHandler {
} // namespace
Protocol::Protocol() : job_factory_(
AtomBrowserContext::Get()->url_request_context_getter()->job_factory()) {
Protocol::Protocol()
: job_factory_(AtomBrowserContext::Get()->job_factory()) {
CHECK(job_factory_);
}
Protocol::JsProtocolHandler Protocol::GetProtocolHandler(
@@ -324,10 +323,6 @@ namespace {
void Initialize(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> unused,
v8::Handle<v8::Context> context, void* priv) {
// Make sure the job factory has been created.
atom::AtomBrowserContext::Get()->url_request_context_getter()->
GetURLRequestContext();
v8::Isolate* isolate = context->GetIsolate();
mate::Dictionary dict(isolate, exports);
dict.Set("protocol", atom::api::Protocol::Create(isolate));

View File

@@ -9,6 +9,7 @@
#include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
@@ -66,7 +67,7 @@ bool WebContents::OnMessageReceived(const IPC::Message& message) {
return handled;
}
void WebContents::WebContentsDestroyed(content::WebContents*) {
void WebContents::WebContentsDestroyed() {
// The RenderViewDeleted was not called when the WebContents is destroyed.
RenderViewDeleted(web_contents_->GetRenderViewHost());
Emit("destroyed");
@@ -155,8 +156,7 @@ bool WebContents::IsCrashed() const {
}
void WebContents::ExecuteJavaScript(const base::string16& code) {
web_contents()->GetRenderViewHost()->ExecuteJavascriptInWebFrame(
base::string16(), code);
web_contents()->GetMainFrame()->ExecuteJavaScript(code);
}
bool WebContents::SendIPCMessage(const base::string16& channel,

View File

@@ -62,7 +62,7 @@ class WebContents : public mate::EventEmitter,
virtual void DidStopLoading(
content::RenderViewHost* render_view_host) OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
virtual void WebContentsDestroyed(content::WebContents*) OVERRIDE;
virtual void WebContentsDestroyed() OVERRIDE;
private:
// Called when received a message from renderer.

View File

@@ -6,10 +6,8 @@
#include "atom/browser/api/atom_api_web_contents.h"
#include "atom/browser/native_window.h"
#include "atom/common/native_mate_converters/function_converter.h"
#include "base/bind.h"
#include "base/callback.h"
#include "content/public/browser/render_process_host.h"
#include "native_mate/callback.h"
#include "native_mate/constructor.h"
#include "native_mate/dictionary.h"
#include "ui/gfx/point.h"
@@ -161,6 +159,10 @@ void Window::Restore() {
window_->Restore();
}
bool Window::IsMinimized() {
return window_->IsMinimized();
}
void Window::SetFullscreen(bool fullscreen) {
window_->SetFullscreen(fullscreen);
}
@@ -357,6 +359,7 @@ void Window::BuildPrototype(v8::Isolate* isolate,
.SetMethod("isMaximized", &Window::IsMaximized)
.SetMethod("minimize", &Window::Minimize)
.SetMethod("restore", &Window::Restore)
.SetMethod("isMinimized", &Window::IsMinimized)
.SetMethod("setFullScreen", &Window::SetFullscreen)
.SetMethod("isFullScreen", &Window::IsFullscreen)
.SetMethod("getSize", &Window::GetSize)

View File

@@ -66,6 +66,7 @@ class Window : public mate::EventEmitter,
bool IsMaximized();
void Minimize();
void Restore();
bool IsMinimized();
void SetFullscreen(bool fullscreen);
bool IsFullscreen();
void SetSize(int width, int height);

View File

@@ -36,7 +36,7 @@ void Event::SetSenderAndMessage(content::WebContents* sender,
Observe(sender);
}
void Event::WebContentsDestroyed(content::WebContents* web_contents) {
void Event::WebContentsDestroyed() {
sender_ = NULL;
message_ = NULL;
}

View File

@@ -40,7 +40,7 @@ class Event : public Wrappable,
virtual ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate);
// content::WebContentsObserver implementations:
virtual void WebContentsDestroyed(content::WebContents*) OVERRIDE;
virtual void WebContentsDestroyed() OVERRIDE;
private:
// Replyer for the synchronous messages.

View File

@@ -24,8 +24,8 @@ if process.platform is 'darwin'
cancelBounce: bindings.dockCancelBounce
setBadge: bindings.dockSetBadgeText
getBadge: bindings.dockGetBadgeText
hide: bindings.hide
show: bindings.show
hide: bindings.dockHide
show: bindings.dockShow
# Be compatible with old API.
app.once 'ready', -> app.emit 'finish-launching'

View File

@@ -0,0 +1,7 @@
module.exports = process.atomBinding 'content_tracing'
# Mirrored from content::TracingController::Options
module.exports.DEFAULT_OPTIONS = 0
module.exports.ENABLE_SYSTRACE = 1 << 0
module.exports.ENABLE_SAMPLING = 1 << 1
module.exports.RECORD_CONTINUOUSLY = 1 << 2

View File

@@ -3,7 +3,10 @@ v8Util = process.atomBinding 'v8_util'
BrowserWindow = require 'browser-window'
fileDialogProperties =
openFile: 1, openDirectory: 2, multiSelections: 4, createDirectory: 8
openFile: 1 << 0
openDirectory: 1 << 1
multiSelections: 1 << 2
createDirectory: 1 << 3
messageBoxTypes = ['none', 'info', 'warning']
@@ -25,6 +28,7 @@ module.exports =
options.title ?= ''
options.defaultPath ?= ''
options.filters ?= []
wrappedCallback =
if typeof callback is 'function'
@@ -34,6 +38,7 @@ module.exports =
binding.showOpenDialog String(options.title),
String(options.defaultPath),
options.filters
properties,
window,
wrappedCallback
@@ -48,6 +53,7 @@ module.exports =
options ?= title: 'Save'
options.title ?= ''
options.defaultPath ?= ''
options.filters ?= []
wrappedCallback =
if typeof callback is 'function'
@@ -57,6 +63,7 @@ module.exports =
binding.showSaveDialog String(options.title),
String(options.defaultPath),
options.filters
window,
wrappedCallback

View File

@@ -0,0 +1,5 @@
bindings = process.atomBinding 'global_shortcut'
globalShortcut = bindings.globalShortcut
module.exports = globalShortcut

View File

@@ -0,0 +1,53 @@
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/atom_access_token_store.h"
#include <utility>
#include "atom/browser/atom_browser_context.h"
#ifndef GOOGLEAPIS_API_KEY
#define GOOGLEAPIS_API_KEY "AIzaSyAQfxPJiounkhOjODEO5ZieffeBv6yft2Q"
#endif
namespace atom {
namespace {
// Notice that we just combined the api key with the url together here, because
// if we use the standard {url: key} format Chromium would override our key with
// the predefined one in common.gypi of libchromiumcontent, which is empty.
const char* kGeolocationProviderUrl =
"https://www.googleapis.com/geolocation/v1/geolocate?key="
GOOGLEAPIS_API_KEY;
} // namespace
AtomAccessTokenStore::AtomAccessTokenStore() {
}
AtomAccessTokenStore::~AtomAccessTokenStore() {
}
void AtomAccessTokenStore::LoadAccessTokens(
const LoadAccessTokensCallbackType& callback) {
AccessTokenSet access_token_set;
// Equivelent to access_token_set[kGeolocationProviderUrl].
// Somehow base::string16 is causing compilation errors when used in a pair
// of std::map on Linux, this can work around it.
std::pair<GURL, base::string16> token_pair;
token_pair.first = GURL(kGeolocationProviderUrl);
access_token_set.insert(token_pair);
callback.Run(access_token_set,
AtomBrowserContext::Get()->url_request_context_getter());
}
void AtomAccessTokenStore::SaveAccessToken(const GURL& server_url,
const base::string16& access_token) {
}
} // namespace atom

View File

@@ -0,0 +1,31 @@
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_ATOM_ACCESS_TOKEN_STORE_H_
#define ATOM_BROWSER_ATOM_ACCESS_TOKEN_STORE_H_
#include "content/public/browser/access_token_store.h"
namespace atom {
class AtomBrowserContext;
class AtomAccessTokenStore : public content::AccessTokenStore {
public:
AtomAccessTokenStore();
virtual ~AtomAccessTokenStore();
// content::AccessTokenStore:
virtual void LoadAccessTokens(
const LoadAccessTokensCallbackType& callback) OVERRIDE;
virtual void SaveAccessToken(const GURL& server_url,
const base::string16& access_token) OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(AtomAccessTokenStore);
};
} // namespace atom
#endif // ATOM_BROWSER_ATOM_ACCESS_TOKEN_STORE_H_

View File

@@ -4,13 +4,15 @@
#include "atom/browser/atom_browser_client.h"
#include "atom/browser/atom_access_token_store.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/atom_resource_dispatcher_host_delegate.h"
#include "atom/browser/native_window.h"
#include "atom/browser/net/atom_url_request_context_getter.h"
#include "atom/browser/window_list.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/web_contents.h"
#include "ui/base/l10n/l10n_util.h"
@@ -46,12 +48,14 @@ AtomBrowserClient::AtomBrowserClient()
AtomBrowserClient::~AtomBrowserClient() {
}
net::URLRequestContextGetter* AtomBrowserClient::CreateRequestContext(
content::BrowserContext* browser_context,
content::ProtocolHandlerMap* protocol_handlers,
content::ProtocolHandlerScopedVector protocol_interceptors) {
return static_cast<AtomBrowserContext*>(browser_context)->
CreateRequestContext(protocol_handlers);
void AtomBrowserClient::ResourceDispatcherHostCreated() {
resource_dispatcher_delegate_.reset(new AtomResourceDispatcherHostDelegate);
content::ResourceDispatcherHost::Get()->SetDelegate(
resource_dispatcher_delegate_.get());
}
content::AccessTokenStore* AtomBrowserClient::CreateAccessTokenStore() {
return new AtomAccessTokenStore;
}
void AtomBrowserClient::OverrideWebkitPrefs(

View File

@@ -11,16 +11,17 @@
namespace atom {
class AtomResourceDispatcherHostDelegate;
class AtomBrowserClient : public brightray::BrowserClient {
public:
AtomBrowserClient();
virtual ~AtomBrowserClient();
protected:
net::URLRequestContextGetter* CreateRequestContext(
content::BrowserContext* browser_context,
content::ProtocolHandlerMap* protocol_handlers,
content::ProtocolHandlerScopedVector protocol_interceptors) OVERRIDE;
// content::ContentBrowserClient:
virtual void ResourceDispatcherHostCreated() OVERRIDE;
virtual content::AccessTokenStore* CreateAccessTokenStore() OVERRIDE;
virtual void OverrideWebkitPrefs(content::RenderViewHost* render_view_host,
const GURL& url,
WebPreferences* prefs) OVERRIDE;
@@ -36,6 +37,8 @@ class AtomBrowserClient : public brightray::BrowserClient {
virtual brightray::BrowserMainParts* OverrideCreateBrowserMainParts(
const content::MainFunctionParams&) OVERRIDE;
scoped_ptr<AtomResourceDispatcherHostDelegate> resource_dispatcher_delegate_;
// The render process which would be swapped out soon.
content::RenderProcessHost* dying_render_process_;

View File

@@ -5,72 +5,54 @@
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/net/atom_url_request_context_getter.h"
#include "atom/browser/net/atom_url_request_job_factory.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/worker_pool.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_context.h"
#include "vendor/brightray/browser/network_delegate.h"
namespace atom {
#include "content/public/common/url_constants.h"
#include "net/url_request/data_protocol_handler.h"
#include "net/url_request/file_protocol_handler.h"
#include "net/url_request/protocol_intercept_job_factory.h"
using content::BrowserThread;
class AtomResourceContext : public content::ResourceContext {
public:
AtomResourceContext() : getter_(NULL) {}
void set_url_request_context_getter(AtomURLRequestContextGetter* getter) {
getter_ = getter;
}
protected:
virtual net::HostResolver* GetHostResolver() OVERRIDE {
DCHECK(getter_);
return getter_->host_resolver();
}
virtual net::URLRequestContext* GetRequestContext() OVERRIDE {
DCHECK(getter_);
return getter_->GetURLRequestContext();
}
virtual bool AllowMicAccess(const GURL& origin) OVERRIDE {
return true;
}
virtual bool AllowCameraAccess(const GURL& origin) OVERRIDE {
return true;
}
private:
AtomURLRequestContextGetter* getter_;
DISALLOW_COPY_AND_ASSIGN(AtomResourceContext);
};
namespace atom {
AtomBrowserContext::AtomBrowserContext()
: resource_context_(new AtomResourceContext) {
: job_factory_(new AtomURLRequestJobFactory) {
}
AtomBrowserContext::~AtomBrowserContext() {
}
AtomURLRequestContextGetter* AtomBrowserContext::CreateRequestContext(
content::ProtocolHandlerMap* protocol_handlers) {
DCHECK(!url_request_getter_);
url_request_getter_ = new AtomURLRequestContextGetter(
GetPath(),
BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO),
BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::FILE),
base::Bind(&AtomBrowserContext::CreateNetworkDelegate,
base::Unretained(this)),
protocol_handlers);
scoped_ptr<net::URLRequestJobFactory>
AtomBrowserContext::CreateURLRequestJobFactory(
content::ProtocolHandlerMap* handlers,
content::ProtocolHandlerScopedVector* interceptors) {
scoped_ptr<AtomURLRequestJobFactory> job_factory(job_factory_);
resource_context_->set_url_request_context_getter(url_request_getter_.get());
return url_request_getter_.get();
}
for (content::ProtocolHandlerMap::iterator it = handlers->begin();
it != handlers->end(); ++it)
job_factory->SetProtocolHandler(it->first, it->second.release());
handlers->clear();
content::ResourceContext* AtomBrowserContext::GetResourceContext() {
return resource_context_.get();
job_factory->SetProtocolHandler(
content::kDataScheme, new net::DataProtocolHandler);
job_factory->SetProtocolHandler(
content::kFileScheme, new net::FileProtocolHandler(
BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)));
// Set up interceptors in the reverse order.
scoped_ptr<net::URLRequestJobFactory> top_job_factory =
job_factory.PassAs<net::URLRequestJobFactory>();
content::ProtocolHandlerScopedVector::reverse_iterator it;
for (it = interceptors->rbegin(); it != interceptors->rend(); ++it)
top_job_factory.reset(new net::ProtocolInterceptJobFactory(
top_job_factory.Pass(), make_scoped_ptr(*it)));
interceptors->weak_clear();
return top_job_factory.Pass();
}
// static

View File

@@ -5,13 +5,11 @@
#ifndef ATOM_BROWSER_ATOM_BROWSER_CONTEXT_H_
#define ATOM_BROWSER_ATOM_BROWSER_CONTEXT_H_
#include "base/memory/scoped_ptr.h"
#include "brightray/browser/browser_context.h"
namespace atom {
class AtomResourceContext;
class AtomURLRequestContextGetter;
class AtomURLRequestJobFactory;
class AtomBrowserContext : public brightray::BrowserContext {
public:
@@ -21,22 +19,16 @@ class AtomBrowserContext : public brightray::BrowserContext {
// Returns the browser context singleton.
static AtomBrowserContext* Get();
// Creates or returns the request context.
AtomURLRequestContextGetter* CreateRequestContext(
content::ProtocolHandlerMap*);
AtomURLRequestContextGetter* url_request_context_getter() const {
DCHECK(url_request_getter_);
return url_request_getter_.get();
}
AtomURLRequestJobFactory* job_factory() const { return job_factory_; }
protected:
// content::BrowserContext implementations:
virtual content::ResourceContext* GetResourceContext() OVERRIDE;
// brightray::BrowserContext:
virtual scoped_ptr<net::URLRequestJobFactory> CreateURLRequestJobFactory(
content::ProtocolHandlerMap* handlers,
content::ProtocolHandlerScopedVector* interceptors) OVERRIDE;
private:
scoped_ptr<AtomResourceContext> resource_context_;
scoped_refptr<AtomURLRequestContextGetter> url_request_getter_;
AtomURLRequestJobFactory* job_factory_; // Weak reference.
DISALLOW_COPY_AND_ASSIGN(AtomBrowserContext);
};

View File

@@ -7,10 +7,10 @@
#include "atom/browser/atom_browser_client.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/browser.h"
#include "atom/browser/javascript_environment.h"
#include "atom/common/api/atom_bindings.h"
#include "atom/common/node_bindings.h"
#include "base/command_line.h"
#include "net/proxy/proxy_resolver_v8.h"
#if defined(OS_WIN)
#include "ui/gfx/win/dpi.h"
@@ -28,14 +28,9 @@ namespace atom {
AtomBrowserMainParts* AtomBrowserMainParts::self_ = NULL;
AtomBrowserMainParts::AtomBrowserMainParts()
: atom_bindings_(new AtomBindings),
browser_(new Browser),
: browser_(new Browser),
node_bindings_(NodeBindings::Create(true)),
isolate_(v8::Isolate::GetCurrent()),
locker_(isolate_),
handle_scope_(isolate_),
context_(isolate_, v8::Context::New(isolate_)),
context_scope_(v8::Local<v8::Context>::New(isolate_, context_)) {
atom_bindings_(new AtomBindings) {
DCHECK(!self_) << "Cannot have two AtomBrowserMainParts";
self_ = this;
}
@@ -53,39 +48,35 @@ brightray::BrowserContext* AtomBrowserMainParts::CreateBrowserContext() {
return new AtomBrowserContext();
}
void AtomBrowserMainParts::InitProxyResolverV8() {
// Since we are integrating node in browser, we can just be sure that an
// V8 instance would be prepared, while the ProxyResolverV8::CreateIsolate()
// would try to create a V8 isolate, which messed everything on Windows, so
// we have to override and call RememberDefaultIsolate on Windows instead.
net::ProxyResolverV8::RememberDefaultIsolate();
}
void AtomBrowserMainParts::PostEarlyInitialization() {
brightray::BrowserMainParts::PostEarlyInitialization();
// The ProxyResolverV8 has setup a complete V8 environment, in order to avoid
// conflicts we only initialize our V8 environment after that.
js_env_.reset(new JavascriptEnvironment);
node_bindings_->Initialize();
// Create the global environment.
global_env = node_bindings_->CreateEnvironment(
v8::Local<v8::Context>::New(isolate_, context_));
global_env = node_bindings_->CreateEnvironment(js_env_->context());
// Add atom-shell extended APIs.
atom_bindings_->BindTo(isolate_, global_env->process_object());
atom_bindings_->BindTo(js_env_->isolate(), global_env->process_object());
}
void AtomBrowserMainParts::PreMainMessageLoopRun() {
// Run user's main script before most things get initialized, so we can have
// a chance to setup everything.
node_bindings_->PrepareMessageLoop();
node_bindings_->RunMessageLoop();
brightray::BrowserMainParts::PreMainMessageLoopRun();
#if defined(USE_X11)
libgtk2ui::GtkInitFromCommandLine(*CommandLine::ForCurrentProcess());
#endif
node_bindings_->PrepareMessageLoop();
node_bindings_->RunMessageLoop();
// Make sure the url request job factory is created before the
// will-finish-launching event.
// Make sure the url request job factory is created before the ready event.
static_cast<content::BrowserContext*>(AtomBrowserContext::Get())->
GetRequestContext();

View File

@@ -6,12 +6,12 @@
#define ATOM_BROWSER_ATOM_BROWSER_MAIN_PARTS_H_
#include "brightray/browser/browser_main_parts.h"
#include "v8/include/v8.h"
namespace atom {
class AtomBindings;
class Browser;
class JavascriptEnvironment;
class NodeBindings;
class AtomBrowserMainParts : public brightray::BrowserMainParts {
@@ -26,7 +26,6 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
protected:
// Implementations of brightray::BrowserMainParts.
virtual brightray::BrowserContext* CreateBrowserContext() OVERRIDE;
virtual void InitProxyResolverV8() OVERRIDE;
// Implementations of content::BrowserMainParts.
virtual void PostEarlyInitialization() OVERRIDE;
@@ -37,16 +36,10 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
#endif
private:
scoped_ptr<AtomBindings> atom_bindings_;
scoped_ptr<Browser> browser_;
scoped_ptr<JavascriptEnvironment> js_env_;
scoped_ptr<NodeBindings> node_bindings_;
// The V8 environment of browser process.
v8::Isolate* isolate_;
v8::Locker locker_;
v8::HandleScope handle_scope_;
v8::UniquePersistent<v8::Context> context_;
v8::Context::Scope context_scope_;
scoped_ptr<AtomBindings> atom_bindings_;
static AtomBrowserMainParts* self_;

View File

@@ -0,0 +1,50 @@
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/atom_resource_dispatcher_host_delegate.h"
#include <string>
#include "base/logging.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/resource_request_info.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request.h"
namespace atom {
namespace {
const char* kDisableXFrameOptions = "disable-x-frame-options";
} // namespace
AtomResourceDispatcherHostDelegate::AtomResourceDispatcherHostDelegate() {
}
AtomResourceDispatcherHostDelegate::~AtomResourceDispatcherHostDelegate() {
}
void AtomResourceDispatcherHostDelegate::OnResponseStarted(
net::URLRequest* request,
content::ResourceContext* resource_context,
content::ResourceResponse* response,
IPC::Sender* sender) {
// Check if frame's name contains "disable-x-frame-options"
int p, f;
if (!content::ResourceRequestInfo::GetRenderFrameForRequest(request, &p, &f))
return;
content::RenderFrameHost* frame = content::RenderFrameHost::FromID(p, f);
if (!frame)
return;
if (frame->GetFrameName().find(kDisableXFrameOptions) == std::string::npos)
return;
// Remove the "X-Frame-Options" from response headers.
net::HttpResponseHeaders* response_headers = request->response_headers();
if (response_headers && response_headers->HasHeader("x-frame-options"))
response_headers->RemoveHeader("x-frame-options");
}
} // namespace atom

View File

@@ -0,0 +1,31 @@
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_ATOM_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
#define ATOM_BROWSER_ATOM_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
#include "base/compiler_specific.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
namespace atom {
class AtomResourceDispatcherHostDelegate
: public content::ResourceDispatcherHostDelegate {
public:
AtomResourceDispatcherHostDelegate();
virtual ~AtomResourceDispatcherHostDelegate();
// content::ResourceDispatcherHostDelegate:
virtual void OnResponseStarted(net::URLRequest* request,
content::ResourceContext* resource_context,
content::ResourceResponse* response,
IPC::Sender* sender) OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(AtomResourceDispatcherHostDelegate);
};
} // namespace atom
#endif // ATOM_BROWSER_ATOM_RESOURCE_DISPATCHER_HOST_DELEGATE_H_

View File

@@ -48,11 +48,13 @@ void AutoUpdater::SetFeedURL(const std::string& feed) {
[[g_updater rac_valuesForKeyPath:@"state" observer:g_updater]
subscribeNext:^(NSNumber *stateNumber) {
int state = [stateNumber integerValue];
if (state == SQRLUpdaterStateCheckingForUpdate) {
delegate->OnCheckingForUpdate();
} else if (state == SQRLUpdaterStateDownloadingUpdate) {
delegate->OnUpdateAvailable();
}
// Dispatching the event on main thread.
dispatch_async(dispatch_get_main_queue(), ^{
if (state == SQRLUpdaterStateCheckingForUpdate)
delegate->OnCheckingForUpdate();
else if (state == SQRLUpdaterStateDownloadingUpdate)
delegate->OnUpdateAvailable();
});
}];
}
}
@@ -89,4 +91,5 @@ void AutoUpdater::CheckForUpdates() {
delegate->OnError(base::SysNSStringToUTF8(error.localizedDescription));
}];
}
} // namespace auto_updater

View File

@@ -0,0 +1,17 @@
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/javascript_environment.h"
namespace atom {
JavascriptEnvironment::JavascriptEnvironment()
: isolate_(v8::Isolate::GetCurrent()),
locker_(isolate_),
handle_scope_(isolate_),
context_(isolate_, v8::Context::New(isolate_)),
context_scope_(v8::Local<v8::Context>::New(isolate_, context_)) {
}
} // namespace atom

View File

@@ -0,0 +1,34 @@
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_JAVASCRIPT_ENVIRONMENT_H_
#define ATOM_BROWSER_JAVASCRIPT_ENVIRONMENT_H_
#include "base/basictypes.h"
#include "v8/include/v8.h"
namespace atom {
class JavascriptEnvironment {
public:
JavascriptEnvironment();
v8::Isolate* isolate() const { return isolate_; }
v8::Local<v8::Context> context() const {
return v8::Local<v8::Context>::New(isolate_, context_);
}
private:
v8::Isolate* isolate_;
v8::Locker locker_;
v8::HandleScope handle_scope_;
v8::UniquePersistent<v8::Context> context_;
v8::Context::Scope context_scope_;
DISALLOW_COPY_AND_ASSIGN(JavascriptEnvironment);
};
} // namespace atom
#endif // ATOM_BROWSER_JAVASCRIPT_ENVIRONMENT_H_

View File

@@ -14,7 +14,7 @@ process.argv.splice 1, 1
# Pick out switches appended by atom-shell.
startMark = process.argv.indexOf '--atom-shell-switches-start'
endMark = process.argv.indexOf '--atom-shell-switches-end'
process.execArgv = process.argv.splice startMark, endMark - startMark + 1
process.argv.splice startMark, endMark - startMark + 1
# Add browser/api/lib to require's search paths,
# which contains javascript part of Atom's built-in libraries.

View File

@@ -27,6 +27,8 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "brightray/browser/inspectable_web_contents.h"
#include "brightray/browser/inspectable_web_contents_view.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/navigation_entry.h"
@@ -38,19 +40,14 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/common/renderer_preferences.h"
#include "content/public/common/user_agent.h"
#include "ipc/ipc_message_macros.h"
#include "native_mate/dictionary.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
#include "vendor/brightray/browser/inspectable_web_contents.h"
#include "vendor/brightray/browser/inspectable_web_contents_view.h"
#include "webkit/common/webpreferences.h"
using content::NavigationEntry;
@@ -61,6 +58,7 @@ NativeWindow::NativeWindow(content::WebContents* web_contents,
const mate::Dictionary& options)
: content::WebContentsObserver(web_contents),
has_frame_(true),
enable_larger_than_screen_(false),
is_closed_(false),
node_integration_("except-iframe"),
has_dialog_attached_(false),
@@ -69,11 +67,10 @@ NativeWindow::NativeWindow(content::WebContents* web_contents,
inspectable_web_contents_(
brightray::InspectableWebContents::Create(web_contents)) {
options.Get(switches::kFrame, &has_frame_);
options.Get(switches::kEnableLargerThanScreen, &enable_larger_than_screen_);
// Read icon before window is created.
gfx::ImageSkia icon;
if (options.Get(switches::kIcon, &icon))
icon_.reset(new gfx::Image(icon));
options.Get(switches::kIcon, &icon_);
// Read iframe security before any navigation.
options.Get(switches::kNodeIntegration, &node_integration_);
@@ -105,10 +102,6 @@ NativeWindow::NativeWindow(content::WebContents* web_contents,
}
NativeWindow::~NativeWindow() {
// Make sure we have the OnRenderViewDeleted message sent even when the window
// is destroyed directly.
DestroyWebContents();
// It's possible that the windows gets destroyed before it's closed, in that
// case we need to ensure the OnWindowClosed message is still notified.
NotifyWindowClosed();
@@ -305,7 +298,7 @@ void NativeWindow::CloseWebContents() {
ScheduleUnresponsiveEvent(5000);
if (web_contents->NeedToFireBeforeUnload())
web_contents->GetMainFrame()->DispatchBeforeUnload(false);
web_contents->DispatchBeforeUnload(false);
else
web_contents->Close();
}
@@ -356,8 +349,6 @@ void NativeWindow::OverrideWebkitPrefs(const GURL& url, WebPreferences* prefs) {
prefs->experimental_webgl_enabled = b;
if (web_preferences.Get("webaudio", &b))
prefs->webaudio_enabled = b;
if (web_preferences.Get("accelerated-compositing", &b))
prefs->accelerated_compositing_enabled = b;
if (web_preferences.Get("plugins", &b))
prefs->plugins_enabled = b;
if (web_preferences.Get("extra-plugin-dirs", &list))
@@ -535,8 +526,9 @@ void NativeWindow::DevToolsSaveToFile(const std::string& url,
if (it != saved_files_.end() && !save_as) {
path = it->second;
} else {
file_dialog::Filters filters;
base::FilePath default_path(base::FilePath::FromUTF8Unsafe(url));
if (!file_dialog::ShowSaveDialog(this, url, default_path, &path)) {
if (!file_dialog::ShowSaveDialog(this, url, default_path, filters, &path)) {
base::StringValue url_value(url);
CallDevToolsFunction("InspectorFrontendAPI.canceledSaveURL", &url_value);
return;

View File

@@ -9,20 +9,19 @@
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "atom/browser/native_window_observer.h"
#include "atom/browser/ui/accelerator_util.h"
#include "base/cancelable_callback.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "atom/browser/native_window_observer.h"
#include "atom/browser/ui/accelerator_util.h"
#include "brightray/browser/default_web_contents_delegate.h"
#include "brightray/browser/inspectable_web_contents_delegate.h"
#include "brightray/browser/inspectable_web_contents_impl.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_observer.h"
#include "native_mate/scoped_persistent.h"
#include "vendor/brightray/browser/default_web_contents_delegate.h"
#include "vendor/brightray/browser/inspectable_web_contents_delegate.h"
#include "vendor/brightray/browser/inspectable_web_contents_impl.h"
#include "ui/gfx/image/image_skia.h"
struct WebPreferences;
@@ -36,7 +35,6 @@ class WebContents;
}
namespace gfx {
class Image;
class Point;
class Rect;
class Size;
@@ -111,6 +109,7 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
virtual bool IsMaximized() = 0;
virtual void Minimize() = 0;
virtual void Restore() = 0;
virtual bool IsMinimized() = 0;
virtual void SetFullscreen(bool fullscreen) = 0;
virtual bool IsFullscreen() = 0;
virtual void SetSize(const gfx::Size& size) = 0;
@@ -252,8 +251,11 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
// Whether window has standard frame.
bool has_frame_;
// Whether window can be resized larger than screen.
bool enable_larger_than_screen_;
// Window icon.
scoped_ptr<gfx::Image> icon_;
gfx::ImageSkia icon_;
private:
// Schedule a notification unresponsive event.

View File

@@ -35,6 +35,7 @@ class NativeWindowMac : public NativeWindow {
virtual bool IsMaximized() OVERRIDE;
virtual void Minimize() OVERRIDE;
virtual void Restore() OVERRIDE;
virtual bool IsMinimized() OVERRIDE;
virtual void SetFullscreen(bool fullscreen) OVERRIDE;
virtual bool IsFullscreen() OVERRIDE;
virtual void SetSize(const gfx::Size& size) OVERRIDE;

View File

@@ -13,7 +13,6 @@
#include "base/strings/sys_string_conversions.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "native_mate/dictionary.h"
@@ -50,31 +49,31 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
}
- (void)windowDidBecomeMain:(NSNotification*)notification {
shell_->NotifyWindowFocus();
content::WebContents* web_contents = shell_->GetWebContents();
if (!web_contents)
return;
web_contents->GetView()->RestoreFocus();
web_contents->RestoreFocus();
content::RenderWidgetHostView* rwhv = web_contents->GetRenderWidgetHostView();
if (rwhv)
rwhv->SetActive(true);
shell_->NotifyWindowFocus();
}
- (void)windowDidResignMain:(NSNotification*)notification {
shell_->NotifyWindowBlur();
content::WebContents* web_contents = shell_->GetWebContents();
if (!web_contents)
return;
web_contents->GetView()->StoreFocus();
web_contents->StoreFocus();
content::RenderWidgetHostView* rwhv = web_contents->GetRenderWidgetHostView();
if (rwhv)
rwhv->SetActive(false);
shell_->NotifyWindowBlur();
}
- (void)windowDidResize:(NSNotification*)otification {
@@ -109,10 +108,12 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
@end
@interface AtomNSWindow : EventProcessingWindow {
@protected
@private
atom::NativeWindowMac* shell_;
bool enable_larger_than_screen_;
}
- (void)setShell:(atom::NativeWindowMac*)shell;
- (void)setEnableLargerThanScreen:(bool)enable;
@end
@implementation AtomNSWindow
@@ -121,6 +122,18 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
shell_ = shell;
}
- (void)setEnableLargerThanScreen:(bool)enable {
enable_larger_than_screen_ = enable;
}
// Enable the window to be larger than screen.
- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen*)screen {
if (enable_larger_than_screen_)
return frameRect;
else
return [super constrainFrameRect:frameRect toScreen:screen];
}
- (IBAction)reload:(id)sender {
shell_->GetWebContents()->GetController().ReloadIgnoringCache(false);
}
@@ -129,6 +142,20 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
shell_->OpenDevTools();
}
// Returns an empty array for AXChildren attribute, this will force the
// SpeechSynthesisServer to use its classical way of speaking the selected text:
// by invoking the "Command+C" for current application and then speak out
// what's in the clipboard. Otherwise the "Text to Speech" would always speak
// out window's title.
// This behavior is taken by both FireFox and Chrome, see also FireFox's bug on
// more of how SpeechSynthesisServer chose which text to read:
// https://bugzilla.mozilla.org/show_bug.cgi?id=674612
- (id)accessibilityAttributeValue:(NSString*)attribute {
if ([attribute isEqualToString:@"AXChildren"])
return [NSArray array];
return [super accessibilityAttributeValue:attribute];
}
@end
@interface ControlRegionView : NSView {
@@ -195,6 +222,7 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
defer:YES];
[atomWindow setShell:this];
[atomWindow setEnableLargerThanScreen:enable_larger_than_screen_];
window_.reset(atomWindow);
AtomNSWindowDelegate* delegate =
@@ -304,6 +332,10 @@ void NativeWindowMac::Restore() {
[window_ deminiaturize:nil];
}
bool NativeWindowMac::IsMinimized() {
return [window_ isMiniaturized];
}
void NativeWindowMac::SetFullscreen(bool fullscreen) {
if (fullscreen == IsFullscreen())
return;
@@ -488,7 +520,7 @@ gfx::NativeWindow NativeWindowMac::GetNativeWindow() {
bool NativeWindowMac::IsWithinDraggableRegion(NSPoint point) const {
if (!draggable_region_)
return false;
NSView* webView = GetWebContents()->GetView()->GetNativeView();
NSView* webView = GetWebContents()->GetNativeView();
NSInteger webViewHeight = NSHeight([webView bounds]);
// |draggable_region_| is stored in local platform-indepdent coordiate system
// while |point| is in local Cocoa coordinate system. Do the conversion
@@ -553,8 +585,6 @@ void NativeWindowMac::InstallView() {
base::scoped_nsobject<CALayer> layer([[CALayer alloc] init]);
[layer setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)];
[view setLayer:layer];
[view setWantsLayer:YES];
[view setFrame:[[window_ contentView] bounds]];
[[window_ contentView] addSubview:view];
} else {
@@ -577,9 +607,7 @@ void NativeWindowMac::UninstallView() {
}
void NativeWindowMac::ClipWebView() {
NSView* view = GetWebContents()->GetView()->GetNativeView();
view.wantsLayer = YES;
NSView* view = GetWebContents()->GetNativeView();
view.layer.masksToBounds = YES;
view.layer.cornerRadius = kAtomWindowCornerRadius;
}
@@ -590,7 +618,7 @@ void NativeWindowMac::InstallDraggableRegionViews() {
// All ControlRegionViews should be added as children of the WebContentsView,
// because WebContentsView will be removed and re-added when entering and
// leaving fullscreen mode.
NSView* webView = GetWebContents()->GetView()->GetNativeView();
NSView* webView = GetWebContents()->GetNativeView();
NSInteger webViewHeight = NSHeight([webView bounds]);
// Remove all ControlRegionViews that are added last time.
@@ -622,7 +650,7 @@ void NativeWindowMac::UpdateDraggableRegionsForCustomDrag(
const std::vector<DraggableRegion>& regions) {
// We still need one ControlRegionView to cover the whole window such that
// mouse events could be captured.
NSView* web_view = GetWebContents()->GetView()->GetNativeView();
NSView* web_view = GetWebContents()->GetNativeView();
gfx::Rect window_bounds(
0, 0, NSWidth([web_view bounds]), NSHeight([web_view bounds]));
system_drag_exclude_areas_.clear();

View File

@@ -24,13 +24,10 @@
#include "base/strings/utf_string_conversions.h"
#include "browser/inspectable_web_contents_view.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/web_contents_view.h"
#include "native_mate/dictionary.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/hit_test.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/views/background.h"
#include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
#include "ui/views/controls/webview/webview.h"
@@ -40,11 +37,15 @@
#if defined(USE_X11)
#include "atom/browser/ui/views/global_menu_bar_x11.h"
#include "atom/browser/ui/views/frameless_view.h"
#include "base/environment.h"
#include "base/nix/xdg_util.h"
#include "chrome/browser/ui/libgtk2ui/unity_service.h"
#include "ui/gfx/x/x11_types.h"
#include "ui/views/window/native_frame_view.h"
#elif defined(OS_WIN)
#include "atom/browser/ui/views/win_frame_view.h"
#include "base/win/scoped_comptr.h"
#include "ui/base/win/shell.h"
#endif
namespace atom {
@@ -58,6 +59,32 @@ const int kMenuBarHeight = 20;
const int kMenuBarHeight = 25;
#endif
#if defined(USE_X11)
bool ShouldUseGlobalMenuBar() {
// Some DE would pretend to be Unity but don't have global application menu,
// so we can not trust unity::IsRunning().
scoped_ptr<base::Environment> env(base::Environment::Create());
return unity::IsRunning() && (base::nix::GetDesktopEnvironment(env.get()) ==
base::nix::DESKTOP_ENVIRONMENT_UNITY);
}
#endif
bool IsAltKey(const content::NativeWebKeyboardEvent& event) {
#if defined(USE_X11)
// 164 and 165 represent VK_LALT and VK_RALT.
return event.windowsKeyCode == 164 || event.windowsKeyCode == 165;
#else
return event.windowsKeyCode == ui::VKEY_MENU;
#endif
}
bool IsAltModifier(const content::NativeWebKeyboardEvent& event) {
typedef content::NativeWebKeyboardEvent::Modifiers Modifiers;
return (event.modifiers == Modifiers::AltKey) ||
(event.modifiers == (Modifiers::AltKey | Modifiers::IsLeft)) ||
(event.modifiers == (Modifiers::AltKey | Modifiers::IsRight));
}
class NativeWindowClientView : public views::ClientView {
public:
NativeWindowClientView(views::Widget* widget,
@@ -81,13 +108,23 @@ NativeWindowViews::NativeWindowViews(content::WebContents* web_contents,
const mate::Dictionary& options)
: NativeWindow(web_contents, options),
window_(new views::Widget),
menu_bar_(NULL),
web_view_(inspectable_web_contents()->GetView()->GetView()),
menu_bar_autohide_(false),
menu_bar_visible_(false),
menu_bar_alt_pressed_(false),
keyboard_event_handler_(new views::UnhandledKeyboardEventHandler),
use_content_size_(false),
resizable_(true) {
options.Get(switches::kResizable, &resizable_);
options.Get(switches::kTitle, &title_);
options.Get(switches::kAutoHideMenuBar, &menu_bar_autohide_);
if (enable_larger_than_screen_)
// We need to set a default maximum window size here otherwise Windows
// will not allow us to resize the window larger than scree.
// Setting directly to INT_MAX somehow doesn't work, so we just devide
// by 10, which should still be large enough.
maximum_size_.SetSize(INT_MAX / 10, INT_MAX / 10);
int width = 800, height = 600;
options.Get(switches::kWidth, &width);
@@ -123,6 +160,7 @@ NativeWindowViews::NativeWindowViews(content::WebContents* web_contents,
use_content_size_)
bounds = ContentBoundsToWindowBounds(bounds);
window_->UpdateWindowIcon();
window_->CenterWindow(bounds.size());
Layout();
}
@@ -186,6 +224,10 @@ void NativeWindowViews::Restore() {
window_->Restore();
}
bool NativeWindowViews::IsMinimized() {
return window_->IsMinimized();
}
void NativeWindowViews::SetFullscreen(bool fullscreen) {
window_->SetFullscreen(fullscreen);
}
@@ -199,6 +241,11 @@ void NativeWindowViews::SetSize(const gfx::Size& size) {
}
gfx::Size NativeWindowViews::GetSize() {
#if defined(OS_WIN)
if (IsMinimized())
return window_->GetRestoredBounds().size();
#endif
return window_->GetWindowBoundsInScreen().size();
}
@@ -219,7 +266,7 @@ gfx::Size NativeWindowViews::GetContentSize() {
gfx::Size content_size =
window_->non_client_view()->frame_view()->GetBoundsForClientView().size();
if (menu_bar_)
if (menu_bar_ && menu_bar_visible_)
content_size.set_height(content_size.height() - kMenuBarHeight);
return content_size;
}
@@ -258,6 +305,21 @@ gfx::Size NativeWindowViews::GetMaximumSize() {
void NativeWindowViews::SetResizable(bool resizable) {
resizable_ = resizable;
#if defined(OS_WIN)
if (has_frame_) {
// WS_MAXIMIZEBOX => Maximize button
// WS_MINIMIZEBOX => Minimize button
// WS_THICKFRAME => Resize handle
DWORD style = ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE);
if (resizable)
style |= WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME;
else
style = (style & ~(WS_MAXIMIZEBOX | WS_THICKFRAME)) | WS_MINIMIZEBOX;
::SetWindowLong(GetAcceleratedWidget(), GWL_STYLE, style);
}
#endif
// FIXME Implement me for X11.
}
@@ -282,6 +344,11 @@ void NativeWindowViews::SetPosition(const gfx::Point& position) {
}
gfx::Point NativeWindowViews::GetPosition() {
#if defined(OS_WIN)
if (IsMinimized())
return window_->GetRestoredBounds().origin();
#endif
return window_->GetWindowBoundsInScreen().origin();
}
@@ -324,11 +391,11 @@ void NativeWindowViews::SetMenu(ui::MenuModel* menu_model) {
RegisterAccelerators(menu_model);
#if defined(USE_X11)
if (!global_menu_bar_)
if (!global_menu_bar_ && ShouldUseGlobalMenuBar())
global_menu_bar_.reset(new GlobalMenuBarX11(this));
// Use global application menu bar when possible.
if (global_menu_bar_->IsServerStarted()) {
if (global_menu_bar_ && global_menu_bar_->IsServerStarted()) {
global_menu_bar_->SetMenu(menu_model);
return;
}
@@ -340,11 +407,14 @@ void NativeWindowViews::SetMenu(ui::MenuModel* menu_model) {
if (!menu_bar_) {
gfx::Size content_size = GetContentSize();
menu_bar_ = new MenuBar;
AddChildViewAt(menu_bar_, 0);
menu_bar_.reset(new MenuBar);
menu_bar_->set_owned_by_client();
if (use_content_size_)
SetContentSize(content_size);
if (!menu_bar_autohide_) {
SetMenuBarVisibility(true);
if (use_content_size_)
SetContentSize(content_size);
}
}
menu_bar_->SetMenu(menu_model);
@@ -391,6 +461,15 @@ void NativeWindowViews::OnWidgetActivationChanged(
NotifyWindowFocus();
else
NotifyWindowBlur();
if (active && GetWebContents() && !IsDevToolsOpened())
GetWebContents()->Focus();
// Hide menu bar when window is blured.
if (!active && menu_bar_autohide_ && menu_bar_visible_) {
SetMenuBarVisibility(false);
Layout();
}
}
void NativeWindowViews::DeleteDelegate() {
@@ -418,10 +497,7 @@ bool NativeWindowViews::ShouldHandleSystemCommands() const {
}
gfx::ImageSkia NativeWindowViews::GetWindowAppIcon() {
if (icon_)
return *(icon_->ToImageSkia());
else
return gfx::ImageSkia();
return icon_;
}
gfx::ImageSkia NativeWindowViews::GetWindowIcon() {
@@ -465,9 +541,11 @@ views::ClientView* NativeWindowViews::CreateClientView(views::Widget* widget) {
views::NonClientFrameView* NativeWindowViews::CreateNonClientFrameView(
views::Widget* widget) {
#if defined(OS_WIN)
WinFrameView* frame_view = new WinFrameView;
frame_view->Init(this, widget);
return frame_view;
if (ui::win::IsAeroGlassEnabled()) {
WinFrameView* frame_view = new WinFrameView;
frame_view->Init(this, widget);
return frame_view;
}
#elif defined(OS_LINUX)
if (has_frame_) {
return new views::NativeFrameView(widget);
@@ -476,15 +554,62 @@ views::NonClientFrameView* NativeWindowViews::CreateNonClientFrameView(
frame_view->Init(this, widget);
return frame_view;
}
#else
return NULL;
#endif
return NULL;
}
void NativeWindowViews::HandleMouseDown() {
// Hide menu bar when web view is clicked.
if (menu_bar_autohide_ && menu_bar_visible_) {
SetMenuBarVisibility(false);
Layout();
}
}
void NativeWindowViews::HandleKeyboardEvent(
content::WebContents*,
const content::NativeWebKeyboardEvent& event) {
keyboard_event_handler_->HandleKeyboardEvent(event, GetFocusManager());
if (!menu_bar_)
return;
// Show accelerator when "Alt" is pressed.
if (menu_bar_visible_ && IsAltKey(event))
menu_bar_->SetAcceleratorVisibility(
event.type == blink::WebInputEvent::RawKeyDown);
// Show the submenu when "Alt+Key" is pressed.
if (event.type == blink::WebInputEvent::RawKeyDown && !IsAltKey(event) &&
IsAltModifier(event)) {
if (!menu_bar_visible_ &&
(menu_bar_->GetAcceleratorIndex(event.windowsKeyCode) != -1)) {
SetMenuBarVisibility(true);
Layout();
}
menu_bar_->ActivateAccelerator(event.windowsKeyCode);
return;
}
if (!menu_bar_autohide_)
return;
// Toggle the menu bar only when a single Alt is released.
if (event.type == blink::WebInputEvent::RawKeyDown && IsAltKey(event) &&
IsAltModifier(event)) {
// When a single Alt is pressed:
menu_bar_alt_pressed_ = true;
} else if (event.type == blink::WebInputEvent::KeyUp && IsAltKey(event) &&
event.modifiers == 0 && menu_bar_alt_pressed_) {
// When a single Alt is released right after a Alt is pressed:
menu_bar_alt_pressed_ = false;
SetMenuBarVisibility(!menu_bar_visible_);
Layout();
} else {
// When any other keys except single Alt have been pressed/released:
menu_bar_alt_pressed_ = false;
}
}
bool NativeWindowViews::AcceleratorPressed(const ui::Accelerator& accelerator) {
@@ -513,11 +638,29 @@ gfx::Rect NativeWindowViews::ContentBoundsToWindowBounds(
const gfx::Rect& bounds) {
gfx::Rect window_bounds =
window_->non_client_view()->GetWindowBoundsForClientBounds(bounds);
if (menu_bar_)
if (menu_bar_ && menu_bar_visible_)
window_bounds.set_height(window_bounds.height() + kMenuBarHeight);
return window_bounds;
}
void NativeWindowViews::SetMenuBarVisibility(bool visible) {
if (!menu_bar_)
return;
// Always show the accelerator when the auto-hide menu bar shows.
if (menu_bar_autohide_)
menu_bar_->SetAcceleratorVisibility(visible);
menu_bar_visible_ = visible;
if (visible) {
DCHECK_EQ(child_count(), 1);
AddChildView(menu_bar_.get());
} else {
DCHECK_EQ(child_count(), 2);
RemoveChildView(menu_bar_.get());
}
}
// static
NativeWindow* NativeWindow::Create(content::WebContents* web_contents,
const mate::Dictionary& options) {

View File

@@ -16,7 +16,6 @@
namespace views {
class UnhandledKeyboardEventHandler;
class Widget;
}
namespace atom {
@@ -46,6 +45,7 @@ class NativeWindowViews : public NativeWindow,
virtual bool IsMaximized() OVERRIDE;
virtual void Minimize() OVERRIDE;
virtual void Restore() OVERRIDE;
virtual bool IsMinimized() OVERRIDE;
virtual void SetFullscreen(bool fullscreen) OVERRIDE;
virtual bool IsFullscreen() OVERRIDE;
virtual void SetSize(const gfx::Size& size) OVERRIDE;
@@ -106,6 +106,7 @@ class NativeWindowViews : public NativeWindow,
views::Widget* widget) OVERRIDE;
// content::WebContentsDelegate:
virtual void HandleMouseDown() OVERRIDE;
virtual void HandleKeyboardEvent(
content::WebContents*,
const content::NativeWebKeyboardEvent& event) OVERRIDE;
@@ -120,10 +121,17 @@ class NativeWindowViews : public NativeWindow,
// in client area we need to substract/add menu bar's height in convertions.
gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& content_bounds);
// Show/Hide the menu bar.
void SetMenuBarVisibility(bool visible);
scoped_ptr<views::Widget> window_;
MenuBar* menu_bar_;
views::View* web_view_; // Managed by inspectable_web_contents_.
scoped_ptr<MenuBar> menu_bar_;
bool menu_bar_autohide_;
bool menu_bar_visible_;
bool menu_bar_alt_pressed_;
#if defined(USE_X11)
scoped_ptr<GlobalMenuBarX11> global_menu_bar_;
#endif

View File

@@ -1,186 +0,0 @@
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/net/atom_url_request_context_getter.h"
#include <algorithm>
#include "atom/browser/net/atom_url_request_job_factory.h"
#include "base/strings/string_util.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/worker_pool.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cookie_store_factory.h"
#include "content/public/common/url_constants.h"
#include "net/cert/cert_verifier.h"
#include "net/cookies/cookie_monster.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_cache.h"
#include "net/http/http_server_properties_impl.h"
#include "net/proxy/dhcp_proxy_script_fetcher_factory.h"
#include "net/proxy/proxy_config_service.h"
#include "net/proxy/proxy_script_fetcher_impl.h"
#include "net/proxy/proxy_service.h"
#include "net/proxy/proxy_service_v8.h"
#include "net/ssl/default_server_bound_cert_store.h"
#include "net/ssl/server_bound_cert_service.h"
#include "net/ssl/ssl_config_service_defaults.h"
#include "net/url_request/data_protocol_handler.h"
#include "net/url_request/file_protocol_handler.h"
#include "net/url_request/static_http_user_agent_settings.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_storage.h"
#include "vendor/brightray/browser/network_delegate.h"
#include "webkit/browser/quota/special_storage_policy.h"
namespace atom {
using content::BrowserThread;
AtomURLRequestContextGetter::AtomURLRequestContextGetter(
const base::FilePath& base_path,
base::MessageLoop* io_loop,
base::MessageLoop* file_loop,
base::Callback<scoped_ptr<brightray::NetworkDelegate>(void)> factory,
content::ProtocolHandlerMap* protocol_handlers)
: base_path_(base_path),
io_loop_(io_loop),
file_loop_(file_loop),
job_factory_(NULL),
network_delegate_factory_(factory) {
// Must first be created on the UI thread.
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
std::swap(protocol_handlers_, *protocol_handlers);
// We must create the proxy config service on the UI loop on Linux because it
// must synchronously run on the glib message loop. This will be passed to
// the URLRequestContextStorage on the IO thread in GetURLRequestContext().
proxy_config_service_.reset(
net::ProxyService::CreateSystemProxyConfigService(
io_loop_->message_loop_proxy(),
file_loop_));
}
AtomURLRequestContextGetter::~AtomURLRequestContextGetter() {
}
net::URLRequestContext* AtomURLRequestContextGetter::GetURLRequestContext() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
base::AutoLock auto_lock(lock_);
if (!url_request_context_.get()) {
url_request_context_.reset(new net::URLRequestContext());
network_delegate_ = network_delegate_factory_.Run().Pass();
url_request_context_->set_network_delegate(network_delegate_.get());
storage_.reset(
new net::URLRequestContextStorage(url_request_context_.get()));
auto cookie_config = content::CookieStoreConfig(
base_path_.Append(FILE_PATH_LITERAL("Cookies")),
content::CookieStoreConfig::EPHEMERAL_SESSION_COOKIES,
nullptr,
nullptr);
storage_->set_cookie_store(content::CreateCookieStore(cookie_config));
storage_->set_server_bound_cert_service(new net::ServerBoundCertService(
new net::DefaultServerBoundCertStore(NULL),
base::WorkerPool::GetTaskRunner(true)));
storage_->set_http_user_agent_settings(
new net::StaticHttpUserAgentSettings(
"en-us,en", base::EmptyString()));
scoped_ptr<net::HostResolver> host_resolver(
net::HostResolver::CreateDefaultResolver(NULL));
net::DhcpProxyScriptFetcherFactory dhcp_factory;
storage_->set_cert_verifier(net::CertVerifier::CreateDefault());
storage_->set_transport_security_state(new net::TransportSecurityState);
storage_->set_proxy_service(
net::CreateProxyServiceUsingV8ProxyResolver(
proxy_config_service_.release(),
new net::ProxyScriptFetcherImpl(url_request_context_.get()),
dhcp_factory.Create(url_request_context_.get()),
host_resolver.get(),
NULL,
url_request_context_->network_delegate()));
storage_->set_ssl_config_service(new net::SSLConfigServiceDefaults);
storage_->set_http_auth_handler_factory(
net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get()));
scoped_ptr<net::HttpServerProperties> server_properties(
new net::HttpServerPropertiesImpl);
storage_->set_http_server_properties(server_properties.Pass());
base::FilePath cache_path = base_path_.Append(FILE_PATH_LITERAL("Cache"));
net::HttpCache::DefaultBackend* main_backend =
new net::HttpCache::DefaultBackend(
net::DISK_CACHE,
net::CACHE_BACKEND_DEFAULT,
cache_path,
0,
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE));
net::HttpNetworkSession::Params network_session_params;
network_session_params.cert_verifier =
url_request_context_->cert_verifier();
network_session_params.transport_security_state =
url_request_context_->transport_security_state();
network_session_params.server_bound_cert_service =
url_request_context_->server_bound_cert_service();
network_session_params.proxy_service =
url_request_context_->proxy_service();
network_session_params.ssl_config_service =
url_request_context_->ssl_config_service();
network_session_params.http_auth_handler_factory =
url_request_context_->http_auth_handler_factory();
network_session_params.network_delegate =
url_request_context_->network_delegate();
network_session_params.http_server_properties =
url_request_context_->http_server_properties();
network_session_params.ignore_certificate_errors = false;
// Give |storage_| ownership at the end in case it's |mapped_host_resolver|.
storage_->set_host_resolver(host_resolver.Pass());
network_session_params.host_resolver =
url_request_context_->host_resolver();
net::HttpCache* main_cache = new net::HttpCache(
network_session_params, main_backend);
storage_->set_http_transaction_factory(main_cache);
DCHECK(!job_factory_);
job_factory_ = new AtomURLRequestJobFactory;
for (content::ProtocolHandlerMap::iterator it = protocol_handlers_.begin();
it != protocol_handlers_.end();
++it) {
bool set_protocol = job_factory_->SetProtocolHandler(
it->first,
it->second.release());
DCHECK(set_protocol);
}
protocol_handlers_.clear();
scoped_ptr<net::FileProtocolHandler> file_protocol_handler(
new net::FileProtocolHandler(
content::BrowserThread::GetBlockingPool()->
GetTaskRunnerWithShutdownBehavior(
base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)));
job_factory_->SetProtocolHandler(content::kDataScheme,
new net::DataProtocolHandler);
job_factory_->SetProtocolHandler(content::kFileScheme,
file_protocol_handler.release());
storage_->set_job_factory(job_factory_);
}
return url_request_context_.get();
}
scoped_refptr<base::SingleThreadTaskRunner>
AtomURLRequestContextGetter::GetNetworkTaskRunner() const {
return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
}
net::HostResolver* AtomURLRequestContextGetter::host_resolver() {
return url_request_context_->host_resolver();
}
} // namespace atom

View File

@@ -1,76 +0,0 @@
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_NET_ATOM_URL_REQUEST_CONTEXT_GETTER_H_
#define ATOM_BROWSER_NET_ATOM_URL_REQUEST_CONTEXT_GETTER_H_
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
#include "content/public/browser/content_browser_client.h"
#include "net/url_request/url_request_context_getter.h"
namespace base {
class MessageLoop;
}
namespace brightray {
class NetworkDelegate;
}
namespace net {
class HostResolver;
class ProxyConfigService;
class URLRequestContextStorage;
}
namespace atom {
class AtomURLRequestJobFactory;
class AtomURLRequestContextGetter : public net::URLRequestContextGetter {
public:
AtomURLRequestContextGetter(
const base::FilePath& base_path,
base::MessageLoop* io_loop,
base::MessageLoop* file_loop,
base::Callback<scoped_ptr<brightray::NetworkDelegate>(void)>,
content::ProtocolHandlerMap* protocol_handlers);
// net::URLRequestContextGetter implementations:
virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE;
virtual scoped_refptr<base::SingleThreadTaskRunner>
GetNetworkTaskRunner() const OVERRIDE;
net::HostResolver* host_resolver();
net::URLRequestContextStorage* storage() const { return storage_.get(); }
AtomURLRequestJobFactory* job_factory() const { return job_factory_; }
protected:
virtual ~AtomURLRequestContextGetter();
private:
base::FilePath base_path_;
base::MessageLoop* io_loop_;
base::MessageLoop* file_loop_;
AtomURLRequestJobFactory* job_factory_;
base::Callback<scoped_ptr<brightray::NetworkDelegate>(void)>
network_delegate_factory_;
base::Lock lock_;
scoped_ptr<net::ProxyConfigService> proxy_config_service_;
scoped_ptr<brightray::NetworkDelegate> network_delegate_;
scoped_ptr<net::URLRequestContextStorage> storage_;
scoped_ptr<net::URLRequestContext> url_request_context_;
content::ProtocolHandlerMap protocol_handlers_;
DISALLOW_COPY_AND_ASSIGN(AtomURLRequestContextGetter);
};
} // namespace atom
#endif // ATOM_BROWSER_NET_ATOM_URL_REQUEST_CONTEXT_GETTER_H_

View File

@@ -17,7 +17,7 @@
<key>CFBundleIconFile</key>
<string>atom.icns</string>
<key>CFBundleVersion</key>
<string>0.14.2</string>
<string>0.15.8</string>
<key>LSMinimumSystemVersion</key>
<string>10.8.0</string>
<key>NSMainNibFile</key>

View File

@@ -50,8 +50,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,14,2,0
PRODUCTVERSION 0,14,2,0
FILEVERSION 0,15,8,0
PRODUCTVERSION 0,15,8,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -68,12 +68,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "GitHub, Inc."
VALUE "FileDescription", "Atom-Shell"
VALUE "FileVersion", "0.14.2"
VALUE "FileVersion", "0.15.8"
VALUE "InternalName", "atom.exe"
VALUE "LegalCopyright", "Copyright (C) 2013 GitHub, Inc. All rights reserved."
VALUE "OriginalFilename", "atom.exe"
VALUE "ProductName", "Atom-Shell"
VALUE "ProductVersion", "0.14.2"
VALUE "ProductVersion", "0.15.8"
END
END
BLOCK "VarFileInfo"

View File

@@ -87,7 +87,7 @@ ui::KeyboardCode KeyboardCodeFromCharCode(char c, bool* shifted) {
bool StringToAccelerator(const std::string& description,
ui::Accelerator* accelerator) {
if (!IsStringASCII(description)) {
if (!base::IsStringASCII(description)) {
LOG(ERROR) << "The accelerator string can only contain ASCII characters";
return false;
}

View File

@@ -6,6 +6,7 @@
#define ATOM_BROWSER_UI_FILE_DIALOG_H_
#include <string>
#include <utility>
#include <vector>
#include "base/callback_forward.h"
@@ -17,11 +18,15 @@ class NativeWindow;
namespace file_dialog {
// <description, extensions>
typedef std::pair<std::string, std::vector<std::string> > Filter;
typedef std::vector<Filter> Filters;
enum FileDialogProperty {
FILE_DIALOG_OPEN_FILE = 1,
FILE_DIALOG_OPEN_DIRECTORY = 2,
FILE_DIALOG_MULTI_SELECTIONS = 4,
FILE_DIALOG_CREATE_DIRECTORY = 8,
FILE_DIALOG_OPEN_FILE = 1 << 0,
FILE_DIALOG_OPEN_DIRECTORY = 1 << 1,
FILE_DIALOG_MULTI_SELECTIONS = 1 << 2,
FILE_DIALOG_CREATE_DIRECTORY = 1 << 3,
};
typedef base::Callback<void(
@@ -33,23 +38,27 @@ typedef base::Callback<void(
bool ShowOpenDialog(atom::NativeWindow* parent_window,
const std::string& title,
const base::FilePath& default_path,
const Filters& filters,
int properties,
std::vector<base::FilePath>* paths);
void ShowOpenDialog(atom::NativeWindow* parent_window,
const std::string& title,
const base::FilePath& default_path,
const Filters& filters,
int properties,
const OpenDialogCallback& callback);
bool ShowSaveDialog(atom::NativeWindow* parent_window,
const std::string& title,
const base::FilePath& default_path,
const Filters& filters,
base::FilePath* path);
void ShowSaveDialog(atom::NativeWindow* parent_window,
const std::string& title,
const base::FilePath& default_path,
const Filters& filters,
const SaveDialogCallback& callback);
} // namespace file_dialog

View File

@@ -17,6 +17,7 @@
#include "atom/browser/native_window.h"
#include "base/callback.h"
#include "base/file_util.h"
#include "base/strings/string_util.h"
#include "chrome/browser/ui/libgtk2ui/gtk2_signal.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
@@ -45,12 +46,24 @@ void SetGtkTransientForAura(GtkWidget* dialog, aura::Window* parent) {
g_object_set_data(G_OBJECT(dialog), kAuraTransientParent, parent);
}
// Makes sure that .jpg also shows .JPG.
gboolean FileFilterCaseInsensitive(const GtkFileFilterInfo* file_info,
std::string* file_extension) {
return EndsWith(file_info->filename, *file_extension, false);
}
// Deletes |data| when gtk_file_filter_add_custom() is done with it.
void OnFileFilterDataDestroyed(std::string* file_extension) {
delete file_extension;
}
class FileChooserDialog {
public:
FileChooserDialog(GtkFileChooserAction action,
atom::NativeWindow* parent_window,
const std::string& title,
const base::FilePath& default_path)
const base::FilePath& default_path,
const Filters& filters)
: dialog_scope_(new atom::NativeWindow::DialogScope(parent_window)) {
const char* confirm_text = GTK_STOCK_OK;
if (action == GTK_FILE_CHOOSER_ACTION_SAVE)
@@ -86,6 +99,9 @@ class FileChooserDialog {
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog_),
default_path.value().c_str());
}
if (!filters.empty())
AddFilters(filters);
}
virtual ~FileChooserDialog() {
@@ -135,6 +151,8 @@ class FileChooserDialog {
GtkWidget* dialog() const { return dialog_; }
private:
void AddFilters(const Filters& filters);
GtkWidget* dialog_;
SaveDialogCallback save_callback_;
@@ -162,17 +180,40 @@ void FileChooserDialog::OnFileDialogResponse(GtkWidget* widget, int response) {
delete this;
}
void FileChooserDialog::AddFilters(const Filters& filters) {
for (size_t i = 0; i < filters.size(); ++i) {
const Filter& filter = filters[i];
GtkFileFilter* gtk_filter = gtk_file_filter_new();
for (size_t j = 0; j < filter.second.size(); ++j) {
scoped_ptr<std::string> file_extension(
new std::string("." + filter.second[j]));
gtk_file_filter_add_custom(
gtk_filter,
GTK_FILE_FILTER_FILENAME,
reinterpret_cast<GtkFileFilterFunc>(FileFilterCaseInsensitive),
file_extension.release(),
reinterpret_cast<GDestroyNotify>(OnFileFilterDataDestroyed));
}
gtk_file_filter_set_name(gtk_filter, filter.first.c_str());
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog_), gtk_filter);
}
}
} // namespace
bool ShowOpenDialog(atom::NativeWindow* parent_window,
const std::string& title,
const base::FilePath& default_path,
const Filters& filters,
int properties,
std::vector<base::FilePath>* paths) {
GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN;
if (properties & FILE_DIALOG_OPEN_DIRECTORY)
action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
FileChooserDialog open_dialog(action, parent_window, title, default_path);
FileChooserDialog open_dialog(action, parent_window, title, default_path,
filters);
if (properties & FILE_DIALOG_MULTI_SELECTIONS)
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(open_dialog.dialog()),
TRUE);
@@ -190,13 +231,14 @@ bool ShowOpenDialog(atom::NativeWindow* parent_window,
void ShowOpenDialog(atom::NativeWindow* parent_window,
const std::string& title,
const base::FilePath& default_path,
const Filters& filters,
int properties,
const OpenDialogCallback& callback) {
GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN;
if (properties & FILE_DIALOG_OPEN_DIRECTORY)
action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
FileChooserDialog* open_dialog = new FileChooserDialog(
action, parent_window, title, default_path);
action, parent_window, title, default_path, filters);
if (properties & FILE_DIALOG_MULTI_SELECTIONS)
gtk_file_chooser_set_select_multiple(
GTK_FILE_CHOOSER(open_dialog->dialog()), TRUE);
@@ -207,9 +249,10 @@ void ShowOpenDialog(atom::NativeWindow* parent_window,
bool ShowSaveDialog(atom::NativeWindow* parent_window,
const std::string& title,
const base::FilePath& default_path,
const Filters& filters,
base::FilePath* path) {
FileChooserDialog save_dialog(
GTK_FILE_CHOOSER_ACTION_SAVE, parent_window, title, default_path);
FileChooserDialog save_dialog(GTK_FILE_CHOOSER_ACTION_SAVE, parent_window,
title, default_path, filters);
gtk_widget_show_all(save_dialog.dialog());
int response = gtk_dialog_run(GTK_DIALOG(save_dialog.dialog()));
if (response == GTK_RESPONSE_ACCEPT) {
@@ -223,9 +266,11 @@ bool ShowSaveDialog(atom::NativeWindow* parent_window,
void ShowSaveDialog(atom::NativeWindow* parent_window,
const std::string& title,
const base::FilePath& default_path,
const Filters& filters,
const SaveDialogCallback& callback) {
FileChooserDialog* save_dialog = new FileChooserDialog(
GTK_FILE_CHOOSER_ACTION_SAVE, parent_window, title, default_path);
GTK_FILE_CHOOSER_ACTION_SAVE, parent_window, title, default_path,
filters);
save_dialog->RunSaveAsynchronous(callback);
}

View File

@@ -9,15 +9,45 @@
#include "atom/browser/native_window.h"
#include "base/file_util.h"
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/strings/sys_string_conversions.h"
namespace file_dialog {
namespace {
CFStringRef CreateUTIFromExtension(const std::string& ext) {
base::ScopedCFTypeRef<CFStringRef> ext_cf(base::SysUTF8ToCFStringRef(ext));
return UTTypeCreatePreferredIdentifierForTag(
kUTTagClassFilenameExtension, ext_cf.get(), NULL);
}
void SetAllowedFileTypes(NSSavePanel* dialog, const Filters& filters) {
NSMutableSet* file_type_set = [NSMutableSet set];
for (size_t i = 0; i < filters.size(); ++i) {
const Filter& filter = filters[i];
for (size_t j = 0; j < filter.second.size(); ++j) {
base::ScopedCFTypeRef<CFStringRef> uti(
CreateUTIFromExtension(filter.second[j]));
[file_type_set addObject:base::mac::CFToNSCast(uti.get())];
// Always allow the extension itself, in case the UTI doesn't map
// back to the original extension correctly. This occurs with dynamic
// UTIs on 10.7 and 10.8.
// See http://crbug.com/148840, http://openradar.me/12316273
base::ScopedCFTypeRef<CFStringRef> ext_cf(
base::SysUTF8ToCFStringRef(filter.second[j]));
[file_type_set addObject:base::mac::CFToNSCast(ext_cf.get())];
}
}
[dialog setAllowedFileTypes:[file_type_set allObjects]];
}
void SetupDialog(NSSavePanel* dialog,
const std::string& title,
const base::FilePath& default_path) {
const base::FilePath& default_path,
const Filters& filters) {
if (!title.empty())
[dialog setTitle:base::SysUTF8ToNSString(title)];
@@ -39,7 +69,10 @@ void SetupDialog(NSSavePanel* dialog,
[dialog setNameFieldStringValue:default_filename];
[dialog setCanSelectHiddenExtension:YES];
[dialog setAllowsOtherFileTypes:YES];
if (filters.empty())
[dialog setAllowsOtherFileTypes:YES];
else
SetAllowedFileTypes(dialog, filters);
}
void SetupDialogForProperties(NSOpenPanel* dialog, int properties) {
@@ -55,7 +88,7 @@ void SetupDialogForProperties(NSOpenPanel* dialog, int properties) {
// Run modal dialog with parent window and return user's choice.
int RunModalDialog(NSSavePanel* dialog, atom::NativeWindow* parent_window) {
__block int chosen = NSFileHandlingPanelCancelButton;
if (parent_window == NULL) {
if (!parent_window || !parent_window->GetNativeWindow()) {
chosen = [dialog runModal];
} else {
NSWindow* window = parent_window->GetNativeWindow();
@@ -83,12 +116,13 @@ void ReadDialogPaths(NSOpenPanel* dialog, std::vector<base::FilePath>* paths) {
bool ShowOpenDialog(atom::NativeWindow* parent_window,
const std::string& title,
const base::FilePath& default_path,
const Filters& filters,
int properties,
std::vector<base::FilePath>* paths) {
DCHECK(paths);
NSOpenPanel* dialog = [NSOpenPanel openPanel];
SetupDialog(dialog, title, default_path);
SetupDialog(dialog, title, default_path, filters);
SetupDialogForProperties(dialog, properties);
int chosen = RunModalDialog(dialog, parent_window);
@@ -102,11 +136,12 @@ bool ShowOpenDialog(atom::NativeWindow* parent_window,
void ShowOpenDialog(atom::NativeWindow* parent_window,
const std::string& title,
const base::FilePath& default_path,
const Filters& filters,
int properties,
const OpenDialogCallback& c) {
NSOpenPanel* dialog = [NSOpenPanel openPanel];
SetupDialog(dialog, title, default_path);
SetupDialog(dialog, title, default_path, filters);
SetupDialogForProperties(dialog, properties);
// Duplicate the callback object here since c is a reference and gcd would
@@ -129,11 +164,12 @@ void ShowOpenDialog(atom::NativeWindow* parent_window,
bool ShowSaveDialog(atom::NativeWindow* parent_window,
const std::string& title,
const base::FilePath& default_path,
const Filters& filters,
base::FilePath* path) {
DCHECK(path);
NSSavePanel* dialog = [NSSavePanel savePanel];
SetupDialog(dialog, title, default_path);
SetupDialog(dialog, title, default_path, filters);
int chosen = RunModalDialog(dialog, parent_window);
if (chosen == NSFileHandlingPanelCancelButton || ![[dialog URL] isFileURL])
@@ -146,10 +182,11 @@ bool ShowSaveDialog(atom::NativeWindow* parent_window,
void ShowSaveDialog(atom::NativeWindow* parent_window,
const std::string& title,
const base::FilePath& default_path,
const Filters& filters,
const SaveDialogCallback& c) {
NSSavePanel* dialog = [NSSavePanel savePanel];
SetupDialog(dialog, title, default_path);
SetupDialog(dialog, title, default_path, filters);
__block SaveDialogCallback callback = c;

View File

@@ -30,103 +30,30 @@ bool IsDirectory(const base::FilePath& path) {
file_info.is_directory : path.EndsWithSeparator();
}
// Get the file type description from the registry. This will be "Text Document"
// for .txt files, "JPEG Image" for .jpg files, etc. If the registry doesn't
// have an entry for the file type, we return false, true if the description was
// found. 'file_ext' must be in form ".txt".
static bool GetRegistryDescriptionFromExtension(const std::wstring& file_ext,
std::wstring* reg_description) {
DCHECK(reg_description);
base::win::RegKey reg_ext(HKEY_CLASSES_ROOT, file_ext.c_str(), KEY_READ);
std::wstring reg_app;
if (reg_ext.ReadValue(NULL, &reg_app) == ERROR_SUCCESS && !reg_app.empty()) {
base::win::RegKey reg_link(HKEY_CLASSES_ROOT, reg_app.c_str(), KEY_READ);
if (reg_link.ReadValue(NULL, reg_description) == ERROR_SUCCESS)
return true;
}
return false;
}
// Set up a filter for a Save/Open dialog, which will consist of |file_ext| file
// extensions (internally separated by semicolons), |ext_desc| as the text
// descriptions of the |file_ext| types (optional), and (optionally) the default
// 'All Files' view. The purpose of the filter is to show only files of a
// particular type in a Windows Save/Open dialog box. The resulting filter is
// returned. The filters created here are:
// 1. only files that have 'file_ext' as their extension
// 2. all files (only added if 'include_all_files' is true)
// Example:
// file_ext: { "*.txt", "*.htm;*.html" }
// ext_desc: { "Text Document" }
// returned: "Text Document\0*.txt\0HTML Document\0*.htm;*.html\0"
// "All Files\0*.*\0\0" (in one big string)
// If a description is not provided for a file extension, it will be retrieved
// from the registry. If the file extension does not exist in the registry, it
// will be omitted from the filter, as it is likely a bogus extension.
void FormatFilterForExtensions(
std::vector<std::wstring>* file_ext,
std::vector<std::wstring>* ext_desc,
bool include_all_files,
std::vector<COMDLG_FILTERSPEC>* file_types) {
DCHECK(file_ext->size() >= ext_desc->size());
if (file_ext->empty())
include_all_files = true;
for (size_t i = 0; i < file_ext->size(); ++i) {
std::wstring ext = (*file_ext)[i];
std::wstring desc;
if (i < ext_desc->size())
desc = (*ext_desc)[i];
if (ext.empty()) {
// Force something reasonable to appear in the dialog box if there is no
// extension provided.
include_all_files = true;
continue;
}
if (desc.empty()) {
DCHECK(ext.find(L'.') != std::wstring::npos);
std::wstring first_extension = ext.substr(ext.find(L'.'));
size_t first_separator_index = first_extension.find(L';');
if (first_separator_index != std::wstring::npos)
first_extension = first_extension.substr(0, first_separator_index);
// Find the extension name without the preceeding '.' character.
std::wstring ext_name = first_extension;
size_t ext_index = ext_name.find_first_not_of(L'.');
if (ext_index != std::wstring::npos)
ext_name = ext_name.substr(ext_index);
if (!GetRegistryDescriptionFromExtension(first_extension, &desc)) {
// The extension doesn't exist in the registry. Create a description
// based on the unknown extension type (i.e. if the extension is .qqq,
// the we create a description "QQQ File (.qqq)").
include_all_files = true;
// TODO(zcbenz): should be localized.
desc = base::i18n::ToUpper(base::WideToUTF16(ext_name)) + L" File";
}
desc += L" (*." + ext_name + L")";
// Store the description.
ext_desc->push_back(desc);
}
COMDLG_FILTERSPEC spec = { (*ext_desc)[i].c_str(), (*file_ext)[i].c_str() };
file_types->push_back(spec);
void ConvertFilters(const Filters& filters,
std::vector<std::wstring>* buffer,
std::vector<COMDLG_FILTERSPEC>* filterspec) {
if (filters.empty()) {
COMDLG_FILTERSPEC spec = { L"All Files (*.*)", L"*.*" };
filterspec->push_back(spec);
return;
}
if (include_all_files) {
// TODO(zcbenz): Should be localized.
ext_desc->push_back(L"All Files (*.*)");
file_ext->push_back(L"*.*");
buffer->reserve(filters.size() * 2);
for (size_t i = 0; i < filters.size(); ++i) {
const Filter& filter = filters[i];
COMDLG_FILTERSPEC spec = {
(*ext_desc)[ext_desc->size() - 1].c_str(),
(*file_ext)[file_ext->size() - 1].c_str(),
};
file_types->push_back(spec);
COMDLG_FILTERSPEC spec;
buffer->push_back(base::UTF8ToWide(filter.first));
spec.pszName = buffer->back().c_str();
std::vector<std::string> extensions(filter.second);
for (size_t j = 0; j < extensions.size(); ++j)
extensions[j].insert(0, "*.");
buffer->push_back(base::UTF8ToWide(JoinString(extensions, ";")));
spec.pszSpec = buffer->back().c_str();
filterspec->push_back(spec);
}
}
@@ -135,26 +62,18 @@ void FormatFilterForExtensions(
template <typename T>
class FileDialog {
public:
FileDialog(const base::FilePath& default_path,
const std::string title,
int options,
const std::vector<std::wstring>& file_ext,
const std::vector<std::wstring>& desc_ext)
: file_ext_(file_ext),
desc_ext_(desc_ext) {
std::vector<COMDLG_FILTERSPEC> filters;
FormatFilterForExtensions(&file_ext_, &desc_ext_, true, &filters);
FileDialog(const base::FilePath& default_path, const std::string& title,
const Filters& filters, int options) {
std::wstring file_part;
if (!IsDirectory(default_path))
file_part = default_path.BaseName().value();
dialog_.reset(new T(
file_part.c_str(),
options,
NULL,
filters.data(),
filters.size()));
std::vector<std::wstring> buffer;
std::vector<COMDLG_FILTERSPEC> filterspec;
ConvertFilters(filters, &buffer, &filterspec);
dialog_.reset(new T(file_part.c_str(), options, NULL,
filterspec.data(), filterspec.size()));
if (!title.empty())
GetPtr()->SetTitle(base::UTF8ToUTF16(title).c_str());
@@ -174,8 +93,6 @@ class FileDialog {
IFileDialog* GetPtr() const { return dialog_->GetPtr(); }
const std::vector<std::wstring> file_ext() const { return file_ext_; }
private:
// Set up the initial directory for the dialog.
void SetDefaultFolder(const base::FilePath file_path) {
@@ -193,10 +110,6 @@ class FileDialog {
scoped_ptr<T> dialog_;
std::vector<std::wstring> file_ext_;
std::vector<std::wstring> desc_ext_;
std::vector<COMDLG_FILTERSPEC> filters_;
DISALLOW_COPY_AND_ASSIGN(FileDialog);
};
@@ -205,6 +118,7 @@ class FileDialog {
bool ShowOpenDialog(atom::NativeWindow* parent_window,
const std::string& title,
const base::FilePath& default_path,
const Filters& filters,
int properties,
std::vector<base::FilePath>* paths) {
int options = FOS_FORCEFILESYSTEM | FOS_FILEMUSTEXIST;
@@ -214,11 +128,7 @@ bool ShowOpenDialog(atom::NativeWindow* parent_window,
options |= FOS_ALLOWMULTISELECT;
FileDialog<CShellFileOpenDialog> open_dialog(
default_path,
title,
options,
std::vector<std::wstring>(),
std::vector<std::wstring>());
default_path, title, filters, options);
if (!open_dialog.Show(parent_window))
return false;
@@ -255,12 +165,14 @@ bool ShowOpenDialog(atom::NativeWindow* parent_window,
void ShowOpenDialog(atom::NativeWindow* parent_window,
const std::string& title,
const base::FilePath& default_path,
const Filters& filters,
int properties,
const OpenDialogCallback& callback) {
std::vector<base::FilePath> paths;
bool result = ShowOpenDialog(parent_window,
title,
default_path,
filters,
properties,
&paths);
callback.Run(result, paths);
@@ -269,52 +181,51 @@ void ShowOpenDialog(atom::NativeWindow* parent_window,
bool ShowSaveDialog(atom::NativeWindow* parent_window,
const std::string& title,
const base::FilePath& default_path,
const Filters& filters,
base::FilePath* path) {
// TODO(zcbenz): Accept custom filters from caller.
std::vector<std::wstring> file_ext;
std::wstring extension = default_path.Extension();
if (!extension.empty())
file_ext.push_back(extension.insert(0, L"*"));
FileDialog<CShellFileSaveDialog> save_dialog(
default_path,
title,
FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT,
file_ext,
std::vector<std::wstring>());
default_path, title, filters,
FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT);
if (!save_dialog.Show(parent_window))
return false;
wchar_t file_name[MAX_PATH];
HRESULT hr = save_dialog.GetDialog()->GetFilePath(file_name, MAX_PATH);
wchar_t buffer[MAX_PATH];
HRESULT hr = save_dialog.GetDialog()->GetFilePath(buffer, MAX_PATH);
if (FAILED(hr))
return false;
std::string file_name = base::WideToUTF8(std::wstring(buffer));
// Append extension according to selected filter.
UINT filter_index = 1;
save_dialog.GetPtr()->GetFileTypeIndex(&filter_index);
std::wstring selected_filter = save_dialog.file_ext()[filter_index - 1];
if (selected_filter != L"*.*") {
std::wstring result = file_name;
if (!EndsWith(result, selected_filter.substr(1), false)) {
if (result[result.length() - 1] != L'.')
result.push_back(L'.');
result.append(selected_filter.substr(2));
*path = base::FilePath(result);
return true;
if (!filters.empty()) {
UINT filter_index = 1;
save_dialog.GetPtr()->GetFileTypeIndex(&filter_index);
const Filter& filter = filters[filter_index - 1];
bool matched = false;
for (size_t i = 0; i < filter.second.size(); ++i) {
if (EndsWith(file_name, filter.second[i], false)) {
matched = true;
break;;
}
}
if (!matched && !filter.second.empty())
file_name += ("." + filter.second[0]);
}
*path = base::FilePath(file_name);
*path = base::FilePath(base::UTF8ToUTF16(file_name));
return true;
}
void ShowSaveDialog(atom::NativeWindow* parent_window,
const std::string& title,
const base::FilePath& default_path,
const Filters& filters,
const SaveDialogCallback& callback) {
base::FilePath path;
bool result = ShowSaveDialog(parent_window, title, default_path, &path);
bool result = ShowSaveDialog(parent_window, title, default_path, filters,
&path);
callback.Run(result, path);
}

View File

@@ -99,7 +99,7 @@ int ShowMessageBox(NativeWindow* parent_window,
// Use runModal for synchronous alert without parent, since we don't have a
// window to wait for.
if (!parent_window)
if (!parent_window || !parent_window->GetNativeWindow())
return [[alert autorelease] runModal];
int ret_code = -1;

View File

@@ -4,16 +4,21 @@
#include "atom/browser/ui/views/menu_bar.h"
#if defined(USE_X11)
#include "gtk/gtk.h"
#endif
#include "atom/browser/ui/views/menu_delegate.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "atom/browser/ui/views/submenu_button.h"
#include "ui/base/models/menu_model.h"
#include "ui/views/background.h"
#include "ui/views/controls/button/menu_button.h"
#include "ui/views/layout/box_layout.h"
#if defined(OS_WIN)
#include "ui/gfx/color_utils.h"
#elif defined(USE_X11)
#include "chrome/browser/ui/libgtk2ui/owned_widget_gtk2.h"
#include "chrome/browser/ui/libgtk2ui/skia_utils_gtk2.h"
#endif
namespace atom {
@@ -25,24 +30,34 @@ const char kViewClassName[] = "AtomMenuBar";
// Default color of the menu bar.
const SkColor kDefaultColor = SkColorSetARGB(255, 233, 233, 233);
// Filter out the "&" in menu label.
base::string16 FilterMenuButtonLabel(const base::string16& label) {
base::string16 out;
base::RemoveChars(label, base::ASCIIToUTF16("&").c_str(), &out);
return out;
#if defined(USE_X11)
void GetMenuBarColor(SkColor* enabled, SkColor* disabled, SkColor* highlight,
SkColor* hover, SkColor* background) {
libgtk2ui::OwnedWidgetGtk fake_menu_bar;
fake_menu_bar.Own(gtk_menu_bar_new());
GtkStyle* style = gtk_rc_get_style(fake_menu_bar.get());
*enabled = libgtk2ui::GdkColorToSkColor(style->fg[GTK_STATE_NORMAL]);
*disabled = libgtk2ui::GdkColorToSkColor(style->fg[GTK_STATE_INSENSITIVE]);
*highlight = libgtk2ui::GdkColorToSkColor(style->fg[GTK_STATE_SELECTED]);
*hover = libgtk2ui::GdkColorToSkColor(style->fg[GTK_STATE_PRELIGHT]);
*background = libgtk2ui::GdkColorToSkColor(style->bg[GTK_STATE_NORMAL]);
}
#endif
} // namespace
MenuBar::MenuBar()
: menu_model_(NULL) {
: background_color_(kDefaultColor),
menu_model_(NULL) {
#if defined(OS_WIN)
SkColor background_color = color_utils::GetSysSkColor(COLOR_MENUBAR);
#else
SkColor background_color = kDefaultColor;
background_color_ = color_utils::GetSysSkColor(COLOR_MENUBAR);
#elif defined(USE_X11)
GetMenuBarColor(&enabled_color_, &disabled_color_, &highlight_color_,
&hover_color_, &background_color_);
#endif
set_background(views::Background::CreateSolidBackground(background_color));
set_background(views::Background::CreateSolidBackground(background_color_));
SetLayoutManager(new views::BoxLayout(
views::BoxLayout::kHorizontal, 0, 0, 0));
}
@@ -55,13 +70,43 @@ void MenuBar::SetMenu(ui::MenuModel* model) {
RemoveAllChildViews(true);
for (int i = 0; i < model->GetItemCount(); ++i) {
views::MenuButton* button = new views::MenuButton(
this, FilterMenuButtonLabel(model->GetLabelAt(i)), this, false);
SubmenuButton* button = new SubmenuButton(this, model->GetLabelAt(i), this);
button->set_tag(i);
#if defined(USE_X11)
button->SetEnabledColor(enabled_color_);
button->SetDisabledColor(disabled_color_);
button->SetHighlightColor(highlight_color_);
button->SetHoverColor(hover_color_);
button->SetUnderlineColor(enabled_color_);
#elif defined(OS_WIN)
button->SetUnderlineColor(color_utils::GetSysSkColor(COLOR_GRAYTEXT));
#endif
AddChildView(button);
}
}
void MenuBar::SetAcceleratorVisibility(bool visible) {
for (int i = 0; i < child_count(); ++i)
static_cast<SubmenuButton*>(child_at(i))->SetAcceleratorVisibility(visible);
}
int MenuBar::GetAcceleratorIndex(base::char16 key) {
for (int i = 0; i < child_count(); ++i) {
SubmenuButton* button = static_cast<SubmenuButton*>(child_at(i));
if (button->accelerator() == key)
return i;
}
return -1;
}
void MenuBar::ActivateAccelerator(base::char16 key) {
int i = GetAcceleratorIndex(key);
if (i != -1)
static_cast<SubmenuButton*>(child_at(i))->Activate();
}
int MenuBar::GetItemCount() const {
return menu_model_->GetItemCount();
}
@@ -98,6 +143,9 @@ void MenuBar::ButtonPressed(views::Button* sender, const ui::Event& event) {
void MenuBar::OnMenuButtonClicked(views::View* source,
const gfx::Point& point) {
// Hide the accelerator when a submenu is activated.
SetAcceleratorVisibility(false);
if (!menu_model_)
return;

View File

@@ -31,6 +31,16 @@ class MenuBar : public views::View,
// Replaces current menu with a new one.
void SetMenu(ui::MenuModel* menu_model);
// Shows underline under accelerators.
void SetAcceleratorVisibility(bool visible);
// Returns which submenu has accelerator |key|, -1 would be returned when
// there is no matching submenu.
int GetAcceleratorIndex(base::char16 key);
// Shows the submenu whose accelerator is |key|.
void ActivateAccelerator(base::char16 key);
// Returns there are how many items in the root menu.
int GetItemCount() const;
@@ -52,6 +62,15 @@ class MenuBar : public views::View,
const gfx::Point& point) OVERRIDE;
private:
SkColor background_color_;
#if defined(USE_X11)
SkColor enabled_color_;
SkColor disabled_color_;
SkColor highlight_color_;
SkColor hover_color_;
#endif
ui::MenuModel* menu_model_;
scoped_ptr<MenuDelegate> menu_delegate_;

View File

@@ -7,6 +7,7 @@
#include "atom/browser/ui/views/menu_bar.h"
#include "base/stl_util.h"
#include "ui/views/controls/button/menu_button.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/menu_model_adapter.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/widget/widget.h"
@@ -39,7 +40,7 @@ void MenuDelegate::RunMenu(ui::MenuModel* model, views::MenuButton* button) {
button->GetWidget()->GetTopLevelWidget(),
button,
bounds,
views::MenuItemView::TOPRIGHT,
views::MENU_ANCHOR_TOPRIGHT,
ui::MENU_SOURCE_MOUSE,
views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU));
}
@@ -107,14 +108,14 @@ void MenuDelegate::WillHideMenu(views::MenuItemView* menu) {
views::MenuItemView* MenuDelegate::GetSiblingMenu(
views::MenuItemView* menu,
const gfx::Point& screen_point,
views::MenuItemView::AnchorPosition* anchor,
views::MenuAnchorPosition* anchor,
bool* has_mnemonics,
views::MenuButton** button) {
ui::MenuModel* model;
if (!menu_bar_->GetMenuButtonFromScreenPoint(screen_point, &model, button))
return NULL;
*anchor = views::MenuItemView::TOPLEFT;
*anchor = views::MENU_ANCHOR_TOPLEFT;
*has_mnemonics = true;
id_ = (*button)->tag();

View File

@@ -46,7 +46,7 @@ class MenuDelegate : public views::MenuDelegate {
virtual views::MenuItemView* GetSiblingMenu(
views::MenuItemView* menu,
const gfx::Point& screen_point,
views::MenuItemView::AnchorPosition* anchor,
views::MenuAnchorPosition* anchor,
bool* has_mnemonics,
views::MenuButton** button);

View File

@@ -24,10 +24,10 @@ void MenuLayout::Layout(views::View* host) {
gfx::Rect web_view_bounds = gfx::Rect(
0, menu_height_, size.width(), size.height() - menu_height_);
views::View* menu_bar = host->child_at(0);
views::View* web_view = host->child_at(1);
menu_bar->SetBoundsRect(menu_Bar_bounds);
views::View* web_view = host->child_at(0);
views::View* menu_bar = host->child_at(1);
web_view->SetBoundsRect(web_view_bounds);
menu_bar->SetBoundsRect(menu_Bar_bounds);
}
gfx::Size MenuLayout::GetPreferredSize(views::View* host) {

View File

@@ -0,0 +1,92 @@
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/ui/views/submenu_button.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/text_utils.h"
namespace atom {
namespace {
// Filter out the "&" in menu label.
base::string16 FilterAccecelator(const base::string16& label) {
base::string16 out;
base::RemoveChars(label, base::ASCIIToUTF16("&").c_str(), &out);
return out;
}
} // namespace
SubmenuButton::SubmenuButton(views::ButtonListener* listener,
const base::string16& title,
views::MenuButtonListener* menu_button_listener)
: views::MenuButton(listener, FilterAccecelator(title),
menu_button_listener, false),
accelerator_(0),
show_underline_(false),
underline_start_(-1),
underline_end_(-1),
text_width_(0),
text_height_(0),
underline_color_(SK_ColorBLACK) {
if (GetUnderlinePosition(title, &accelerator_, &underline_start_,
&underline_end_))
gfx::Canvas::SizeStringInt(text(), font_list(), &text_width_,
&text_height_, 0, 0);
}
SubmenuButton::~SubmenuButton() {
}
void SubmenuButton::SetAcceleratorVisibility(bool visible) {
if (visible == show_underline_)
return;
show_underline_ = visible;
SchedulePaint();
}
void SubmenuButton::SetUnderlineColor(SkColor color) {
underline_color_ = color;
}
void SubmenuButton::OnPaint(gfx::Canvas* canvas) {
views::MenuButton::OnPaint(canvas);
if (show_underline_ && (underline_start_ != underline_end_)) {
int padding = (width() - text_width_) / 2;
int underline_height = (height() + text_height_) / 2 - 2;
canvas->DrawLine(gfx::Point(underline_start_ + padding, underline_height),
gfx::Point(underline_end_ + padding, underline_height),
underline_color_);
}
}
bool SubmenuButton::GetUnderlinePosition(const base::string16& text,
base::char16* accelerator,
int* start, int* end) {
int pos, span;
base::string16 trimmed = gfx::RemoveAcceleratorChar(text, '&', &pos, &span);
if (pos > -1 && span != 0) {
*accelerator = base::ToUpperASCII(trimmed[pos]);
GetCharacterPosition(trimmed, pos, start);
GetCharacterPosition(trimmed, pos + span, end);
return true;
}
return false;
}
void SubmenuButton::GetCharacterPosition(
const base::string16& text, int index, int* pos) {
int height;
gfx::Canvas::SizeStringInt(text.substr(0, index), font_list(), pos, &height,
0, 0);
}
} // namespace atom

View File

@@ -0,0 +1,50 @@
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_UI_VIEWS_SUBMENU_BUTTON_H_
#define ATOM_BROWSER_UI_VIEWS_SUBMENU_BUTTON_H_
#include "ui/views/controls/button/menu_button.h"
namespace atom {
// Special button that used by menu bar to show submenus.
class SubmenuButton : public views::MenuButton {
public:
SubmenuButton(views::ButtonListener* listener,
const base::string16& title,
views::MenuButtonListener* menu_button_listener);
virtual ~SubmenuButton();
void SetAcceleratorVisibility(bool visible);
void SetUnderlineColor(SkColor color);
base::char16 accelerator() const { return accelerator_; }
// views::MenuButton:
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
private:
bool GetUnderlinePosition(const base::string16& text,
base::char16* accelerator,
int* start, int* end);
void GetCharacterPosition(
const base::string16& text, int index, int* pos);
base::char16 accelerator_;
bool show_underline_;
int underline_start_;
int underline_end_;
int text_width_;
int text_height_;
SkColor underline_color_;
DISALLOW_COPY_AND_ASSIGN(SubmenuButton);
};
} // namespace atom
#endif // ATOM_BROWSER_UI_VIEWS_SUBMENU_BUTTON_H_

View File

@@ -60,16 +60,14 @@ void NotifyIcon::HandleClickEvent(const gfx::Point& cursor_pos,
if (!SetForegroundWindow(window_))
return;
menu_runner_.reset(new views::MenuRunner(menu_model_));
views::MenuRunner::RunResult result = menu_runner_->RunMenuAt(
views::MenuRunner menu_runner(menu_model_);
ignore_result(menu_runner.RunMenuAt(
NULL,
NULL,
gfx::Rect(cursor_pos, gfx::Size()),
views::MenuItemView::TOPLEFT,
views::MENU_ANCHOR_TOPLEFT,
ui::MENU_SOURCE_MOUSE,
views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU);
if (result == views::MenuRunner::MENU_DELETED)
LOG(ERROR) << "Menu deleted when running";
views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU));
}
void NotifyIcon::ResetIcon() {

View File

@@ -20,10 +20,6 @@ namespace gfx {
class Point;
}
namespace views {
class MenuRunner;
}
namespace atom {
class NotifyIconHost;
@@ -72,7 +68,6 @@ class NotifyIcon : public TrayIcon {
// The context menu.
ui::SimpleMenuModel* menu_model_;
scoped_ptr<views::MenuRunner> menu_runner_;
DISALLOW_COPY_AND_ASSIGN(NotifyIcon);
};

View File

@@ -28,7 +28,7 @@ int32_t IDWeakMap::Add(v8::Isolate* isolate, v8::Handle<v8::Object> object) {
object->SetHiddenValue(mate::StringToV8(isolate, "IDWeakMapKey"),
mate::Converter<int32_t>::ToV8(isolate, key));
map_[key] = new mate::RefCountedPersistent<v8::Object>(object);
map_[key] = new mate::RefCountedPersistent<v8::Object>(isolate, object);
map_[key]->SetWeak(this, WeakCallback);
return key;
}

View File

@@ -7,10 +7,9 @@
#include <string>
#include "atom/common/atom_version.h"
#include "atom/common/native_mate_converters/function_converter.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "base/callback.h"
#include "base/logging.h"
#include "native_mate/callback.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_includes.h"

View File

@@ -16,7 +16,7 @@ void ObjectLifeMonitor::BindTo(v8::Isolate* isolate,
target->SetHiddenValue(MATE_STRING_NEW(isolate, "destructor"), destructor);
ObjectLifeMonitor* olm = new ObjectLifeMonitor();
olm->handle_.reset(target);
olm->handle_.reset(isolate, target);
olm->handle_.SetWeak(olm, WeakCallback);
}

View File

@@ -6,8 +6,8 @@
#define ATOM_VERSION_H
#define ATOM_MAJOR_VERSION 0
#define ATOM_MINOR_VERSION 14
#define ATOM_PATCH_VERSION 2
#define ATOM_MINOR_VERSION 15
#define ATOM_PATCH_VERSION 8
#define ATOM_VERSION_IS_RELEASE 1

View File

@@ -1,21 +0,0 @@
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/common/browser_v8_locker.h"
namespace node {
extern bool g_standalone_mode;
}
namespace atom {
BrowserV8Locker::BrowserV8Locker(v8::Isolate* isolate) {
if (node::g_standalone_mode)
locker_.reset(new v8::Locker(isolate));
}
BrowserV8Locker::~BrowserV8Locker() {
}
} // namespace atom

View File

@@ -1,28 +0,0 @@
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_BROWSER_V8_LOCKER_H_
#define ATOM_COMMON_BROWSER_V8_LOCKER_H_
#include "base/memory/scoped_ptr.h"
#include "v8/include/v8.h"
namespace atom {
// Like v8::Locker, but only do lock when in browser process.
class BrowserV8Locker {
public:
explicit BrowserV8Locker(v8::Isolate* isolate);
~BrowserV8Locker();
private:
void* operator new(size_t size);
void operator delete(void*, size_t);
scoped_ptr<v8::Locker> locker_;
};
} // namespace atom
#endif // ATOM_COMMON_BROWSER_V8_LOCKER_H_

View File

@@ -8,7 +8,7 @@
#ifndef ATOM_COMMON_CHROME_VERSION_H_
#define ATOM_COMMON_CHROME_VERSION_H_
#define CHROME_VERSION_STRING "35.0.1916.153"
#define CHROME_VERSION_STRING "36.0.1985.125"
#define CHROME_VERSION "v" CHROME_VERSION_STRING
#endif // ATOM_COMMON_CHROME_VERSION_H_

View File

@@ -54,12 +54,14 @@ void CrashReporterWin::InitBreakpad(const std::string& product_name,
if (waiting_event != INVALID_HANDLE_VALUE)
WaitForSingleObject(waiting_event, 1000);
int handler_types = google_breakpad::ExceptionHandler::HANDLER_EXCEPTION |
google_breakpad::ExceptionHandler::HANDLER_PURECALL;
breakpad_.reset(new google_breakpad::ExceptionHandler(
temp_dir.value(),
FilterCallback,
MinidumpCallback,
this,
google_breakpad::ExceptionHandler::HANDLER_ALL,
handler_types,
kSmallDumpType,
pipe_name.c_str(),
GetCustomInfo(product_name, version, company_name)));

View File

@@ -350,6 +350,8 @@ void ExecUploadProcessOrTerminate(const BreakpadInfo& info,
"--timeout=60", // Set a timeout so we don't hang forever.
"--tries=1", // Don't retry if the upload fails.
"--quiet", // Be silent.
"-O", // output reply to /dev/null.
"/dev/null",
NULL,
};
static const char msg[] = "Cannot upload crash dump: cannot exec "

View File

@@ -25,3 +25,11 @@ wrapWithActivateUvLoop = (func) ->
process.nextTick = wrapWithActivateUvLoop process.nextTick
global.setImmediate = wrapWithActivateUvLoop timers.setImmediate
global.clearImmediate = timers.clearImmediate
# setTimeout needs to update the polling timeout of the event loop, when called
# under Chromium's event loop the node's event loop won't get a chance to update
# the timeout, so we have to force the node's event loop to recalculate the
# timeout in browser process.
if process.type is 'browser'
global.setTimeout = wrapWithActivateUvLoop timers.setTimeout
global.setInterval = wrapWithActivateUvLoop timers.setInterval

View File

@@ -0,0 +1,22 @@
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/common/native_mate_converters/accelerator_converter.h"
#include <string>
#include "atom/browser/ui/accelerator_util.h"
namespace mate {
// static
bool Converter<ui::Accelerator>::FromV8(
v8::Isolate* isolate, v8::Handle<v8::Value> val, ui::Accelerator* out) {
std::string keycode;
if (!ConvertFromV8(isolate, val, &keycode))
return false;
return accelerator_util::StringToAccelerator(keycode, out);
}
} // namespace mate

View File

@@ -0,0 +1,24 @@
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_ACCELERATOR_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_ACCELERATOR_CONVERTER_H_
#include "native_mate/converter.h"
namespace ui {
class Accelerator;
}
namespace mate {
template<>
struct Converter<ui::Accelerator> {
static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
ui::Accelerator* out);
};
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_ACCELERATOR_CONVERTER_H_

View File

@@ -1,209 +0,0 @@
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_FUNCTION_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_FUNCTION_CONVERTER_H_
#include "atom/common/browser_v8_locker.h"
#include "base/bind.h"
#include "base/callback.h"
#include "native_mate/constructor.h"
#include "native_mate/scoped_persistent.h"
namespace mate {
namespace internal {
typedef scoped_refptr<RefCountedPersistent<v8::Function> > SafeV8Function;
// Helper to convert type to V8 with storage type (const T& to T).
template<typename T>
v8::Handle<v8::Value> ConvertToV8(v8::Isolate* isolate, T a) {
return Converter<typename base::internal::CallbackParamTraits<T>::StorageType>
::ToV8(isolate, a);
}
// This set of templates invokes a V8::Function by converting the C++ types.
template<typename Sig>
struct V8FunctionInvoker;
template<typename R>
struct V8FunctionInvoker<R()> {
static R Go(v8::Isolate* isolate, SafeV8Function function) {
R ret;
atom::BrowserV8Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::Function> holder = function->NewHandle();
v8::Handle<v8::Value> val(holder->Call(holder, 0, NULL));
Converter<R>::FromV8(isolate, val, &ret);
return ret;
}
};
template<>
struct V8FunctionInvoker<void()> {
static void Go(v8::Isolate* isolate, SafeV8Function function) {
atom::BrowserV8Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::Function> holder = function->NewHandle();
holder->Call(holder, 0, NULL);
}
};
template<typename R, typename P1>
struct V8FunctionInvoker<R(P1)> {
static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1) {
R ret;
atom::BrowserV8Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::Function> holder = function->NewHandle();
v8::Handle<v8::Value> args[] = {
ConvertToV8(isolate, a1),
};
v8::Handle<v8::Value> val(holder->Call(holder, arraysize(args), args));
Converter<R>::FromV8(isolate, val, &ret);
return ret;
}
};
template<typename P1>
struct V8FunctionInvoker<void(P1)> {
static void Go(v8::Isolate* isolate, SafeV8Function function, P1 a1) {
atom::BrowserV8Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::Function> holder = function->NewHandle();
v8::Handle<v8::Value> args[] = {
ConvertToV8(isolate, a1),
};
holder->Call(holder, arraysize(args), args);
}
};
template<typename R, typename P1, typename P2>
struct V8FunctionInvoker<R(P1, P2)> {
static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2) {
R ret;
atom::BrowserV8Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::Function> holder = function->NewHandle();
v8::Handle<v8::Value> args[] = {
ConvertToV8(isolate, a1),
ConvertToV8(isolate, a2),
};
v8::Handle<v8::Value> val(holder->Call(holder, arraysize(args), args));
Converter<R>::FromV8(isolate, val, &ret);
return ret;
}
};
template<typename P1, typename P2>
struct V8FunctionInvoker<void(P1, P2)> {
static void Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2) {
atom::BrowserV8Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::Function> holder = function->NewHandle();
v8::Handle<v8::Value> args[] = {
ConvertToV8(isolate, a1),
ConvertToV8(isolate, a2),
};
holder->Call(holder, arraysize(args), args);
}
};
template<typename R, typename P1, typename P2, typename P3>
struct V8FunctionInvoker<R(P1, P2, P3)> {
static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2,
P3 a3) {
R ret;
atom::BrowserV8Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::Function> holder = function->NewHandle();
v8::Handle<v8::Value> args[] = {
ConvertToV8(isolate, a1),
ConvertToV8(isolate, a2),
ConvertToV8(isolate, a3),
};
v8::Handle<v8::Value> val(holder->Call(holder, arraysize(args), args));
Converter<R>::FromV8(isolate, val, &ret);
return ret;
}
};
template<typename P1, typename P2, typename P3>
struct V8FunctionInvoker<void(P1, P2, P3)> {
static void Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2,
P3 a3) {
atom::BrowserV8Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::Function> holder = function->NewHandle();
v8::Handle<v8::Value> args[] = {
ConvertToV8(isolate, a1),
ConvertToV8(isolate, a2),
ConvertToV8(isolate, a3),
};
holder->Call(holder, arraysize(args), args);
}
};
template<typename R, typename P1, typename P2, typename P3, typename P4>
struct V8FunctionInvoker<R(P1, P2, P3, P4)> {
static R Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2,
P3 a3, P4 a4) {
R ret;
atom::BrowserV8Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::Function> holder = function->NewHandle();
v8::Handle<v8::Value> args[] = {
ConvertToV8(isolate, a1),
ConvertToV8(isolate, a2),
ConvertToV8(isolate, a3),
ConvertToV8(isolate, a4),
};
v8::Handle<v8::Value> val(holder->Call(holder, arraysize(args), args));
Converter<R>::FromV8(isolate, val, &ret);
return ret;
}
};
template<typename P1, typename P2, typename P3, typename P4>
struct V8FunctionInvoker<void(P1, P2, P3, P4)> {
static void Go(v8::Isolate* isolate, SafeV8Function function, P1 a1, P2 a2,
P3 a3, P4 a4) {
atom::BrowserV8Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::Function> holder = function->NewHandle();
v8::Handle<v8::Value> args[] = {
ConvertToV8(isolate, a1),
ConvertToV8(isolate, a2),
ConvertToV8(isolate, a3),
ConvertToV8(isolate, a4),
};
holder->Call(holder, arraysize(args), args);
}
};
} // namespace internal
template<typename Sig>
struct Converter<base::Callback<Sig> > {
static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
const base::Callback<Sig>& val) {
return CreateFunctionTemplate(isolate, val)->GetFunction();
}
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
base::Callback<Sig>* out) {
if (!val->IsFunction())
return false;
internal::SafeV8Function function(
new RefCountedPersistent<v8::Function>(val));
*out = base::Bind(&internal::V8FunctionInvoker<Sig>::Go, isolate, function);
return true;
}
};
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_FUNCTION_CONVERTER_H_

View File

@@ -5,6 +5,7 @@
#include "atom/common/native_mate_converters/image_converter.h"
#include <string>
#include <vector>
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "base/file_util.h"
@@ -18,12 +19,83 @@ namespace mate {
namespace {
ui::ScaleFactor GetScaleFactorFromFileName(const base::FilePath& path) {
struct ScaleFactorPair {
const char* name;
float scale;
};
ScaleFactorPair kScaleFactorPairs[] = {
// The "@2x" is put as first one to make scale matching faster.
{ "@2x" , 2.0f },
{ "@3x" , 3.0f },
{ "@1x" , 1.0f },
{ "@1.25x" , 1.25f },
{ "@1.33x" , 1.33f },
{ "@1.4x" , 1.4f },
{ "@1.5x" , 1.5f },
{ "@1.8x" , 1.8f },
{ "@2.5x" , 2.5f },
};
float GetScaleFactorFromPath(const base::FilePath& path) {
std::string filename(path.BaseName().RemoveExtension().AsUTF8Unsafe());
if (EndsWith(filename, "@2x", true))
return ui::SCALE_FACTOR_200P;
else
return ui::SCALE_FACTOR_100P;
// There is no scale info in the file path.
if (!EndsWith(filename, "x", true))
return 1.0f;
// We don't try to convert string to float here because it is very very
// expensive.
for (unsigned i = 0; i < arraysize(kScaleFactorPairs); ++i) {
if (EndsWith(filename, kScaleFactorPairs[i].name, true))
return kScaleFactorPairs[i].scale;
}
return 1.0f;
}
void AppendIfExists(std::vector<base::FilePath>* paths,
const base::FilePath& path) {
if (base::PathExists(path))
paths->push_back(path);
}
void PopulatePossibleFilePaths(std::vector<base::FilePath>* paths,
const base::FilePath& path) {
AppendIfExists(paths, path);
std::string filename(path.BaseName().RemoveExtension().AsUTF8Unsafe());
if (MatchPattern(filename, "*@*x"))
return;
for (unsigned i = 0; i < arraysize(kScaleFactorPairs); ++i)
AppendIfExists(paths,
path.InsertBeforeExtensionASCII(kScaleFactorPairs[i].name));
}
bool AddImageSkiaRepFromPath(gfx::ImageSkia* image,
const base::FilePath& path) {
std::string file_contents;
if (!base::ReadFileToString(path, &file_contents))
return false;
const unsigned char* data =
reinterpret_cast<const unsigned char*>(file_contents.data());
size_t size = file_contents.size();
scoped_ptr<SkBitmap> decoded(new SkBitmap());
// Try PNG first.
if (!gfx::PNGCodec::Decode(data, size, decoded.get()))
// Try JPEG.
decoded.reset(gfx::JPEGCodec::Decode(data, size));
if (decoded) {
image->AddRepresentation(gfx::ImageSkiaRep(
*decoded.release(), GetScaleFactorFromPath(path)));
return true;
}
return false;
}
} // namespace
@@ -33,25 +105,16 @@ bool Converter<gfx::ImageSkia>::FromV8(v8::Isolate* isolate,
gfx::ImageSkia* out) {
base::FilePath path;
if (Converter<base::FilePath>::FromV8(isolate, val, &path)) {
std::string file_contents;
if (!base::ReadFileToString(path, &file_contents))
std::vector<base::FilePath> paths;
PopulatePossibleFilePaths(&paths, path);
if (paths.empty())
return false;
const unsigned char* data =
reinterpret_cast<const unsigned char*>(file_contents.data());
size_t size = file_contents.size();
scoped_ptr<SkBitmap> decoded(new SkBitmap());
// Try PNG first.
if (!gfx::PNGCodec::Decode(data, size, decoded.get()))
// Try JPEG.
decoded.reset(gfx::JPEGCodec::Decode(data, size));
if (decoded) {
*out = gfx::ImageSkia(gfx::ImageSkiaRep(*decoded.release(),
GetScaleFactorFromFileName(path)));
return true;
for (size_t i = 0; i < paths.size(); ++i) {
if (!AddImageSkiaRepFromPath(out, paths[i]))
return false;
}
return true;
}
return false;

View File

@@ -7,13 +7,13 @@
#include <string>
#include <vector>
#include "atom/common/browser_v8_locker.h"
#include "base/command_line.h"
#include "base/base_paths.h"
#include "base/files/file_path.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "content/public/browser/browser_thread.h"
#include "native_mate/locker.h"
#if defined(OS_WIN)
#include "base/strings/utf_string_conversions.h"
@@ -61,10 +61,12 @@ REFERENCE_MODULE(uv);
// Atom Shell's builtin modules.
REFERENCE_MODULE(atom_browser_app);
REFERENCE_MODULE(atom_browser_auto_updater);
REFERENCE_MODULE(atom_browser_content_tracing);
REFERENCE_MODULE(atom_browser_dialog);
REFERENCE_MODULE(atom_browser_menu);
REFERENCE_MODULE(atom_browser_power_monitor);
REFERENCE_MODULE(atom_browser_protocol);
REFERENCE_MODULE(atom_browser_global_shortcut);
REFERENCE_MODULE(atom_browser_tray);
REFERENCE_MODULE(atom_browser_window);
REFERENCE_MODULE(atom_common_clipboard);
@@ -244,7 +246,7 @@ void NodeBindings::UvRunOnce() {
node::Environment* env = uv_env() ? uv_env() : global_env;
// Use Locker in browser process.
BrowserV8Locker locker(env->isolate());
mate::Locker locker(env->isolate());
v8::HandleScope handle_scope(env->isolate());
// Enter node context while dealing with uv events.

View File

@@ -48,6 +48,12 @@ const char kWebPreferences[] = "web-preferences";
// The factor of which page should be zoomed.
const char kZoomFactor[] = "zoom-factor";
// The menu bar is hidden unless "Alt" is pressed.
const char kAutoHideMenuBar[] = "auto-hide-menu-bar";
// Enable window to be resized larger than screen.
const char kEnableLargerThanScreen[] = "enable-larger-than-screen";
} // namespace switches
} // namespace atom

View File

@@ -32,6 +32,8 @@ extern const char kAcceptFirstMouse[];
extern const char kUseContentSize[];
extern const char kWebPreferences[];
extern const char kZoomFactor[];
extern const char kAutoHideMenuBar[];
extern const char kEnableLargerThanScreen[];
} // namespace switches

View File

@@ -7,19 +7,19 @@
#include "atom/common/native_mate_converters/value_converter.h"
#include "content/public/renderer/render_view.h"
#include "native_mate/dictionary.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "atom/common/node_includes.h"
using content::RenderView;
using blink::WebFrame;
using blink::WebLocalFrame;
using blink::WebView;
namespace {
RenderView* GetCurrentRenderView() {
WebFrame* frame = WebFrame::frameForCurrentContext();
WebLocalFrame* frame = WebLocalFrame::frameForCurrentContext();
if (!frame)
return NULL;

View File

@@ -6,7 +6,7 @@
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "atom/common/node_includes.h"
@@ -18,7 +18,7 @@ namespace api {
namespace {
blink::WebView* GetCurrentWebView() {
blink::WebFrame* frame = blink::WebFrame::frameForCurrentContext();
blink::WebLocalFrame* frame = blink::WebLocalFrame::frameForCurrentContext();
if (!frame)
return NULL;
return frame->view();

View File

@@ -18,6 +18,7 @@
#include "third_party/WebKit/public/web/WebDraggableRegion.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "atom/common/node_includes.h"
@@ -36,7 +37,8 @@ AtomRenderViewObserver::AtomRenderViewObserver(
AtomRenderViewObserver::~AtomRenderViewObserver() {
}
void AtomRenderViewObserver::DidCreateDocumentElement(blink::WebFrame* frame) {
void AtomRenderViewObserver::DidCreateDocumentElement(
blink::WebLocalFrame* frame) {
// Read --zoom-factor from command line.
std::string zoom_factor_str = CommandLine::ForCurrentProcess()->
GetSwitchValueASCII(switches::kZoomFactor);;

View File

@@ -25,7 +25,7 @@ class AtomRenderViewObserver : public content::RenderViewObserver {
private:
// content::RenderViewObserver implementation.
virtual void DidCreateDocumentElement(blink::WebFrame* frame) OVERRIDE;
virtual void DidCreateDocumentElement(blink::WebLocalFrame* frame) OVERRIDE;
virtual void DraggableRegionsChanged(blink::WebFrame* frame) OVERRIDE;
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;

View File

@@ -70,6 +70,10 @@ AtomRendererClient::AtomRendererClient()
node_integration_ = ALL;
if (IsNodeBindingEnabled()) {
// Always enable harmony when node binding is on.
std::string flags("--harmony");
v8::V8::SetFlagsFromString(flags.c_str(), static_cast<int>(flags.size()));
node_bindings_.reset(NodeBindings::Create(false));
atom_bindings_.reset(new AtomRendererBindings);
}

View File

@@ -0,0 +1,122 @@
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/extensions/global_shortcut_listener.h"
#include "base/logging.h"
#include "content/public/browser/browser_thread.h"
#include "ui/base/accelerators/accelerator.h"
using content::BrowserThread;
namespace extensions {
GlobalShortcutListener::GlobalShortcutListener()
: shortcut_handling_suspended_(false) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
GlobalShortcutListener::~GlobalShortcutListener() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(accelerator_map_.empty()); // Make sure we've cleaned up.
}
bool GlobalShortcutListener::RegisterAccelerator(
const ui::Accelerator& accelerator, Observer* observer) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (IsShortcutHandlingSuspended())
return false;
AcceleratorMap::const_iterator it = accelerator_map_.find(accelerator);
if (it != accelerator_map_.end()) {
// The accelerator has been registered.
return false;
}
if (!RegisterAcceleratorImpl(accelerator)) {
// If the platform-specific registration fails, mostly likely the shortcut
// has been registered by other native applications.
return false;
}
if (accelerator_map_.empty())
StartListening();
accelerator_map_[accelerator] = observer;
return true;
}
void GlobalShortcutListener::UnregisterAccelerator(
const ui::Accelerator& accelerator, Observer* observer) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (IsShortcutHandlingSuspended())
return;
AcceleratorMap::iterator it = accelerator_map_.find(accelerator);
// We should never get asked to unregister something that we didn't register.
DCHECK(it != accelerator_map_.end());
// The caller should call this function with the right observer.
DCHECK(it->second == observer);
UnregisterAcceleratorImpl(accelerator);
accelerator_map_.erase(it);
if (accelerator_map_.empty())
StopListening();
}
void GlobalShortcutListener::UnregisterAccelerators(Observer* observer) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (IsShortcutHandlingSuspended())
return;
AcceleratorMap::iterator it = accelerator_map_.begin();
while (it != accelerator_map_.end()) {
if (it->second == observer) {
AcceleratorMap::iterator to_remove = it++;
UnregisterAccelerator(to_remove->first, observer);
} else {
++it;
}
}
}
void GlobalShortcutListener::SetShortcutHandlingSuspended(bool suspended) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (shortcut_handling_suspended_ == suspended)
return;
shortcut_handling_suspended_ = suspended;
for (AcceleratorMap::iterator it = accelerator_map_.begin();
it != accelerator_map_.end();
++it) {
// On Linux, when shortcut handling is suspended we cannot simply early
// return in NotifyKeyPressed (similar to what we do for non-global
// shortcuts) because we'd eat the keyboard event thereby preventing the
// user from setting the shortcut. Therefore we must unregister while
// handling is suspended and register when handling resumes.
if (shortcut_handling_suspended_)
UnregisterAcceleratorImpl(it->first);
else
RegisterAcceleratorImpl(it->first);
}
}
bool GlobalShortcutListener::IsShortcutHandlingSuspended() const {
return shortcut_handling_suspended_;
}
void GlobalShortcutListener::NotifyKeyPressed(
const ui::Accelerator& accelerator) {
AcceleratorMap::iterator iter = accelerator_map_.find(accelerator);
if (iter == accelerator_map_.end()) {
// This should never occur, because if it does, we have failed to unregister
// or failed to clean up the map after unregistering the shortcut.
NOTREACHED();
return; // No-one is listening to this key.
}
iter->second->OnKeyPressed(accelerator);
}
} // namespace extensions

View File

@@ -0,0 +1,99 @@
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_H_
#define CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_H_
#include <map>
#include "base/basictypes.h"
#include "ui/events/keycodes/keyboard_codes.h"
namespace ui {
class Accelerator;
}
namespace extensions {
// Platform-neutral implementation of a class that keeps track of observers and
// monitors keystrokes. It relays messages to the appropriate observer when a
// global shortcut has been struck by the user.
class GlobalShortcutListener {
public:
class Observer {
public:
// Called when your global shortcut (|accelerator|) is struck.
virtual void OnKeyPressed(const ui::Accelerator& accelerator) = 0;
};
virtual ~GlobalShortcutListener();
static GlobalShortcutListener* GetInstance();
// Register an observer for when a certain |accelerator| is struck. Returns
// true if register successfully, or false if 1) the specificied |accelerator|
// has been registered by another caller or other native applications, or
// 2) shortcut handling is suspended.
//
// Note that we do not support recognizing that an accelerator has been
// registered by another application on all platforms. This is a per-platform
// consideration.
bool RegisterAccelerator(const ui::Accelerator& accelerator,
Observer* observer);
// Stop listening for the given |accelerator|, does nothing if shortcut
// handling is suspended.
void UnregisterAccelerator(const ui::Accelerator& accelerator,
Observer* observer);
// Stop listening for all accelerators of the given |observer|, does nothing
// if shortcut handling is suspended.
void UnregisterAccelerators(Observer* observer);
// Suspend/Resume global shortcut handling. Note that when suspending,
// RegisterAccelerator/UnregisterAccelerator/UnregisterAccelerators are not
// allowed to be called until shortcut handling has been resumed.
void SetShortcutHandlingSuspended(bool suspended);
// Returns whether shortcut handling is currently suspended.
bool IsShortcutHandlingSuspended() const;
protected:
GlobalShortcutListener();
// Called by platform specific implementations of this class whenever a key
// is struck. Only called for keys that have an observer registered.
void NotifyKeyPressed(const ui::Accelerator& accelerator);
private:
// The following methods are implemented by platform-specific implementations
// of this class.
//
// Start/StopListening are called when transitioning between zero and nonzero
// registered accelerators. StartListening will be called after
// RegisterAcceleratorImpl and StopListening will be called after
// UnregisterAcceleratorImpl.
//
// For RegisterAcceleratorImpl, implementations return false if registration
// did not complete successfully.
virtual void StartListening() = 0;
virtual void StopListening() = 0;
virtual bool RegisterAcceleratorImpl(const ui::Accelerator& accelerator) = 0;
virtual void UnregisterAcceleratorImpl(
const ui::Accelerator& accelerator) = 0;
// The map of accelerators that have been successfully registered as global
// shortcuts and their observer.
typedef std::map<ui::Accelerator, Observer*> AcceleratorMap;
AcceleratorMap accelerator_map_;
// Keeps track of whether shortcut handling is currently suspended.
bool shortcut_handling_suspended_;
DISALLOW_COPY_AND_ASSIGN(GlobalShortcutListener);
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_H_

View File

@@ -0,0 +1,106 @@
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_MAC_H_
#define CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_MAC_H_
#include "chrome/browser/extensions/global_shortcut_listener.h"
#include <Carbon/Carbon.h>
#include <CoreFoundation/CoreFoundation.h>
#include <map>
#include "base/mac/scoped_nsobject.h"
namespace extensions {
// Mac-specific implementation of the GlobalShortcutListener class that
// listens for global shortcuts. Handles basic keyboard intercepting and
// forwards its output to the base class for processing.
//
// This class does two things:
// 1. Intercepts media keys. Uses an event tap for intercepting media keys
// (PlayPause, NextTrack, PreviousTrack).
// 2. Binds keyboard shortcuts (hot keys). Carbon RegisterEventHotKey API for
// binding to non-media key global hot keys (eg. Command-Shift-1).
class GlobalShortcutListenerMac : public GlobalShortcutListener {
public:
GlobalShortcutListenerMac();
virtual ~GlobalShortcutListenerMac();
private:
typedef int KeyId;
typedef std::map<ui::Accelerator, KeyId> AcceleratorIdMap;
typedef std::map<KeyId, ui::Accelerator> IdAcceleratorMap;
typedef std::map<KeyId, EventHotKeyRef> IdHotKeyRefMap;
// Keyboard event callbacks.
void OnHotKeyEvent(EventHotKeyID hot_key_id);
bool OnMediaKeyEvent(int key_code);
// GlobalShortcutListener implementation.
virtual void StartListening() OVERRIDE;
virtual void StopListening() OVERRIDE;
virtual bool RegisterAcceleratorImpl(
const ui::Accelerator& accelerator) OVERRIDE;
virtual void UnregisterAcceleratorImpl(
const ui::Accelerator& accelerator) OVERRIDE;
// Mac-specific functions for registering hot keys with modifiers.
bool RegisterHotKey(const ui::Accelerator& accelerator, KeyId hot_key_id);
void UnregisterHotKey(const ui::Accelerator& accelerator);
// Enable and disable the media key event tap.
void StartWatchingMediaKeys();
void StopWatchingMediaKeys();
// Enable and disable the hot key event handler.
void StartWatchingHotKeys();
void StopWatchingHotKeys();
// Whether or not any media keys are currently registered.
bool IsAnyMediaKeyRegistered();
// Whether or not any hot keys are currently registered.
bool IsAnyHotKeyRegistered();
// The callback for when an event tap happens.
static CGEventRef EventTapCallback(
CGEventTapProxy proxy, CGEventType type, CGEventRef event, void* refcon);
// The callback for when a hot key event happens.
static OSStatus HotKeyHandler(
EventHandlerCallRef next_handler, EventRef event, void* user_data);
// Whether this object is listening for global shortcuts.
bool is_listening_;
// The hotkey identifier for the next global shortcut that is added.
KeyId hot_key_id_;
// A map of all hotkeys (media keys and shortcuts) mapping to their
// corresponding hotkey IDs. For quickly finding if an accelerator is
// registered.
AcceleratorIdMap accelerator_ids_;
// The inverse map for quickly looking up accelerators by hotkey id.
IdAcceleratorMap id_accelerators_;
// Keyboard shortcut IDs to hotkeys map for unregistration.
IdHotKeyRefMap id_hot_key_refs_;
// Event tap for intercepting mac media keys.
CFMachPortRef event_tap_;
CFRunLoopSourceRef event_tap_source_;
// Event handler for keyboard shortcut hot keys.
EventHandlerRef event_handler_;
DISALLOW_COPY_AND_ASSIGN(GlobalShortcutListenerMac);
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_MAC_H_

View File

@@ -0,0 +1,383 @@
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/extensions/global_shortcut_listener_mac.h"
#include <ApplicationServices/ApplicationServices.h>
#import <Cocoa/Cocoa.h>
#include <IOKit/hidsystem/ev_keymap.h>
#import "base/mac/foundation_util.h"
#include "content/public/browser/browser_thread.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/events/event.h"
#import "ui/events/keycodes/keyboard_code_conversion_mac.h"
using content::BrowserThread;
using extensions::GlobalShortcutListenerMac;
namespace {
// The media keys subtype. No official docs found, but widely known.
// http://lists.apple.com/archives/cocoa-dev/2007/Aug/msg00499.html
const int kSystemDefinedEventMediaKeysSubtype = 8;
ui::KeyboardCode MediaKeyCodeToKeyboardCode(int key_code) {
switch (key_code) {
case NX_KEYTYPE_PLAY:
return ui::VKEY_MEDIA_PLAY_PAUSE;
case NX_KEYTYPE_PREVIOUS:
case NX_KEYTYPE_REWIND:
return ui::VKEY_MEDIA_PREV_TRACK;
case NX_KEYTYPE_NEXT:
case NX_KEYTYPE_FAST:
return ui::VKEY_MEDIA_NEXT_TRACK;
}
return ui::VKEY_UNKNOWN;
}
bool IsMediaKey(const ui::Accelerator& accelerator) {
if (accelerator.modifiers() != 0)
return false;
return (accelerator.key_code() == ui::VKEY_MEDIA_NEXT_TRACK ||
accelerator.key_code() == ui::VKEY_MEDIA_PREV_TRACK ||
accelerator.key_code() == ui::VKEY_MEDIA_PLAY_PAUSE ||
accelerator.key_code() == ui::VKEY_MEDIA_STOP);
}
} // namespace
namespace extensions {
// static
GlobalShortcutListener* GlobalShortcutListener::GetInstance() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
static GlobalShortcutListenerMac* instance =
new GlobalShortcutListenerMac();
return instance;
}
GlobalShortcutListenerMac::GlobalShortcutListenerMac()
: is_listening_(false),
hot_key_id_(0),
event_tap_(NULL),
event_tap_source_(NULL),
event_handler_(NULL) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
GlobalShortcutListenerMac::~GlobalShortcutListenerMac() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// By this point, UnregisterAccelerator should have been called for all
// keyboard shortcuts. Still we should clean up.
if (is_listening_)
StopListening();
// If keys are still registered, make sure we stop the tap. Again, this
// should never happen.
if (IsAnyMediaKeyRegistered())
StopWatchingMediaKeys();
if (IsAnyHotKeyRegistered())
StopWatchingHotKeys();
}
void GlobalShortcutListenerMac::StartListening() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!accelerator_ids_.empty());
DCHECK(!id_accelerators_.empty());
DCHECK(!is_listening_);
is_listening_ = true;
}
void GlobalShortcutListenerMac::StopListening() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(accelerator_ids_.empty()); // Make sure the set is clean.
DCHECK(id_accelerators_.empty());
DCHECK(is_listening_);
is_listening_ = false;
}
void GlobalShortcutListenerMac::OnHotKeyEvent(EventHotKeyID hot_key_id) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// This hot key should be registered.
DCHECK(id_accelerators_.find(hot_key_id.id) != id_accelerators_.end());
// Look up the accelerator based on this hot key ID.
const ui::Accelerator& accelerator = id_accelerators_[hot_key_id.id];
NotifyKeyPressed(accelerator);
}
bool GlobalShortcutListenerMac::OnMediaKeyEvent(int media_key_code) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
ui::KeyboardCode key_code = MediaKeyCodeToKeyboardCode(media_key_code);
// Create an accelerator corresponding to the keyCode.
ui::Accelerator accelerator(key_code, 0);
// Look for a match with a bound hot_key.
if (accelerator_ids_.find(accelerator) != accelerator_ids_.end()) {
// If matched, callback to the event handling system.
NotifyKeyPressed(accelerator);
return true;
}
return false;
}
bool GlobalShortcutListenerMac::RegisterAcceleratorImpl(
const ui::Accelerator& accelerator) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(accelerator_ids_.find(accelerator) == accelerator_ids_.end());
if (IsMediaKey(accelerator)) {
if (!IsAnyMediaKeyRegistered()) {
// If this is the first media key registered, start the event tap.
StartWatchingMediaKeys();
}
} else {
// Register hot_key if they are non-media keyboard shortcuts.
if (!RegisterHotKey(accelerator, hot_key_id_))
return false;
if (!IsAnyHotKeyRegistered()) {
StartWatchingHotKeys();
}
}
// Store the hotkey-ID mappings we will need for lookup later.
id_accelerators_[hot_key_id_] = accelerator;
accelerator_ids_[accelerator] = hot_key_id_;
++hot_key_id_;
return true;
}
void GlobalShortcutListenerMac::UnregisterAcceleratorImpl(
const ui::Accelerator& accelerator) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(accelerator_ids_.find(accelerator) != accelerator_ids_.end());
// Unregister the hot_key if it's a keyboard shortcut.
if (!IsMediaKey(accelerator))
UnregisterHotKey(accelerator);
// Remove hot_key from the mappings.
KeyId key_id = accelerator_ids_[accelerator];
id_accelerators_.erase(key_id);
accelerator_ids_.erase(accelerator);
if (IsMediaKey(accelerator)) {
// If we unregistered a media key, and now no media keys are registered,
// stop the media key tap.
if (!IsAnyMediaKeyRegistered())
StopWatchingMediaKeys();
} else {
// If we unregistered a hot key, and no more hot keys are registered, remove
// the hot key handler.
if (!IsAnyHotKeyRegistered()) {
StopWatchingHotKeys();
}
}
}
bool GlobalShortcutListenerMac::RegisterHotKey(
const ui::Accelerator& accelerator, KeyId hot_key_id) {
EventHotKeyID event_hot_key_id;
// Signature uniquely identifies the application that owns this hot_key.
event_hot_key_id.signature = base::mac::CreatorCodeForApplication();
event_hot_key_id.id = hot_key_id;
// Translate ui::Accelerator modifiers to cmdKey, altKey, etc.
int modifiers = 0;
modifiers |= (accelerator.IsShiftDown() ? shiftKey : 0);
modifiers |= (accelerator.IsCtrlDown() ? controlKey : 0);
modifiers |= (accelerator.IsAltDown() ? optionKey : 0);
modifiers |= (accelerator.IsCmdDown() ? cmdKey : 0);
int key_code = ui::MacKeyCodeForWindowsKeyCode(accelerator.key_code(), 0,
NULL, NULL);
// Register the event hot key.
EventHotKeyRef hot_key_ref;
OSStatus status = RegisterEventHotKey(key_code, modifiers, event_hot_key_id,
GetApplicationEventTarget(), 0, &hot_key_ref);
if (status != noErr)
return false;
id_hot_key_refs_[hot_key_id] = hot_key_ref;
return true;
}
void GlobalShortcutListenerMac::UnregisterHotKey(
const ui::Accelerator& accelerator) {
// Ensure this accelerator is already registered.
DCHECK(accelerator_ids_.find(accelerator) != accelerator_ids_.end());
// Get the ref corresponding to this accelerator.
KeyId key_id = accelerator_ids_[accelerator];
EventHotKeyRef ref = id_hot_key_refs_[key_id];
// Unregister the event hot key.
UnregisterEventHotKey(ref);
// Remove the event from the mapping.
id_hot_key_refs_.erase(key_id);
}
void GlobalShortcutListenerMac::StartWatchingMediaKeys() {
// Make sure there's no existing event tap.
DCHECK(event_tap_ == NULL);
DCHECK(event_tap_source_ == NULL);
// Add an event tap to intercept the system defined media key events.
event_tap_ = CGEventTapCreate(kCGSessionEventTap,
kCGHeadInsertEventTap,
kCGEventTapOptionDefault,
CGEventMaskBit(NX_SYSDEFINED),
EventTapCallback,
this);
if (event_tap_ == NULL) {
LOG(ERROR) << "Error: failed to create event tap.";
return;
}
event_tap_source_ = CFMachPortCreateRunLoopSource(kCFAllocatorSystemDefault,
event_tap_, 0);
if (event_tap_source_ == NULL) {
LOG(ERROR) << "Error: failed to create new run loop source.";
return;
}
CFRunLoopAddSource(CFRunLoopGetCurrent(), event_tap_source_,
kCFRunLoopCommonModes);
}
void GlobalShortcutListenerMac::StopWatchingMediaKeys() {
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), event_tap_source_,
kCFRunLoopCommonModes);
// Ensure both event tap and source are initialized.
DCHECK(event_tap_ != NULL);
DCHECK(event_tap_source_ != NULL);
// Invalidate the event tap.
CFMachPortInvalidate(event_tap_);
CFRelease(event_tap_);
event_tap_ = NULL;
// Release the event tap source.
CFRelease(event_tap_source_);
event_tap_source_ = NULL;
}
void GlobalShortcutListenerMac::StartWatchingHotKeys() {
DCHECK(!event_handler_);
EventHandlerUPP hot_key_function = NewEventHandlerUPP(HotKeyHandler);
EventTypeSpec event_type;
event_type.eventClass = kEventClassKeyboard;
event_type.eventKind = kEventHotKeyPressed;
InstallApplicationEventHandler(
hot_key_function, 1, &event_type, this, &event_handler_);
}
void GlobalShortcutListenerMac::StopWatchingHotKeys() {
DCHECK(event_handler_);
RemoveEventHandler(event_handler_);
event_handler_ = NULL;
}
bool GlobalShortcutListenerMac::IsAnyMediaKeyRegistered() {
// Iterate through registered accelerators, looking for media keys.
AcceleratorIdMap::iterator it;
for (it = accelerator_ids_.begin(); it != accelerator_ids_.end(); ++it) {
if (IsMediaKey(it->first))
return true;
}
return false;
}
bool GlobalShortcutListenerMac::IsAnyHotKeyRegistered() {
AcceleratorIdMap::iterator it;
for (it = accelerator_ids_.begin(); it != accelerator_ids_.end(); ++it) {
if (!IsMediaKey(it->first))
return true;
}
return false;
}
// Processed events should propagate if they aren't handled by any listeners.
// For events that don't matter, this handler should return as quickly as
// possible.
// Returning event causes the event to propagate to other applications.
// Returning NULL prevents the event from propagating.
// static
CGEventRef GlobalShortcutListenerMac::EventTapCallback(
CGEventTapProxy proxy, CGEventType type, CGEventRef event, void* refcon) {
GlobalShortcutListenerMac* shortcut_listener =
static_cast<GlobalShortcutListenerMac*>(refcon);
// Handle the timeout case by re-enabling the tap.
if (type == kCGEventTapDisabledByTimeout) {
CGEventTapEnable(shortcut_listener->event_tap_, TRUE);
return event;
}
// Convert the CGEvent to an NSEvent for access to the data1 field.
NSEvent* ns_event = [NSEvent eventWithCGEvent:event];
if (ns_event == nil) {
return event;
}
// Ignore events that are not system defined media keys.
if (type != NX_SYSDEFINED ||
[ns_event type] != NSSystemDefined ||
[ns_event subtype] != kSystemDefinedEventMediaKeysSubtype) {
return event;
}
NSInteger data1 = [ns_event data1];
// Ignore media keys that aren't previous, next and play/pause.
// Magical constants are from http://weblog.rogueamoeba.com/2007/09/29/
int key_code = (data1 & 0xFFFF0000) >> 16;
if (key_code != NX_KEYTYPE_PLAY && key_code != NX_KEYTYPE_NEXT &&
key_code != NX_KEYTYPE_PREVIOUS && key_code != NX_KEYTYPE_FAST &&
key_code != NX_KEYTYPE_REWIND) {
return event;
}
int key_flags = data1 & 0x0000FFFF;
bool is_key_pressed = ((key_flags & 0xFF00) >> 8) == 0xA;
// If the key wasn't pressed (eg. was released), ignore this event.
if (!is_key_pressed)
return event;
// Now we have a media key that we care about. Send it to the caller.
bool was_handled = shortcut_listener->OnMediaKeyEvent(key_code);
// Prevent event from proagating to other apps if handled by Chrome.
if (was_handled)
return NULL;
// By default, pass the event through.
return event;
}
// static
OSStatus GlobalShortcutListenerMac::HotKeyHandler(
EventHandlerCallRef next_handler, EventRef event, void* user_data) {
// Extract the hotkey from the event.
EventHotKeyID hot_key_id;
OSStatus result = GetEventParameter(event, kEventParamDirectObject,
typeEventHotKeyID, NULL, sizeof(hot_key_id), NULL, &hot_key_id);
if (result != noErr)
return result;
GlobalShortcutListenerMac* shortcut_listener =
static_cast<GlobalShortcutListenerMac*>(user_data);
shortcut_listener->OnHotKeyEvent(hot_key_id);
return noErr;
}
} // namespace extensions

View File

@@ -0,0 +1,105 @@
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/extensions/global_shortcut_listener_win.h"
#include "base/win/win_util.h"
#include "content/public/browser/browser_thread.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/events/event_constants.h"
#include "ui/events/keycodes/keyboard_code_conversion_win.h"
using content::BrowserThread;
namespace extensions {
// static
GlobalShortcutListener* GlobalShortcutListener::GetInstance() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
static GlobalShortcutListenerWin* instance =
new GlobalShortcutListenerWin();
return instance;
}
GlobalShortcutListenerWin::GlobalShortcutListenerWin()
: is_listening_(false) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
GlobalShortcutListenerWin::~GlobalShortcutListenerWin() {
if (is_listening_)
StopListening();
}
void GlobalShortcutListenerWin::StartListening() {
DCHECK(!is_listening_); // Don't start twice.
DCHECK(!hotkey_ids_.empty()); // Also don't start if no hotkey is registered.
gfx::SingletonHwnd::GetInstance()->AddObserver(this);
is_listening_ = true;
}
void GlobalShortcutListenerWin::StopListening() {
DCHECK(is_listening_); // No point if we are not already listening.
DCHECK(hotkey_ids_.empty()); // Make sure the map is clean before ending.
gfx::SingletonHwnd::GetInstance()->RemoveObserver(this);
is_listening_ = false;
}
void GlobalShortcutListenerWin::OnWndProc(HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam) {
if (message != WM_HOTKEY)
return;
int key_code = HIWORD(lparam);
int modifiers = 0;
modifiers |= (LOWORD(lparam) & MOD_SHIFT) ? ui::EF_SHIFT_DOWN : 0;
modifiers |= (LOWORD(lparam) & MOD_ALT) ? ui::EF_ALT_DOWN : 0;
modifiers |= (LOWORD(lparam) & MOD_CONTROL) ? ui::EF_CONTROL_DOWN : 0;
ui::Accelerator accelerator(
ui::KeyboardCodeForWindowsKeyCode(key_code), modifiers);
NotifyKeyPressed(accelerator);
}
bool GlobalShortcutListenerWin::RegisterAcceleratorImpl(
const ui::Accelerator& accelerator) {
DCHECK(hotkey_ids_.find(accelerator) == hotkey_ids_.end());
int modifiers = 0;
modifiers |= accelerator.IsShiftDown() ? MOD_SHIFT : 0;
modifiers |= accelerator.IsCtrlDown() ? MOD_CONTROL : 0;
modifiers |= accelerator.IsAltDown() ? MOD_ALT : 0;
static int hotkey_id = 0;
bool success = !!RegisterHotKey(
gfx::SingletonHwnd::GetInstance()->hwnd(),
hotkey_id,
modifiers,
accelerator.key_code());
if (!success) {
// Most likely error: 1409 (Hotkey already registered).
return false;
}
hotkey_ids_[accelerator] = hotkey_id++;
return true;
}
void GlobalShortcutListenerWin::UnregisterAcceleratorImpl(
const ui::Accelerator& accelerator) {
HotkeyIdMap::iterator it = hotkey_ids_.find(accelerator);
DCHECK(it != hotkey_ids_.end());
bool success = !!UnregisterHotKey(
gfx::SingletonHwnd::GetInstance()->hwnd(), it->second);
// This call should always succeed, as long as we pass in the right HWND and
// an id we've used to register before.
DCHECK(success);
hotkey_ids_.erase(it);
}
} // namespace extensions

View File

@@ -0,0 +1,51 @@
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_WIN_H_
#define CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_WIN_H_
#include <windows.h>
#include "chrome/browser/extensions/global_shortcut_listener.h"
#include "ui/gfx/win/singleton_hwnd.h"
namespace extensions {
// Windows-specific implementation of the GlobalShortcutListener class that
// listens for global shortcuts. Handles setting up a keyboard hook and
// forwarding its output to the base class for processing.
class GlobalShortcutListenerWin : public GlobalShortcutListener,
public gfx::SingletonHwnd::Observer {
public:
GlobalShortcutListenerWin();
virtual ~GlobalShortcutListenerWin();
private:
// The implementation of our Window Proc, called by SingletonHwnd.
virtual void OnWndProc(HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam) OVERRIDE;
// GlobalShortcutListener implementation.
virtual void StartListening() OVERRIDE;
virtual void StopListening() OVERRIDE;
virtual bool RegisterAcceleratorImpl(
const ui::Accelerator& accelerator) OVERRIDE;
virtual void UnregisterAcceleratorImpl(
const ui::Accelerator& accelerator) OVERRIDE;
// Whether this object is listening for global shortcuts.
bool is_listening_;
// A map of registered accelerators and their registration ids.
typedef std::map<ui::Accelerator, int> HotkeyIdMap;
HotkeyIdMap hotkey_ids_;
DISALLOW_COPY_AND_ASSIGN(GlobalShortcutListenerWin);
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_WIN_H_

View File

@@ -0,0 +1,158 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/extensions/global_shortcut_listener_x11.h"
#include "content/public/browser/browser_thread.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/events/keycodes/keyboard_code_conversion_x.h"
#include "ui/events/platform/x11/x11_event_source.h"
#include "ui/gfx/x/x11_error_tracker.h"
#include "ui/gfx/x/x11_types.h"
using content::BrowserThread;
namespace {
// The modifiers masks used for grabing keys. Due to XGrabKey only working on
// exact modifiers, we need to grab all key combination including zero or more
// of the following: Num lock, Caps lock and Scroll lock. So that we can make
// sure the behavior of global shortcuts is consistent on all platforms.
const unsigned int kModifiersMasks[] = {
0, // No additional modifier.
Mod2Mask, // Num lock
LockMask, // Caps lock
Mod5Mask, // Scroll lock
Mod2Mask | LockMask,
Mod2Mask | Mod5Mask,
LockMask | Mod5Mask,
Mod2Mask | LockMask | Mod5Mask
};
int GetNativeModifiers(const ui::Accelerator& accelerator) {
int modifiers = 0;
modifiers |= accelerator.IsShiftDown() ? ShiftMask : 0;
modifiers |= accelerator.IsCtrlDown() ? ControlMask : 0;
modifiers |= accelerator.IsAltDown() ? Mod1Mask : 0;
return modifiers;
}
} // namespace
namespace extensions {
// static
GlobalShortcutListener* GlobalShortcutListener::GetInstance() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
static GlobalShortcutListenerX11* instance =
new GlobalShortcutListenerX11();
return instance;
}
GlobalShortcutListenerX11::GlobalShortcutListenerX11()
: is_listening_(false),
x_display_(gfx::GetXDisplay()),
x_root_window_(DefaultRootWindow(x_display_)) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
GlobalShortcutListenerX11::~GlobalShortcutListenerX11() {
if (is_listening_)
StopListening();
}
void GlobalShortcutListenerX11::StartListening() {
DCHECK(!is_listening_); // Don't start twice.
DCHECK(!registered_hot_keys_.empty()); // Also don't start if no hotkey is
// registered.
ui::X11EventSource::GetInstance()->AddPlatformEventDispatcher(this);
is_listening_ = true;
}
void GlobalShortcutListenerX11::StopListening() {
DCHECK(is_listening_); // No point if we are not already listening.
DCHECK(registered_hot_keys_.empty()); // Make sure the set is clean before
// ending.
ui::X11EventSource::GetInstance()->RemovePlatformEventDispatcher(this);
is_listening_ = false;
}
bool GlobalShortcutListenerX11::CanDispatchEvent(
const ui::PlatformEvent& event) {
return event->type == KeyPress;
}
uint32_t GlobalShortcutListenerX11::DispatchEvent(
const ui::PlatformEvent& event) {
CHECK_EQ(KeyPress, event->type);
OnXKeyPressEvent(event);
return ui::POST_DISPATCH_NONE;
}
bool GlobalShortcutListenerX11::RegisterAcceleratorImpl(
const ui::Accelerator& accelerator) {
DCHECK(registered_hot_keys_.find(accelerator) == registered_hot_keys_.end());
int modifiers = GetNativeModifiers(accelerator);
KeyCode keycode = XKeysymToKeycode(x_display_,
XKeysymForWindowsKeyCode(accelerator.key_code(), false));
gfx::X11ErrorTracker err_tracker;
// Because XGrabKey only works on the exact modifiers mask, we should register
// our hot keys with modifiers that we want to ignore, including Num lock,
// Caps lock, Scroll lock. See comment about |kModifiersMasks|.
for (size_t i = 0; i < arraysize(kModifiersMasks); ++i) {
XGrabKey(x_display_, keycode, modifiers | kModifiersMasks[i],
x_root_window_, False, GrabModeAsync, GrabModeAsync);
}
if (err_tracker.FoundNewError()) {
// We may have part of the hotkeys registered, clean up.
for (size_t i = 0; i < arraysize(kModifiersMasks); ++i) {
XUngrabKey(x_display_, keycode, modifiers | kModifiersMasks[i],
x_root_window_);
}
return false;
}
registered_hot_keys_.insert(accelerator);
return true;
}
void GlobalShortcutListenerX11::UnregisterAcceleratorImpl(
const ui::Accelerator& accelerator) {
DCHECK(registered_hot_keys_.find(accelerator) != registered_hot_keys_.end());
int modifiers = GetNativeModifiers(accelerator);
KeyCode keycode = XKeysymToKeycode(x_display_,
XKeysymForWindowsKeyCode(accelerator.key_code(), false));
for (size_t i = 0; i < arraysize(kModifiersMasks); ++i) {
XUngrabKey(x_display_, keycode, modifiers | kModifiersMasks[i],
x_root_window_);
}
registered_hot_keys_.erase(accelerator);
}
void GlobalShortcutListenerX11::OnXKeyPressEvent(::XEvent* x_event) {
DCHECK(x_event->type == KeyPress);
int modifiers = 0;
modifiers |= (x_event->xkey.state & ShiftMask) ? ui::EF_SHIFT_DOWN : 0;
modifiers |= (x_event->xkey.state & ControlMask) ? ui::EF_CONTROL_DOWN : 0;
modifiers |= (x_event->xkey.state & Mod1Mask) ? ui::EF_ALT_DOWN : 0;
ui::Accelerator accelerator(
ui::KeyboardCodeFromXKeyEvent(x_event), modifiers);
if (registered_hot_keys_.find(accelerator) != registered_hot_keys_.end())
NotifyKeyPressed(accelerator);
}
} // namespace extensions

View File

@@ -0,0 +1,57 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_X11_H_
#define CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_X11_H_
#include <X11/Xlib.h>
#include <set>
#include "chrome/browser/extensions/global_shortcut_listener.h"
#include "ui/events/platform/platform_event_dispatcher.h"
namespace extensions {
// X11-specific implementation of the GlobalShortcutListener class that
// listens for global shortcuts. Handles basic keyboard intercepting and
// forwards its output to the base class for processing.
class GlobalShortcutListenerX11 : public GlobalShortcutListener,
public ui::PlatformEventDispatcher {
public:
GlobalShortcutListenerX11();
virtual ~GlobalShortcutListenerX11();
// ui::PlatformEventDispatcher implementation.
virtual bool CanDispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
virtual uint32_t DispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
private:
// GlobalShortcutListener implementation.
virtual void StartListening() OVERRIDE;
virtual void StopListening() OVERRIDE;
virtual bool RegisterAcceleratorImpl(
const ui::Accelerator& accelerator) OVERRIDE;
virtual void UnregisterAcceleratorImpl(
const ui::Accelerator& accelerator) OVERRIDE;
// Invoked when a global shortcut is pressed.
void OnXKeyPressEvent(::XEvent* x_event);
// Whether this object is listening for global shortcuts.
bool is_listening_;
// The x11 default display and the native root window.
::Display* x_display_;
::Window x_root_window_;
// A set of registered accelerators.
typedef std::set<ui::Accelerator> RegisteredHotKeys;
RegisteredHotKeys registered_hot_keys_;
DISALLOW_COPY_AND_ASSIGN(GlobalShortcutListenerX11);
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_GLOBAL_SHORTCUT_LISTENER_X11_H_

View File

@@ -7,7 +7,6 @@
}],
['OS=="win" and (MSVS_VERSION=="2013e" or MSVS_VERSION=="2012e" or MSVS_VERSION=="2010e")', {
'msvs_express': 1,
'windows_driver_kit_path%': 'C:/WinDDK/7600.16385.1',
},{
'msvs_express': 0,
}],
@@ -202,33 +201,6 @@
},
},
}], # clang==1
# Using Visual Studio Express.
['msvs_express==1', {
'target_defaults': {
'defines!': [
'_SECURE_ATL',
],
'msvs_settings': {
'VCLibrarianTool': {
'AdditionalLibraryDirectories': [
'<(windows_driver_kit_path)/lib/ATL/i386',
],
},
'VCLinkerTool': {
'AdditionalLibraryDirectories': [
'<(windows_driver_kit_path)/lib/ATL/i386',
],
'AdditionalDependencies': [
'atlthunk.lib',
],
},
},
'msvs_system_include_dirs': [
'<(windows_driver_kit_path)/inc/atl71',
'<(windows_driver_kit_path)/inc/mfc42',
],
},
}], # msvs_express==1
# The breakdpad on Windows assumes Debug_x64 and Release_x64 configurations.
['OS=="win"', {
'target_defaults': {

View File

@@ -8,13 +8,16 @@
* [Synopsis](api/synopsis.md)
* [Process object](api/process.md)
* [Supported Chrome command line switches](api/chrome-command-line-switches.md)
Modules for browser side:
* [app](api/app.md)
* [auto-updater](api/auto-updater.md)
* [browser-window](api/browser-window.md)
* [content-tracing](api/content-tracing.md)
* [dialog](api/dialog.md)
* [global-shortcut](api/global-shortcut.md)
* [ipc (browser)](api/ipc-browser.md)
* [menu](api/menu.md)
* [menu-item](api/menu-item.md)

41
docs/api/accelerator.md Normal file
View File

@@ -0,0 +1,41 @@
# Accelerator
An accelerator is string that represents a keyboard shortcut, it can contain
multiple modifiers and key codes, combined by the `+` character.
Examples:
* `Command+A`
* `Ctrl+Shift+Z`
## Platform notice
On Linux and Windows, the `Command` key would not have any effect, you can
use `CommandOrControl` which represents `Command` on OS X and `Control` on
Linux and Windows to define some accelerators.
## Available modifiers
* `Command` (or `Cmd` for short)
* `Control` (or `Ctrl` for short)
* `CommandOrControl` (or `CmdOrCtrl` for short)
* `Alt`
* `Shift`
## Available key codes
* `0` to `9`
* `A` to `Z`
* `F1` to `F24`
* Punctuations like `~`, `!`, `@`, `#`, `$`, etc.
* `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`

View File

@@ -87,6 +87,14 @@ executed. It is possible that a window cancels the quitting by returning
Quit the application directly, it will not try to close all windows so cleanup
code will not run.
## app.getDataPath()
Returns the path for storing configuration files, with app name appended.
* `%APPDATA%\MyAppName` on Windows
* `~/.config/MyAppName` on Linux
* `~/Library/Application Support/MyAppName` on OS X
## app.getVersion()
Returns the version of loaded application, if no version is found in

View File

@@ -5,6 +5,10 @@
The `auto-updater` module is a simple wrap around the
[Squirrel.Mac](https://github.com/Squirrel/Squirrel.Mac) framework.
Squirrel.Mac requires that your `.app` folder is signed using the
[codesign](https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/codesign.1.html)
utility for updates to be installed.
## Squirrel
Squirrel is an OS X framework focused on making application updates **as safe

View File

@@ -18,6 +18,9 @@ win.show();
You can also create a window without chrome by using
[Frameless Window](frameless-window.md) API.
Security strategy of web pages showed by `BrowserWindow` is a bit different from
normal browsers, see [Web Security](web-security.md) for more.
## Class: BrowserWindow
`BrowserWindow` is an
@@ -51,10 +54,15 @@ You can also create a window without chrome by using
* `show` Boolean - Whether window should be shown when created
* `frame` Boolean - Specify `false` to create a
[Frameless Window](frameless-window.md)
* `node-integration` String - Can be `all`, `except-iframe`,
`manual-enable-iframe` or `disable`.
* `node-integration` String - Default value is `except-iframe`, can also be
`all`, `manual-enable-iframe` or `disable`, see
[Web Security](web-security.md) for more informations.
* `accept-first-mouse` Boolean - Whether the web view accepts a single
mouse-down event that simultaneously activates the window
* `auto-hide-menu-bar` Boolean - Auto hide the menu bar unless the `Alt`
key is pressed.
* `enable-larger-than-screen` Boolean - Enable the window to be resized larger
than screen.
* `web-preferences` Object - Settings of web page's features
* `javascript` Boolean
* `web-security` Boolean
@@ -63,7 +71,6 @@ You can also create a window without chrome by using
* `text-areas-are-resizable` Boolean
* `webgl` Boolean
* `webaudio` Boolean
* `accelerated-compositing` Boolean
* `plugins` Boolean - Whether plugins should be enabled, currently only
`NPAPI` plugins are supported.
* `extra-plugin-dirs` Array - Array of paths that would be searched for
@@ -76,35 +83,6 @@ Creates a new `BrowserWindow` with native properties set by the `options`.
Usually you only need to set the `width` and `height`, other properties will
have decent default values.
By default the `node-integration` option is `except-iframe`, which means node
integration is disabled in all iframes, . You can also set it to `all`, with
which node integration is available to the main page and all its iframes, or
`manual-enable-iframe`, which is like `except-iframe`, but would enable iframes
whose name is suffixed by `-enable-node-integration`. And setting to `disable`
would disable the node integration in both the main page and its iframes.
An example of enable node integration in iframe with `node-integration` set to
`manual-enable-iframe`:
```html
<!-- iframe with node integration enabled -->
<iframe name="gh-enable-node-integration" src="https://github.com"></iframe>
<!-- iframe with node integration disabled -->
<iframe src="http://jandan.net"></iframe>
```
And in atom-shell, the security limitation of iframe is stricter than normal
browser, by default iframe is sandboxed with all permissions except the
`allow-same-origin`, which means iframe could not access parent's js context.
If you want to enable things like `parent.window.process.exit()` in iframe,
you should explicitly set `sandbox` to `none`:
```html
<iframe sandbox="none" src="https://github.com"></iframe>
```
### Event: 'page-title-updated'
* `event` Event
@@ -252,6 +230,10 @@ the Dock.
Restores the window from minimized state to its previous state.
### BrowserWindow.isMinimized()
Returns whether the window is minimized.
### BrowserWindow.setFullScreen(flag)
* `flag` Boolean

View File

@@ -0,0 +1,45 @@
# Supported Chrome command line switches
Following command lines switches in Chrome browser are also Supported in
atom-shell, you can use [app.commandLine.appendSwitch](append-switch) to append
them in your app's main script before the [ready](ready) event of [app](app)
module is emitted:
```javascript
var app = require('app');
app.commandLine.appendSwitch('remote-debugging-port', '88315');
app.commandLine.appendSwitch('host-rules', 'MAP * 127.0.0.1');
app.on('ready', function() {
});
```
## --remote-debugging-port=`port`
Enables remote debug over HTTP on the specified `port`.
## --host-rules=`rules`
Comma-separated list of `rules` that control how hostnames are mapped.
For example:
* `MAP * 127.0.0.1` Forces all hostnames to be mapped to 127.0.0.1
* `MAP *.google.com proxy` Forces all google.com subdomains to be resolved to
"proxy".
* `MAP test.com [::1]:77` Forces "test.com" to resolve to IPv6 loopback. Will
also force the port of the resulting socket address to be 77.
* `MAP * baz, EXCLUDE www.google.com` Remaps everything to "baz", except for
"www.google.com".
These mappings apply to the endpoint host in a net request (the TCP connect
and host resolver in a direct connection, and the `CONNECT` in an http proxy
connection, and the endpoint host in a `SOCKS` proxy connection).
## --host-resolver-rules=`rules`
Like `--host-rules` but these `rules` only apply to the host resolver.
[app](app.md)
[append-switch](app.md#appcommandlineappendswitchswitch-value)
[ready](app.md##event-ready)

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