]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/mag/server/src/user_state.cc
c29da36a5a8449c9909f0059f7917daeec4823b8
[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 (ust->vstack()->mode().kill())
151     return 0;
152
153   if (v)
154     v->handle_event(e, ust->mouse_pos());
155
156   return 0;
157 }
158
159 static int user_state_post_pointer_event(lua_State *l)
160 {
161   User_state *ust = lua_check_class<Lua_user_state>(l, 1)->u;
162   
163   if (ust->vstack()->mode().kill())
164     return 0;
165
166   View *v = ust->kbd_focus();
167   if (!lua_isnil(l, 2))
168     v = lua_check_class<Lua_view_proxy>(l, 2)->view();
169
170   if (!v)
171     return 0;
172
173   Point m = ust->mouse_pos();
174   User_state::Event e;
175   e.time = lua_tonumber(l, 4);
176   e.payload.stream_id = (l4_umword_t)lua_touserdata(l, 3);
177   e.payload.type = L4RE_EV_ABS;
178   e.payload.code = L4RE_ABS_X;
179   e.payload.value = m.x();
180   v->handle_event(e, ust->mouse_pos());
181   e.payload.code = L4RE_ABS_Y;
182   e.payload.value = m.y();
183   v->handle_event(e, ust->mouse_pos());
184
185   return 0;
186 }
187
188 static int user_state_set_pointer(lua_State *l)
189 {
190   User_state *ust = lua_check_class<Lua_user_state>(l, 1)->u;
191
192   int x, y;
193   x = lua_tointeger(l, 2);
194   y = lua_tointeger(l, 3);
195   ust->set_pointer(x, y);
196   return 0;
197 }
198
199 static int user_state_move_pointer(lua_State *l)
200 {
201   User_state *ust = lua_check_class<Lua_user_state>(l, 1)->u;
202
203   int x, y;
204   x = lua_tointeger(l, 2);
205   y = lua_tointeger(l, 3);
206   ust->move_pointer(x, y);
207   return 0;
208 }
209
210
211 static int user_state_toggle_mode(lua_State *l)
212 {
213   User_state *ust = lua_check_class<Lua_user_state>(l, 1)->u;
214
215   int x;
216   x = lua_tointeger(l, 2);
217   ust->vstack()->toggle_mode((Mag_server::Mode::Mode_flag)x);
218   return 0;
219 }
220
221 static int user_state_find_pointed_view(lua_State *l)
222 {
223   User_state *ust = lua_check_class<Lua_user_state>(l, 1)->u;
224   Lua_view_proxy *vp = lua_check_class<Lua_view_proxy>(l, 2);
225   vp->view(ust->vstack()->find(ust->mouse_pos()));
226   return 0;
227 }
228
229 static int user_state_create_view_proxy(lua_State *l)
230 {
231   User_state *ust = lua_check_class<Lua_user_state>(l, 1)->u;
232   if (lua_alloc_class<Lua_view_proxy>(l, ust))
233     return 1;
234
235   return 0;
236 }
237
238
239 static int lua_view_proxy_set(lua_State *l)
240 {
241   int top = lua_gettop(l);
242   Lua_view_proxy *d = lua_check_class<Lua_view_proxy>(l, 1);
243   View *sv = 0;
244   if (top >= 2 || !lua_isnil(l, 2))
245     sv = lua_check_class<Lua_view_proxy>(l, 2)->view();
246   d->view(sv);
247   return 0;
248 }
249
250 static int user_state_set_kbd_focus(lua_State *l)
251 {
252   int top = lua_gettop(l);
253   User_state *ust = lua_check_class<Lua_user_state>(l, 1)->u;
254   View *v = 0;
255   if (top >= 2 && !lua_isnil(l,2))
256     v = lua_check_class<Lua_view_proxy>(l, 2)->view();
257
258   lua_pushboolean(l, ust->set_focus(v));
259   return 1;
260 }
261
262
263 char const *const Lua_user_state::_class = "Mag_server.User_state_class";
264 char const *const Lua_view_proxy::_class = "Mag_server.View_proxy_class";
265
266
267 luaL_Reg const Lua_user_state::_ops[] =
268 { { "set_pointer", &user_state_set_pointer },
269   { "move_pointer", &user_state_move_pointer },
270   { "set_kbd_focus", &user_state_set_kbd_focus },
271   { "post_event", &user_state_post_event },
272   { "post_pointer_event", &user_state_post_pointer_event },
273   { "toggle_mode", &user_state_toggle_mode },
274   { "create_view_proxy", &user_state_create_view_proxy },
275   { "find_pointed_view", &user_state_find_pointed_view },
276   { 0, 0 }
277 };
278
279 luaL_Reg const Lua_view_proxy::_ops[] =
280 { { "set", &lua_view_proxy_set },
281   { 0, 0 }
282 };
283
284
285
286 }
287
288 static void dump_stack(lua_State *l)
289 {
290   int i = lua_gettop(l);
291   while (i)
292     {
293       int t = lua_type(l, i);
294       switch (t)
295         {
296         case LUA_TSTRING:
297           printf("#%02d: '%s'\n", i, lua_tostring(l, i));
298           break;
299         case LUA_TBOOLEAN:
300           printf("#%02d: %s\n", i, lua_toboolean(l, i) ? "true" : "false");
301           break;
302         case LUA_TNUMBER:
303           printf("#%02d: %g\n", i, lua_tonumber(l, i));
304           break;
305         default:
306           printf("#%02d: [%s] %p\n", i, lua_typename(l, t), lua_topointer(l, i));
307           break;
308         }
309
310       --i;
311     }
312 }
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     lua_alloc_class<Lua_view_proxy>(l, u->u);
328     lua_setfield(l, -2, "focused_view");
329   }
330 };
331
332
333 User_state::User_state(lua_State *lua, View_stack *_vstack, View *cursor)
334 : _vstack(_vstack), _mouse_pos(0,0), _keyboard_focus(0),
335   _mouse_cursor(cursor), _l(lua)
336 {
337   lua_getglobal(_l, "Mag");
338   lua_alloc_class<Lua_user_state>(_l, this);
339   lua_setfield(_l, -2, "user_state");
340
341   lua_pushcfunction(_l, &Lua::ab_create);
342   lua_setfield(_l, -2, "Axis_buf");
343
344   lua_pop(_l, 1);
345
346   if (_mouse_cursor)
347     vstack()->push_top(_mouse_cursor, true);
348   vstack()->update_all_views();
349 }
350
351 User_state::~User_state()
352 {
353   lua_getglobal(_l, "Mag");
354   lua_pushnil(_l);
355   lua_setfield(_l, -2, "user_state");
356   lua_pop(_l, 1);
357 }
358
359 void
360 User_state::forget_view(View *v)
361 {
362   vstack()->forget_view(v);
363   for (View_proxy *p = _view_proxies; p; p = p->_n)
364     p->forget(v);
365
366   if (_keyboard_focus == v)
367     _keyboard_focus = 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   if (v)
380     v->set_focus(true);
381
382   return true;
383 }
384
385 void
386 User_state::handle_event(Event const &e)
387 {
388   lua_getfield(_l, LUA_GLOBALSINDEX, "handle_event");
389   lua_pushlightuserdata(_l, const_cast<Event *>(&e));
390   if (lua_pcall(_l, 1, 0, 0))
391     {
392       fprintf(stderr, "ERROR: lua event handling returned: %s.\n", lua_tostring(_l, -1));
393       lua_pop(_l, 1);
394     }
395 }
396
397 }