much improved paint and reflow scheduling
This commit is contained in:
parent
002318c213
commit
dd894d1024
6 changed files with 63 additions and 20 deletions
24
src/Box.cpp
24
src/Box.cpp
|
@ -95,4 +95,28 @@ double Box::clamp_for_dimension(Direction direction, double value) {
|
|||
}
|
||||
}
|
||||
|
||||
Box Box::united(const Box &other) {
|
||||
if (is_null()) {
|
||||
return other;
|
||||
}
|
||||
if (other.is_null()) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Box rect;
|
||||
rect.set_left(std::min(left(), other.left()));
|
||||
rect.set_top(std::min(top(), other.top()));
|
||||
rect.set_right(std::max(right(), other.right()));
|
||||
rect.set_bottom(std::max(bottom(), other.bottom()));
|
||||
return rect;
|
||||
}
|
||||
|
||||
bool Box::is_null() const {
|
||||
return !(m_x && m_y && m_width && m_height);
|
||||
}
|
||||
|
||||
std::string Box::debug() {
|
||||
return "Box(" + std::to_string(m_x) + ", " + std::to_string(m_y) + ", " + std::to_string(m_width) + ", " + std::to_string(m_height) + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
13
src/Box.hpp
13
src/Box.hpp
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "Point.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace Raven {
|
||||
|
||||
|
@ -51,6 +52,11 @@ public:
|
|||
double min_height() const { return m_min_height; }
|
||||
double max_width() const { return m_max_width; }
|
||||
double max_height() const { return m_max_height; }
|
||||
double top() const { return y(); }
|
||||
double bottom() const { return y() + height() - 1; }
|
||||
double left() const { return x(); }
|
||||
double right() const { return x() + width() - 1; }
|
||||
bool is_null() const;
|
||||
double dimension_at(Direction direction) { return direction == Direction::Horizontal ? width() : height(); }
|
||||
double max_dimension_at(Direction direction) { return direction == Direction::Horizontal ? max_width() : max_height(); }
|
||||
double min_dimension_at(Direction direction) { return direction == Direction::Horizontal ? min_width() : min_height(); }
|
||||
|
@ -60,6 +66,10 @@ public:
|
|||
void set_y(double y) { m_y = y; }
|
||||
void set_width(double width);
|
||||
void set_height(double height);
|
||||
void set_top(double top) { set_y(top); }
|
||||
void set_bottom(double bottom) { set_height(bottom - y() + 1); }
|
||||
void set_right(double right) { set_width(right - x() + 1); }
|
||||
void set_left(double left) { set_x(left); }
|
||||
|
||||
void set_max_width(double max_width) { m_max_width = max_width; set_width(m_width); }
|
||||
void set_max_height(double max_height) { m_max_height = max_height; set_height(m_height); }
|
||||
|
@ -73,6 +83,9 @@ public:
|
|||
bool contains_box(const Box &other) const;
|
||||
|
||||
Box offset(double x, double y);
|
||||
Box united(const Box &other);
|
||||
|
||||
std::string debug();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -192,18 +192,18 @@ void Widget::handle_repaint_rect(RepaintRectEvent &event) {
|
|||
}
|
||||
|
||||
void Widget::handle_relayout_subtree(RelayoutSubtreeEvent &event) {
|
||||
on_layout(); // hack
|
||||
on_layout();
|
||||
|
||||
m_window_relative = compute_window_relative();
|
||||
|
||||
for (auto child : m_children) {
|
||||
child->dispatch_event(event);
|
||||
}
|
||||
|
||||
if (m_layout) {
|
||||
m_layout->run();
|
||||
}
|
||||
|
||||
for (auto child : m_children) {
|
||||
child->dispatch_event(event);
|
||||
}
|
||||
|
||||
on_after_layout();
|
||||
}
|
||||
|
||||
|
|
|
@ -76,9 +76,10 @@ bool Window::dispatch_to_main_widget(Event &event) {
|
|||
}
|
||||
|
||||
void Window::repaint(Box geometry) {
|
||||
m_did_repaint_during_batch = true;
|
||||
if (m_batches)
|
||||
if (m_batches) {
|
||||
m_invalidated_area = m_invalidated_area.united(geometry);
|
||||
return;
|
||||
}
|
||||
|
||||
auto event = RepaintRectEvent(true, geometry);
|
||||
dispatch_to_main_widget(event);
|
||||
|
@ -116,7 +117,6 @@ void Window::reflow() {
|
|||
}
|
||||
|
||||
void Window::start_batch() {
|
||||
//INFO << "New batch started. Current count: " << m_batches << std::endl;
|
||||
m_batches++;
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,6 @@ void Window::end_batch() {
|
|||
// we are only interested in performing batch operations for the last batch
|
||||
if (m_batches > 1) {
|
||||
m_batches--;
|
||||
//INFO << "Consumed batch. Current count: " << m_batches << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -135,17 +134,17 @@ void Window::end_batch() {
|
|||
|
||||
if (m_did_relayout_during_batch) {
|
||||
reflow();
|
||||
} else if (m_did_repaint_during_batch) {
|
||||
repaint();
|
||||
} else if (!m_invalidated_area.is_null()) {
|
||||
repaint(m_invalidated_area);
|
||||
}
|
||||
|
||||
m_did_relayout_during_batch = false;
|
||||
m_did_repaint_during_batch = false;
|
||||
INFO << "Performed all batch actions." << std::endl;
|
||||
m_invalidated_area = {0, 0, 0, 0};
|
||||
}
|
||||
|
||||
void Window::run(bool block) {
|
||||
XEvent e;
|
||||
bool is_loop_batch_started = false;
|
||||
|
||||
for (;;) {
|
||||
if (block || XPending(m_x_display))
|
||||
|
@ -153,10 +152,13 @@ void Window::run(bool block) {
|
|||
else
|
||||
break;
|
||||
|
||||
if (!is_loop_batch_started) {
|
||||
start_batch();
|
||||
is_loop_batch_started = true;
|
||||
}
|
||||
switch (e.type) {
|
||||
case MapNotify: {
|
||||
INFO << "[X11 EVENT] MapNotify" << std::endl;
|
||||
end_batch();
|
||||
INFO << "[X11 EVENT] MapNotify" << std::endl;
|
||||
break;
|
||||
}
|
||||
case ConfigureNotify: {
|
||||
|
@ -210,14 +212,16 @@ void Window::run(bool block) {
|
|||
}
|
||||
}
|
||||
|
||||
if (XPending(m_x_display) == 0 && !m_microtasks.empty()) {
|
||||
start_batch();
|
||||
if (XPending(m_x_display) == 0) {
|
||||
while (!m_microtasks.empty()) {
|
||||
auto callback = m_microtasks.front();
|
||||
callback();
|
||||
m_microtasks.pop();
|
||||
}
|
||||
end_batch();
|
||||
if (is_loop_batch_started) {
|
||||
end_batch();
|
||||
is_loop_batch_started = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,8 +59,8 @@ private:
|
|||
Box m_rect { 0, 0, 800, 600 };
|
||||
Painter m_painter {};
|
||||
Cairo::RefPtr<Cairo::XlibSurface> m_xlib_surface { nullptr };
|
||||
int m_batches { 1 };
|
||||
bool m_did_repaint_during_batch { false };
|
||||
int m_batches { 0 };
|
||||
Box m_invalidated_area {0, 0, 0, 0};
|
||||
bool m_did_relayout_during_batch { false };
|
||||
std::queue<std::function<void()>> m_microtasks;
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
int main() {
|
||||
Raven::Window window {};
|
||||
window.spawn_window();
|
||||
window.start_batch();
|
||||
|
||||
auto main_widget = window.set_main_widget<Raven::Widget>();
|
||||
auto main_widget_layout = main_widget->set_layout<Raven::BoxLayout>(Raven::Direction::Horizontal);
|
||||
|
@ -66,6 +67,7 @@ int main() {
|
|||
}
|
||||
list_view->elements_updated();
|
||||
|
||||
window.end_batch();
|
||||
window.run(true);
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue