Skip to content

Commit ecc4899

Browse files
authored
Live scale changes (#3583)
Surfaces need to track scale changes on outputs they appear on Fixes: #3552 (Reviewers note: this depends on #3586)
2 parents 99e8ffa + b668b1d commit ecc4899

14 files changed

+74
-15
lines changed

src/include/server/mir/scene/null_surface_observer.h

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class NullSurfaceObserver : public SurfaceObserver
4949
void application_id_set_to(Surface const* surf, std::string const& application_id) override;
5050
void entered_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) override;
5151
void left_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) override;
52+
void rescale_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) override;
5253

5354
protected:
5455
NullSurfaceObserver(NullSurfaceObserver const&) = delete;

src/include/server/mir/scene/surface_observer.h

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class SurfaceObserver
6464
virtual void depth_layer_set_to(Surface const* surf, MirDepthLayer depth_layer) = 0;
6565
virtual void entered_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) = 0;
6666
virtual void left_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) = 0;
67+
virtual void rescale_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) = 0;
6768

6869
protected:
6970
SurfaceObserver() = default;

src/miroil/surface.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class miroil::SurfaceObserverImpl : public mir::scene::SurfaceObserver
5959
mir::geometry::Size const &window_size) override;
6060
void entered_output(mir::scene::Surface const* surf, mir::graphics::DisplayConfigurationOutputId const& id) override;
6161
void left_output(mir::scene::Surface const* surf, mir::graphics::DisplayConfigurationOutputId const& id) override;
62+
void rescale_output(mir::scene::Surface const* surf, mir::graphics::DisplayConfigurationOutputId const& id) override;
6263

6364
private:
6465
std::shared_ptr<miroil::SurfaceObserver> listener;
@@ -171,6 +172,12 @@ void miroil::SurfaceObserverImpl::left_output(
171172
{
172173
}
173174

175+
void miroil::SurfaceObserverImpl::rescale_output(
176+
mir::scene::Surface const* /*surf*/,
177+
mir::graphics::DisplayConfigurationOutputId const& /*id*/)
178+
{
179+
}
180+
174181
miroil::Surface::Surface(std::shared_ptr<mir::scene::Surface> wrapped) :
175182
wrapped(wrapped)
176183
{

src/server/frontend_wayland/fractional_scale_v1.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ void mf::FractionalScaleV1::output_left(mir::graphics::DisplayConfigurationOutpu
102102
recompute_scale();
103103
}
104104

105+
void mf::FractionalScaleV1::scale_change_on_output(mir::graphics::DisplayConfigurationOutput const& config)
106+
{
107+
surface_outputs[config.id] = config.scale;
108+
recompute_scale();
109+
}
110+
105111
void mf::FractionalScaleV1::recompute_scale()
106112
{
107113
auto max_element = std::max_element(

src/server/frontend_wayland/fractional_scale_v1.h

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class FractionalScaleV1 : public wayland::FractionalScaleV1
3838

3939
void output_entered(mir::graphics::DisplayConfigurationOutput const& config);
4040
void output_left(mir::graphics::DisplayConfigurationOutput const& config);
41+
void scale_change_on_output(mir::graphics::DisplayConfigurationOutput const& config);
4142

4243
private:
4344
// Houses a set of outputs the surface occupies

src/server/frontend_wayland/wayland_surface_observer.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,15 @@ void mf::WaylandSurfaceObserver::left_output(ms::Surface const*, graphics::Displ
134134
});
135135
}
136136

137+
void mf::WaylandSurfaceObserver::rescale_output(ms::Surface const*, graphics::DisplayConfigurationOutputId const& id)
138+
{
139+
run_on_wayland_thread_unless_window_destroyed(
140+
[id](Impl* impl, WindowWlSurfaceRole*)
141+
{
142+
impl->window.value().handle_scale_output(id);
143+
});
144+
}
145+
137146
void mf::WaylandSurfaceObserver::run_on_wayland_thread_unless_window_destroyed(
138147
std::function<void(Impl* impl, WindowWlSurfaceRole* window)>&& work)
139148
{

src/server/frontend_wayland/wayland_surface_observer.h

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class WaylandSurfaceObserver : public scene::NullSurfaceObserver
5757
void input_consumed(scene::Surface const*, std::shared_ptr<MirEvent const> const& event) override;
5858
void entered_output(scene::Surface const*, graphics::DisplayConfigurationOutputId const& id) override;
5959
void left_output(scene::Surface const*, graphics::DisplayConfigurationOutputId const& id) override;
60+
void rescale_output(scene::Surface const*, graphics::DisplayConfigurationOutputId const& id) override;
6061
///@}
6162

6263
/// Should only be called from the Wayland thread

src/server/frontend_wayland/window_wl_surface_role.cpp

+19-2
Original file line numberDiff line numberDiff line change
@@ -461,11 +461,20 @@ auto mf::WindowWlSurfaceRole::output_config_changed(graphics::DisplayConfigurati
461461
client,
462462
[&](OutputInstance* instance)
463463
{
464+
if (auto const fractional_scale = surface.value().get_fractional_scale())
465+
fractional_scale.value().output_entered(config);
464466
surface.value().send_enter_event(instance->resource);
465467
pending_enter_events.erase(id_it);
466468
});
467469
}
468470
}
471+
472+
if (auto id_it{std::ranges::find(pending_rescale_events, config.id)}; id_it != pending_rescale_events.end())
473+
{
474+
if (auto const fractional_scale = surface.value().get_fractional_scale())
475+
fractional_scale.value().scale_change_on_output(config);
476+
pending_rescale_events.erase(id_it);
477+
}
469478
}
470479

