Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --idle-timeout-when-locked for idle timeout when session is locked #3546

Merged
merged 5 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/platform/mir/options/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ extern char const* const wayland_extensions_opt;
extern char const* const add_wayland_extensions_opt;
extern char const* const drop_wayland_extensions_opt;
extern char const* const idle_timeout_opt;
extern char const* const idle_timeout_when_locked_opt;

extern char const* const enable_key_repeat_opt;

Expand Down
5 changes: 5 additions & 0 deletions src/include/server/mir/shell/idle_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ class IdleHandler : public ObserverRegistrar<IdleHandlerObserver>
/// is sent the display is never turned off or dimmed, which is the default.
virtual void set_display_off_timeout(std::optional<time::Duration> timeout) = 0;

/// Duration Mir will remain idle before the display is turned off when the session is locked. The display may dim
/// some time before this. If nullopt is sent, the display is never turned off or dimmed during session lock, which
/// is the default.
virtual void set_display_off_timeout_when_locked(std::optional<time::Duration> timeout) = 0;

private:
IdleHandler(IdleHandler const&) = delete;
IdleHandler& operator=(IdleHandler const&) = delete;
Expand Down
8 changes: 6 additions & 2 deletions src/platform/options/default_configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ char const* const mo::wayland_extensions_opt = "wayland-extensions";
char const* const mo::add_wayland_extensions_opt = "add-wayland-extensions";
char const* const mo::drop_wayland_extensions_opt = "drop-wayland-extensions";
char const* const mo::idle_timeout_opt = "idle-timeout";
char const* const mo::idle_timeout_when_locked_opt = "idle-timeout-when-locked";

char const* const mo::off_opt_value = "off";
char const* const mo::log_opt_value = "log";
Expand Down Expand Up @@ -177,8 +178,11 @@ mo::DefaultConfiguration::DefaultConfiguration(
(enable_key_repeat_opt, po::value<bool>()->default_value(true),
"Enable server generated key repeat")
(idle_timeout_opt, po::value<int>()->default_value(0),
"Time (in seconds) Mir will remain idle before turning off the display, "
"or 0 to keep display on forever.")
"Time (in seconds) Mir will remain idle before turning off the display "
"when the session is not locked, or 0 to keep display on forever.")
(idle_timeout_when_locked_opt, po::value<int>()->default_value(0),
"Time (in seconds) Mir will remain idle before turning off the display "
"when the session is locked, or 0 to keep the display on forever.")
(fatal_except_opt, "On \"fatal error\" conditions [e.g. drivers behaving "
"in unexpected ways] throw an exception (instead of a core dump)")
(debug_opt, "Enable extra development debugging. "
Expand Down
8 changes: 7 additions & 1 deletion src/platform/symbols.map
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,12 @@ MIR_PLATFORM_2.18 {
vtable?for?mir::options::Option;
vtable?for?mir::options::ProgramOption;
};
local: *;
};

MIR_PLATFORM_2.19 {
global:
extern "C++" {
mir::options::idle_timeout_when_locked_opt;
};
local: *;
} MIR_PLATFORM_2.18;
95 changes: 82 additions & 13 deletions src/server/shell/basic_idle_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "basic_idle_handler.h"
#include "mir/fatal.h"
#include "mir/scene/idle_hub.h"
#include "mir/scene/session_lock.h"
#include "mir/graphics/renderable.h"
#include "mir/renderer/sw/pixel_source.h"
#include "mir/input/scene.h"
Expand Down Expand Up @@ -170,51 +171,119 @@ struct PowerModeSetter : ms::IdleStateObserver
};
}

class msh::BasicIdleHandler::SessionLockListener : public ms::SessionLockObserver
{
public:
explicit SessionLockListener(msh::BasicIdleHandler* idle_handler) : idle_handler{idle_handler}
{
}

void on_lock() override
{
idle_handler->on_session_lock();
}

void on_unlock() override
{
idle_handler->on_session_unlock();
}

private:
msh::BasicIdleHandler* const idle_handler;
};

msh::BasicIdleHandler::BasicIdleHandler(
std::shared_ptr<ms::IdleHub> const& idle_hub,
std::shared_ptr<input::Scene> const& input_scene,
std::shared_ptr<graphics::GraphicBufferAllocator> const& allocator,
std::shared_ptr<msh::DisplayConfigurationController> const& display_config_controller)
std::shared_ptr<msh::DisplayConfigurationController> const& display_config_controller,
std::shared_ptr<ms::SessionLock> const& session_lock)
: idle_hub{idle_hub},
input_scene{input_scene},
allocator{allocator},
display_config_controller{display_config_controller}
display_config_controller{display_config_controller},
session_lock{session_lock},
session_lock_monitor{std::make_shared<SessionLockListener>(this)}
{
session_lock->register_interest(session_lock_monitor);
}

msh::BasicIdleHandler::~BasicIdleHandler()
{
session_lock->unregister_interest(*session_lock_monitor);
std::lock_guard lock{mutex};
clear_observers(lock);
}

void msh::BasicIdleHandler::set_display_off_timeout(std::optional<time::Duration> timeout)
{
std::lock_guard lock{mutex};
if (timeout == current_off_timeout)
if (timeout != current_off_timeout)
{
return;
current_off_timeout = timeout;
if (!session_locked)
{
clear_observers(lock);
register_observers(lock);
}
}
current_off_timeout = timeout;
clear_observers(lock);
if (timeout)
}

