X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/5c471ed8362098ad535177010c7b15957a586234..140a68de78d89faa79e64f29179a254ab8bd2607:/lib/gui/ewidgetdesktop.cpp diff --git a/lib/gui/ewidgetdesktop.cpp b/lib/gui/ewidgetdesktop.cpp index c820610e..c89cd270 100644 --- a/lib/gui/ewidgetdesktop.cpp +++ b/lib/gui/ewidgetdesktop.cpp @@ -1,11 +1,19 @@ #include #include #include +#include + +extern void dumpRegion(const gRegion ®ion); void eWidgetDesktop::addRootWidget(eWidget *root, int top) { assert(!root->m_desktop); - if (!top) + + /* buffered mode paints back-to-front, while immediate mode is front-to-back. */ + if (m_comp_mode == cmBuffered) + top = !top; + + if (top) m_root.push_back(root); else m_root.push_front(root); @@ -23,57 +31,120 @@ void eWidgetDesktop::removeRootWidget(eWidget *root) m_root.remove(root); } -void eWidgetDesktop::calcWidgetClipRegion(struct eWidgetDesktopCompBuffer *comp, eWidget *widget, gRegion &parent_visible) +int eWidgetDesktop::movedWidget(eWidget *root) +{ + if ((m_comp_mode == cmBuffered) && (root->m_comp_buffer)) + { + root->m_comp_buffer->m_position = root->position(); +// redrawComposition(0); + return 0; + } + + return -1; +} + +void eWidgetDesktop::calcWidgetClipRegion(eWidget *widget, gRegion &parent_visible) { /* start with our clip region, clipped with the parent's */ if (widget->m_vis & eWidget::wVisShow) { widget->m_visible_region = widget->m_clip_region; - widget->m_visible_region.moveBy(widget->position() - comp->m_position); + widget->m_visible_region.moveBy(widget->position()); widget->m_visible_region &= parent_visible; // in parent space! - /* TODO: check transparency here! */ - /* remove everything this widget will contain from parent's visible list */ - parent_visible -= widget->m_visible_region; // will remove child regions too! + if (!widget->isTransparent()) + /* remove everything this widget will contain from parent's visible list, unless widget is transparent. */ + parent_visible -= widget->m_visible_region; // will remove child regions too! /* now prepare for recursing to childs */ widget->m_visible_region.moveBy(-widget->position()); // now in local space - } else widget->m_visible_region = gRegion(); widget->m_visible_with_childs = widget->m_visible_region; - for (ePtrList::iterator i(widget->m_childs.begin()); i != widget->m_childs.end(); ++i) - calcWidgetClipRegion(comp, *i, widget->m_visible_region); + /* add childs in reverse (Z) order - we're going from front-to-bottom here. */ + ePtrList::iterator i(widget->m_childs.end()); + + for (;;) + { + if (i != widget->m_childs.end()) + { + if (i->m_vis & eWidget::wVisShow) + calcWidgetClipRegion(*i, widget->m_visible_region); + else + clearVisibility(*i); + } + if (i == widget->m_childs.begin()) + break; + --i; + } } -void eWidgetDesktop::recalcClipRegions() +void eWidgetDesktop::recalcClipRegions(eWidget *root) { if (m_comp_mode == cmImmediate) - m_screen.m_background_region = gRegion(eRect(ePoint(0, 0), m_screen.m_screen_size)); - - for (ePtrList::iterator i(m_root.begin()); i != m_root.end(); ++i) { - eWidgetDesktopCompBuffer *comp = (m_comp_mode == cmImmediate) ? &m_screen : i->m_comp_buffer; + gRegion background_before = m_screen.m_background_region; - if (m_comp_mode != cmImmediate) + m_screen.m_background_region = gRegion(eRect(ePoint(0, 0), m_screen.m_screen_size)); + + for (ePtrList::iterator i(m_root.begin()); i != m_root.end(); ++i) { - if (!comp) + if (!(i->m_vis & eWidget::wVisShow)) { - createBufferForWidget(*i); - comp = i->m_comp_buffer; - } - - comp->m_background_region = gRegion(eRect(ePoint(0, 0), comp->m_screen_size)); + clearVisibility(i); + continue; + } + + gRegion visible_before = i->m_visible_with_childs; + + calcWidgetClipRegion(*i, m_screen.m_background_region); + + gRegion redraw = (i->m_visible_with_childs - visible_before) | (visible_before - i->m_visible_with_childs); + + redraw.moveBy(i->position()); + + invalidate(redraw); + } + + gRegion redraw = (background_before - m_screen.m_background_region) | (m_screen.m_background_region - background_before); + invalidate(redraw); + } else if (m_comp_mode == cmBuffered) + { + if (!root->m_vis & eWidget::wVisShow) + { + clearVisibility(root); + removeBufferForWidget(root); + return; } + if ((!root->m_comp_buffer) || (root->size() != root->m_comp_buffer->m_screen_size)) + createBufferForWidget(root); + + eWidgetDesktopCompBuffer *comp = root->m_comp_buffer; + + gRegion visible_before = root->m_visible_with_childs; + + comp->m_background_region = gRegion(eRect(comp->m_position, comp->m_screen_size)); + + gRegion visible_new = root->m_visible_with_childs - visible_before; + gRegion visible_lost = visible_before - root->m_visible_with_childs; + visible_new.moveBy(root->position()); + visible_lost.moveBy(root->position()); + + /* this sucks, obviously. */ + invalidate(visible_new); + invalidate(visible_lost); - calcWidgetClipRegion(comp, *i, comp->m_background_region); + calcWidgetClipRegion(root, comp->m_background_region); } } void eWidgetDesktop::invalidate(const gRegion ®ion) { + if (region.empty()) + return; + if (m_timer && !m_require_redraw) m_timer->start(0, 1); // start singleshot redraw timer @@ -84,10 +155,12 @@ void eWidgetDesktop::invalidate(const gRegion ®ion) else for (ePtrList::iterator i(m_root.begin()); i != m_root.end(); ++i) { + if (!(i->m_vis & eWidget::wVisShow)) + continue; + eWidgetDesktopCompBuffer *comp = i->m_comp_buffer; gRegion mregion = region; - mregion.moveBy(-comp->m_position); comp->m_dirty_region |= mregion; } } @@ -118,7 +191,7 @@ void eWidgetDesktop::setBackgroundColor(gRGB col) void eWidgetDesktop::setPalette(gPixmap &pm) { - if (m_comp_mode == cmImmediate) +// if (m_comp_mode == cmImmediate) { ASSERT(m_screen.m_dc); gPainter painter(m_screen.m_dc); @@ -152,7 +225,6 @@ void eWidgetDesktop::paintBackground(eWidgetDesktopCompBuffer *comp) void eWidgetDesktop::paint() { - eDebug("paint"); m_require_redraw = 0; /* walk all root windows. */ @@ -160,9 +232,14 @@ void eWidgetDesktop::paint() { eWidgetDesktopCompBuffer *comp = (m_comp_mode == cmImmediate) ? &m_screen : i->m_comp_buffer; + if (!(i->m_vis & eWidget::wVisShow)) + continue; + { gPainter painter(comp->m_dc); + painter.moveOffset(-comp->m_position); i->doPaint(painter, comp->m_dirty_region); + painter.resetOffset(); } if (m_comp_mode != cmImmediate) @@ -171,11 +248,18 @@ void eWidgetDesktop::paint() if (m_comp_mode == cmImmediate) paintBackground(&m_screen); + + if (m_comp_mode == cmBuffered) + { +// redrawComposition(0); + } } void eWidgetDesktop::setDC(gDC *dc) { m_screen.m_dc = dc; + if (m_comp_mode == cmBuffered) + redrawComposition(1); } void eWidgetDesktop::setRedrawTask(eMainloop &ml) @@ -199,7 +283,7 @@ void eWidgetDesktop::makeCompatiblePixmap(gPixmap &pm) if (m_comp_mode != cmImmediate) return; - eDebug("widgetDesktop: make compatible pixmap of %p\n", &pm); +// eDebug("widgetDesktop: make compatible pixmap of %p", &pm); if (!m_screen.m_dc) { eWarning("eWidgetDesktop: no DC to make pixmap compatible with!"); @@ -235,12 +319,13 @@ eWidgetDesktop::eWidgetDesktop(eSize size): m_mainloop(0), m_timer(0) m_screen.m_screen_size = size; m_require_redraw = 0; + CONNECT(gRC::getInstance()->notify, eWidgetDesktop::notify); setCompositionMode(cmImmediate); } eWidgetDesktop::~eWidgetDesktop() { - /* destroy all buffer */ + /* destroy all buffers */ setCompositionMode(-1); } @@ -250,11 +335,26 @@ void eWidgetDesktop::createBufferForWidget(eWidget *widget) eWidgetDesktopCompBuffer *comp = widget->m_comp_buffer = new eWidgetDesktopCompBuffer; - eRect bbox = widget->m_clip_region.extends; + eDebug("create buffer for widget, %d x %d\n", widget->size().width(), widget->size().height()); + + eRect bbox = eRect(widget->position(), widget->size()); comp->m_position = bbox.topLeft(); comp->m_dirty_region = gRegion(eRect(ePoint(0, 0), bbox.size())); comp->m_screen_size = bbox.size(); -// comp->m_dc = new .. ; + /* TODO: configurable bit depth. */ + + /* clone palette. FIXME. */ + ePtr pm = new gPixmap(comp->m_screen_size, 32, 1), pm_screen; + pm->surface->clut.data = new gRGB[256]; + pm->surface->clut.colors = 256; + pm->surface->clut.start = 0; + + + m_screen.m_dc->getPixmap(pm_screen); + + memcpy(pm->surface->clut.data, pm_screen->surface->clut.data, 256 * sizeof(gRGB)); + + comp->m_dc = new gDC(pm); } void eWidgetDesktop::removeBufferForWidget(eWidget *widget) @@ -265,3 +365,49 @@ void eWidgetDesktop::removeBufferForWidget(eWidget *widget) widget->m_comp_buffer = 0; } } + +void eWidgetDesktop::redrawComposition(int notified) +{ + if (m_comp_mode != cmBuffered) + return; + + assert(m_screen.m_dc); + + gPainter p(m_screen.m_dc); + p.resetClip(eRect(ePoint(0, 0), m_screen.m_screen_size)); + p.setBackgroundColor(m_screen.m_background_color); + p.clear(); + + for (ePtrList::iterator i(m_root.begin()); i != m_root.end(); ++i) + { + if (!i->isVisible()) + continue; + ePtr pm; + ASSERT(i->m_comp_buffer); + i->m_comp_buffer->m_dc->getPixmap(pm); + p.blit(pm, i->m_comp_buffer->m_position, eRect(), gPixmap::blitAlphaBlend); + } + + // flip activates on next vsync. + p.flip(); + p.waitVSync(); + + if (notified) + p.notify(); + + for (ePtrList::iterator i(m_root.begin()); i != m_root.end(); ++i) + if (i->m_animation.m_active) + i->m_animation.tick(1); +} + +void eWidgetDesktop::notify() +{ + redrawComposition(1); +} + +void eWidgetDesktop::clearVisibility(eWidget *widget) +{ + widget->m_visible_with_childs = gRegion(); + for (ePtrList::iterator i(widget->m_childs.begin()); i != widget->m_childs.end(); ++i) + clearVisibility(*i); +}