summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2017-03-12 17:25:04 +0100
committerBent Bisballe Nyeng <deva@aasimon.org>2017-03-12 17:33:17 +0100
commit494e7218597a6cd94902b3ae6f827e74b41c00b0 (patch)
tree8b0e7359b9664249945b62a0012c2178b5faf823
parent75de9c0ac782fa6fecb92f3a22f311b517856abb (diff)
Fix redrawing of underlying exposed area on Widget moves/resizing.
-rw-r--r--plugingui/pixelbuffer.cc18
-rw-r--r--plugingui/pixelbuffer.h37
-rw-r--r--plugingui/widget.cc49
-rw-r--r--plugingui/window.cc43
4 files changed, 118 insertions, 29 deletions
diff --git a/plugingui/pixelbuffer.cc b/plugingui/pixelbuffer.cc
index bbef84c..360ad06 100644
--- a/plugingui/pixelbuffer.cc
+++ b/plugingui/pixelbuffer.cc
@@ -33,7 +33,7 @@
namespace GUI
{
-PixelBuffer::PixelBuffer(size_t width, size_t height)
+PixelBuffer::PixelBuffer(std::size_t width, std::size_t height)
: buf(nullptr)
{
realloc(width, height);
@@ -44,7 +44,7 @@ PixelBuffer::~PixelBuffer()
free(buf);
}
-void PixelBuffer::realloc(size_t width, size_t height)
+void PixelBuffer::realloc(std::size_t width, std::size_t height)
{
free(buf);
buf = (unsigned char *)calloc(width * height, 3);
@@ -53,7 +53,7 @@ void PixelBuffer::realloc(size_t width, size_t height)
}
#define PX(k) ((x + y * width) * 3 + k)
-void PixelBuffer::setPixel(size_t x, size_t y,
+void PixelBuffer::setPixel(std::size_t x, std::size_t y,
unsigned char red,
unsigned char green,
unsigned char blue,
@@ -84,7 +84,7 @@ void PixelBuffer::setPixel(size_t x, size_t y,
}
}
-PixelBufferAlpha::PixelBufferAlpha(size_t width, size_t height)
+PixelBufferAlpha::PixelBufferAlpha(std::size_t width, std::size_t height)
: managed(true)
, buf(nullptr)
, x(0)
@@ -101,7 +101,7 @@ PixelBufferAlpha::~PixelBufferAlpha()
}
}
-void PixelBufferAlpha::realloc(size_t width, size_t height)
+void PixelBufferAlpha::realloc(std::size_t width, std::size_t height)
{
free(buf);
buf = (unsigned char *)calloc(width * height, 4);
@@ -111,7 +111,7 @@ void PixelBufferAlpha::realloc(size_t width, size_t height)
#undef PX
#define PX(k) ((x + y * width) * 4 + k)
-void PixelBufferAlpha::setPixel(size_t x, size_t y,
+void PixelBufferAlpha::setPixel(std::size_t x, std::size_t y,
unsigned char red,
unsigned char green,
unsigned char blue,
@@ -135,7 +135,7 @@ static inline void getAlpha(unsigned char _a, unsigned char _b,
b *= (1 - a);
}
-void PixelBufferAlpha::addPixel(size_t x, size_t y,
+void PixelBufferAlpha::addPixel(std::size_t x, std::size_t y,
unsigned char red,
unsigned char green,
unsigned char blue,
@@ -172,13 +172,13 @@ void PixelBufferAlpha::addPixel(size_t x, size_t y,
}
}
-void PixelBufferAlpha::addPixel(size_t x, size_t y, const Colour& c)
+void PixelBufferAlpha::addPixel(std::size_t x, std::size_t y, const Colour& c)
{
addPixel(x, y,
c.red() * 255, c.green() * 255, c.blue() * 255, c.alpha() * 255);
}
-void PixelBufferAlpha::pixel(size_t x, size_t y,
+void PixelBufferAlpha::pixel(std::size_t x, std::size_t y,
unsigned char* red,
unsigned char* green,
unsigned char* blue,
diff --git a/plugingui/pixelbuffer.h b/plugingui/pixelbuffer.h
index 94c5496..71869a0 100644
--- a/plugingui/pixelbuffer.h
+++ b/plugingui/pixelbuffer.h
@@ -33,47 +33,49 @@
namespace GUI
{
-class PixelBuffer {
+class PixelBuffer
+{
public:
- PixelBuffer(size_t width, size_t height);
+ PixelBuffer(std::size_t width, std::size_t height);
~PixelBuffer();
- void realloc(size_t width, size_t height);
+ void realloc(std::size_t width, std::size_t height);
- void setPixel(size_t x, size_t y,
+ void setPixel(std::size_t x, std::size_t y,
unsigned char red,
unsigned char green,
unsigned char blue,
unsigned char alpha);
unsigned char* buf{nullptr};
- size_t width{0};
- size_t height{0};
+ std::size_t width{0};
+ std::size_t height{0};
};
-class PixelBufferAlpha {
+class PixelBufferAlpha
+{
public:
PixelBufferAlpha() = default;
- PixelBufferAlpha(size_t width, size_t height);
+ PixelBufferAlpha(std::size_t width, std::size_t height);
~PixelBufferAlpha();
- void realloc(size_t width, size_t height);
+ void realloc(std::size_t width, std::size_t height);
- void setPixel(size_t x, size_t y,
+ void setPixel(std::size_t x, std::size_t y,
unsigned char red,
unsigned char green,
unsigned char blue,
unsigned char alpha);
- void addPixel(size_t x, size_t y,
+ void addPixel(std::size_t x, std::size_t y,
unsigned char red,
unsigned char green,
unsigned char blue,
unsigned char alpha);
- void addPixel(size_t x, size_t y, const Colour& c);
+ void addPixel(std::size_t x, std::size_t y, const Colour& c);
- void pixel(size_t x, size_t y,
+ void pixel(std::size_t x, std::size_t y,
unsigned char* red,
unsigned char* green,
unsigned char* blue,
@@ -86,6 +88,15 @@ public:
int x{0};
int y{0};
bool dirty{true};
+ bool visible{true};
+
+ // Add optional dirty rect that this pixelbuffer took up since it was last
+ // rendered. Make sure to update this list on resize and/or move.
+ std::size_t last_width{0};
+ std::size_t last_height{0};
+ int last_x{0};
+ int last_y{0};
+ bool has_last{false};
};
} // GUI::
diff --git a/plugingui/widget.cc b/plugingui/widget.cc
index 7d92a22..00acfbf 100644
--- a/plugingui/widget.cc
+++ b/plugingui/widget.cc
@@ -42,6 +42,9 @@ Widget::Widget(Widget* parent)
parent->addChild(this);
_window = parent->window();
}
+
+ pixbuf.x = translateToWindowX();
+ pixbuf.y = translateToWindowY();
}
Widget::~Widget()
@@ -64,12 +67,14 @@ void Widget::hide()
void Widget::setVisible(bool visible)
{
- _visible = visible;
-
- if(visible)
+ if(_visible == visible)
{
- redraw();
+ return;
}
+
+ _visible = visible;
+ pixbuf.visible = visible;
+ redraw();
}
bool Widget::visible() const
@@ -130,7 +135,20 @@ void Widget::resize(std::size_t width, std::size_t height)
_width = width;
_height = height;
+
+ // Store old size/position in pixelbuffer for rendering invalidation.
+ if(!pixbuf.has_last)
+ {
+ pixbuf.last_width = pixbuf.width;
+ pixbuf.last_height = pixbuf.height;
+ pixbuf.last_x = pixbuf.x;
+ pixbuf.last_y = pixbuf.y;
+ pixbuf.has_last = true;
+ }
+
pixbuf.realloc(width, height);
+ pixbuf.x = translateToWindowX();
+ pixbuf.y = translateToWindowY();
redraw();
sizeChangeNotifier(width, height);
}
@@ -145,6 +163,20 @@ void Widget::move(int x, int y)
_x = x;
_y = y;
+
+ // Store old size/position in pixelbuffer for rendering invalidation.
+ if(!pixbuf.has_last)
+ {
+ pixbuf.last_width = pixbuf.width;
+ pixbuf.last_height = pixbuf.height;
+ pixbuf.last_x = pixbuf.x;
+ pixbuf.last_y = pixbuf.y;
+ pixbuf.has_last = true;
+ }
+
+ //pixbuf.x = translateToWindowX();
+ //pixbuf.y = translateToWindowY();
+
positionChangeNotifier(x, y);
}
@@ -216,11 +248,14 @@ std::vector<PixelBufferAlpha*> Widget::getPixelBuffers()
dirty = false;
}
- pixelBuffers.push_back(&pixbuf);
+ if(pixbuf.dirty || visible())
+ {
+ pixelBuffers.push_back(&pixbuf);
+ }
- for(auto child : children)
+ if(visible())
{
- if(child->visible())
+ for(auto child : children)
{
auto childPixelBuffers = child->getPixelBuffers();
pixelBuffers.insert(pixelBuffers.end(),
diff --git a/plugingui/window.cc b/plugingui/window.cc
index d4046c2..8bc5c62 100644
--- a/plugingui/window.cc
+++ b/plugingui/window.cc
@@ -262,10 +262,50 @@ bool Window::updateBuffer()
};
}
}
+
+ if(pixel_buffer->has_last)
+ {
+ auto x1 = (std::size_t)pixel_buffer->last_x;
+ auto x2 = (std::size_t)(pixel_buffer->last_x + pixel_buffer->last_width);
+ auto y1 = (std::size_t)pixel_buffer->last_y;
+ auto y2 = (std::size_t)(pixel_buffer->last_y + pixel_buffer->last_height);
+
+ pixel_buffer->has_last = false;
+ if(!has_dirty_rect)
+ {
+ // Insert this area:
+ dirty_rect = {x1, y1, x2, y2};
+ has_dirty_rect = true;
+ }
+ else
+ {
+ // Expand existing area:
+ auto x1_0 = dirty_rect.x1;
+ auto y1_0 = dirty_rect.y1;
+ auto x2_0 = dirty_rect.x2;
+ auto y2_0 = dirty_rect.y2;
+ dirty_rect = {
+ (x1_0 < x1) ? x1_0 : x1,
+ (y1_0 < y1) ? y1_0 : y1,
+ (x2_0 > x2) ? x2_0 : x2,
+ (y2_0 > y2) ? y2_0 : y2
+ };
+ }
+ }
+ }
+
+ if(!has_dirty_rect)
+ {
+ return false;
}
for(auto& pixel_buffer : pixel_buffers)
{
+ if(!pixel_buffer->visible)
+ {
+ continue;
+ }
+
int update_width = pixel_buffer->width;
int update_height = pixel_buffer->height;
@@ -308,6 +348,9 @@ bool Window::updateBuffer()
}
}
+ dirty_rect.x2 = std::min(wpixbuf.width, dirty_rect.x2);
+ dirty_rect.y2 = std::min(wpixbuf.height, dirty_rect.y2);
+
native->redraw(dirty_rect);
needs_redraw = false;