]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/mag/plugins/client_fb/client_fb.cc
21648744f4d37c793e7188c0abf93bdc13331733
[l4.git] / l4 / pkg / mag / plugins / client_fb / client_fb.cc
1 /*
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)
5  *
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.
9  */
10 #include "client_fb.h"
11
12 #include <l4/mag-gfx/clip_guard>
13 #include <l4/mag-gfx/texture>
14
15 #include <l4/mag/server/view_stack>
16
17 #include <l4/re/env>
18 #include <l4/re/event_enums.h>
19 #include <l4/re/error_helper>
20 #include <l4/sys/factory>
21 #include <l4/re/util/meta>
22 #include <l4/re/console>
23
24 #include <l4/mag/server/user_state>
25 #include <cstdio>
26
27
28 namespace Mag_server {
29
30 using L4Re::chksys;
31 using L4Re::chkcap;
32
33 enum { Bar_height = 16 };
34
35 Client_fb::Client_fb(Core_api const *core, Rect const &pos, Point const &offs,
36                      Texture *fb, L4::Cap<L4Re::Dataspace> const &fb_ds)
37 : View(pos.offset(0, 0, 0, Bar_height), F_need_frame),
38   Icu_svr(1, &_ev_irq),
39   _core(core), _offs(offs), _fb(fb),
40   _bar_size(pos.w(), Bar_height)
41 {
42   using L4Re::Video::View;
43   using L4Re::Video::Color_component;
44   using L4Re::Video::Goos;
45
46   _fb_ds = fb_ds;
47   _view_info.flags = View::F_none;
48
49   _view_info.view_index = 0;
50   _view_info.xpos = 0;
51   _view_info.ypos = 0;
52   _view_info.width = fb->size().w();
53   _view_info.height = fb->size().h();
54   _view_info.buffer_offset = 0;
55   _view_info.buffer_index = 0;
56   _view_info.bytes_per_line = _view_info.width * fb->type()->bytes_per_pixel();
57   _view_info.pixel_info = *fb->type();
58
59   _screen_info.flags = Goos::F_pointer;
60   _screen_info.width = _view_info.width;
61   _screen_info.height = _view_info.height;
62   _screen_info.num_static_views = 1;
63   _screen_info.num_static_buffers = 1;
64   _screen_info.pixel_info = _view_info.pixel_info;
65
66
67   L4Re::Env const *e = L4Re::Env::env();
68   _ev_ds = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
69
70   chksys(e->mem_alloc()->alloc(L4_PAGESIZE, _ev_ds.get()));
71   chksys(e->rm()->attach(&_ev_ds_m, L4_PAGESIZE, L4Re::Rm::Search_addr, _ev_ds.get(), 0, L4_PAGESHIFT));
72
73   _events = L4Re::Event_buffer(_ev_ds_m.get(), L4_PAGESIZE);
74 }
75
76 void
77 Client_fb::draw(Canvas *canvas, View_stack const *, Mode mode) const
78 {
79   /* use dimming in x-ray mode */
80   Canvas::Mix_mode op = mode.flat() ? Canvas::Solid : Canvas::Mixed;
81
82   /* is this the currently focused view? */
83   Rgb32::Color frame_color = focused() ? Rgb32::White : View::frame_color();
84
85   /* do not dim the focused view in x-ray mode */
86   if (mode.xray() && !mode.kill() && focused())
87     op = Canvas::Solid;
88
89   /*
90    * The view content and label should never overdraw the
91    * frame of the view in non-flat Nitpicker modes. The frame
92    * is located outside the view area. By shrinking the
93    * clipping area to the view area, we protect the frame.
94    */
95   Clip_guard clip_guard(canvas, *this);
96
97   /*
98    * If the clipping area shrinked to zero,
99    * we do not process drawing operations.
100    */
101   if (!canvas->clip_valid()/* || !_session*/)
102     return;
103
104   /* draw view content */
105   Rgb32::Color mix_color = mode.kill() ? kill_color() : Rgb32::Black;
106
107   canvas->draw_box(Rect(p1(), _bar_size), Rgb32::Color(56, 68,88));
108
109   canvas->draw_texture(_fb, mix_color, _offs + p1() + Point(0, _bar_size.h()), op);
110
111 #if 0
112   if (mode.flat())
113     return;
114
115   /* draw label */
116   draw_label(canvas, _label_rect.p1(), _session->label(), WHITE, _title, frame_color);
117 #endif
118 }
119
120 void
121 Client_fb::handle_event(L4Re::Event_buffer::Event const &e,
122                         Point const &mouse)
123 {
124   static Point left_drag;
125
126   if (e.payload.type == L4RE_EV_ABS && e.payload.code == 1 && left_drag != Point())
127     {
128       Rect npos = Rect(p1() + mouse - left_drag, size());
129       left_drag = mouse;
130       _core->user_state()->vstack()->viewport(this, npos, true);
131       return;
132     }
133
134   if (e.payload.type == L4RE_EV_KEY)
135     {
136       View_stack *_stack = _core->user_state()->vstack();
137       if (e.payload.code == L4RE_BTN_LEFT && e.payload.value == 1 &&
138           !_stack->on_top(this))
139         _stack->push_top(this);
140
141       if (e.payload.code == L4RE_BTN_LEFT && Rect(p1(), _bar_size).contains(mouse))
142         {
143           if (e.payload.value == 1)
144             left_drag = mouse;
145           else if (e.payload.value == 0)
146             left_drag = Point();
147           return;
148         }
149     }
150
151   if (e.payload.type == L4RE_EV_ABS && e.payload.code <= L4RE_ABS_Y)
152     {
153       // wait for the following ABS_Y axis
154       if (e.payload.type == L4RE_ABS_X)
155         return;
156
157       Rect r = (*this - Rect(p1(), _bar_size)).b;
158       if (!r.contains(mouse))
159         return;
160
161       Point mp = p1() + Point(0, _bar_size.h());
162       mp = Point(_fb->size()).min(Point(0,0).max(mouse - mp));
163       L4Re::Event_buffer::Event ne;
164       ne.time = e.time;
165       ne.payload.type = L4RE_EV_ABS;
166       ne.payload.code = L4RE_ABS_X;
167       ne.payload.value = mp.x();
168       ne.payload.stream_id = e.payload.stream_id;
169       _events.put(ne);
170       ne.payload.code = L4RE_ABS_Y;
171       ne.payload.value = mp.y();
172       _events.put(ne);
173       _ev_irq.trigger();
174       return;
175     }
176
177   if (_events.put(e))
178     _ev_irq.trigger();
179
180 }
181
182
183 int
184 Client_fb::refresh(int x, int y, int w, int h)
185 {
186   _core->user_state()->vstack()->refresh_view(this, 0, Rect(p1() + Point(x, y + _bar_size.h()), Area(w, h)));
187   return 0;
188 }
189
190 int
191 Client_fb::dispatch(l4_umword_t obj, L4::Ipc_iostream &s)
192 {
193   l4_msgtag_t tag;
194   s >> tag;
195
196   switch (tag.label())
197     {
198     case L4::Meta::Protocol:
199       return L4Re::Util::handle_meta_request<L4Re::Console>(s);
200     case L4_PROTO_IRQ:
201       return Icu_svr::dispatch(obj, s);
202     case L4Re::Protocol::Goos:
203       return L4Re::Util::Video::Goos_svr::dispatch(obj, s);
204     case L4Re::Protocol::Event:
205         {
206           L4::Opcode op;
207           s >> op;
208           switch (op)
209             {
210             case L4Re::Event_::Get:
211               s << _ev_ds.get();
212               return L4_EOK;
213             default:
214               return -L4_ENOSYS;
215             }
216         }
217     default:
218       return -L4_EBADPROTO;
219     }
220 }
221
222
223 void
224 Client_fb::destroy()
225 {
226   _core->user_state()->forget_view(this);
227   delete _fb;
228   _fb = 0;
229 }
230
231 }