#include <l4/mag/server/plugin>
#include <l4/mag/server/object>
+#include <l4/mag/server/session>
#include <l4/mag/server/user_state>
#include <l4/mag-gfx/clip_guard>
#include <l4/mag-gfx/texture>
char const *type() const { return "Mag client"; }
void start(Core_api *core);
- int dispatch(l4_umword_t obj, L4::Ipc_iostream &ios);
+ int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
void destroy();
};
class Client_view;
class Mag_goos
-: public Object,
+: public Session, public Object,
public L4Re::Util::Icu_cap_array_svr<Mag_goos>
{
private:
typedef std::vector<cxx::Ref_ptr<Client_buffer> > Buffer_vector;
typedef std::vector<cxx::Auto_ptr<Client_view> > View_vector;
-
Buffer_vector _buffers;
View_vector _views;
- int screen_dispatch(l4_umword_t, L4::Ipc_iostream &ios);
- int event_dispatch(l4_umword_t, L4::Ipc_iostream &ios);
+ int screen_dispatch(l4_umword_t, L4::Ipc::Iostream &ios);
+ int event_dispatch(l4_umword_t, L4::Ipc::Iostream &ios);
+
+ int screen_info(L4::Ipc::Iostream &ios);
+ int screen_create_buffer(L4::Ipc::Iostream &ios);
+ int screen_create_view(L4::Ipc::Iostream &ios);
+ int screen_delete_view(L4::Ipc::Iostream &ios);
+ int screen_get_buffer(L4::Ipc::Iostream &ios);
+ int screen_view_info(L4::Ipc::Iostream &ios);
+ int screen_view_set_info(L4::Ipc::Iostream &ios);
+ int screen_view_stack(L4::Ipc::Iostream &ios);
+ int screen_view_refresh(L4::Ipc::Iostream &ios);
+ int screen_refresh(L4::Ipc::Iostream &ios);
+
+ int event_get(L4::Ipc::Iostream &ios);
+ int event_get_stream_info_for_id(L4::Ipc::Iostream &ios);
+ int event_get_axis_info(L4::Ipc::Iostream &ios);
public:
Mag_goos(Core_api const *core);
- void put_event(L4Re::Event_buffer::Event const &ne, bool trigger);
- int dispatch(l4_umword_t obj, L4::Ipc_iostream &ios);
+ void put_event(Hid_report *e, bool trigger);
+ int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
L4::Cap<void> rcv_cap() const { return _core->rcv_cap(); }
void destroy();
+ static void set_default_background(Session *_s, Property_handler const *, cxx::String const &);
};
Client_view(Core_api const *core, Mag_goos *screen);
virtual ~Client_view();
- int dispatch(l4_umword_t obj, L4::Ipc_iostream &ios);
- void draw(Canvas *, View_stack const *, Mode, bool) const;
- void handle_event(L4Re::Event_buffer::Event const &e, Point const &mouse);
+ int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
+ void draw(Canvas *, View_stack const *, Mode) const;
+ void handle_event(Hid_report *e, Point const &mouse, bool core_dev);
void get_info(L4Re::Video::View::Info *inf) const;
void set_info(L4Re::Video::View::Info const &inf,
cxx::Ref_ptr<Client_buffer> const &b);
+
+ Session *session() const { return _screen; }
};
Client_view::Client_view(Core_api const *core, Mag_goos *screen)
_front_txt = pi->factory->create_texture(Area(0,0), (void*)1);
_back_txt = pi->factory->create_texture(Area(0,0), (void*)1);
+ calc_label_sz(core->label_font());
}
Client_view::~Client_view()
{
+ if (_screen && _screen->background() == this)
+ {
+ // look for other background views below
+ View_stack *vs = _core->user_state()->vstack();
+ // We can either search below this view in the stack, or
+ // we can search from the top of the stack to find the uppermost
+ // view of our session that is tagged as background
+ View *v = vs->next_view(this); // search below this view
+ // View *v = vs->top(); // Search from the top of the stack
+ for (; v; v = vs->next_view(v))
+ if (v != this && v->session() == _screen && v->background())
+ break;
+ _screen->background(v);
+ }
+
_core->user_state()->forget_view(this);
delete _back_txt;
delete _front_txt;
{
using L4Re::Video::Color_component;
inf->flags = L4Re::Video::View::F_fully_dynamic;
- // we do not support chaning the pixel format
+ // we do not support changing the pixel format
inf->flags &= ~L4Re::Video::View::F_set_pixel;
+ if (above())
+ inf->flags |= L4Re::Video::View::F_above;
+
inf->xpos = x1();
inf->ypos = y1();
inf->width = w();
_back_txt->size(_front_txt->size());
_back_txt->pixels(_front_txt->pixels());
+ if (inf.flags & L4Re::Video::View::F_set_flags)
+ set_above(inf.flags & L4Re::Video::View::F_above);
+
+ if (inf.flags & L4Re::Video::View::F_set_background)
+ {
+ _core->user_state()->vstack()->push_bottom(this);
+ set_as_background();
+ _screen->background(this);
+ }
+
if (inf.has_set_bytes_per_line())
{
_back_txt->size(Area(inf.bytes_per_line / pi->bytes_per_pixel(), 0));
recalc_height = true;
}
- if (inf.has_set_buffer_offset())
+ if (!_buffer)
+ {
+ _back_txt->size(Area(0, 0));
+ _back_txt->pixels((char *)0);
+ _front_txt->size(Area(0, 0));
+ _front_txt->pixels((char *)0);
+ }
+
+ if (inf.has_set_buffer_offset() && _buffer)
{
_back_txt->pixels((char *)_buffer->local_addr() + inf.buffer_offset);
_buf_offset = inf.buffer_offset;
recalc_height = true;
}
- if (recalc_height)
+ if (recalc_height && _buffer)
{
unsigned long w = _back_txt->size().w();
unsigned long bw = w * pi->bytes_per_pixel();
printf("Plugin: Mag_client service started\n");
}
+void Mag_goos::set_default_background(Session *_s, Property_handler const *, cxx::String const &)
+{
+ Mag_goos *s = static_cast<Mag_goos *>(_s);
+
+ s->flags(F_default_background, 0);
+}
+
+namespace {
+ Session::Property_handler const _opts[] =
+ { { "default-background", false, &Mag_goos::set_default_background },
+ { "dfl-bg", false, &Mag_goos::set_default_background },
+ { 0, 0, 0 }
+ };
+};
+
int
-Mag_client::dispatch(l4_umword_t, L4::Ipc_iostream &ios)
+Mag_client::dispatch(l4_umword_t, L4::Ipc::Iostream &ios)
{
l4_msgtag_t tag;
ios >> tag;
if (L4::kobject_typeid<L4Re::Console>()->
has_proto(L4::Ipc::read<L4::Factory::Proto>(ios)))
{
+ L4::Ipc::Istream_copy cp_is = ios;
+
cxx::Ref_ptr<Mag_goos> cf(new Mag_goos(_core));
+ _core->set_session_options(cf.get(), cp_is, _opts);
+ _core->register_session(cf.get());
_core->registry()->register_obj(cf);
cf->obj_cap()->dec_refcnt(1);
}
int
-Mag_goos::dispatch(l4_umword_t obj, L4::Ipc_iostream &ios)
+Mag_goos::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
{
l4_msgtag_t tag;
ios >> tag;
}
}
+inline int
+Mag_goos::event_get(L4::Ipc::Iostream &ios)
+{
+ ios << L4::Ipc::Snd_fpage(_ev_ds.get().fpage(L4_CAP_FPAGE_RW));
+ return L4_EOK;
+}
+
+inline int
+Mag_goos::event_get_stream_info_for_id(L4::Ipc::Iostream &ios)
+{
+ L4Re::Event_stream_info info;
+ l4_umword_t id;
+
+ ios >> id;
+ int i = _core->user_state()->get_input_stream_info_for_id(id, &info);
+ if (i < 0)
+ return i;
+
+ ios.put(info);
+ return i;
+}
+
+inline int
+Mag_goos::event_get_axis_info(L4::Ipc::Iostream &ios)
+{
+ l4_umword_t id;
+ long unsigned naxes = L4RE_ABS_MAX;
+ unsigned axes[L4RE_ABS_MAX];
+ ios >> id >> L4::Ipc::buf_cp_in(axes, naxes);
+ L4Re::Event_absinfo infos[naxes];
+ int i = _core->user_state()->get_input_axis_info(id, naxes, axes, infos, 0);
+ if (i < 0)
+ return i;
+
+ ios << L4::Ipc::buf_cp_out(infos, naxes);
+ return i;
+}
+
int
-Mag_goos::event_dispatch(l4_umword_t, L4::Ipc_iostream &ios)
+Mag_goos::event_dispatch(l4_umword_t, L4::Ipc::Iostream &ios)
{
L4::Opcode op;
ios >> op;
switch (op)
{
- case L4Re::Event_::Get:
- ios << L4::Ipc::Snd_fpage(_ev_ds.get().fpage(L4_CAP_FPAGE_RW));
- return L4_EOK;
- default:
- return -L4_ENOSYS;
+ case L4Re::Event_::Get: return event_get(ios);
+ case L4Re::Event_::Get_stream_info_for_id: return event_get_stream_info_for_id(ios);
+ case L4Re::Event_::Get_axis_info: return event_get_axis_info(ios);
+ default: return -L4_ENOSYS;
}
}
-int
-Mag_goos::screen_dispatch(l4_umword_t, L4::Ipc_iostream &ios)
+inline int
+Mag_goos::screen_info(L4::Ipc::Iostream &ios)
{
- L4::Opcode op;
- ios >> op;
+ using L4Re::Video::Color_component;
+ using L4Re::Video::Goos;
- switch (op)
- {
- case ::L4Re::Video::Goos_::Info:
- {
- using L4Re::Video::Color_component;
- using L4Re::Video::Goos;
-
- Goos::Info i;
- Area a = _core->user_state()->vstack()->canvas()->size();
- Pixel_info const *mag_pi = _core->user_state()->vstack()->canvas()->type();
- i.width = a.w();
- i.height = a.h();
- i.flags = Goos::F_pointer
- | Goos::F_dynamic_views
- | Goos::F_dynamic_buffers;
-
- i.num_static_views = 0;
- i.num_static_buffers = 0;
- i.pixel_info = *mag_pi;
-
- ios.put(i);
-
- return L4_EOK;
- }
-
- case L4Re::Video::Goos_::Create_buffer:
- {
- unsigned long size;
- ios >> size;
-
- cxx::Ref_ptr<Client_buffer> b(new Client_buffer(_core, size));
- _buffers.push_back(b);
- b->index = _buffers.size() - 1;
-
- ios << L4::Ipc::Snd_fpage(b->ds_cap(), L4_CAP_FPAGE_RW);
-
- return b->index;
- }
-
- case L4Re::Video::Goos_::Create_view:
- {
- cxx::Auto_ptr<Client_view> v(new Client_view(_core, this));
- _views.push_back(v);
- return _views.size() - 1;
- }
-
- case L4Re::Video::Goos_::Get_buffer:
- {
- unsigned idx;
- ios >> idx;
- if (idx >= _buffers.size())
- return -L4_ERANGE;
+ Goos::Info i;
+ Area a = _core->user_state()->vstack()->canvas()->size();
+ Pixel_info const *mag_pi = _core->user_state()->vstack()->canvas()->type();
+ i.width = a.w();
+ i.height = a.h();
+ i.flags = Goos::F_pointer
+ | Goos::F_dynamic_views
+ | Goos::F_dynamic_buffers;
- ios << _buffers[idx]->ds_cap();
- return L4_EOK;
- }
+ i.num_static_views = 0;
+ i.num_static_buffers = 0;
+ i.pixel_info = *mag_pi;
- case L4Re::Video::Goos_::View_info:
- {
- unsigned idx;
- ios >> idx;
- if (idx >= _views.size())
- return -L4_ERANGE;
+ ios.put(i);
- Client_view *cv = _views[idx].get();
+ return L4_EOK;
+}
- L4Re::Video::View::Info vi;
- vi.view_index = idx;
- cv->get_info(&vi);
- ios.put(vi);
+inline int
+Mag_goos::screen_create_buffer(L4::Ipc::Iostream &ios)
+{
+ unsigned long size;
+ ios >> size;
- return L4_EOK;
- }
+ cxx::Ref_ptr<Client_buffer> b(new Client_buffer(_core, size));
+ _buffers.push_back(b);
+ b->index = _buffers.size() - 1;
- case L4Re::Video::Goos_::View_set_info:
- {
- unsigned idx;
- ios >> idx;
- if (idx >= _views.size())
- return -L4_ERANGE;
+ ios << L4::Ipc::Snd_fpage(b->ds_cap(), L4_CAP_FPAGE_RW);
- Client_view *cv = _views[idx].get();
+ return b->index;
+}
- L4Re::Video::View::Info vi;
- ios.get(vi);
+inline int
+Mag_goos::screen_create_view(L4::Ipc::Iostream &)
+{
+ cxx::Auto_ptr<Client_view> v(new Client_view(_core, this));
+ unsigned idx = 0;
+ for (View_vector::iterator i = _views.begin(); i != _views.end();
+ ++i, ++idx)
+ if (!*i)
+ {
+ *i = v;
+ return idx;
+ }
+
+ _views.push_back(v);
+ return _views.size() - 1;
+}
- cxx::Weak_ptr<Client_buffer> cb(0);
- if (vi.has_set_buffer())
- {
- if (vi.buffer_index >= _buffers.size())
- return -L4_ERANGE;
+inline int
+Mag_goos::screen_delete_view(L4::Ipc::Iostream &ios)
+{
+ unsigned idx;
+ ios >> idx;
+ if (idx >= _views.size())
+ return -L4_ERANGE;
- cb = _buffers[vi.buffer_index];
- }
+ _views[idx].reset(0);
+ return L4_EOK;
+}
- cv->set_info(vi, cb);
- return L4_EOK;
- }
+inline int
+Mag_goos::screen_get_buffer(L4::Ipc::Iostream &ios)
+{
+ unsigned idx;
+ ios >> idx;
+ if (idx >= _buffers.size())
+ return -L4_ERANGE;
- case L4Re::Video::Goos_::View_stack:
- {
- Client_view *pivot = 0;
- Client_view *cv;
- bool behind;
- unsigned cvi, pvi;
+ ios << _buffers[idx]->ds_cap();
+ return L4_EOK;
+}
- ios >> cvi >> pvi >> behind;
+inline int
+Mag_goos::screen_view_info(L4::Ipc::Iostream &ios)
+{
+ unsigned idx;
+ ios >> idx;
+ if (idx >= _views.size())
+ return -L4_ERANGE;
- if (cvi >= _views.size())
- return -L4_ERANGE;
+ Client_view *cv = _views[idx].get();
- cv = _views[cvi].get();
+ L4Re::Video::View::Info vi;
+ vi.view_index = idx;
+ cv->get_info(&vi);
+ ios.put(vi);
- if (pvi < _views.size())
- pivot = _views[pvi].get();
+ return L4_EOK;
+}
- if (!pivot)
- {
- if (behind)
- _core->user_state()->vstack()->push_bottom(cv);
- else
- _core->user_state()->vstack()->push_top(cv);
- }
- else
- _core->user_state()->vstack()->stack(cv, pivot, behind);
+inline int
+Mag_goos::screen_view_set_info(L4::Ipc::Iostream &ios)
+{
+ unsigned idx;
+ ios >> idx;
+ if (idx >= _views.size())
+ return -L4_ERANGE;
- }
- return L4_EOK;
+ Client_view *cv = _views[idx].get();
- case L4Re::Video::Goos_::View_refresh:
- {
- unsigned idx;
- int x, y, w, h;
- ios >> idx >> x >> y >> w >> h;
+ L4Re::Video::View::Info vi;
+ ios.get(vi);
- if (idx >= _views.size())
- return -L4_ERANGE;
+ cxx::Weak_ptr<Client_buffer> cb(0);
+ if (vi.has_set_buffer())
+ {
+ if (vi.buffer_index >= _buffers.size())
+ return -L4_ERANGE;
- Client_view *cv = _views[idx].get();
- _core->user_state()->vstack()->refresh_view(cv, 0, Rect(cv->p1() + Point(x,y), Area(w,h)));
+ cb = _buffers[vi.buffer_index];
+ }
- return L4_EOK;
- }
+ cv->set_info(vi, cb);
+ return L4_EOK;
+}
- default:
- return -L4_ENOSYS;
+inline int
+Mag_goos::screen_view_stack(L4::Ipc::Iostream &ios)
+{
+ Client_view *pivot = 0;
+ Client_view *cv;
+ bool behind;
+ unsigned cvi, pvi;
+
+ ios >> cvi >> pvi >> behind;
+
+ if (cvi >= _views.size())
+ return -L4_ERANGE;
+
+ cv = _views[cvi].get();
+
+ if (pvi < _views.size())
+ pivot = _views[pvi].get();
+
+ if (!pivot)
+ {
+ if (!behind)
+ _core->user_state()->vstack()->push_bottom(cv);
+ else
+ _core->user_state()->vstack()->push_top(cv);
+ }
+ else
+ _core->user_state()->vstack()->stack(cv, pivot, behind);
+
+ return L4_EOK;
+}
+
+inline int
+Mag_goos::screen_view_refresh(L4::Ipc::Iostream &ios)
+{
+ unsigned idx;
+ int x, y, w, h;
+ ios >> idx >> x >> y >> w >> h;
+
+ if (idx >= _views.size())
+ return -L4_ERANGE;
+
+ Client_view *cv = _views[idx].get();
+ _core->user_state()->vstack()->refresh_view(cv, 0, Rect(cv->p1() + Point(x,y), Area(w,h)));
+
+ return L4_EOK;
+}
+
+inline int
+Mag_goos::screen_refresh(L4::Ipc::Iostream &ios)
+{
+ int x, y, w, h;
+ ios >> x >> y >> w >> h;
+
+ _core->user_state()->vstack()->refresh_view(0, 0, Rect(Point(x,y), Area(w,h)));
+
+ return L4_EOK;
+}
+
+int
+Mag_goos::screen_dispatch(l4_umword_t, L4::Ipc::Iostream &ios)
+{
+ using namespace L4Re::Video;
+ L4::Opcode op;
+ ios >> op;
+
+ switch (op)
+ {
+ case Goos_::Info: return screen_info(ios);
+ case Goos_::Create_buffer:return screen_create_buffer(ios);
+ case Goos_::Create_view: return screen_create_view(ios);
+ case Goos_::Delete_view: return screen_delete_view(ios);
+ case Goos_::Get_buffer: return screen_get_buffer(ios);
+ case Goos_::View_info: return screen_view_info(ios);
+ case Goos_::View_set_info: return screen_view_set_info(ios);
+ case Goos_::View_stack: return screen_view_stack(ios);
+ case Goos_::View_refresh: return screen_view_refresh(ios);
+ case Goos_::Screen_refresh: return screen_refresh(ios);
+ default: return -L4_ENOSYS;
}
}
}
-
void
-Mag_goos::put_event(L4Re::Event_buffer::Event const &ne, bool trigger)
+Mag_goos::put_event(Hid_report *e, bool _trigger)
{
- if (_events.put(ne) && trigger)
+ if (post_hid_report(e, _events, Axis_xfrm_noop()) && _trigger)
_ev_irq.trigger();
}
void
-Client_view::draw(Canvas *c, View_stack const *, Mode mode, bool focused) const
+Client_view::draw(Canvas *c, View_stack const *, Mode mode) const
{
Canvas::Mix_mode op = mode.flat() ? Canvas::Solid : Canvas::Mixed;
- Rgb32::Color frame_color = focused ? Rgb32::White : View::frame_color();
- if (mode.xray() && !mode.kill() && focused)
+ if (mode.xray() && !mode.kill() && focused())
op = Canvas::Solid;
- if (!_buffer)
- return;
-
Clip_guard cg(c, *this);
if (!c->clip_valid())
return;
- Rgb32::Color mix_color = mode.kill() ? kill_color() : Rgb32::Black;
- c->draw_texture(_front_txt, mix_color, p1(), op);
+ Rgb32::Color mix_color = /*mode.kill() ? kill_color() :*/ session()->color();
+ Area s(0, 0);
+ if (_buffer)
+ {
+ c->draw_texture(_front_txt, mix_color, p1(), op);
+ s = _front_txt->size();
+ }
+
+ Area r = size() - s;
+ if (r.h() > 0)
+ c->draw_box(Rect(p1() + Point(0, s.h()), Area(size().w(), r.h())), mix_color);
+
+ if (r.w() > 0 && size().h() != r.h())
+ c->draw_box(Rect(p1() + Point(s.w(), 0), Area(r.w(), s.h())), mix_color);
}
void
-Client_view::handle_event(L4Re::Event_buffer::Event const &e,
- Point const &mouse)
+Client_view::handle_event(Hid_report *e, Point const &, bool)
{
- static Point left_drag;
-
- if (e.payload.type == L4RE_EV_MAX)
- {
- L4Re::Event_buffer::Event ne;
- ne.time = e.time;
- ne.payload.type = L4RE_EV_ABS;
- ne.payload.code = L4RE_ABS_X;
- ne.payload.value = mouse.x();
- ne.payload.stream_id = 0;
- _screen->put_event(ne, false);
- ne.payload.code = L4RE_ABS_Y;
- ne.payload.value = mouse.y();
- _screen->put_event(ne, true);
- return;
- }
-
_screen->put_event(e, true);
-
}