mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 04:27:44 +00:00
Start refactoring graphics system to have per-window backing stores.
It was fun for everyone to share a single framebuffer but it was also kinda really awful. Let's move towards having a "GraphicsBitmap" as the backing store for each Window. This is going to need a lot of refactoring so let's get started.
This commit is contained in:
parent
2735b7e50d
commit
9963da9005
21 changed files with 212 additions and 41 deletions
|
@ -35,7 +35,7 @@ public:
|
||||||
WeakLink<T>* leakLink() { return m_link.leakRef(); }
|
WeakLink<T>* leakLink() { return m_link.leakRef(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WeakPtr(RetainPtr<WeakLink<T>>&& link) : m_link(std::move(link)) { }
|
WeakPtr(RetainPtr<WeakLink<T>>&& link) : m_link(move(link)) { }
|
||||||
|
|
||||||
RetainPtr<WeakLink<T>> m_link;
|
RetainPtr<WeakLink<T>> m_link;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
#include "Rect.h"
|
#include "Rect.h"
|
||||||
|
#include "Size.h"
|
||||||
|
|
||||||
class AbstractScreen : public Object {
|
class AbstractScreen : public Object {
|
||||||
public:
|
public:
|
||||||
|
@ -12,6 +13,7 @@ public:
|
||||||
|
|
||||||
static AbstractScreen& the();
|
static AbstractScreen& the();
|
||||||
|
|
||||||
|
Size size() const { return { width(), height() }; }
|
||||||
Rect rect() const { return { 0, 0, width(), height() }; }
|
Rect rect() const { return { 0, 0, width(), height() }; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "Widget.h"
|
#include "Widget.h"
|
||||||
#include <AK/AKString.h>
|
#include <AK/AKString.h>
|
||||||
|
#include <AK/Function.h>
|
||||||
|
|
||||||
class Button final : public Widget {
|
class Button final : public Widget {
|
||||||
public:
|
public:
|
||||||
|
@ -11,7 +12,7 @@ public:
|
||||||
String caption() const { return m_caption; }
|
String caption() const { return m_caption; }
|
||||||
void setCaption(String&&);
|
void setCaption(String&&);
|
||||||
|
|
||||||
std::function<void(Button&)> onClick;
|
Function<void(Button&)> onClick;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void paintEvent(PaintEvent&) override;
|
virtual void paintEvent(PaintEvent&) override;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "FrameBufferSDL.h"
|
#include "FrameBufferSDL.h"
|
||||||
|
#include "GraphicsBitmap.h"
|
||||||
#include <AK/Assertions.h>
|
#include <AK/Assertions.h>
|
||||||
|
|
||||||
FrameBufferSDL* s_the = nullptr;
|
FrameBufferSDL* s_the = nullptr;
|
||||||
|
@ -57,3 +58,27 @@ void FrameBufferSDL::initializeSDL()
|
||||||
SDL_UpdateWindowSurface(m_window);
|
SDL_UpdateWindowSurface(m_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dword* FrameBufferSDL::scanline(int y)
|
||||||
|
{
|
||||||
|
return (dword*)(((byte*)m_surface->pixels) + (y * m_surface->pitch));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameBufferSDL::blit(const Point& position, GraphicsBitmap& bitmap)
|
||||||
|
{
|
||||||
|
Rect dst_rect(position, bitmap.size());
|
||||||
|
|
||||||
|
printf("blit at %d,%d %dx%d\n", dst_rect.x(), dst_rect.y(), dst_rect.width(), dst_rect.height());
|
||||||
|
dst_rect.intersect(rect());
|
||||||
|
printf(" -> intersection %d,%d %dx%d\n", dst_rect.x(), dst_rect.y(), dst_rect.width(), dst_rect.height());
|
||||||
|
|
||||||
|
for (int y = 0; y < dst_rect.height(); ++y) {
|
||||||
|
auto* framebuffer_scanline = scanline(position.y() + y);
|
||||||
|
auto* bitmap_scanline = bitmap.scanline(y);
|
||||||
|
memcpy(framebuffer_scanline + position.x(), bitmap_scanline, dst_rect.width() * 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameBufferSDL::flush()
|
||||||
|
{
|
||||||
|
SDL_UpdateWindowSurface(m_window);
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include "AbstractScreen.h"
|
#include "AbstractScreen.h"
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
|
class GraphicsBitmap;
|
||||||
|
|
||||||
class FrameBufferSDL final : public AbstractScreen {
|
class FrameBufferSDL final : public AbstractScreen {
|
||||||
public:
|
public:
|
||||||
FrameBufferSDL(unsigned width, unsigned height);
|
FrameBufferSDL(unsigned width, unsigned height);
|
||||||
|
@ -15,6 +17,11 @@ public:
|
||||||
|
|
||||||
static FrameBufferSDL& the();
|
static FrameBufferSDL& the();
|
||||||
|
|
||||||
|
dword* scanline(int y);
|
||||||
|
|
||||||
|
void blit(const Point&, GraphicsBitmap&);
|
||||||
|
void flush();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initializeSDL();
|
void initializeSDL();
|
||||||
|
|
||||||
|
|
25
Widgets/GraphicsBitmap.cpp
Normal file
25
Widgets/GraphicsBitmap.cpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#include "GraphicsBitmap.h"
|
||||||
|
#include <AK/kmalloc.h>
|
||||||
|
|
||||||
|
RetainPtr<GraphicsBitmap> GraphicsBitmap::create(const Size& size)
|
||||||
|
{
|
||||||
|
return adopt(*new GraphicsBitmap(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsBitmap::GraphicsBitmap(const Size& size)
|
||||||
|
: m_size(size)
|
||||||
|
{
|
||||||
|
m_data = (byte*)kmalloc(size.width() * size.height() * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsBitmap::~GraphicsBitmap()
|
||||||
|
{
|
||||||
|
kfree(m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
dword* GraphicsBitmap::scanline(int y)
|
||||||
|
{
|
||||||
|
unsigned pitch = m_size.width() * 4;
|
||||||
|
return (dword*)(((byte*)m_data) + (y * pitch));
|
||||||
|
}
|
||||||
|
|
23
Widgets/GraphicsBitmap.h
Normal file
23
Widgets/GraphicsBitmap.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Size.h"
|
||||||
|
#include <AK/Retainable.h>
|
||||||
|
#include <AK/RetainPtr.h>
|
||||||
|
|
||||||
|
class GraphicsBitmap : public Retainable<GraphicsBitmap> {
|
||||||
|
public:
|
||||||
|
static RetainPtr<GraphicsBitmap> create(const Size&);
|
||||||
|
~GraphicsBitmap();
|
||||||
|
|
||||||
|
dword* scanline(int y);
|
||||||
|
|
||||||
|
Size size() const { return m_size; }
|
||||||
|
int width() const { return m_size.width(); }
|
||||||
|
int height() const { return m_size.height(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit GraphicsBitmap(const Size&);
|
||||||
|
|
||||||
|
Size m_size;
|
||||||
|
byte* m_data { nullptr };
|
||||||
|
};
|
|
@ -11,6 +11,7 @@ VFS_OBJS = \
|
||||||
FrameBufferSDL.o \
|
FrameBufferSDL.o \
|
||||||
EventLoop.o \
|
EventLoop.o \
|
||||||
EventLoopSDL.o \
|
EventLoopSDL.o \
|
||||||
|
Rect.o \
|
||||||
Object.o \
|
Object.o \
|
||||||
Widget.o \
|
Widget.o \
|
||||||
RootWidget.o \
|
RootWidget.o \
|
||||||
|
@ -28,6 +29,7 @@ VFS_OBJS = \
|
||||||
ListBox.o \
|
ListBox.o \
|
||||||
TextBox.o \
|
TextBox.o \
|
||||||
MsgBox.o \
|
MsgBox.o \
|
||||||
|
GraphicsBitmap.o \
|
||||||
test.o
|
test.o
|
||||||
|
|
||||||
OBJS = $(AK_OBJS) $(VFS_OBJS)
|
OBJS = $(AK_OBJS) $(VFS_OBJS)
|
||||||
|
|
|
@ -11,28 +11,18 @@ Painter::Painter(Widget& widget)
|
||||||
: m_widget(widget)
|
: m_widget(widget)
|
||||||
, m_font(&widget.font())
|
, m_font(&widget.font())
|
||||||
{
|
{
|
||||||
if (auto* window = widget.window()) {
|
m_target = widget.backing();
|
||||||
m_translation = window->position();
|
ASSERT(m_target);
|
||||||
m_translation.moveBy(widget.relativePosition());
|
m_window = widget.window();
|
||||||
} else {
|
m_translation.moveBy(widget.relativePosition());
|
||||||
m_translation.setX(widget.x());
|
|
||||||
m_translation.setY(widget.y());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_clipRect.setWidth(AbstractScreen::the().width());
|
m_clipRect.setWidth(AbstractScreen::the().width());
|
||||||
m_clipRect.setHeight(AbstractScreen::the().height());
|
m_clipRect.setHeight(AbstractScreen::the().height());
|
||||||
}
|
}
|
||||||
|
|
||||||
Painter::~Painter()
|
Painter::~Painter()
|
||||||
{
|
{
|
||||||
int rc = SDL_UpdateWindowSurface(FrameBufferSDL::the().window());
|
if (m_window)
|
||||||
ASSERT(rc == 0);
|
m_window->did_paint();
|
||||||
}
|
|
||||||
|
|
||||||
static dword* scanline(int y)
|
|
||||||
{
|
|
||||||
auto& surface = *FrameBufferSDL::the().surface();
|
|
||||||
return (dword*)(((byte*)surface.pixels) + (y * surface.pitch));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Painter::fillRect(const Rect& rect, Color color)
|
void Painter::fillRect(const Rect& rect, Color color)
|
||||||
|
@ -41,7 +31,7 @@ void Painter::fillRect(const Rect& rect, Color color)
|
||||||
r.moveBy(m_translation);
|
r.moveBy(m_translation);
|
||||||
|
|
||||||
for (int y = max(r.top(), m_clipRect.top()); y < min(r.bottom(), m_clipRect.bottom()); ++y) {
|
for (int y = max(r.top(), m_clipRect.top()); y < min(r.bottom(), m_clipRect.bottom()); ++y) {
|
||||||
dword* bits = scanline(y);
|
dword* bits = m_target->scanline(y);
|
||||||
for (int x = max(r.left(), m_clipRect.left()); x < min(r.right(), m_clipRect.right()); ++x) {
|
for (int x = max(r.left(), m_clipRect.left()); x < min(r.right(), m_clipRect.right()); ++x) {
|
||||||
bits[x] = color.value();
|
bits[x] = color.value();
|
||||||
}
|
}
|
||||||
|
@ -54,7 +44,7 @@ void Painter::drawRect(const Rect& rect, Color color)
|
||||||
r.moveBy(m_translation);
|
r.moveBy(m_translation);
|
||||||
|
|
||||||
for (int y = max(r.top(), m_clipRect.top()); y < min(r.bottom(), m_clipRect.bottom()); ++y) {
|
for (int y = max(r.top(), m_clipRect.top()); y < min(r.bottom(), m_clipRect.bottom()); ++y) {
|
||||||
dword* bits = scanline(y);
|
dword* bits = m_target->scanline(y);
|
||||||
if (y == r.top() || y == (r.bottom() - 1)) {
|
if (y == r.top() || y == (r.bottom() - 1)) {
|
||||||
for (int x = max(r.left(), m_clipRect.left()); x < min(r.right(), m_clipRect.right()); ++x) {
|
for (int x = max(r.left(), m_clipRect.left()); x < min(r.right(), m_clipRect.right()); ++x) {
|
||||||
bits[x] = color.value();
|
bits[x] = color.value();
|
||||||
|
@ -74,7 +64,7 @@ void Painter::xorRect(const Rect& rect, Color color)
|
||||||
r.moveBy(m_translation);
|
r.moveBy(m_translation);
|
||||||
|
|
||||||
for (int y = max(r.top(), m_clipRect.top()); y < min(r.bottom(), m_clipRect.bottom()); ++y) {
|
for (int y = max(r.top(), m_clipRect.top()); y < min(r.bottom(), m_clipRect.bottom()); ++y) {
|
||||||
dword* bits = scanline(y);
|
dword* bits = m_target->scanline(y);
|
||||||
if (y == r.top() || y == (r.bottom() - 1)) {
|
if (y == r.top() || y == (r.bottom() - 1)) {
|
||||||
for (int x = max(r.left(), m_clipRect.left()); x < min(r.right(), m_clipRect.right()); ++x) {
|
for (int x = max(r.left(), m_clipRect.left()); x < min(r.right(), m_clipRect.right()); ++x) {
|
||||||
bits[x] ^= color.value();
|
bits[x] ^= color.value();
|
||||||
|
@ -96,7 +86,7 @@ void Painter::drawBitmap(const Point& p, const CBitmap& bitmap, Color color)
|
||||||
int y = point.y() + row;
|
int y = point.y() + row;
|
||||||
if (y < m_clipRect.top() || y >= m_clipRect.bottom())
|
if (y < m_clipRect.top() || y >= m_clipRect.bottom())
|
||||||
break;
|
break;
|
||||||
dword* bits = scanline(y);
|
dword* bits = m_target->scanline(y);
|
||||||
for (unsigned j = 0; j < bitmap.width(); ++j) {
|
for (unsigned j = 0; j < bitmap.width(); ++j) {
|
||||||
int x = point.x() + j;
|
int x = point.x() + j;
|
||||||
if (x < m_clipRect.left() || x >= m_clipRect.right())
|
if (x < m_clipRect.left() || x >= m_clipRect.right())
|
||||||
|
@ -143,7 +133,7 @@ void Painter::drawPixel(const Point& p, Color color)
|
||||||
point.moveBy(m_translation);
|
point.moveBy(m_translation);
|
||||||
if (!m_clipRect.contains(point))
|
if (!m_clipRect.contains(point))
|
||||||
return;
|
return;
|
||||||
scanline(point.y())[point.x()] = color.value();
|
m_target->scanline(point.y())[point.x()] = color.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Painter::drawLine(const Point& p1, const Point& p2, Color color)
|
void Painter::drawLine(const Point& p1, const Point& p2, Color color)
|
||||||
|
@ -162,7 +152,7 @@ void Painter::drawLine(const Point& p1, const Point& p2, Color color)
|
||||||
if (point1.y() > point2.y())
|
if (point1.y() > point2.y())
|
||||||
std::swap(point1, point2);
|
std::swap(point1, point2);
|
||||||
for (int y = max(point1.y(), m_clipRect.top()); y <= min(point2.y(), m_clipRect.bottom()); ++y)
|
for (int y = max(point1.y(), m_clipRect.top()); y <= min(point2.y(), m_clipRect.bottom()); ++y)
|
||||||
scanline(y)[x] = color.value();
|
m_target->scanline(y)[x] = color.value();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +166,7 @@ void Painter::drawLine(const Point& p1, const Point& p2, Color color)
|
||||||
return;
|
return;
|
||||||
if (point1.x() > point2.x())
|
if (point1.x() > point2.x())
|
||||||
std::swap(point1, point2);
|
std::swap(point1, point2);
|
||||||
auto* pixels = scanline(point1.y());
|
auto* pixels = m_target->scanline(point1.y());
|
||||||
for (int x = max(point1.x(), m_clipRect.left()); x <= min(point2.x(), m_clipRect.right()); ++x)
|
for (int x = max(point1.x(), m_clipRect.left()); x <= min(point2.x(), m_clipRect.right()); ++x)
|
||||||
pixels[x] = color.value();
|
pixels[x] = color.value();
|
||||||
return;
|
return;
|
||||||
|
@ -193,7 +183,7 @@ void Painter::drawLine(const Point& p1, const Point& p2, Color color)
|
||||||
|
|
||||||
int y = point1.y();
|
int y = point1.y();
|
||||||
for (int x = point1.x(); x <= point2.x(); ++x) {
|
for (int x = point1.x(); x <= point2.x(); ++x) {
|
||||||
scanline(y)[x] = color.value();
|
m_target->scanline(y)[x] = color.value();
|
||||||
error += deltaError;
|
error += deltaError;
|
||||||
if (error >= 0.5) {
|
if (error >= 0.5) {
|
||||||
y = (double)y + yStep;
|
y = (double)y + yStep;
|
||||||
|
|
|
@ -7,8 +7,10 @@
|
||||||
#include <AK/AKString.h>
|
#include <AK/AKString.h>
|
||||||
|
|
||||||
class CBitmap;
|
class CBitmap;
|
||||||
|
class GraphicsBitmap;
|
||||||
class Font;
|
class Font;
|
||||||
class Widget;
|
class Widget;
|
||||||
|
class Window;
|
||||||
|
|
||||||
class Painter {
|
class Painter {
|
||||||
public:
|
public:
|
||||||
|
@ -32,6 +34,7 @@ private:
|
||||||
Widget& m_widget;
|
Widget& m_widget;
|
||||||
const Font* m_font;
|
const Font* m_font;
|
||||||
Point m_translation;
|
Point m_translation;
|
||||||
|
|
||||||
Rect m_clipRect;
|
Rect m_clipRect;
|
||||||
|
RetainPtr<GraphicsBitmap> m_target;
|
||||||
|
Window* m_window { nullptr };
|
||||||
};
|
};
|
||||||
|
|
21
Widgets/Rect.cpp
Normal file
21
Widgets/Rect.cpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#include "Rect.h"
|
||||||
|
#include <AK/StdLibExtras.h>
|
||||||
|
|
||||||
|
void Rect::intersect(const Rect& other)
|
||||||
|
{
|
||||||
|
int l = max(left(), other.left());
|
||||||
|
int r = min(right(), other.right());
|
||||||
|
int t = max(top(), other.top());
|
||||||
|
int b = min(bottom(), other.bottom());
|
||||||
|
|
||||||
|
if (l >= r || t >= b) {
|
||||||
|
m_location = { };
|
||||||
|
m_size = { };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_location.setX(l);
|
||||||
|
m_location.setY(t);
|
||||||
|
m_size.setWidth(r - l);
|
||||||
|
m_size.setHeight(b - t);
|
||||||
|
}
|
|
@ -1,14 +1,19 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Point.h"
|
#include "Point.h"
|
||||||
|
#include "Size.h"
|
||||||
|
|
||||||
class Rect {
|
class Rect {
|
||||||
public:
|
public:
|
||||||
Rect() { }
|
Rect() { }
|
||||||
Rect(int x, int y, int width, int height)
|
Rect(int x, int y, int width, int height)
|
||||||
: m_location(x, y)
|
: m_location(x, y)
|
||||||
, m_width(width)
|
, m_size(width, height)
|
||||||
, m_height(height)
|
{
|
||||||
|
}
|
||||||
|
Rect(const Point& location, const Size& size)
|
||||||
|
: m_location(location)
|
||||||
|
, m_size(size)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,25 +90,33 @@ public:
|
||||||
|
|
||||||
int x() const { return location().x(); }
|
int x() const { return location().x(); }
|
||||||
int y() const { return location().y(); }
|
int y() const { return location().y(); }
|
||||||
int width() const { return m_width; }
|
int width() const { return m_size.width(); }
|
||||||
int height() const { return m_height; }
|
int height() const { return m_size.height(); }
|
||||||
|
|
||||||
void setX(int x) { m_location.setX(x); }
|
void setX(int x) { m_location.setX(x); }
|
||||||
void setY(int y) { m_location.setY(y); }
|
void setY(int y) { m_location.setY(y); }
|
||||||
void setWidth(int width) { m_width = width; }
|
void setWidth(int width) { m_size.setWidth(width); }
|
||||||
void setHeight(int height) { m_height = height; }
|
void setHeight(int height) { m_size.setHeight(height); }
|
||||||
|
|
||||||
Point location() const { return m_location; }
|
Point location() const { return m_location; }
|
||||||
|
Size size() const { return m_size; }
|
||||||
|
|
||||||
bool operator==(const Rect& other) const
|
bool operator==(const Rect& other) const
|
||||||
{
|
{
|
||||||
return m_location == other.m_location
|
return m_location == other.m_location
|
||||||
&& m_width == other.m_width
|
&& m_size == other.m_size;
|
||||||
&& m_height == other.m_height;
|
}
|
||||||
|
|
||||||
|
void intersect(const Rect&);
|
||||||
|
|
||||||
|
static Rect intersection(const Rect& a, const Rect& b)
|
||||||
|
{
|
||||||
|
Rect r(a);
|
||||||
|
r.intersect(b);
|
||||||
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Point m_location;
|
Point m_location;
|
||||||
int m_width { 0 };
|
Size m_size;
|
||||||
int m_height { 0 };
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include "AbstractScreen.h"
|
||||||
|
#include "GraphicsBitmap.h"
|
||||||
#include "RootWidget.h"
|
#include "RootWidget.h"
|
||||||
#include "Painter.h"
|
#include "Painter.h"
|
||||||
#include "WindowManager.h"
|
#include "WindowManager.h"
|
||||||
|
@ -5,6 +7,7 @@
|
||||||
|
|
||||||
RootWidget::RootWidget()
|
RootWidget::RootWidget()
|
||||||
{
|
{
|
||||||
|
m_backing = GraphicsBitmap::create(AbstractScreen::the().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
RootWidget::~RootWidget()
|
RootWidget::~RootWidget()
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include "Widget.h"
|
#include "Widget.h"
|
||||||
|
|
||||||
|
class GraphicsBitmap;
|
||||||
|
|
||||||
class RootWidget final : public Widget {
|
class RootWidget final : public Widget {
|
||||||
public:
|
public:
|
||||||
RootWidget();
|
RootWidget();
|
||||||
|
@ -10,4 +12,8 @@ public:
|
||||||
private:
|
private:
|
||||||
virtual void paintEvent(PaintEvent&) override;
|
virtual void paintEvent(PaintEvent&) override;
|
||||||
virtual void mouseMoveEvent(MouseEvent&) override;
|
virtual void mouseMoveEvent(MouseEvent&) override;
|
||||||
|
|
||||||
|
virtual GraphicsBitmap* backing() override { return m_backing.ptr(); }
|
||||||
|
|
||||||
|
RetainPtr<GraphicsBitmap> m_backing;
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,6 +13,12 @@ public:
|
||||||
void setWidth(int w) { m_width = w; }
|
void setWidth(int w) { m_width = w; }
|
||||||
void setHeight(int h) { m_height = h; }
|
void setHeight(int h) { m_height = h; }
|
||||||
|
|
||||||
|
bool operator==(const Size& other) const
|
||||||
|
{
|
||||||
|
return m_width == other.m_width &&
|
||||||
|
m_height == other.m_height;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_width { 0 };
|
int m_width { 0 };
|
||||||
int m_height { 0 };
|
int m_height { 0 };
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "Widget.h"
|
#include "Widget.h"
|
||||||
#include "Event.h"
|
#include "Event.h"
|
||||||
#include "EventLoop.h"
|
#include "EventLoop.h"
|
||||||
|
#include "GraphicsBitmap.h"
|
||||||
#include "WindowManager.h"
|
#include "WindowManager.h"
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
#include "Painter.h"
|
#include "Painter.h"
|
||||||
|
@ -155,3 +156,10 @@ void Widget::setFont(RetainPtr<Font>&& font)
|
||||||
else
|
else
|
||||||
m_font = std::move(font);
|
m_font = std::move(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GraphicsBitmap* Widget::backing()
|
||||||
|
{
|
||||||
|
if (auto* w = window())
|
||||||
|
return w->backing();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
#include "Color.h"
|
#include "Color.h"
|
||||||
#include "Font.h"
|
#include "Font.h"
|
||||||
#include <AK/AKString.h>
|
#include <AK/AKString.h>
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
|
class GraphicsBitmap;
|
||||||
class Window;
|
class Window;
|
||||||
|
|
||||||
class Widget : public Object {
|
class Widget : public Object {
|
||||||
|
@ -15,7 +15,7 @@ public:
|
||||||
explicit Widget(Widget* parent = nullptr);
|
explicit Widget(Widget* parent = nullptr);
|
||||||
virtual ~Widget();
|
virtual ~Widget();
|
||||||
|
|
||||||
virtual void event(Event&);
|
virtual void event(Event&) override;
|
||||||
virtual void paintEvent(PaintEvent&);
|
virtual void paintEvent(PaintEvent&);
|
||||||
virtual void showEvent(ShowEvent&);
|
virtual void showEvent(ShowEvent&);
|
||||||
virtual void hideEvent(HideEvent&);
|
virtual void hideEvent(HideEvent&);
|
||||||
|
@ -83,6 +83,8 @@ public:
|
||||||
const Font& font() const { return *m_font; }
|
const Font& font() const { return *m_font; }
|
||||||
void setFont(RetainPtr<Font>&&);
|
void setFont(RetainPtr<Font>&&);
|
||||||
|
|
||||||
|
virtual GraphicsBitmap* backing();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Window* m_window { nullptr };
|
Window* m_window { nullptr };
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ void Window::setTitle(String&& title)
|
||||||
if (m_title == title)
|
if (m_title == title)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_title = std::move(title);
|
m_title = move(title);
|
||||||
WindowManager::the().notifyTitleChanged(*this);
|
WindowManager::the().notifyTitleChanged(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ void Window::setRect(const Rect& rect)
|
||||||
return;
|
return;
|
||||||
auto oldRect = m_rect;
|
auto oldRect = m_rect;
|
||||||
m_rect = rect;
|
m_rect = rect;
|
||||||
|
m_backing = GraphicsBitmap::create(m_rect.size());
|
||||||
WindowManager::the().notifyRectChanged(*this, oldRect, m_rect);
|
WindowManager::the().notifyRectChanged(*this, oldRect, m_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,6 +96,11 @@ void Window::event(Event& event)
|
||||||
return Object::event(event);
|
return Object::event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Window::did_paint()
|
||||||
|
{
|
||||||
|
WindowManager::the().did_paint(*this);
|
||||||
|
}
|
||||||
|
|
||||||
bool Window::isActive() const
|
bool Window::isActive() const
|
||||||
{
|
{
|
||||||
return WindowManager::the().activeWindow() == this;
|
return WindowManager::the().activeWindow() == this;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
#include "Rect.h"
|
#include "Rect.h"
|
||||||
|
#include "GraphicsBitmap.h"
|
||||||
#include <AK/AKString.h>
|
#include <AK/AKString.h>
|
||||||
#include <AK/WeakPtr.h>
|
#include <AK/WeakPtr.h>
|
||||||
|
|
||||||
|
@ -50,6 +51,10 @@ public:
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
|
GraphicsBitmap* backing() { return m_backing.ptr(); }
|
||||||
|
|
||||||
|
void did_paint();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
String m_title;
|
String m_title;
|
||||||
Rect m_rect;
|
Rect m_rect;
|
||||||
|
@ -57,5 +62,7 @@ private:
|
||||||
bool m_isBeingDragged { false };
|
bool m_isBeingDragged { false };
|
||||||
|
|
||||||
WeakPtr<Widget> m_focusedWidget;
|
WeakPtr<Widget> m_focusedWidget;
|
||||||
|
|
||||||
|
RetainPtr<GraphicsBitmap> m_backing;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "AbstractScreen.h"
|
#include "AbstractScreen.h"
|
||||||
#include "TerminalWidget.h"
|
#include "TerminalWidget.h"
|
||||||
#include "EventLoop.h"
|
#include "EventLoop.h"
|
||||||
|
#include "FrameBufferSDL.h"
|
||||||
|
|
||||||
extern TerminalWidget* g_tw;
|
extern TerminalWidget* g_tw;
|
||||||
|
|
||||||
|
@ -131,6 +132,17 @@ void WindowManager::repaint()
|
||||||
handlePaintEvent(*make<PaintEvent>());
|
handlePaintEvent(*make<PaintEvent>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WindowManager::did_paint(Window& window)
|
||||||
|
{
|
||||||
|
auto& framebuffer = FrameBufferSDL::the();
|
||||||
|
framebuffer.blit({ 0, 0 }, *m_rootWidget->backing());
|
||||||
|
for (auto* window : m_windows) {
|
||||||
|
ASSERT(window->backing());
|
||||||
|
framebuffer.blit(window->position(), *window->backing());
|
||||||
|
}
|
||||||
|
framebuffer.flush();
|
||||||
|
}
|
||||||
|
|
||||||
void WindowManager::removeWindow(Window& window)
|
void WindowManager::removeWindow(Window& window)
|
||||||
{
|
{
|
||||||
if (!m_windows.contains(&window))
|
if (!m_windows.contains(&window))
|
||||||
|
@ -239,7 +251,6 @@ void WindowManager::processMouseEvent(MouseEvent& event)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::handlePaintEvent(PaintEvent& event)
|
void WindowManager::handlePaintEvent(PaintEvent& event)
|
||||||
|
@ -255,6 +266,14 @@ void WindowManager::handlePaintEvent(PaintEvent& event)
|
||||||
|
|
||||||
for (auto* window : m_windows)
|
for (auto* window : m_windows)
|
||||||
window->event(event);
|
window->event(event);
|
||||||
|
|
||||||
|
auto& framebuffer = FrameBufferSDL::the();
|
||||||
|
framebuffer.blit({ 0, 0 }, *m_rootWidget->backing());
|
||||||
|
for (auto* window : m_windows) {
|
||||||
|
ASSERT(window->backing());
|
||||||
|
framebuffer.blit(window->position(), *window->backing());
|
||||||
|
}
|
||||||
|
framebuffer.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::event(Event& event)
|
void WindowManager::event(Event& event)
|
||||||
|
|
|
@ -29,6 +29,8 @@ public:
|
||||||
|
|
||||||
bool isVisible(Window&) const;
|
bool isVisible(Window&) const;
|
||||||
|
|
||||||
|
void did_paint(Window&);
|
||||||
|
|
||||||
void repaint();
|
void repaint();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue