Browse Source

views: Add an empty menu bar.

Cheng Zhao 10 years ago
parent
commit
2ee7caccfe

+ 4 - 0
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',

+ 40 - 9
atom/browser/native_window_views.cc

@@ -7,6 +7,8 @@
 #include <string>
 #include <vector>
 
+#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) {

+ 6 - 0
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<views::Widget> window_;
+  MenuBar* menu_bar_;
   views::View* web_view_;  // Managed by inspectable_web_contents_.
 
 #if defined(USE_X11)

+ 6 - 2
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());

+ 1 - 0
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.

+ 34 - 0
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

+ 28 - 0
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_

+ 54 - 0
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

+ 32 - 0
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_