Skip to content

Commit

Permalink
Live scale changes (#3583)
Browse files Browse the repository at this point in the history
Surfaces need to track scale changes on outputs they appear on

Fixes: #3552

(Reviewers note: this depends on #3586)
  • Loading branch information
hbatagelo authored and AlanGriffiths committed Sep 9, 2024
1 parent 910d3b8 commit 4e10bef
Show file tree
Hide file tree
Showing 14 changed files with 74 additions and 15 deletions.
1 change: 1 addition & 0 deletions src/include/server/mir/scene/null_surface_observer.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class NullSurfaceObserver : public SurfaceObserver
void application_id_set_to(Surface const* surf, std::string const& application_id) override;
void entered_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) override;
void left_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) override;
void rescale_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) override;

protected:
NullSurfaceObserver(NullSurfaceObserver const&) = delete;
Expand Down
1 change: 1 addition & 0 deletions src/include/server/mir/scene/surface_observer.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class SurfaceObserver
virtual void depth_layer_set_to(Surface const* surf, MirDepthLayer depth_layer) = 0;
virtual void entered_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) = 0;
virtual void left_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) = 0;
virtual void rescale_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) = 0;

protected:
SurfaceObserver() = default;
Expand Down
7 changes: 7 additions & 0 deletions src/miroil/surface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class miroil::SurfaceObserverImpl : public mir::scene::SurfaceObserver
mir::geometry::Size const &window_size) override;
void entered_output(mir::scene::Surface const* surf, mir::graphics::DisplayConfigurationOutputId const& id) override;
void left_output(mir::scene::Surface const* surf, mir::graphics::DisplayConfigurationOutputId const& id) override;
void rescale_output(mir::scene::Surface const* surf, mir::graphics::DisplayConfigurationOutputId const& id) override;

private:
std::shared_ptr<miroil::SurfaceObserver> listener;
Expand Down Expand Up @@ -171,6 +172,12 @@ void miroil::SurfaceObserverImpl::left_output(
{
}

void miroil::SurfaceObserverImpl::rescale_output(
mir::scene::Surface const* /*surf*/,
mir::graphics::DisplayConfigurationOutputId const& /*id*/)
{
}

miroil::Surface::Surface(std::shared_ptr<mir::scene::Surface> wrapped) :
wrapped(wrapped)
{
Expand Down
6 changes: 6 additions & 0 deletions src/server/frontend_wayland/fractional_scale_v1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ void mf::FractionalScaleV1::output_left(mir::graphics::DisplayConfigurationOutpu
recompute_scale();
}

void mf::FractionalScaleV1::scale_change_on_output(mir::graphics::DisplayConfigurationOutput const& config)
{
surface_outputs[config.id] = config.scale;
recompute_scale();
}

void mf::FractionalScaleV1::recompute_scale()
{
auto max_element = std::max_element(
Expand Down
1 change: 1 addition & 0 deletions src/server/frontend_wayland/fractional_scale_v1.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class FractionalScaleV1 : public wayland::FractionalScaleV1

void output_entered(mir::graphics::DisplayConfigurationOutput const& config);
void output_left(mir::graphics::DisplayConfigurationOutput const& config);
void scale_change_on_output(mir::graphics::DisplayConfigurationOutput const& config);

private:
// Houses a set of outputs the surface occupies
Expand Down
9 changes: 9 additions & 0 deletions src/server/frontend_wayland/wayland_surface_observer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,15 @@ void mf::WaylandSurfaceObserver::left_output(ms::Surface const*, graphics::Displ
});
}

void mf::WaylandSurfaceObserver::rescale_output(ms::Surface const*, graphics::DisplayConfigurationOutputId const& id)
{
run_on_wayland_thread_unless_window_destroyed(
[id](Impl* impl, WindowWlSurfaceRole*)
{
impl->window.value().handle_scale_output(id);
});
}

void mf::WaylandSurfaceObserver::run_on_wayland_thread_unless_window_destroyed(
std::function<void(Impl* impl, WindowWlSurfaceRole* window)>&& work)
{
Expand Down
1 change: 1 addition & 0 deletions src/server/frontend_wayland/wayland_surface_observer.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class WaylandSurfaceObserver : public scene::NullSurfaceObserver
void input_consumed(scene::Surface const*, std::shared_ptr<MirEvent const> const& event) override;
void entered_output(scene::Surface const*, graphics::DisplayConfigurationOutputId const& id) override;
void left_output(scene::Surface const*, graphics::DisplayConfigurationOutputId const& id) override;
void rescale_output(scene::Surface const*, graphics::DisplayConfigurationOutputId const& id) override;
///@}

/// Should only be called from the Wayland thread
Expand Down
21 changes: 19 additions & 2 deletions src/server/frontend_wayland/window_wl_surface_role.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,11 +461,20 @@ auto mf::WindowWlSurfaceRole::output_config_changed(graphics::DisplayConfigurati
client,
[&](OutputInstance* instance)
{
if (auto const fractional_scale = surface.value().get_fractional_scale())
fractional_scale.value().output_entered(config);
surface.value().send_enter_event(instance->resource);
pending_enter_events.erase(id_it);
});
}
}

if (auto id_it{std::ranges::find(pending_rescale_events, config.id)}; id_it != pending_rescale_events.end())
{
if (auto const fractional_scale = surface.value().get_fractional_scale())
fractional_scale.value().scale_change_on_output(config);
pending_rescale_events.erase(id_it);
}
}

