]> rtime.felk.cvut.cz Git - l4.git/blobdiff - l4/pkg/mag/plugins/mag_client/mag_client.cc
update
[l4.git] / l4 / pkg / mag / plugins / mag_client / mag_client.cc
index 09d0f8399989f97f4393bdf92ea2d5dc7189ee06..f252f0b125cb25ff6384683d3d5ad39d6251250f 100644 (file)
@@ -26,6 +26,7 @@
 
 #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>
@@ -58,7 +59,7 @@ public:
   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();
 };
 
@@ -66,7 +67,7 @@ class Client_buffer;
 class Client_view;
 
 class Mag_goos
-: public Object,
+: public Session, public Object,
   public L4Re::Util::Icu_cap_array_svr<Mag_goos>
 {
 private:
@@ -81,23 +82,38 @@ 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 &);
 };
 
 
@@ -142,13 +158,15 @@ public:
   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)
@@ -159,10 +177,26 @@ 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;
@@ -174,8 +208,11 @@ Client_view::get_info(L4Re::Video::View::Info *inf) const
 {
   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();
@@ -205,6 +242,16 @@ Client_view::set_info(L4Re::Video::View::Info const &inf,
   _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));
@@ -218,14 +265,22 @@ Client_view::set_info(L4Re::Video::View::Info const &inf,
       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();
@@ -281,8 +336,23 @@ void Mag_client::start(Core_api *core)
     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;
@@ -295,8 +365,12 @@ Mag_client::dispatch(l4_umword_t, L4::Ipc_iostream &ios)
       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);
 
@@ -315,7 +389,7 @@ Mag_client::destroy()
 }
 
 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;
@@ -335,174 +409,261 @@ Mag_goos::dispatch(l4_umword_t obj, L4::Ipc_iostream &ios)
     }
 }
 
+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;
     }
 }
 
@@ -528,58 +689,46 @@ Client_buffer::Client_buffer(Core_api const *, unsigned long size)
 }
 
 
-
 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);
-
 }