sculpt: screensaver infrastructure

This patch enhances Sculpt with the ability to detect user inactivity
for driving a screensaver by combining nitpicker's hover and focus
reports with a timer.

Issue #4950
This commit is contained in:
Norman Feske 2023-06-29 17:21:18 +02:00
parent 8463f4910a
commit 75bfc37b18
4 changed files with 159 additions and 1 deletions

View File

@ -273,6 +273,8 @@ install_config {
<policy label="runtime -> capslock" report="global_keys_handler -> capslock"/>
<policy label="drivers -> numlock" report="global_keys_handler -> numlock"/>
<policy label="runtime -> clicked" report="nitpicker -> clicked"/>
<policy label="leitzentrale -> manager -> nitpicker_focus" report="nitpicker -> focus"/>
<policy label="leitzentrale -> manager -> nitpicker_hover" report="nitpicker -> hover"/>
<policy label="nit_focus -> leitzentrale"
report="global_keys_handler -> leitzentrale"/>
<policy label="nit_focus -> slides"
@ -577,6 +579,8 @@ install_config {
<child name="config_fs_rom"/> </service>
<service name="ROM" label_prefix="config -> ">
<child name="config_fs_rom"/> </service>
<service name="ROM" label="manager -> nitpicker_focus">
<child name="report_rom"/> </service>
<service name="ROM" label="manager -> nitpicker_hover">
<child name="report_rom"/> </service>
<service name="ROM" label="manager -> leitzentrale">

View File

@ -254,6 +254,8 @@
<child name="config_fs_report" label="managed -> depot_query"/> </service>
<service name="Report"> <child name="report_rom"/> </service>
<service name="ROM" label_prefix="report ->"> <parent/> </service>
<service name="ROM" label="nitpicker_focus"> <parent/> </service>
<service name="ROM" label="nitpicker_hover"> <parent/> </service>
<service name="ROM" label_suffix="_hover"> <child name="report_rom"/> </service>
<service name="ROM" label="window_list"> <child name="report_rom"/> </service>
<service name="ROM" label="decorator_margins"> <child name="report_rom"/> </service>

View File

@ -36,6 +36,7 @@
#include <model/file_operation_queue.h>
#include <model/settings.h>
#include <model/presets.h>
#include <model/screensaver.h>
#include <view/download_status.h>
#include <view/popup_dialog.h>
#include <view/panel_dialog.h>
@ -71,7 +72,8 @@ struct Sculpt::Main : Input_event_handler,
Panel_dialog::State,
Dialog,
Popup_dialog::Refresh,
Menu_view::Hover_update_handler
Menu_view::Hover_update_handler,
Screensaver::Action
{
Env &_env;
@ -114,6 +116,16 @@ struct Sculpt::Main : Input_event_handler,
void _handle_gui_mode();
Screensaver _screensaver { _env, *this };
/**
* Screensaver::Action interface
*/
void screensaver_changed() override
{
/* hook for driving the lifetime of the display driver */
}
Managed_config<Main> _fonts_config {
_env, "config", "fonts", *this, &Main::_handle_fonts_config };

View File

@ -0,0 +1,140 @@
/*
* \brief Logic for activating/deactivating the screensaver
* \author Norman Feske
* \date 2023-06-27
*/
/*
* Copyright (C) 2023 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _MODEL__SCREENSAVER_H_
#define _MODEL__SCREENSAVER_H_
#include <types.h>
namespace Sculpt { class Screensaver; }
class Sculpt::Screensaver : Noncopyable
{
public:
struct Action : Interface
{
virtual void screensaver_changed() = 0;
};
private:
Env &_env;
Action &_action;
/* config */
unsigned _max_seconds_of_inactivity = 10;
bool _blank_after_some_time = true;
/* state */
uint64_t _last_activity_ms = 0;
bool _recent_user_activity = true;
bool _forced_blanked = false;
Timer::Connection _timer { _env };
Signal_handler<Screensaver> _timer_handler {
_env.ep(), *this, &Screensaver::_handle_timer };
void _handle_timer()
{
uint64_t const now = _timer.elapsed_ms();
if (now - _last_activity_ms > _max_seconds_of_inactivity*1000) {
if (_recent_user_activity) {
_recent_user_activity = false;
_action.screensaver_changed();
}
}
}
void _wake_up()
{
_last_activity_ms = _timer.elapsed_ms();
_timer.trigger_once(_max_seconds_of_inactivity*1024*1024);
if (!_recent_user_activity) {
_recent_user_activity = true;
_action.screensaver_changed();
}
}
/**
* Utility for watching the 'active' attribute of a ROM module
*/
struct Watched_rom : Noncopyable
{
Screensaver &_screensaver;
Attached_rom_dataspace _rom;
Signal_handler<Watched_rom> _handler {
_screensaver._env.ep(), *this, &Watched_rom::_handle };
Watched_rom(Screensaver &screensaver, char const *label)
:
_screensaver(screensaver), _rom(screensaver._env, label)
{
_rom.sigh(_handler);
}
void _handle()
{
_rom.update();
if (_rom.xml().attribute_value("active", false))
_screensaver._wake_up();
}
};
Watched_rom _nitpicker_focus { *this, "nitpicker_focus" };
Watched_rom _nitpicker_hover { *this, "nitpicker_hover" };
public:
Screensaver(Env &env, Action &action) : _env(env), _action(action)
{
_timer.sigh(_timer_handler);
}
bool display_enabled() const
{
if (_forced_blanked)
return false;
if (_blank_after_some_time && !_recent_user_activity)
return false;
return true;
}
void blank_after_some_time(bool blank_after_some_time)
{
_blank_after_some_time = blank_after_some_time;
_wake_up();
}
/**
* User enforces the enabling or disabling of the display (power button)
*/
void force_toggle()
{
if (display_enabled())
_forced_blanked = true;
else
_forced_blanked = false;
_action.screensaver_changed();
}
};
#endif /* _MODEL__SCREENSAVER_H_ */