- start working on compositing support
authorFelix Domke <tmbinc@elitedvb.net>
Sat, 20 Aug 2005 23:09:30 +0000 (23:09 +0000)
committerFelix Domke <tmbinc@elitedvb.net>
Sat, 20 Aug 2005 23:09:30 +0000 (23:09 +0000)
lib/gui/ewidget.h
lib/gui/ewidgetdesktop.cpp
lib/gui/ewidgetdesktop.h

index 89b3b38f23f80c89462726af7caf81e02a40f5af..8bd199f9d4a1548c47b85ee362c2374288e1b12e 100644 (file)
@@ -5,6 +5,8 @@
 #include <lib/base/eptrlist.h> /* for eSmartPtrList */
 #include <lib/gui/ewindowstyle.h> /* for eWindowStyle */
 
+class eWidgetDesktop;class eWidgetDesktop;
+
 class eWidget
 {
        friend class eWidgetDesktop;
@@ -73,6 +75,7 @@ public:
 
                // all in local space!
        gRegion m_clip_region, m_visible_region, m_visible_with_childs;
+       struct eWidgetDesktopCompBuffer *m_comp_buffer;
        
        enum eWidgetEvent
        {
index 3a60a26ae99ea9bf845ec3043e6d0e4dfb1e938c..c820610e567cc179c1775a9c425dc330d58bdae0 100644 (file)
@@ -10,93 +10,172 @@ void eWidgetDesktop::addRootWidget(eWidget *root, int top)
        else
                m_root.push_front(root);
        root->m_desktop = this;
+
+               /* the creation will be postponed. */
+       root->m_comp_buffer = 0;
 }
 
 void eWidgetDesktop::removeRootWidget(eWidget *root)
 {
+       if (m_comp_mode == cmBuffered)
+               removeBufferForWidget(root);
+
        m_root.remove(root);
 }
 
-void eWidgetDesktop::calcWidgetClipRegion(eWidget *widget, gRegion &parent_visible)
+void eWidgetDesktop::calcWidgetClipRegion(struct eWidgetDesktopCompBuffer *comp, 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());
+               widget->m_visible_region.moveBy(widget->position() - comp->m_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!
 
                        /* 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<eWidget>::iterator i(widget->m_childs.begin()); i != widget->m_childs.end(); ++i)
-               calcWidgetClipRegion(*i, widget->m_visible_region);
+               calcWidgetClipRegion(comp, *i, widget->m_visible_region);
 }
 
 void eWidgetDesktop::recalcClipRegions()
 {
-       m_background_region = gRegion(eRect(ePoint(0, 0), m_screen_size));
+       if (m_comp_mode == cmImmediate)
+               m_screen.m_background_region = gRegion(eRect(ePoint(0, 0), m_screen.m_screen_size));
        
        for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i)
-               calcWidgetClipRegion(*i, m_background_region);
+       {
+               eWidgetDesktopCompBuffer *comp = (m_comp_mode == cmImmediate) ? &m_screen : i->m_comp_buffer;
+               
+               if (m_comp_mode != cmImmediate)
+               {
+                       if (!comp)
+                       {
+                               createBufferForWidget(*i);
+                               comp = i->m_comp_buffer;
+                       }
+                       
+                       comp->m_background_region = gRegion(eRect(ePoint(0, 0), comp->m_screen_size));
+               }
+               
+               calcWidgetClipRegion(comp, *i, comp->m_background_region);
+       }
 }
 
 void eWidgetDesktop::invalidate(const gRegion &region)
 {
-       if (m_timer && m_dirty_region.empty())
+       if (m_timer && !m_require_redraw)
                m_timer->start(0, 1); // start singleshot redraw timer
-       m_dirty_region |= region;
+       
+       m_require_redraw = 1;
+       
+       if (m_comp_mode == cmImmediate)
+               m_screen.m_dirty_region |= region;
+       else
+               for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i)
+               {
+                       eWidgetDesktopCompBuffer *comp = i->m_comp_buffer;
+                       
+                       gRegion mregion = region;
+                       mregion.moveBy(-comp->m_position);
+                       comp->m_dirty_region |= mregion;
+               }
 }
 
-void eWidgetDesktop::setBackgroundColor(gRGB col)
+void eWidgetDesktop::setBackgroundColor(eWidgetDesktopCompBuffer *comp, gRGB col)
 {
-       m_background_color = col;
+       comp->m_background_color = col;
        
                /* if there's something visible from the background, redraw it with the new color. */
-       if (m_dc && m_background_region.valid() && !m_background_region.empty())
+       if (comp->m_dc && comp->m_background_region.valid() && !comp->m_background_region.empty())
        {
                        /* todo: split out "setBackgroundColor / clear"... maybe? */
-               gPainter painter(m_dc);
-               painter.resetClip(m_background_region);
-               painter.setBackgroundColor(m_background_color);
+               gPainter painter(comp->m_dc);
+               painter.resetClip(comp->m_background_region);
+               painter.setBackgroundColor(comp->m_background_color);
                painter.clear();
        }
 }
 
+void eWidgetDesktop::setBackgroundColor(gRGB col)
+{
+       setBackgroundColor(&m_screen, col);
+
+       if (m_comp_mode == cmBuffered)
+               for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i)
+                       setBackgroundColor(i->m_comp_buffer, col);
+}
+
 void eWidgetDesktop::setPalette(gPixmap &pm)
 {
-       ASSERT(m_dc);
-       gPainter painter(m_dc);
-       painter.setPalette(&pm);
+       if (m_comp_mode == cmImmediate)
+       {
+               ASSERT(m_screen.m_dc);
+               gPainter painter(m_screen.m_dc);
+               painter.setPalette(&pm);
+       }
+       
+       if (m_comp_mode == cmBuffered)
+       {
+               for (ePtrList<eWidget>::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);
+               }
+       }
 }
 
