2
* Copyright © 2016 Canonical Ltd.
4
* This program is free software: you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License version 3,
6
* as published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Authored by: Alan Griffiths <alan@octopull.co.uk>
19
#include "persist_display_config.h"
21
#include <mir/graphics/display_configuration_policy.h>
22
#include <mir/server.h>
23
#include <mir/version.h>
25
#if MIR_SERVER_VERSION >= MIR_VERSION_NUMBER(0, 26, 0)
26
#include <mir/graphics/display_configuration_observer.h>
27
#include <mir/observer_registrar.h>
30
namespace mg = mir::graphics;
34
struct PersistDisplayConfigPolicy
36
PersistDisplayConfigPolicy() = default;
37
virtual ~PersistDisplayConfigPolicy() = default;
38
PersistDisplayConfigPolicy(PersistDisplayConfigPolicy const&) = delete;
39
auto operator=(PersistDisplayConfigPolicy const&) -> PersistDisplayConfigPolicy& = delete;
41
void apply_to(mg::DisplayConfiguration& conf, mg::DisplayConfigurationPolicy& default_policy);
42
void save_config(mg::DisplayConfiguration const& base_conf);
45
struct DisplayConfigurationPolicyAdapter : mg::DisplayConfigurationPolicy
47
DisplayConfigurationPolicyAdapter(
48
std::shared_ptr<PersistDisplayConfigPolicy> const& self,
49
std::shared_ptr<mg::DisplayConfigurationPolicy> const& wrapped) :
50
self{self}, default_policy{wrapped}
53
void apply_to(mg::DisplayConfiguration& conf) override
55
self->apply_to(conf, *default_policy);
58
std::shared_ptr<PersistDisplayConfigPolicy> const self;
59
std::shared_ptr<mg::DisplayConfigurationPolicy> const default_policy;
62
#if MIR_SERVER_VERSION >= MIR_VERSION_NUMBER(0, 26, 0)
63
struct DisplayConfigurationObserver : mg::DisplayConfigurationObserver
65
void initial_configuration(std::shared_ptr<mg::DisplayConfiguration const> const& /*config*/) override {}
67
void configuration_applied(std::shared_ptr<mg::DisplayConfiguration const> const& /*config*/) override {}
69
void configuration_failed(
70
std::shared_ptr<mg::DisplayConfiguration const> const& /*attempted*/,
71
std::exception const& /*error*/) override {}
73
void catastrophic_configuration_error(
74
std::shared_ptr<mg::DisplayConfiguration const> const& /*failed_fallback*/,
75
std::exception const& /*error*/) override {}
78
struct DisplayConfigurationObserver { };
82
struct miral::PersistDisplayConfig::Self : PersistDisplayConfigPolicy, DisplayConfigurationObserver
85
Self(DisplayConfigurationPolicyWrapper const& custom_wrapper) :
86
custom_wrapper{custom_wrapper} {}
88
DisplayConfigurationPolicyWrapper const custom_wrapper =
89
[](const std::shared_ptr<mg::DisplayConfigurationPolicy> &wrapped) { return wrapped; };
91
#if MIR_SERVER_VERSION >= MIR_VERSION_NUMBER(0, 26, 0)
92
void base_configuration_updated(std::shared_ptr<mg::DisplayConfiguration const> const& base_config) override
94
save_config(*base_config);
97
void session_configuration_applied(std::shared_ptr<mir::frontend::Session> const&,
98
std::shared_ptr<mg::DisplayConfiguration> const&){}
99
void session_configuration_removed(std::shared_ptr<mir::frontend::Session> const&) {}
103
miral::PersistDisplayConfig::PersistDisplayConfig() :
104
self{std::make_shared<Self>()}
108
miral::PersistDisplayConfig::PersistDisplayConfig(DisplayConfigurationPolicyWrapper const& custom_wrapper) :
109
self{std::make_shared<Self>(custom_wrapper)}
113
miral::PersistDisplayConfig::~PersistDisplayConfig() = default;
115
miral::PersistDisplayConfig::PersistDisplayConfig(PersistDisplayConfig const&) = default;
117
auto miral::PersistDisplayConfig::operator=(PersistDisplayConfig const&) -> PersistDisplayConfig& = default;
119
void miral::PersistDisplayConfig::operator()(mir::Server& server)
121
server.wrap_display_configuration_policy(
122
[this](std::shared_ptr<mg::DisplayConfigurationPolicy> const& wrapped)
123
-> std::shared_ptr<mg::DisplayConfigurationPolicy>
125
return std::make_shared<DisplayConfigurationPolicyAdapter>(self, self->custom_wrapper(wrapped));
128
#if MIR_SERVER_VERSION >= MIR_VERSION_NUMBER(0, 26, 0)
129
server.add_init_callback([this, &server]
130
{ server.the_display_configuration_observer_registrar()->register_interest(self); });
132
// Up to Mir-0.25 detecting changes to the base display config is only possible client-side
133
// (and gives a different configuration API)
134
// If we decide implementing this is necessary for earlier Mir versions then this is where to plumb it in.
135
(void)&PersistDisplayConfigPolicy::save_config; // Fake "using" the function for now
139
void PersistDisplayConfigPolicy::apply_to(
140
mg::DisplayConfiguration& conf,
141
mg::DisplayConfigurationPolicy& default_policy)
143
// TODO if the h/w profile (by some definition) has changed, then apply corresponding saved config (if any).
145
default_policy.apply_to(conf);
148
void PersistDisplayConfigPolicy::save_config(mg::DisplayConfiguration const& /*base_conf*/)
150
// TODO save display config options against the h/w profile