ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/cf.schmorp.de/dclient/src/frontend/client/input_handler.cpp
Revision: 1.8
Committed: Sun Oct 24 20:31:52 2010 UTC (16 years ago) by sf-pippijn
Branch: MAIN
Changes since 1.7: +30 -29 lines
Log Message:
use EV and plain sockets instead of asio

File Contents

# User Rev Content
1 sf-pippijn 1.1 #include "deliantra/sender.h"
2    
3     #include "dclient/input_handler.h"
4 sf-pippijn 1.6 #include "dclient/render_glyph.h"
5 sf-pippijn 1.1 #include "dclient/widgets.h"
6 sf-pippijn 1.3 #include "dclient/widgets/inventory.h"
7 sf-pippijn 1.1 #include "dclient/widgets/map.h"
8 sf-pippijn 1.3 #include "dclient/widgets/query.h"
9     #include "dclient/widgets/stats.h"
10 sf-pippijn 1.1
11     #include "adt/bind.h"
12    
13 sf-pippijn 1.8 #include <ndk/application.hh>
14     #include <ndk/color.hh>
15 sf-pippijn 1.1
16     #include <curses.h>
17    
18 sf-pippijn 1.8 #include <ev.h>
19    
20 sf-pippijn 1.1 typedef unsigned long flags_t;
21    
22     enum class flags
23     : flags_t
24     {
25     none,
26     firing = 1 << 0,
27     running = 1 << 1,
28    
29     COUNT
30     };
31    
32     static flags &
33     operator += (flags &lhs, flags rhs)
34     {
35     return lhs = flags (flags_t (lhs) | flags_t (rhs));
36     }
37    
38     static flags &
39     operator -= (flags &lhs, flags rhs)
40     {
41     return lhs = flags (flags_t (lhs) & ~flags_t (rhs));
42     }
43    
44     static bool
45     operator & (flags lhs, flags rhs)
46     {
47     return flags_t (lhs) & flags_t (rhs);
48     }
49    
50    
51     enum class action
52     {
53     none,
54    
55     north,
56     northeast,
57     east,
58     southeast,
59     south,
60     southwest,
61     west,
62     northwest,
63    
64     run,
65     fire,
66     stay_fire,
67    
68     quit,
69     redraw,
70 sf-pippijn 1.3 resize,
71     maximise,
72 sf-pippijn 1.1 input_mode,
73    
74     apply,
75     take,
76    
77     COUNT
78     };
79    
80    
81     struct input_handler::pimpl
82     : sender
83     {
84 sf-pippijn 1.8 pimpl (communicator &comm, widgets &ui);
85 sf-pippijn 1.1
86 sf-pippijn 1.7 void perform (ndk::panel *sender, action cmd, action arg = action::none);
87 sf-pippijn 1.1
88 sf-pippijn 1.3 ndk::event::result on_kbd_common (ndk::keyboard const &ev);
89     ndk::event::result on_kbd_map (ndk::keyboard const &ev);
90 sf-pippijn 1.1
91     void on_command (std::string const &cmd);
92 sf-pippijn 1.8 void stdin_read_cb (ev::io &w, int revents);
93 sf-pippijn 1.1
94     widgets &ui;
95     std::string esc;
96 sf-pippijn 1.8 ev::io stdin_watcher;
97 sf-pippijn 1.1 flags state;
98     };
99    
100 sf-pippijn 1.8 input_handler::pimpl::pimpl (communicator &comm, widgets &ui)
101 sf-pippijn 1.1 : sender (comm)
102     , ui (ui)
103     , state (flags::none)
104     {
105 sf-pippijn 1.3 auto kbd_common = ndk::slot (&pimpl::on_kbd_common, this);
106    
107     ui.map->events ()->on_keyboard (kbd_common);
108     ui.info->events ()->on_keyboard (kbd_common);
109     ui.stats->events ()->on_keyboard (kbd_common);
110     ui.inventory->events ()->on_keyboard (kbd_common);
111     ui.container->events ()->on_keyboard (kbd_common);
112     ui.invmenu->events ()->on_keyboard (kbd_common);
113     ui.query->events ()->on_keyboard (kbd_common);
114    
115     ui.map->events ()->on_keyboard (ndk::slot (&pimpl::on_kbd_map, this));
116    
117     ui.input->on_commit () = ndk::slot (&pimpl::on_command, this);
118 sf-pippijn 1.8
119     stdin_watcher.set (STDIN_FILENO, ev::READ);
120     stdin_watcher.set<pimpl, &pimpl::stdin_read_cb> (this);
121     stdin_watcher.start ();
122 sf-pippijn 1.1 }
123    
124     void
125 sf-pippijn 1.7 input_handler::pimpl::perform (ndk::panel *sender, action cmd, action arg)
126 sf-pippijn 1.1 {
127 sf-pippijn 1.8 struct ev_loop *loop = ev_default_loop ();
128    
129 sf-pippijn 1.1 if (state & flags::running)
130     {
131     send ("command", "run_stop");
132     state -= flags::running;
133     }
134     if (state & flags::firing)
135     {
136     send ("command", "fire_stop");
137     state -= flags::firing;
138     }
139    
140     switch (cmd)
141     {
142     case action::none:
143     break;
144    
145     // direction commands
146     case action::north: send ("command", "north" ); break;
147     case action::northeast: send ("command", "northeast"); break;
148     case action::east: send ("command", "east" ); break;
149     case action::southeast: send ("command", "southeast"); break;
150     case action::south: send ("command", "south" ); break;
151     case action::southwest: send ("command", "southwest"); break;
152     case action::west: send ("command", "west" ); break;
153     case action::northwest: send ("command", "northwest"); break;
154    
155     // running
156     case action::run:
157     send ("command", "run ", int (arg));
158     state += flags::running;
159     break;
160    
161     // firing
162     case action::fire:
163     send ("command", "fire ", int (arg));
164     state += flags::firing;
165     break;
166    
167     case action::stay_fire:
168     send ("command", "stay fire");
169     break;
170    
171     // control commands
172     case action::quit:
173 sf-pippijn 1.8 ev_break (EV_A_ EVBREAK_ALL);
174 sf-pippijn 1.1 break;
175    
176     case action::redraw:
177     redrawwin (stdscr);
178     break;
179    
180 sf-pippijn 1.3 case action::resize:
181     ui.resize ();
182     break;
183    
184     case action::maximise:
185     if (ui.maximised)
186     ui.maximised = nullptr;
187     else
188     ui.maximised = sender;
189     perform (sender, action::resize);
190     break;
191    
192 sf-pippijn 1.1 case action::input_mode:
193 sf-pippijn 1.3 ui.input->visualize ();
194     ui.input->focus ();
195 sf-pippijn 1.1 break;
196    
197     // action commands
198     case action::apply:
199     send ("command", "apply");
200     break;
201    
202     case action::take:
203     send ("command", "take");
204     break;
205    
206     // never happens
207     case action::COUNT:
208     abort ();
209     }
210     }
211    
212     ndk::event::result
213 sf-pippijn 1.3 input_handler::pimpl::on_kbd_common (ndk::keyboard const &ev)
214 sf-pippijn 1.1 {
215     switch (ev.code ())
216     {
217     case ndk::key::error:
218     throw "ERR";
219    
220 sf-pippijn 1.3 // control actions
221     case ndk::key::ctrl_d:
222     case 'q':
223     perform (ev.sender (), action::quit);
224     return ndk::event::accepted;
225    
226     case ndk::key::ctrl_l:
227     perform (ev.sender (), action::redraw);
228     return ndk::event::accepted;
229    
230     case ndk::key::resize:
231     perform (ev.sender (), action::resize);
232     return ndk::event::accepted;
233    
234     case ndk::key::F10:
235     perform (ev.sender (), action::maximise);
236     return ndk::event::accepted;
237    
238     default:
239     return ndk::event::ignored;
240     }
241     }
242    
243     ndk::event::result
244     input_handler::pimpl::on_kbd_map (ndk::keyboard const &ev)
245     {
246     switch (ev.code ())
247     {
248 sf-pippijn 1.1 // moving
249     case 'j':
250     case '2':
251     case ndk::key::down:
252 sf-pippijn 1.3 perform (ev.sender (), action::south);
253 sf-pippijn 1.1 return ndk::event::accepted;
254     case 'k':
255     case '8':
256     case ndk::key::up:
257 sf-pippijn 1.3 perform (ev.sender (), action::north);
258 sf-pippijn 1.1 return ndk::event::accepted;
259     case 'h':
260     case '4':
261     case ndk::key::left:
262 sf-pippijn 1.3 perform (ev.sender (), action::west);
263 sf-pippijn 1.1 return ndk::event::accepted;
264     case 'l':
265     case '6':
266     case ndk::key::right:
267 sf-pippijn 1.3 perform (ev.sender (), action::east);
268 sf-pippijn 1.1 return ndk::event::accepted;
269     case '7':
270     case ndk::key::home:
271 sf-pippijn 1.3 perform (ev.sender (), action::northwest);
272 sf-pippijn 1.1 return ndk::event::accepted;
273     case '9':
274     case ndk::key::pg_up:
275 sf-pippijn 1.3 perform (ev.sender (), action::northeast);
276 sf-pippijn 1.1 return ndk::event::accepted;
277     case '5':
278     case ndk::key::numpad_center:
279 sf-pippijn 1.3 perform (ev.sender (), action::stay_fire);
280 sf-pippijn 1.1 return ndk::event::accepted;
281     case '1':
282     case ndk::key::end:
283 sf-pippijn 1.3 perform (ev.sender (), action::southwest);
284 sf-pippijn 1.1 return ndk::event::accepted;
285     case '3':
286     case ndk::key::pg_dn:
287 sf-pippijn 1.3 perform (ev.sender (), action::southeast);
288 sf-pippijn 1.1 return ndk::event::accepted;
289    
290     case ' ':
291 sf-pippijn 1.3 perform (ev.sender (), action::apply);
292 sf-pippijn 1.1 return ndk::event::accepted;
293     case ',':
294 sf-pippijn 1.3 perform (ev.sender (), action::take);
295 sf-pippijn 1.1 return ndk::event::accepted;
296     case ndk::key::enter:
297     case 'i':
298 sf-pippijn 1.3 perform (ev.sender (), action::input_mode);
299 sf-pippijn 1.1 return ndk::event::accepted;
300     case 'c':
301 sf-pippijn 1.3 ui.input->set_text ("chat ");
302     perform (ev.sender (), action::input_mode);
303 sf-pippijn 1.1 return ndk::event::accepted;
304     case '"':
305 sf-pippijn 1.3 ui.input->set_text ("say ");
306     perform (ev.sender (), action::input_mode);
307 sf-pippijn 1.1 return ndk::event::accepted;
308     case '\'':
309 sf-pippijn 1.3 ui.input->set_text ("tell ");
310     perform (ev.sender (), action::input_mode);
311 sf-pippijn 1.1 return ndk::event::accepted;
312    
313     // firing
314     case 'J':
315     case ndk::key::shift_down:
316 sf-pippijn 1.3 perform (ev.sender (), action::fire, action::south);
317 sf-pippijn 1.1 return ndk::event::accepted;
318     case 'K':
319     case ndk::key::shift_up:
320 sf-pippijn 1.3 perform (ev.sender (), action::fire, action::north);
321 sf-pippijn 1.1 return ndk::event::accepted;
322     case 'H':
323     case ndk::key::shift_left:
324 sf-pippijn 1.3 perform (ev.sender (), action::fire, action::west);
325 sf-pippijn 1.1 return ndk::event::accepted;
326     case 'L':
327     case ndk::key::shift_right:
328 sf-pippijn 1.3 perform (ev.sender (), action::fire, action::east);
329 sf-pippijn 1.1 return ndk::event::accepted;
330     case ndk::key::shift_home:
331 sf-pippijn 1.3 perform (ev.sender (), action::fire, action::northwest);
332 sf-pippijn 1.1 return ndk::event::accepted;
333     case ndk::key::shift_pg_up:
334 sf-pippijn 1.3 perform (ev.sender (), action::fire, action::northeast);
335 sf-pippijn 1.1 return ndk::event::accepted;
336     case ndk::key::shift_end:
337 sf-pippijn 1.3 perform (ev.sender (), action::fire, action::southwest);
338 sf-pippijn 1.1 return ndk::event::accepted;
339     case ndk::key::shift_pg_dn:
340 sf-pippijn 1.3 perform (ev.sender (), action::fire, action::southeast);
341 sf-pippijn 1.1 return ndk::event::accepted;
342    
343     // running
344     //case 'J':
345     case ndk::key::ctrl_down:
346 sf-pippijn 1.3 perform (ev.sender (), action::run, action::south);
347 sf-pippijn 1.1 return ndk::event::accepted;
348     //case 'K':
349     case ndk::key::ctrl_up:
350 sf-pippijn 1.3 perform (ev.sender (), action::run, action::north);
351 sf-pippijn 1.1 return ndk::event::accepted;
352     //case 'H':
353     case ndk::key::ctrl_left:
354 sf-pippijn 1.3 perform (ev.sender (), action::run, action::west);
355 sf-pippijn 1.1 return ndk::event::accepted;
356     //case 'L':
357     case ndk::key::ctrl_right:
358 sf-pippijn 1.3 perform (ev.sender (), action::run, action::east);
359 sf-pippijn 1.1 return ndk::event::accepted;
360     case ndk::key::ctrl_home:
361 sf-pippijn 1.3 perform (ev.sender (), action::run, action::northwest);
362 sf-pippijn 1.1 return ndk::event::accepted;
363     case ndk::key::ctrl_pg_up:
364 sf-pippijn 1.3 perform (ev.sender (), action::run, action::northeast);
365 sf-pippijn 1.1 return ndk::event::accepted;
366     case ndk::key::ctrl_end:
367 sf-pippijn 1.3 perform (ev.sender (), action::run, action::southwest);
368 sf-pippijn 1.1 return ndk::event::accepted;
369     case ndk::key::ctrl_pg_dn:
370 sf-pippijn 1.3 perform (ev.sender (), action::run, action::southeast);
371 sf-pippijn 1.1 return ndk::event::accepted;
372    
373 sf-pippijn 1.5 case ndk::key::ctrl_l:
374 sf-pippijn 1.4 case ndk::key::F10:
375     case ndk::key::resize:
376 sf-pippijn 1.1 case ndk::key::tab:
377     return ndk::event::ignored;
378    
379     case ndk::key::unknown:
380 sf-pippijn 1.3 return ndk::event::ignored;
381 sf-pippijn 1.1
382     default:
383     if (getenv ("DCLIENT_FATAL"))
384     throw ev.code ();
385     else
386     {
387 sf-pippijn 1.6 ui.info->add_text (ndi_color (3, 0), "unknown keycode: 0%03o\n", ev.code ());
388 sf-pippijn 1.3 ui.info->visualize ();
389     return ndk::event::ignored;
390 sf-pippijn 1.1 }
391     }
392     }
393    
394     void
395     input_handler::pimpl::on_command (std::string const &cmd)
396     {
397 sf-pippijn 1.8 ui.input->set_text ("");
398    
399 sf-pippijn 1.3 if (!cmd.empty ())
400     send ("command", cmd);
401 sf-pippijn 1.8 else
402     {
403     ui.map->focus ();
404     ui.input->hide ();
405     ndk::app->cursor_off (); // FIXME: should be done automatically
406     }
407     }
408 sf-pippijn 1.1
409 sf-pippijn 1.8 void
410     input_handler::pimpl::stdin_read_cb (ev::io &w, int revents)
411     {
412     ndk::app->process (getch ());
413 sf-pippijn 1.1 }
414    
415    
416 sf-pippijn 1.8 input_handler::input_handler (communicator &comm, widgets &ui)
417     : impl (new pimpl (comm, ui))
418 sf-pippijn 1.1 {
419     }
420    
421     input_handler::~input_handler ()
422     {
423     delete impl;
424     }