Allow sheets to be attached at a custom offset #4679
authorBen Gotow <bengotow@gmail.com>
Sun, 27 Mar 2016 01:12:25 +0000 (18:12 -0700)
committerBen Gotow <bengotow@gmail.com>
Sat, 16 Apr 2016 14:16:43 +0000 (10:16 -0400)
Adds a new "setSheetOffset" API to the `dialog` module, which allows you to change the attachment point for sheets on Mac OS X. I put the API on the dialog module, even though Mac OS X requires that the native window hold and return the desired offset.

1. I was originally hoping to make this an argument on the actual dialog.show* calls, but it seems the parameter set is defined in `libchromiumcontent` and I wasn't sure it would be appropriate to add there?

2.  The API could also be on the BrowserWindow (eg `BrowserWindow.setSheetOffset`). I don't have a strong preference, but I think it's more discoverable on the `dialog` module.

atom/browser/api/atom_api_dialog.cc
atom/browser/native_window.cc
atom/browser/native_window.h
atom/browser/native_window_mac.mm
docs/api/dialog.md
lib/browser/api/dialog.js

index 0a544c5..965b928 100644 (file)
@@ -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<v8::Object> exports, v8::Local<v8::Value> unused,
   dict.SetMethod("showMessageBox", &ShowMessageBox);
   dict.SetMethod("showErrorBox", &atom::ShowErrorBox);
   dict.SetMethod("showOpenDialog", &ShowOpenDialog);
+  dict.SetMethod("setSheetOffset", &SetSheetOffset);
   dict.SetMethod("showSaveDialog", &ShowSaveDialog);
 }
 
index d7ed861..37bf8f6 100644 (file)
@@ -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;
index f91d041..d60ac20 100644 (file)
@@ -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<NativeWindow> 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_;
index b24e828..dc2929f 100644 (file)
@@ -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 {
index 9fbc20d..f36850f 100644 (file)
@@ -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 ...
+```
index 6669d8c..f88d25c 100644 (file)
@@ -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)