summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsky <sky@chromium.org>2016-01-22 14:28:21 -0800
committerCommit bot <commit-bot@chromium.org>2016-01-22 22:30:08 +0000
commita57d9927dcb3a8548eae83450c8fe1ee7e3b568b (patch)
treeed20b2dd59f8476606cd4393f9595791440d9ca4
parent8d82e2ce2bc8d95fbfe53f6e7f98c345bba2de01 (diff)
downloadchromium_src-a57d9927dcb3a8548eae83450c8fe1ee7e3b568b.zip
chromium_src-a57d9927dcb3a8548eae83450c8fe1ee7e3b568b.tar.gz
chromium_src-a57d9927dcb3a8548eae83450c8fe1ee7e3b568b.tar.bz2
Start of display management for mus
This adds a DisplayManager interface that you get from mus. You can then attach an observer to observe display related changes. BUG=548429 TEST=none R=ben@chromium.org Committed: https://crrev.com/bc2281a7a7576f5b4da85986298322b3c9d2234e Cr-Commit-Position: refs/heads/master@{#370880} Review URL: https://codereview.chromium.org/1615023004 Cr-Commit-Position: refs/heads/master@{#371059}
-rw-r--r--ash/display/screen_ash.cc47
-rw-r--r--base/threading/thread_restrictions.h2
-rw-r--r--components/mus/mus_app.cc37
-rw-r--r--components/mus/mus_app.h15
-rw-r--r--components/mus/public/interfaces/BUILD.gn1
-rw-r--r--components/mus/public/interfaces/display.mojom25
-rw-r--r--components/mus/public/interfaces/window_manager_constants.mojom9
-rw-r--r--components/mus/ws/connection_manager.cc39
-rw-r--r--components/mus/ws/connection_manager.h19
-rw-r--r--components/mus/ws/display_manager.cc5
-rw-r--r--components/mus/ws/display_manager.h5
-rw-r--r--components/mus/ws/window_tree_host_impl.cc9
-rw-r--r--components/mus/ws/window_tree_host_impl.h6
-rw-r--r--components/mus/ws/window_tree_unittest.cc1
-rw-r--r--components/web_view/frame_connection.cc2
-rw-r--r--ui/gfx/BUILD.gn2
-rw-r--r--ui/gfx/display_finder.cc50
-rw-r--r--ui/gfx/display_finder.h31
-rw-r--r--ui/gfx/gfx.gyp2
-rw-r--r--ui/views/mus/BUILD.gn2
-rw-r--r--ui/views/mus/screen_mus.cc203
-rw-r--r--ui/views/mus/screen_mus.h71
-rw-r--r--ui/views/mus/window_manager_connection.cc61
-rw-r--r--ui/views/mus/window_manager_connection.h9
24 files changed, 539 insertions, 114 deletions
diff --git a/ash/display/screen_ash.cc b/ash/display/screen_ash.cc
index 6008922..477c710 100644
--- a/ash/display/screen_ash.cc
+++ b/ash/display/screen_ash.cc
@@ -17,6 +17,7 @@
#include "ui/aura/env.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/gfx/display.h"
+#include "ui/gfx/display_finder.h"
#include "ui/gfx/screen.h"
namespace ash {
@@ -27,42 +28,6 @@ DisplayManager* GetDisplayManager() {
return Shell::GetInstance()->display_manager();
}
-gfx::Display FindDisplayNearestPoint(const std::vector<gfx::Display>& displays,
- const gfx::Point& point) {
- int min_distance = INT_MAX;
- const gfx::Display* nearest_display = NULL;
- for (std::vector<gfx::Display>::const_iterator iter = displays.begin();
- iter != displays.end(); ++iter) {
- const gfx::Display& display = *iter;
- int distance = display.bounds().ManhattanDistanceToPoint(point);
- if (distance < min_distance) {
- min_distance = distance;
- nearest_display = &display;
- }
- }
- // There should always be at least one display that is less than INT_MAX away.
- DCHECK(nearest_display);
- return *nearest_display;
-}
-
-const gfx::Display* FindDisplayMatching(
- const std::vector<gfx::Display>& displays,
- const gfx::Rect& match_rect) {
- int max_area = 0;
- const gfx::Display* matching = NULL;
- for (std::vector<gfx::Display>::const_iterator iter = displays.begin();
- iter != displays.end(); ++iter) {
- const gfx::Display& display = *iter;
- gfx::Rect intersect = gfx::IntersectRects(display.bounds(), match_rect);
- int area = intersect.width() * intersect.height();
- if (area > max_area) {
- max_area = area;
- matching = &display;
- }
- }
- return matching;
-}
-
class ScreenForShutdown : public gfx::Screen {
public:
explicit ScreenForShutdown(ScreenAsh* screen_ash)
@@ -84,11 +49,11 @@ class ScreenForShutdown : public gfx::Screen {
return primary_display_;
}
gfx::Display GetDisplayNearestPoint(const gfx::Point& point) const override {
- return FindDisplayNearestPoint(display_list_, point);
+ return *gfx::FindDisplayNearestPoint(display_list_, point);
}
gfx::Display GetDisplayMatching(const gfx::Rect& match_rect) const override {
const gfx::Display* matching =
- FindDisplayMatching(display_list_, match_rect);
+ gfx::FindDisplayWithBiggestIntersection(display_list_, match_rect);
// Fallback to the primary display if there is no matching display.
return matching ? *matching : GetPrimaryDisplay();
}
@@ -187,14 +152,14 @@ gfx::Display ScreenAsh::GetDisplayNearestPoint(const gfx::Point& point) const {
// Fallback to the display that has the shortest Manhattan distance from
// the |point|. This is correct in the only areas that matter, namely in the
// corners between the physical screens.
- return FindDisplayNearestPoint(GetDisplayManager()->active_display_list(),
- point);
+ return *gfx::FindDisplayNearestPoint(
+ GetDisplayManager()->active_display_list(), point);
}
gfx::Display ScreenAsh::GetDisplayMatching(const gfx::Rect& match_rect) const {
if (match_rect.IsEmpty())
return GetDisplayNearestPoint(match_rect.origin());
- const gfx::Display* matching = FindDisplayMatching(
+ const gfx::Display* matching = gfx::FindDisplayWithBiggestIntersection(
GetDisplayManager()->active_display_list(), match_rect);
// Fallback to the primary display if there is no matching display.
return matching ? *matching : GetPrimaryDisplay();
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h
index eec00fb..ec380b8 100644
--- a/base/threading/thread_restrictions.h
+++ b/base/threading/thread_restrictions.h
@@ -81,6 +81,7 @@ class WindowResizeHelperMac;
}
namespace views {
+class ScreenMus;
class WindowManagerConnection;
}
@@ -233,6 +234,7 @@ class BASE_EXPORT ThreadRestrictions {
#if !defined(OFFICIAL_BUILD)
friend class content::SoftwareOutputDeviceMus; // Interim non-production code
#endif
+ friend class views::ScreenMus;
friend class views::WindowManagerConnection;
// END USAGE THAT NEEDS TO BE FIXED.
diff --git a/components/mus/mus_app.cc b/components/mus/mus_app.cc
index 25b97a0..c2dc704 100644
--- a/components/mus/mus_app.cc
+++ b/components/mus/mus_app.cc
@@ -39,6 +39,11 @@ using mus::mojom::Gpu;
namespace mus {
+struct MandolineUIServicesApp::PendingRequest {
+ scoped_ptr<mojo::InterfaceRequest<mojom::DisplayManager>> dm_request;
+ scoped_ptr<mojo::InterfaceRequest<mojom::WindowManager>> wm_request;
+};
+
MandolineUIServicesApp::MandolineUIServicesApp()
: app_impl_(nullptr) {}
@@ -87,16 +92,21 @@ void MandolineUIServicesApp::Initialize(ApplicationImpl* app) {
bool MandolineUIServicesApp::ConfigureIncomingConnection(
ApplicationConnection* connection) {
connection->AddService<Gpu>(this);
+ connection->AddService<mojom::DisplayManager>(this);
connection->AddService<mojom::WindowManager>(this);
connection->AddService<WindowTreeHostFactory>(this);
return true;
}
void MandolineUIServicesApp::OnFirstRootConnectionCreated() {
- WindowManagerRequests requests;
- requests.swap(pending_window_manager_requests_);
- for (auto& request : requests)
- Create(nullptr, std::move(*request));
+ PendingRequests requests;
+ requests.swap(pending_requests_);
+ for (auto& request : requests) {
+ if (request->dm_request)
+ Create(nullptr, std::move(*request->dm_request));
+ else
+ Create(nullptr, std::move(*request->wm_request));
+ }
}
void MandolineUIServicesApp::OnNoMoreRootConnections() {
@@ -119,10 +129,25 @@ MandolineUIServicesApp::CreateClientConnectionForEmbedAtWindow(
void MandolineUIServicesApp::Create(
mojo::ApplicationConnection* connection,
+ mojo::InterfaceRequest<mojom::DisplayManager> request) {
+ if (!connection_manager_->has_tree_host_connections()) {
+ scoped_ptr<PendingRequest> pending_request(new PendingRequest);
+ pending_request->dm_request.reset(
+ new mojo::InterfaceRequest<mojom::DisplayManager>(std::move(request)));
+ pending_requests_.push_back(std::move(pending_request));
+ return;
+ }
+ connection_manager_->AddDisplayManagerBinding(std::move(request));
+}
+
+void MandolineUIServicesApp::Create(
+ mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<mojom::WindowManager> request) {
if (!connection_manager_->has_tree_host_connections()) {
- pending_window_manager_requests_.push_back(make_scoped_ptr(
- new mojo::InterfaceRequest<mojom::WindowManager>(std::move(request))));
+ scoped_ptr<PendingRequest> pending_request(new PendingRequest);
+ pending_request->wm_request.reset(
+ new mojo::InterfaceRequest<mojom::WindowManager>(std::move(request)));
+ pending_requests_.push_back(std::move(pending_request));
return;
}
if (!window_manager_impl_) {
diff --git a/components/mus/mus_app.h b/components/mus/mus_app.h
index d318b569..08d893a 100644
--- a/components/mus/mus_app.h
+++ b/components/mus/mus_app.h
@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "components/mus/public/interfaces/display.mojom.h"
#include "components/mus/public/interfaces/gpu.mojom.h"
#include "components/mus/public/interfaces/window_manager.mojom.h"
#include "components/mus/public/interfaces/window_tree.mojom.h"
@@ -43,6 +44,7 @@ class ForwardingWindowManager;
class MandolineUIServicesApp
: public mojo::ApplicationDelegate,
public ws::ConnectionManagerDelegate,
+ public mojo::InterfaceFactory<mojom::DisplayManager>,
public mojo::InterfaceFactory<mojom::WindowManager>,
public mojo::InterfaceFactory<mojom::WindowTreeHostFactory>,
public mojo::InterfaceFactory<mojom::Gpu>,
@@ -52,6 +54,10 @@ class MandolineUIServicesApp
~MandolineUIServicesApp() override;
private:
+ // Holds InterfaceRequests received before the first WindowTreeHost Display
+ // has been established.
+ struct PendingRequest;
+
// ApplicationDelegate:
void Initialize(mojo::ApplicationImpl* app) override;
bool ConfigureIncomingConnection(
@@ -67,6 +73,10 @@ class MandolineUIServicesApp
uint32_t policy_bitmask,
mojom::WindowTreeClientPtr client) override;
+ // mojo::InterfaceFactory<mojom::DisplayManager> implementation.
+ void Create(mojo::ApplicationConnection* connection,
+ mojo::InterfaceRequest<mojom::DisplayManager> request) override;
+
// mojo::InterfaceFactory<mojom::WindowManager> implementation.
void Create(mojo::ApplicationConnection* connection,
mojo::InterfaceRequest<mojom::WindowManager> request) override;
@@ -94,9 +104,8 @@ class MandolineUIServicesApp
scoped_refptr<GpuState> gpu_state_;
scoped_ptr<ui::PlatformEventSource> event_source_;
mojo::TracingImpl tracing_;
- using WindowManagerRequests =
- std::vector<scoped_ptr<mojo::InterfaceRequest<mojom::WindowManager>>>;
- WindowManagerRequests pending_window_manager_requests_;
+ using PendingRequests = std::vector<scoped_ptr<PendingRequest>>;
+ PendingRequests pending_requests_;
// Surfaces
scoped_refptr<SurfacesState> surfaces_state_;
diff --git a/components/mus/public/interfaces/BUILD.gn b/components/mus/public/interfaces/BUILD.gn
index c20d0db..a9c8dd1 100644
--- a/components/mus/public/interfaces/BUILD.gn
+++ b/components/mus/public/interfaces/BUILD.gn
@@ -10,6 +10,7 @@ mojom("interfaces") {
"command_buffer.mojom",
"compositor_frame.mojom",
"cursor.mojom",
+ "display.mojom",
"gpu.mojom",
"gpu_capabilities.mojom",
"input_event_constants.mojom",
diff --git a/components/mus/public/interfaces/display.mojom b/components/mus/public/interfaces/display.mojom
new file mode 100644
index 0000000..7136499
--- /dev/null
+++ b/components/mus/public/interfaces/display.mojom
@@ -0,0 +1,25 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module mus.mojom;
+
+import "components/mus/public/interfaces/window_manager_constants.mojom";
+
+interface DisplayManagerObserver {
+ // Sent when the observer is added. Gives the initial state.
+ OnDisplays(array<Display> displays);
+
+ // The specified set of displays has changed in some way. This is used both
+ // when a new display is added, or when a property of a display changes.
+ // |displays| does not necessarily contain the complete set of displays,
+ // only those that changed.
+ OnDisplaysChanged(array<Display> displays);
+
+ // An existing display was removed.
+ OnDisplayRemoved(int64 id);
+};
+
+interface DisplayManager {
+ AddObserver(DisplayManagerObserver observer);
+};
diff --git a/components/mus/public/interfaces/window_manager_constants.mojom b/components/mus/public/interfaces/window_manager_constants.mojom
index 010b2a6f..9b86fa2 100644
--- a/components/mus/public/interfaces/window_manager_constants.mojom
+++ b/components/mus/public/interfaces/window_manager_constants.mojom
@@ -31,12 +31,21 @@ const int32 kResizeBehaviorCanResize = 1;
const int32 kResizeBehaviorCanMaximize = 2;
const int32 kResizeBehaviorCanMinimize = 4;
+enum TouchSupport {
+ UNKNOWN,
+ AVAILABLE,
+ UNAVAILABLE,
+};
+
+// TODO(sky): move this to display.mojom
struct Display {
int64 id;
mojo.Rect bounds;
mojo.Rect work_area;
float device_pixel_ratio;
Rotation rotation;
+ TouchSupport touch_support;
+ bool is_primary;
};
enum WindowType {
diff --git a/components/mus/ws/connection_manager.cc b/components/mus/ws/connection_manager.cc
index fd7e782..3cd24d8 100644
--- a/components/mus/ws/connection_manager.cc
+++ b/components/mus/ws/connection_manager.cc
@@ -20,7 +20,6 @@
#include "ui/gfx/geometry/size_conversions.h"
namespace mus {
-
namespace ws {
ConnectionManager::ConnectionManager(
@@ -254,6 +253,11 @@ WindowTreeHostImpl* ConnectionManager::GetActiveWindowTreeHost() {
return host_connection_map_.begin()->first;
}
+void ConnectionManager::AddDisplayManagerBinding(
+ mojo::InterfaceRequest<mojom::DisplayManager> request) {
+ display_manager_bindings_.AddBinding(this, std::move(request));
+}
+
uint32_t ConnectionManager::GenerateWindowManagerChangeId(
WindowTreeImpl* source,
uint32_t client_change_id) {
@@ -583,6 +587,37 @@ void ConnectionManager::OnTransientWindowRemoved(
}
}
-} // namespace ws
+void ConnectionManager::AddObserver(mojom::DisplayManagerObserverPtr observer) {
+ mojo::Array<mojom::DisplayPtr> displays(host_connection_map_.size());
+ {
+ size_t i = 0;
+ int next_x = 0;
+ for (auto& pair : host_connection_map_) {
+ const WindowTreeHostImpl* tree_host = pair.first;
+ const ServerWindow* root = tree_host->root_window();
+ displays[i] = mojom::Display::New();
+ displays[i]->id = tree_host->id();
+ displays[i]->bounds = mojo::Rect::New();
+ displays[i]->bounds->x = next_x;
+ displays[i]->bounds->y = 0;
+ displays[i]->bounds->width = root->bounds().size().width();
+ displays[i]->bounds->height = root->bounds().size().height();
+ next_x += displays[i]->bounds->width;
+ // TODO(sky): window manager needs an API to set the work area.
+ displays[i]->work_area = displays[i]->bounds.Clone();
+ displays[i]->device_pixel_ratio =
+ tree_host->GetViewportMetrics().device_pixel_ratio;
+ displays[i]->rotation = tree_host->GetRotation();
+ // TODO(sky): make this real.
+ displays[i]->is_primary = i == 0;
+ // TODO(sky): make this real.
+ displays[i]->touch_support = mojom::TouchSupport::UNKNOWN;
+ ++i;
+ }
+ }
+ observer->OnDisplays(std::move(displays));
+ display_manager_observers_.AddInterfacePtr(std::move(observer));
+}
+} // namespace ws
} // namespace mus
diff --git a/components/mus/ws/connection_manager.h b/components/mus/ws/connection_manager.h
index 79210b5..922ac5f 100644
--- a/components/mus/ws/connection_manager.h
+++ b/components/mus/ws/connection_manager.h
@@ -14,6 +14,7 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/timer/timer.h"
+#include "components/mus/public/interfaces/display.mojom.h"
#include "components/mus/public/interfaces/window_tree.mojom.h"
#include "components/mus/public/interfaces/window_tree_host.mojom.h"
#include "components/mus/surfaces/surfaces_state.h"
@@ -22,6 +23,8 @@
#include "components/mus/ws/server_window_delegate.h"
#include "components/mus/ws/server_window_observer.h"
#include "components/mus/ws/window_tree_host_impl.h"
+#include "mojo/common/weak_binding_set.h"
+#include "mojo/common/weak_interface_ptr_set.h"
#include "mojo/converters/surfaces/custom_surface_converter.h"
#include "mojo/public/cpp/bindings/array.h"
#include "mojo/public/cpp/bindings/binding.h"
@@ -37,8 +40,12 @@ class WindowTreeImpl;
// ConnectionManager manages the set of connections to the window server (all
// the WindowTreeImpls) as well as providing the root of the hierarchy.
+//
+// TODO(sky): this class is doing too much. Refactor to make responsibilities
+// clearer.
class ConnectionManager : public ServerWindowDelegate,
- public ServerWindowObserver {
+ public ServerWindowObserver,
+ public mojom::DisplayManager {
public:
ConnectionManager(ConnectionManagerDelegate* delegate,
const scoped_refptr<mus::SurfacesState>& surfaces_state);
@@ -125,6 +132,9 @@ class ConnectionManager : public ServerWindowDelegate,
return !host_connection_map_.empty();
}
+ void AddDisplayManagerBinding(
+ mojo::InterfaceRequest<mojom::DisplayManager> request);
+
// Returns a change id for the window manager that is associated with
// |source| and |client_change_id|. When the window manager replies
// WindowManagerChangeCompleted() is called to obtain the original source
@@ -254,6 +264,9 @@ class ConnectionManager : public ServerWindowDelegate,
void OnTransientWindowRemoved(ServerWindow* window,
ServerWindow* transient_child) override;
+ // Overriden from mojom::DisplayManager:
+ void AddObserver(mojom::DisplayManagerObserverPtr observer) override;
+
ConnectionManagerDelegate* delegate_;
// State for rendering into a Surface.
@@ -284,6 +297,10 @@ class ConnectionManager : public ServerWindowDelegate,
// Next id supplied to the window manager.
uint32_t next_wm_change_id_;
+ mojo::WeakBindingSet<mojom::DisplayManager> display_manager_bindings_;
+ mojo::WeakInterfacePtrSet<mojom::DisplayManagerObserver>
+ display_manager_observers_;
+
DISALLOW_COPY_AND_ASSIGN(ConnectionManager);
};
diff --git a/components/mus/ws/display_manager.cc b/components/mus/ws/display_manager.cc
index e38e1d4..205a6506 100644
--- a/components/mus/ws/display_manager.cc
+++ b/components/mus/ws/display_manager.cc
@@ -254,6 +254,11 @@ const mojom::ViewportMetrics& DefaultDisplayManager::GetViewportMetrics() {
return metrics_;
}
+mojom::Rotation DefaultDisplayManager::GetRotation() {
+ // TODO(sky): implement me.
+ return mojom::Rotation::VALUE_0;
+}
+
void DefaultDisplayManager::UpdateTextInputState(
const ui::TextInputState& state) {
ui::PlatformImeController* ime = platform_window_->GetPlatformImeController();
diff --git a/components/mus/ws/display_manager.h b/components/mus/ws/display_manager.h
index 4cf6e4b..be2c3130 100644
--- a/components/mus/ws/display_manager.h
+++ b/components/mus/ws/display_manager.h
@@ -15,6 +15,7 @@
#include "base/strings/string16.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
+#include "components/mus/public/interfaces/window_manager_constants.mojom.h"
#include "components/mus/public/interfaces/window_tree.mojom.h"
#include "components/mus/ws/display_manager_delegate.h"
#include "mojo/public/cpp/bindings/callback.h"
@@ -54,6 +55,7 @@ class EventDispatcher;
class ServerWindow;
// DisplayManager is used to connect the root ServerWindow to a display.
+// TODO(sky): rename this given we have a mojom type with the same name now.
class DisplayManager {
public:
virtual ~DisplayManager() {}
@@ -75,6 +77,8 @@ class DisplayManager {
virtual void SetCursorById(int32_t cursor) = 0;
+ virtual mojom::Rotation GetRotation() = 0;
+
virtual const mojom::ViewportMetrics& GetViewportMetrics() = 0;
virtual void UpdateTextInputState(const ui::TextInputState& state) = 0;
@@ -112,6 +116,7 @@ class DefaultDisplayManager : public DisplayManager,
void SetTitle(const base::string16& title) override;
void SetCursorById(int32_t cursor) override;
const mojom::ViewportMetrics& GetViewportMetrics() override;
+ mojom::Rotation GetRotation() override;
void UpdateTextInputState(const ui::TextInputState& state) override;
void SetImeVisibility(bool visible) override;
bool IsFramePending() const override;
diff --git a/components/mus/ws/window_tree_host_impl.cc b/components/mus/ws/window_tree_host_impl.cc
index ef92138..8aa8f6a 100644
--- a/components/mus/ws/window_tree_host_impl.cc
+++ b/components/mus/ws/window_tree_host_impl.cc
@@ -51,6 +51,8 @@ mojom::EventPtr CoalesceEvents(mojom::EventPtr first, mojom::EventPtr second) {
return second;
}
+uint32_t next_id = 1;
+
} // namespace
class WindowTreeHostImpl::ProcessedEventTarget {
@@ -98,7 +100,8 @@ WindowTreeHostImpl::WindowTreeHostImpl(
DisplayManager::Create(app_impl, gpu_state, surfaces_state)),
window_manager_(std::move(window_manager)),
tree_awaiting_input_ack_(nullptr),
- last_cursor_(0) {
+ last_cursor_(0),
+ id_(next_id) {
display_manager_->Init(this);
if (client_) {
client_.set_connection_error_handler(base::Bind(
@@ -155,6 +158,10 @@ const mojom::ViewportMetrics& WindowTreeHostImpl::GetViewportMetrics() const {
return display_manager_->GetViewportMetrics();
}
+mojom::Rotation WindowTreeHostImpl::GetRotation() const {
+ return display_manager_->GetRotation();
+}
+
void WindowTreeHostImpl::SetFocusedWindow(ServerWindow* new_focused_window) {
ServerWindow* old_focused_window = focus_controller_->GetFocusedWindow();
if (old_focused_window == new_focused_window)
diff --git a/components/mus/ws/window_tree_host_impl.h b/components/mus/ws/window_tree_host_impl.h
index 5247b01..850b3ee 100644
--- a/components/mus/ws/window_tree_host_impl.h
+++ b/components/mus/ws/window_tree_host_impl.h
@@ -56,6 +56,8 @@ class WindowTreeHostImpl : public DisplayManagerDelegate,
// Initializes state that depends on the existence of a WindowTreeHostImpl.
void Init(WindowTreeHostDelegate* delegate);
+ uint32_t id() const { return id_; }
+
const WindowTreeImpl* GetWindowTree() const;
WindowTreeImpl* GetWindowTree();
@@ -80,6 +82,8 @@ class WindowTreeHostImpl : public DisplayManagerDelegate,
// Returns the metrics for this viewport.
const mojom::ViewportMetrics& GetViewportMetrics() const;
+ mojom::Rotation GetRotation() const;
+
ConnectionManager* connection_manager() { return connection_manager_; }
mojom::WindowManager* window_manager() { return window_manager_.get(); }
@@ -222,6 +226,8 @@ class WindowTreeHostImpl : public DisplayManagerDelegate,
std::queue<scoped_ptr<QueuedEvent>> event_queue_;
base::OneShotTimer event_ack_timer_;
+ const uint32_t id_;
+
DISALLOW_COPY_AND_ASSIGN(WindowTreeHostImpl);
};
diff --git a/components/mus/ws/window_tree_unittest.cc b/components/mus/ws/window_tree_unittest.cc
index 1a8f84b..d985e6e 100644
--- a/components/mus/ws/window_tree_unittest.cc
+++ b/components/mus/ws/window_tree_unittest.cc
@@ -312,6 +312,7 @@ class TestDisplayManager : public DisplayManager {
void SetViewportSize(const gfx::Size& size) override {}
void SetTitle(const base::string16& title) override {}
void SetCursorById(int32_t cursor) override { *cursor_id_storage_ = cursor; }
+ mojom::Rotation GetRotation() override { return mojom::Rotation::VALUE_0; }
const mojom::ViewportMetrics& GetViewportMetrics() override {
return display_metrices_;
}
diff --git a/components/web_view/frame_connection.cc b/components/web_view/frame_connection.cc
index a29b0501..7358c3d 100644
--- a/components/web_view/frame_connection.cc
+++ b/components/web_view/frame_connection.cc
@@ -10,6 +10,7 @@
#include "base/callback.h"
#include "build/build_config.h"
#include "components/clipboard/public/interfaces/clipboard.mojom.h"
+#include "components/mus/public/interfaces/display.mojom.h"
#include "components/mus/public/interfaces/gpu.mojom.h"
#include "components/mus/public/interfaces/window_tree_host.mojom.h"
#include "components/resource_provider/public/interfaces/resource_provider.mojom.h"
@@ -100,6 +101,7 @@ void FrameConnection::Init(mojo::ApplicationImpl* app,
mojo::Array<mojo::String> window_manager_interfaces;
window_manager_interfaces.push_back(mus::mojom::Gpu::Name_);
window_manager_interfaces.push_back(mus::mojom::WindowTreeHostFactory::Name_);
+ window_manager_interfaces.push_back(mus::mojom::DisplayManager::Name_);
filter->filter.insert("mojo:mus", std::move(window_manager_interfaces));
mojo::Array<mojo::String> test_runner_interfaces;
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn
index 3bb45dd..eab0ab8 100644
--- a/ui/gfx/BUILD.gn
+++ b/ui/gfx/BUILD.gn
@@ -72,6 +72,8 @@ component("gfx") {
"display.h",
"display_change_notifier.cc",
"display_change_notifier.h",
+ "display_finder.cc",
+ "display_finder.h",
"display_observer.cc",
"display_observer.h",
"favicon_size.cc",
diff --git a/ui/gfx/display_finder.cc b/ui/gfx/display_finder.cc
new file mode 100644
index 0000000..af27f1b
--- /dev/null
+++ b/ui/gfx/display_finder.cc
@@ -0,0 +1,50 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/display_finder.h"
+
+#include <limits>
+
+#include "base/logging.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace gfx {
+
+const Display* FindDisplayNearestPoint(const std::vector<Display>& displays,
+ const Point& point) {
+ DCHECK(!displays.empty());
+ int min_distance = std::numeric_limits<int>::max();
+ const Display* nearest_display = nullptr;
+ for (const auto& display : displays) {
+ const int distance = display.bounds().ManhattanDistanceToPoint(point);
+ if (distance < min_distance) {
+ min_distance = distance;
+ nearest_display = &display;
+ }
+ }
+ // There should always be at least one display that is less than INT_MAX away.
+ DCHECK(nearest_display);
+ return nearest_display;
+}
+
+const Display* FindDisplayWithBiggestIntersection(
+ const std::vector<Display>& displays,
+ const Rect& rect) {
+ DCHECK(!displays.empty());
+ int max_area = 0;
+ const Display* matching = nullptr;
+ for (const auto& display : displays) {
+ const Rect intersect = IntersectRects(display.bounds(), rect);
+ const int area = intersect.width() * intersect.height();
+ if (area > max_area) {
+ max_area = area;
+ matching = &display;
+ }
+ }
+ return matching;
+}
+
+} // namespace gfx
diff --git a/ui/gfx/display_finder.h b/ui/gfx/display_finder.h
new file mode 100644
index 0000000..2fb81f6
--- /dev/null
+++ b/ui/gfx/display_finder.h
@@ -0,0 +1,31 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_DISPLAY_FINDER_H_
+#define UI_GFX_DISPLAY_FINDER_H_
+
+#include <vector>
+
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+class Display;
+class Point;
+class Rect;
+
+// Returns the display in |displays| closest to |point|.
+GFX_EXPORT const Display* FindDisplayNearestPoint(
+ const std::vector<Display>& displays,
+ const Point& point);
+
+// Returns the display in |displays| with the biggest intersection of |rect|.
+// If none of the displays intersect |rect| null is returned.
+GFX_EXPORT const Display* FindDisplayWithBiggestIntersection(
+ const std::vector<Display>& displays,
+ const Rect& rect);
+
+} // namespace gfx
+
+#endif // UI_GFX_DISPLAY_FINDER_H_
diff --git a/ui/gfx/gfx.gyp b/ui/gfx/gfx.gyp
index edff14b..c2bb097 100644
--- a/ui/gfx/gfx.gyp
+++ b/ui/gfx/gfx.gyp
@@ -153,6 +153,8 @@
'display.h',
'display_change_notifier.cc',
'display_change_notifier.h',
+ 'display_finder.cc',
+ 'display_finder.h',
'display_observer.cc',
'display_observer.h',
'favicon_size.cc',
diff --git a/ui/views/mus/BUILD.gn b/ui/views/mus/BUILD.gn
index f386389..bf49a3d 100644
--- a/ui/views/mus/BUILD.gn
+++ b/ui/views/mus/BUILD.gn
@@ -23,6 +23,8 @@ component("mus") {
"native_widget_mus.h",
"platform_window_mus.cc",
"platform_window_mus.h",
+ "screen_mus.cc",
+ "screen_mus.h",
"surface_binding.cc",
"surface_binding.h",
"surface_context_factory.cc",
diff --git a/ui/views/mus/screen_mus.cc b/ui/views/mus/screen_mus.cc
new file mode 100644
index 0000000..2a02349
--- /dev/null
+++ b/ui/views/mus/screen_mus.cc
@@ -0,0 +1,203 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/mus/screen_mus.h"
+
+#include "mojo/converters/geometry/geometry_type_converters.h"
+#include "mojo/shell/public/cpp/application_connection.h"
+#include "mojo/shell/public/cpp/application_impl.h"
+#include "ui/gfx/display_finder.h"
+#include "ui/gfx/display_observer.h"
+
+namespace mojo {
+
+template <>
+struct TypeConverter<gfx::Display, mus::mojom::DisplayPtr> {
+ static gfx::Display Convert(const mus::mojom::DisplayPtr& input) {
+ gfx::Display result(input->id, input->bounds.To<gfx::Rect>());
+ result.set_work_area(input->work_area.To<gfx::Rect>());
+ result.set_device_scale_factor(input->device_pixel_ratio);
+ switch (input->rotation) {
+ case mus::mojom::Rotation::VALUE_0:
+ result.set_rotation(gfx::Display::ROTATE_0);
+ break;
+ case mus::mojom::Rotation::VALUE_90:
+ result.set_rotation(gfx::Display::ROTATE_90);
+ break;
+ case mus::mojom::Rotation::VALUE_180:
+ result.set_rotation(gfx::Display::ROTATE_180);
+ break;
+ case mus::mojom::Rotation::VALUE_270:
+ result.set_rotation(gfx::Display::ROTATE_270);
+ break;
+ }
+ switch (input->touch_support) {
+ case mus::mojom::TouchSupport::UNKNOWN:
+ result.set_touch_support(gfx::Display::TOUCH_SUPPORT_UNKNOWN);
+ break;
+ case mus::mojom::TouchSupport::AVAILABLE:
+ result.set_touch_support(gfx::Display::TOUCH_SUPPORT_AVAILABLE);
+ break;
+ case mus::mojom::TouchSupport::UNAVAILABLE:
+ result.set_touch_support(gfx::Display::TOUCH_SUPPORT_UNAVAILABLE);
+ break;
+ }
+ return result;
+ }
+};
+
+} // namespace mojo
+
+namespace views {
+
+ScreenMus::ScreenMus()
+ : primary_display_index_(0), display_manager_observer_binding_(this) {}
+
+ScreenMus::~ScreenMus() {}
+
+void ScreenMus::Init(mojo::ApplicationImpl* app) {
+ gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, this);
+
+ app->ConnectToService("mojo:mus", &display_manager_);
+
+ display_manager_->AddObserver(
+ display_manager_observer_binding_.CreateInterfacePtrAndBind());
+ // We need the set of displays before we can continue. Wait for it.
+ display_manager_observer_binding_.WaitForIncomingMethodCall();
+
+ // The WaitForIncomingMethodCall() should have supplied the set of Displays.
+ DCHECK(displays_.size());
+}
+
+int ScreenMus::FindDisplayIndexById(int64_t id) const {
+ for (size_t i = 0; i < displays_.size(); ++i) {
+ if (displays_[i].id() == id)
+ return static_cast<int>(i);
+ }
+ return -1;
+}
+
+void ScreenMus::ProcessDisplayChanged(const gfx::Display& changed_display,
+ bool is_primary) {
+ const int display_index = FindDisplayIndexById(changed_display.id());
+ if (display_index == -1) {
+ displays_.push_back(changed_display);
+ if (is_primary)
+ primary_display_index_ = static_cast<int>(displays_.size()) - 1;
+ FOR_EACH_OBSERVER(gfx::DisplayObserver, observers_,
+ OnDisplayAdded(changed_display));
+ return;
+ }
+
+ gfx::Display* local_display = &displays_[display_index];
+ uint32_t changed_values = 0;
+ if (is_primary && display_index != primary_display_index_) {
+ primary_display_index_ = display_index;
+ // ash::DisplayManager only notifies for the Display gaining primary, not
+ // the one losing it.
+ changed_values |= gfx::DisplayObserver::DISPLAY_METRIC_PRIMARY;
+ }
+ if (local_display->bounds() != changed_display.bounds()) {
+ local_display->set_bounds(changed_display.bounds());
+ changed_values |= gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS;
+ }
+ if (local_display->work_area() != changed_display.work_area()) {
+ local_display->set_work_area(changed_display.work_area());
+ changed_values |= gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA;
+ }
+ if (local_display->rotation() != changed_display.rotation()) {
+ local_display->set_rotation(changed_display.rotation());
+ changed_values |= gfx::DisplayObserver::DISPLAY_METRIC_ROTATION;
+ }
+ if (local_display->device_scale_factor() !=
+ changed_display.device_scale_factor()) {
+ local_display->set_device_scale_factor(
+ changed_display.device_scale_factor());
+ changed_values |= gfx::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR;
+ }
+ FOR_EACH_OBSERVER(gfx::DisplayObserver, observers_,
+ OnDisplayMetricsChanged(*local_display, changed_values));
+}
+
+gfx::Point ScreenMus::GetCursorScreenPoint() {
+ NOTIMPLEMENTED();
+ return gfx::Point();
+}
+
+gfx::NativeWindow ScreenMus::GetWindowUnderCursor() {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+gfx::NativeWindow ScreenMus::GetWindowAtScreenPoint(const gfx::Point& point) {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+gfx::Display ScreenMus::GetPrimaryDisplay() const {
+ return displays_[primary_display_index_];
+}
+
+gfx::Display ScreenMus::GetDisplayNearestWindow(gfx::NativeView view) const {
+ NOTIMPLEMENTED();
+ return GetPrimaryDisplay();
+}
+
+gfx::Display ScreenMus::GetDisplayNearestPoint(const gfx::Point& point) const {
+ return *gfx::FindDisplayNearestPoint(displays_, point);
+}
+
+int ScreenMus::GetNumDisplays() const {
+ return static_cast<int>(displays_.size());
+}
+
+std::vector<gfx::Display> ScreenMus::GetAllDisplays() const {
+ return displays_;
+}
+
+gfx::Display ScreenMus::GetDisplayMatching(const gfx::Rect& match_rect) const {
+ const gfx::Display* match =
+ gfx::FindDisplayWithBiggestIntersection(displays_, match_rect);
+ return match ? *match : GetPrimaryDisplay();
+}
+
+void ScreenMus::AddObserver(gfx::DisplayObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void ScreenMus::RemoveObserver(gfx::DisplayObserver* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void ScreenMus::OnDisplays(mojo::Array<mus::mojom::DisplayPtr> displays) {
+ // This should only be called once from Init() before any observers have been
+ // added.
+ DCHECK(displays_.empty());
+ displays_ = displays.To<std::vector<gfx::Display>>();
+ for (size_t i = 0; i < displays.size(); ++i) {
+ if (displays[i]->is_primary)
+ primary_display_index_ = static_cast<int>(i);
+ }
+}
+
+void ScreenMus::OnDisplaysChanged(
+ mojo::Array<mus::mojom::DisplayPtr> transport_displays) {
+ for (size_t i = 0; i < transport_displays.size(); ++i) {
+ const bool is_primary = transport_displays[i]->is_primary;
+ ProcessDisplayChanged(transport_displays[i].To<gfx::Display>(), is_primary);
+ }
+}
+
+void ScreenMus::OnDisplayRemoved(int64_t id) {
+ const int index = FindDisplayIndexById(id);
+ DCHECK_NE(-1, index);
+ // Another display must become primary before the existing primary is
+ // removed.
+ DCHECK_NE(index, primary_display_index_);
+ const gfx::Display display = displays_[index];
+ FOR_EACH_OBSERVER(gfx::DisplayObserver, observers_,
+ OnDisplayRemoved(display));
+}
+
+} // namespace views
diff --git a/ui/views/mus/screen_mus.h b/ui/views/mus/screen_mus.h
new file mode 100644
index 0000000..16adc16
--- /dev/null
+++ b/ui/views/mus/screen_mus.h
@@ -0,0 +1,71 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_MUS_SCREEN_MUS_H_
+#define UI_VIEWS_MUS_SCREEN_MUS_H_
+
+#include <vector>
+
+#include "base/observer_list.h"
+#include "components/mus/public/interfaces/display.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/screen.h"
+#include "ui/views/mus/mus_export.h"
+
+namespace mojo {
+class ApplicationImpl;
+}
+
+namespace views {
+
+// Screen implementation backed by mus::mojom::DisplayManager.
+class VIEWS_MUS_EXPORT ScreenMus
+ : public gfx::Screen,
+ public NON_EXPORTED_BASE(mus::mojom::DisplayManagerObserver) {
+ public:
+ ScreenMus();
+ ~ScreenMus() override;
+
+ void Init(mojo::ApplicationImpl* app);
+
+ private:
+ int FindDisplayIndexById(int64_t id) const;
+
+ // Invoked when a display changed in some weay, including being added.
+ // If |is_primary| is true, |changed_display| is the primary display.
+ void ProcessDisplayChanged(const gfx::Display& changed_display,
+ bool is_primary);
+
+ // gfx::Screen:
+ gfx::Point GetCursorScreenPoint() override;
+ gfx::NativeWindow GetWindowUnderCursor() override;
+ gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) override;
+ gfx::Display GetPrimaryDisplay() const override;
+ gfx::Display GetDisplayNearestWindow(gfx::NativeView view) const override;
+ gfx::Display GetDisplayNearestPoint(const gfx::Point& point) const override;
+ int GetNumDisplays() const override;
+ std::vector<gfx::Display> GetAllDisplays() const override;
+ gfx::Display GetDisplayMatching(const gfx::Rect& match_rect) const override;
+ void AddObserver(gfx::DisplayObserver* observer) override;
+ void RemoveObserver(gfx::DisplayObserver* observer) override;
+
+ // mus::mojom::DisplayManager:
+ void OnDisplays(mojo::Array<mus::mojom::DisplayPtr> displays) override;
+ void OnDisplaysChanged(mojo::Array<mus::mojom::DisplayPtr> display) override;
+ void OnDisplayRemoved(int64_t id) override;
+
+ mus::mojom::DisplayManagerPtr display_manager_;
+ std::vector<gfx::Display> displays_;
+ int primary_display_index_;
+ mojo::Binding<mus::mojom::DisplayManagerObserver>
+ display_manager_observer_binding_;
+ base::ObserverList<gfx::DisplayObserver> observers_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenMus);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_MUS_SCREEN_MUS_H_
diff --git a/ui/views/mus/window_manager_connection.cc b/ui/views/mus/window_manager_connection.cc
index b13c09e..defc7e4 100644
--- a/ui/views/mus/window_manager_connection.cc
+++ b/ui/views/mus/window_manager_connection.cc
@@ -15,55 +15,12 @@
#include "mojo/converters/network/network_type_converters.h"
#include "mojo/shell/public/cpp/application_connection.h"
#include "mojo/shell/public/cpp/application_impl.h"
-#include "ui/gfx/display.h"
-#include "ui/gfx/geometry/point_conversions.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/mojo/init/ui_init.h"
#include "ui/views/mus/native_widget_mus.h"
+#include "ui/views/mus/screen_mus.h"
#include "ui/views/mus/window_manager_frame_values.h"
#include "ui/views/views_delegate.h"
-namespace mojo {
-
-gfx::Display::Rotation GFXRotationFromMojomRotation(
- mus::mojom::Rotation input) {
- switch (input) {
- case mus::mojom::Rotation::VALUE_0:
- return gfx::Display::ROTATE_0;
- case mus::mojom::Rotation::VALUE_90:
- return gfx::Display::ROTATE_90;
- case mus::mojom::Rotation::VALUE_180:
- return gfx::Display::ROTATE_180;
- case mus::mojom::Rotation::VALUE_270:
- return gfx::Display::ROTATE_270;
- }
- return gfx::Display::ROTATE_0;
-}
-
-template <>
-struct TypeConverter<gfx::Display, mus::mojom::DisplayPtr> {
- static gfx::Display Convert(const mus::mojom::DisplayPtr& input) {
- gfx::Display result;
- result.set_id(input->id);
- result.SetScaleAndBounds(input->device_pixel_ratio,
- input->bounds.To<gfx::Rect>());
- gfx::Rect work_area(
- gfx::ScaleToFlooredPoint(
- gfx::Point(input->work_area->x, input->work_area->y),
- 1.0f / input->device_pixel_ratio),
- gfx::ScaleToFlooredSize(
- gfx::Size(input->work_area->width, input->work_area->height),
- 1.0f / input->device_pixel_ratio));
- result.set_work_area(work_area);
- result.set_rotation(GFXRotationFromMojomRotation(input->rotation));
- return result;
- }
-};
-
-} // namespace mojo
-
namespace views {
-
namespace {
using WindowManagerConnectionPtr =
@@ -73,14 +30,11 @@ using WindowManagerConnectionPtr =
base::LazyInstance<WindowManagerConnectionPtr>::Leaky lazy_tls_ptr =
LAZY_INSTANCE_INITIALIZER;
-std::vector<gfx::Display> GetDisplaysFromWindowManager(
- mus::mojom::WindowManagerPtr* window_manager) {
+void GetWindowManagerFrameValues(mus::mojom::WindowManagerPtr* window_manager) {
+ // TODO(sky): maybe this should be associated with Display?
WindowManagerFrameValues frame_values;
- std::vector<gfx::Display> displays;
(*window_manager)
- ->GetConfig([&displays,
- &frame_values](mus::mojom::WindowManagerConfigPtr results) {
- displays = results->displays.To<std::vector<gfx::Display>>();
+ ->GetConfig([&frame_values](mus::mojom::WindowManagerConfigPtr results) {
frame_values.normal_insets =
results->normal_client_area_insets.To<gfx::Insets>();
frame_values.maximized_insets =
@@ -90,7 +44,6 @@ std::vector<gfx::Display> GetDisplaysFromWindowManager(
});
CHECK(window_manager->WaitForIncomingResponse());
WindowManagerFrameValues::SetInstance(frame_values);
- return displays;
}
} // namespace
@@ -133,8 +86,10 @@ WindowManagerConnection::WindowManagerConnection(mojo::ApplicationImpl* app)
: app_(app), window_tree_connection_(nullptr) {
app->ConnectToService("mojo:mus", &window_manager_);
- ui_init_.reset(new ui::mojo::UIInit(
- GetDisplaysFromWindowManager(&window_manager_)));
+ GetWindowManagerFrameValues(&window_manager_);
+
+ screen_.reset(new ScreenMus);
+ screen_->Init(app);
ViewsDelegate::GetInstance()->set_native_widget_factory(
base::Bind(&WindowManagerConnection::CreateNativeWidget,
base::Unretained(this)));
diff --git a/ui/views/mus/window_manager_connection.h b/ui/views/mus/window_manager_connection.h
index ab12a03..af25003 100644
--- a/ui/views/mus/window_manager_connection.h
+++ b/ui/views/mus/window_manager_connection.h
@@ -18,14 +18,9 @@ namespace mojo {
class ApplicationImpl;
}
-namespace ui {
-namespace mojo {
-class UIInit;
-}
-}
-
namespace views {
class NativeWidget;
+class ScreenMus;
namespace internal {
class NativeWidgetDelegate;
}
@@ -60,7 +55,7 @@ class VIEWS_MUS_EXPORT WindowManagerConnection
mojo::ApplicationImpl* app_;
mus::mojom::WindowManagerPtr window_manager_;
- scoped_ptr<ui::mojo::UIInit> ui_init_;
+ scoped_ptr<ScreenMus> screen_;
scoped_ptr<mus::WindowTreeConnection> window_tree_connection_;
DISALLOW_COPY_AND_ASSIGN(WindowManagerConnection);