2 * (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3 * Alexander Warg <warg@os.inf.tu-dresden.de>
4 * economic rights: Technische Universität Dresden (Germany)
6 * This file is part of TUD:OS and distributed under the terms of the
7 * GNU General Public License 2.
8 * Please see the COPYING-GPL-2 file for details.
10 #include "client_fb.h"
12 #include <l4/mag-gfx/clip_guard>
13 #include <l4/mag-gfx/texture>
15 #include <l4/mag/server/view_stack>
16 #include <l4/mag/server/factory>
19 #include <l4/re/event_enums.h>
20 #include <l4/re/error_helper>
21 #include <l4/re/util/cap_alloc>
22 #include <l4/sys/factory>
23 #include <l4/re/util/meta>
24 #include <l4/re/console>
26 #include <l4/mag/server/user_state>
31 namespace Mag_server {
35 using L4Re::Util::Auto_cap;
37 enum { Bar_height = 16 };
39 Client_fb::Client_fb(Core_api const *core)
40 : View(Rect(), F_need_frame),
43 _bar_height(Bar_height),
48 Client_fb::set_geometry_prop(Session *_s, Property_handler const *, cxx::String const &v)
50 Client_fb *s = static_cast<Client_fb*>(_s);
51 // ignore multiple geometry properties
61 if (r >= a.len() || a[r] != 'x')
62 L4Re::chksys(-L4_EINVAL, "invalid geometry format");
67 if (r < a.len() && a[r] == '+')
73 if (r < a.len() && a[r] == '+')
79 if (w <= 0 || h <= 0 || w >= 10000 || h >= 10000)
80 L4Re::chksys(-L4_ERANGE, "invalid geometry (too big)");
82 Area sz = s->_core->user_state()->vstack()->canvas()->size();
96 s->set_geometry(Rect(Point(x, y), Area(w, h)));
100 Client_fb::set_flags_prop(Session *_s, Property_handler const *p, cxx::String const &)
102 Client_fb *s = static_cast<Client_fb*>(_s);
104 if (!strcmp(p->tag, "focus"))
105 s->_flags |= F_fb_focus;
107 if (!strcmp(p->tag, "shaded"))
108 s->_flags |= F_fb_shaded;
110 if (!strcmp(p->tag, "fixed"))
111 s->_flags |= F_fb_fixed_location;
115 Client_fb::set_bar_height_prop(Session *_s, Property_handler const *, cxx::String const &v)
117 Client_fb *s = static_cast<Client_fb*>(_s);
118 int r = v.from_dec(&s->_bar_height);
120 L4Re::chksys(-L4_EINVAL, "invalid bar height format");
122 s->_bar_height = std::max(std::min(s->_bar_height, 100), 4);
128 using L4Re::Video::View;
129 using L4Re::Video::Color_component;
130 using L4Re::Video::Goos;
134 Auto_cap<L4Re::Dataspace>::Cap ds(
135 L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>());
137 Screen_factory *sf = dynamic_cast<Screen_factory*>(_core->user_state()->vstack()->canvas()->type()->factory);
138 //Screen_factory *sf = dynamic_cast<Screen_factory*>(Rgb16::type()->factory);
140 L4Re::chksys(L4Re::Env::env()->mem_alloc()->alloc(sf->get_texture_size(res),
143 L4Re::Rm::Auto_region<void *> dsa;
144 L4Re::chksys(L4Re::Env::env()->rm()->attach(&dsa, ds->size(), L4Re::Rm::Search_addr, ds.get(), 0, L4_SUPERPAGESHIFT));
146 _fb = sf->create_texture(res, dsa.get());
148 set_geometry(Rect(p1(), visible_size()));
150 _fb_ds = ds.release();
152 if (_flags & F_fb_focus)
153 _core->user_state()->set_focus(this);
155 _view_info.flags = View::F_none;
157 _view_info.view_index = 0;
160 _view_info.width = _fb->size().w();
161 _view_info.height = _fb->size().h();
162 _view_info.buffer_offset = 0;
163 _view_info.buffer_index = 0;
164 _view_info.bytes_per_line = _view_info.width * _fb->type()->bytes_per_pixel();
165 _view_info.pixel_info = *_fb->type();
167 _screen_info.flags = Goos::F_pointer;
168 _screen_info.width = _view_info.width;
169 _screen_info.height = _view_info.height;
170 _screen_info.num_static_views = 1;
171 _screen_info.num_static_buffers = 1;
172 _screen_info.pixel_info = _view_info.pixel_info;
175 L4Re::Env const *e = L4Re::Env::env();
176 _ev_ds = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
179 chksys(e->mem_alloc()->alloc(L4_PAGESIZE, _ev_ds.get()));
180 chksys(e->rm()->attach(&_ev_ds_m, L4_PAGESIZE, L4Re::Rm::Search_addr, _ev_ds.get(), 0, L4_PAGESHIFT));
182 _events = L4Re::Event_buffer(_ev_ds_m.get(), L4_PAGESIZE);
184 calc_label_sz(_core->label_font());
189 Client_fb::draw(Canvas *canvas, View_stack const *, Mode mode) const
191 /* use dimming in x-ray mode */
192 Canvas::Mix_mode op = mode.flat() ? Canvas::Solid : Canvas::Mixed;
194 /* is this the currently focused view? */
195 Rgb32::Color frame_color = focused() ? Rgb32::White : View::frame_color();
197 /* do not dim the focused view in x-ray mode */
198 if (mode.xray() && !mode.kill() && focused())
202 * The view content and label should never overdraw the
203 * frame of the view in non-flat Nitpicker modes. The frame
204 * is located outside the view area. By shrinking the
205 * clipping area to the view area, we protect the frame.
207 Clip_guard clip_guard(canvas, *this);
210 * If the clipping area shrinked to zero,
211 * we do not process drawing operations.
213 if (!canvas->clip_valid()/* || !_session*/)
216 /* draw view content */
217 Rgb32::Color mix_color = /*mode.kill() ? kill_color() :*/ session()->color();
219 canvas->draw_box(top(_bar_height), Rgb32::Color(56, 68, 88));
221 canvas->draw_texture(_fb, mix_color, p1() + Point(0, _bar_height), op);
225 Client_fb::visible_size() const
227 if (_flags & F_fb_shaded)
228 return Area(_fb->size().w(), _bar_height);
230 return _fb->size() + Area(0, _bar_height);
235 Client_fb::toggle_shaded()
238 _flags ^= F_fb_shaded;
239 Rect n = Rect(p1(), visible_size());
241 _core->user_state()->vstack()->refresh_view(0, 0, r | n);
245 Client_fb::handle_event(L4Re::Event_buffer::Event const &e,
248 static Point left_drag;
250 if (e.payload.type == L4RE_EV_ABS && e.payload.code == 1 && left_drag != Point())
252 Rect npos = Rect(p1() + mouse - left_drag, size());
254 _core->user_state()->vstack()->viewport(this, npos, true);
258 Rect bar = top(_bar_height);
260 if (e.payload.type == L4RE_EV_KEY)
262 View_stack *_stack = _core->user_state()->vstack();
263 if (e.payload.code == L4RE_BTN_LEFT && e.payload.value == 1 &&
264 !_stack->on_top(this))
265 _stack->push_top(this);
267 if (e.payload.code == L4RE_BTN_LEFT
268 && bar.contains(mouse)
269 && !(_flags & F_fb_fixed_location))
271 if (e.payload.value == 1)
273 else if (e.payload.value == 0)
278 if (e.payload.code == L4RE_BTN_MIDDLE
279 && bar.contains(mouse)
280 && e.payload.value == 1)
287 if (e.payload.type == L4RE_EV_ABS && e.payload.code <= L4RE_ABS_Y)
289 // wait for the following ABS_Y axis
290 if (e.payload.type == L4RE_ABS_X)
293 Rect r = (*this - bar).b();
294 if (!r.contains(mouse))
297 Point mp = p1() + Point(0, _bar_height);
298 mp = Point(_fb->size()).min(Point(0,0).max(mouse - mp));
299 L4Re::Event_buffer::Event ne;
301 ne.payload.type = L4RE_EV_ABS;
302 ne.payload.code = L4RE_ABS_X;
303 ne.payload.value = mp.x();
304 ne.payload.stream_id = e.payload.stream_id;
306 ne.payload.code = L4RE_ABS_Y;
307 ne.payload.value = mp.y();
313 // no events if window is shaded
314 if (_flags & F_fb_shaded)
324 Client_fb::refresh(int x, int y, int w, int h)
326 _core->user_state()->vstack()->refresh_view(this, 0, Rect(p1() + Point(x, y + _bar_height), Area(w, h)));
331 Client_fb::dispatch(l4_umword_t obj, L4::Ipc_iostream &s)
338 case L4::Meta::Protocol:
339 return L4Re::Util::handle_meta_request<L4Re::Console>(s);
341 return Icu_svr::dispatch(obj, s);
342 case L4Re::Protocol::Goos:
343 return L4Re::Util::Video::Goos_svr::dispatch(obj, s);
344 case L4Re::Protocol::Event:
350 case L4Re::Event_::Get:
358 return -L4_EBADPROTO;
366 _core->user_state()->forget_view(this);