Skip to content

Commit 269eb3b

Browse files
committed
Add debouncing to windowserver to avoid huge number of rerenders; Fix vertical label centering
1 parent 966a31f commit 269eb3b

File tree

8 files changed

+80
-80
lines changed

8 files changed

+80
-80
lines changed

applications/windowserver/src/components/component.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ void component_t::setBoundsInternal(const g_rectangle& newBounds)
8080
g_mutex_release(lock);
8181
}
8282

83+
void component_t::recheckGraphics()
84+
{
85+
if(hasGraphics())
86+
graphics.resize(bounds.width, bounds.height);
87+
}
88+
8389
g_rectangle component_t::getBounds() const
8490
{
8591
g_mutex_acquire(lock);
@@ -451,7 +457,7 @@ void component_t::markFor(component_requirement_t req)
451457
if(parent)
452458
parent->markChildsFor(req);
453459

454-
windowserver_t::instance()->requestUpdate();
460+
windowserver_t::instance()->requestUpdateLater();
455461
}
456462

457463
void component_t::markChildsFor(component_requirement_t req)

applications/windowserver/src/components/component.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,8 @@ class component_t : public bounding_component_t, public focusable_component_t
348348

349349
void addListener(g_ui_component_event_type eventType, g_tid target_thread, g_ui_component_id id);
350350
bool callForListeners(g_ui_component_event_type eventType, const std::function<void(event_listener_info_t&)>& func);
351+
352+
void recheckGraphics();
351353
};
352354

353355
#endif

applications/windowserver/src/components/label.cpp

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <cairo/cairo.h>
2626
#include <ghost.h>
2727
#include <sstream>
28+
#include <windowserver.hpp>
2829

2930
label_t::label_t()
3031
{
@@ -42,16 +43,6 @@ void label_t::setFont(g_font* newFont)
4243

4344
void label_t::update()
4445
{
45-
g_rectangle thisBounds(0, 0, getBounds().width, getBounds().height);
46-
47-
// Check if the component was ever layouted, otherwise set to a high value
48-
if(thisBounds.width == 0 && thisBounds.height == 0)
49-
{
50-
thisBounds.width = 9999;
51-
thisBounds.height = 9999;
52-
}
53-
54-
// get text bounds
5546
auto cr = graphics.acquireContext();
5647
if(!cr)
5748
return;
@@ -81,34 +72,29 @@ void label_t::paint()
8172
{
8273
clearSurface();
8374

84-
auto cr = graphics.acquireContext();
85-
if(!cr)
86-
return;
87-
88-
g_mutex_acquire(lock);
8975
auto bounds = getBounds();
90-
g_mutex_release(lock);
91-
92-
cairo_save(cr);
93-
cairo_set_source_rgb(cr, ARGB_FR_FROM(color), ARGB_FB_FROM(color), ARGB_FG_FROM(color));
94-
95-
int textLeft;
96-
int textBot = (bounds.height / 2 - fontExtents.height / 2) + fontExtents.height;
9776

77+
int textX;
78+
int textY = bounds.height / 2 - fontExtents.height / 2 + fontExtents.ascent;
9879
if(alignment == g_text_alignment::CENTER)
9980
{
100-
textLeft = bounds.width / 2 - textExtents.width / 2;
81+
textX = bounds.width / 2 - textExtents.width / 2;
10182
}
10283
else if(alignment == g_text_alignment::RIGHT)
10384
{
104-
textLeft = bounds.width - textExtents.width;
85+
textX = bounds.width - textExtents.width;
10586
}
10687
else
10788
{
108-
textLeft = 0;
89+
textX = 0;
10990
}
11091

111-
cairo_move_to(cr, textLeft, textBot);
92+
auto cr = graphics.acquireContext();
93+
if(!cr)
94+
return;
95+
cairo_save(cr);
96+
cairo_set_source_rgb(cr, ARGB_FR_FROM(color), ARGB_FB_FROM(color), ARGB_FG_FROM(color));
97+
cairo_move_to(cr, textX, textY);
11298
cairo_set_font_face(cr, font->getFace());
11399
cairo_set_font_size(cr, fontSize);
114100
cairo_show_text(cr, text.c_str());

applications/windowserver/src/components/panel.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ void panel_t::setBackground(g_color_argb color)
4242
{
4343
background = color;
4444
markFor(COMPONENT_REQUIREMENT_PAINT);
45+
recheckGraphics();
4546
}
4647

4748
g_color_argb panel_t::getBackground()

applications/windowserver/src/input/input_receiver.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ void input_receiver_t::startReceiveKeyEvents()
5454

5555
event_queue->bufferKeyEvent(key);
5656

57-
windowserver_t::instance()->requestUpdate();
57+
windowserver_t::instance()->requestUpdateImmediately();
5858
}
5959
}
6060

@@ -103,6 +103,6 @@ void input_receiver_t::startReceiveMouseEvents()
103103
cursor_t::nextPressedButtons |= G_MOUSE_BUTTON_3;
104104
}
105105

