]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/mag/server/src/view_stack.cc
3d0d2ffb1584fe2543eeb763c28845630eeb267a
[l4.git] / l4 / pkg / mag / server / src / view_stack.cc
1 /*
2  * (c) 2010 Alexander Warg <warg@os.inf.tu-dresden.de>
3  *     economic rights: Technische Universität Dresden (Germany)
4  *
5  * This file is part of TUD:OS and distributed under the terms of the
6  * GNU General Public License 2.
7  * Please see the COPYING-GPL-2 file for details.
8  */
9 #include <l4/mag-gfx/clip_guard>
10
11 #include "view_stack"
12 #include "view"
13
14 #include <cstdio>
15 #include <cstring>
16
17 namespace Mag_server {
18
19 class Redraw_queue
20 {
21 public:
22   enum { Num_entries = 100 };
23
24   // merge all overlapping rects in the queue
25   void merge()
26   {
27     for (unsigned i = last; i > 0; --i)
28       for (unsigned j = 0; j < last; ++j)
29         {
30           if (i - 1 == j)
31             continue;
32
33           if ((_q[j] & _q[i-1]).valid())
34             {
35               _q[j] = _q[j] | _q[i-1];
36               memmove(_q + i - 1, _q + i, (last - i) * sizeof(Rect));
37               --last;
38               break;
39             }
40         }
41   }
42
43   void q(Rect const &r)
44   {
45     if (!r.valid())
46       return;
47     //printf("q[%d,%d - %d,%d]\n", r.x1(), r.y1(), r.x2(), r.y2());
48     for (unsigned i = 0; i < last; ++i)
49       {
50         if ((_q[i] & r).valid())
51           {
52             // merge with overlapping rect
53             _q[i] = _q[i] | r;
54             merge();
55             return;
56           }
57       }
58
59     if (last < Num_entries)
60       _q[last++] = r; // add new entry
61     else
62       {
63         // queue is full, just merge with the last entry
64         _q[last-1] = _q[last - 1] | r;
65         merge();
66       }
67   }
68
69   void clear()
70   { last = 0; }
71
72   typedef Rect const *iterator;
73
74   iterator begin() const { return _q; }
75   iterator end() const { return _q + last; }
76
77 private:
78   Rect _q[Num_entries];
79   unsigned last;
80 };
81
82 static Redraw_queue rdq;
83
84 Rect
85 View_stack::outline(View const *v) const
86 {
87   if (_mode.flat() || !v->need_frame())
88     return *v;
89   else
90     return v->grow(3);
91 }
92
93 void
94 View_stack::viewport(View *v, Rect const &pos, bool) const
95 {
96   Rect old = outline(v);
97
98   /* take over new view parameters */
99   v->set_geometry(pos);
100
101   Rect compound = old | outline(v);
102
103 #if 0
104   /* update labels (except when moving the mouse cursor) */
105   if (v != top())
106     _place_labels(compound);
107 #endif
108
109   /* update area on screen */
110   rdq.q(compound);
111 //  draw_recursive(top(), 0, /*redraw ? 0 : view->session(),*/ compound);
112 }
113
114 void
115 View_stack::draw_frame(View const *v) const
116 {
117   if (_mode.flat() || !v->need_frame())
118     return;
119
120   Rgb32::Color color = v->focused() ? Rgb32::White : View::frame_color();
121   _canvas->draw_rect(v->offset(-3, -3, 3, 3), Rgb32::Black);
122   _canvas->draw_rect(v->offset(-2, -2, 2, 2), color);
123   _canvas->draw_rect(v->offset(-1, -1, 1, 1), Rgb32::Black);
124 }
125
126 void
127 View_stack::draw_label(View const *v) const
128 {
129   if (_mode.flat() || !v->need_frame())
130     return;
131 }
132
133 void
134 View_stack::draw_recursive(View const *v, View const *dst, Rect const &rect) const
135 {
136   Rect clipped;
137
138   /* find next view that intersects with the current clipping rectangle */
139   for ( ; v && !(clipped = outline(v) & rect).valid(); )
140     v = v->next();
141
142   if (!v)
143     return;
144
145   Rect_tuple border = rect - clipped;
146
147   View const *n = v->next();
148   if (n && border.t.valid())
149     draw_recursive(n, dst, border.t);
150   if (n && border.l.valid())
151     draw_recursive(n, dst, border.l);
152
153   if (!dst || dst == v || v->transparent())
154     {
155       Clip_guard g(_canvas, clipped);
156       draw_frame(v);
157       v->draw(_canvas, this, _mode);
158       draw_label(v);
159     }
160
161   if (n && border.r.valid())
162     draw_recursive(n, dst, border.r);
163   if (n && border.b.valid())
164     draw_recursive(n, dst, border.b);
165 }
166
167 void
168 View_stack::refresh_view(View const *v, View const *dst, Rect const &rect) const
169 {
170   (void)dst;
171   Rect r = rect;
172   if (v)
173     r = r & outline(v);
174
175   rdq.q(r);
176   //draw_recursive(top(), dst, r);
177 }
178
179 void
180 View_stack::flush()
181 {
182   for (Redraw_queue::iterator i = rdq.begin(); i != rdq.end(); ++i)
183     {
184       draw_recursive(top(), 0, *i);
185       if (_canvas_view)
186         _canvas_view->refresh(i->x1(), i->y1(), i->w(), i->h());
187     }
188
189   rdq.clear();
190 }
191
192 void
193 View_stack::stack(View *v, View *pivot, bool behind)
194 {
195   remove(v);
196   if (behind)
197     insert_after(v, pivot);
198   else
199     insert_before(v, pivot);
200
201   refresh_view(v, 0, outline(v));
202 }
203
204
205 View *
206 View_stack::find(Point const &pos) const
207 {
208   View *n = top()->next();
209   while (n && !n->contains(pos))
210     n = n->next();
211
212   return n;
213 }
214
215 }