-void eWidgetDesktop::paint()
+void eWidgetDesktop::paintBackground(eWidgetDesktopCompBuffer *comp)
 {
-       gPainter painter(m_dc);
-               /* walk all root windows. */
-       for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i)
-               i->doPaint(painter, m_dirty_region);
-       m_dirty_region &= m_background_region;
+       comp->m_dirty_region &= comp->m_background_region;
        
-       painter.resetClip(m_dirty_region);
-       painter.setBackgroundColor(m_background_color);
-       painter.clear();
+       gPainter painter(comp->m_dc);
        
+       painter.resetClip(comp->m_dirty_region);
+       painter.setBackgroundColor(comp->m_background_color);
+       painter.clear();
        painter.flush();
        
-       m_dirty_region = gRegion();
+       comp->m_dirty_region = gRegion();
+}
+
+void eWidgetDesktop::paint()
+{
+       eDebug("paint");
+       m_require_redraw = 0;
+       
+               /* walk all root windows. */
+       for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i)
+       {
+               eWidgetDesktopCompBuffer *comp = (m_comp_mode == cmImmediate) ? &m_screen : i->m_comp_buffer;
+               
+               {
+                       gPainter painter(comp->m_dc);
+                       i->doPaint(painter, comp->m_dirty_region);
+               }
+
+               if (m_comp_mode != cmImmediate)
+                       paintBackground(comp);
+       }
+       
+       if (m_comp_mode == cmImmediate)
+               paintBackground(&m_screen);
 }
 
 void eWidgetDesktop::setDC(gDC *dc)
 {
-       m_dc = dc;
+       m_screen.m_dc = dc;
 }
 
 void eWidgetDesktop::setRedrawTask(eMainloop &ml)
@@ -111,14 +190,17 @@ void eWidgetDesktop::setRedrawTask(eMainloop &ml)
        m_timer = new eTimer(m_mainloop);
        CONNECT(m_timer->timeout, eWidgetDesktop::paint);
        
