chromeos: Add maximize/restore button.
This makes Chrome watch the _CHROME_LAYOUT_MODE property
that the window manager now sets on the root window and use
it to update the state of a new button to the right of the
status area that can be used to toggle between having
maximized or overlapping browser windows.
BUG=chromium-os:13963
TEST=manual
Review URL: http://codereview.chromium.org/7276022
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@90804 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index fd5f9af8..3fce9e4 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -11730,9 +11730,6 @@
<message name="IDS_STATUSBAR_WINDOW_RESTORE_TOOLTIP" desc="Tooltip for the layout mode button in the status bar when the window is maximized.">
Restore
</message>
- <message name="IDS_STATUSBAR_WINDOW_SWITCHER_TOOLTIP" desc="Tooltip for the window switcher in the status bar.">
- Switch windows
- </message>
<message name="IDS_VERSION_FIELD_PREFIX" desc="Display the OS version to the user.">
version
</message>
diff --git a/chrome/app/theme/statusbar_window_center.png b/chrome/app/theme/statusbar_window_center.png
deleted file mode 100644
index ce3941c..0000000
--- a/chrome/app/theme/statusbar_window_center.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/statusbar_window_left.png b/chrome/app/theme/statusbar_window_left.png
deleted file mode 100644
index 10baa2d..0000000
--- a/chrome/app/theme/statusbar_window_left.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/statusbar_window_right.png b/chrome/app/theme/statusbar_window_right.png
deleted file mode 100644
index 021ef233..0000000
--- a/chrome/app/theme/statusbar_window_right.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/statusbar_window_switcher.png b/chrome/app/theme/statusbar_window_switcher.png
deleted file mode 100644
index c923fc97a..0000000
--- a/chrome/app/theme/statusbar_window_switcher.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index 2a32010c6..91e3dbc0 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -564,7 +564,6 @@
<include name="IDR_STATUSBAR_WINDOW_RESTORE" file="statusbar_window_restore.png" type="BINDATA" />
<include name="IDR_STATUSBAR_WIRED" file="statusbar_wired.png" type="BINDATA" />
<include name="IDR_STATUSBAR_WIRED_BLACK" file="statusbar_wiredb.png" type="BINDATA" />
- <include name="IDR_STATUSBAR_WINDOW_SWITCHER" file="statusbar_window_switcher.png" type="BINDATA" />
<include name="IDR_USER_IMAGE_NO_VIDEO" file="no_video.png" type="BINDATA" />
<include name="IDR_USER_IMAGE_CAPTURE" file="snapshot_wide.png" type="BINDATA" />
<include name="IDR_USER_IMAGE_RECYCLE" file="discard_wide.png" type="BINDATA" />
diff --git a/chrome/browser/chromeos/frame/browser_frame_chromeos.cc b/chrome/browser/chromeos/frame/browser_frame_chromeos.cc
deleted file mode 100644
index 7d09f01c..0000000
--- a/chrome/browser/chromeos/frame/browser_frame_chromeos.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2011 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.
-
-#include "chrome/browser/chromeos/frame/browser_frame_chromeos.h"
-
-#include "base/command_line.h"
-#include "chrome/browser/ui/views/frame/browser_view.h"
-#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
-#include "chrome/common/chrome_switches.h"
-
-// static (Factory method.)
-BrowserFrame* BrowserFrame::Create(BrowserView* browser_view,
- Profile* profile) {
- chromeos::BrowserFrameChromeos* frame =
- new chromeos::BrowserFrameChromeos(browser_view, profile);
- frame->InitBrowserFrame();
- return frame;
-}
-
-namespace chromeos {
-
-BrowserFrameChromeos::BrowserFrameChromeos(
- BrowserView* browser_view, Profile* profile)
- : BrowserFrameGtk(browser_view, profile) {
-}
-
-BrowserFrameChromeos::~BrowserFrameChromeos() {
-}
-
-void BrowserFrameChromeos::InitBrowserFrame() {
- BrowserFrameGtk::InitBrowserFrame();
-
- if (!browser_view()->IsBrowserTypePopup() &&
- !browser_view()->IsBrowserTypePanel()) {
- // On chromeos we want windows to always render as active.
- DisableInactiveRendering();
- }
-}
-
-bool BrowserFrameChromeos::IsMaximized() const {
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeosFrame))
- return NativeWidgetGtk::IsMaximized();
- bool is_popup_or_panel = browser_view()->IsBrowserTypePopup() ||
- browser_view()->IsBrowserTypePanel();
- return !IsFullscreen() &&
- (!is_popup_or_panel || NativeWidgetGtk::IsMaximized());
-}
-
-} // namespace chromeos
diff --git a/chrome/browser/chromeos/frame/browser_frame_chromeos.h b/chrome/browser/chromeos/frame/browser_frame_chromeos.h
deleted file mode 100644
index bb4edbc..0000000
--- a/chrome/browser/chromeos/frame/browser_frame_chromeos.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef CHROME_BROWSER_CHROMEOS_FRAME_BROWSER_FRAME_CHROMEOS_H_
-#define CHROME_BROWSER_CHROMEOS_FRAME_BROWSER_FRAME_CHROMEOS_H_
-#pragma once
-
-#include "chrome/browser/ui/views/frame/browser_frame_gtk.h"
-
-namespace chromeos {
-
-class BrowserFrameChromeos : public BrowserFrameGtk {
- public:
- BrowserFrameChromeos(BrowserView* browser_view, Profile* profile);
- virtual ~BrowserFrameChromeos();
-
- // BrowserFrameGtk overrides.
- virtual void InitBrowserFrame();
-
- // views::NativeWidgetGtk overrides.
- virtual bool IsMaximized() const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(BrowserFrameChromeos);
-};
-
-} // namespace chroemos
-
-#endif // CHROME_BROWSER_CHROMEOS_FRAME_BROWSER_FRAME_CHROMEOS_H_
diff --git a/chrome/browser/chromeos/frame/browser_view.cc b/chrome/browser/chromeos/frame/browser_view.cc
index 191577f..5d177d5 100644
--- a/chrome/browser/chromeos/frame/browser_view.cc
+++ b/chrome/browser/chromeos/frame/browser_view.cc
@@ -11,6 +11,7 @@
#include "base/command_line.h"
#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/chromeos/frame/layout_mode_button.h"
#include "chrome/browser/chromeos/frame/panel_browser_view.h"
#include "chrome/browser/chromeos/status/input_method_menu_button.h"
#include "chrome/browser/chromeos/status/network_menu_button.h"
@@ -113,10 +114,10 @@
namespace chromeos {
-// LayoutManager for BrowserView, which layouts extra components such as
+// LayoutManager for BrowserView, which lays out extra components such as
// the status views as follows:
// ____ __ __
-// / \ \ \ [StatusArea]
+// / \ \ \ [StatusArea] [LayoutModeButton]
//
class BrowserViewLayout : public ::BrowserViewLayout {
public:
@@ -128,6 +129,7 @@
void Installed(views::View* host) {
status_area_ = NULL;
+ layout_mode_button_ = NULL;
::BrowserViewLayout::Installed(host);
}
@@ -138,17 +140,22 @@
case VIEW_ID_STATUS_AREA:
status_area_ = static_cast<chromeos::StatusAreaView*>(view);
break;
+ case VIEW_ID_LAYOUT_MODE_BUTTON:
+ layout_mode_button_ = static_cast<chromeos::LayoutModeButton*>(view);
+ break;
}
}
// In the normal and the compact navigation bar mode, ChromeOS
- // layouts compact navigation buttons and status views in the title
+ // lays out compact navigation buttons and status views in the title
// area. See Layout
virtual int LayoutTabStripRegion() OVERRIDE {
if (browser_view_->IsFullscreen() || !browser_view_->IsTabStripVisible()) {
status_area_->SetVisible(false);
tabstrip_->SetVisible(false);
tabstrip_->SetBounds(0, 0, 0, 0);
+ layout_mode_button_->SetVisible(false);
+ layout_mode_button_->SetBounds(0, 0, 0, 0);
return 0;
}
@@ -202,6 +209,12 @@
if (status_area_->HitTest(point_in_status_area_coords))
return true;
+ gfx::Point point_in_layout_mode_button_coords(point);
+ views::View::ConvertPointToView(browser_view_, layout_mode_button_,
+ &point_in_layout_mode_button_coords);
+ if (layout_mode_button_->HitTest(point_in_layout_mode_button_coords))
+ return true;
+
return false;
}
@@ -213,6 +226,8 @@
tabstrip_->SetVisible(true);
status_area_->SetVisible(true);
+ layout_mode_button_->SetVisible(false);
+ layout_mode_button_->SetBounds(0, 0, 0, 0);
gfx::Size status_size = status_area_->GetPreferredSize();
int status_height = status_size.height();
@@ -222,7 +237,7 @@
status_area_->SetBounds(status_x, bounds.bottom() - status_height,
status_size.width(), status_height);
- // The tabstrip's width is the bigger of it's preferred width and the width
+ // The tabstrip's width is the bigger of its preferred width and the width
// the status area.
int tabstrip_w = std::max(status_x + status_size.width(),
tabstrip_->GetPreferredSize().width());
@@ -249,20 +264,37 @@
return bounds.y() + toolbar_height;
}
- // Lays out tabstrip and status area in the title bar area (given by
- // |bounds|).
+ // Lays out tabstrip, status area, and layout mode button in the title bar
+ // area (given by |bounds|).
int LayoutTitlebarComponents(const gfx::Rect& bounds) {
if (bounds.IsEmpty())
return 0;
+ const bool show_layout_mode_button =
+ chromeos_browser_view()->should_show_layout_mode_button();
+
tabstrip_->SetVisible(true);
status_area_->SetVisible(
!chromeos_browser_view()->has_hide_status_area_property());
+ layout_mode_button_->SetVisible(show_layout_mode_button);
- // Layout status area after tab strip.
+ const gfx::Size layout_mode_button_size =
+ layout_mode_button_->GetPreferredSize();
+ layout_mode_button_->SetBounds(
+ bounds.right() - layout_mode_button_size.width(),
+ bounds.y(),
+ layout_mode_button_size.width(),
+ layout_mode_button_size.height());
+
+ // Lay out status area after tab strip and before layout mode button (if
+ // shown).
gfx::Size status_size = status_area_->GetPreferredSize();
+ const int status_right =
+ show_layout_mode_button ?
+ layout_mode_button_->bounds().x() :
+ bounds.right();
status_area_->SetBounds(
- bounds.right() - status_size.width(),
+ status_right - status_size.width(),
bounds.y() + kStatusAreaVerticalAdjustment,
status_size.width(),
status_size.height());
@@ -273,6 +305,7 @@
}
chromeos::StatusAreaView* status_area_;
+ chromeos::LayoutModeButton* layout_mode_button_;
DISALLOW_COPY_AND_ASSIGN(BrowserViewLayout);
};
@@ -282,9 +315,12 @@
BrowserView::BrowserView(Browser* browser)
: ::BrowserView(browser),
status_area_(NULL),
+ layout_mode_button_(NULL),
saved_focused_widget_(NULL),
- has_hide_status_area_property_(false) {
+ has_hide_status_area_property_(false),
+ should_show_layout_mode_button_(false) {
system_menu_delegate_.reset(new SimpleMenuModelDelegateAdapter(this));
+ BrowserList::AddObserver(this);
MessageLoopForUI::current()->AddObserver(this);
if (!g_chrome_state_gdk_atom)
@@ -298,6 +334,7 @@
if (toolbar())
toolbar()->RemoveMenuListener(this);
MessageLoopForUI::current()->RemoveObserver(this);
+ BrowserList::RemoveObserver(this);
}
// BrowserView, ::BrowserView overrides:
@@ -309,6 +346,11 @@
AddChildView(status_area_);
status_area_->Init();
+ layout_mode_button_ = new LayoutModeButton();
+ layout_mode_button_->set_id(VIEW_ID_LAYOUT_MODE_BUTTON);
+ AddChildView(layout_mode_button_);
+ layout_mode_button_->Init();
+
frame()->non_client_view()->set_context_menu_controller(this);
// Listen to wrench menu opens.
@@ -319,6 +361,7 @@
gtk_widget_add_events(GTK_WIDGET(frame()->GetNativeWindow()),
GDK_PROPERTY_CHANGE_MASK);
FetchHideStatusAreaProperty();
+ UpdateLayoutModeButtonVisibility();
// Make sure the window is set to the right type.
std::vector<int> params;
@@ -446,6 +489,22 @@
saved_focused_widget_ = gtk_window_get_focus(GetNativeHandle());
}
+// BrowserView, BrowserList::Observer implementation.
+
+void BrowserView::OnBrowserAdded(const Browser* browser) {
+ const bool was_showing = should_show_layout_mode_button_;
+ UpdateLayoutModeButtonVisibility();
+ if (should_show_layout_mode_button_ != was_showing)
+ Layout();
+}
+
+void BrowserView::OnBrowserRemoved(const Browser* browser) {
+ const bool was_showing = should_show_layout_mode_button_;
+ UpdateLayoutModeButtonVisibility();
+ if (should_show_layout_mode_button_ != was_showing)
+ Layout();
+}
+
// BrowserView, StatusAreaHost implementation.
Profile* BrowserView::GetProfile() const {
@@ -542,6 +601,21 @@
has_hide_status_area_property_ = false;
}
+void BrowserView::UpdateLayoutModeButtonVisibility() {
+ int count = 0;
+ for (BrowserList::const_iterator it = BrowserList::begin();
+ it != BrowserList::end(); ++it) {
+ if ((*it)->is_type_tabbed()) {
+ ++count;
+ if (count >= 2) {
+ should_show_layout_mode_button_ = true;
+ return;
+ }
+ }
+ }
+ should_show_layout_mode_button_ = false;
+}
+
} // namespace chromeos
// static
diff --git a/chrome/browser/chromeos/frame/browser_view.h b/chrome/browser/chromeos/frame/browser_view.h
index 9d8e6ec..f2bbc92 100644
--- a/chrome/browser/chromeos/frame/browser_view.h
+++ b/chrome/browser/chromeos/frame/browser_view.h
@@ -10,6 +10,7 @@
#include "base/message_loop.h"
#include "chrome/browser/chromeos/status/status_area_host.h"
+#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "views/context_menu_controller.h"
#include "views/controls/menu/menu_wrapper.h"
@@ -31,6 +32,7 @@
namespace chromeos {
+class LayoutModeButton;
class StatusAreaView;
class StatusAreaButton;
@@ -38,12 +40,13 @@
// BrowserView created with Browser::TYPE_TABBED. This extender adds controls
// to the title bar as follows:
// ____ __ __
-// / \ \ \ [StatusArea]
+// / \ \ \ [StatusArea] [LayoutModeButton]
//
// and adds the system context menu to the remaining area of the titlebar.
class BrowserView : public ::BrowserView,
public views::ContextMenuController,
public views::MenuListener,
+ public BrowserList::Observer,
public StatusAreaHost,
public MessageLoopForUI::Observer {
public:
@@ -72,6 +75,10 @@
// views::MenuListener implementation.
virtual void OnMenuOpened() OVERRIDE;
+ // BrowserList::Observer implementation.
+ virtual void OnBrowserAdded(const Browser* browser) OVERRIDE;
+ virtual void OnBrowserRemoved(const Browser* browser) OVERRIDE;
+
// StatusAreaHost overrides.
virtual Profile* GetProfile() const OVERRIDE;
virtual gfx::NativeWindow GetNativeWindow() const OVERRIDE;
@@ -93,6 +100,9 @@
bool has_hide_status_area_property() const {
return has_hide_status_area_property_;
}
+ bool should_show_layout_mode_button() const {
+ return should_show_layout_mode_button_;
+ }
// static implementation for chromeos::PanelBrowserView.
static WindowOpenDisposition DispositionForPopupBounds(
@@ -110,8 +120,12 @@
// Updates |has_hide_status_area_property_| by querying the X server.
void FetchHideStatusAreaProperty();
- // Status Area view.
+ // Updates |should_show_layout_mode_button_|. Changes won't be visible
+ // onscreen until Layout() is called.
+ void UpdateLayoutModeButtonVisibility();
+
StatusAreaView* status_area_;
+ LayoutModeButton* layout_mode_button_;
// System menu.
scoped_ptr<views::MenuItemView> system_menu_;
@@ -126,6 +140,10 @@
// hide the status area.
bool has_hide_status_area_property_;
+ // Should the layout mode button be shown? We only show it if there are
+ // multiple browsers open.
+ bool should_show_layout_mode_button_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserView);
};
diff --git a/chrome/browser/chromeos/frame/layout_mode_button.cc b/chrome/browser/chromeos/frame/layout_mode_button.cc
new file mode 100644
index 0000000..ffc2f41
--- /dev/null
+++ b/chrome/browser/chromeos/frame/layout_mode_button.cc
@@ -0,0 +1,100 @@
+// Copyright (c) 2011 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.
+
+#include "chrome/browser/chromeos/frame/layout_mode_button.h"
+
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/chromeos/wm_ipc.h"
+#include "content/common/notification_details.h"
+#include "content/common/notification_source.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "third_party/cros/chromeos_wm_ipc_enums.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "views/widget/widget.h"
+
+namespace {
+const int kHorizontalPaddingPixels = 2;
+} // namespace
+
+namespace chromeos {
+
+LayoutModeButton::LayoutModeButton()
+ : ALLOW_THIS_IN_INITIALIZER_LIST(ImageButton(this)) {
+}
+
+LayoutModeButton::~LayoutModeButton() {
+}
+
+gfx::Size LayoutModeButton::GetPreferredSize() {
+ gfx::Size size = ImageButton::GetPreferredSize();
+ size.Enlarge(2 * kHorizontalPaddingPixels, 0);
+ return size;
+}
+
+bool LayoutModeButton::HitTest(const gfx::Point& l) const {
+ // Handle events above our bounds so that we'll see clicks occuring in the
+ // padding between the top of the screen and the button.
+ const gfx::Point point(l.x(), std::max(y(), l.y()));
+ return ImageButton::HitTest(point);
+}
+
+void LayoutModeButton::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(type == NotificationType::LAYOUT_MODE_CHANGED);
+ UpdateForCurrentLayoutMode();
+}
+
+void LayoutModeButton::Init() {
+ WmIpc* wm_ipc = WmIpc::instance();
+ registrar_.Add(this,
+ NotificationType::LAYOUT_MODE_CHANGED,
+ Source<WmIpc>(wm_ipc));
+ UpdateForCurrentLayoutMode();
+}
+
+void LayoutModeButton::ButtonPressed(views::Button* sender,
+ const views::Event& event) {
+ DCHECK_EQ(sender, this);
+ WmIpc* wm_ipc = WmIpc::instance();
+ const WmIpcLayoutMode mode = wm_ipc->layout_mode();
+
+ WmIpc::Message message(WM_IPC_MESSAGE_WM_SET_LAYOUT_MODE);
+ switch (mode) {
+ case WM_IPC_LAYOUT_MAXIMIZED:
+ message.set_param(0, WM_IPC_LAYOUT_OVERLAPPING);
+ break;
+ case WM_IPC_LAYOUT_OVERLAPPING:
+ message.set_param(0, WM_IPC_LAYOUT_MAXIMIZED);
+ break;
+ default:
+ DLOG(WARNING) << "Unknown layout mode " << mode;
+ message.set_param(0, WM_IPC_LAYOUT_MAXIMIZED);
+ }
+ wm_ipc->SendMessage(message);
+}
+
+void LayoutModeButton::UpdateForCurrentLayoutMode() {
+ const WmIpcLayoutMode mode = WmIpc::instance()->layout_mode();
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ switch (mode) {
+ case WM_IPC_LAYOUT_MAXIMIZED:
+ SetImage(BS_NORMAL, rb.GetBitmapNamed(IDR_STATUSBAR_WINDOW_RESTORE));
+ SetTooltipText(UTF16ToWide(
+ l10n_util::GetStringUTF16(IDS_STATUSBAR_WINDOW_RESTORE_TOOLTIP)));
+ break;
+ case WM_IPC_LAYOUT_OVERLAPPING:
+ SetImage(BS_NORMAL, rb.GetBitmapNamed(IDR_STATUSBAR_WINDOW_MAXIMIZE));
+ SetTooltipText(UTF16ToWide(
+ l10n_util::GetStringUTF16(IDS_STATUSBAR_WINDOW_MAXIMIZE_TOOLTIP)));
+ break;
+ default:
+ DLOG(WARNING) << "Unknown layout mode " << mode;
+ }
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/frame/layout_mode_button.h b/chrome/browser/chromeos/frame/layout_mode_button.h
new file mode 100644
index 0000000..3e7e98d8
--- /dev/null
+++ b/chrome/browser/chromeos/frame/layout_mode_button.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2011 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.
+
+#ifndef CHROME_BROWSER_CHROMEOS_FRAME_LAYOUT_MODE_BUTTON_H_
+#define CHROME_BROWSER_CHROMEOS_FRAME_LAYOUT_MODE_BUTTON_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "content/common/notification_observer.h"
+#include "content/common/notification_registrar.h"
+#include "views/controls/button/button.h"
+#include "views/controls/button/image_button.h"
+
+class NotificationDetails;
+class NotificationSource;
+
+namespace chromeos {
+
+// Maximize/restore button in the corner of each browser window.
+class LayoutModeButton : public views::ImageButton,
+ public views::ButtonListener,
+ public NotificationObserver {
+ public:
+ LayoutModeButton();
+ virtual ~LayoutModeButton();
+
+ // views::* override.
+ virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual bool HitTest(const gfx::Point& l) const OVERRIDE;
+
+ // NotificationObserver implementation.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) OVERRIDE;
+
+ void Init();
+
+ private:
+ // views::ButtonListener implementation.
+ virtual void ButtonPressed(views::Button* sender, const views::Event& event)
+ OVERRIDE;
+
+ // Update our icon and tooltip appropriately for the current layout mode.
+ void UpdateForCurrentLayoutMode();
+
+ // A registrar for subscribing to LAYOUT_MODE_CHANGED notifications.
+ NotificationRegistrar registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(LayoutModeButton);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_FRAME_LAYOUT_MODE_BUTTON_H_
diff --git a/chrome/browser/chromeos/status/status_area_view.cc b/chrome/browser/chromeos/status/status_area_view.cc
index f34e4cd..806c32be 100644
--- a/chrome/browser/chromeos/status/status_area_view.cc
+++ b/chrome/browser/chromeos/status/status_area_view.cc
@@ -11,7 +11,6 @@
#include "chrome/browser/chromeos/status/network_menu_button.h"
#include "chrome/browser/chromeos/status/power_menu_button.h"
#include "chrome/browser/chromeos/status/status_area_host.h"
-#include "chrome/browser/chromeos/status/window_switcher_button.h"
#include "grit/theme_resources.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
@@ -32,8 +31,7 @@
clock_view_(NULL),
input_method_view_(NULL),
network_view_(NULL),
- power_view_(NULL),
- window_switcher_view_(NULL) {
+ power_view_(NULL) {
}
void StatusAreaView::Init() {
@@ -53,10 +51,6 @@
// Power.
power_view_ = new PowerMenuButton(host_);
AddChildView(power_view_);
-
- // Window Switcher.
- window_switcher_view_ = new WindowSwitcherButton(host_);
- AddChildView(window_switcher_view_);
}
gfx::Size StatusAreaView::GetPreferredSize() {
diff --git a/chrome/browser/chromeos/status/status_area_view.h b/chrome/browser/chromeos/status/status_area_view.h
index 1b858f7..23b7ae9 100644
--- a/chrome/browser/chromeos/status/status_area_view.h
+++ b/chrome/browser/chromeos/status/status_area_view.h
@@ -17,7 +17,6 @@
class NetworkMenuButton;
class PowerMenuButton;
class StatusAreaHost;
-class WindowSwitcherButton;
// This class is used to wrap the small informative widgets in the upper-right
// of the window title bar. It is used on ChromeOS only.
@@ -38,9 +37,6 @@
InputMethodMenuButton* input_method_view() { return input_method_view_; }
NetworkMenuButton* network_view() { return network_view_; }
PowerMenuButton* power_view() { return power_view_; }
- WindowSwitcherButton* window_switcher_view() {
- return window_switcher_view_;
- }
private:
StatusAreaHost* host_;
@@ -49,7 +45,6 @@
InputMethodMenuButton* input_method_view_;
NetworkMenuButton* network_view_;
PowerMenuButton* power_view_;
- WindowSwitcherButton* window_switcher_view_;
DISALLOW_COPY_AND_ASSIGN(StatusAreaView);
};
diff --git a/chrome/browser/chromeos/status/window_switcher_button.cc b/chrome/browser/chromeos/status/window_switcher_button.cc
deleted file mode 100644
index f51129d..0000000
--- a/chrome/browser/chromeos/status/window_switcher_button.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (c) 2011 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.
-
-#include "chrome/browser/chromeos/status/window_switcher_button.h"
-
-#include "chrome/browser/chromeos/status/status_area_host.h"
-#include "chrome/browser/chromeos/wm_ipc.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/gfx/canvas.h"
-
-namespace chromeos {
-
-namespace {
-int GetNormalBrowserCount() {
- int count = 0;
- BrowserList::const_iterator iter;
- for (iter = BrowserList::begin(); iter != BrowserList::end(); ++iter) {
- if ((*iter)->is_type_tabbed())
- count++;
- }
- return count;
-}
-}
-
-WindowSwitcherButton::WindowSwitcherButton(StatusAreaHost* host)
- : StatusAreaButton(host, this) {
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- SetIcon(*rb.GetBitmapNamed(IDR_STATUSBAR_WINDOW_SWITCHER));
- SetEnabled(true);
-
- UpdateStatus();
- BrowserList::AddObserver(this);
-}
-
-WindowSwitcherButton::~WindowSwitcherButton() {
- BrowserList::RemoveObserver(this);
-}
-
-void WindowSwitcherButton::UpdateStatus() {
- if (GetNormalBrowserCount() < 2) {
- // There are less than two browsers. This means we can't switch
- // anywhere, so we disappear.
- SetTooltipText(L"");
- SetVisible(false);
- PreferredSizeChanged();
- return;
- }
-
- SetTooltipText(UTF16ToWide(l10n_util::GetStringUTF16(
- IDS_STATUSBAR_WINDOW_SWITCHER_TOOLTIP)));
-
- // There are at least two browsers, so we show ourselves.
- SetVisible(true);
- PreferredSizeChanged();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// WindowSwitcherButton, views::ViewMenuDelegate implementation:
-
-void WindowSwitcherButton::RunMenu(views::View* source, const gfx::Point& pt) {
- // Don't do anything if there aren't at least two normal browsers to
- // switch between.
- if (GetNormalBrowserCount() < 2)
- return;
-
- // Send a message to the ChromeOS window manager to switch to the
- // next top level browser window. Only the window manager knows
- // what order they are in, so we can't use Chrome's browser list
- // to decide.
- WmIpc::Message message(chromeos::WM_IPC_MESSAGE_WM_CYCLE_WINDOWS);
- message.set_param(0, true);
- WmIpc::instance()->SendMessage(message);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// BrowserList::Observer implementation:
-
-// Called immediately after a browser is added to the list
-void WindowSwitcherButton::OnBrowserAdded(const Browser* browser) {
- UpdateStatus();
-}
-
-// Called immediately after a browser is removed from the list
-void WindowSwitcherButton::OnBrowserRemoved(const Browser* browser) {
- UpdateStatus();
-}
-
-} // namespace chromeos
diff --git a/chrome/browser/chromeos/status/window_switcher_button.h b/chrome/browser/chromeos/status/window_switcher_button.h
deleted file mode 100644
index 7ed086d..0000000
--- a/chrome/browser/chromeos/status/window_switcher_button.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef CHROME_BROWSER_CHROMEOS_STATUS_WINDOW_SWITCHER_BUTTON_H_
-#define CHROME_BROWSER_CHROMEOS_STATUS_WINDOW_SWITCHER_BUTTON_H_
-#pragma once
-
-#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/chromeos/status/status_area_button.h"
-#include "chrome/browser/ui/browser_list.h"
-#include "content/common/notification_observer.h"
-#include "views/controls/button/menu_button.h"
-#include "views/controls/menu/view_menu_delegate.h"
-
-namespace chromeos {
-
-class StatusAreaHost;
-
-// The window switcher button in the status area. This button allows
-// the user to move to the next window if they click on the icon.
-class WindowSwitcherButton : public StatusAreaButton,
- public views::ViewMenuDelegate,
- public BrowserList::Observer {
- public:
- explicit WindowSwitcherButton(StatusAreaHost* host);
- virtual ~WindowSwitcherButton();
-
- private:
- // Updates the status of the button based on the state of the
- // browser list.
- void UpdateStatus();
-
- // BrowserList::Observer API
- virtual void OnBrowserAdded(const Browser* browser);
- virtual void OnBrowserRemoved(const Browser* browser);
-
- // views::ViewMenuDelegate implementation.
- virtual void RunMenu(views::View* source, const gfx::Point& pt);
-
- DISALLOW_COPY_AND_ASSIGN(WindowSwitcherButton);
-};
-
-} // namespace chromeos
-
-#endif // CHROME_BROWSER_CHROMEOS_STATUS_WINDOW_SWITCHER_BUTTON_H_
diff --git a/chrome/browser/chromeos/view_ids.h b/chrome/browser/chromeos/view_ids.h
index 090490e..6d31565 100644
--- a/chrome/browser/chromeos/view_ids.h
+++ b/chrome/browser/chromeos/view_ids.h
@@ -15,6 +15,7 @@
VIEW_ID_STATUS_AREA = VIEW_ID_PREDEFINED_COUNT + 10000,
VIEW_ID_SCREEN_LOCKER_SIGNOUT_LINK,
VIEW_ID_SCREEN_LOCKER_SHUTDOWN,
+ VIEW_ID_LAYOUT_MODE_BUTTON,
};
#endif // CHROME_BROWSER_CHROMEOS_VIEW_IDS_H_
diff --git a/chrome/browser/chromeos/wm_ipc.cc b/chrome/browser/chromeos/wm_ipc.cc
index 97e1e56..aad446c6 100644
--- a/chrome/browser/chromeos/wm_ipc.cc
+++ b/chrome/browser/chromeos/wm_ipc.cc
@@ -12,6 +12,7 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "content/common/notification_service.h"
#include "ui/base/x/x11_util.h"
using std::map;
@@ -30,6 +31,7 @@
// Each value from the Atom enum must be present here.
static const AtomInfo kAtomInfos[] = {
+ { WmIpc::ATOM_CHROME_LAYOUT_MODE, "_CHROME_LAYOUT_MODE" },
{ WmIpc::ATOM_CHROME_LOGGED_IN, "_CHROME_LOGGED_IN" },
{ WmIpc::ATOM_CHROME_STATE, "_CHROME_STATE" },
{ WmIpc::ATOM_CHROME_STATE_COLLAPSED_PANEL, "_CHROME_STATE_COLLAPSED_PANEL" },
@@ -200,6 +202,14 @@
}
}
+void WmIpc::HandleRootWindowPropertyEvent(const GdkEventProperty& event) {
+ static GdkAtom layout_mode_gdk_atom =
+ gdk_x11_xatom_to_atom(type_to_atom_[ATOM_CHROME_LAYOUT_MODE]);
+
+ if (event.atom == layout_mode_gdk_atom)
+ FetchLayoutModeProperty();
+}
+
void WmIpc::SetLoggedInProperty(bool logged_in) {
std::vector<int> values;
values.push_back(static_cast<int>(logged_in));
@@ -214,7 +224,10 @@
XFlush(ui::GetXDisplay());
}
-WmIpc::WmIpc() {
+WmIpc::WmIpc()
+ : wm_message_atom_(0),
+ wm_(0),
+ layout_mode_(WM_IPC_LAYOUT_MAXIMIZED) {
scoped_array<char*> names(new char*[kNumAtoms]);
scoped_array<Atom> atoms(new Atom[kNumAtoms]);
@@ -241,9 +254,12 @@
GdkWindow* root = gdk_get_default_root_window();
GdkEventMask event_mask = gdk_window_get_events(root);
gdk_window_set_events(
- root, static_cast<GdkEventMask>(event_mask | GDK_STRUCTURE_MASK));
+ root,
+ static_cast<GdkEventMask>(
+ event_mask | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK));
InitWmInfo();
+ FetchLayoutModeProperty();
}
WmIpc::~WmIpc() {}
@@ -260,4 +276,20 @@
SendMessage(msg);
}
+void WmIpc::FetchLayoutModeProperty() {
+ int value = 0;
+ if (ui::GetIntProperty(
+ gdk_x11_get_default_root_xwindow(),
+ GetAtomName(ATOM_CHROME_LAYOUT_MODE),
+ &value)) {
+ layout_mode_ = static_cast<WmIpcLayoutMode>(value);
+ NotificationService::current()->Notify(
+ NotificationType::LAYOUT_MODE_CHANGED,
+ Source<WmIpc>(this),
+ Details<WmIpcLayoutMode>(&layout_mode_));
+ } else {
+ DLOG(WARNING) << "Missing _CHROME_LAYOUT_MODE property on root window";
+ }
+}
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/wm_ipc.h b/chrome/browser/chromeos/wm_ipc.h
index cb08351..152323b8 100644
--- a/chrome/browser/chromeos/wm_ipc.h
+++ b/chrome/browser/chromeos/wm_ipc.h
@@ -27,7 +27,8 @@
class WmIpc {
public:
enum AtomType {
- ATOM_CHROME_LOGGED_IN = 0,
+ ATOM_CHROME_LAYOUT_MODE = 0,
+ ATOM_CHROME_LOGGED_IN,
ATOM_CHROME_STATE,
ATOM_CHROME_STATE_COLLAPSED_PANEL,
ATOM_CHROME_STATE_STATUS_HIDDEN,
@@ -88,6 +89,8 @@
// Returns the single instance of WmIpc.
static WmIpc* instance();
+ WmIpcLayoutMode layout_mode() const { return layout_mode_; }
+
// Gets or sets a property describing a window's type.
// WmIpcMessageType is defined in chromeos_wm_ipc_enums.h. Type-specific
// parameters may also be supplied. The caller is responsible for trapping
@@ -122,6 +125,9 @@
// See ICCCM 2.8 for more info about MANAGER selections.
void HandleNonChromeClientMessageEvent(const GdkEventClient& event);
+ // Handle an event reporting a property change on the root window.
+ void HandleRootWindowPropertyEvent(const GdkEventProperty& event);
+
// Sets a _CHROME_LOGGED_IN property on the root window describing whether
// the user is currently logged in or not.
void SetLoggedInProperty(bool logged_in);
@@ -135,11 +141,15 @@
WmIpc();
~WmIpc();
- // Initialize 'wm_' and send the window manager a message telling it the
+ // Initializes 'wm_' and sends the window manager a message telling it the
// version of the IPC protocol that we support. This is called in our
// constructor, but needs to be re-run if the window manager gets restarted.
void InitWmInfo();
+ // Updates |layout_mode_| based on the current value of the root window's
+ // _CHROME_LAYOUT_MODE property.
+ void FetchLayoutModeProperty();
+
// Maps between our Atom enum and the X server's atom IDs and from the
// server's IDs to atoms' string names.
std::map<AtomType, Atom> type_to_atom_;
@@ -149,9 +159,12 @@
// Cached value of type_to_atom_[ATOM_CHROME_WM_MESSAGE].
Atom wm_message_atom_;
- // Handle to the wm. Used for sending messages.
+ // Handle to the WM. Used for sending messages.
XID wm_;
+ // The current value of the root window's _CHROME_LAYOUT_MODE property.
+ WmIpcLayoutMode layout_mode_;
+
DISALLOW_COPY_AND_ASSIGN(WmIpc);
};
diff --git a/chrome/browser/chromeos/wm_message_listener.cc b/chrome/browser/chromeos/wm_message_listener.cc
index c0815e4..aa493a3 100644
--- a/chrome/browser/chromeos/wm_message_listener.cc
+++ b/chrome/browser/chromeos/wm_message_listener.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -28,6 +28,11 @@
ProcessMessage(message, client_event->window);
else
wm_ipc->HandleNonChromeClientMessageEvent(*client_event);
+ } else if (event->type == GDK_PROPERTY_NOTIFY) {
+ GdkEventProperty* property_event =
+ reinterpret_cast<GdkEventProperty*>(event);
+ if (property_event->window == gdk_get_default_root_window())
+ WmIpc::instance()->HandleRootWindowPropertyEvent(*property_event);
}
}
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 2964ee9..435c88b3 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -413,6 +413,8 @@
'browser/chromeos/frame/bubble_frame_view.h',
'browser/chromeos/frame/bubble_window.cc',
'browser/chromeos/frame/bubble_window.h',
+ 'browser/chromeos/frame/layout_mode_button.cc',
+ 'browser/chromeos/frame/layout_mode_button.h',
'browser/chromeos/frame/panel_browser_view.cc',
'browser/chromeos/frame/panel_browser_view.h',
'browser/chromeos/frame/panel_controller.cc',
@@ -699,8 +701,6 @@
'browser/chromeos/status/status_area_host.h',
'browser/chromeos/status/status_area_view.cc',
'browser/chromeos/status/status_area_view.h',
- 'browser/chromeos/status/window_switcher_button.cc',
- 'browser/chromeos/status/window_switcher_button.h',
'browser/chromeos/system_access.cc',
'browser/chromeos/system_access.h',
'browser/chromeos/system_key_event_listener.cc',
diff --git a/content/common/notification_type.h b/content/common/notification_type.h
index 418df4ec..c51f947c 100644
--- a/content/common/notification_type.h
+++ b/content/common/notification_type.h
@@ -1228,6 +1228,9 @@
// Sent when a panel state changed.
PANEL_STATE_CHANGED,
+ // Sent when the window manager's layout mode has changed.
+ LAYOUT_MODE_CHANGED,
+
// Sent when the wizard's content view is destroyed. The source and details
// are not used.
WIZARD_CONTENT_VIEW_DESTROYED,