]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/mag/server/src/user_state.cc
update
[l4.git] / l4 / pkg / mag / server / src / user_state.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 "user_state"
11 #include "lua"
12
13 #include <lua.h>
14 #include <lauxlib.h>
15 #include <lualib.h>
16
17 #include <l4/cxx/exceptions>
18 #include <l4/re/event_enums.h>
19 #include <errno.h>
20
21
22 namespace Mag_server {
23
24 void
25 User_state::set_pointer(int x, int y)
26 {
27   Point p(x, y);
28   Rect scr(Point(0, 0), vstack()->canvas()->size());
29   p = p.min(scr.p2());
30   p = p.max(scr.p1());
31
32   if (_mouse_pos != p)
33     {
34       _mouse_pos = p;
35       vstack()->viewport(_mouse_cursor, Rect(_mouse_pos, _mouse_cursor->size()), true);
36     }
37 }
38
39 namespace {
40
41 namespace Lua {
42
43 class Axis_buf
44 {
45 private:
46   unsigned char s;
47   l4_int32_t v[0];
48
49 public:
50   Axis_buf(unsigned char _s) : s(_s-1) { assert ((_s & s) == 0); }
51   l4_int32_t get(unsigned char idx) const { return v[idx & s]; }
52   void set(unsigned char idx, l4_int32_t val) { v[idx & s] = val; }
53
54   static char const *const _class;
55   static luaL_Reg const _ops[];
56 };
57
58 static int ab_get(lua_State *l)
59 {
60   Axis_buf *s = lua_check_class<Axis_buf>(l, 1);
61   int idx = lua_tointeger(l, 2);
62   lua_pushinteger(l, s->get(idx));
63   return 1;
64 }
65
66 static int ab_set(lua_State *l)
67 {
68   Axis_buf *s = lua_check_class<Axis_buf>(l, 1);
69   int idx = lua_tointeger(l, 2);
70   s->set(idx, lua_tointeger(l, 3));
71   return 0;
72 }
73
74 static int ab_copy(lua_State *l)
75 {
76   Axis_buf *s = lua_check_class<Axis_buf>(l, 1);
77   int idx1 = lua_tointeger(l, 2);
78   int idx2 = lua_tointeger(l, 3);
79   s->set(idx1, s->get(idx2));
80   return 0;
81 }
82
83 static int ab_create(lua_State *l)
84 {
85   unsigned long sz = lua_tointeger(l, 1);
86   unsigned long z;
87   for (z = 0; z < 8 && (1UL << z) < sz; ++z)
88     ;
89   sz = (1UL << z);
90   unsigned long msz = sizeof(Axis_buf) + sizeof(l4_int32_t) * sz;
91   new (lua_newuserdata(l, msz)) Axis_buf(sz);
92
93   if (luaL_newmetatable(l, Axis_buf::_class))
94     {
95       lua_pushcfunction(l, &ab_set);
96       lua_setfield(l, -2, "__newindex");
97       lua_newtable(l);
98       Lua_register_ops<Axis_buf>::init(l);
99       lua_setfield(l, -2, "__index");
100     }
101   lua_setmetatable(l, -2);
102   return 1;
103 }
104
105 char const *const Axis_buf::_class = "Mag_server.Lua.Axis_buf";
106 luaL_Reg const Axis_buf::_ops[] = {
107       { "get", &ab_get },
108       { "set", &ab_set },
109       { "copy", &ab_copy },
110       { 0, 0 }
111 };
112
113
114 }
115
116
117 struct Lua_user_state
118 {
119   User_state *u;
120   static char const *const _class;
121   static luaL_Reg const _ops[];
122   explicit Lua_user_state(User_state *u) : u(u) {}
123 };
124
125 struct Lua_view_proxy : public User_state::View_proxy
126 {
127   explicit Lua_view_proxy(User_state *u) : View_proxy(u) {}
128   static char const *const _class;
129   static luaL_Reg const _ops[];
130 };
131
132 static int user_state_post_event(lua_State *l)
133 {
134   int top = lua_gettop(l);
135   User_state *ust = lua_check_class<Lua_user_state>(l, 1)->u;
136   View *v = ust->kbd_focus();
137   if (top >= 2 && !lua_isnil(l, 2))
138     v = lua_check_class<Lua_view_proxy>(l, 2)->view();
139
140   User_state::Event e;
141   e.time = lua_tonumber(l, 4);
142   e.payload.stream_id = (l4_umword_t)lua_touserdata(l, 3);
143   e.payload.type = lua_tointeger(l, 5);
144   e.payload.code = lua_tointeger(l, 6);
145   e.payload.value = lua_tointeger(l, 7);
146
147   if (top >= 8 && lua_toboolean(l, 8))
148     ust->vstack()->update_all_views();
149
150   if (v && (!ust->vstack()->mode().kill() || v->super_view()))
151     v->handle_event(e, ust->mouse_pos());
152
153   return 0;
154 }
155
156 static int user_state_post_pointer_event(lua_State *l)
157 {
158   User_state *ust = lua_check_class<Lua_user_state>(l, 1)->u;
159  
160
161   View *v = ust->kbd_focus();
162   if (!lua_isnil(l, 2))
163     v = lua_check_class<Lua_view_proxy>(l, 2)->view();
164
165   if (!v)
166     return 0;
167
168   if (ust->vstack()->mode().kill() && !v->super_view())
169     return 0;
170
171   Point m = ust->mouse_pos();
172   User_state::Event e;
173   e.time = lua_tonumber(l, 4);
174   e.payload.stream_id = (l4_umword_t)lua_touserdata(l, 3);
175   e.payload.type = L4RE_EV_ABS;
176   e.payload.code = L4RE_ABS_X;
177   e.payload.value = m.x();
178   v->handle_event(e, ust->mouse_pos());
179   e.payload.code = L4RE_ABS_Y;
180   e.payload.value = m.y();
181   v->handle_event(e, ust->mouse_pos());
182
183   return 0;
184 }
185
186 static int user_state_set_pointer(lua_State *l)
187 {
188   User_state *ust = lua_check_class<Lua_user_state>(l, 1)->u;
189
190   int x, y;
191   x = lua_tointeger(l, 2);
192   y = lua_tointeger(l, 3);
193   ust->set_pointer(x, y);
194   return 0;
195 }
196
197 static int user_state_move_pointer(lua_State *l)
198 {
199   User_state *ust = lua_check_class<Lua_user_state>(l, 1)->u;
200
201   int x, y;
202   x = lua_tointeger(l, 2);
203   y = lua_tointeger(l, 3);
204   ust->move_pointer(x, y);
205   return 0;
206 }
207
208
209 static int user_state_toggle_mode(lua_State *l)
210 {
211   User_state *ust = lua_check_class<Lua_user_state>(l, 1)->u;
212
213   int x;
214   x = lua_tointeger(l, 2);
215   ust->vstack()->toggle_mode((Mag_server::Mode::Mode_flag)x);
216   return 0;
217 }
218
219 static int user_state_find_pointed_view(lua_State *l)
220 {
221   User_state *ust = lua_check_class<Lua_user_state>(l, 1)->u;
222   Lua_view_proxy *vp = lua_check_class<Lua_view_proxy>(l, 2);
223   vp->view(ust->vstack()->find(ust->mouse_pos()));
224   return 0;
225 }
226
227 static int user_state_create_view_proxy(lua_State *l)
228 {
229   User_state *ust = lua_check_class<Lua_user_state>(l, 1)->u;
230   if (lua_alloc_class<Lua_view_proxy>(l, ust))
231     return 1;
232
233   return 0;
234 }
235
236
237 static int lua_view_proxy_set(lua_State *l)
238 {
239   int top = lua_gettop(l);
240   Lua_view_proxy *d = lua_check_class<Lua_view_proxy>(l, 1);
241   View *sv = 0;
242   if (top >= 2 || !lua_isnil(l, 2))
243     sv = lua_check_class<Lua_view_proxy>(l, 2)->view();
244   d->view(sv);
245   return 0;
246 }
247
248 static int user_state_set_kbd_focus(lua_State *l)
249 {
250   int top = lua_gettop(l);
251   User_state *ust = lua_check_class<Lua_user_state>(l, 1)->u;
252   View *v = 0;
253   if (top >= 2 && !lua_isnil(l,2))
254     v = lua_check_class<Lua_view_proxy>(l, 2)->view();
255
256   lua_pushboolean(l, ust->set_focus(v));
257   return 1;
258 }
259
260
261 char const *const Lua_user_state::_class = "Mag_server.User_state_class";
262 char const *const Lua_view_proxy::_class = "Mag_server.View_proxy_class";
263
264
265 luaL_Reg const Lua_user_state::_ops[] =
266 { { "set_pointer", &user_state_set_pointer },
267   { "move_pointer", &user_state_move_pointer },
268   { "set_kbd_focus", &user_state_set_kbd_focus },
269   { "post_event", &user_state_post_event },
270   { "post_pointer_event", &user_state_post_pointer_event },
271   { "toggle_mode", &user_state_toggle_mode },
272   { "create_view_proxy", &user_state_create_view_proxy },
273   { "find_pointed_view", &user_state_find_pointed_view },
274   { 0, 0 }
275 };
276
277 luaL_Reg const Lua_view_proxy::_ops[] =
278 { { "set", &lua_view_proxy_set },
279   { 0, 0 }
280 };
281
282
283
284 }
285
286 #if 0
287 static void dump_stack(lua_State *l)
288 {
289   int i = lua_gettop(l);
290   while (i)
291     {
292       int t = lua_type(l, i);
293       switch (t)
294         {
295         case LUA_TSTRING:
296           printf("#%02d: '%s'\n", i, lua_tostring(l, i));
297           break;
298         case LUA_TBOOLEAN:
299           printf("#%02d: %s\n", i, lua_toboolean(l, i) ? "true" : "false");
300           break;
301         case LUA_TNUMBER:
302           printf("#%02d: %g\n", i, lua_tonumber(l, i));
303           break;
304         default:
305           printf("#%02d: [%s] %p\n", i, lua_typename(l, t), lua_topointer(l, i));
306           break;
307         }
308
309       --i;
310     }
311 }
312 #endif
313
314 template<>
315 struct Lua_register_ops<Lua_user_state>
316 {
317   static void init(lua_State *l)
318   {
319     luaL_register(l, NULL, Lua_user_state::_ops);
320     Lua_user_state *u = (Lua_user_state*)lua_touserdata(l, -3);
321     Area sz = u->u->vstack()->canvas()->size();
322     lua_pushinteger(l, sz.w());
323     lua_setfield(l, -2, "width");
324     lua_pushinteger(l, sz.h());
325     lua_setfield(l, -2, "height");
326   }
327 };
328
329
330 User_state::User_state(lua_State *lua, View_stack *_vstack, View *cursor)
331 : _vstack(_vstack), _mouse_pos(0,0), _keyboard_focus(0),
332   _mouse_cursor(cursor), _l(lua)
333 {
334   lua_getglobal(_l, "Mag");
335   lua_alloc_class<Lua_user_state>(_l, this);
336   lua_setfield(_l, -2, "user_state");
337
338   lua_pushcfunction(_l, &Lua::ab_create);
339   lua_setfield(_l, -2, "Axis_buf");
340
341   lua_pop(_l, 1);
342
343   if (_mouse_cursor)
344     vstack()->push_top(_mouse_cursor, true);
345   vstack()->update_all_views();
346 }
347
348 User_state::~User_state()
349 {
350   lua_getglobal(_l, "Mag");
351   lua_pushnil(_l);
352   lua_setfield(_l, -2, "user_state");
353   lua_pop(_l, 1);
354 }
355
356 void
357 User_state::forget_view(View *v)
358 {
359   vstack()->forget_view(v);
360   for (View_proxy *p = _view_proxies; p; p = p->_n)
361     p->forget(v);
362
363   if (_keyboard_focus == v)
364     _keyboard_focus = 0;
365
366   if (_vstack->focused() == v)
367     _vstack->set_focused(0);
368 }
369
370 bool
371 User_state::set_focus(View *v)
372 {
373   if (_keyboard_focus == v)
374     return false;
375
376   if (_keyboard_focus)
377     _keyboard_focus->set_focus(false);
378   _keyboard_focus = v;
379   _vstack->set_focused(v);
380
381   if (v)
382     v->set_focus(true);
383
384   return true;
385 }
386
387 void
388 User_state::handle_event(Event const &e)
389 {
390   lua_getfield(_l, LUA_GLOBALSINDEX, "handle_event");
391   lua_pushlightuserdata(_l, const_cast<Event *>(&e));
392   if (lua_pcall(_l, 1, 0, 0))
393     {
394       fprintf(stderr, "ERROR: lua event handling returned: %s.\n", lua_tostring(_l, -1));
395       lua_pop(_l, 1);
396     }
397 }
398
399 }