-       if (!m_dirty_region.empty())
+       if (m_require_redraw)
                m_timer->start(0, 1);
 }
 
 void eWidgetDesktop::makeCompatiblePixmap(gPixmap &pm)
 {
+       if (m_comp_mode != cmImmediate)
+               return;
+       
        eDebug("widgetDesktop: make compatible pixmap of %p\n", &pm);
-       if (!m_dc)
+       if (!m_screen.m_dc)
        {
                eWarning("eWidgetDesktop: no DC to make pixmap compatible with!");
                return;
@@ -128,19 +210,58 @@ void eWidgetDesktop::makeCompatiblePixmap(gPixmap &pm)
        gPainter pixmap_painter(pixmap_dc);
        
        ePtr<gPixmap> target_pixmap;
-       m_dc->getPixmap(target_pixmap);
+       m_screen.m_dc->getPixmap(target_pixmap);
        
        assert(target_pixmap);
        
        pixmap_painter.mergePalette(target_pixmap);
 }
 
-eWidgetDesktop::eWidgetDesktop(eSize size): m_screen_size(size), m_mainloop(0), m_timer(0)
+void eWidgetDesktop::setCompositionMode(int mode)
+{
+       m_comp_mode = mode;
+       
+       if (mode == cmBuffered)
+               for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i)
+                       createBufferForWidget(*i);
+       else
+               for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i)
+                       removeBufferForWidget(*i);
+}
+
+eWidgetDesktop::eWidgetDesktop(eSize size): m_mainloop(0), m_timer(0)
 {
-       m_dirty_region = gRegion(eRect(ePoint(0, 0), m_screen_size));
+       m_screen.m_dirty_region = gRegion(eRect(ePoint(0, 0), size));
+       m_screen.m_screen_size = size;
+       m_require_redraw = 0;
+
+       setCompositionMode(cmImmediate);
 }
 
 eWidgetDesktop::~eWidgetDesktop()
 {
+               /* destroy all buffer */
+       setCompositionMode(-1);
 }
 
+void eWidgetDesktop::createBufferForWidget(eWidget *widget)
+{
+       removeBufferForWidget(widget);
+       
+       eWidgetDesktopCompBuffer *comp = widget->m_comp_buffer = new eWidgetDesktopCompBuffer;
+       
+       eRect bbox = widget->m_clip_region.extends;
+       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 .. ;
+}
+
+void eWidgetDesktop::removeBufferForWidget(eWidget *widget)
+{
+       if (widget->m_comp_buffer)
+       {
+               delete widget->m_comp_buffer;
+               widget->m_comp_buffer = 0;
+       }
+}
index c917e36a6f55cf294fad7598e257d64d55c775e8..af772bd273ba76a30f2b4ddcdf374c5708232a28 100644 (file)
@@ -8,14 +8,28 @@ class eWidget;
 class eMainloop;
 class eTimer;
 
-class eWidgetDesktop: public Object
+               /* an eWidgetDesktopCompBuffer is a composition buffer. in 
+                  immediate composition  mode, we only have one composition 
+                  buffer - the screen.
+                  in buffered mode, we have one buffer for each widget, plus
+                  the screen.
+                  
+                  even in buffered mode, we have a background region, because
+                  a window can be arbitrary shaped. the screen size acts as a bounding
+                  box in these cases. */
+
+struct eWidgetDesktopCompBuffer
 {
-public: // weil debug
+       ePoint m_position;
        eSize m_screen_size;
        gRegion m_dirty_region;
        gRegion m_background_region;
        ePtr<gDC> m_dc;
        gRGB m_background_color;
+};
+
+class eWidgetDesktop: public Object
+{
 public:
        eWidgetDesktop(eSize screen);
        ~eWidgetDesktop();
@@ -28,18 +42,35 @@ public:
        void setDC(gDC *dc);
        
        void setBackgroundColor(gRGB col);
+       void setBackgroundColor(eWidgetDesktopCompBuffer *comp, gRGB col);
        
        void setPalette(gPixmap &pm);
        
        void setRedrawTask(eMainloop &ml);
        
        void makeCompatiblePixmap(gPixmap &pm);
+       
+       enum {
+               cmImmediate,
+               cmBuffered
+       };
+       
+       void setCompositionMode(int mode);
 private:
        ePtrList<eWidget> m_root;
-       void calcWidgetClipRegion(eWidget *widget, gRegion &parent_visible);
+       void calcWidgetClipRegion(eWidgetDesktopCompBuffer *comp, eWidget *widget, gRegion &parent_visible);
+       void paintBackground(eWidgetDesktopCompBuffer *comp);
        
        eMainloop *m_mainloop;
        eTimer *m_timer;
+       
+       int m_comp_mode;
+       int m_require_redraw;
+       
+       eWidgetDesktopCompBuffer m_screen;
+       
+       void createBufferForWidget(eWidget *widget);
+       void removeBufferForWidget(eWidget *widget);
 };
 
 #endif