From 2ee7caccfe28bce11b640cf3193352e12673b3c4 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 16 Jul 2014 22:10:10 +0800 Subject: [PATCH] views: Add an empty menu bar. --- atom.gyp | 4 ++ atom/browser/native_window_views.cc | 49 ++++++++++++++---- atom/browser/native_window_views.h | 6 +++ atom/browser/ui/views/global_menu_bar_x11.cc | 8 ++- atom/browser/ui/views/global_menu_bar_x11.h | 1 + atom/browser/ui/views/menu_bar.cc | 34 ++++++++++++ atom/browser/ui/views/menu_bar.h | 28 ++++++++++ atom/browser/ui/views/menu_layout.cc | 54 ++++++++++++++++++++ atom/browser/ui/views/menu_layout.h | 32 ++++++++++++ 9 files changed, 205 insertions(+), 11 deletions(-) create mode 100644 atom/browser/ui/views/menu_bar.cc create mode 100644 atom/browser/ui/views/menu_bar.h create mode 100644 atom/browser/ui/views/menu_layout.cc create mode 100644 atom/browser/ui/views/menu_layout.h diff --git a/atom.gyp b/atom.gyp index 6b0a7fa49929..249c9611215d 100644 --- a/atom.gyp +++ b/atom.gyp @@ -141,6 +141,10 @@ 'atom/browser/ui/views/global_menu_bar_x11.h', 'atom/browser/ui/views/linux_frame_view.cc', 'atom/browser/ui/views/linux_frame_view.h', + 'atom/browser/ui/views/menu_bar.cc', + 'atom/browser/ui/views/menu_bar.h', + 'atom/browser/ui/views/menu_layout.cc', + 'atom/browser/ui/views/menu_layout.h', 'atom/browser/ui/views/win_frame_view.cc', 'atom/browser/ui/views/win_frame_view.h', 'atom/browser/ui/win/notify_icon_host.cc', diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index b0e3784e123d..86311e5d14e4 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -7,6 +7,8 @@ #include #include +#include "atom/browser/ui/views/menu_bar.h" +#include "atom/browser/ui/views/menu_layout.h" #include "atom/common/draggable_region.h" #include "atom/common/options_switches.h" #include "base/strings/utf_string_conversions.h" @@ -20,7 +22,6 @@ #include "ui/views/background.h" #include "ui/views/controls/webview/unhandled_keyboard_event_handler.h" #include "ui/views/controls/webview/webview.h" -#include "ui/views/layout/fill_layout.h" #include "ui/views/window/client_view.h" #include "ui/views/widget/widget.h" @@ -35,6 +36,9 @@ namespace atom { namespace { +// The menu bar height in pixels. +const int kMenuBarHeight = 25; + class NativeWindowClientView : public views::ClientView { public: NativeWindowClientView(views::Widget* widget, @@ -58,6 +62,7 @@ NativeWindowViews::NativeWindowViews(content::WebContents* web_contents, const mate::Dictionary& options) : NativeWindow(web_contents, options), window_(new views::Widget), + menu_bar_(NULL), web_view_(inspectable_web_contents()->GetView()->GetView()), keyboard_event_handler_(new views::UnhandledKeyboardEventHandler), resizable_(true) { @@ -93,7 +98,7 @@ NativeWindowViews::NativeWindowViews(content::WebContents* web_contents, window_->Init(params); // Add web view. - SetLayoutManager(new views::FillLayout); + SetLayoutManager(new MenuLayout(kMenuBarHeight)); set_background(views::Background::CreateStandardPanelBackground()); AddChildView(web_view_); @@ -101,7 +106,7 @@ NativeWindowViews::NativeWindowViews(content::WebContents* web_contents, if (has_frame_ && options.Get(switches::kUseContentSize, &use_content_size) && use_content_size) - bounds = window_->non_client_view()->GetWindowBoundsForClientBounds(bounds); + bounds = ContentBoundsToWindowBounds(bounds); window_->CenterWindow(bounds.size()); Layout(); @@ -190,16 +195,18 @@ void NativeWindowViews::SetContentSize(const gfx::Size& size) { gfx::Rect bounds = window_->GetWindowBoundsInScreen(); bounds.set_size(size); - window_->SetBounds( - window_->non_client_view()->GetWindowBoundsForClientBounds(bounds)); + window_->SetBounds(ContentBoundsToWindowBounds(bounds)); } gfx::Size NativeWindowViews::GetContentSize() { if (!has_frame_) return GetSize(); - return window_->non_client_view()->frame_view()-> - GetBoundsForClientView().size(); + gfx::Size content_size = + window_->non_client_view()->frame_view()->GetBoundsForClientView().size(); + if (menu_bar_) + content_size.set_height(content_size.height() - kMenuBarHeight); + return content_size; } void NativeWindowViews::SetMinimumSize(const gfx::Size& size) { @@ -274,14 +281,29 @@ bool NativeWindowViews::IsKiosk() { } void NativeWindowViews::SetMenu(ui::MenuModel* menu_model) { - // FIXME RegisterAccelerators(menu_model); #if defined(USE_X11) if (!global_menu_bar_) global_menu_bar_.reset(new GlobalMenuBarX11(this)); - global_menu_bar_->SetMenu(menu_model); + + // Use global application menu bar when possible. + if (global_menu_bar_->IsServerStarted()) { + global_menu_bar_->SetMenu(menu_model); + return; + } #endif + + // Do not show menu bar in frameless window. + if (!has_frame_) + return; + + if (!menu_bar_) { + gfx::Size content_size = GetContentSize(); + menu_bar_ = new MenuBar; + AddChildViewAt(menu_bar_, 0); + SetContentSize(content_size); + } } gfx::NativeWindow NativeWindowViews::GetNativeWindow() { @@ -430,6 +452,15 @@ void NativeWindowViews::RegisterAccelerators(ui::MenuModel* menu_model) { } } +gfx::Rect NativeWindowViews::ContentBoundsToWindowBounds( + const gfx::Rect& bounds) { + gfx::Rect window_bounds = + window_->non_client_view()->GetWindowBoundsForClientBounds(bounds); + if (menu_bar_) + window_bounds.set_height(window_bounds.height() + kMenuBarHeight); + return window_bounds; +} + // static NativeWindow* NativeWindow::Create(content::WebContents* web_contents, const mate::Dictionary& options) { diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h index 5e2094036e24..c4cf6cb80940 100644 --- a/atom/browser/native_window_views.h +++ b/atom/browser/native_window_views.h @@ -22,6 +22,7 @@ class Widget; namespace atom { class GlobalMenuBarX11; +class MenuBar; class NativeWindowViews : public NativeWindow, public views::WidgetDelegateView, @@ -113,7 +114,12 @@ class NativeWindowViews : public NativeWindow, // Register accelerators supported by the menu model. void RegisterAccelerators(ui::MenuModel* menu_model); + // Converts between client area and window area, since we include the menu bar + // in client area we need to substract/add menu bar's height in convertions. + gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& content_bounds); + scoped_ptr window_; + MenuBar* menu_bar_; views::View* web_view_; // Managed by inspectable_web_contents_. #if defined(USE_X11) diff --git a/atom/browser/ui/views/global_menu_bar_x11.cc b/atom/browser/ui/views/global_menu_bar_x11.cc index eeecb2a1735f..4b7338eab16c 100644 --- a/atom/browser/ui/views/global_menu_bar_x11.cc +++ b/atom/browser/ui/views/global_menu_bar_x11.cc @@ -171,7 +171,7 @@ GlobalMenuBarX11::GlobalMenuBarX11(NativeWindowViews* window) } GlobalMenuBarX11::~GlobalMenuBarX11() { - if (server_) + if (IsServerStarted()) g_object_unref(server_); GlobalMenuBarRegistrarX11::GetInstance()->OnWindowUnmapped(xid_); @@ -183,7 +183,7 @@ std::string GlobalMenuBarX11::GetPathForWindow(gfx::AcceleratedWidget xid) { } void GlobalMenuBarX11::SetMenu(ui::MenuModel* menu_model) { - if (!server_) + if (!IsServerStarted()) return; DbusmenuMenuitem* root_item = menuitem_new(); @@ -195,6 +195,10 @@ void GlobalMenuBarX11::SetMenu(ui::MenuModel* menu_model) { g_object_unref(root_item); } +bool GlobalMenuBarX11::IsServerStarted() const { + return server_; +} + void GlobalMenuBarX11::InitServer(gfx::AcceleratedWidget xid) { std::string path = GetPathForWindow(xid); server_ = server_new(path.c_str()); diff --git a/atom/browser/ui/views/global_menu_bar_x11.h b/atom/browser/ui/views/global_menu_bar_x11.h index a3ff7cb86da4..09d2eb6d1342 100644 --- a/atom/browser/ui/views/global_menu_bar_x11.h +++ b/atom/browser/ui/views/global_menu_bar_x11.h @@ -44,6 +44,7 @@ class GlobalMenuBarX11 { static std::string GetPathForWindow(gfx::AcceleratedWidget xid); void SetMenu(ui::MenuModel* menu_model); + bool IsServerStarted() const; private: // Creates a DbusmenuServer. diff --git a/atom/browser/ui/views/menu_bar.cc b/atom/browser/ui/views/menu_bar.cc new file mode 100644 index 000000000000..3580cd241ada --- /dev/null +++ b/atom/browser/ui/views/menu_bar.cc @@ -0,0 +1,34 @@ +// Copyright (c) 2014 GitHub, Inc. All rights reserved. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/ui/views/menu_bar.h" + +#include "ui/gfx/canvas.h" + +namespace atom { + +namespace { + +const char kViewClassName[] = "AtomMenuBar"; + +// Default color of the menu bar. +const SkColor kDefaultColor = SkColorSetARGB(255, 233, 233, 233); + +} // namespace + +MenuBar::MenuBar() { +} + +MenuBar::~MenuBar() { +} + +void MenuBar::Paint(gfx::Canvas* canvas) { + canvas->FillRect(bounds(), kDefaultColor); +} + +const char* MenuBar::GetClassName() const { + return kViewClassName; +} + +} // namespace atom diff --git a/atom/browser/ui/views/menu_bar.h b/atom/browser/ui/views/menu_bar.h new file mode 100644 index 000000000000..1b537f44b3bf --- /dev/null +++ b/atom/browser/ui/views/menu_bar.h @@ -0,0 +1,28 @@ +// Copyright (c) 2014 GitHub, Inc. All rights reserved. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_UI_VIEWS_MENU_BAR_H_ +#define ATOM_BROWSER_UI_VIEWS_MENU_BAR_H_ + +#include "ui/views/view.h" + +namespace atom { + +class MenuBar : public views::View { + public: + MenuBar(); + virtual ~MenuBar(); + + protected: + // views::View: + virtual void Paint(gfx::Canvas* canvas) OVERRIDE; + virtual const char* GetClassName() const OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(MenuBar); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_UI_VIEWS_MENU_BAR_H_ diff --git a/atom/browser/ui/views/menu_layout.cc b/atom/browser/ui/views/menu_layout.cc new file mode 100644 index 000000000000..cb92e98f4ebd --- /dev/null +++ b/atom/browser/ui/views/menu_layout.cc @@ -0,0 +1,54 @@ +// Copyright (c) 2014 GitHub, Inc. All rights reserved. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/ui/views/menu_layout.h" + +namespace atom { + +MenuLayout::MenuLayout(int menu_height) + : menu_height_(menu_height) { +} + +MenuLayout::~MenuLayout() { +} + +void MenuLayout::Layout(views::View* host) { + if (!HasMenu(host)) { + views::FillLayout::Layout(host); + return; + } + + gfx::Size size = host->GetContentsBounds().size(); + gfx::Rect menu_Bar_bounds = gfx::Rect(0, 0, size.width(), menu_height_); + gfx::Rect web_view_bounds = gfx::Rect( + 0, menu_height_, size.width(), size.height() - menu_height_); + + views::View* menu_bar = host->child_at(0); + views::View* web_view = host->child_at(1); + menu_bar->SetBoundsRect(menu_Bar_bounds); + web_view->SetBoundsRect(web_view_bounds); +} + +gfx::Size MenuLayout::GetPreferredSize(views::View* host) { + gfx::Size size = views::FillLayout::GetPreferredSize(host); + if (!HasMenu(host)) + return size; + + size.set_height(size.height() + menu_height_); + return size; +} + +int MenuLayout::GetPreferredHeightForWidth(views::View* host, int width) { + int height = views::FillLayout::GetPreferredHeightForWidth(host, width); + if (!HasMenu(host)) + return height; + + return height + menu_height_; +} + +bool MenuLayout::HasMenu(const views::View* host) const { + return host->child_count() == 2; +} + +} // namespace atom diff --git a/atom/browser/ui/views/menu_layout.h b/atom/browser/ui/views/menu_layout.h new file mode 100644 index 000000000000..1b3d78e28d96 --- /dev/null +++ b/atom/browser/ui/views/menu_layout.h @@ -0,0 +1,32 @@ +// Copyright (c) 2014 GitHub, Inc. All rights reserved. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_UI_VIEWS_MENU_LAYOUT_H_ +#define ATOM_BROWSER_UI_VIEWS_MENU_LAYOUT_H_ + +#include "ui/views/layout/fill_layout.h" + +namespace atom { + +class MenuLayout : public views::FillLayout { + public: + explicit MenuLayout(int menu_height); + virtual ~MenuLayout(); + + // views::LayoutManager: + virtual void Layout(views::View* host) OVERRIDE; + virtual gfx::Size GetPreferredSize(views::View* host) OVERRIDE; + virtual int GetPreferredHeightForWidth(views::View* host, int width) OVERRIDE; + + private: + bool HasMenu(const views::View* host) const; + + int menu_height_; + + DISALLOW_COPY_AND_ASSIGN(MenuLayout); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_UI_VIEWS_MENU_LAYOUT_H_