void msh::BasicIdleHandler::set_display_off_timeout_when_locked(std::optional<time::Duration> timeout)
{
std::lock_guard lock{mutex};
if (timeout != current_off_timeout_when_locked)
{
current_off_timeout_when_locked = timeout;
if (session_locked)
{
clear_observers(lock);
register_observers(lock);
}
}
}

void msh::BasicIdleHandler::on_session_lock()
{
std::lock_guard lock{mutex};
session_locked = true;
if (current_off_timeout_when_locked != current_off_timeout)
{
clear_observers(lock);
register_observers(lock);
}
}

void msh::BasicIdleHandler::on_session_unlock()
{
std::lock_guard lock{mutex};
session_locked = false;
if (current_off_timeout_when_locked != current_off_timeout)
{
clear_observers(lock);
register_observers(lock);
}
}

void msh::BasicIdleHandler::register_observers(ProofOfMutexLock const&)
{
if (auto const off_timeout{session_locked ? current_off_timeout_when_locked : current_off_timeout})
{
auto const off_timeout = timeout.value();
if (off_timeout <= time::Duration{})
if (*off_timeout <= time::Duration{0})
{
fatal_error("BasicIdleHandler given invalid timeout %d, should be >0", off_timeout.count());
fatal_error("BasicIdleHandler given invalid timeout %d, should be >0", off_timeout->count());
}
Comment on lines 273 to 275
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the wrong time to be validating input and erroring. (That should be on startup when the input is parsed)

if (off_timeout >= dim_time_before_off * 2)
if (*off_timeout >= dim_time_before_off * 2)
{
auto const dim_timeout = off_timeout - dim_time_before_off;
auto const dim_timeout = *off_timeout - dim_time_before_off;
auto const dimmer = std::make_shared<Dimmer>(input_scene, allocator, multiplexer);
observers.push_back(dimmer);
idle_hub->register_interest(dimmer, dim_timeout);
}
auto const power_setter = std::make_shared<PowerModeSetter>(
display_config_controller, mir_power_mode_off, multiplexer);
observers.push_back(power_setter);
idle_hub->register_interest(power_setter, off_timeout);
idle_hub->register_interest(power_setter, *off_timeout);
}
}

Expand Down
16 changes: 15 additions & 1 deletion src/server/shell/basic_idle_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ namespace scene
{
class IdleHub;
class IdleStateObserver;
class SessionLock;
}
namespace shell
{
Expand All @@ -51,12 +52,15 @@ class BasicIdleHandler : public IdleHandler
std::shared_ptr<scene::IdleHub> const& idle_hub,
std::shared_ptr<input::Scene> const& input_scene,
std::shared_ptr<graphics::GraphicBufferAllocator> const& allocator,
std::shared_ptr<shell::DisplayConfigurationController> const& display_config_controller);
std::shared_ptr<shell::DisplayConfigurationController> const& display_config_controller,
std::shared_ptr<scene::SessionLock> const& session_lock);

~BasicIdleHandler();

void set_display_off_timeout(std::optional<time::Duration> timeout) override;

void set_display_off_timeout_when_locked(std::optional<time::Duration> timeout) override;

void register_interest(std::weak_ptr<IdleHandlerObserver> const&) override;

void register_interest(
Expand All @@ -70,15 +74,25 @@ class BasicIdleHandler : public IdleHandler
void unregister_interest(IdleHandlerObserver const&) override;

private:
class SessionLockListener;

void on_session_lock();
void on_session_unlock();

void register_observers(ProofOfMutexLock const&);
void clear_observers(ProofOfMutexLock const&);

std::shared_ptr<scene::IdleHub> const idle_hub;
std::shared_ptr<input::Scene> const input_scene;
std::shared_ptr<graphics::GraphicBufferAllocator> const allocator;
std::shared_ptr<shell::DisplayConfigurationController> const display_config_controller;
std::shared_ptr<scene::SessionLock> const session_lock;
std::shared_ptr<SessionLockListener> const session_lock_monitor;

std::mutex mutex;
std::optional<time::Duration> current_off_timeout;
std::optional<time::Duration> current_off_timeout_when_locked;
bool session_locked{false};
std::vector<std::shared_ptr<scene::IdleStateObserver>> observers;

class BasicIdleHandlerObserverMultiplexer: public ObserverMultiplexer<IdleHandlerObserver>
Expand Down
22 changes: 21 additions & 1 deletion src/server/shell/default_configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ auto mir::DefaultServerConfiguration::the_idle_handler() -> std::shared_ptr<msh:
the_idle_hub(),
the_input_scene(),
the_buffer_allocator(),
the_display_configuration_controller());
the_display_configuration_controller(),
the_session_lock());

auto options = the_options();
int const idle_timeout_seconds = options->get<int>(options::idle_timeout_opt);
Expand All @@ -122,6 +123,25 @@ auto mir::DefaultServerConfiguration::the_idle_handler() -> std::shared_ptr<msh:
idle_handler->set_display_off_timeout(std::chrono::seconds{idle_timeout_seconds});
}

int const idle_timeout_when_locked = options->get<int>(options::idle_timeout_when_locked_opt);
if (idle_timeout_when_locked < 0)
{
throw mir::AbnormalExit(
"Invalid " +
std::string{options::idle_timeout_when_locked_opt} +
" value " +
std::to_string(idle_timeout_when_locked) +
", must be > 0");
}
if (idle_timeout_when_locked == 0)
{
idle_handler->set_display_off_timeout_when_locked(std::nullopt);
}
else
{
idle_handler->set_display_off_timeout_when_locked(std::chrono::seconds{idle_timeout_when_locked});
}

return idle_handler;
});
}
Expand Down
Loading
Loading