Commit a4102566 authored by Evan Stade's avatar Evan Stade Committed by Commit Bot

Mash: add support for window frame context menus on Ash-provided frames

Adds a single-item context menu for Hosted app windows (teleport
window). This is currently only supported in single process Mash
because multi user window manager doesn't work in multi process Mash.

Bug: 887051
Change-Id: Ifd1c7a08acf46615ff5fec2f0e7a614c9c99775c
Reviewed-on: https://chromium-review.googlesource.com/c/1287202Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Commit-Queue: Evan Stade <estade@chromium.org>
Cr-Commit-Position: refs/heads/master@{#601184}
parent 2baa8027
...@@ -32,13 +32,20 @@ ...@@ -32,13 +32,20 @@
#include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
#include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/view.h" #include "ui/views/view.h"
#include "ui/views/view_targeter.h" #include "ui/views/view_targeter.h"
#include "ui/views/widget/widget.h" #include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h" #include "ui/views/widget/widget_delegate.h"
DEFINE_UI_CLASS_PROPERTY_TYPE(ash::NonClientFrameViewAsh*);
namespace ash { namespace ash {
DEFINE_UI_CLASS_PROPERTY_KEY(NonClientFrameViewAsh*,
kNonClientFrameViewAshKey,
nullptr);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// NonClientFrameViewAshWindowStateDelegate // NonClientFrameViewAshWindowStateDelegate
...@@ -250,6 +257,8 @@ NonClientFrameViewAsh::NonClientFrameViewAsh(views::Widget* frame) ...@@ -250,6 +257,8 @@ NonClientFrameViewAsh::NonClientFrameViewAsh(views::Widget* frame)
} }
Shell::Get()->AddShellObserver(this); Shell::Get()->AddShellObserver(this);
Shell::Get()->split_view_controller()->AddObserver(this); Shell::Get()->split_view_controller()->AddObserver(this);
frame_window->SetProperty(kNonClientFrameViewAshKey, this);
} }
NonClientFrameViewAsh::~NonClientFrameViewAsh() { NonClientFrameViewAsh::~NonClientFrameViewAsh() {
...@@ -258,6 +267,11 @@ NonClientFrameViewAsh::~NonClientFrameViewAsh() { ...@@ -258,6 +267,11 @@ NonClientFrameViewAsh::~NonClientFrameViewAsh() {
Shell::Get()->split_view_controller()->RemoveObserver(this); Shell::Get()->split_view_controller()->RemoveObserver(this);
} }
// static
NonClientFrameViewAsh* NonClientFrameViewAsh::Get(aura::Window* window) {
return window->GetProperty(kNonClientFrameViewAshKey);
}
void NonClientFrameViewAsh::InitImmersiveFullscreenControllerForView( void NonClientFrameViewAsh::InitImmersiveFullscreenControllerForView(
ImmersiveFullscreenController* immersive_fullscreen_controller) { ImmersiveFullscreenController* immersive_fullscreen_controller) {
immersive_fullscreen_controller->Init(header_view_, frame_, header_view_); immersive_fullscreen_controller->Init(header_view_, frame_, header_view_);
...@@ -291,6 +305,23 @@ gfx::Rect NonClientFrameViewAsh::GetClientBoundsForWindowBounds( ...@@ -291,6 +305,23 @@ gfx::Rect NonClientFrameViewAsh::GetClientBoundsForWindowBounds(
return client_bounds; return client_bounds;
} }
void NonClientFrameViewAsh::SetWindowFrameMenuItems(
const menu_utils::MenuItemList& menu_item_list,
mojom::MenuDelegatePtr delegate) {
if (menu_item_list.empty()) {
menu_model_.reset();
menu_delegate_.reset();
} else {
menu_model_ = std::make_unique<ui::SimpleMenuModel>(this);
menu_utils::PopulateMenuFromMojoMenuItems(menu_model_.get(), nullptr,
menu_item_list, nullptr);
menu_delegate_ = std::move(delegate);
}
header_view_->set_context_menu_controller(menu_item_list.empty() ? nullptr
: this);
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// NonClientFrameViewAsh, views::NonClientFrameView overrides: // NonClientFrameViewAsh, views::NonClientFrameView overrides:
...@@ -456,6 +487,33 @@ void NonClientFrameViewAsh::OnSplitViewStateChanged( ...@@ -456,6 +487,33 @@ void NonClientFrameViewAsh::OnSplitViewStateChanged(
UpdateHeaderView(); UpdateHeaderView();
} }
void NonClientFrameViewAsh::ShowContextMenuForView(
views::View* source,
const gfx::Point& point,
ui::MenuSourceType source_type) {
DCHECK_EQ(header_view_, source);
DCHECK(menu_model_);
menu_runner_ = std::make_unique<views::MenuRunner>(
menu_model_.get(),
views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU);
menu_runner_->RunMenuAt(GetWidget(), nullptr,
gfx::Rect(point, gfx::Size(0, 0)),
views::MENU_ANCHOR_TOPLEFT, source_type);
}
bool NonClientFrameViewAsh::IsCommandIdChecked(int command_id) const {
return false;
}
bool NonClientFrameViewAsh::IsCommandIdEnabled(int command_id) const {
return true;
}
void NonClientFrameViewAsh::ExecuteCommand(int command_id, int event_flags) {
menu_delegate_->MenuItemActivated(command_id);
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// NonClientFrameViewAsh, private: // NonClientFrameViewAsh, private:
......
...@@ -9,11 +9,16 @@ ...@@ -9,11 +9,16 @@
#include "ash/ash_export.h" #include "ash/ash_export.h"
#include "ash/frame/header_view.h" #include "ash/frame/header_view.h"
#include "ash/public/cpp/menu_utils.h"
#include "ash/public/interfaces/menu.mojom.h"
#include "ash/shell_observer.h" #include "ash/shell_observer.h"
#include "ash/wm/splitview/split_view_controller.h" #include "ash/wm/splitview/split_view_controller.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/optional.h" #include "base/optional.h"
#include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkColor.h"
#include "ui/base/models/simple_menu_model.h"
#include "ui/views/context_menu_controller.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/window/non_client_view.h" #include "ui/views/window/non_client_view.h"
namespace views { namespace views {
...@@ -36,7 +41,9 @@ class NonClientFrameViewAshImmersiveHelper; ...@@ -36,7 +41,9 @@ class NonClientFrameViewAshImmersiveHelper;
// BrowserNonClientFrameViewAsh. // BrowserNonClientFrameViewAsh.
class ASH_EXPORT NonClientFrameViewAsh : public views::NonClientFrameView, class ASH_EXPORT NonClientFrameViewAsh : public views::NonClientFrameView,
public ShellObserver, public ShellObserver,
public SplitViewController::Observer { public SplitViewController::Observer,
public views::ContextMenuController,
public ui::SimpleMenuModel::Delegate {
public: public:
// Internal class name. // Internal class name.
static const char kViewClassName[]; static const char kViewClassName[];
...@@ -50,6 +57,8 @@ class ASH_EXPORT NonClientFrameViewAsh : public views::NonClientFrameView, ...@@ -50,6 +57,8 @@ class ASH_EXPORT NonClientFrameViewAsh : public views::NonClientFrameView,
explicit NonClientFrameViewAsh(views::Widget* frame); explicit NonClientFrameViewAsh(views::Widget* frame);
~NonClientFrameViewAsh() override; ~NonClientFrameViewAsh() override;
static NonClientFrameViewAsh* Get(aura::Window* window);
// Sets the caption button modeland updates the caption buttons. // Sets the caption button modeland updates the caption buttons.
void SetCaptionButtonModel(std::unique_ptr<CaptionButtonModel> model); void SetCaptionButtonModel(std::unique_ptr<CaptionButtonModel> model);
...@@ -75,6 +84,12 @@ class ASH_EXPORT NonClientFrameViewAsh : public views::NonClientFrameView, ...@@ -75,6 +84,12 @@ class ASH_EXPORT NonClientFrameViewAsh : public views::NonClientFrameView,
gfx::Rect GetClientBoundsForWindowBounds( gfx::Rect GetClientBoundsForWindowBounds(
const gfx::Rect& window_bounds) const; const gfx::Rect& window_bounds) const;
// Sets the menu items to show in the context menu. If |menu_item_list| is
// empty, no context menu will be shown. Menu item activation is dispatched to
// |delegate|.
void SetWindowFrameMenuItems(const menu_utils::MenuItemList& menu_item_list,
mojom::MenuDelegatePtr delegate);
// views::NonClientFrameView: // views::NonClientFrameView:
gfx::Rect GetBoundsForClientView() const override; gfx::Rect GetBoundsForClientView() const override;
gfx::Rect GetWindowBoundsForClientBounds( gfx::Rect GetWindowBoundsForClientBounds(
...@@ -109,6 +124,16 @@ class ASH_EXPORT NonClientFrameViewAsh : public views::NonClientFrameView, ...@@ -109,6 +124,16 @@ class ASH_EXPORT NonClientFrameViewAsh : public views::NonClientFrameView,
void OnSplitViewStateChanged(SplitViewController::State previous_state, void OnSplitViewStateChanged(SplitViewController::State previous_state,
SplitViewController::State state) override; SplitViewController::State state) override;
// views::ContextMenuController:
void ShowContextMenuForView(View* source,
const gfx::Point& point,
ui::MenuSourceType source_type) override;
// ui::SimpleMenuModel::Delegate:
bool IsCommandIdChecked(int command_id) const override;
bool IsCommandIdEnabled(int command_id) const override;
void ExecuteCommand(int command_id, int event_flags) override;
const views::View* GetAvatarIconViewForTest() const; const views::View* GetAvatarIconViewForTest() const;
SkColor GetActiveFrameColorForTest() const; SkColor GetActiveFrameColorForTest() const;
...@@ -117,10 +142,10 @@ class ASH_EXPORT NonClientFrameViewAsh : public views::NonClientFrameView, ...@@ -117,10 +142,10 @@ class ASH_EXPORT NonClientFrameViewAsh : public views::NonClientFrameView,
views::Widget* frame() { return frame_; } views::Widget* frame() { return frame_; }
protected: protected:
// Called when overview mode or split view state changed. If overview mode and // Called when overview mode or split view state changed. If overview mode
// split view mode are both active at the same time, the header of the window // and split view mode are both active at the same time, the header of the
// in split view should be visible, but the headers of other windows in // window in split view should be visible, but the headers of other windows
// overview are not. // in overview are not.
void UpdateHeaderView(); void UpdateHeaderView();
private: private:
...@@ -133,8 +158,8 @@ class ASH_EXPORT NonClientFrameViewAsh : public views::NonClientFrameView, ...@@ -133,8 +158,8 @@ class ASH_EXPORT NonClientFrameViewAsh : public views::NonClientFrameView,
bool DoesIntersectRect(const views::View* target, bool DoesIntersectRect(const views::View* target,
const gfx::Rect& rect) const override; const gfx::Rect& rect) const override;
// Returns the container for the minimize/maximize/close buttons that is held // Returns the container for the minimize/maximize/close buttons that is
// by the HeaderView. Used in testing. // held by the HeaderView. Used in testing.
FrameCaptionButtonContainerView* GetFrameCaptionButtonContainerViewForTest(); FrameCaptionButtonContainerView* GetFrameCaptionButtonContainerViewForTest();
// Height from top of window to top of client area. // Height from top of window to top of client area.
...@@ -153,10 +178,16 @@ class ASH_EXPORT NonClientFrameViewAsh : public views::NonClientFrameView, ...@@ -153,10 +178,16 @@ class ASH_EXPORT NonClientFrameViewAsh : public views::NonClientFrameView,
// Track whether the device is in overview mode. Set this to true when // Track whether the device is in overview mode. Set this to true when
// overview mode started and false when overview mode finished. Use this to // overview mode started and false when overview mode finished. Use this to
// check whether we should paint when splitview state changes instead of // check whether we should paint when splitview state changes instead of
// Shell::Get()->window_selector_controller()->IsSelecting() because the later // Shell::Get()->window_selector_controller()->IsSelecting() because the
// actually may be still be false after overview mode has started. // later actually may be still be false after overview mode has started.
bool in_overview_mode_ = false; bool in_overview_mode_ = false;
// Helpers for the context menu users will see when right-clicking on
// |header_view_|.
std::unique_ptr<ui::SimpleMenuModel> menu_model_;
std::unique_ptr<views::MenuRunner> menu_runner_;
mojom::MenuDelegatePtr menu_delegate_;
std::unique_ptr<NonClientFrameViewAshImmersiveHelper> immersive_helper_; std::unique_ptr<NonClientFrameViewAshImmersiveHelper> immersive_helper_;
DISALLOW_COPY_AND_ASSIGN(NonClientFrameViewAsh); DISALLOW_COPY_AND_ASSIGN(NonClientFrameViewAsh);
......
...@@ -389,7 +389,7 @@ TEST_F(NonClientFrameViewAshTest, GetPreferredOnScreenHeightInTabletMaximzied) { ...@@ -389,7 +389,7 @@ TEST_F(NonClientFrameViewAshTest, GetPreferredOnScreenHeightInTabletMaximzied) {
std::unique_ptr<views::Widget> widget = CreateTestWidget(delegate); std::unique_ptr<views::Widget> widget = CreateTestWidget(delegate);
auto* frame_view = static_cast<ash::NonClientFrameViewAsh*>( auto* frame_view = static_cast<ash::NonClientFrameViewAsh*>(
widget->non_client_view()->frame_view()); widget->non_client_view()->frame_view());
auto* header_view = static_cast<HeaderView*>(frame_view->GetHeaderView()); auto* header_view = frame_view->GetHeaderView();
ASSERT_TRUE(widget->IsMaximized()); ASSERT_TRUE(widget->IsMaximized());
EXPECT_TRUE(header_view->in_immersive_mode()); EXPECT_TRUE(header_view->in_immersive_mode());
static_cast<ImmersiveFullscreenControllerDelegate*>(header_view) static_cast<ImmersiveFullscreenControllerDelegate*>(header_view)
...@@ -545,8 +545,7 @@ TEST_F(NonClientFrameViewAshTest, BackButton) { ...@@ -545,8 +545,7 @@ TEST_F(NonClientFrameViewAshTest, BackButton) {
delegate->non_client_frame_view(); delegate->non_client_frame_view();
non_client_frame_view->SetCaptionButtonModel(std::move(model)); non_client_frame_view->SetCaptionButtonModel(std::move(model));
HeaderView* header_view = HeaderView* header_view = non_client_frame_view->GetHeaderView();
static_cast<HeaderView*>(non_client_frame_view->GetHeaderView());
EXPECT_FALSE(header_view->GetBackButton()); EXPECT_FALSE(header_view->GetBackButton());
model_ptr->SetVisible(CAPTION_BUTTON_ICON_BACK, true); model_ptr->SetVisible(CAPTION_BUTTON_ICON_BACK, true);
non_client_frame_view->SizeConstraintsChanged(); non_client_frame_view->SizeConstraintsChanged();
...@@ -626,8 +625,7 @@ TEST_F(NonClientFrameViewAshTest, CustomButtonModel) { ...@@ -626,8 +625,7 @@ TEST_F(NonClientFrameViewAshTest, CustomButtonModel) {
delegate->non_client_frame_view(); delegate->non_client_frame_view();
non_client_frame_view->SetCaptionButtonModel(std::move(model)); non_client_frame_view->SetCaptionButtonModel(std::move(model));
HeaderView* header_view = HeaderView* header_view = non_client_frame_view->GetHeaderView();
static_cast<HeaderView*>(non_client_frame_view->GetHeaderView());
FrameCaptionButtonContainerView::TestApi test_api( FrameCaptionButtonContainerView::TestApi test_api(
header_view->caption_button_container()); header_view->caption_button_container());
...@@ -699,8 +697,7 @@ TEST_F(NonClientFrameViewAshTest, WideFrame) { ...@@ -699,8 +697,7 @@ TEST_F(NonClientFrameViewAshTest, WideFrame) {
NonClientFrameViewAsh* non_client_frame_view = NonClientFrameViewAsh* non_client_frame_view =
delegate->non_client_frame_view(); delegate->non_client_frame_view();
HeaderView* header_view = HeaderView* header_view = non_client_frame_view->GetHeaderView();
static_cast<HeaderView*>(non_client_frame_view->GetHeaderView());
widget->Maximize(); widget->Maximize();
std::unique_ptr<WideFrameView> wide_frame_view = std::unique_ptr<WideFrameView> wide_frame_view =
......
...@@ -199,7 +199,7 @@ void WideFrameView::OnOverviewModeEnded() { ...@@ -199,7 +199,7 @@ void WideFrameView::OnOverviewModeEnded() {
HeaderView* WideFrameView::GetTargetHeaderView() { HeaderView* WideFrameView::GetTargetHeaderView() {
auto* frame_view = static_cast<NonClientFrameViewAsh*>( auto* frame_view = static_cast<NonClientFrameViewAsh*>(
target_->non_client_view()->frame_view()); target_->non_client_view()->frame_view());
return static_cast<HeaderView*>(frame_view->GetHeaderView()); return frame_view->GetHeaderView();
} }
} // namespace ash } // namespace ash
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
module ash.mojom; module ash.mojom;
import "ash/public/interfaces/menu.mojom";
import "ui/events/mojo/event_constants.mojom"; import "ui/events/mojo/event_constants.mojom";
// The previewed snap state for a window, corresponding to the use of a // The previewed snap state for a window, corresponding to the use of a
...@@ -48,4 +49,10 @@ interface AshWindowManager { ...@@ -48,4 +49,10 @@ interface AshWindowManager {
// Plays the window bounce animation (scale the window up and down). // Plays the window bounce animation (scale the window up and down).
BounceWindow(uint64 window_id); BounceWindow(uint64 window_id);
// Sets the context menu items to be displayed on a window's frame, for
// windows where the frame is provided by Ash. |delegate| handles interaction
// with the menu.
SetWindowFrameMenuItems(uint64 window_id, array<MenuItem> menu_items,
MenuDelegate delegate);
}; };
...@@ -66,3 +66,9 @@ struct MenuItem { ...@@ -66,3 +66,9 @@ struct MenuItem {
int64 radio_group_id; // The radio group id. int64 radio_group_id; // The radio group id.
MenuSeparatorType separator_type; // The separator type. MenuSeparatorType separator_type; // The separator type.
}; };
// An interface implemented by clients to handle interaction with menus run in
// Ash.
interface MenuDelegate {
MenuItemActivated(int32 command_id);
};
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "ash/ws/ash_window_manager.h" #include "ash/ws/ash_window_manager.h"
#include "ash/display/screen_orientation_controller.h" #include "ash/display/screen_orientation_controller.h"
#include "ash/frame/non_client_frame_view_ash.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "ash/wm/window_state.h" #include "ash/wm/window_state.h"
...@@ -121,4 +122,24 @@ void AshWindowManager::BounceWindow(ws::Id window_id) { ...@@ -121,4 +122,24 @@ void AshWindowManager::BounceWindow(ws::Id window_id) {
::wm::AnimateWindow(window, ::wm::WINDOW_ANIMATION_TYPE_BOUNCE); ::wm::AnimateWindow(window, ::wm::WINDOW_ANIMATION_TYPE_BOUNCE);
} }
void AshWindowManager::SetWindowFrameMenuItems(
ws::Id window_id,
menu_utils::MenuItemList menu_item_list,
mojom::MenuDelegatePtr delegate) {
aura::Window* window = window_tree_->GetWindowByTransportId(window_id);
if (!window) {
DVLOG(1) << "SetWindowFrameMenuItems passed invalid window, id="
<< window_id;
return;
}
NonClientFrameViewAsh* frame_view = NonClientFrameViewAsh::Get(window);
if (!frame_view) {
DVLOG(1) << "SetWindowFrameMenuItems called on frameless window";
return;
}
frame_view->SetWindowFrameMenuItems(menu_item_list, std::move(delegate));
}
} // namespace ash } // namespace ash
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define ASH_WS_ASH_WINDOW_MANAGER_H_ #define ASH_WS_ASH_WINDOW_MANAGER_H_
#include "ash/frame/ash_frame_caption_controller.h" #include "ash/frame/ash_frame_caption_controller.h"
#include "ash/public/cpp/menu_utils.h"
#include "ash/public/interfaces/ash_window_manager.mojom.h" #include "ash/public/interfaces/ash_window_manager.mojom.h"
#include "mojo/public/cpp/bindings/associated_binding.h" #include "mojo/public/cpp/bindings/associated_binding.h"
#include "services/ws/common/types.h" #include "services/ws/common/types.h"
...@@ -39,6 +40,9 @@ class AshWindowManager : public mojom::AshWindowManager, ...@@ -39,6 +40,9 @@ class AshWindowManager : public mojom::AshWindowManager,
void MaximizeWindowByCaptionClick(ws::Id window_id, void MaximizeWindowByCaptionClick(ws::Id window_id,
ui::mojom::PointerKind pointer) override; ui::mojom::PointerKind pointer) override;
void BounceWindow(ws::Id window_id) override; void BounceWindow(ws::Id window_id) override;
void SetWindowFrameMenuItems(ws::Id window_id,
menu_utils::MenuItemList menu_item_list,
mojom::MenuDelegatePtr delegate) override;
private: private:
ws::WindowTree* window_tree_; ws::WindowTree* window_tree_;
......
...@@ -12,10 +12,12 @@ ...@@ -12,10 +12,12 @@
#include "ash/public/cpp/ash_constants.h" #include "ash/public/cpp/ash_constants.h"
#include "ash/public/cpp/ash_switches.h" #include "ash/public/cpp/ash_switches.h"
#include "ash/public/cpp/immersive/immersive_fullscreen_controller.h" #include "ash/public/cpp/immersive/immersive_fullscreen_controller.h"
#include "ash/public/cpp/menu_utils.h"
#include "ash/public/cpp/shelf_types.h" #include "ash/public/cpp/shelf_types.h"
#include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/shell_window_ids.h"
#include "ash/public/cpp/window_properties.h" #include "ash/public/cpp/window_properties.h"
#include "ash/public/cpp/window_state_type.h" #include "ash/public/cpp/window_state_type.h"
#include "ash/public/interfaces/constants.mojom.h"
#include "ash/wm/window_state.h" // mash-ok #include "ash/wm/window_state.h" // mash-ok
#include "base/logging.h" #include "base/logging.h"
#include "chrome/browser/chromeos/note_taking_helper.h" #include "chrome/browser/chromeos/note_taking_helper.h"
...@@ -30,6 +32,8 @@ ...@@ -30,6 +32,8 @@
#include "services/ws/public/mojom/window_manager.mojom.h" #include "services/ws/public/mojom/window_manager.mojom.h"
#include "ui/aura/client/aura_constants.h" #include "ui/aura/client/aura_constants.h"
#include "ui/aura/mus/property_converter.h" #include "ui/aura/mus/property_converter.h"
#include "ui/aura/mus/window_mus.h"
#include "ui/aura/mus/window_tree_client.h"
#include "ui/aura/mus/window_tree_host_mus.h" #include "ui/aura/mus/window_tree_host_mus.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/base/hit_test.h" #include "ui/base/hit_test.h"
...@@ -43,6 +47,7 @@ ...@@ -43,6 +47,7 @@
#include "ui/views/controls/menu/menu_model_adapter.h" #include "ui/views/controls/menu/menu_model_adapter.h"
#include "ui/views/controls/menu/menu_runner.h" #include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/controls/webview/webview.h" #include "ui/views/controls/webview/webview.h"
#include "ui/views/mus/mus_client.h"
#include "ui/views/widget/widget.h" #include "ui/views/widget/widget.h"
#include "ui/wm/core/coordinate_conversion.h" #include "ui/wm/core/coordinate_conversion.h"
...@@ -53,11 +58,23 @@ ChromeNativeAppWindowViewsAuraAsh::ChromeNativeAppWindowViewsAuraAsh() ...@@ -53,11 +58,23 @@ ChromeNativeAppWindowViewsAuraAsh::ChromeNativeAppWindowViewsAuraAsh()
std::make_unique<ExclusiveAccessManager>(this)) { std::make_unique<ExclusiveAccessManager>(this)) {
if (TabletModeClient::Get()) if (TabletModeClient::Get())
TabletModeClient::Get()->AddObserver(this); TabletModeClient::Get()->AddObserver(this);
if (features::IsSingleProcessMash()) {
MultiUserWindowManager::GetInstance()->AddObserver(this);
ash_window_manager_ =
views::MusClient::Get()
->window_tree_client()
->BindWindowManagerInterface<ash::mojom::AshWindowManager>();
}
} }
ChromeNativeAppWindowViewsAuraAsh::~ChromeNativeAppWindowViewsAuraAsh() { ChromeNativeAppWindowViewsAuraAsh::~ChromeNativeAppWindowViewsAuraAsh() {
if (TabletModeClient::Get()) if (TabletModeClient::Get())
TabletModeClient::Get()->RemoveObserver(this); TabletModeClient::Get()->RemoveObserver(this);
if (features::IsSingleProcessMash())
MultiUserWindowManager::GetInstance()->RemoveObserver(this);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
...@@ -190,6 +207,8 @@ void ChromeNativeAppWindowViewsAuraAsh::ShowContextMenuForView( ...@@ -190,6 +207,8 @@ void ChromeNativeAppWindowViewsAuraAsh::ShowContextMenuForView(
views::View* source, views::View* source,
const gfx::Point& p, const gfx::Point& p,
ui::MenuSourceType source_type) { ui::MenuSourceType source_type) {
DCHECK(!features::IsUsingWindowService());
menu_model_ = CreateMultiUserContextMenu(GetNativeWindow()); menu_model_ = CreateMultiUserContextMenu(GetNativeWindow());
if (!menu_model_.get()) if (!menu_model_.get())
return; return;
...@@ -503,6 +522,33 @@ void ChromeNativeAppWindowViewsAuraAsh::OnWindowDestroying( ...@@ -503,6 +522,33 @@ void ChromeNativeAppWindowViewsAuraAsh::OnWindowDestroying(
observed_window_.Remove(window); observed_window_.Remove(window);
} }
void ChromeNativeAppWindowViewsAuraAsh::OnOwnerEntryAdded(
aura::Window* window) {
OnOwnerEntryChanged(window);
}
void ChromeNativeAppWindowViewsAuraAsh::OnOwnerEntryChanged(
aura::Window* window) {
if (window != GetWidget()->GetNativeWindow())
return;
std::unique_ptr<ui::MenuModel> menu_model =
CreateMultiUserContextMenu(GetNativeWindow());
ash::mojom::MenuDelegatePtr delegate;
binding_.Close();
binding_.Bind(mojo::MakeRequest(&delegate));
ash_window_manager_->SetWindowFrameMenuItems(
aura::WindowMus::Get(GetWidget()->GetNativeWindow()->GetRootWindow())
->server_id(),
ash::menu_utils::GetMojoMenuItemsFromModel(menu_model.get()),
std::move(delegate));
}
void ChromeNativeAppWindowViewsAuraAsh::MenuItemActivated(int command_id) {
ExecuteVisitDesktopCommand(command_id, GetWidget()->GetNativeWindow());
}
void ChromeNativeAppWindowViewsAuraAsh::OnMenuClosed() { void ChromeNativeAppWindowViewsAuraAsh::OnMenuClosed() {
menu_runner_.reset(); menu_runner_.reset();
menu_model_.reset(); menu_model_.reset();
......
...@@ -8,13 +8,17 @@ ...@@ -8,13 +8,17 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "ash/public/interfaces/ash_window_manager.mojom.h"
#include "ash/public/interfaces/menu.mojom.h"
#include "ash/wm/window_state_observer.h" // mash-ok #include "ash/wm/window_state_observer.h" // mash-ok
#include "base/gtest_prod_util.h" #include "base/gtest_prod_util.h"
#include "base/scoped_observer.h" #include "base/scoped_observer.h"
#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
#include "chrome/browser/ui/ash/tablet_mode_client_observer.h" #include "chrome/browser/ui/ash/tablet_mode_client_observer.h"
#include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h"
#include "chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.h" #include "chrome/browser/ui/views/apps/chrome_native_app_window_views_aura.h"
#include "chrome/browser/ui/views/exclusive_access_bubble_views_context.h" #include "chrome/browser/ui/views/exclusive_access_bubble_views_context.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "ui/aura/window_observer.h" #include "ui/aura/window_observer.h"
#include "ui/base/accelerators/accelerator.h" #include "ui/base/accelerators/accelerator.h"
#include "ui/views/context_menu_controller.h" #include "ui/views/context_menu_controller.h"
...@@ -40,7 +44,9 @@ class ChromeNativeAppWindowViewsAuraAsh ...@@ -40,7 +44,9 @@ class ChromeNativeAppWindowViewsAuraAsh
public ExclusiveAccessContext, public ExclusiveAccessContext,
public ExclusiveAccessBubbleViewsContext, public ExclusiveAccessBubbleViewsContext,
public ash::wm::WindowStateObserver, public ash::wm::WindowStateObserver,
public aura::WindowObserver { public aura::WindowObserver,
public MultiUserWindowManager::Observer,
public ash::mojom::MenuDelegate {
public: public:
ChromeNativeAppWindowViewsAuraAsh(); ChromeNativeAppWindowViewsAuraAsh();
~ChromeNativeAppWindowViewsAuraAsh() override; ~ChromeNativeAppWindowViewsAuraAsh() override;
...@@ -129,6 +135,13 @@ class ChromeNativeAppWindowViewsAuraAsh ...@@ -129,6 +135,13 @@ class ChromeNativeAppWindowViewsAuraAsh
intptr_t old) override; intptr_t old) override;
void OnWindowDestroying(aura::Window* window) override; void OnWindowDestroying(aura::Window* window) override;
// MultiUserWindowManager::Observer:
void OnOwnerEntryAdded(aura::Window* window) override;
void OnOwnerEntryChanged(aura::Window* window) override;
// ash::mojom::MenuDelegate:
void MenuItemActivated(int command_id) override;
private: private:
FRIEND_TEST_ALL_PREFIXES(ChromeNativeAppWindowViewsAuraAshBrowserTest, FRIEND_TEST_ALL_PREFIXES(ChromeNativeAppWindowViewsAuraAshBrowserTest,
ImmersiveWorkFlow); ImmersiveWorkFlow);
...@@ -154,6 +167,9 @@ class ChromeNativeAppWindowViewsAuraAsh ...@@ -154,6 +167,9 @@ class ChromeNativeAppWindowViewsAuraAsh
// Callback for MenuRunner // Callback for MenuRunner
void OnMenuClosed(); void OnMenuClosed();
// Callback for Ash-controlled context menus, invoked over Mojo.
void ExecuteContextMenuItem(int command_id);
// Whether immersive mode should be enabled. // Whether immersive mode should be enabled.
bool ShouldEnableImmersiveMode() const; bool ShouldEnableImmersiveMode() const;
...@@ -161,7 +177,7 @@ class ChromeNativeAppWindowViewsAuraAsh ...@@ -161,7 +177,7 @@ class ChromeNativeAppWindowViewsAuraAsh
// app's and window manager's state. // app's and window manager's state.
void UpdateImmersiveMode(); void UpdateImmersiveMode();
// Used to show the system menu. // Used to show the system menu. Only used in !Mash.
std::unique_ptr<ui::MenuModel> menu_model_; std::unique_ptr<ui::MenuModel> menu_model_;
std::unique_ptr<views::MenuRunner> menu_runner_; std::unique_ptr<views::MenuRunner> menu_runner_;
...@@ -171,6 +187,10 @@ class ChromeNativeAppWindowViewsAuraAsh ...@@ -171,6 +187,10 @@ class ChromeNativeAppWindowViewsAuraAsh
bool tablet_mode_enabled_ = false; bool tablet_mode_enabled_ = false;
// Only used in mash.
ash::mojom::AshWindowManagerAssociatedPtr ash_window_manager_;
mojo::Binding<ash::mojom::MenuDelegate> binding_{this};
ScopedObserver<aura::Window, aura::WindowObserver> observed_window_{this}; ScopedObserver<aura::Window, aura::WindowObserver> observed_window_{this};
ScopedObserver<ash::wm::WindowState, ash::wm::WindowStateObserver> ScopedObserver<ash::wm::WindowState, ash::wm::WindowStateObserver>
observed_window_state_{this}; observed_window_state_{this};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment