1 #include <lib/gui/ewidgetdesktop.h>
2 #include <lib/gui/ewidget.h>
3 #include <lib/base/ebase.h>
5 void eWidgetDesktop::addRootWidget(eWidget *root, int top)
7 assert(!root->m_desktop);
9 m_root.push_back(root);
11 m_root.push_front(root);
12 root->m_desktop = this;
14 /* the creation will be postponed. */
15 root->m_comp_buffer = 0;
18 void eWidgetDesktop::removeRootWidget(eWidget *root)
20 if (m_comp_mode == cmBuffered)
21 removeBufferForWidget(root);
26 void eWidgetDesktop::calcWidgetClipRegion(struct eWidgetDesktopCompBuffer *comp, eWidget *widget, gRegion &parent_visible)
28 /* start with our clip region, clipped with the parent's */
29 if (widget->m_vis & eWidget::wVisShow)
31 widget->m_visible_region = widget->m_clip_region;
32 widget->m_visible_region.moveBy(widget->position() - comp->m_position);
33 widget->m_visible_region &= parent_visible; // in parent space!
34 /* TODO: check transparency here! */
36 /* remove everything this widget will contain from parent's visible list */
37 parent_visible -= widget->m_visible_region; // will remove child regions too!
39 /* now prepare for recursing to childs */
40 widget->m_visible_region.moveBy(-widget->position()); // now in local space
43 widget->m_visible_region = gRegion();
45 widget->m_visible_with_childs = widget->m_visible_region;
47 for (ePtrList<eWidget>::iterator i(widget->m_childs.begin()); i != widget->m_childs.end(); ++i)
48 calcWidgetClipRegion(comp, *i, widget->m_visible_region);
51 void eWidgetDesktop::recalcClipRegions()
53 if (m_comp_mode == cmImmediate)
54 m_screen.m_background_region = gRegion(eRect(ePoint(0, 0), m_screen.m_screen_size));
56 for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i)
58 eWidgetDesktopCompBuffer *comp = (m_comp_mode == cmImmediate) ? &m_screen : i->m_comp_buffer;
60 if (m_comp_mode != cmImmediate)
64 createBufferForWidget(*i);
65 comp = i->m_comp_buffer;
68 comp->m_background_region = gRegion(eRect(ePoint(0, 0), comp->m_screen_size));
71 calcWidgetClipRegion(comp, *i, comp->m_background_region);
75 void eWidgetDesktop::invalidate(const gRegion ®ion)
77 if (m_timer && !m_require_redraw)
78 m_timer->start(0, 1); // start singleshot redraw timer
82 if (m_comp_mode == cmImmediate)
83 m_screen.m_dirty_region |= region;
85 for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i)
87 eWidgetDesktopCompBuffer *comp = i->m_comp_buffer;
89 gRegion mregion = region;
90 mregion.moveBy(-comp->m_position);
91 comp->m_dirty_region |= mregion;
95 void eWidgetDesktop::setBackgroundColor(eWidgetDesktopCompBuffer *comp, gRGB col)
97 comp->m_background_color = col;
99 /* if there's something visible from the background, redraw it with the new color. */
100 if (comp->m_dc && comp->m_background_region.valid() && !comp->m_background_region.empty())
102 /* todo: split out "setBackgroundColor / clear"... maybe? */
103 gPainter painter(comp->m_dc);
104 painter.resetClip(comp->m_background_region);
105 painter.setBackgroundColor(comp->m_background_color);
110 void eWidgetDesktop::setBackgroundColor(gRGB col)
112 setBackgroundColor(&m_screen, col);
114 if (m_comp_mode == cmBuffered)
115 for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i)
116 setBackgroundColor(i->m_comp_buffer, col);
119 void eWidgetDesktop::setPalette(gPixmap &pm)
121 if (m_comp_mode == cmImmediate)
123 ASSERT(m_screen.m_dc);
124 gPainter painter(m_screen.m_dc);
125 painter.setPalette(&pm);
128 if (m_comp_mode == cmBuffered)
130 for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i)
132 ASSERT(i->m_comp_buffer->m_dc);
133 gPainter painter(i->m_comp_buffer->m_dc);
134 painter.setPalette(&pm);
139 void eWidgetDesktop::paintBackground(eWidgetDesktopCompBuffer *comp)
141 comp->m_dirty_region &= comp->m_background_region;
143 gPainter painter(comp->m_dc);
145 painter.resetClip(comp->m_dirty_region);
146 painter.setBackgroundColor(comp->m_background_color);
150 comp->m_dirty_region = gRegion();
153 void eWidgetDesktop::paint()
156 m_require_redraw = 0;
158 /* walk all root windows. */
159 for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i)
161 eWidgetDesktopCompBuffer *comp = (m_comp_mode == cmImmediate) ? &m_screen : i->m_comp_buffer;
164 gPainter painter(comp->m_dc);
165 i->doPaint(painter, comp->m_dirty_region);
168 if (m_comp_mode != cmImmediate)
169 paintBackground(comp);
172 if (m_comp_mode == cmImmediate)
173 paintBackground(&m_screen);
176 void eWidgetDesktop::setDC(gDC *dc)
181 void eWidgetDesktop::setRedrawTask(eMainloop &ml)
190 m_timer = new eTimer(m_mainloop);
191 CONNECT(m_timer->timeout, eWidgetDesktop::paint);
193 if (m_require_redraw)
194 m_timer->start(0, 1);
197 void eWidgetDesktop::makeCompatiblePixmap(gPixmap &pm)
199 if (m_comp_mode != cmImmediate)
202 eDebug("widgetDesktop: make compatible pixmap of %p\n", &pm);
205 eWarning("eWidgetDesktop: no DC to make pixmap compatible with!");
209 ePtr<gDC> pixmap_dc = new gDC(&pm);
210 gPainter pixmap_painter(pixmap_dc);
212 ePtr<gPixmap> target_pixmap;
213 m_screen.m_dc->getPixmap(target_pixmap);
215 assert(target_pixmap);
217 pixmap_painter.mergePalette(target_pixmap);
220 void eWidgetDesktop::setCompositionMode(int mode)
224 if (mode == cmBuffered)
225 for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i)
226 createBufferForWidget(*i);
228 for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i)
229 removeBufferForWidget(*i);
232 eWidgetDesktop::eWidgetDesktop(eSize size): m_mainloop(0), m_timer(0)
234 m_screen.m_dirty_region = gRegion(eRect(ePoint(0, 0), size));
235 m_screen.m_screen_size = size;
236 m_require_redraw = 0;
238 setCompositionMode(cmImmediate);
241 eWidgetDesktop::~eWidgetDesktop()
243 /* destroy all buffer */
244 setCompositionMode(-1);
247 void eWidgetDesktop::createBufferForWidget(eWidget *widget)
249 removeBufferForWidget(widget);
251 eWidgetDesktopCompBuffer *comp = widget->m_comp_buffer = new eWidgetDesktopCompBuffer;
253 eRect bbox = widget->m_clip_region.extends;
254 comp->m_position = bbox.topLeft();
255 comp->m_dirty_region = gRegion(eRect(ePoint(0, 0), bbox.size()));
256 comp->m_screen_size = bbox.size();
257 // comp->m_dc = new .. ;
260 void eWidgetDesktop::removeBufferForWidget(eWidget *widget)
262 if (widget->m_comp_buffer)
264 delete widget->m_comp_buffer;
265 widget->m_comp_buffer = 0;