diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc
index 252c8f920354..dcdc10dc36a8 100644
--- a/atom/browser/api/atom_api_window.cc
+++ b/atom/browser/api/atom_api_window.cc
@@ -124,6 +124,14 @@ void Window::OnWindowRestore() {
   Emit("restore");
 }
 
+void Window::OnWindowResize() {
+  Emit("resize", GetBounds().size());
+}
+
+void Window::OnWindowMove() {
+  Emit("move", window_->GetPosition());
+}
+
 void Window::OnWindowEnterFullScreen() {
   Emit("enter-full-screen");
 }
diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h
index 8aa1ed0988dc..efe196bd55fc 100644
--- a/atom/browser/api/atom_api_window.h
+++ b/atom/browser/api/atom_api_window.h
@@ -64,6 +64,8 @@ class Window : public mate::EventEmitter,
   void OnWindowUnmaximize() override;
   void OnWindowMinimize() override;
   void OnWindowRestore() override;
+  void OnWindowResize() override;
+  void OnWindowMove() override;
   void OnWindowEnterFullScreen() override;
   void OnWindowLeaveFullScreen() override;
   void OnWindowEnterHtmlFullScreen() override;
diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc
index e937bbdfccf1..9bc97d5d192e 100644
--- a/atom/browser/native_window.cc
+++ b/atom/browser/native_window.cc
@@ -535,6 +535,14 @@ void NativeWindow::NotifyWindowRestore() {
   FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowRestore());
 }
 
+void NativeWindow::NotifyWindowResize() {
+  FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowResize());
+}
+
+void NativeWindow::NotifyWindowMove() {
+  FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowMove());
+}
+
 void NativeWindow::NotifyWindowEnterFullScreen() {
   FOR_EACH_OBSERVER(NativeWindowObserver, observers_,
                     OnWindowEnterFullScreen());
diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h
index b114ecf510b4..7f72ebdf5e02 100644
--- a/atom/browser/native_window.h
+++ b/atom/browser/native_window.h
@@ -207,6 +207,8 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
   void NotifyWindowUnmaximize();
   void NotifyWindowMinimize();
   void NotifyWindowRestore();
+  void NotifyWindowMove();
+  void NotifyWindowResize();
   void NotifyWindowEnterFullScreen();
   void NotifyWindowLeaveFullScreen();
   void NotifyWindowEnterHtmlFullScreen();
diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm
index a9ff57d8d279..6a21f33b2ffc 100644
--- a/atom/browser/native_window_mac.mm
+++ b/atom/browser/native_window_mac.mm
@@ -98,6 +98,12 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
 - (void)windowDidResize:(NSNotification*)notification {
   if (!shell_->has_frame())
     shell_->ClipWebView();
+
+  shell_->NotifyWindowResize();
+}
+
+- (void)windowDidMove:(NSNotification*)notification {
+  shell_->NotifyWindowMove();
 }
 
 - (void)windowDidMiniaturize:(NSNotification*)notification {
diff --git a/atom/browser/native_window_observer.h b/atom/browser/native_window_observer.h
index 8c09e832a829..1db1fed7cbfa 100644
--- a/atom/browser/native_window_observer.h
+++ b/atom/browser/native_window_observer.h
@@ -47,6 +47,8 @@ class NativeWindowObserver {
   virtual void OnWindowUnmaximize() {}
   virtual void OnWindowMinimize() {}
   virtual void OnWindowRestore() {}
+  virtual void OnWindowResize() {}
+  virtual void OnWindowMove() {}
   virtual void OnWindowEnterFullScreen() {}
   virtual void OnWindowLeaveFullScreen() {}
   virtual void OnWindowEnterHtmlFullScreen() {}
diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc
index 4c99f88969ba..29e480ce7382 100644
--- a/atom/browser/native_window_views.cc
+++ b/atom/browser/native_window_views.cc
@@ -720,6 +720,22 @@ void NativeWindowViews::OnWidgetActivationChanged(
     SetMenuBarVisibility(false);
 }
 
+void NativeWindowViews::OnWidgetBoundsChanged(
+    views::Widget* widget, const gfx::Rect& bounds) {
+  if (widget != window_.get())
+    return;
+
+  if (widget_size_ != bounds.size()) {
+    NotifyWindowResize();
+    widget_size_ = bounds.size();
+  }
+
+  if (widget_pos_ != bounds.origin()) {
+    NotifyWindowMove();
+    widget_pos_ = bounds.origin();
+  }
+}
+
 void NativeWindowViews::DeleteDelegate() {
   NotifyWindowClosed();
 }
diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h
index 15f073d8d8c1..88d2c78eee2d 100644
--- a/atom/browser/native_window_views.h
+++ b/atom/browser/native_window_views.h
@@ -93,6 +93,8 @@ class NativeWindowViews : public NativeWindow,
   // views::WidgetObserver:
   void OnWidgetActivationChanged(
       views::Widget* widget, bool active) override;
+  void OnWidgetBoundsChanged(
+      views::Widget* widget, const gfx::Rect& bounds) override;
 
   // views::WidgetDelegate:
   void DeleteDelegate() override;
@@ -173,6 +175,8 @@ class NativeWindowViews : public NativeWindow,
   std::string title_;
   gfx::Size minimum_size_;
   gfx::Size maximum_size_;
+  gfx::Size widget_size_;
+  gfx::Point widget_pos_;
 
   scoped_ptr<SkRegion> draggable_region_;
 
diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md
index cc68f2008b9e..056148b398d8 100644
--- a/docs/api/browser-window.md
+++ b/docs/api/browser-window.md
@@ -171,6 +171,24 @@ Emitted when window is minimized.
 
 Emitted when window is restored from minimized state.
 
+### Event: 'resize'
+
+* `event` Event
+* `value` Object
+  * `width` Integer
+  * `height` Integer
+
+Emitted when window is resized.
+
+### Event: 'move'
+
+* `event` Event
+* `value` Object
+  * `x` Integer
+  * `y` Integer
+
+Emitted when window is moved.
+
 ### Event: 'enter-full-screen'
 
 Emitted when window enters full screen state.
diff --git a/spec/api-browser-window-spec.coffee b/spec/api-browser-window-spec.coffee
index 958bd7295803..12f790d3b29b 100644
--- a/spec/api-browser-window-spec.coffee
+++ b/spec/api-browser-window-spec.coffee
@@ -90,12 +90,22 @@ describe 'browser-window module', ->
         done()
 
   describe 'BrowserWindow.setSize(width, height)', ->
-    it 'sets the window size', ->
-      size = [400, 400]
+    it 'sets the window size', (done) ->
+      size = [20, 400]
+      w.on 'resize', (e, value) ->
+        assert.equal value.width, size[0]
+        assert.equal value.height, size[1]
+        done()
       w.setSize size[0], size[1]
-      after = w.getSize()
-      assert.equal after[0], size[0]
-      assert.equal after[1], size[1]
+
+  describe 'BrowserWindow.setPosition(x, y)', ->
+    it 'sets the window position', (done) ->
+      pos = [10, 10]
+      w.on 'move', (e, value) ->
+        assert.equal value.x, pos[0]
+        assert.equal value.y, pos[1]
+        done()
+      w.setPosition pos[0], pos[1]
 
   describe 'BrowserWindow.setContentSize(width, height)', ->
     it 'sets the content size', ->