106-
windowserver_t::instance()->requestUpdate();
106+
windowserver_t::instance()->requestUpdateImmediately();
107107
}
108108
}

applications/windowserver/src/interface/interface_receiver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ void interfaceReceiverProcessCommand(g_message_header* requestMessage)
560560
responseLength = sizeof(g_ui_simple_response);
561561
}
562562

563-
windowserver_t::instance()->requestUpdate();
563+
windowserver_t::instance()->requestUpdateLater();
564564

565565
if(responseMessage)
566566
{

applications/windowserver/src/windowserver.cpp

Lines changed: 37 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,21 @@ void windowserver_t::startInputHandlers()
7272
}
7373

7474
server->loadCursor();
75-
server->requestUpdate();
75+
server->requestUpdateLater();
7676
}
7777

78-
void startOtherTasks()
78+
void windowserver_t::startOtherTasks()
7979
{
8080
g_task_register_id("windowserver/launcher");
8181
// TODO not the windowservers job
8282
g_spawn("/applications/desktop.bin", "", "", G_SECURITY_LEVEL_APPLICATION);
8383
}
8484

85+
void windowserver_t::startLazyUpdateLoop()
86+
{
87+
windowserver_t::instance()->updateDebounceLoop();
88+
}
89+
8590
void windowserver_t::launch()
8691
{
8792
g_task_register_id("windowserver");
@@ -98,10 +103,10 @@ void windowserver_t::launch()
98103

99104
g_create_task((void*) &interfaceRegistrationThread);
100105
g_create_task((void*) &startOtherTasks);
106+
g_create_task((void*) &startLazyUpdateLoop);
101107

102-
updateTask = g_create_task_d((void*) startUpdateLoop, this);
103108
renderTask = g_get_tid();
104-
renderLoop(screenBounds);
109+
updateLoop(screenBounds);
105110
}
106111

107112
void windowserver_t::createVitalComponents(g_rectangle screenBounds)
@@ -146,70 +151,62 @@ void windowserver_t::initializeVideo()
146151
}
147152
}
148153

149-
void windowserver_t::startUpdateLoop(windowserver_t* self)
150-
{
151-
self->updateLoop();
152-
}
153-
154-
void windowserver_t::updateLoop()
154+
void windowserver_t::updateLoop(const g_rectangle& screenBounds) const
155155
{
156156
g_task_register_id("windowserver/updater");
157157

158-
int timesUpdated = 0;
158+
graphics_t global;
159+
global.resize(screenBounds.width, screenBounds.height, false);
160+
161+
cursor_t::nextPosition = g_point(screenBounds.width / 2, screenBounds.height / 2);
159162

163+
uint64_t lastUpdate = 0;
160164
g_mutex_acquire(updateLock);
161165
while(true)
162166
{
163-
++timesUpdated;
164167
eventProcessor->process();
165168

166169
screen->resolveRequirement(COMPONENT_REQUIREMENT_UPDATE, 0);
167170
screen->resolveRequirement(COMPONENT_REQUIREMENT_LAYOUT, 0);
168171
screen->resolveRequirement(COMPONENT_REQUIREMENT_PAINT, 0);
169172

170-
requestRender();
173+
screen->blit(&global, screenBounds, g_point(0, 0));
174+
cursor_t::paint(&global);
175+
176+
output(&global);
171177

178+
framesTotal++;
172179
if(!g_mutex_acquire_to(updateLock, 1000))
173-
{
174-
klog("Times updated: %i", timesUpdated);
175-
}
180+
klog("Times updated: %i", framesTotal);
181+
182+
auto now = g_millis();
183+
if(now - lastUpdate < 10)
184+
g_sleep(5);
185+
lastUpdate = now;
176186
}
177187
}
178188

