Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(564)

Unified Diff: mash/simple_wm/simple_wm.cc

Issue 2571653002: Add a basic task switcher to the simple window manager. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « mash/simple_wm/simple_wm.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mash/simple_wm/simple_wm.cc
diff --git a/mash/simple_wm/simple_wm.cc b/mash/simple_wm/simple_wm.cc
index 49917e298038468c406f6f578fbb3b05073c1366..a0fe8473ec87e65d4de45ee41c064635636e1da0 100644
--- a/mash/simple_wm/simple_wm.cc
+++ b/mash/simple_wm/simple_wm.cc
@@ -4,11 +4,14 @@
#include "mash/simple_wm/simple_wm.h"
+#include "base/observer_list.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/layout_manager.h"
#include "ui/display/screen_base.h"
#include "ui/gfx/canvas.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/mus/aura_init.h"
#include "ui/views/mus/mus_client.h"
@@ -26,6 +29,156 @@ const int kNonClientSize = 5;
} // 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);
sky 2016/12/12 23:16:07 Remove observers from windows_?
Ben Goodger (Google) 2016/12/12 23:24:45 Done.
+ }
+
+ 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);
+ window->AddObserver(this);
+ 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) {
+ 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 {
+ 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);
sky 2016/12/12 23:16:07 Don't you want to increment width rather than heig
+ }
+
+ 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,
public aura::WindowObserver {
public:
@@ -38,11 +191,14 @@ class SimpleWM::FrameView : public views::WidgetDelegateView,
private:
// views::WidgetDelegateView:
base::string16 GetWindowTitle() const override {
- base::string16* title =
+ base::string16* title_from_property =
client_window_->GetProperty(aura::client::kTitleKey);
- if (!title)
- return base::UTF8ToUTF16("(Window)");
- return *title;
+ base::string16 title = title_from_property ? *title_from_property
+ : base::UTF8ToUTF16("(Window)");
+ // TODO(beng): quick hack to cause WindowObserver::OnWindowTitleChanged to
+ // fire.
+ GetWidget()->GetNativeWindow()->SetTitle(title);
+ return title;
}
void Layout() override {
// Client offsets are applied automatically by the window service.
@@ -63,6 +219,50 @@ class SimpleWM::FrameView : public views::WidgetDelegateView,
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() {}
+
+ private:
+ // aura::LayoutManager:
+ void OnWindowResized() override {}
+ virtual void OnWindowAddedToLayout(aura::Window* child) override {
+ Layout();
+ }
+ virtual void OnWillRemoveWindowFromLayout(aura::Window* child) override {}
+ virtual void OnWindowRemovedFromLayout(aura::Window* child) override {}
+ virtual void OnChildWindowVisibilityChanged(aura::Window* child,
+ bool visible) override {}
+ virtual 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() {
@@ -165,7 +365,7 @@ aura::Window* SimpleWM::OnWmCreateTopLevelWindow(
FrameView* frame_view = new FrameView(client_window);
params.delegate = frame_view;
params.native_widget = frame_native_widget;
- params.parent = root_;
+ params.parent = window_root_;
params.bounds = gfx::Rect(10, 10, 500, 500);
frame_widget->Init(params);
frame_widget->Show();
@@ -194,12 +394,36 @@ void SimpleWM::OnWmNewDisplay(
std::unique_ptr<aura::WindowTreeHostMus> window_tree_host,
const display::Display& display) {
// Only handles a single root.
- DCHECK(!root_);
+ DCHECK(!window_root_);
window_tree_host_ = std::move(window_tree_host);
window_tree_host_->InitCompositor();
- root_ = window_tree_host_->window();
+ 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_);
- window_manager_client_->AddActivationParent(root_);
+ window_manager_client_->AddActivationParent(window_root_);
ui::mojom::FrameDecorationValuesPtr frame_decoration_values =
ui::mojom::FrameDecorationValues::New();
frame_decoration_values->normal_client_area_insets.Set(
@@ -207,14 +431,14 @@ void SimpleWM::OnWmNewDisplay(
frame_decoration_values->max_title_bar_button_width = 0;
window_manager_client_->SetFrameDecorationValues(
std::move(frame_decoration_values));
- new wm::DefaultActivationClient(root_);
- aura::client::SetFocusClient(root_, &focus_client_);
+ new wm::DefaultActivationClient(display_root_);
+ aura::client::SetFocusClient(display_root_, &focus_client_);
}
void SimpleWM::OnWmDisplayRemoved(
aura::WindowTreeHostMus* window_tree_host) {
DCHECK_EQ(window_tree_host, window_tree_host_.get());
- root_ = nullptr;
+ window_root_ = nullptr;
window_tree_host_.reset();
}
@@ -241,5 +465,10 @@ SimpleWM::FrameView* SimpleWM::GetFrameViewForClientWindow(
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
« no previous file with comments | « mash/simple_wm/simple_wm.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698