summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2018-10-12 19:39:48 +0200
committerAndreas Kling <awesomekling@gmail.com>2018-10-12 19:39:48 +0200
commit6f9e0e3876a60562fdc20496767ebf17cbb89f02 (patch)
tree939943819f0ea51a9f33fe2f033114f620e2de1f
parent74aa4d53453843280413cb3a12b274c322c0cbf7 (diff)
downloadserenity-6f9e0e3876a60562fdc20496767ebf17cbb89f02.zip
After moving a window, try to repaint a bit less.
Only repaint windows that intersect either the old or the new rect. Also only repaint those rects in the root widget.
-rw-r--r--Widgets/Event.h9
-rw-r--r--Widgets/Rect.h8
-rw-r--r--Widgets/RootWidget.cpp11
-rw-r--r--Widgets/Widget.cpp7
-rw-r--r--Widgets/Widget.h1
-rw-r--r--Widgets/Window.cpp20
-rw-r--r--Widgets/Window.h2
-rw-r--r--Widgets/WindowManager.cpp71
-rw-r--r--Widgets/WindowManager.h5
9 files changed, 111 insertions, 23 deletions
diff --git a/Widgets/Event.h b/Widgets/Event.h
index 6de27b79e0..917a6960bc 100644
--- a/Widgets/Event.h
+++ b/Widgets/Event.h
@@ -2,6 +2,7 @@
#include <AK/Types.h>
#include "Point.h"
+#include "Rect.h"
static const char* eventNames[] = {
"Invalid",
@@ -61,10 +62,16 @@ public:
class PaintEvent final : public Event {
public:
- PaintEvent()
+ explicit PaintEvent(const Rect& rect = Rect())
: Event(Event::Paint)
+ , m_rect(rect)
{
}
+
+ const Rect& rect() const { return m_rect; }
+private:
+ friend class WindowManager;
+ Rect m_rect;
};
class ShowEvent final : public Event {
diff --git a/Widgets/Rect.h b/Widgets/Rect.h
index d61ae16f7f..98b0d865ff 100644
--- a/Widgets/Rect.h
+++ b/Widgets/Rect.h
@@ -67,6 +67,14 @@ public:
setY(top);
}
+ bool intersects(const Rect& other) const
+ {
+ return left() < other.right()
+ && other.left() < right()
+ && top() < other.bottom()
+ && other.top() < bottom();
+ }
+
int x() const { return location().x(); }
int y() const { return location().y(); }
int width() const { return m_width; }
diff --git a/Widgets/RootWidget.cpp b/Widgets/RootWidget.cpp
index ed9c6ce891..79666c110b 100644
--- a/Widgets/RootWidget.cpp
+++ b/Widgets/RootWidget.cpp
@@ -13,10 +13,15 @@ RootWidget::~RootWidget()
void RootWidget::onPaint(PaintEvent& event)
{
- //printf("RootWidget::onPaint\n");
- Painter painter(*this);
- painter.fillRect(Rect(0, 0, 800, 600), Color(0x40, 0x40, 0x40));
Widget::onPaint(event);
+
+ printf("RootWidget::onPaint: %d,%d %dx%d\n",
+ event.rect().x(),
+ event.rect().y(),
+ event.rect().width(),
+ event.rect().height());
+ Painter painter(*this);
+ painter.fillRect(event.rect(), Color(0x40, 0x40, 0x40));
}
void RootWidget::onMouseMove(MouseEvent& event)
diff --git a/Widgets/Widget.cpp b/Widgets/Widget.cpp
index f5a66e79f1..a742ba6461 100644
--- a/Widgets/Widget.cpp
+++ b/Widgets/Widget.cpp
@@ -23,6 +23,11 @@ void Widget::setWindowRelativeRect(const Rect& rect)
update();
}
+void Widget::repaint(const Rect& rect)
+{
+ event(*make<PaintEvent>(rect));
+}
+
void Widget::event(Event& event)
{
switch (event.type()) {
@@ -94,7 +99,7 @@ void Widget::update()
if (m_hasPendingPaintEvent)
return;
m_hasPendingPaintEvent = true;
- EventLoop::main().postEvent(this, make<PaintEvent>());
+ EventLoop::main().postEvent(this, make<PaintEvent>(rect()));
}
Widget::HitTestResult Widget::hitTest(int x, int y)
diff --git a/Widgets/Widget.h b/Widgets/Widget.h
index 2979c529e1..804f3332ec 100644
--- a/Widgets/Widget.h
+++ b/Widgets/Widget.h
@@ -34,6 +34,7 @@ public:
Rect rect() const { return { 0, 0, width(), height() }; }
void update();
+ void repaint(const Rect&);
struct HitTestResult {
Widget* widget { nullptr };
diff --git a/Widgets/Window.cpp b/Widgets/Window.cpp
index 2e0b95746e..4848a89c9b 100644
--- a/Widgets/Window.cpp
+++ b/Widgets/Window.cpp
@@ -41,6 +41,11 @@ void Window::setRect(const Rect& rect)
WindowManager::the().notifyRectChanged(*this, oldRect, m_rect);
}
+void Window::repaint()
+{
+ event(*make<PaintEvent>());
+}
+
void Window::event(Event& event)
{
if (event.isMouseEvent()) {
@@ -58,12 +63,23 @@ void Window::event(Event& event)
}
if (event.isPaintEvent()) {
+ auto& pe = static_cast<PaintEvent&>(event);
+ printf("Window[\"%s\"]: paintEvent %d,%d %dx%d\n", className(),
+ pe.rect().x(),
+ pe.rect().y(),
+ pe.rect().width(),
+ pe.rect().height());
+
if (isBeingDragged()) {
// Ignore paint events during window drag.
return;
}
- if (m_mainWidget)
- return m_mainWidget->event(event);
+ if (m_mainWidget) {
+ if (pe.rect().isEmpty())
+ return m_mainWidget->event(*make<PaintEvent>(m_mainWidget->rect()));
+ else
+ return m_mainWidget->event(event);
+ }
return Object::event(event);
}
diff --git a/Widgets/Window.h b/Widgets/Window.h
index f37f75c757..1af1f96d7b 100644
--- a/Widgets/Window.h
+++ b/Widgets/Window.h
@@ -35,6 +35,8 @@ public:
bool isBeingDragged() const { return m_isBeingDragged; }
void setIsBeingDragged(bool b) { m_isBeingDragged = b; }
+ void repaint();
+
private:
String m_title;
Rect m_rect;
diff --git a/Widgets/WindowManager.cpp b/Widgets/WindowManager.cpp
index 6f1f235bb0..15104a933e 100644
--- a/Widgets/WindowManager.cpp
+++ b/Widgets/WindowManager.cpp
@@ -21,6 +21,23 @@ static inline Rect titleBarRectForWindow(const Window& window)
};
}
+static inline Rect borderRectForWindow(const Window& window)
+{
+ auto titleBarRect = titleBarRectForWindow(window);
+ return { titleBarRect.x() - 1,
+ titleBarRect.y() - 1,
+ titleBarRect.width() + 2,
+ windowFrameWidth + windowTitleBarHeight + window.rect().height() + 4
+ };
+}
+
+static inline Rect outerRectForWindow(const Window& window)
+{
+ auto rect = borderRectForWindow(window);
+ rect.inflate(2, 2);
+ return rect;
+}
+
WindowManager& WindowManager::the()
{
static WindowManager* s_the = new WindowManager;
@@ -49,7 +66,9 @@ void WindowManager::paintWindowFrame(Window& window)
//printf("[WM] paintWindowFrame {%p}, rect: %d,%d %dx%d\n", &window, window.rect().x(), window.rect().y(), window.rect().width(), window.rect().height());
- Rect topRect = titleBarRectForWindow(window);
+ auto titleBarRect = titleBarRectForWindow(window);
+ auto outerRect = outerRectForWindow(window);
+ auto borderRect = borderRectForWindow(window);
Rect bottomRect {
window.x() - windowFrameWidth,
@@ -71,12 +90,6 @@ void WindowManager::paintWindowFrame(Window& window)
window.height()
};
- Rect borderRect {
- topRect.x() - 1,
- topRect.y() - 1,
- topRect.width() + 2,
- windowFrameWidth + windowTitleBarHeight + window.rect().height() + 4
- };
if (!m_lastDragRect.isEmpty()) {
p.xorRect(m_lastDragRect, Color(255, 0, 0));
@@ -84,22 +97,20 @@ void WindowManager::paintWindowFrame(Window& window)
}
if (m_dragWindow == &window) {
- borderRect.inflate(2, 2);
- p.xorRect(borderRect, Color(255, 0, 0));
- m_lastDragRect = borderRect;
+ p.xorRect(outerRect, Color(255, 0, 0));
+ m_lastDragRect = outerRect;
return;
}
p.drawRect(borderRect, Color(255, 255, 255));
- borderRect.inflate(2, 2);
- p.drawRect(borderRect, m_windowBorderColor);
+ p.drawRect(outerRect, m_windowBorderColor);
- p.fillRect(topRect, m_windowBorderColor);
+ p.fillRect(titleBarRect, m_windowBorderColor);
p.fillRect(bottomRect, m_windowBorderColor);
p.fillRect(leftRect, m_windowBorderColor);
p.fillRect(rightRect, m_windowBorderColor);
- p.drawText(topRect, window.title(), Painter::TextAlignment::Center, m_windowTitleColor);
+ p.drawText(titleBarRect, window.title(), Painter::TextAlignment::Center, m_windowTitleColor);
}
void WindowManager::addWindow(Window& window)
@@ -124,6 +135,7 @@ void WindowManager::handleTitleBarMouseEvent(Window& window, MouseEvent& event)
m_dragWindow = &window;
m_dragOrigin = event.position();
m_dragWindowOrigin = window.position();
+ m_dragStartRect = outerRectForWindow(window);
window.setIsBeingDragged(true);
return;
}
@@ -136,14 +148,38 @@ void WindowManager::handleTitleBarMouseEvent(Window& window, MouseEvent& event)
#endif
}
+void WindowManager::repaintAfterMove(const Rect& oldRect, const Rect& newRect)
+{
+ printf("[WM] repaint: [%d,%d %dx%d] -> [%d,%d %dx%d]\n",
+ oldRect.x(),
+ oldRect.y(),
+ oldRect.width(),
+ oldRect.height(),
+ newRect.x(),
+ newRect.y(),
+ newRect.width(),
+ newRect.height());
+
+ m_rootWidget->repaint(oldRect);
+ m_rootWidget->repaint(newRect);
+ for (auto* window : m_windows) {
+ if (outerRectForWindow(*window).intersects(oldRect) || outerRectForWindow(*window).intersects(newRect)) {
+ paintWindowFrame(*window);
+ window->repaint();
+ }
+ }
+}
+
void WindowManager::processMouseEvent(MouseEvent& event)
{
if (event.type() == Event::MouseUp) {
if (m_dragWindow) {
printf("[WM] Finish dragging Window{%p}\n", m_dragWindow);
m_dragWindow->setIsBeingDragged(false);
+ m_dragEndRect = outerRectForWindow(*m_dragWindow);
m_dragWindow = nullptr;
- EventLoop::main().postEvent(this, make<PaintEvent>());
+
+ repaintAfterMove(m_dragStartRect, m_dragEndRect);
return;
}
}
@@ -179,6 +215,11 @@ void WindowManager::processMouseEvent(MouseEvent& event)
void WindowManager::handlePaintEvent(PaintEvent& event)
{
//printf("[WM] paint event\n");
+ if (event.rect().isEmpty()) {
+ event.m_rect.setWidth(AbstractScreen::the().width());
+ event.m_rect.setHeight(AbstractScreen::the().height());
+ }
+
m_rootWidget->event(event);
paintWindowFrames();
diff --git a/Widgets/WindowManager.h b/Widgets/WindowManager.h
index a81135f0fa..08995bc00d 100644
--- a/Widgets/WindowManager.h
+++ b/Widgets/WindowManager.h
@@ -29,7 +29,8 @@ private:
void processMouseEvent(MouseEvent&);
void handleTitleBarMouseEvent(Window&, MouseEvent&);
void handlePaintEvent(PaintEvent&);
-
+ void repaintAfterMove(const Rect& oldRect, const Rect& newRect);
+
virtual void event(Event&) override;
Color m_windowBorderColor;
@@ -43,4 +44,6 @@ private:
Point m_dragOrigin;
Point m_dragWindowOrigin;
Rect m_lastDragRect;
+ Rect m_dragStartRect;
+ Rect m_dragEndRect;
};