Fix issue with overlays on macOS w/the new async painting (fix #1931)

Fixed regression introduced in d20436f9570302e20484b51435276dc9bad94009.
Now overlays are kept on the screen and the overlapped area is restored
just in time when we have to re-paint some widget on that area.
This commit is contained in:
David Capello 2018-11-15 15:42:50 -03:00
parent 52e2585c2c
commit 9b2889ef66
6 changed files with 62 additions and 39 deletions

View File

@ -1,3 +1,4 @@
Copyright (C) 2018 Igara Studio S.A.
Copyright (c) 2001-2018 David Capello
Permission is hereby granted, free of charge, to any person obtaining

View File

@ -243,7 +243,6 @@ void Manager::flipDisplay()
update_cursor_overlay();
// Draw overlays.
overlays->captureOverlappedAreas();
overlays->drawOverlays();
// Flip dirty region.
@ -257,8 +256,6 @@ void Manager::flipDisplay()
m_dirtyRegion.clear();
}
overlays->restoreOverlappedAreas();
}
bool Manager::generateMessages()
@ -1483,6 +1480,10 @@ bool Manager::sendMessageToWidget(Message* msg, Widget* widget)
return false;
PaintMessage* paintMsg = static_cast<PaintMessage*>(msg);
// Restore overlays in the region that we're going to paint.
OverlayManager::instance()->restoreOverlappedAreas(paintMsg->rect());
os::Surface* surface = m_display->getSurface();
surface->saveClip();

View File