179-
void windowserver_t::requestUpdate() const
189+
void windowserver_t::requestUpdateImmediately() const
180190
{
181191
g_mutex_release(updateLock);
182192
}
183193

184-
185-
void windowserver_t::renderLoop(g_rectangle screenBounds)
194+
void windowserver_t::requestUpdateLater() const
186195
{
187-
g_task_register_id("windowserver/renderer");
188-
189-
graphics_t global;
190-
global.resize(screenBounds.width, screenBounds.height, false);
191-
192-
cursor_t::nextPosition = g_point(screenBounds.width / 2, screenBounds.height / 2);
196+
g_mutex_release(lazyUpdateLock);
197+
}
193198

194-
g_mutex_acquire(renderLock);
199+
void windowserver_t::updateDebounceLoop() const
200+
{
201+
g_mutex_acquire(lazyUpdateLock);
195202
while(true)
196203
{
197-
screen->blit(&global, screenBounds, g_point(0, 0));
198-
cursor_t::paint(&global);
199-
200-
output(&global);
201-
202-
framesTotal++;
203-
g_mutex_acquire_to(renderLock, 1000);
204+
g_sleep(10);
205+
g_mutex_acquire_to(lazyUpdateLock, 1000);
206+
g_mutex_release(updateLock);
204207
}
205208
}
206209

207-
void windowserver_t::requestRender() const
208-
{
209-
g_mutex_release(renderLock);
210-
g_yield_t(renderTask);
211-
}
212-
213210
void windowserver_t::output(graphics_t* graphics) const
214211
{
215212
g_rectangle invalid = screen->grabInvalid();
@@ -360,7 +357,7 @@ void windowserver_t::fpsCounter()
360357
std::stringstream s;
361358
s << "FPS: " << framesTotal << ", Time: " << seconds;
362359
instance()->stateLabel->setTitle(s.str());
363-
instance()->requestUpdate();
360+
instance()->requestUpdateLater();
364361
framesTotal = 0;
365362
}
366363
}

applications/windowserver/src/windowserver.hpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,17 @@ class windowserver_t
3636
{
3737
g_tid updateTask = G_TID_NONE;
3838
g_tid renderTask = G_TID_NONE;
39+
3940
g_user_mutex updateLock = g_mutex_initialize();
40-
g_user_mutex renderLock = g_mutex_initialize();
41+
g_user_mutex lazyUpdateLock = g_mutex_initialize();
4142

4243
void initializeVideo();
4344
void createVitalComponents(g_rectangle screenBounds);
4445
void loadCursor();
4546
static void startInputHandlers();
4647

47-
void renderLoop(g_rectangle screenBounds);
48-
49-
static void startUpdateLoop(windowserver_t* self);
50-
void updateLoop();
48+
void updateLoop(const g_rectangle& screenBounds) const;
49+
void updateDebounceLoop() const;
5150

5251
static void fpsCounter();
5352

@@ -67,15 +66,17 @@ class windowserver_t
6766
void launch();
6867

6968
/**
70-
* When components have changed, requests the windowserver to perform an
71-
* update of all dirty components on the screen.
69+
* When components have changed, requests the server to perform an update of
70+
* all components. This triggers the update to run immediately.
7271
*/
73-
void requestUpdate() const;
72+
void requestUpdateImmediately() const;
7473

7574
/**
76-
* Requests the windowserver to perform a rendering.
75+
* Also requests an update, but debounces requests that come in very quickly.
76+
* This is used to avoid that for example a large amount of changes via the
77+
* interface cause too many updates.
7778
*/
78-
void requestRender() const;
79+
void requestUpdateLater() const;
7980

8081
static void setDebug(bool cond);
8182
static bool isDebug();
@@ -97,6 +98,10 @@ class windowserver_t
9798
*/
9899
component_t* dispatchUpwards(component_t* component, event_t& event);
99100

101+
/**
102+
* Switches the focus from the currently focused component to a different
103+
* component. Must be used to ensure state is updated correctly.
104+
*/
100105
component_t* switchFocus(component_t* to);
101106

102107
/**
@@ -105,6 +110,9 @@ class windowserver_t
105110
* @return the instance
106111
*/
107112
static windowserver_t* instance();
113+
114+
static void startLazyUpdateLoop();
115+
static void startOtherTasks();
108116
};
109117

110118
#endif

0 commit comments

Comments
 (0)