diff --git a/repos/gems/sculpt/leitzentrale/default b/repos/gems/sculpt/leitzentrale/default
index 13c7801756..b4919bc8f6 100644
--- a/repos/gems/sculpt/leitzentrale/default
+++ b/repos/gems/sculpt/leitzentrale/default
@@ -178,15 +178,15 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/repos/gems/src/app/decorator/main.cc b/repos/gems/src/app/decorator/main.cc
index 43c284bf8e..a696b4cc38 100644
--- a/repos/gems/src/app/decorator/main.cc
+++ b/repos/gems/src/app/decorator/main.cc
@@ -17,6 +17,7 @@
#include
#include
#include
+#include
#include
#include
@@ -39,6 +40,18 @@ struct Decorator::Main : Window_factory_base
{
Env &_env;
+ Timer::Connection _timer { _env };
+
+ /*
+ * Time base for animations, which are computed in steps of 10 ms
+ */
+ struct Ticks { uint64_t cs; /* centi-seconds (10 ms) */ };
+
+ Ticks _now()
+ {
+ return { .cs = _timer.curr_time().trunc_to_plain_ms().value / 10 };
+ }
+
Gui::Connection _gui { _env };
struct Canvas
@@ -104,33 +117,31 @@ struct Decorator::Main : Window_factory_base
Animator _animator { };
- /**
- * Process the update every 'frame_period' GUI sync signals. The
- * 'frame_cnt' holds the counter of the GUI sync signals.
- *
- * A lower 'frame_period' value makes the decorations more responsive
- * but it also puts more load on the system.
- *
- * If the GUI sync signal fires every 10 milliseconds, a
- * 'frame_period' of 2 results in an update rate of 1000/20 = 50 frames per
- * second.
- */
- unsigned _frame_cnt = 0;
- unsigned _frame_period = 2;
-
- /**
- * Install handler for responding to GUI sync events
- */
- void _handle_gui_sync();
-
- void _trigger_sync_handling()
- {
- _gui.framebuffer.sync_sigh(_gui_sync_handler);
- }
+ Ticks _previous_sync { };
Signal_handler _gui_sync_handler = {
_env.ep(), *this, &Main::_handle_gui_sync };
+ void _handle_gui_sync();
+
+ bool _gui_sync_enabled = false;
+
+ void _trigger_gui_sync()
+ {
+ Ticks const now = _now();
+ bool const idle = now.cs - _previous_sync.cs > 3;
+
+ if (!_gui_sync_enabled) {
+ _gui.framebuffer.sync_sigh(_gui_sync_handler);
+ _gui_sync_enabled = true;
+ }
+
+ if (idle) {
+ _previous_sync = now;
+ _gui_sync_handler.local_submit();
+ }
+ }
+
Heap _heap { _env.ram(), _env.rm() };
Attached_rom_dataspace _config { _env, "config" };
@@ -267,16 +278,15 @@ void Decorator::Main::_handle_window_layout_update()
_window_layout_update_needed = true;
- _trigger_sync_handling();
+ _trigger_gui_sync();
}
void Decorator::Main::_handle_gui_sync()
{
- if (_frame_cnt++ < _frame_period)
- return;
+ Ticks const now = _now();
- _frame_cnt = 0;
+ Ticks const passed_ticks { now.cs - _previous_sync.cs };
bool model_updated = false;
@@ -300,31 +310,30 @@ void Decorator::Main::_handle_gui_sync()
bool const windows_animated = _window_stack.schedule_animated_windows();
- /*
- * To make the perceived animation speed independent from the setting of
- * 'frame_period', we update the animation as often as the GUI
- * sync signal occurs.
- */
- for (unsigned i = 0; i < _frame_period; i++)
+ for (unsigned i = 0; i < passed_ticks.cs; i++)
_animator.animate();
- if (!model_updated && !windows_animated)
- return;
+ if (model_updated || windows_animated) {
- Dirty_rect dirty = _window_stack.draw(_canvas->canvas);
+ Dirty_rect dirty = _window_stack.draw(_canvas->canvas);
- _window_stack.update_gui_views();
+ _window_stack.update_gui_views();
- _gui.execute();
+ _gui.execute();
- dirty.flush([&] (Rect const &r) {
- _gui.framebuffer.refresh(r.x1(), r.y1(), r.w(), r.h()); });
+ dirty.flush([&] (Rect const &r) {
+ _gui.framebuffer.refresh(r.x1(), r.y1(), r.w(), r.h()); });
+ }
/*
* Disable sync handling when becoming idle
*/
- if (!_animator.active())
+ if (!_animator.active()) {
_gui.framebuffer.sync_sigh(Signal_context_capability());
+ _gui_sync_enabled = false;
+ }
+
+ _previous_sync = now;
}
diff --git a/repos/gems/src/app/decorator/window_element.h b/repos/gems/src/app/decorator/window_element.h
index 6865fb5f17..d51cf99b71 100644
--- a/repos/gems/src/app/decorator/window_element.h
+++ b/repos/gems/src/app/decorator/window_element.h
@@ -99,10 +99,10 @@ class Decorator::Window_element : public Animator::Item
/* medium fade-in when gaining the focus or hover highlight */
if ((!_state.focused && state.focused)
|| (!_state.highlighted && state.highlighted))
- return 15;
+ return 30;
/* slow fade-out when leaving focus or hover highlight */
- return 20;
+ return 40;
}
public:
diff --git a/repos/gems/src/app/themed_decorator/main.cc b/repos/gems/src/app/themed_decorator/main.cc
index 5361aa819f..5bcbe84687 100644
--- a/repos/gems/src/app/themed_decorator/main.cc
+++ b/repos/gems/src/app/themed_decorator/main.cc
@@ -17,6 +17,7 @@
#include
#include
#include
+#include
/* decorator includes */
#include
@@ -36,6 +37,18 @@ struct Decorator::Main : Window_factory_base
{
Env &_env;
+ Timer::Connection _timer { _env };
+
+ /*
+ * Time base for animations, which are computed in steps of 10 ms
+ */
+ struct Ticks { uint64_t cs; /* centi-seconds (10 ms) */ };
+
+ Ticks _now()
+ {
+ return { .cs = _timer.curr_time().trunc_to_plain_ms().value / 10 };
+ }
+
Window_stack _window_stack = { *this };
/**
@@ -77,19 +90,7 @@ struct Decorator::Main : Window_factory_base
Reporter _decorator_margins_reporter = { _env, "decorator_margins" };
- /**
- * Process the update every 'frame_period' GUI sync signals. The
- * 'frame_cnt' holds the counter of the GUI sync signals.
- *
- * A lower 'frame_period' value makes the decorations more responsive
- * but it also puts more load on the system.
- *
- * If the GUI sync signal fires every 10 milliseconds, a
- * 'frame_period' of 2 results in an update rate of 1000/20 = 50 frames per
- * second.
- */
- unsigned _frame_cnt = 0;
- unsigned _frame_period = 2;
+ Ticks _previous_sync { };
/**
* Install handler for responding to GUI sync events
@@ -99,9 +100,22 @@ struct Decorator::Main : Window_factory_base
Signal_handler _gui_sync_handler = {
_env.ep(), *this, &Main::_handle_gui_sync };
- void _trigger_sync_handling()
+ bool _gui_sync_enabled = false;
+
+ void _trigger_gui_sync()
{
- _gui.framebuffer.sync_sigh(_gui_sync_handler);
+ Ticks const now = _now();
+ bool const idle = now.cs - _previous_sync.cs > 3;
+
+ if (!_gui_sync_enabled) {
+ _gui.framebuffer.sync_sigh(_gui_sync_handler);
+ _gui_sync_enabled = true;
+ }
+
+ if (idle) {
+ _previous_sync = now;
+ _gui_sync_handler.local_submit();
+ }
}
Attached_rom_dataspace _config { _env, "config" };
@@ -141,7 +155,7 @@ struct Decorator::Main : Window_factory_base
Genode::log("pointer information unavailable");
}
- _trigger_sync_handling();
+ _trigger_gui_sync();
_hover_reporter.enabled(true);
@@ -252,16 +266,15 @@ void Decorator::Main::_handle_window_layout_update()
_window_layout_update_needed = true;
- _trigger_sync_handling();
+ _trigger_gui_sync();
}
void Decorator::Main::_handle_gui_sync()
{
- if (_frame_cnt++ < _frame_period)
- return;
+ Ticks const now = _now();
- _frame_cnt = 0;
+ Ticks const passed_ticks { now.cs - _previous_sync.cs };
bool model_updated = false;
@@ -286,25 +299,23 @@ void Decorator::Main::_handle_gui_sync()
bool const windows_animated = _window_stack.schedule_animated_windows();
- /*
- * To make the perceived animation speed independent from the setting of
- * 'frame_period', we update the animation as often as the GUI sync signal
- * occurs.
- */
- for (unsigned i = 0; i < _frame_period; i++)
+ for (unsigned i = 0; i < passed_ticks.cs; i++)
_animator.animate();
- if (!model_updated && !windows_animated)
- return;
-
- _window_stack.update_gui_views();
- _gui.execute();
+ if (model_updated || windows_animated) {
+ _window_stack.update_gui_views();
+ _gui.execute();
+ }
/*
* Disable sync handling when becoming idle
*/
- if (!_animator.active())
+ if (!_animator.active()) {
_gui.framebuffer.sync_sigh(Signal_context_capability());
+ _gui_sync_enabled = false;
+ }
+
+ _previous_sync = now;
}