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);
175 if (m_comp_mode == cmBuffered)
177 eDebug("redraw composition");
182 void eWidgetDesktop::setDC(gDC *dc)
187 void eWidgetDesktop::setRedrawTask(eMainloop &ml)
196 m_timer = new eTimer(m_mainloop);
197 CONNECT(m_timer->timeout, eWidgetDesktop::paint);
199 if (m_require_redraw)
200 m_timer->start(0, 1);
203 void eWidgetDesktop::makeCompatiblePixmap(gPixmap &pm)
205 if (m_comp_mode != cmImmediate)
208 eDebug("widgetDesktop: make compatible pixmap of %p\n", &pm);
211 eWarning("eWidgetDesktop: no DC to make pixmap compatible with!");
215 ePtr<gDC> pixmap_dc = new gDC(&pm);
216 gPainter pixmap_painter(pixmap_dc);
218 ePtr<gPixmap> target_pixmap;
219 m_screen.m_dc->getPixmap(target_pixmap);
221 assert(target_pixmap);
223 pixmap_painter.mergePalette(target_pixmap);
226 void eWidgetDesktop::setCompositionMode(int mode)
230 if (mode == cmBuffered)
231 for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i)
232 createBufferForWidget(*i);
234 for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i)
235 removeBufferForWidget(*i);
238 eWidgetDesktop::eWidgetDesktop(eSize size): m_mainloop(0), m_timer(0)
240 m_screen.m_dirty_region = gRegion(eRect(ePoint(0, 0), size));
241 m_screen.m_screen_size = size;
242 m_require_redraw = 0;
244 setCompositionMode(cmImmediate);
247 eWidgetDesktop::~eWidgetDesktop()
249 /* destroy all buffers */
250 setCompositionMode(-1);
253 void eWidgetDesktop::createBufferForWidget(eWidget *widget)
255 removeBufferForWidget(widget);
257 eWidgetDesktopCompBuffer *comp = widget->m_comp_buffer = new eWidgetDesktopCompBuffer;
259 eRect bbox = widget->m_clip_region.extends;
260 comp->m_position = bbox.topLeft();
261 comp->m_dirty_region = gRegion(eRect(ePoint(0, 0), bbox.size()));
262 comp->m_screen_size = bbox.size();
263 /* TODO: configurable bit depth. */
264 comp->m_dc = new gDC(new gPixmap(comp->m_screen_size, 32));
267 void eWidgetDesktop::removeBufferForWidget(eWidget *widget)
269 if (widget->m_comp_buffer)
271 delete widget->m_comp_buffer;
272 widget->m_comp_buffer = 0;
276 void eWidgetDesktop::redrawComposition()
278 gPainter p(m_screen.m_dc);
280 for (ePtrList<eWidget>::iterator i(m_root.begin()); i != m_root.end(); ++i)
283 ASSERT(i->m_comp_buffer);
284 i->m_comp_buffer->m_dc->getPixmap(pm);
285 p.blit(pm, i->m_comp_buffer->m_position, eRect(), gPixmap::blitAlphaTest);