summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorasargent@chromium.org <asargent@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-28 04:42:43 +0000
committerasargent@chromium.org <asargent@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-28 04:42:43 +0000
commit99d8f096aa417b8b94f0d0dafb4350bd19607758 (patch)
treeb54cc08ca43f0776dbe497d8c9caa72e414c4b0c
parent7240505e7e7c1aa3e866c13ef614bf1409c17eeb (diff)
downloadchromium_src-99d8f096aa417b8b94f0d0dafb4350bd19607758.zip
chromium_src-99d8f096aa417b8b94f0d0dafb4350bd19607758.tar.gz
chromium_src-99d8f096aa417b8b94f0d0dafb4350bd19607758.tar.bz2
Add app window property change events
This adds onBoundsChanged, onMinimized, onMaximized, and onRestored events. BUG=134070 Review URL: https://codereview.chromium.org/11364230 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@169848 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/api/app_window/app_window_apitest.cc12
-rw-r--r--chrome/browser/extensions/platform_app_browsertest.cc4
-rw-r--r--chrome/browser/ui/cocoa/extensions/shell_window_cocoa.mm6
-rw-r--r--chrome/browser/ui/extensions/shell_window.cc51
-rw-r--r--chrome/browser/ui/extensions/shell_window.h10
-rw-r--r--chrome/browser/ui/gtk/extensions/shell_window_gtk.cc7
-rw-r--r--chrome/browser/ui/views/extensions/shell_window_views.cc16
-rw-r--r--chrome/browser/ui/views/extensions/shell_window_views.h10
-rw-r--r--chrome/common/extensions/api/app_current_window_internal.idl8
-rw-r--r--chrome/common/extensions/api/app_window.idl6
-rw-r--r--chrome/renderer/resources/extensions/app_window_custom_bindings.js43
-rw-r--r--chrome/test/data/extensions/platform_apps/windows_api_properties/background.js40
-rw-r--r--chrome/test/data/extensions/platform_apps/windows_api_properties/main.html1
-rw-r--r--chrome/test/data/extensions/platform_apps/windows_api_properties/main.js57
-rw-r--r--chrome/test/data/extensions/platform_apps/windows_api_properties/manifest.json9
15 files changed, 236 insertions, 44 deletions
diff --git a/chrome/browser/extensions/api/app_window/app_window_apitest.cc b/chrome/browser/extensions/api/app_window/app_window_apitest.cc
index 09d42b4..5307888 100644
--- a/chrome/browser/extensions/api/app_window/app_window_apitest.cc
+++ b/chrome/browser/extensions/api/app_window/app_window_apitest.cc
@@ -37,4 +37,16 @@ IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, WindowsApiBounds) {
ASSERT_TRUE(success_listener.WaitUntilSatisfied());
}
+// TODO(asargent) - Fix onMinimzed event on OSX (crbug.com/162793) and figure
+// out what to do about the fact that minimize events don't work under ubuntu
+// unity (crbug.com/162794 and https://bugs.launchpad.net/unity/+bug/998073).
+#if defined(TOOLKIT_VIEWS)
+
+IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, WindowsApiProperties) {
+ EXPECT_TRUE(
+ RunExtensionTest("platform_apps/windows_api_properties")) << message_;
+}
+
+#endif // defined(TOOLKIT_VIEWS)
+
} // namespace extensions
diff --git a/chrome/browser/extensions/platform_app_browsertest.cc b/chrome/browser/extensions/platform_app_browsertest.cc
index 46b176f..3736e0a 100644
--- a/chrome/browser/extensions/platform_app_browsertest.cc
+++ b/chrome/browser/extensions/platform_app_browsertest.cc
@@ -655,9 +655,9 @@ IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest,
}
// In the GTK ShellWindow implementation there also is a delay between
- // getting the correct bounds and it calling SaveWindowPosition, so call that
+ // getting the correct bounds and it calling SaveWindowPosition, so call a
// method explicitly to make sure the value was stored.
- window->SaveWindowPosition();
+ window->OnNativeWindowChanged();
#endif // defined(TOOLKIT_GTK)
// Make sure the window was properly moved&resized.
diff --git a/chrome/browser/ui/cocoa/extensions/shell_window_cocoa.mm b/chrome/browser/ui/cocoa/extensions/shell_window_cocoa.mm
index 779564f..34143a2 100644
--- a/chrome/browser/ui/cocoa/extensions/shell_window_cocoa.mm
+++ b/chrome/browser/ui/cocoa/extensions/shell_window_cocoa.mm
@@ -656,7 +656,7 @@ bool ShellWindowCocoa::IsAlwaysOnTop() const {
void ShellWindowCocoa::WindowWillClose() {
[window_controller_ setShellWindow:NULL];
- shell_window_->SaveWindowPosition();
+ shell_window_->OnNativeWindowChanged();
shell_window_->OnNativeClose();
}
@@ -682,11 +682,11 @@ void ShellWindowCocoa::WindowDidResignKey() {
}
void ShellWindowCocoa::WindowDidResize() {
- shell_window_->SaveWindowPosition();
+ shell_window_->OnNativeWindowChanged();
}
void ShellWindowCocoa::WindowDidMove() {
- shell_window_->SaveWindowPosition();
+ shell_window_->OnNativeWindowChanged();
}
bool ShellWindowCocoa::HandledByExtensionCommand(NSEvent* event) {
diff --git a/chrome/browser/ui/extensions/shell_window.cc b/chrome/browser/ui/extensions/shell_window.cc
index 7406536..71e9459 100644
--- a/chrome/browser/ui/extensions/shell_window.cc
+++ b/chrome/browser/ui/extensions/shell_window.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/ui/extensions/shell_window.h"
#include "base/utf_string_conversions.h"
+#include "base/values.h"
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/shell_window_geometry_cache.h"
@@ -143,7 +144,7 @@ void ShellWindow::Init(const GURL& url,
new_params.bounds = bounds;
native_window_.reset(NativeShellWindow::Create(this, new_params));
- SaveWindowPosition();
+ OnNativeWindowChanged();
if (!params.hidden)
GetBaseWindow()->Show();
@@ -287,6 +288,34 @@ void ShellWindow::OnNativeClose() {
delete this;
}
+void ShellWindow::OnNativeWindowChanged() {
+ SaveWindowPosition();
+ if (!native_window_ || !web_contents_)
+ return;
+ ListValue args;
+ DictionaryValue* dictionary = new DictionaryValue();
+ args.Append(dictionary);
+
+ gfx::Rect bounds = native_window_->GetBounds();
+ app_window::Bounds update;
+ update.left.reset(new int(bounds.x()));
+ update.top.reset(new int(bounds.y()));
+ update.width.reset(new int(bounds.width()));
+ update.height.reset(new int(bounds.height()));
+ dictionary->Set("bounds", update.ToValue().release());
+ dictionary->SetBoolean("minimized", native_window_->IsMinimized());
+ dictionary->SetBoolean("maximized", native_window_->IsMaximized());
+
+ content::RenderViewHost* rvh = web_contents_->GetRenderViewHost();
+ rvh->Send(new ExtensionMsg_MessageInvoke(rvh->GetRoutingID(),
+ extension_->id(),
+ "updateAppWindowProperties",
+ args,
+ GURL(),
+ false));
+}
+
+
BaseWindow* ShellWindow::GetBaseWindow() {
return native_window_.get();
}
@@ -460,28 +489,8 @@ void ShellWindow::AddMessageToDevToolsConsole(ConsoleMessageLevel level,
rvh->GetRoutingID(), level, message));
}
-void ShellWindow::SendBoundsUpdate() {
- if (!native_window_ || !web_contents_)
- return;
- gfx::Rect bounds = native_window_->GetBounds();
- content::RenderViewHost* rvh = web_contents_->GetRenderViewHost();
- ListValue args;
- app_window::Bounds update;
- update.left.reset(new int(bounds.x()));
- update.top.reset(new int(bounds.y()));
- update.width.reset(new int(bounds.width()));
- update.height.reset(new int(bounds.height()));
- args.Append(update.ToValue().release());
- rvh->Send(new ExtensionMsg_MessageInvoke(rvh->GetRoutingID(),
- extension_->id(),
- "updateAppWindowBounds",
- args,
- GURL(),
- false));
-}
void ShellWindow::SaveWindowPosition() {
- SendBoundsUpdate();
if (window_key_.empty())
return;
if (!native_window_)
diff --git a/chrome/browser/ui/extensions/shell_window.h b/chrome/browser/ui/extensions/shell_window.h
index 2f8b89c..a367e56 100644
--- a/chrome/browser/ui/extensions/shell_window.h
+++ b/chrome/browser/ui/extensions/shell_window.h
@@ -101,9 +101,9 @@ class ShellWindow : public content::NotificationObserver,
// invoke this method instead of using "delete this".
void OnNativeClose();
- // Should be called by native implementations when the window size/position
- // has changed.
- void SaveWindowPosition();
+ // Should be called by native implementations when the window size, position,
+ // or minimized/maximized state has changed.
+ void OnNativeWindowChanged();
protected:
ShellWindow(Profile* profile,
@@ -174,8 +174,8 @@ class ShellWindow : public content::NotificationObserver,
void AddMessageToDevToolsConsole(content::ConsoleMessageLevel level,
const std::string& message);
- // Sends an update message with the current bounds to the renderer.
- void SendBoundsUpdate();
+ // Saves the window geometry/position.
+ void SaveWindowPosition();
virtual void UpdateDraggableRegions(
const std::vector<extensions::DraggableRegion>& regions);
diff --git a/chrome/browser/ui/gtk/extensions/shell_window_gtk.cc b/chrome/browser/ui/gtk/extensions/shell_window_gtk.cc
index 32e7c73..f636c15 100644
--- a/chrome/browser/ui/gtk/extensions/shell_window_gtk.cc
+++ b/chrome/browser/ui/gtk/extensions/shell_window_gtk.cc
@@ -173,7 +173,7 @@ void ShellWindowGtk::Hide() {
}
void ShellWindowGtk::Close() {
- shell_window_->SaveWindowPosition();
+ shell_window_->OnNativeWindowChanged();
// Cancel any pending callback from the window configure debounce timer.
window_configure_debounce_timer_.Stop();
@@ -204,6 +204,7 @@ void ShellWindowGtk::Maximize() {
void ShellWindowGtk::Minimize() {
gtk_window_iconify(window_);
+ shell_window_->OnNativeWindowChanged();
}
void ShellWindowGtk::Restore() {
@@ -211,6 +212,7 @@ void ShellWindowGtk::Restore() {
gtk_window_unmaximize(window_);
else if (IsMinimized())
gtk_window_deiconify(window_);
+ shell_window_->OnNativeWindowChanged();
}
void ShellWindowGtk::SetBounds(const gfx::Rect& bounds) {
@@ -275,7 +277,7 @@ gboolean ShellWindowGtk::OnConfigure(GtkWidget* widget,
void ShellWindowGtk::OnDebouncedBoundsChanged() {
gtk_window_util::UpdateWindowPosition(this, &bounds_, &restored_bounds_);
- shell_window_->SaveWindowPosition();
+ shell_window_->OnNativeWindowChanged();
}
gboolean ShellWindowGtk::OnWindowState(GtkWidget* sender,
@@ -290,6 +292,7 @@ gboolean ShellWindowGtk::OnWindowState(GtkWidget* sender,
rvh->ExitFullscreen();
}
+ shell_window_->OnNativeWindowChanged();
return FALSE;
}
diff --git a/chrome/browser/ui/views/extensions/shell_window_views.cc b/chrome/browser/ui/views/extensions/shell_window_views.cc
index c8e0ec9..dcebae2 100644
--- a/chrome/browser/ui/views/extensions/shell_window_views.cc
+++ b/chrome/browser/ui/views/extensions/shell_window_views.cc
@@ -434,6 +434,7 @@ ShellWindowViews::ShellWindowViews(ShellWindow* shell_window,
shell_window_));
OnViewWasResized();
+ window_->AddObserver(this);
}
views::View* ShellWindowViews::GetInitiallyFocusedView() {
@@ -575,6 +576,7 @@ bool ShellWindowViews::IsAlwaysOnTop() const {
}
void ShellWindowViews::DeleteDelegate() {
+ window_->RemoveObserver(this);
shell_window_->OnNativeClose();
}
@@ -693,7 +695,17 @@ bool ShellWindowViews::ShouldShowWindowTitle() const {
}
void ShellWindowViews::OnWidgetMove() {
- shell_window_->SaveWindowPosition();
+ shell_window_->OnNativeWindowChanged();
+}
+
+void ShellWindowViews::OnWidgetVisibilityChanged(views::Widget* widget,
+ bool visible) {
+ shell_window_->OnNativeWindowChanged();
+}
+
+void ShellWindowViews::OnWidgetActivationChanged(views::Widget* widget,
+ bool active) {
+ shell_window_->OnNativeWindowChanged();
}
void ShellWindowViews::Layout() {
@@ -733,7 +745,7 @@ void ShellWindowViews::RenderViewHostChanged() {
void ShellWindowViews::SaveWindowPlacement(const gfx::Rect& bounds,
ui::WindowShowState show_state) {
views::WidgetDelegate::SaveWindowPlacement(bounds, show_state);
- shell_window_->SaveWindowPosition();
+ shell_window_->OnNativeWindowChanged();
}
// static
diff --git a/chrome/browser/ui/views/extensions/shell_window_views.h b/chrome/browser/ui/views/extensions/shell_window_views.h
index 18beabf..d58422b 100644
--- a/chrome/browser/ui/views/extensions/shell_window_views.h
+++ b/chrome/browser/ui/views/extensions/shell_window_views.h
@@ -13,6 +13,7 @@
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/rect.h"
#include "ui/views/widget/widget_delegate.h"
+#include "ui/views/widget/widget_observer.h"
class ExtensionKeybindingRegistryViews;
class Profile;
@@ -30,7 +31,8 @@ class WebView;
}
class ShellWindowViews : public NativeShellWindow,
- public views::WidgetDelegateView {
+ public views::WidgetDelegateView,
+ public views::WidgetObserver {
public:
ShellWindowViews(ShellWindow* shell_window,
const ShellWindow::CreateParams& params);
@@ -78,6 +80,12 @@ class ShellWindowViews : public NativeShellWindow,
virtual bool ShouldShowWindowTitle() const OVERRIDE;
virtual void OnWidgetMove() OVERRIDE;
+ // WidgetObserver implementation.
+ virtual void OnWidgetVisibilityChanged(views::Widget* widget,
+ bool visible) OVERRIDE;
+ virtual void OnWidgetActivationChanged(views::Widget* widget,
+ bool active) OVERRIDE;
+
protected:
// views::View implementation.
virtual void Layout() OVERRIDE;
diff --git a/chrome/common/extensions/api/app_current_window_internal.idl b/chrome/common/extensions/api/app_current_window_internal.idl
index e1a4b3d..782b882 100644
--- a/chrome/common/extensions/api/app_current_window_internal.idl
+++ b/chrome/common/extensions/api/app_current_window_internal.idl
@@ -28,4 +28,12 @@
static void hide();
static void setBounds(Bounds bounds);
};
+
+ interface Events {
+ static void onClosed();
+ static void onBoundsChanged();
+ static void onMinimized();
+ static void onMaximized();
+ static void onRestored();
+ };
};
diff --git a/chrome/common/extensions/api/app_window.idl b/chrome/common/extensions/api/app_window.idl
index e2d04ab..3ca6fb9 100644
--- a/chrome/common/extensions/api/app_window.idl
+++ b/chrome/common/extensions/api/app_window.idl
@@ -83,9 +83,15 @@ namespace app.window {
// Minimize the window.
static void minimize();
+ // Is the window minimized?
+ static boolean isMinimized();
+
// Maximize the window.
static void maximize();
+ // Is the window maximized?
+ static bool isMaximized();
+
// Restore the window.
static void restore();
diff --git a/chrome/renderer/resources/extensions/app_window_custom_bindings.js b/chrome/renderer/resources/extensions/app_window_custom_bindings.js
index 9d38b6d..4d454f0 100644
--- a/chrome/renderer/resources/extensions/app_window_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/app_window_custom_bindings.js
@@ -88,6 +88,12 @@ chromeHidden.registerCustomHook('app.window', function(bindingsAPI) {
return { left: bounds.left, top: bounds.top,
width: bounds.width, height: bounds.height };
};
+ AppWindow.prototype.isMinimized = function() {
+ return chromeHidden.appWindowData.minimized;
+ };
+ AppWindow.prototype.isMaximized = function() {
+ return chromeHidden.appWindowData.maximized;
+ };
Object.defineProperty(AppWindow.prototype, 'id', {get: function() {
return chromeHidden.appWindowData.id;
@@ -96,18 +102,39 @@ chromeHidden.registerCustomHook('app.window', function(bindingsAPI) {
chromeHidden.appWindowData = {
id: params.id || '',
bounds: { left: params.bounds.left, top: params.bounds.top,
- width: params.bounds.width, height: params.bounds.height }
+ width: params.bounds.width, height: params.bounds.height },
+ minimized: false,
+ maximized: false
};
chromeHidden.currentAppWindow = new AppWindow;
});
});
-chromeHidden.updateAppWindowBounds = function(info) {
- var data = chromeHidden.appWindowData;
- if (!data)
+function boundsEqual(bounds1, bounds2) {
+ if (!bounds1 || !bounds2)
+ return false;
+ return (bounds1.left == bounds2.left && bounds1.top == bounds2.top &&
+ bounds1.width == bounds2.width && bounds1.height == bounds2.height);
+}
+
+chromeHidden.updateAppWindowProperties = function(update) {
+ if (!chromeHidden.appWindowData)
return;
- data.bounds.left = info.left;
- data.bounds.top = info.top;
- data.bounds.width = info.width;
- data.bounds.height = info.height;
+ var oldData = chromeHidden.appWindowData;
+ update.id = oldData.id;
+ chromeHidden.appWindowData = update;
+
+ var currentWindow = chromeHidden.currentAppWindow;
+
+ if (!boundsEqual(oldData.bounds, update.bounds))
+ currentWindow["onBoundsChanged"].dispatch();
+
+ if (!oldData.minimized && update.minimized)
+ currentWindow["onMinimized"].dispatch();
+ if (!oldData.maximized && update.maximized)
+ currentWindow["onMaximized"].dispatch();
+
+ if ((oldData.minimized && !update.minimized) ||
+ (oldData.maximized && !update.maximized))
+ currentWindow["onRestored"].dispatch();
};
diff --git a/chrome/test/data/extensions/platform_apps/windows_api_properties/background.js b/chrome/test/data/extensions/platform_apps/windows_api_properties/background.js
new file mode 100644
index 0000000..e59a6c0
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/windows_api_properties/background.js
@@ -0,0 +1,40 @@
+// Copyright (c) 2012 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.
+
+var eventCounts = {};
+var eventCallback = null;
+
+function clearEventCounts() {
+ eventCallback = null;
+ eventCounts['onBoundsChanged'] = 0;
+ eventCounts['onMinimized'] = 0;
+ eventCounts['onMaximized'] = 0;
+ eventCounts['onRestored'] = 0;
+}
+
+clearEventCounts();
+
+chrome.app.window.create('main.html', function(win) {
+ win.onBoundsChanged.addListener(function() {
+ eventCounts['onBoundsChanged']++;
+ if (eventCallback)
+ eventCallback();
+ });
+ win.onMinimized.addListener(function() {
+ eventCounts['onMinimized']++;
+ if (eventCallback)
+ eventCallback();
+ });
+ win.onMaximized.addListener(function() {
+ eventCounts['onMaximized']++;
+ if (eventCallback)
+ eventCallback();
+ });
+ win.onRestored.addListener(function() {
+ eventCounts['onRestored']++;
+ if (eventCallback)
+ eventCallback();
+ });
+});
+
diff --git a/chrome/test/data/extensions/platform_apps/windows_api_properties/main.html b/chrome/test/data/extensions/platform_apps/windows_api_properties/main.html
new file mode 100644
index 0000000..ee7be70
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/windows_api_properties/main.html
@@ -0,0 +1 @@
+<script src="main.js"></script>
diff --git a/chrome/test/data/extensions/platform_apps/windows_api_properties/main.js b/chrome/test/data/extensions/platform_apps/windows_api_properties/main.js
new file mode 100644
index 0000000..d469581
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/windows_api_properties/main.js
@@ -0,0 +1,57 @@
+// Copyright (c) 2012 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.
+
+var current = chrome.app.window.current();
+var bg = null;
+var nextTestNumber = 1;
+
+function makeEventTest(eventName, startFunction) {
+ var test = function() {
+ bg.clearEventCounts();
+ var listener = function() {
+ current[eventName].removeListener(listener);
+ function waitForBackgroundPageToSeeEvent() {
+ if (!bg.eventCounts[eventName] > 0) {
+ bg.eventCallback = waitForBackgroundPageToSeeEvent;
+ }
+ else {
+ bg.eventCallback = null;
+ current.restore();
+ chrome.test.succeed();
+ }
+ }
+ waitForBackgroundPageToSeeEvent();
+ };
+ current[eventName].addListener(listener);
+ startFunction();
+ };
+ // For anonymous functions, setting 'generatedName' controls what shows up in
+ // the apitest framework's logging output.
+ test.generatedName = "Test" + nextTestNumber++ + "_" + eventName;
+ return test;
+}
+
+
+var tests = [
+
+ makeEventTest('onMinimized', function() { current.minimize(); }),
+ makeEventTest('onMaximized', function() { current.maximize(); }),
+ makeEventTest('onRestored', function() {
+ current.minimize();
+ current.restore();
+ }),
+ makeEventTest('onRestored', function() {
+ current.maximize();
+ current.restore();
+ }),
+ makeEventTest('onBoundsChanged', function() {
+ current.setBounds({left:5, top:5, width:100, height:100});
+ })
+
+];
+
+chrome.runtime.getBackgroundPage(function(page) {
+ bg = page;
+ chrome.test.runTests(tests);
+});
diff --git a/chrome/test/data/extensions/platform_apps/windows_api_properties/manifest.json b/chrome/test/data/extensions/platform_apps/windows_api_properties/manifest.json
new file mode 100644
index 0000000..ce09a2d
--- /dev/null
+++ b/chrome/test/data/extensions/platform_apps/windows_api_properties/manifest.json
@@ -0,0 +1,9 @@
+{
+ "name": "app.windows properties",
+ "version": "1",
+ "app": {
+ "background": {
+ "scripts": ["background.js"]
+ }
+ }
+}