Commit 88b833af authored by ben's avatar ben Committed by Commit bot

Add a basic task switcher to the simple window manager.

R=sky@chromium.org

Review-Url: https://codereview.chromium.org/2571653002
Cr-Commit-Position: refs/heads/master@{#437968}
parent 19d351e0
...@@ -4,11 +4,14 @@ ...@@ -4,11 +4,14 @@
#include "mash/simple_wm/simple_wm.h" #include "mash/simple_wm/simple_wm.h"
#include "base/observer_list.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "ui/aura/client/aura_constants.h" #include "ui/aura/client/aura_constants.h"
#include "ui/aura/layout_manager.h"
#include "ui/display/screen_base.h" #include "ui/display/screen_base.h"
#include "ui/gfx/canvas.h" #include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/mojo/geometry.mojom.h" #include "ui/gfx/geometry/mojo/geometry.mojom.h"
#include "ui/views/controls/button/md_text_button.h"
#include "ui/views/controls/label.h" #include "ui/views/controls/label.h"
#include "ui/views/mus/aura_init.h" #include "ui/views/mus/aura_init.h"
#include "ui/views/mus/mus_client.h" #include "ui/views/mus/mus_client.h"
...@@ -26,6 +29,158 @@ const int kNonClientSize = 5; ...@@ -26,6 +29,158 @@ const int kNonClientSize = 5;
} // namespace } // namespace
class SimpleWM::WindowListModelObserver {
public:
virtual void OnWindowAddedOrRemoved() = 0;
virtual void OnWindowTitleChanged(size_t index,
const base::string16& title) = 0;
};
class SimpleWM::WindowListModel : public aura::WindowObserver {
public:
explicit WindowListModel(aura::Window* window_container)
: window_container_(window_container) {
window_container_->AddObserver(this);
}
~WindowListModel() override {
window_container_->RemoveObserver(this);
for (auto window : windows_)
window->RemoveObserver(this);
}
size_t GetSize() const {
return windows_.size();
}
base::string16 GetTitle(size_t index) const {
return windows_.at(index)->GetTitle();
}
aura::Window* GetWindow(size_t index) const {
return windows_.at(index);
}
void AddObserver(WindowListModelObserver* observer) {
observers_.AddObserver(observer);
}
void RemoveObserver(WindowListModelObserver* observer) {
observers_.RemoveObserver(observer);
}
private:
// aura::WindowObserver:
void OnWindowAdded(aura::Window* window) override {
if (window->parent() == window_container_)
AddWindow(window);
for (auto& observer : observers_)
observer.OnWindowAddedOrRemoved();
}
void OnWillRemoveWindow(aura::Window* window) override {
window->RemoveObserver(this);
for (auto& observer : observers_)
observer.OnWindowAddedOrRemoved();
auto it = std::find(windows_.begin(), windows_.end(), window);
DCHECK(it != windows_.end());
windows_.erase(it);
}
void OnWindowTitleChanged(aura::Window* window) override {
auto it = std::find(windows_.begin(), windows_.end(), window);
size_t index = it - windows_.begin();
for (auto& observer : observers_)
observer.OnWindowTitleChanged(index, window->GetTitle());
}
void AddWindow(aura::Window* window) {
window->AddObserver(this);
auto it = std::find(windows_.begin(), windows_.end(), window);
DCHECK(it == windows_.end());
windows_.push_back(window);
}
aura::Window* window_container_;
std::vector<aura::Window*> windows_;
base::ObserverList<WindowListModelObserver> observers_;
DISALLOW_COPY_AND_ASSIGN(WindowListModel);
};
class SimpleWM::WindowListView : public views::WidgetDelegateView,
public views::ButtonListener,
public SimpleWM::WindowListModelObserver {
public:
using ActivateCallback = base::Callback<void(aura::Window*)>;
WindowListView(WindowListModel* model, ActivateCallback activate_callback)
: model_(model), activate_callback_(activate_callback) {
model_->AddObserver(this);
Rebuild();
}
~WindowListView() override {
model_->RemoveObserver(this);
}
static const int kButtonSpacing = 5;
// views::View
void Layout() override {
int x_offset = kButtonSpacing;
for (int i = 0; i < child_count(); ++i) {
View* v = child_at(i);
gfx::Size ps = v->GetPreferredSize();
gfx::Rect bounds(x_offset, kButtonSpacing, ps.width(), ps.height());
v->SetBoundsRect(bounds);
x_offset = bounds.right() + kButtonSpacing;
}
}
void OnPaint(gfx::Canvas* canvas) override {
canvas->DrawColor(SK_ColorLTGRAY);
}
gfx::Size GetPreferredSize() const override {
std::unique_ptr<views::MdTextButton> measure_button(
views::MdTextButton::Create(nullptr, base::UTF8ToUTF16("Sample")));
int height =
measure_button->GetPreferredSize().height() + 2 * kButtonSpacing;
return gfx::Size(0, height);
}
private:
// views::ButtonListener:
void ButtonPressed(views::Button* sender, const ui::Event& event) override {
activate_callback_.Run(
model_->GetWindow(static_cast<size_t>(sender->tag())));
}
// WindowListModelObserver:
void OnWindowAddedOrRemoved() override {
Rebuild();
}
void OnWindowTitleChanged(size_t index,
const base::string16& new_title) override {
views::MdTextButton* label =
static_cast<views::MdTextButton*>(child_at(static_cast<int>(index)));
label->SetText(new_title);
Layout();
}
void Rebuild() {
RemoveAllChildViews(true);
size_t size = model_->GetSize();
for (size_t i = 0; i < size; ++i) {
base::string16 title = model_->GetTitle(i);
if (title.empty())
title = base::UTF8ToUTF16("Untitled");
views::MdTextButton* button = views::MdTextButton::Create(this, title);
button->set_tag(static_cast<int>(i));
AddChildView(button);
}
Layout();
}
WindowListModel* model_;
ActivateCallback activate_callback_;
DISALLOW_COPY_AND_ASSIGN(WindowListView);
};
class SimpleWM::FrameView : public views::WidgetDelegateView, class SimpleWM::FrameView : public views::WidgetDelegateView,
public aura::WindowObserver { public aura::WindowObserver {
public: public:
...@@ -38,11 +193,14 @@ class SimpleWM::FrameView : public views::WidgetDelegateView, ...@@ -38,11 +193,14 @@ class SimpleWM::FrameView : public views::WidgetDelegateView,
private: private:
// views::WidgetDelegateView: // views::WidgetDelegateView:
base::string16 GetWindowTitle() const override { base::string16 GetWindowTitle() const override {
base::string16* title = base::string16* title_from_property =
client_window_->GetProperty(aura::client::kTitleKey); client_window_->GetProperty(aura::client::kTitleKey);
if (!title) base::string16 title = title_from_property ? *title_from_property
return base::UTF8ToUTF16("(Window)"); : base::UTF8ToUTF16("(Window)");
return *title; // TODO(beng): quick hack to cause WindowObserver::OnWindowTitleChanged to
// fire.
GetWidget()->GetNativeWindow()->SetTitle(title);
return title;
} }
void Layout() override { void Layout() override {
// Client offsets are applied automatically by the window service. // Client offsets are applied automatically by the window service.
...@@ -63,6 +221,50 @@ class SimpleWM::FrameView : public views::WidgetDelegateView, ...@@ -63,6 +221,50 @@ class SimpleWM::FrameView : public views::WidgetDelegateView,
DISALLOW_COPY_AND_ASSIGN(FrameView); DISALLOW_COPY_AND_ASSIGN(FrameView);
}; };
class SimpleWM::DisplayLayoutManager : public aura::LayoutManager {
public:
DisplayLayoutManager(aura::Window* display_root,
aura::Window* window_root,
SimpleWM::WindowListView* window_list_view)
: display_root_(display_root),
window_root_(window_root),
window_list_view_(window_list_view) {}
~DisplayLayoutManager() override {}
private:
// aura::LayoutManager:
void OnWindowResized() override {}
void OnWindowAddedToLayout(aura::Window* child) override {
Layout();
}
void OnWillRemoveWindowFromLayout(aura::Window* child) override {}
void OnWindowRemovedFromLayout(aura::Window* child) override {}
void OnChildWindowVisibilityChanged(aura::Window* child,
bool visible) override {}
void SetChildBounds(aura::Window* child,
const gfx::Rect& requested_bounds) override {
SetChildBoundsDirect(child, requested_bounds);
}
void Layout() {
gfx::Size ps = window_list_view_->GetPreferredSize();
gfx::Rect bounds = display_root_->bounds();
gfx::Rect window_root_bounds = bounds;
window_root_bounds.set_height(window_root_bounds.height() - ps.height());
window_root_->SetBounds(window_root_bounds);
gfx::Rect window_list_view_bounds = bounds;
window_list_view_bounds.set_height(ps.height());
window_list_view_bounds.set_y(window_root_bounds.bottom());
window_list_view_->GetWidget()->SetBounds(window_list_view_bounds);
}
aura::Window* display_root_;
aura::Window* window_root_;
SimpleWM::WindowListView* window_list_view_;
DISALLOW_COPY_AND_ASSIGN(DisplayLayoutManager);
};
SimpleWM::SimpleWM() {} SimpleWM::SimpleWM() {}
SimpleWM::~SimpleWM() { SimpleWM::~SimpleWM() {
...@@ -165,7 +367,7 @@ aura::Window* SimpleWM::OnWmCreateTopLevelWindow( ...@@ -165,7 +367,7 @@ aura::Window* SimpleWM::OnWmCreateTopLevelWindow(
FrameView* frame_view = new FrameView(client_window); FrameView* frame_view = new FrameView(client_window);
params.delegate = frame_view; params.delegate = frame_view;
params.native_widget = frame_native_widget; params.native_widget = frame_native_widget;
params.parent = root_; params.parent = window_root_;
params.bounds = gfx::Rect(10, 10, 500, 500); params.bounds = gfx::Rect(10, 10, 500, 500);
frame_widget->Init(params); frame_widget->Init(params);
frame_widget->Show(); frame_widget->Show();
...@@ -194,11 +396,36 @@ void SimpleWM::OnWmNewDisplay( ...@@ -194,11 +396,36 @@ void SimpleWM::OnWmNewDisplay(
std::unique_ptr<aura::WindowTreeHostMus> window_tree_host, std::unique_ptr<aura::WindowTreeHostMus> window_tree_host,
const display::Display& display) { const display::Display& display) {
// Only handles a single root. // Only handles a single root.
DCHECK(!root_); DCHECK(!window_root_);
window_tree_host_ = std::move(window_tree_host); window_tree_host_ = std::move(window_tree_host);
root_ = window_tree_host_->window(); window_tree_host_->InitHost();
display_root_ = window_tree_host_->window();
window_root_ = new aura::Window(nullptr);
window_root_->Init(ui::LAYER_NOT_DRAWN);
display_root_->AddChild(window_root_);
window_root_->Show();
window_list_model_ = base::MakeUnique<WindowListModel>(window_root_);
views::Widget* window_list_widget = new views::Widget;
views::NativeWidgetAura* window_list_widget_native_widget =
new views::NativeWidgetAura(window_list_widget, true);
views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL);
WindowListView* window_list_view =
new WindowListView(window_list_model_.get(),
base::Bind(&SimpleWM::OnWindowListViewItemActivated,
base::Unretained(this)));
params.delegate = window_list_view;
params.native_widget = window_list_widget_native_widget;
params.parent = display_root_;
window_list_widget->Init(params);
window_list_widget->Show();
display_root_->SetLayoutManager(new DisplayLayoutManager(
display_root_, window_root_, window_list_view));
DCHECK(window_manager_client_); DCHECK(window_manager_client_);
window_manager_client_->AddActivationParent(root_); window_manager_client_->AddActivationParent(window_root_);
ui::mojom::FrameDecorationValuesPtr frame_decoration_values = ui::mojom::FrameDecorationValuesPtr frame_decoration_values =
ui::mojom::FrameDecorationValues::New(); ui::mojom::FrameDecorationValues::New();
frame_decoration_values->normal_client_area_insets.Set( frame_decoration_values->normal_client_area_insets.Set(
...@@ -206,14 +433,14 @@ void SimpleWM::OnWmNewDisplay( ...@@ -206,14 +433,14 @@ void SimpleWM::OnWmNewDisplay(
frame_decoration_values->max_title_bar_button_width = 0; frame_decoration_values->max_title_bar_button_width = 0;
window_manager_client_->SetFrameDecorationValues( window_manager_client_->SetFrameDecorationValues(
std::move(frame_decoration_values)); std::move(frame_decoration_values));
new wm::DefaultActivationClient(root_); new wm::DefaultActivationClient(display_root_);
aura::client::SetFocusClient(root_, &focus_client_); aura::client::SetFocusClient(display_root_, &focus_client_);
} }
void SimpleWM::OnWmDisplayRemoved( void SimpleWM::OnWmDisplayRemoved(
aura::WindowTreeHostMus* window_tree_host) { aura::WindowTreeHostMus* window_tree_host) {
DCHECK_EQ(window_tree_host, window_tree_host_.get()); DCHECK_EQ(window_tree_host, window_tree_host_.get());
root_ = nullptr; window_root_ = nullptr;
window_tree_host_.reset(); window_tree_host_.reset();
} }
...@@ -240,5 +467,10 @@ SimpleWM::FrameView* SimpleWM::GetFrameViewForClientWindow( ...@@ -240,5 +467,10 @@ SimpleWM::FrameView* SimpleWM::GetFrameViewForClientWindow(
return it != client_window_to_frame_view_.end() ? it->second : nullptr; return it != client_window_to_frame_view_.end() ? it->second : nullptr;
} }
} // namespace simple_wm void SimpleWM::OnWindowListViewItemActivated(aura::Window* window) {
aura::client::ActivationClient* activation_client =
aura::client::GetActivationClient(window->GetRootWindow());
activation_client->ActivateWindow(window);
}
} // namespace simple_wm
...@@ -47,7 +47,11 @@ class SimpleWM : public service_manager::Service, ...@@ -47,7 +47,11 @@ class SimpleWM : public service_manager::Service,
~SimpleWM() override; ~SimpleWM() override;
private: private:
class DisplayLayoutManager;
class FrameView; class FrameView;
class WindowListModel;
class WindowListModelObserver;
class WindowListView;
// service_manager::Service: // service_manager::Service:
void OnStart() override; void OnStart() override;
...@@ -93,18 +97,22 @@ class SimpleWM : public service_manager::Service, ...@@ -93,18 +97,22 @@ class SimpleWM : public service_manager::Service,
FrameView* GetFrameViewForClientWindow(aura::Window* client_window); FrameView* GetFrameViewForClientWindow(aura::Window* client_window);
void OnWindowListViewItemActivated(aura::Window* index);
std::unique_ptr<views::AuraInit> aura_init_; std::unique_ptr<views::AuraInit> aura_init_;
::wm::WMState wm_state_; ::wm::WMState wm_state_;
std::unique_ptr<display::ScreenBase> screen_; std::unique_ptr<display::ScreenBase> screen_;
aura::PropertyConverter property_converter_; aura::PropertyConverter property_converter_;
aura::test::TestFocusClient focus_client_; aura::test::TestFocusClient focus_client_;
std::unique_ptr<aura::WindowTreeHostMus> window_tree_host_; std::unique_ptr<aura::WindowTreeHostMus> window_tree_host_;
aura::Window* root_ = nullptr; aura::Window* display_root_ = nullptr;
aura::Window* window_root_ = nullptr;
aura::WindowManagerClient* window_manager_client_ = nullptr; aura::WindowManagerClient* window_manager_client_ = nullptr;
std::unique_ptr<aura::WindowTreeClient> window_tree_client_; std::unique_ptr<aura::WindowTreeClient> window_tree_client_;
std::unique_ptr<ui::Gpu> gpu_; std::unique_ptr<ui::Gpu> gpu_;
std::unique_ptr<aura::MusContextFactory> compositor_context_factory_; std::unique_ptr<aura::MusContextFactory> compositor_context_factory_;
std::map<aura::Window*, FrameView*> client_window_to_frame_view_; std::map<aura::Window*, FrameView*> client_window_to_frame_view_;
std::unique_ptr<WindowListModel> window_list_model_;
bool started_ = false; bool started_ = false;
......
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