471480
return true;
@@ -524,7 +533,7 @@ void mf::WindowWlSurfaceRole::handle_enter_output(graphics::DisplayConfiguration
524533
auto const& config{global->current_config()};
525534
if (config.id == id)
526535
{
527-
if (auto fractional_scale = surface.value().get_fractional_scale())
536+
if (auto const fractional_scale = surface.value().get_fractional_scale())
528537
fractional_scale.value().output_entered(config);
529538

530539
global->for_each_output_bound_by(
@@ -552,7 +561,7 @@ void mf::WindowWlSurfaceRole::handle_leave_output(graphics::DisplayConfiguration
552561
auto const& config{global->current_config()};
553562
if (config.id == id)
554563
{
555-
if(auto fractional_scale = surface.value().get_fractional_scale())
564+
if(auto const fractional_scale = surface.value().get_fractional_scale())
556565
fractional_scale.value().output_left(config);
557566

558567
global->for_each_output_bound_by(
@@ -566,6 +575,14 @@ void mf::WindowWlSurfaceRole::handle_leave_output(graphics::DisplayConfiguration
566575
}
567576
}
568577

578+
void mf::WindowWlSurfaceRole::handle_scale_output(graphics::DisplayConfigurationOutputId id)
579+
{
580+
if (surface)
581+
{
582+
pending_rescale_events.push_back(id);
583+
}
584+
}
585+
569586
void mf::WindowWlSurfaceRole::apply_client_size(mir::shell::SurfaceSpecification& mods)
570587
{
571588
if ((!committed_width_set_explicitly || !committed_height_set_explicitly) && surface)

src/server/frontend_wayland/window_wl_surface_role.h

+2
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ class WindowWlSurfaceRole
102102

103103
void handle_enter_output(graphics::DisplayConfigurationOutputId id);
104104
void handle_leave_output(graphics::DisplayConfigurationOutputId id) const;
105+
void handle_scale_output(graphics::DisplayConfigurationOutputId id);
105106

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

176177
std::vector<graphics::DisplayConfigurationOutputId> pending_enter_events;
178+
std::vector<graphics::DisplayConfigurationOutputId> pending_rescale_events;
177179
};
178180

179181
}

src/server/scene/basic_surface.cpp

+20-9
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,11 @@ class ms::BasicSurface::Multiplexer : public ObserverMultiplexer<SurfaceObserver
169169
{
170170
for_each_observer(&SurfaceObserver::left_output, surf, id);
171171
}
172+
173+
void rescale_output(Surface const* surf, graphics::DisplayConfigurationOutputId const& id) override
174+
{
175+
for_each_observer(&SurfaceObserver::rescale_output, surf, id);
176+
}
172177
};
173178

174179
namespace
@@ -989,28 +994,34 @@ auto mir::scene::BasicSurface::content_top_left(State const& state) const -> geo
989994
void mir::scene::BasicSurface::track_outputs()
990995
{
991996
auto const state{synchronised_state.lock()};
992-
std::set<mg::DisplayConfigurationOutputId> tracked;
997+
decltype(tracked_output_scales) tracked;
993998

994999
display_config->for_each_output(
9951000
[&](mg::DisplayConfigurationOutput const& output)
9961001
{
9971002
if (output.valid() && output.used && output.extents().overlaps(state->surface_rect))
9981003
{
999-
if (!tracked_outputs.contains(output.id))
1004+
if (!tracked_output_scales.contains(output.id))
10001005
{
10011006
observers->entered_output(this, output.id);
10021007
}
1003-
tracked.insert(output.id);
1008+
tracked.emplace(output.id, output.scale);
10041009
}
10051010
});
10061011

1007-
// TODO: Once std::views::filter is properly supported across compilers, replace the
1008-
// creation of `untracked` with iteration over a filtered view of `tracked_outputs`
1009-
std::vector<mg::DisplayConfigurationOutputId> untracked;
1010-
std::ranges::set_difference(tracked_outputs, tracked, std::back_inserter(untracked));
1011-
std::ranges::for_each(untracked, [&](auto const& id) { observers->left_output(this, id); });
1012+
for (auto const& [id, scale] : tracked_output_scales)
1013+
{
1014+
if (auto new_entry = tracked.find(id); new_entry == tracked.end())
1015+
{
1016+
observers->left_output(this, id);
1017+
}
1018+
else if (new_entry->second != scale)
1019+
{
1020+
observers->rescale_output(this, id);
1021+
}
1022+
}
10121023

1013-
tracked_outputs = std::move(tracked);
1024+
tracked_output_scales = std::move(tracked);
10141025
}
10151026

10161027
void mir::scene::BasicSurface::linearised_track_outputs()

src/server/scene/basic_surface.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ class BasicSurface : public Surface
239239
std::shared_ptr<ObserverRegistrar<graphics::DisplayConfigurationObserver>> display_config_registrar;
240240
std::shared_ptr<DisplayConfigurationEarlyListener> const display_config_monitor;
241241
std::shared_ptr<graphics::DisplayConfiguration const> display_config;
242-
std::set<graphics::DisplayConfigurationOutputId> tracked_outputs;
242+
std::unordered_map<graphics::DisplayConfigurationOutputId, float> tracked_output_scales;
243243
};
244244

245245
}

src/server/scene/null_surface_observer.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,6 @@ void ms::NullSurfaceObserver::placed_relative(Surface const*, geometry::Rectangl
3737
void ms::NullSurfaceObserver::input_consumed(Surface const*, std::shared_ptr<MirEvent const> const&) {}
3838
void ms::NullSurfaceObserver::depth_layer_set_to(Surface const*, MirDepthLayer) {}
3939
void ms::NullSurfaceObserver::application_id_set_to(Surface const*, std::string const&) {}
40-
void ms::NullSurfaceObserver::entered_output(Surface const*, graphics::DisplayConfigurationOutputId const&) {};
41-
void ms::NullSurfaceObserver::left_output(Surface const*, graphics::DisplayConfigurationOutputId const&) {};
40+
void ms::NullSurfaceObserver::entered_output(Surface const*, graphics::DisplayConfigurationOutputId const&) {}
41+
void ms::NullSurfaceObserver::left_output(Surface const*, graphics::DisplayConfigurationOutputId const&) {}
42+
void ms::NullSurfaceObserver::rescale_output(Surface const*, graphics::DisplayConfigurationOutputId const&){}

src/server/symbols.map

+2
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,7 @@ global:
488488
mir::scene::NullSurfaceObserver::placed_relative*;
489489
mir::scene::NullSurfaceObserver::reception_mode_set_to*;
490490
mir::scene::NullSurfaceObserver::renamed*;
491+
mir::scene::NullSurfaceObserver::rescale_output*;
491492
mir::scene::NullSurfaceObserver::transformation_set_to*;
492493
mir::scene::NullSurfaceObserver::window_resized_to*;
493494
mir::scene::Observer::?Observer*;
@@ -947,6 +948,7 @@ global:
947948
non-virtual?thunk?to?mir::scene::NullSurfaceObserver::placed_relative*;
948949
non-virtual?thunk?to?mir::scene::NullSurfaceObserver::reception_mode_set_to*;
949950
non-virtual?thunk?to?mir::scene::NullSurfaceObserver::renamed*;
951+
non-virtual?thunk?to?mir::scene::NullSurfaceObserver::rescale_output*;
950952
non-virtual?thunk?to?mir::scene::NullSurfaceObserver::transformation_set_to*;
951953
non-virtual?thunk?to?mir::scene::NullSurfaceObserver::window_resized_to*;
952954
non-virtual?thunk?to?mir::scene::Observer::?Observer*;

tests/mir_test_framework/window_management_test_harness.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ struct mir_test_framework::WindowManagementTestHarness::Self : public ms::Surfac
8383
void depth_layer_set_to(ms::Surface const*, MirDepthLayer) override {}
8484
void entered_output(ms::Surface const*, mg::DisplayConfigurationOutputId const&) override {}
8585
void left_output(ms::Surface const*, mg::DisplayConfigurationOutputId const&) override {}
86-
86+
void rescale_output(ms::Surface const*, mg::DisplayConfigurationOutputId const&) override {}
8787
std::mutex mutable mutex;
8888
std::vector<std::shared_ptr<mc::BufferStream>> streams;
8989
std::vector<std::shared_ptr<ms::Surface>> known_surfaces;

0 commit comments

Comments
 (0)