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 _view_info.flags = View::F_none;
154 _view_info.view_index = 0;
157 _view_info.width = _fb->size().w();
158 _view_info.height = _fb->size().h();
159 _view_info.buffer_offset = 0;
160 _view_info.buffer_index = 0;
161 _view_info.bytes_per_line = _view_info.width * _fb->type()->bytes_per_pixel();
162 _view_info.pixel_info = *_fb->type();
164 _screen_info.flags = Goos::F_pointer;
165 _screen_info.width = _view_info.width;
166 _screen_info.height = _view_info.height;
167 _screen_info.num_static_views = 1;
168 _screen_info.num_static_buffers = 1;
169 _screen_info.pixel_info = _view_info.pixel_info;
172 L4Re::Env const *e = L4Re::Env::env();
173 _ev_ds = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
176 chksys(e->mem_alloc()->alloc(L4_PAGESIZE, _ev_ds.get()));
177 chksys(e->rm()->attach(&_ev_ds_m, L4_PAGESIZE, L4Re::Rm::Search_addr, _ev_ds.get(), 0, L4_PAGESHIFT));
179 _events = L4Re::Event_buffer(_ev_ds_m.get(), L4_PAGESIZE);
181 calc_label_sz(_core->label_font());
186 Client_fb::view_setup()
188 if (_flags & F_fb_focus)
189 _core->user_state()->set_focus(this);
193 Client_fb::draw(Canvas *canvas, View_stack const *, Mode mode) const
195 /* use dimming in x-ray mode */
196 Canvas::Mix_mode op = mode.flat() ? Canvas::Solid : Canvas::Mixed;
198 /* do not dim the focused view in x-ray mode */
199 if (mode.xray() && !mode.kill() && focused())
203 * The view content and label should never overdraw the
204 * frame of the view in non-flat Nitpicker modes. The frame
205 * is located outside the view area. By shrinking the
206 * clipping area to the view area, we protect the frame.
208 Clip_guard clip_guard(canvas, *this);
211 * If the clipping area shrinked to zero,
212 * we do not process drawing operations.
214 if (!canvas->clip_valid()/* || !_session*/)
217 /* draw view content */
218 Rgb32::Color mix_color = /*mode.kill() ? kill_color() :*/ session()->color();
220 canvas->draw_box(top(_bar_height), Rgb32::Color(56, 68, 88));
222 canvas->draw_texture(_fb, mix_color, p1() + Point(0, _bar_height), op);
226 Client_fb::visible_size() const
228 if (_flags & F_fb_shaded)
229 return Area(_fb->size().w(), _bar_height);
231 return _fb->size() + Area(0, _bar_height);
236 Client_fb::toggle_shaded()
239 _flags ^= F_fb_shaded;
240 Rect n = Rect(p1(), visible_size());
242 _core->user_state()->vstack()->refresh_view(0, 0, r | n);
246 Client_fb::handle_core_event(Hid_report *e, Point const &mouse)
248 static Point left_drag;
249 static l4_umword_t drag_dev;
250 bool consumed = false;
252 Valuator<int> const *abs = e->get_vals(3);
253 if (abs && abs->get(1).valid() && left_drag != Point())
255 Rect npos = Rect(p1() + mouse - left_drag, size());
257 _core->user_state()->vstack()->viewport(this, npos, true);
261 Rect bar = top(_bar_height);
263 Hid_report::Key_event const *btn_left = e->find_key_event(L4RE_BTN_LEFT);
264 View_stack *_stack = _core->user_state()->vstack();
265 if (btn_left && btn_left->value == 1 && !_stack->on_top(this))
266 _stack->push_top(this);
268 if (btn_left && bar.contains(mouse) && !(_flags & F_fb_fixed_location))
270 if (btn_left->value == 1 && left_drag == Point())
273 drag_dev = e->device_id();
275 else if (btn_left->value == 0 && e->device_id() == drag_dev)
280 Hid_report::Key_event const *btn_middle = e->find_key_event(L4RE_BTN_MIDDLE);
281 if (btn_middle && btn_middle->value == 1 && bar.contains(mouse))
287 // no events if window is shaded
288 if (consumed || (_flags & F_fb_shaded))
299 Axis_info_vector const *v;
301 Abs_xfrm(Axis_info_vector const *v, Point const &p1, Area const &sz)
302 : p1(p1), sz(sz), v(v) {}
304 void operator () (unsigned axis, int &val) const
306 Axis_info const *ai = v->get(axis);
312 val = cxx::min(sz.w(), cxx::max(0, val - p1.x()));
315 val = cxx::min(sz.h(), cxx::max(0, val - p1.y()));
326 Client_fb::handle_event(Hid_report *e, Point const &mouse, bool core_dev)
328 static Point left_drag;
330 if (core_dev && handle_core_event(e, mouse))
333 // no events if window is shaded
334 if (_flags & F_fb_shaded)
337 Abs_xfrm xfrm(e->abs_infos(), p1() + Point(0, _bar_height), _fb->size());
338 bool trigger = post_hid_report(e, _events, xfrm);
346 Client_fb::refresh(int x, int y, int w, int h)
348 _core->user_state()->vstack()->refresh_view(this, 0, Rect(p1() + Point(x, y + _bar_height), Area(w, h)));
353 Client_fb::get_stream_info_for_id(l4_umword_t id, L4Re::Event_stream_info *info)
355 return _core->user_state()->get_input_stream_info_for_id(id, info);
359 Client_fb::get_abs_info(l4_umword_t id, unsigned naxes, unsigned *axes,
360 L4Re::Event_absinfo *infos)
362 unsigned char ax_mode[naxes];
363 int i = _core->user_state()->get_input_axis_info(id, naxes, axes, infos, ax_mode);
364 // < 0: means we got an error
365 // == 0: means the device is an non-core device and not translated
366 // == 1: means ths device is used as core input pointer (adjust X and Y)
370 for (unsigned a = 0; a < naxes; ++a)
378 infos[a].max = _fb->size().w();
382 infos[a].max = _fb->size().h();
390 Client_fb::event_get(L4::Ipc::Iostream &s)
397 Client_fb::event_get_stream_info_for_id(L4::Ipc::Iostream &s)
399 L4Re::Event_stream_info info;
403 int i = get_stream_info_for_id(id, &info);
412 Client_fb::event_get_axis_info(L4::Ipc::Iostream &s)
415 long unsigned naxes = L4RE_ABS_MAX;
416 unsigned axes[L4RE_ABS_MAX];
417 s >> id >> L4::Ipc::buf_cp_in(axes, naxes);
418 L4Re::Event_absinfo infos[naxes];
419 int i = get_abs_info(id, naxes, axes, infos);
423 s << L4::Ipc::buf_cp_out(infos, naxes);
428 Client_fb::event_dispatch(l4_umword_t, L4::Ipc::Iostream &s)
430 using namespace L4Re;
438 case Event_::Get_stream_info_for_id:
439 return event_get_stream_info_for_id(s);
440 case Event_::Get_axis_info:
441 return event_get_axis_info(s);
448 Client_fb::dispatch(l4_umword_t obj, L4::Ipc::Iostream &s)
450 using namespace L4Re;
457 case L4::Meta::Protocol:
458 return L4Re::Util::handle_meta_request<L4Re::Console>(s);
460 return Icu_svr::dispatch(obj, s);
462 return L4Re::Util::Video::Goos_svr::dispatch(obj, s);
463 case Protocol::Event:
464 return event_dispatch(obj, s);
466 return -L4_EBADPROTO;
474 _core->user_state()->forget_view(this);