| // Copyright 2018 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/ozone/platform/wayland/host/wayland_output_manager.h" |
| |
| #include <algorithm> |
| #include <cstdint> |
| #include <memory> |
| |
| #include "ui/ozone/platform/wayland/host/wayland_connection.h" |
| #include "ui/ozone/platform/wayland/host/wayland_output.h" |
| |
| namespace ui { |
| |
| WaylandOutputManager::WaylandOutputManager() = default; |
| |
| WaylandOutputManager::~WaylandOutputManager() = default; |
| |
| // Output is considered ready when at least one wl_output is fully configured |
| // (i.e: wl_output::done received), so that WaylandOutputManager is able to |
| // instantiate a valid WaylandScreen when requested by the upper layer. |
| bool WaylandOutputManager::IsOutputReady() const { |
| return std::find_if(output_list_.begin(), output_list_.end(), |
| [](const auto& output) { return output->is_ready(); }) != |
| output_list_.end(); |
| } |
| |
| void WaylandOutputManager::AddWaylandOutput(uint32_t output_id, |
| wl_output* output) { |
| // Make sure an output with |output_id| has not been added yet. It's very |
| // unlikely to happen, unless a compositor has a bug in the numeric names |
| // representation of global objects. |
| auto output_it = GetOutputItById(output_id); |
| DCHECK(output_it == output_list_.end()); |
| auto wayland_output = std::make_unique<WaylandOutput>(output_id, output); |
| |
| // Even if WaylandScreen has not been created, the output still must be |
| // initialized, which results in setting up a wl_listener and getting the |
| // geometry and the scaling factor from the Wayland Compositor. |
| wayland_output->Initialize(this); |
| DCHECK(!wayland_output->is_ready()); |
| |
| output_list_.push_back(std::move(wayland_output)); |
| } |
| |
| void WaylandOutputManager::RemoveWaylandOutput(uint32_t output_id) { |
| auto output_it = GetOutputItById(output_id); |
| |
| // Check the comment in the WaylandConnetion::GlobalRemove. |
| if (output_it == output_list_.end()) |
| return; |
| |
| if (wayland_screen_) |
| wayland_screen_->OnOutputRemoved(output_id); |
| output_list_.erase(output_it); |
| } |
| |
| std::unique_ptr<WaylandScreen> WaylandOutputManager::CreateWaylandScreen( |
| WaylandConnection* connection) { |
| auto wayland_screen = std::make_unique<WaylandScreen>(connection); |
| wayland_screen_ = wayland_screen->GetWeakPtr(); |
| |
| // As long as |wl_output| sends geometry and other events asynchronously (that |
| // is, the initial configuration is sent once the interface is bound), we'll |
| // have to tell each output to manually inform the delegate about available |
| // geometry, scale factor and etc, which will result in feeding the |
| // WaylandScreen with the data through OnOutputHandleGeometry and |
| // OutOutputHandleScale. All the other hot geometry and scale changes are done |
| // automatically, and the |wayland_screen_| is notified immediately about the |
| // changes. |
| for (const auto& output : output_list_) { |
| if (output->is_ready()) { |
| wayland_screen->OnOutputAddedOrUpdated( |
| output->output_id(), output->bounds(), output->scale_factor()); |
| } |
| } |
| |
| return wayland_screen; |
| } |
| |
| uint32_t WaylandOutputManager::GetIdForOutput(wl_output* output) const { |
| auto output_it = std::find_if( |
| output_list_.begin(), output_list_.end(), |
| [output](const auto& item) { return item->has_output(output); }); |
| // This is unlikely to happen, but better to be explicit here. |
| DCHECK(output_it != output_list_.end()); |
| return output_it->get()->output_id(); |
| } |
| |
| WaylandOutput* WaylandOutputManager::GetOutput(uint32_t id) const { |
| auto output_it = GetOutputItById(id); |
| // This is unlikely to happen, but better to be explicit here. |
| DCHECK(output_it != output_list_.end()); |
| return output_it->get(); |
| } |
| |
| void WaylandOutputManager::OnOutputHandleMetrics(uint32_t output_id, |
| const gfx::Rect& new_bounds, |
| int32_t scale_factor) { |
| if (wayland_screen_) { |
| wayland_screen_->OnOutputAddedOrUpdated(output_id, new_bounds, |
| scale_factor); |
| } |
| } |
| |
| WaylandOutputManager::OutputList::const_iterator |
| WaylandOutputManager::GetOutputItById(uint32_t id) const { |
| return std::find_if( |
| output_list_.begin(), output_list_.end(), |
| [id](const auto& item) { return item->output_id() == id; }); |
| } |
| |
| } // namespace ui |