Browse Source

feat: Add will-resize event to TopLevelWindow (#13649)

The new `will-resize` event can be used to prevent the resize from
happening before the native window is actually resized. This is in
contrast to the existing the `resize` event, which is sent *after* the
native window has already been resized. For apps with e.g. custom window
snapping logic, the `resize` event is not sufficient because it will
result in flickering between the dragged size and the snapped size.

`will-resize` is only emitted on macOS and Windows.
Birunthan Mohanathas 6 years ago
parent
commit
c8dc2d3730

+ 7 - 0
atom/browser/api/atom_api_top_level_window.cc

@@ -194,6 +194,13 @@ void TopLevelWindow::OnWindowRestore() {
   Emit("restore");
 }
 
+void TopLevelWindow::OnWindowWillResize(const gfx::Rect& new_bounds,
+                                        bool* prevent_default) {
+  if (Emit("will-resize", new_bounds)) {
+    *prevent_default = true;
+  }
+}
+
 void TopLevelWindow::OnWindowResize() {
   Emit("resize");
 }

+ 2 - 0
atom/browser/api/atom_api_top_level_window.h

@@ -60,6 +60,8 @@ class TopLevelWindow : public mate::TrackableObject<TopLevelWindow>,
   void OnWindowUnmaximize() override;
   void OnWindowMinimize() override;
   void OnWindowRestore() override;
+  void OnWindowWillResize(const gfx::Rect& new_bounds,
+                          bool* prevent_default) override;
   void OnWindowResize() override;
   void OnWindowMove() override;
   void OnWindowMoved() override;

+ 6 - 0
atom/browser/native_window.cc

@@ -458,6 +458,12 @@ void NativeWindow::NotifyWindowRestore() {
     observer.OnWindowRestore();
 }
 
+void NativeWindow::NotifyWindowWillResize(const gfx::Rect& new_bounds,
+                                          bool* prevent_default) {
+  for (NativeWindowObserver& observer : observers_)
+    observer.OnWindowWillResize(new_bounds, prevent_default);
+}
+
 void NativeWindow::NotifyWindowResize() {
   for (NativeWindowObserver& observer : observers_)
     observer.OnWindowResize();

+ 2 - 0
atom/browser/native_window.h

@@ -236,6 +236,8 @@ class NativeWindow : public base::SupportsUserData,
   void NotifyWindowMinimize();
   void NotifyWindowRestore();
   void NotifyWindowMove();
+  void NotifyWindowWillResize(const gfx::Rect& new_bounds,
+                              bool* prevent_default);
   void NotifyWindowResize();
   void NotifyWindowMoved();
   void NotifyWindowScrollTouchBegin();

+ 6 - 0
atom/browser/native_window_observer.h

@@ -16,6 +16,10 @@
 #include <windows.h>
 #endif
 
+namespace gfx {
+class Rect;
+}
+
 namespace atom {
 
 class NativeWindowObserver {
@@ -63,6 +67,8 @@ class NativeWindowObserver {
   virtual void OnWindowUnmaximize() {}
   virtual void OnWindowMinimize() {}
   virtual void OnWindowRestore() {}
+  virtual void OnWindowWillResize(const gfx::Rect& new_bounds,
+                                  bool* prevent_default) {}
   virtual void OnWindowResize() {}
   virtual void OnWindowMove() {}
   virtual void OnWindowMoved() {}

+ 12 - 1
atom/browser/native_window_views_win.cc

@@ -187,6 +187,16 @@ bool NativeWindowViews::PreHandleMSG(UINT message,
       if (HIWORD(w_param) == THBN_CLICKED)
         return taskbar_host_.HandleThumbarButtonEvent(LOWORD(w_param));
       return false;
+    case WM_SIZING: {
+      bool prevent_default = false;
+      NotifyWindowWillResize(gfx::Rect(*reinterpret_cast<RECT*>(l_param)),
+                             &prevent_default);
+      if (prevent_default) {
+        ::GetWindowRect(GetAcceleratedWidget(),
+                        reinterpret_cast<RECT*>(l_param));
+      }
+      return false;
+    }
     case WM_SIZE: {
       // Handle window state change.
       HandleSizeEvent(w_param, l_param);
@@ -198,7 +208,8 @@ bool NativeWindowViews::PreHandleMSG(UINT message,
     }
     case WM_MOVING: {
       if (!movable_)
-        ::GetWindowRect(GetAcceleratedWidget(), (LPRECT)l_param);
+        ::GetWindowRect(GetAcceleratedWidget(),
+                        reinterpret_cast<RECT*>(l_param));
       return false;
     }
     case WM_MOVE: {

+ 9 - 0
atom/browser/ui/cocoa/atom_ns_window_delegate.mm

@@ -112,6 +112,15 @@
                extraHeightPlusFrame);
   }
 
+  {
+    bool prevent_default = false;
+    gfx::Rect new_bounds(gfx::Point(sender.frame.origin), gfx::Size(newSize));
+    shell_->NotifyWindowWillResize(new_bounds, &prevent_default);
+    if (prevent_default) {
+      return sender.frame.size;
+    }
+  }
+
   return newSize;
 }
 

+ 12 - 1
docs/api/browser-window.md

@@ -490,9 +490,20 @@ Emitted when the window is minimized.
 
 Emitted when the window is restored from a minimized state.
 
+#### Event: 'will-resize' _macOS_ _Windows_
+
+Returns:
+
+* `event` Event
+* `newBounds` [`Rectangle`](structures/rectangle.md) - Size the window is being resized to.
+
+Emitted before the window is resized. Calling `event.preventDefault()` will prevent the window from being resized.
+
+Note that this is only emitted when the window is being resized manually. Resizing the window with `setBounds`/`setSize` will not emit this event.
+
 #### Event: 'resize'
 
-Emitted when the window is being resized.
+Emitted after the window has been resized.
 
 #### Event: 'move'