diff options
author | sky <sky@chromium.org> | 2016-01-22 14:28:21 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-22 22:30:08 +0000 |
commit | a57d9927dcb3a8548eae83450c8fe1ee7e3b568b (patch) | |
tree | ed20b2dd59f8476606cd4393f9595791440d9ca4 | |
parent | 8d82e2ce2bc8d95fbfe53f6e7f98c345bba2de01 (diff) | |
download | chromium_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}
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); |