diff --git a/atom/browser/api/atom_api_dialog.cc b/atom/browser/api/atom_api_dialog.cc index 0a544c5646..965b928783 100644 --- a/atom/browser/api/atom_api_dialog.cc +++ b/atom/browser/api/atom_api_dialog.cc @@ -66,6 +66,10 @@ void ShowMessageBox(int type, } } +void SetSheetOffset(atom::NativeWindow* window, const double offset) { + window->SetSheetOffset(offset); +} + void ShowOpenDialog(const std::string& title, const base::FilePath& default_path, const file_dialog::Filters& filters, @@ -112,6 +116,7 @@ void Initialize(v8::Local exports, v8::Local unused, dict.SetMethod("showMessageBox", &ShowMessageBox); dict.SetMethod("showErrorBox", &atom::ShowErrorBox); dict.SetMethod("showOpenDialog", &ShowOpenDialog); + dict.SetMethod("setSheetOffset", &SetSheetOffset); dict.SetMethod("showSaveDialog", &ShowSaveDialog); } diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index d7ed86165b..37bf8f687e 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -201,6 +201,14 @@ gfx::Size NativeWindow::GetContentSize() { return WindowSizeToContentSize(GetSize()); } +void NativeWindow::SetSheetOffset(const double offset) { + sheet_offset_ = offset; +} + +double NativeWindow::GetSheetOffset() { + return sheet_offset_; +} + void NativeWindow::SetSizeConstraints( const extensions::SizeConstraints& window_constraints) { extensions::SizeConstraints content_constraints; diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index f91d041c05..d60ac209d8 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -190,6 +190,9 @@ class NativeWindow : public base::SupportsUserData, gfx::Size GetAspectRatioExtraSize(); void SetAspectRatio(double aspect_ratio, const gfx::Size& extra_size); + void SetSheetOffset(const double offset); + double GetSheetOffset(); + base::WeakPtr GetWeakPtr() { return weak_factory_.GetWeakPtr(); } @@ -326,6 +329,9 @@ class NativeWindow : public base::SupportsUserData, // it should be cancelled when we can prove that the window is responsive. base::CancelableClosure window_unresposive_closure_; + // Used to display sheets at the appropriate vertical offset + double sheet_offset_; + // Used to maintain the aspect ratio of a view which is inside of the // content view. double aspect_ratio_; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index b24e828e57..dc2929f82e 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -243,6 +243,12 @@ bool ScopedDisableResize::disable_resize_ = false; return NO; } +- (NSRect)window:(NSWindow *)window willPositionSheet:(NSWindow *)sheet usingRect:(NSRect)rect { + rect.origin.y = window.contentView.frame.size.height - shell_->GetSheetOffset(); + return rect; +} + + @end @interface AtomNSWindow : NSWindow { diff --git a/docs/api/dialog.md b/docs/api/dialog.md index 9fbc20dd83..f36850f310 100644 --- a/docs/api/dialog.md +++ b/docs/api/dialog.md @@ -18,10 +18,6 @@ The Dialog is opened from Electron's main thread. If you want to use the dialog const dialog = require('electron').remote.dialog; ``` -**Note for OS X**: If you want to present dialogs as sheets, the only thing you -have to do is provide a `BrowserWindow` reference in the `browserWindow` -parameter. - ## Methods The `dialog` module has the following methods: @@ -125,3 +121,27 @@ This API can be called safely before the `ready` event the `app` module emits, it is usually used to report errors in early stage of startup. If called before the app `ready`event on Linux, the message will be emitted to stderr, and no GUI dialog will appear. + + +## Sheets + +On Mac OS X, dialogs are presented as sheets attached to a window if you provide +a `BrowserWindow` reference in the `browserWindow` parameter, or modals if no +window is provided. + +### `dialog.setSheetOffset(browserWindow, offset)` + +* `browserWindow` BrowserWindow (optional) + +Changes the attachment point for sheets on Mac OS X. By default, sheets are attached +just below the window frame, but you may want to display them beneath a HTML-rendered +toolbar. For example: +``` +const {remote} = require('electron'); +const browserWindow = remote.getCurrentWindow(); + +var toolbarRect = document.getElementById('toolbar').getBoundingClientRect(); +remote.dialog.setSheetOffset(browserWindow, toolbarRect.height); + +... show dialog ... +``` diff --git a/lib/browser/api/dialog.js b/lib/browser/api/dialog.js index 6669d8cab8..f88d25cfbb 100644 --- a/lib/browser/api/dialog.js +++ b/lib/browser/api/dialog.js @@ -49,7 +49,11 @@ var checkAppInitialized = function () { } module.exports = { - showOpenDialog: function (...args) { + setSheetOffset: function(window, offset) { + return binding.setSheetOffset(window, offset) + }, + + showOpenDialog: function(...args) { var prop, properties, value, wrappedCallback checkAppInitialized() let [window, options, callback] = parseArgs.apply(null, args)