@ -1,4 +1,5 @@
// Aseprite UI Library
// Copyright (C) 2018 Igara Studio S.A.
// Copyright (C) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
@ -18,7 +19,8 @@ namespace ui {
Overlay::Overlay(os::Surface* overlaySurface, const gfx::Point& pos, ZOrder zorder)
: m_surface(overlaySurface)
, m_overlap(NULL)
, m_overlap(nullptr)
, m_captured(nullptr)
, m_pos(pos)
, m_zorder(zorder)
{
@ -26,6 +28,8 @@ Overlay::Overlay(os::Surface* overlaySurface, const gfx::Point& pos, ZOrder zord
Overlay::~Overlay()
{
ASSERT(!m_captured);
if (m_surface) {
Manager* manager = Manager::getDefault();
if (manager)
@ -54,13 +58,14 @@ gfx::Rect Overlay::bounds() const
return gfx::Rect(0, 0, 0, 0);
}
void Overlay::drawOverlay(os::Surface* screen)
void Overlay::drawOverlay()
{
if (!m_surface)
if (!m_surface ||
!m_captured)
return;
os::SurfaceLock lock(m_surface);
screen->drawRgbaSurface(m_surface, m_pos.x, m_pos.y);
m_captured->drawRgbaSurface(m_surface, m_pos.x, m_pos.y);
Manager::getDefault()->dirtyRect(
gfx::Rect(m_pos.x, m_pos.y,
@ -70,12 +75,16 @@ void Overlay::drawOverlay(os::Surface* screen)
void Overlay::moveOverlay(const gfx::Point& newPos)
{
if (m_captured)
restoreOverlappedArea(gfx::Rect());
m_pos = newPos;
}
void Overlay::captureOverlappedArea(os::Surface* screen)
{
if (!m_surface)
if (!m_surface ||
m_captured)
return;
if (!m_overlap) {
@ -88,24 +97,28 @@ void Overlay::captureOverlappedArea(os::Surface* screen)
os::SurfaceLock lock(m_overlap);
screen->blitTo(m_overlap, m_pos.x, m_pos.y, 0, 0,
m_overlap->width(), m_overlap->height());
m_captured = screen;
}
void Overlay::restoreOverlappedArea(os::Surface* screen)
void Overlay::restoreOverlappedArea(const gfx::Rect& restoreBounds)
{
if (!m_surface)
if (!m_surface ||
!m_overlap ||
!m_captured)
return;
if (!m_overlap)
if (!restoreBounds.isEmpty() &&
!restoreBounds.intersects(bounds()))
return;
os::SurfaceLock lock(m_overlap);
m_overlap->blitTo(screen, 0, 0, m_pos.x, m_pos.y,
m_overlap->blitTo(m_captured, 0, 0, m_pos.x, m_pos.y,
m_overlap->width(), m_overlap->height());
Manager::getDefault()->dirtyRect(
gfx::Rect(m_pos.x, m_pos.y,
m_overlap->width(),
m_overlap->height()));
Manager::getDefault()->dirtyRect(bounds());
m_captured = nullptr;
}
}

View File

@ -1,4 +1,5 @@
// Aseprite UI Library
// Copyright (C) 2018 Igara Studio S.A.
// Copyright (C) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
@ -34,9 +35,9 @@ namespace ui {
gfx::Rect bounds() const;
void captureOverlappedArea(os::Surface* screen);
void restoreOverlappedArea(os::Surface* screen);
void restoreOverlappedArea(const gfx::Rect& restoreBounds);
void drawOverlay(os::Surface* screen);
void drawOverlay();
void moveOverlay(const gfx::Point& newPos);
bool operator<(const Overlay& other) const {
@ -46,6 +47,11 @@ namespace ui {
private:
os::Surface* m_surface;
os::Surface* m_overlap;
// Surface where we captured the overlapped (m_overlap)
// region. It's nullptr if the overlay wasn't drawn yet.
os::Surface* m_captured;
gfx::Point m_pos;
ZOrder m_zorder;
};

View File

@ -1,5 +1,6 @@
// Aseprite UI Library
// Copyright (C) 2001-2013, 2015, 2016 David Capello
// Copyright (C) 2018 Igara Studio S.A.
// Copyright (C) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -53,46 +54,46 @@ void OverlayManager::addOverlay(Overlay* overlay)
void OverlayManager::removeOverlay(Overlay* overlay)
{
if (overlay)
overlay->restoreOverlappedArea(gfx::Rect());
iterator it = std::find(begin(), end(), overlay);
ASSERT(it != end());
if (it != end())
m_overlays.erase(it);
}
void OverlayManager::captureOverlappedAreas()
void OverlayManager::restoreOverlappedAreas(const gfx::Rect& restoreBounds)
{
if (m_overlays.empty())
return;
// TODO can we remove this?
Manager* manager = Manager::getDefault();
if (!manager)
return;
os::Surface* displaySurface = manager->getDisplay()->getSurface();
os::SurfaceLock lock(displaySurface);
for (Overlay* overlay : *this)
overlay->captureOverlappedArea(displaySurface);
}
void OverlayManager::restoreOverlappedAreas()
{
Manager* manager = Manager::getDefault();
if (!manager)
return;
os::Surface* displaySurface = manager->getDisplay()->getSurface();
os::SurfaceLock lock(displaySurface);
for (Overlay* overlay : *this)
overlay->restoreOverlappedArea(displaySurface);
overlay->restoreOverlappedArea(restoreBounds);
}
void OverlayManager::drawOverlays()
{
if (m_overlays.empty())
return;
Manager* manager = Manager::getDefault();
if (!manager)
return;
os::Surface* displaySurface = manager->getDisplay()->getSurface();
os::SurfaceLock lock(displaySurface);
for (Overlay* overlay : *this)
overlay->drawOverlay(displaySurface);
overlay->captureOverlappedArea(displaySurface);
for (Overlay* overlay : *this)
overlay->drawOverlay();
}
} // namespace ui

View File

@ -1,5 +1,6 @@
// Aseprite UI Library
// Copyright (C) 2001-2013, 2015 David Capello
// Copyright (C) 2018 Igara Studio S.A.
// Copyright (C) 2001-2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -8,6 +9,7 @@
#define UI_OVERLAY_MANAGER_H_INCLUDED
#pragma once
#include "gfx/rect.h"
#include "ui/base.h"
#include <vector>
@ -30,9 +32,8 @@ namespace ui {
void addOverlay(Overlay* overlay);
void removeOverlay(Overlay* overlay);
void captureOverlappedAreas();
void restoreOverlappedAreas();
void drawOverlays();
void restoreOverlappedAreas(const gfx::Rect& bounds);
private:
static void destroyInstance();