return true;
Expand Down Expand Up @@ -524,7 +533,7 @@ void mf::WindowWlSurfaceRole::handle_enter_output(graphics::DisplayConfiguration
auto const& config{global->current_config()};
if (config.id == id)
{
if (auto fractional_scale = surface.value().get_fractional_scale())
if (auto const fractional_scale = surface.value().get_fractional_scale())
fractional_scale.value().output_entered(config);

global->for_each_output_bound_by(
Expand Down Expand Up @@ -552,7 +561,7 @@ void mf::WindowWlSurfaceRole::handle_leave_output(graphics::DisplayConfiguration
auto const& config{global->current_config()};
if (config.id == id)
{
if(auto fractional_scale = surface.value().get_fractional_scale())
if(auto const fractional_scale = surface.value().get_fractional_scale())
fractional_scale.value().output_left(config);

global->for_each_output_bound_by(
Expand All @@ -566,6 +575,14 @@ void mf::WindowWlSurfaceRole::handle_leave_output(graphics::DisplayConfiguration
}
}

void mf::WindowWlSurfaceRole::handle_scale_output(graphics::DisplayConfigurationOutputId id)
{
if (surface)
{
pending_rescale_events.push_back(id);
}
}

void mf::WindowWlSurfaceRole::apply_client_size(mir::shell::SurfaceSpecification& mods)
{
if ((!committed_width_set_explicitly || !committed_height_set_explicitly) && surface)
Expand Down
2 changes: 2 additions & 0 deletions src/server/frontend_wayland/window_wl_surface_role.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ class WindowWlSurfaceRole

void handle_enter_output(graphics::DisplayConfigurationOutputId id);
void handle_leave_output(graphics::DisplayConfigurationOutputId id) const;
void handle_scale_output(graphics::DisplayConfigurationOutputId id);

/// Gets called after the surface has committed (so current_size() may return the committed buffer size) but before
/// the Mir window is modified (so if a pending size is set or a spec is applied those changes will take effect)
Expand Down Expand Up @@ -174,6 +175,7 @@ class WindowWlSurfaceRole
void apply_client_size(mir::shell::SurfaceSpecification& mods);

std::vector<graphics::DisplayConfigurationOutputId> pending_enter_events;
std::vector<graphics::DisplayConfigurationOutputId> pending_rescale_events;
};

}
Expand Down
29 changes: 20 additions & 9 deletions src/server/scene/basic_surface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ class ms::BasicSurface::Multiplexer : public ObserverMultiplexer<SurfaceObserver
{
for_each_observer(&SurfaceObserver::left_output, surf, id);
}

void rescale_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) override
{
for_each_observer(&SurfaceObserver::rescale_output, surf, id);
}
};

namespace
Expand Down Expand Up @@ -989,28 +994,34 @@ auto mir::scene::BasicSurface::content_top_left(State const& state) const -> geo
void mir::scene::BasicSurface::track_outputs()
{
auto const state{synchronised_state.lock()};
std::set<mg::DisplayConfigurationOutputId> tracked;
decltype(tracked_output_scales) tracked;

display_config->for_each_output(
[&](mg::DisplayConfigurationOutput const& output)
{
if (output.valid() && output.used && output.extents().overlaps(state->surface_rect))
{
if (!tracked_outputs.contains(output.id))
if (!tracked_output_scales.contains(output.id))
{
observers->entered_output(this, output.id);
}
tracked.insert(output.id);
tracked.emplace(output.id, output.scale);
}
});

// TODO: Once std::views::filter is properly supported across compilers, replace the
// creation of `untracked` with iteration over a filtered view of `tracked_outputs`
std::vector<mg::DisplayConfigurationOutputId> untracked;
std::ranges::set_difference(tracked_outputs, tracked, std::back_inserter(untracked));
std::ranges::for_each(untracked, [&](auto const& id) { observers->left_output(this, id); });
for (auto const& [id, scale] : tracked_output_scales)
{
if (auto new_entry = tracked.find(id); new_entry == tracked.end())
{
observers->left_output(this, id);
}
else if (new_entry->second != scale)
{
observers->rescale_output(this, id);
}
}

tracked_outputs = std::move(tracked);
tracked_output_scales = std::move(tracked);
}

void mir::scene::BasicSurface::linearised_track_outputs()
Expand Down
2 changes: 1 addition & 1 deletion src/server/scene/basic_surface.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ class BasicSurface : public Surface
std::shared_ptr<ObserverRegistrar<graphics::DisplayConfigurationObserver>> display_config_registrar;
std::shared_ptr<DisplayConfigurationEarlyListener> const display_config_monitor;
std::shared_ptr<graphics::DisplayConfiguration const> display_config;
std::set<graphics::DisplayConfigurationOutputId> tracked_outputs;
std::unordered_map<graphics::DisplayConfigurationOutputId, float> tracked_output_scales;
};

}
Expand Down
5 changes: 3 additions & 2 deletions src/server/scene/null_surface_observer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,6 @@ void ms::NullSurfaceObserver::placed_relative(Surface const*, geometry::Rectangl
void ms::NullSurfaceObserver::input_consumed(Surface const*, std::shared_ptr<MirEvent const> const&) {}
void ms::NullSurfaceObserver::depth_layer_set_to(Surface const*, MirDepthLayer) {}
void ms::NullSurfaceObserver::application_id_set_to(Surface const*, std::string const&) {}
void ms::NullSurfaceObserver::entered_output(Surface const*, graphics::DisplayConfigurationOutputId const&) {};
void ms::NullSurfaceObserver::left_output(Surface const*, graphics::DisplayConfigurationOutputId const&) {};
void ms::NullSurfaceObserver::entered_output(Surface const*, graphics::DisplayConfigurationOutputId const&) {}
void ms::NullSurfaceObserver::left_output(Surface const*, graphics::DisplayConfigurationOutputId const&) {}
void ms::NullSurfaceObserver::rescale_output(Surface const*, graphics::DisplayConfigurationOutputId const&){}
2 changes: 2 additions & 0 deletions src/server/symbols.map
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,7 @@ global:
mir::scene::NullSurfaceObserver::placed_relative*;
mir::scene::NullSurfaceObserver::reception_mode_set_to*;
mir::scene::NullSurfaceObserver::renamed*;
mir::scene::NullSurfaceObserver::rescale_output*;
mir::scene::NullSurfaceObserver::transformation_set_to*;
mir::scene::NullSurfaceObserver::window_resized_to*;
mir::scene::Observer::?Observer*;
Expand Down Expand Up @@ -947,6 +948,7 @@ global:
non-virtual?thunk?to?mir::scene::NullSurfaceObserver::placed_relative*;
non-virtual?thunk?to?mir::scene::NullSurfaceObserver::reception_mode_set_to*;
non-virtual?thunk?to?mir::scene::NullSurfaceObserver::renamed*;
non-virtual?thunk?to?mir::scene::NullSurfaceObserver::rescale_output*;
non-virtual?thunk?to?mir::scene::NullSurfaceObserver::transformation_set_to*;
non-virtual?thunk?to?mir::scene::NullSurfaceObserver::window_resized_to*;
non-virtual?thunk?to?mir::scene::Observer::?Observer*;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ struct mir_test_framework::WindowManagementTestHarness::Self : public ms::Surfac
void depth_layer_set_to(ms::Surface const*, MirDepthLayer) override {}
void entered_output(ms::Surface const*, mg::DisplayConfigurationOutputId const&) override {}
void left_output(ms::Surface const*, mg::DisplayConfigurationOutputId const&) override {}

void rescale_output(ms::Surface const*, mg::DisplayConfigurationOutputId const&) override {}
std::mutex mutable mutex;
std::vector<std::shared_ptr<mc::BufferStream>> streams;
std::vector<std::shared_ptr<ms::Surface>> known_surfaces;
Expand Down

0 comments on commit 4e10bef

Please sign in to comment.