ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/cf.schmorp.de/dclient/src/backend/ndk/transport.cpp
Revision: 1.7
Committed: Sun Oct 24 20:31:51 2010 UTC (15 years, 11 months ago) by sf-pippijn
Branch: MAIN
Changes since 1.6: +6 -6 lines
Log Message:
use EV and plain sockets instead of asio

File Contents

# User Rev Content
1 sf-pippijn 1.1 /* transport.cc
2     * This file is part of NDK++ library
3     * Copyright (c) 2003 by Stanislav Ievlev
4     *
5     * This file is covered by the GNU Library General Public License,
6 sf-pippijn 1.7 * which should be included with libndk as the file COPYING.
7 sf-pippijn 1.1 */
8    
9 sf-pippijn 1.6 #include "live.h"
10    
11 sf-pippijn 1.7 #include <ndk/transport.hh>
12 sf-pippijn 1.1
13 sf-pippijn 1.7 #include <ndk/application.hh>
14     #include <ndk/events.hh>
15     #include <ndk/keymap.hh>
16 sf-pippijn 1.1
17 sf-pippijn 1.7 #include <ndk/panel.hh>
18 sf-pippijn 1.1
19     #include <adt/string.h>
20    
21     #include <curses.h>
22    
23 sf-pippijn 1.6 #include <algorithm>
24    
25 sf-pippijn 1.1 using namespace ndk;
26    
27     namespace
28     {
29     template<typename EventT>
30     struct run_impl
31     {
32     /**< functor to run callback functions */
33 sf-pippijn 1.4 run_impl (EventT const &e)
34 sf-pippijn 1.1 : e_ (e)
35     {
36     }
37    
38     template<typename CallbackT>
39     event::result operator () (CallbackT &callback)
40     {
41     return callback (e_);
42     }
43    
44 sf-pippijn 1.4 EventT const &e_;
45 sf-pippijn 1.1 };
46    
47     template<typename EventT>
48     run_impl<EventT>
49 sf-pippijn 1.4 run_callback (EventT const &e)
50 sf-pippijn 1.1 {
51     return run_impl<EventT> (e);
52     }
53    
54     template<typename Ret, typename Tp, typename Arg1T>
55     struct mem_fun1_impl
56     {
57     /**< simple helper binder of member function */
58     mem_fun1_impl (Ret (Tp::*f)(Arg1T), Arg1T arg)
59     : f_ (f)
60     , arg_ (arg)
61     {
62     }
63    
64     Ret operator () (Tp *obj)
65     {
66     return (obj->*f_)(arg_);
67     }
68    
69     Ret (Tp::*f_)(Arg1T);
70     Arg1T arg_;
71     };
72    
73     template<typename Ret, typename Tp, typename Arg1T, typename Arg2T>
74     struct mem_fun2_impl
75     {
76     /**< simple helper binder of member function */
77     mem_fun2_impl (Ret (Tp::*f)(Arg1T, Arg2T), Arg1T arg1, Arg2T arg2)
78     : f_ (f)
79     , arg1_ (arg1)
80     , arg2_ (arg2)
81     {
82     }
83    
84     Ret operator () (Tp *obj)
85     {
86     return (obj->*f_)(arg1_, arg2_);
87     }
88    
89     Ret (Tp::*f_)(Arg1T, Arg2T);
90     Arg1T arg1_;
91     Arg2T arg2_;
92     };
93     }
94    
95    
96     bool
97 sf-pippijn 1.6 mouse::over (panel const &p) const
98 sf-pippijn 1.1 {
99     if (p.hidden ())
100     return false;
101     else
102     return p.x () <= x () && x () <= p.right_x () - 1 &&
103     p.y () <= y () && y () <= p.bottom_y () - 1;
104    
105     }
106    
107 sf-pippijn 1.6 engine::engine (engine *parent, panel *geometry)
108 sf-pippijn 1.1 : geometry_ (geometry)
109     , in_focus_ (this)
110     , accept_ (true)
111     {
112 sf-pippijn 1.6 parent_ = parent ? parent : app->events (); /* by default head is application */
113 sf-pippijn 1.1 parent_->add_child (this);
114     }
115    
116     engine::engine ()
117     : parent_ (0)
118     , geometry_ (0)
119     , in_focus_ (this)
120     , accept_ (true)
121     {
122     }
123    
124     engine::~engine ()
125     {
126     if (parent_)
127     parent_->del_child (this);
128     }
129    
130     void
131     engine::in_focus (engine *item)
132     {
133     if (std::find (childs_.begin (), childs_.end (), item) != childs_.end ())
134     {
135     in_focus_ = item;
136     in_focus_->system (event (enter_focus)); /* notify item */
137     }
138     else
139     throw std::runtime_error ("unable to set focus to unknown widget");
140     }
141    
142     engine *
143     engine::head () /**< @return main head of the transport tree */
144     {
145     engine *head = this; /* find local event loop head */
146    
147     while (head->parent_)
148     head = head->parent_;
149     return head;
150     }
151    
152     void
153     engine::update ()
154     {
155 sf-pippijn 1.6 #if LIVE
156 sf-pippijn 1.1 update_panels (); /* update current status */
157 sf-pippijn 1.3 return_unless (doupdate () == OK);
158 sf-pippijn 1.6 #endif
159 sf-pippijn 1.1 }
160    
161     void
162     engine::process (int const ch)
163     {
164     key code = parsekey (esc_, ch);
165     if (code == key::mouse)
166     {
167     mouse ev = getmouse (esc_);
168     process (ev);
169     }
170     else if (code != key::intermediate)
171     {
172     keyboard ev (code);
173     process (ev);
174     }
175    
176 sf-pippijn 1.6 #if LIVE
177 sf-pippijn 1.3 return_unless (doupdate () == OK); /* commit all changes to the screen */
178 sf-pippijn 1.6 #endif
179 sf-pippijn 1.1 }
180    
181     void
182 sf-pippijn 1.4 engine::on_keyboard (keyboard_event const &callback, bool front)
183 sf-pippijn 1.1 {
184     if (front)
185     keyboard_.push_front (callback);
186     else
187     keyboard_.push_back (callback);
188     }
189    
190     void
191     engine::on_mouse (mouse_event const &callback, bool front)
192     {
193     if (front)
194     mouse_.push_front (callback);
195     else
196     mouse_.push_back (callback);
197     }
198    
199     void
200 sf-pippijn 1.4 engine::on_system (system_event const &callback, bool front)
201 sf-pippijn 1.1 {
202     if (front)
203     system_.push_front (callback);
204     else
205     system_.push_back (callback);
206     }
207    
208     void
209     engine::rat (mouse const &ev)
210     {
211 sf-pippijn 1.2 foreach (mouse_event &m, mouse_)
212 sf-pippijn 1.1 m (ev);
213     }
214    
215     event::result
216 sf-pippijn 1.4 engine::kbd (keyboard const &kev)
217 sf-pippijn 1.1 {
218     event::result res = event::ignored;
219 sf-pippijn 1.4 keyboard const ev (kev.code (), geometry_);
220 sf-pippijn 1.1 kbd_events::iterator it = std::find_if (keyboard_.begin (),
221     keyboard_.end (),
222     run_callback (ev));
223    
224     if (it != keyboard_.end ())
225     {
226     res = event::accepted;
227     std::for_each (++it,
228     keyboard_.end (),
229     run_callback (ev));
230     }
231    
232     return res;
233     }
234    
235     event::result
236 sf-pippijn 1.4 engine::system (event const &ev)
237 sf-pippijn 1.1 {
238     event::result res = event::ignored;
239     sys_events::iterator it = std::find_if (system_.begin (),
240     system_.end (),
241     run_callback (ev));
242    
243     if (it != system_.end ())
244     {
245     res = event::accepted;
246     std::for_each (++it,
247     system_.end (),
248     run_callback (ev));
249     }
250    
251     return res;
252     }
253    
254     void
255     engine::add_child (engine *p)
256     {
257     childs_.push_back (p);
258     }
259    
260     void
261     engine::del_child (engine *p)
262     {
263     childs_.erase (std::remove (childs_.begin (),
264     childs_.end (),
265     p), childs_.end ());
266     }
267    
268     void
269     engine::little_switch (engine *item)
270     {
271     if (item == in_focus_ || !item->accept ())
272     return; /* nothing to switch */
273    
274     /* all permissions ok - let's switch focus now */
275     if (in_focus_ != this)
276     in_focus_->leave_all ();
277     in_focus_ = item;
278     if (in_focus_ != this)
279     in_focus_->enter_all ();
280    
281 sf-pippijn 1.6 #if LIVE
282 sf-pippijn 1.2 update_panels (); /* update panel's status */
283 sf-pippijn 1.6 #endif
284 sf-pippijn 1.1 }
285    
286     void
287     engine::big_switch (engine *item)
288     {
289 sf-pippijn 1.4 child_items list; /* hierarchy we need to walk to produce a big switch */
290 sf-pippijn 1.1
291     /* first cycle determine widgets we need to switch */
292     for (; item != this; item = item->parent_)
293     list.push_back (item);
294    
295     for (child_items::reverse_iterator it = list.rbegin (); it != list.rend (); it++)
296     (*it)->parent_->little_switch (*it);
297     }
298    
299     void
300     engine::switch_to (engine *item)
301     {
302     head ()->big_switch (item);
303     }
304    
305     void
306     engine::find_over (mouse const &ev, child_items *list)
307     {
308     if (geometry_ && ev.over (*geometry_))
309     list->push_back (this);
310    
311 sf-pippijn 1.2 foreach (engine *child, childs_)
312 sf-pippijn 1.1 child->find_over (ev, list);
313     }
314    
315     void
316     engine::process (mouse const &ev)
317     {
318     /* walk throw the all objects and find all objects under mouse pointer */
319     child_items list;
320    
321     find_over (ev, &list);
322    
323     if (list.empty ())
324     {
325 sf-pippijn 1.3 flash ();
326 sf-pippijn 1.1 return;
327     }
328    
329     /* then find widget over all visible widgets */
330     child_items::iterator top = std::max_element (list.begin (),
331     list.end (),
332     higher);
333    
334     big_switch (*top); /* then made a big switch to top widget */
335    
336     /*
337     * let's widget process it's event
338     * find latest widget who can process mouse event
339     */
340     engine *current = *top;
341     while (!current->accept () && current->parent_)
342     current = current->parent_;
343     if (current->parent_)
344     current->rat (ev);
345     }
346    
347     void
348     engine::find_leafs (child_items *list)
349     {
350     child_items active_childs;
351    
352 sf-pippijn 1.2 foreach (engine *child, childs_)
353 sf-pippijn 1.1 child->find_leafs (&active_childs);
354    
355     /*
356     * if we cannot find active childs, but have active father
357     * then add father if it's not hidden now
358     */
359     if (active_childs.empty () && accept_ && geometry_ && !geometry_->hidden ())
360     list->push_back (this);
361     else
362     /* append active childs to the big list */
363     list->insert (list->end (), active_childs.begin (), active_childs.end ());
364     }
365    
366     void
367 sf-pippijn 1.4 engine::process (keyboard const &ev)
368 sf-pippijn 1.1 {
369     /*
370     * call at_event only for itself else call process event to pass messages
371     * to subwidgets, last widget always have in_focus_ equals "this"
372     */
373     engine *current = this;
374    
375 sf-pippijn 1.3 if (ev.code () == key::error)
376     throw "ERR";
377    
378 sf-pippijn 1.1 while (current->in_focus_ != current)
379     current = current->in_focus_;
380     if (current->kbd (ev) != event::accepted) /* if widget ignore processing then we can process it itself */
381     if (ev.code () == key::tab)
382     {
383     child_items list;
384     find_leafs (&list); /* collect all leaves of the transport subtree //FIXME: start search not from head, but from current in_focus */
385    
386     if (list.empty ())
387     return; /* nothing to switch to */
388    
389     engine *next; /* calculate next candidate to switch */
390     child_items::iterator it = std::find (list.begin (), list.end (), current);
391     if (it == list.end ()) /* first item by default */
392     next = list.at (0);
393     else
394     next = (++it == list.end ()) ? *list.begin () : *it;
395    
396     big_switch (next);
397     }
398     }
399    
400     void
401     engine::emit (int type)
402     {
403     head ()->process_system (event (type, this));
404     }
405    
406     event::result
407 sf-pippijn 1.4 engine::process_system (event const &ev)
408 sf-pippijn 1.1 {
409     /* find are some child accept this event */
410     child_items::const_iterator item =
411     std::find_if (childs_.begin (),
412     childs_.end (),
413 sf-pippijn 1.4 mem_fun1_impl<event::result, engine, event const &> (&engine::process_system, ev));
414 sf-pippijn 1.1
415     return (item != childs_.end ()) ? event::accepted : system (ev);
416     }
417    
418     /* send event to object and all it's childs */
419     void
420     engine::leave_all ()
421     {
422     system (event (leave_focus));
423 sf-pippijn 1.2 foreach (engine *child, childs_)
424 sf-pippijn 1.1 child->leave_all ();
425     }
426    
427     void
428     engine::enter_all ()
429     {
430     engine *current = this;
431    
432     while (current->in_focus_ != current)
433     {
434     current->system (event (enter_focus));
435     current = current->in_focus_;
436     }
437     current->system (event (enter_focus));
438     }
439    
440     void
441     engine::set_accept (bool val)
442     {
443     accept_ = val;
444     }
445    
446     bool
447     engine::accept () const
448     {
449     return accept_;
450     }
451 sf-pippijn 1.6
452     bool
453     engine::higher (engine *lhs, engine *rhs)
454     {
455     return rhs->geometry_->higher (*lhs->geometry_);
456     }