Index: components/mus/ws/connection_manager.cc |
diff --git a/components/mus/ws/connection_manager.cc b/components/mus/ws/connection_manager.cc |
index 3cd24d8f5eba2729ec414e028dae8de259f3a53e..c7a6bee3a7fb9e3e7bd1b8d2aa60ed81268495e5 100644 |
--- a/components/mus/ws/connection_manager.cc |
+++ b/components/mus/ws/connection_manager.cc |
@@ -31,7 +31,8 @@ ConnectionManager::ConnectionManager( |
next_host_id_(0), |
current_operation_(nullptr), |
in_destructor_(false), |
- next_wm_change_id_(0) {} |
+ next_wm_change_id_(0), |
+ got_valid_frame_decorations_(false) {} |
ConnectionManager::~ConnectionManager() { |
in_destructor_ = true; |
@@ -391,6 +392,24 @@ void ConnectionManager::ProcessViewportMetricsChanged( |
pair.second->service()->ProcessViewportMetricsChanged( |
host, old_metrics, new_metrics, IsOperationSource(pair.first)); |
} |
+ |
+ if (!got_valid_frame_decorations_) |
+ return; |
+} |
+ |
+void ConnectionManager::ProcessFrameDecorationValuesChanged( |
+ WindowTreeHostImpl* host) { |
+ if (!got_valid_frame_decorations_) { |
+ got_valid_frame_decorations_ = true; |
+ display_manager_observers_.ForAllPtrs([this]( |
+ mojom::DisplayManagerObserver* observer) { CallOnDisplays(observer); }); |
+ return; |
+ } |
+ |
+ display_manager_observers_.ForAllPtrs( |
+ [this, &host](mojom::DisplayManagerObserver* observer) { |
+ CallOnDisplayChanged(observer, host); |
+ }); |
} |
bool ConnectionManager::GetAndClearInFlightWindowManagerChange( |
@@ -432,6 +451,64 @@ void ConnectionManager::MaybeUpdateNativeCursor(ServerWindow* window) { |
impl->MaybeChangeCursorOnWindowTreeChange(); |
} |
+void ConnectionManager::CallOnDisplays( |
+ mojom::DisplayManagerObserver* observer) { |
+ mojo::Array<mojom::DisplayPtr> displays(host_connection_map_.size()); |
+ { |
+ size_t i = 0; |
+ for (auto& pair : host_connection_map_) { |
+ displays[i] = DisplayForHost(pair.first); |
+ ++i; |
+ } |
+ } |
+ observer->OnDisplays(std::move(displays)); |
+} |
+ |
+void ConnectionManager::CallOnDisplayChanged( |
+ mojom::DisplayManagerObserver* observer, |
+ WindowTreeHostImpl* host) { |
+ mojo::Array<mojom::DisplayPtr> displays(1); |
+ displays[0] = DisplayForHost(host); |
+ display_manager_observers_.ForAllPtrs( |
+ [&displays](mojom::DisplayManagerObserver* observer) { |
+ observer->OnDisplaysChanged(displays.Clone()); |
+ }); |
+} |
+ |
+mojom::DisplayPtr ConnectionManager::DisplayForHost(WindowTreeHostImpl* host) { |
+ size_t i = 0; |
+ int next_x = 0; |
+ for (auto& pair : host_connection_map_) { |
+ const ServerWindow* root = host->root_window(); |
+ if (pair.first == host) { |
+ mojom::DisplayPtr display = mojom::Display::New(); |
+ display = mojom::Display::New(); |
+ display->id = host->id(); |
+ display->bounds = mojo::Rect::New(); |
+ display->bounds->x = next_x; |
+ display->bounds->y = 0; |
+ display->bounds->width = root->bounds().size().width(); |
+ display->bounds->height = root->bounds().size().height(); |
+ // TODO(sky): window manager needs an API to set the work area. |
+ display->work_area = display->bounds.Clone(); |
+ display->device_pixel_ratio = |
+ host->GetViewportMetrics().device_pixel_ratio; |
+ display->rotation = host->GetRotation(); |
+ // TODO(sky): make this real. |
+ display->is_primary = i == 0; |
+ // TODO(sky): make this real. |
+ display->touch_support = mojom::TouchSupport::UNKNOWN; |
+ display->frame_decoration_values = |
+ host->frame_decoration_values().Clone(); |
+ return display; |
+ } |
+ next_x += root->bounds().size().width(); |
+ ++i; |
+ } |
+ NOTREACHED(); |
+ return mojom::Display::New(); |
+} |
+ |
mus::SurfacesState* ConnectionManager::GetSurfacesState() { |
return surfaces_state_.get(); |
} |
@@ -588,34 +665,14 @@ void ConnectionManager::OnTransientWindowRemoved( |
} |
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; |
- } |
+ // Many clients key off the frame decorations to size widgets. Wait for frame |
+ // decorations before notifying so that we don't have to worry about clients |
+ // resizing appropriately. |
+ if (!got_valid_frame_decorations_) { |
+ display_manager_observers_.AddInterfacePtr(std::move(observer)); |
+ return; |
} |
- observer->OnDisplays(std::move(displays)); |
+ CallOnDisplays(observer.get()); |
display_manager_observers_.AddInterfacePtr(std::move(observer)); |
} |