X-Git-Url: http://code.vuplus.com/gitweb/?p=vuplus_dvbapp;a=blobdiff_plain;f=lib%2Fgui%2Fewidgetdesktop.cpp;h=08bd04740fcfc8c33d4d5ba49c6223a2311877c7;hp=4d0c0a9b73437cd04ee798b1892d8fa5906f018a;hb=cf57753fe26b8468048598a53124d876f216bc3d;hpb=ab2ae6bd08a0ef13fc7462d51fc3a9ab15509b17 diff --git a/lib/gui/ewidgetdesktop.cpp b/lib/gui/ewidgetdesktop.cpp index 4d0c0a9..08bd047 100644 --- a/lib/gui/ewidgetdesktop.cpp +++ b/lib/gui/ewidgetdesktop.cpp @@ -7,7 +7,7 @@ extern void dumpRegion(const gRegion ®ion); void eWidgetDesktop::addRootWidget(eWidget *root) { - assert(!root->m_desktop); + ASSERT(!root->m_desktop); int invert_sense = 0; /* buffered mode paints back-to-front, while immediate mode is front-to-back. */ @@ -29,27 +29,34 @@ void eWidgetDesktop::addRootWidget(eWidget *root) root->m_desktop = this; /* the creation will be postponed. */ - root->m_comp_buffer = 0; + for (int i = 0; i < MAX_LAYER; ++i) + root->m_comp_buffer[i] = 0; } void eWidgetDesktop::removeRootWidget(eWidget *root) { if (m_comp_mode == cmBuffered) - removeBufferForWidget(root); + { + for (int i = 0; i < MAX_LAYER; ++i) + removeBufferForWidget(root, i); + } m_root.remove(root); } int eWidgetDesktop::movedWidget(eWidget *root) { - if ((m_comp_mode == cmBuffered) && (root->m_comp_buffer)) + if (m_comp_mode != cmBuffered) + return -1; /* native move not supported */ + + for (int i = 0; i < MAX_LAYER; ++i) { - root->m_comp_buffer->m_position = root->position(); + if (root->m_comp_buffer[i]) + root->m_comp_buffer[i]->m_position = root->position(); // redrawComposition(0); - return 0; } - - return -1; + + return 0; /* native move ok */ } void eWidgetDesktop::calcWidgetClipRegion(eWidget *widget, gRegion &parent_visible) @@ -124,60 +131,101 @@ void eWidgetDesktop::recalcClipRegions(eWidget *root) if (!root->m_vis & eWidget::wVisShow) { clearVisibility(root); - removeBufferForWidget(root); + for (int i = 0; i < MAX_LAYER; ++i) + removeBufferForWidget(root, i); return; } - if ((!root->m_comp_buffer) || (root->size() != root->m_comp_buffer->m_screen_size)) - createBufferForWidget(root); - eWidgetDesktopCompBuffer *comp = root->m_comp_buffer; + for (int i = 0; i < MAX_LAYER; ++i) + { + eWidgetDesktopCompBuffer *comp = root->m_comp_buffer[i]; + + /* TODO: layers might not be required to have the screen size, for memory reasons. */ + if ((i == 0 && !comp) || (comp && (root->size() != comp->m_screen_size))) + createBufferForWidget(root, 0); - 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(root, comp->m_background_region); + comp = root->m_comp_buffer[i]; /* it might have changed. */ + + if (!comp) + continue; /* WAIT, don't we need to invalidate,whatever */ + + /* CHECKME: don't we need to recalculate everything? after all, our buffer has changed and is likely to be cleared */ + 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()); + + invalidate(visible_new, root, i); + invalidate(visible_lost, root, i); + + calcWidgetClipRegion(root, comp->m_background_region); + } + } +} + +void eWidgetDesktop::invalidateWidgetLayer(const gRegion ®ion, const eWidget *widget, int layer) +{ + if (m_comp_mode == cmImmediate) + { + invalidate(region); + return; + } + eWidgetDesktopCompBuffer *comp = widget->m_comp_buffer[layer]; + if (comp) + comp->m_dirty_region |= region; +} + +void eWidgetDesktop::invalidateWidget(const gRegion ®ion, const eWidget *widget, int layer) +{ + if (m_comp_mode == cmImmediate) + { + invalidate(region); + return; } + + if (!(widget->m_vis & eWidget::wVisShow)) + return; + + gRegion mregion = region; + if (layer == -1) + for (int layer = 0; layer < MAX_LAYER; ++layer) + invalidateWidgetLayer(mregion, widget, layer); + else + invalidateWidgetLayer(mregion, widget, layer); } -void eWidgetDesktop::invalidate(const gRegion ®ion) +void eWidgetDesktop::invalidate(const gRegion ®ion, const eWidget *widget, int layer) { if (region.empty()) return; - + if (m_timer && !m_require_redraw) m_timer->start(0, 1); // start singleshot redraw timer - + m_require_redraw = 1; - + if (m_comp_mode == cmImmediate) + { + /* in immediate mode, we don't care for widget and layer, we use the topmost. */ m_screen.m_dirty_region |= region; - 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; - comp->m_dirty_region |= mregion; - } + } else + { + if (!widget) + for (ePtrList::iterator i(m_root.begin()); i != m_root.end(); ++i) + invalidateWidget(region, i); + else + invalidateWidget(region, widget, layer); + } } void eWidgetDesktop::setBackgroundColor(eWidgetDesktopCompBuffer *comp, gRGB col) { comp->m_background_color = col; - + /* if there's something visible from the background, redraw it with the new color. */ if (comp->m_dc && comp->m_background_region.valid() && !comp->m_background_region.empty()) { @@ -195,7 +243,11 @@ void eWidgetDesktop::setBackgroundColor(gRGB col) if (m_comp_mode == cmBuffered) for (ePtrList::iterator i(m_root.begin()); i != m_root.end(); ++i) - setBackgroundColor(i->m_comp_buffer, col); + { + for (int l = 0; l < MAX_LAYER; ++l) + if (i->m_comp_buffer[l]) + setBackgroundColor(i->m_comp_buffer[l], l ? gRGB(0, 0, 0, 0) : col); /* all layers above 0 will have a transparent background */ + } } void eWidgetDesktop::setPalette(gPixmap &pm) @@ -211,15 +263,23 @@ void eWidgetDesktop::setPalette(gPixmap &pm) { for (ePtrList::iterator i(m_root.begin()); i != m_root.end(); ++i) { - ASSERT(i->m_comp_buffer->m_dc); - gPainter painter(i->m_comp_buffer->m_dc); - painter.setPalette(&pm); + for (int l = 0; l < MAX_LAYER; ++l) + { + if (!i->m_comp_buffer[l]) + continue; + ASSERT(i->m_comp_buffer[l]->m_dc); + gPainter painter(i->m_comp_buffer[l]->m_dc); + painter.setPalette(&pm); + } } } } void eWidgetDesktop::paintBackground(eWidgetDesktopCompBuffer *comp) { + if (!comp) + return; + comp->m_dirty_region &= comp->m_background_region; gPainter painter(comp->m_dc); @@ -227,40 +287,55 @@ void eWidgetDesktop::paintBackground(eWidgetDesktopCompBuffer *comp) painter.resetClip(comp->m_dirty_region); painter.setBackgroundColor(comp->m_background_color); painter.clear(); - painter.flush(); comp->m_dirty_region = gRegion(); } + +void eWidgetDesktop::paintLayer(eWidget *widget, int layer) +{ + eWidgetDesktopCompBuffer *comp = (m_comp_mode == cmImmediate) ? &m_screen : widget->m_comp_buffer[layer]; + if (m_comp_mode == cmImmediate) + ASSERT(layer == 0); + if (!comp) + return; + gPainter painter(comp->m_dc); + painter.moveOffset(-comp->m_position); + widget->doPaint(painter, comp->m_dirty_region, layer); + painter.resetOffset(); +} + void eWidgetDesktop::paint() { m_require_redraw = 0; - + /* walk all root windows. */ for (ePtrList::iterator i(m_root.begin()); i != m_root.end(); ++i) { - 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) - paintBackground(comp); + if (m_comp_mode == cmImmediate) + paintLayer(i, 0); + else + for (int l = 0; l < MAX_LAYER; ++l) + { + paintLayer(i, l); + paintBackground(i->m_comp_buffer[l]); + } } - + if (m_comp_mode == cmImmediate) paintBackground(&m_screen); - + if (m_comp_mode == cmBuffered) { // redrawComposition(0); + } else + { + gPainter painter(m_screen.m_dc); + painter.flush(); } } @@ -275,18 +350,22 @@ void eWidgetDesktop::setRedrawTask(eMainloop &ml) { if (m_mainloop) { - delete m_timer; m_timer = 0; m_mainloop = 0; } m_mainloop = &ml; - m_timer = new eTimer(m_mainloop); + m_timer = eTimer::create(m_mainloop); CONNECT(m_timer->timeout, eWidgetDesktop::paint); if (m_require_redraw) m_timer->start(0, 1); } +void eWidgetDesktop::makeCompatiblePixmap(ePtr &pm) +{ + makeCompatiblePixmap(*(pm.operator->())); +} + void eWidgetDesktop::makeCompatiblePixmap(gPixmap &pm) { if (m_comp_mode != cmImmediate) @@ -302,7 +381,10 @@ void eWidgetDesktop::makeCompatiblePixmap(gPixmap &pm) ePtr target_pixmap; m_screen.m_dc->getPixmap(target_pixmap); - assert(target_pixmap); + if (!target_pixmap) { + eDebug("no target pixmap! assuming bpp > 8 for accelerated graphics."); + return; + } if (target_pixmap->surface && target_pixmap->surface->bpp > 8) return; @@ -319,13 +401,14 @@ void eWidgetDesktop::setCompositionMode(int mode) if (mode == cmBuffered) for (ePtrList::iterator i(m_root.begin()); i != m_root.end(); ++i) - createBufferForWidget(*i); + createBufferForWidget(*i, 0); else for (ePtrList::iterator i(m_root.begin()); i != m_root.end(); ++i) - removeBufferForWidget(*i); + for (int l = 0; l < MAX_LAYER; ++l) + removeBufferForWidget(*i, l); } -eWidgetDesktop::eWidgetDesktop(eSize size): m_mainloop(0), m_timer(0) +eWidgetDesktop::eWidgetDesktop(eSize size): m_mainloop(0) { m_screen.m_dirty_region = gRegion(eRect(ePoint(0, 0), size)); m_screen.m_screen_size = size; @@ -348,40 +431,39 @@ eWidgetDesktop::~eWidgetDesktop() setCompositionMode(-1); } -void eWidgetDesktop::createBufferForWidget(eWidget *widget) +void eWidgetDesktop::createBufferForWidget(eWidget *widget, int layer) { - removeBufferForWidget(widget); - - eWidgetDesktopCompBuffer *comp = widget->m_comp_buffer = new eWidgetDesktopCompBuffer; - - eDebug("create buffer for widget, %d x %d\n", widget->size().width(), widget->size().height()); - + removeBufferForWidget(widget, layer); + + eWidgetDesktopCompBuffer *comp = widget->m_comp_buffer[layer] = new eWidgetDesktopCompBuffer; + + eDebug("create buffer for widget layer %d, %d x %d\n", layer, 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(); /* 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) +void eWidgetDesktop::removeBufferForWidget(eWidget *widget, int layer) { - if (widget->m_comp_buffer) + if (widget->m_comp_buffer[layer]) { - delete widget->m_comp_buffer; - widget->m_comp_buffer = 0; + delete widget->m_comp_buffer[layer]; + widget->m_comp_buffer[layer] = 0; } } @@ -390,7 +472,7 @@ void eWidgetDesktop::redrawComposition(int notified) if (m_comp_mode != cmBuffered) return; - assert(m_screen.m_dc); + ASSERT(m_screen.m_dc); gPainter p(m_screen.m_dc); p.resetClip(eRect(ePoint(0, 0), m_screen.m_screen_size)); @@ -401,10 +483,14 @@ void eWidgetDesktop::redrawComposition(int notified) { 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); + for (int layer = 0; layer < MAX_LAYER; ++layer) + { + ePtr pm; + if (!i->m_comp_buffer[layer]) + continue; + i->m_comp_buffer[layer]->m_dc->getPixmap(pm); + p.blit(pm, i->m_comp_buffer[layer]->m_position, eRect(), gPixmap::blitAlphaBlend); + } } // flip activates on next vsync. @@ -430,3 +516,9 @@ void eWidgetDesktop::clearVisibility(eWidget *widget) for (ePtrList::iterator i(widget->m_childs.begin()); i != widget->m_childs.end(); ++i) clearVisibility(*i); } + +void eWidgetDesktop::resize(eSize size) +{ + m_screen.m_dirty_region = gRegion(eRect(ePoint(0, 0), size)); + m_screen.m_screen_size = size; +}