]> 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 "input_source"
11 #include "user_state"
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 #include <cstring>
21
22 #include "lua_glue.swg.h"
23
24 //#define CONFIG_SCREENSHOT
25 #if defined (CONFIG_SCREENSHOT)
26 # include <zlib.h>
27
28
29 namespace {
30
31 using namespace Mag_server;
32
33 static void base64_encodeblock(char const *_in, char *out)
34 {
35   unsigned char const *in = (unsigned char const *)_in;
36
37   out[0] = (in[0] >> 2) + ' ';
38   out[1] = (((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)) + ' ';
39   out[2] = (((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)) + ' ';
40   out[3] = (in[2] & 0x3f) + ' ';
41 }
42
43 static void uuencode(char const *in, unsigned long bytes)
44 {
45   char uubuf[100];
46   char *out;
47
48   while (bytes)
49     {
50       unsigned cnt = 0;
51       out = uubuf;
52
53       while (bytes)
54         {
55           unsigned n = 3;
56           if (bytes < n)
57             n = bytes;
58
59           if (cnt + n > 45)
60             break;
61
62           base64_encodeblock(in, out);
63           in += 3;
64           out += 4;
65
66           bytes -= n;
67           cnt += n;
68         }
69       *out = 0;
70
71       printf("%c%s\n", cnt + ' ', uubuf);
72     }
73 }
74
75 static void maybe_screenshot(User_state *ust, User_state::Event const &e)
76 {
77   if (e.payload.type != L4RE_EV_KEY || e.payload.value != 1
78       || e.payload.code != L4RE_KEY_F12)
79     return;
80
81   char obuf[1024];
82   int flush;
83   printf("Start screen shot ==========================\n");
84   printf("begin 600 screenshot.Z\n");
85
86   z_stream s;
87   s.zalloc = Z_NULL;
88   s.zfree = Z_NULL;
89   s.opaque = Z_NULL;
90   s.next_in = (Bytef*)ust->vstack()->canvas()->buffer();
91   s.avail_in = ust->vstack()->canvas()->size().h() * ust->vstack()->canvas()->bytes_per_line();
92   s.total_in = s.avail_in;
93   s.total_out = 0;
94
95   deflateInit2(&s, 9, Z_DEFLATED, 16 + 15, 9, Z_DEFAULT_STRATEGY);
96
97   do
98     {
99       flush = s.avail_in ? Z_NO_FLUSH : Z_FINISH;
100       do
101         {
102           s.next_out = (Bytef*)obuf;
103           s.avail_out = sizeof(obuf);
104
105           if (deflate(&s, flush) == Z_STREAM_ERROR)
106             {
107               printf("\nERROR: compressing screenshot\n");
108               break;
109             }
110
111           unsigned b = sizeof(obuf) - s.avail_out;
112           if (b)
113             uuencode(obuf, b);
114         }
115       while (s.avail_out == 0);
116     }
117   while (flush != Z_FINISH); //s.avail_out == 0);
118
119   deflateEnd(&s);
120   printf(" \nend\n");
121   printf("\nEND screen shot ==========================\n");
122 }
123
124 }
125 #else
126 inline void maybe_screenshot(Mag_server::User_state *, Mag_server::User_state::Event const &) {}
127 #endif
128
129 int luaopen_Mag(lua_State*);
130
131 namespace Mag_server {
132
133 User_state *user_state;
134
135 Hid_report::Hid_report(l4_umword_t dev_id, unsigned rels, unsigned abss, unsigned mscs,
136                        unsigned sws, unsigned mts)
137 : _device_id(dev_id), _kevs(0), _abs_info(0)
138 {
139   _vals[0].create(rels, 0);
140   _vals[1].create(abss, 0);
141   _vals[2].create(mscs, 0);
142   _vals[3].create(sws, 0);
143
144   _mts = 0;
145   if (mts)
146     {
147       _mts = mts + 1;
148       _mt = new Valuator<int>[_mts];
149     }
150
151   for (unsigned i = 0; i < _mts; ++i)
152     _mt[i].create(Num_mt_vals, Mt_val_offset); // 13 mt axes, currently
153 }
154
155 Hid_report::~Hid_report()
156 {
157   if (_mts)
158     delete [] _mt;
159 }
160
161 void
162 Hid_report::clear()
163 {
164   for (unsigned i = 0; i < Num_types; ++i)
165     _vals[i].clear();
166
167   for (unsigned i = 0; i < _mts; ++i)
168     _mt[i].clear();
169
170   _kevs = 0;
171 }
172
173 Valuator<int> const *
174 Hid_report::get_vals(unsigned char type) const
175 {
176   // check for out of range...
177   if (type < Type_offset || (type = type - Type_offset) >= Num_types)
178     return 0;
179
180   return &_vals[type];
181 }
182
183 Valuator<int> *
184 Hid_report::get_vals(unsigned char type)
185 {
186   // check for out of range...
187   if (type < Type_offset || (type = type - Type_offset) >= Num_types)
188     return 0;
189
190   return &_vals[type];
191 }
192
193 Valuator<int> const *
194 Hid_report::get_mt_vals(unsigned id) const
195 {
196   if (_mts && id < _mts - 1)
197     return &_mt[id];
198
199   return 0;
200 }
201
202 bool
203 Hid_report::get(unsigned char type, unsigned code, int &val) const
204 {
205   // check for out of range...
206   if (type < Type_offset || (type = type - Type_offset) >= Num_types)
207     return false;
208
209   if (!_vals[type].valid(code))
210     return false;
211
212   val = _vals[type][code].val();
213   return true;
214 }
215
216 void
217 Hid_report::set(unsigned char type, unsigned code, int val)
218 {
219   // check for out of range...
220   if (type < Type_offset || (type = type - Type_offset) >= Num_types)
221     return;
222
223   _vals[type].set(code, val);
224 }
225
226 bool
227 Hid_report::mt_get(unsigned id, unsigned code, int &val) const
228 {
229   if (id >= _mts)
230     return false;
231
232   if (!_mt[id].valid(code))
233     return false;
234
235   val = _mt[id][code].val();
236   return true;
237 }
238
239 void
240 Hid_report::mt_set(unsigned code, int val)
241 {
242   if (!_mts)
243     return;
244
245   _mt[_mts-1].set(code, val);
246 }
247
248 bool
249 Hid_report::submit_mt()
250 {
251   if (!_mts)
252     return false;
253
254   Valuator<int> &s = _mt[_mts-1];
255   Value<int> id = s[0x39];
256   if (!id.valid())
257     {
258       s.clear();
259       return false;
260     }
261
262   if (id.val() >= (long)_mts - 1)
263     {
264       s.clear();
265       return false;
266     }
267
268   _mt[id.val()].swap(s);
269   return true;
270 }
271
272 bool
273 Hid_report::add_key(int code, int value)
274 {
275   if (_kevs >= Num_key_events)
276     return false;
277
278   _kev[_kevs].code = code;
279   _kev[_kevs].value = value;
280   ++_kevs;
281   return true;
282 }
283
284 Hid_report::Key_event const *
285 Hid_report::get_key_event(unsigned idx) const
286 {
287   if (idx < _kevs)
288     return _kev + idx;
289
290   return 0;
291 }
292
293 Hid_report::Key_event const *
294 Hid_report::find_key_event(int code) const
295 {
296   for (unsigned i = 0; i < _kevs; ++i)
297     if (_kev[i].code == code)
298       return _kev + i;
299
300   return 0;
301 }
302
303 void
304 Hid_report::remove_key_event(int code)
305 {
306   unsigned i;
307   for (i = 0; i < _kevs && _kev[i].code != code; ++i)
308     ;
309
310   if (i >= _kevs)
311     return;
312
313   memmove(_kev + i, _kev + i + 1, (_kevs - i - 1) * sizeof(Key_event));
314   --_kevs;
315 }
316
317
318 void
319 User_state::set_pointer(int x, int y, bool hide)
320 {
321   Point p(x, y);
322   Rect scr(Point(0, 0), vstack()->canvas()->size());
323   p = p.min(scr.p2());
324   p = p.max(scr.p1());
325
326   _mouse_pos = p;
327   if (hide && _mouse_cursor->x1() < scr.x2())
328     vstack()->viewport(_mouse_cursor, Rect(scr.p2(), _mouse_cursor->size()), true);
329
330   if (!hide && _mouse_cursor->p1() != _mouse_pos)
331     vstack()->viewport(_mouse_cursor, Rect(_mouse_pos, _mouse_cursor->size()), true);
332 }
333
334 #if 0
335 static void dump_stack(lua_State *l)
336 {
337   int i = lua_gettop(l);
338   while (i)
339     {
340       int t = lua_type(l, i);
341       switch (t)
342         {
343         case LUA_TSTRING:
344           printf("#%02d: '%s'\n", i, lua_tostring(l, i));
345           break;
346         case LUA_TBOOLEAN:
347           printf("#%02d: %s\n", i, lua_toboolean(l, i) ? "true" : "false");
348           break;
349         case LUA_TNUMBER:
350           printf("#%02d: %g\n", i, lua_tonumber(l, i));
351           break;
352         default:
353           printf("#%02d: [%s] %p\n", i, lua_typename(l, t), lua_topointer(l, i));
354           break;
355         }
356
357       --i;
358     }
359 }
360 #endif
361
362 User_state::User_state(lua_State *lua, View_stack *_vstack, View *cursor)
363 : _vstack(_vstack), _mouse_pos(0,0), _keyboard_focus(0),
364   _mouse_cursor(cursor), _l(lua)
365 {
366   user_state = this;
367   if (_mouse_cursor)
368     {
369       vstack()->push_top(_mouse_cursor, true);
370       Point pos(vstack()->canvas()->size());
371       vstack()->viewport(_mouse_cursor, Rect(pos, _mouse_cursor->size()), true);
372     }
373   vstack()->update_all_views();
374   luaopen_Mag(lua);
375 }
376
377 User_state::~User_state()
378 {
379   user_state = 0;
380 }
381
382 void
383 User_state::forget_view(View *v)
384 {
385   vstack()->forget_view(v);
386   for (View_proxy *p = _view_proxies; p; p = p->_n)
387     p->forget(v);
388
389   if (_keyboard_focus == v)
390     _keyboard_focus = 0;
391
392   if (_vstack->focused() == v)
393     {
394       _vstack->set_focused(0);
395       _vstack->update_all_views();
396     }
397 }
398
399 bool
400 User_state::set_focus(View *v)
401 {
402   if (_keyboard_focus == v)
403     return false;
404
405   if (_keyboard_focus)
406     _keyboard_focus->set_focus(false);
407   _keyboard_focus = v;
408   _vstack->set_focused(v);
409
410   if (v)
411     v->set_focus(true);
412
413   return true;
414 }
415
416 int
417 User_state::get_input_stream_info_for_id(l4_umword_t id, Input_info *info) const
418 {
419   lua_State *l = _l;
420   int top = lua_gettop(l);
421   lua_getglobal(l, "input_source_info");
422   lua_pushinteger(l, id);
423   if (lua_pcall(l, 1, 2, 0))
424     {
425       fprintf(stderr, "ERROR: lua event handling returned: %s.\n", lua_tostring(l, -1));
426       lua_pop(l, 1);
427       return -L4_ENOSYS;
428     }
429
430   int r = lua_tointeger(l, -2);
431   if (r < 0)
432     {
433       lua_settop(l, top);
434       return r;
435     }
436
437
438   L4Re::Event_stream_info *i = 0;
439   swig_type_info *type = SWIG_TypeQuery(l, "L4Re::Event_stream_info *");
440   if (!type)
441     {
442       fprintf(stderr, "Ooops: did not find type 'L4Re::Event_stream_info'\n");
443       lua_settop(l, top);
444       return -L4_EINVAL;
445     }
446     if (!SWIG_IsOK(SWIG_ConvertPtr(l, -1, (void**)&i, type, 0)))
447     {
448       fprintf(stderr, "Ooops: expected 'L4Re::Event_stream_info' as arg 2\n");
449       lua_settop(l, top);
450       return -L4_EINVAL;
451     }
452
453   if (!i)
454     {
455       lua_settop(l, top);
456       return -L4_EINVAL;
457     }
458
459   *info = *i;
460   lua_settop(l, top);
461   return r;
462 }
463
464 int
465 User_state::get_input_axis_info(l4_umword_t id, unsigned naxes, unsigned const *axis,
466                                 Input_absinfo *info, unsigned char *ax_mode) const
467 {
468   lua_State *l = _l;
469   int top = lua_gettop(l);
470   lua_getglobal(l, "input_source_abs_info");
471   lua_pushinteger(l, id);
472   for (unsigned i = 0; i < naxes; ++i)
473     lua_pushinteger(l, axis[i]);
474
475   if (lua_pcall(l, 1 + naxes, 1 + naxes, 0))
476     {
477       fprintf(stderr, "ERROR: lua event handling returned: %s.\n", lua_tostring(l, -1));
478       lua_settop(l, top);
479       return -L4_ENOSYS;
480     }
481
482   int r = lua_tointeger(l, top + 1);
483   if (r < 0)
484     {
485       lua_settop(l, top);
486       return r;
487     }
488
489   for (unsigned i = 0; i < naxes; ++i)
490     {
491       int ndx = top + i + 2;
492       if (!lua_istable(l, ndx) && !lua_isuserdata(l, ndx))
493         {
494           fprintf(stderr, "ERROR: lua event handling returned: %s.\n", lua_tostring(l, top + 1));
495           lua_settop(l, top);
496           return -L4_EINVAL;
497         }
498
499       lua_getfield(l, ndx, "value");
500       info[i].value = lua_tointeger(l, -1);
501       lua_pop(l, 1);
502
503       lua_getfield(l, ndx, "min");
504       info[i].min = lua_tointeger(l, -1);
505       lua_pop(l, 1);
506
507       lua_getfield(l, ndx, "max");
508       info[i].max = lua_tointeger(l, -1);
509       lua_pop(l, 1);
510
511       lua_getfield(l, ndx, "fuzz");
512       info[i].fuzz = lua_tointeger(l, -1);
513       lua_pop(l, 1);
514
515       lua_getfield(l, ndx, "flat");
516       info[i].flat = lua_tointeger(l, -1);
517       lua_pop(l, 1);
518
519       lua_getfield(l, ndx, "resolution");
520       info[i].resolution = lua_tointeger(l, -1);
521       lua_pop(l, 1);
522
523       if (ax_mode)
524         {
525           lua_getfield(l, ndx, "mode");
526           ax_mode[i] = lua_tointeger(l, -1);
527           lua_pop(l, 1);
528         }
529     }
530
531   lua_settop(l, top);
532   return r;
533 }
534
535 }