source: golgotha/src/i4/device/kernel.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 12 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 8.9 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "device/kernel.hh"
10#include "memory/malloc.hh"
11#include "error/alert.hh"
12#include "device/device.hh"
13#include "device/event.hh"
14#include "time/time.hh"
15#include "threads/threads.hh"
16#include "isllist.hh"
17
18enum { I4_SHOW_NONE,
19       I4_SHOW_ALL,
20       I4_SHOW_NON_TRIVAL,        // excludes mouse move & window messages     
21};
22
23int i4_show_events=I4_SHOW_NONE;
24
25i4_kernel_device_class i4_kernel;
26
27
28struct defered_event
29{
30  i4_event_handler_reference_class<i4_event_handler_class> send_to;
31  defered_event *next;
32  i4_event *ev_copy;
33  defered_event(i4_event_handler_class *_send_to,
34                i4_event *ev) : ev_copy(ev->copy())
35  {
36    send_to.reference(_send_to);
37  }
38
39  ~defered_event()
40  {
41    delete ev_copy;
42  }
43
44};
45
46 
47struct event_handler_delete_node
48{
49  i4_event_handler_class *who;
50  event_handler_delete_node *next;
51  event_handler_delete_node(i4_event_handler_class *who)
52    : who(who) {}
53};
54
55
56static defered_event *defered_list;
57
58
59
60static i4_critical_section_class list_lock;
61static i4_isl_list<defered_event> list;
62typedef i4_isl_list<defered_event>::iterator def_iter;
63
64static i4_isl_list<event_handler_delete_node> eh_delete_list;
65static i4_time_class last_user_input;
66
67// r includes event and who to send to
68void i4_kernel_device_class::send(i4_event_reaction_class *r)
69{
70  if (r && r->handler_reference.get())
71    send_event(r->handler_reference.get(), r->event);
72}
73
74
75
76#ifdef DEBUG
77void i4_kernel_device_class::show_pending()
78{
79  list_lock.lock();
80
81  i4_isl_list<defered_event>::iterator i=list.begin();
82
83  for (;i!=list.end();++i)
84    i4_warning("'%s' for '%s'",i->ev_copy->name(), i->send_to.get()->name());   
85 
86  list_lock.unlock();
87}
88#endif
89
90void i4_kernel_device_class::deque_events(i4_event_handler_class *for_who)
91{
92  list_lock.lock();
93
94  i4_isl_list<defered_event>::iterator i=list.begin(), last=list.end(), q;
95  for (; i!=list.end(); )
96  {
97    if (i->send_to.get()==for_who)
98    {
99      if (last==list.end())
100        list.erase();
101      else
102        list.erase_after(last);
103     
104
105      q=i;
106      ++i;
107
108      list_lock.unlock();      // in case deleted events send events
109      delete &*q;
110      list_lock.lock();
111    }
112    else
113    {
114      last=i;
115      ++i;
116    }
117  }
118 
119  list_lock.unlock();
120}
121
122
123void i4_kernel_device_class::send_event(i4_event_handler_class *send_to, i4_event *ev)
124{
125
126
127  if (ev->when()!=i4_event::NOW)
128  {   
129#ifndef I4_RETAIL
130    if (i4_show_events==I4_SHOW_ALL ||
131        (i4_show_events==I4_SHOW_NON_TRIVAL &&
132         !(ev->type()==i4_event::MOUSE_MOVE || ev->type()==i4_event::WINDOW_MESSAGE)))
133      i4_warning("queing : '%s' to '%s'",ev->name(), send_to->name());
134#endif
135    defered_event *dv=new defered_event(send_to,ev);
136
137    list_lock.lock();
138    list.insert_end(*dv);   
139    list_lock.unlock();
140  } else
141  {
142#ifndef I4_RETAIL
143    if (i4_show_events==I4_SHOW_ALL ||
144        (i4_show_events==I4_SHOW_NON_TRIVAL &&
145         !(ev->type()==i4_event::MOUSE_MOVE || ev->type()==i4_event::WINDOW_MESSAGE)))
146      i4_warning("sending : '%s' to '%s'",ev->name(), send_to->name());
147#endif
148
149    send_to->call_stack_counter++;
150    events_sent++;
151    send_to->receive_event(ev);
152    send_to->call_stack_counter--;
153  } 
154}
155
156i4_bool i4_kernel_device_class::process_events()       // returns true if an event was dispatched 
157{
158  i4_bool ret=i4_F;
159  for (i4_device_class *d=device_list; d; d=d->next)
160    if (d->process_events())
161      ret=i4_T;
162
163  ret=(i4_bool)(flush_events() | ret);
164
165  check_for_idle();
166
167  return ret;
168}
169
170
171i4_bool i4_kernel_device_class::flush_events()
172{
173
174
175  i4_bool ret=i4_F;
176
177  // send any events that were qued
178  while (list.begin()!=list.end())
179  {
180    list_lock.lock();
181    i4_isl_list<defered_event>::iterator old=list.begin();
182    list.erase();
183    list_lock.unlock();
184
185    // make sure event handler is still around..
186    i4_event_handler_class *eh=old->send_to.get();   
187    if (eh)
188    {
189#ifdef DEBUG
190      i4_event *ev=old->ev_copy;
191      if (i4_show_events==I4_SHOW_ALL ||
192          (i4_show_events==I4_SHOW_NON_TRIVAL &&
193           !(ev->type()==i4_event::MOUSE_MOVE || ev->type()==i4_event::WINDOW_MESSAGE)))
194        i4_warning("sending : '%s' to '%s'",old->ev_copy->name(), eh->name());
195#endif
196
197      eh->call_stack_counter++;
198      events_sent++;
199      eh->receive_event(old->ev_copy);
200      eh->call_stack_counter--;
201    }
202
203    delete &*old;
204
205    ret=i4_T;
206  }
207
208
209  list_lock.lock();
210  // delete any event handlers that are qued for deletion
211  i4_isl_list<event_handler_delete_node>::iterator i=eh_delete_list.begin(),
212    last=eh_delete_list.end(), q;
213
214
215  while (i!=eh_delete_list.end())
216  {
217    if (!i->who->thinking())
218    {
219      q=i;
220      ++i;
221     
222      if (last!=eh_delete_list.end())
223        eh_delete_list.erase_after(last);
224      else
225        eh_delete_list.erase();
226
227      list_lock.unlock();     // unlock because deleted object might send events
228
229      delete q->who;
230      delete &*q;
231
232      list_lock.lock();
233    }
234    else ++i;
235  }
236
237
238  list_lock.unlock();
239
240  return ret;
241}
242
243
244void i4_kernel_device_class::request_events(i4_event_handler_class *for_who, w32 event_types)
245{
246  int type=0;
247  while (event_types)
248  {
249    if (event_types&1)
250      response[type]=new response_type(for_who, response[type]);
251
252    event_types>>=1;   
253    type++;
254  }
255}
256
257// unrequest_events tells any devices sending event_types events to you to stop
258void i4_kernel_device_class::unrequest_events(i4_event_handler_class *for_who, w32 event_types)
259{
260  int type=0;
261  while (event_types)
262  {
263    if (event_types&1)
264    {
265      response_type *last=0, *p;
266      for (p=response[type]; p && p->who!=for_who; p=p->next)
267        last=p;
268       
269       
270     
271      if (!p)
272        i4_error("unrequesting events & not installed");
273      else
274      {
275        //        for_who->dereference();
276        if (response[type]->who==for_who)
277          response[type]=response[type]->next;
278        else
279          last->next=p->next;
280
281        delete p;
282      }
283    }
284    event_types>>=1;
285    type++;
286  }
287}
288
289void i4_kernel_device_class::add_device(i4_device_class *device)       // returns 16 bits device id
290{
291  device->next=device_list;
292  device_list=device;
293}
294
295void i4_kernel_device_class::remove_device(i4_device_class *device)
296{
297  i4_device_class *last=0, *p;
298  for (p=device_list; p && p!=device; p=p->next)
299    last=p;
300
301  if (!p)
302    i4_error("remove device : device not found");
303  if (last)
304    last->next=device->next;
305  else
306    device_list=device->next;
307}
308
309
310void i4_kernel_device_class::not_idle()
311{
312  last_user_input.get();
313}
314
315void i4_kernel_device_class::check_for_idle()
316{
317  if (can_send_idle)
318  {
319    i4_time_class now;
320    if (now.milli_diff(last_user_input)>milliseconds_before_idle_events_sent)
321    {
322      i4_user_idle_event_class uiev;
323      broadcast_event_type(&uiev, i4_device_class::FLAG_IDLE);
324      can_send_idle=i4_F;
325    } 
326  }
327}
328
329void i4_kernel_device_class::set_milliseconds_before_idle_events_sent(w32 milli_seconds)
330{
331  milliseconds_before_idle_events_sent=milli_seconds;
332  check_for_idle();
333}
334
335i4_kernel_device_class::i4_kernel_device_class()
336{
337  events_sent=0;
338  can_send_idle=i4_F;
339  milliseconds_before_idle_events_sent=1000;
340
341  memset(response,0,sizeof(response));
342  device_list=0;
343}
344
345
346void i4_kernel_device_class::broadcast_event_type(i4_event *ev, w32 event_type)
347{
348  if (event_type & (i4_device_class::FLAG_MOUSE_MOVE |
349                    i4_device_class::FLAG_MOUSE_BUTTON_DOWN |
350                    i4_device_class::FLAG_MOUSE_BUTTON_UP |
351                    i4_device_class::FLAG_KEY_PRESS |                   
352                    i4_device_class::FLAG_KEY_RELEASE))
353  {
354    can_send_idle=i4_T;
355    last_user_input.get();     
356  }
357
358  int type=0;
359  while ((event_type&1)==0)
360  {
361    event_type>>=1;
362    type++;
363  }
364
365  for (response_type *r=response[type]; r; r=r->next)
366    send_event(r->who, ev);
367
368}
369
370
371void i4_kernel_device_class::delete_handler(i4_event_handler_class *handler)
372{
373  if (handler->thinking())
374    eh_delete_list.insert(*(new event_handler_delete_node(handler)));
375  else
376  {
377    //i4_warning("need to fix this handler deletion thing, trey");
378    ///*
379    if (!valid_ptr(handler))
380    {
381      valid_ptr(handler);
382      i4_warning("bad handler pointer");
383    }
384    else
385    //*/
386      delete handler;
387  }
388}
Note: See TracBrowser for help on using the repository browser.