summaryrefslogblamecommitdiff
path: root/src/lib/ecore_input_evas/ecore_input_evas.c
blob: 23e954320f6ba0f26614f075af127c3d2f5290b8 (plain) (tree)
1
2
3
4
5
6
7
8
9




                    
                   

                  
                        
 
                             
                                     








                                                      


                                        


                    












                                                  
                       





                           
                                            
                                                         

                                      








                                                                            
                                                                                         



                         
                                                           
                                          
                                                              
                  
                                




                                           
                        







































                                                                                         
                                    
 
                                                                          
                    







































                                                                               
                                  
















                                                                                                  
                                    



























                                                            
















                                                                      

                                         


       

                                          

      


                                              
 










                                            



                                           


         




                                                                      
 
                         
 

                                             
 


                              


                              
                       
 
                                       






                                          
                                        










                                              
           














                                                                   
                       













                                                              
                



                                                                  
                                                       
                                              

                                                                     







                                                        
       







                                                      
                                 

 
                
                                                                                                     
 
                         


                                              
                                                       
                                              

                                                          



                                                                                                                                








                                                                                     


                                                             
                            


                                                                          
                                                                     
                                                         
            
                                                                   
                                                       
      
       
      
                                

                                    




                                                                        

                                                 
                                                                         



                                                                                

                                                               
            

                                  




                                                                      

                                               
                                                                       



                                                                              

                                                             
      
                                 

 
              
                                                                                      




                              
                                                       
                                              

                            
                                             
                                                                          


                                                                        
                                                                              
                                            


       
                               



                                                                   

                                                                    
                                                                    



                                                                           
                                            
      
                                 

 
              
                                                                                             
 
                                                                                                    

 
              
                                                                                           
 
                                                                                                  

 
                



                                                                      
                                                       
                                              



                                                                     

                                                                    
                     

                                                                     
              
               


                                                                
                                 

 
              
                                                                                    
 
                                                                      

 
              
                                                                                  
 
                                                                    

 
              
                                                                                       




                              
                                                       
                                              

                                                                                     
                                 

 
              
                                                                                    
 
                                                                              

 
              
                                                                                     
 
                                                                               

 








                                                                                       


                                                                     


                                 


                           
                                            

                                         

                                                               
                                     
      

                                                                                           



                     
                                              



                           
                            


                                                                               

                                                                                    
                                                                             

                                                                                  
                                                                                        

                                                                                             
                                                                                      

                                                                                           
                                                                                 

                                                                                      
                                                                                  

                                                                                       
                                                                               

                                                                                    
                                                                                

                                                                                     


                                                                                       
 
                                              
 










                                                           
                                       
 
                  
                    
 





                                         
            
 

                                           
 

                                
                                                                                          
      

                                                              
      
 

                          
 

                                                         
 

                                       
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <string.h>
#include <stdlib.h>

#include "Ecore.h"
#include "Ecore_Input.h"

#include "Ecore_Input_Evas.h"
#include "ecore_input_evas_private.h"

int _ecore_input_evas_log_dom = -1;

typedef struct _Ecore_Input_Window Ecore_Input_Window;
struct _Ecore_Input_Window
{
   Evas *evas;
   void *window;
   Ecore_Event_Mouse_Move_Cb move_mouse;
   Ecore_Event_Multi_Move_Cb move_multi;
   Ecore_Event_Multi_Down_Cb down_multi;
   Ecore_Event_Multi_Up_Cb up_multi;
   int ignore_event;
};

typedef enum _Ecore_Input_State {
  ECORE_INPUT_NONE = 0,
  ECORE_INPUT_DOWN,
  ECORE_INPUT_MOVE,
  ECORE_INPUT_UP
} Ecore_Input_State;

typedef struct _Ecore_Input_Last Ecore_Event_Last;
struct _Ecore_Input_Last
{
   Ecore_Event_Mouse_Button *ev;
   Ecore_Timer *timer;

   unsigned int device;
   unsigned int buttons;
   Ecore_Input_State state;

   Eina_Bool faked : 1;
};

static int _ecore_event_evas_init_count = 0;
static Ecore_Event_Handler *ecore_event_evas_handlers[9];
static Eina_Hash *_window_hash = NULL;

static Eina_List *_last_events = NULL;
static double _last_events_timeout = 0.5;
static Eina_Bool _last_events_enable = EINA_FALSE;

static Eina_Bool _ecore_event_evas_mouse_button(Ecore_Event_Mouse_Button *e,
                                                Ecore_Event_Press press,
                                                Eina_Bool faked);

static Ecore_Event_Last *
_ecore_event_evas_lookup(unsigned int device, unsigned int buttons, Eina_Bool create_new)
{
   Ecore_Event_Last *eel;
   Eina_List *l;

   //the number of last event is small, simple check is ok.
   EINA_LIST_FOREACH(_last_events, l, eel)
     if ((eel->device == device) && (eel->buttons == buttons))
       return eel;
   if (!create_new) return NULL;
   eel = malloc(sizeof (Ecore_Event_Last));
   if (!eel) return NULL;

   eel->timer = NULL;
   eel->ev = NULL;
   eel->device = device;
   eel->buttons = buttons;
   eel->state = ECORE_INPUT_NONE;
   eel->faked = EINA_FALSE;

   _last_events = eina_list_append(_last_events, eel);
   return eel;
}

static Eina_Bool
_ecore_event_evas_push_fake(void *data)
{
   Ecore_Event_Last *eel = data;

   switch (eel->state)
     {
      case ECORE_INPUT_NONE:
      case ECORE_INPUT_UP:
         /* should not happen */
         break;
      case ECORE_INPUT_DOWN:
         /* use the saved Ecore_Event */
         /* No up event since timeout started ... */
      case ECORE_INPUT_MOVE:
         /* No up event since timeout started ... */
         _ecore_event_evas_mouse_button(eel->ev, ECORE_UP, EINA_TRUE);
         eel->faked = EINA_TRUE;
         break;
     }

   free(eel->ev);
   eel->ev = NULL;
   eel->timer = NULL;
   return EINA_FALSE;
}

static void
_ecore_event_evas_push_mouse_button(Ecore_Event_Mouse_Button *e, Ecore_Event_Press press)
{
   Ecore_Event_Last *eel;

   if (!_last_events_enable) return;

   eel = _ecore_event_evas_lookup(e->multi.device, e->buttons, EINA_TRUE);
   if (!eel) return;

   switch (eel->state)
     {
      case ECORE_INPUT_NONE:
         goto fine;
      case ECORE_INPUT_DOWN:
         if (press == ECORE_UP)
           goto fine;

         /* press == ECORE_DOWN => emit a faked UP then */
         _ecore_event_evas_mouse_button(e, ECORE_UP, EINA_TRUE);
         break;
      case ECORE_INPUT_MOVE:
         if (press == ECORE_UP)
           goto fine;

         /* FIXME: handle fake button up and push for more delay here */

         /* press == ECORE_DOWN */
         _ecore_event_evas_mouse_button(e, ECORE_DOWN, EINA_TRUE);
         break;
      case ECORE_INPUT_UP:
         if (press == ECORE_DOWN)
           goto fine;

         /* press == ECORE_UP */
         _ecore_event_evas_mouse_button(e, ECORE_UP, EINA_TRUE);
         break;
     }

 fine:
   eel->state = (press == ECORE_DOWN) ? ECORE_INPUT_DOWN : ECORE_INPUT_UP;
   if (_last_events_timeout)
     {
        if (eel->timer) ecore_timer_del(eel->timer);
        eel->timer = NULL;
        if (press == ECORE_DOWN)
          {
             /* Save the Ecore_Event somehow */
             if (!eel->ev) eel->ev = malloc(sizeof (Ecore_Event_Mouse_Button));
             if (!eel->ev) return;
             memcpy(eel->ev, e, sizeof (Ecore_Event_Mouse_Button));
             eel->timer = ecore_timer_add(_last_events_timeout, _ecore_event_evas_push_fake, eel);
          }
        else
          {
             free(eel->ev);
             eel->ev = NULL;
          }
     }
}

static void
_ecore_event_evas_push_mouse_move(Ecore_Event_Mouse_Move *e)
{
   Ecore_Event_Last *eel;
   Eina_List *l;

   if (!_last_events_enable) return;

   EINA_LIST_FOREACH(_last_events, l, eel)
     switch (eel->state)
       {
        case ECORE_INPUT_NONE:
        case ECORE_INPUT_UP:
           /* none or up and moving, sounds fine to me */
           break;
        case ECORE_INPUT_DOWN:
        case ECORE_INPUT_MOVE:
           /* Down and moving, let's see */
           if (eel->ev)
             {
                /* Add some delay to the timer */
                ecore_timer_reset(eel->timer);
                /* Update position */
                eel->ev->x = e->x;
                eel->ev->y = e->y;
                eel->ev->root.x = e->root.x;
                eel->ev->root.y = e->root.y;
                eel->state = ECORE_INPUT_MOVE;
                break;
             }
           /* FIXME: Timer did expire, do something maybe */
           break;
       }
}

EAPI void
ecore_event_evas_modifier_lock_update(Evas *e, unsigned int modifiers)
{
   if (modifiers & ECORE_EVENT_MODIFIER_SHIFT)
     evas_key_modifier_on(e, "Shift");
   else evas_key_modifier_off(e, "Shift");

   if (modifiers & ECORE_EVENT_MODIFIER_CTRL)
     evas_key_modifier_on(e, "Control");
   else evas_key_modifier_off(e, "Control");

   if (modifiers & ECORE_EVENT_MODIFIER_ALT)
     evas_key_modifier_on(e, "Alt");
   else evas_key_modifier_off(e, "Alt");

   if (modifiers & ECORE_EVENT_MODIFIER_WIN)
     {
        evas_key_modifier_on(e, "Super");
        evas_key_modifier_on(e, "Hyper");
     }
   else
     {
        evas_key_modifier_off(e, "Super");
        evas_key_modifier_off(e, "Hyper");
     }

   if (modifiers & ECORE_EVENT_MODIFIER_ALTGR)
     evas_key_modifier_on(e, "AltGr");
   else evas_key_modifier_off(e, "AltGr");

   if (modifiers & ECORE_EVENT_LOCK_SCROLL)
     evas_key_lock_on(e, "Scroll_Lock");
   else evas_key_lock_off(e, "Scroll_Lock");

   if (modifiers & ECORE_EVENT_LOCK_NUM)
     evas_key_lock_on(e, "Num_Lock");
   else evas_key_lock_off(e, "Num_Lock");

   if (modifiers & ECORE_EVENT_LOCK_CAPS)
     evas_key_lock_on(e, "Caps_Lock");
   else evas_key_lock_off(e, "Caps_Lock");

   if (modifiers & ECORE_EVENT_LOCK_SHIFT)
     evas_key_lock_on(e, "Shift_Lock");
   else evas_key_lock_off(e, "Shift_Lock");
}

EAPI void
ecore_event_window_register(Ecore_Window id, void *window, Evas *evas,
                            Ecore_Event_Mouse_Move_Cb move_mouse,
                            Ecore_Event_Multi_Move_Cb move_multi,
                            Ecore_Event_Multi_Down_Cb down_multi,
                            Ecore_Event_Multi_Up_Cb up_multi)
{
   Ecore_Input_Window *w;

   w = calloc(1, sizeof(Ecore_Input_Window));
   if (!w) return;

   w->evas = evas;
   w->window = window;
   w->move_mouse = move_mouse;
   w->move_multi = move_multi;
   w->down_multi = down_multi;
   w->up_multi = up_multi;
   w->ignore_event = 0;

   eina_hash_add(_window_hash, &id, w);

   evas_key_modifier_add(evas, "Shift");
   evas_key_modifier_add(evas, "Control");
   evas_key_modifier_add(evas, "Alt");
   evas_key_modifier_add(evas, "Meta");
   evas_key_modifier_add(evas, "Hyper");
   evas_key_modifier_add(evas, "Super");
   evas_key_modifier_add(evas, "AltGr");
   evas_key_lock_add(evas, "Caps_Lock");
   evas_key_lock_add(evas, "Num_Lock");
   evas_key_lock_add(evas, "Scroll_Lock");
}

EAPI void
ecore_event_window_unregister(Ecore_Window id)
{
   eina_hash_del(_window_hash, &id, NULL);
}

EAPI void *
ecore_event_window_match(Ecore_Window id)
{
   Ecore_Input_Window *lookup;

   lookup = eina_hash_find(_window_hash, &id);
   if (lookup) return lookup->window;
   return NULL;
}

EAPI void
ecore_event_window_ignore_events(Ecore_Window id, int ignore_event)
{
   Ecore_Input_Window *lookup;

   lookup = eina_hash_find(_window_hash, &id);
   if (!lookup) return;
   lookup->ignore_event = ignore_event;
}

static Ecore_Input_Window*
_ecore_event_window_match(Ecore_Window id)
{
   Ecore_Input_Window *lookup;

   lookup = eina_hash_find(_window_hash, &id);
   if (!lookup) return NULL;
   if (lookup->ignore_event) return NULL; /* Pass on event. */
   return lookup;
}

static Eina_Bool
_ecore_event_evas_key(Ecore_Event_Key *e, Ecore_Event_Press press)
{
   Ecore_Input_Window *lookup;

   lookup = _ecore_event_window_match(e->event_window);
   if (!lookup) return ECORE_CALLBACK_PASS_ON;
   ecore_event_evas_modifier_lock_update(lookup->evas, e->modifiers);
   if (press == ECORE_DOWN)
     evas_event_feed_key_down_with_keycode(lookup->evas,
                                           e->keyname,
                                           e->key,
                                           e->string,
                                           e->compose,
                                           e->timestamp,
                                           e->data,
                                           e->keycode);
   else
     evas_event_feed_key_up_with_keycode(lookup->evas,
                                         e->keyname,
                                         e->key,
                                         e->string,
                                         e->compose,
                                         e->timestamp,
                                         e->data,
                                         e->keycode);
   return ECORE_CALLBACK_PASS_ON;
}

static Eina_Bool
_ecore_event_evas_mouse_button(Ecore_Event_Mouse_Button *e, Ecore_Event_Press press, Eina_Bool faked)
{
   Ecore_Event_Last *eel;
   Ecore_Input_Window *lookup;
   Evas_Button_Flags flags = EVAS_BUTTON_NONE;

   lookup = _ecore_event_window_match(e->event_window);
   if (!lookup) return ECORE_CALLBACK_PASS_ON;
   if (e->double_click) flags |= EVAS_BUTTON_DOUBLE_CLICK;
   if (e->triple_click) flags |= EVAS_BUTTON_TRIPLE_CLICK;
   INF("\tButtonEvent:ecore_event_evas press(%d), device(%d), button(%d), fake(%d)", press, e->multi.device, e->buttons, faked);
   if (_last_events_enable)
     {
        //error handle: if ecore up without ecore down
        if (press == ECORE_UP)
          {
             eel = _ecore_event_evas_lookup(e->multi.device, e->buttons, EINA_FALSE);
             if ((!eel) || (eel->state == ECORE_INPUT_UP))
               {
                  INF("ButtonEvent: up event without down event.");
                  return ECORE_CALLBACK_PASS_ON;
               }
          }
     }

   if (!faked) _ecore_event_evas_push_mouse_button(e, press);
   if (e->multi.device == 0)
     {
        ecore_event_evas_modifier_lock_update(lookup->evas, e->modifiers);
        if (press == ECORE_DOWN)
          evas_event_feed_mouse_down(lookup->evas, e->buttons, flags,
                                     e->timestamp, NULL);
        else
          evas_event_feed_mouse_up(lookup->evas, e->buttons, flags,
                                   e->timestamp, NULL);
     }
   else
     {
        if (press == ECORE_DOWN)
          {
             if (lookup->down_multi)
                lookup->down_multi(lookup->window, e->multi.device,
                                   e->x, e->y, e->multi.radius,
                                   e->multi.radius_x, e->multi.radius_y,
                                   e->multi.pressure, e->multi.angle,
                                   e->multi.x, e->multi.y, flags,
                                   e->timestamp);
             else
               evas_event_input_multi_down(lookup->evas, e->multi.device,
                                           e->x, e->y, e->multi.radius,
                                           e->multi.radius_x, e->multi.radius_y,
                                           e->multi.pressure, e->multi.angle,
                                           e->multi.x, e->multi.y, flags,
                                           e->timestamp, NULL);
          }
        else
          {
             if (lookup->up_multi)
                lookup->up_multi(lookup->window, e->multi.device,
                                 e->x, e->y, e->multi.radius,
                                 e->multi.radius_x, e->multi.radius_y,
                                 e->multi.pressure, e->multi.angle,
                                 e->multi.x, e->multi.y, flags,
                                 e->timestamp);
             else
               evas_event_input_multi_up(lookup->evas, e->multi.device,
                                         e->x, e->y, e->multi.radius,
                                         e->multi.radius_x, e->multi.radius_y,
                                         e->multi.pressure, e->multi.angle,
                                         e->multi.x, e->multi.y, flags,
                                         e->timestamp, NULL);
          }
     }
   return ECORE_CALLBACK_PASS_ON;
}

EAPI Eina_Bool
ecore_event_evas_mouse_move(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
   Ecore_Event_Mouse_Move *e;
   Ecore_Input_Window *lookup;

   e = event;
   lookup = _ecore_event_window_match(e->event_window);
   if (!lookup) return ECORE_CALLBACK_PASS_ON;
   if (e->multi.device == 0)
     {
        _ecore_event_evas_push_mouse_move(e);
        ecore_event_evas_modifier_lock_update(lookup->evas, e->modifiers);
        if (lookup->move_mouse)
           lookup->move_mouse(lookup->window, e->x, e->y, e->timestamp);
        else
           evas_event_input_mouse_move(lookup->evas, e->x, e->y, e->timestamp,
                                      NULL);
     }
   else
     {
        if (lookup->move_multi)
           lookup->move_multi(lookup->window, e->multi.device,
                              e->x, e->y, e->multi.radius,
                              e->multi.radius_x, e->multi.radius_y,
                              e->multi.pressure, e->multi.angle,
                              e->multi.x, e->multi.y, e->timestamp);
        else
          evas_event_input_multi_move(lookup->evas, e->multi.device,
                                      e->x, e->y, e->multi.radius,
                                      e->multi.radius_x, e->multi.radius_y,
                                      e->multi.pressure, e->multi.angle,
                                      e->multi.x, e->multi.y, e->timestamp,
                                      NULL);
     }
   return ECORE_CALLBACK_PASS_ON;
}

EAPI Eina_Bool
ecore_event_evas_mouse_button_down(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
   return _ecore_event_evas_mouse_button((Ecore_Event_Mouse_Button *)event, ECORE_DOWN, EINA_FALSE);
}

EAPI Eina_Bool
ecore_event_evas_mouse_button_up(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
   return _ecore_event_evas_mouse_button((Ecore_Event_Mouse_Button *)event, ECORE_UP, EINA_FALSE);
}

static Eina_Bool
_ecore_event_evas_mouse_io(Ecore_Event_Mouse_IO *e, Ecore_Event_IO io)
{
   Ecore_Input_Window *lookup;

   lookup = _ecore_event_window_match(e->event_window);
   if (!lookup) return ECORE_CALLBACK_PASS_ON;
   ecore_event_evas_modifier_lock_update(lookup->evas, e->modifiers);
   switch (io)
     {
      case ECORE_IN:
         evas_event_feed_mouse_in(lookup->evas, e->timestamp, NULL);
         break;
      case ECORE_OUT:
         evas_event_feed_mouse_out(lookup->evas, e->timestamp, NULL);
         break;
      default:
         break;
     }

   lookup->move_mouse(lookup->window, e->x, e->y, e->timestamp);
   return ECORE_CALLBACK_PASS_ON;
}

EAPI Eina_Bool
ecore_event_evas_key_down(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
   return _ecore_event_evas_key((Ecore_Event_Key *)event, ECORE_DOWN);
}

EAPI Eina_Bool
ecore_event_evas_key_up(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
   return _ecore_event_evas_key((Ecore_Event_Key *)event, ECORE_UP);
}

EAPI Eina_Bool
ecore_event_evas_mouse_wheel(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
   Ecore_Event_Mouse_Wheel *e;
   Ecore_Input_Window *lookup;

   e = event;
   lookup = _ecore_event_window_match(e->event_window);
   if (!lookup) return ECORE_CALLBACK_PASS_ON;
   ecore_event_evas_modifier_lock_update(lookup->evas, e->modifiers);
   evas_event_feed_mouse_wheel(lookup->evas, e->direction, e->z, e->timestamp, NULL);
   return ECORE_CALLBACK_PASS_ON;
}

EAPI Eina_Bool
ecore_event_evas_mouse_in(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
   return _ecore_event_evas_mouse_io((Ecore_Event_Mouse_IO *)event, ECORE_IN);
}

EAPI Eina_Bool
ecore_event_evas_mouse_out(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
   return _ecore_event_evas_mouse_io((Ecore_Event_Mouse_IO *)event, ECORE_OUT);
}

EAPI Eina_Bool
ecore_event_evas_axis_update(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
   Ecore_Event_Axis_Update *e;
   Ecore_Input_Window *lookup;

   e = event;
   lookup = _ecore_event_window_match(e->event_window);
   if (!lookup) return ECORE_CALLBACK_PASS_ON;
   evas_event_feed_axis_update(lookup->evas, e->timestamp, e->device,
                               e->toolid, e->naxis,
                               (Evas_Axis *)e->axis, NULL);
   return ECORE_CALLBACK_PASS_ON;
}

EAPI int
ecore_event_evas_init(void)
{
   if (++_ecore_event_evas_init_count !=  1)
     return _ecore_event_evas_init_count;

   _ecore_input_evas_log_dom = eina_log_domain_register
     ("ecore_input_evas",  ECORE_INPUT_EVAS_DEFAULT_LOG_COLOR);
   if (_ecore_input_evas_log_dom < 0)
     {
        EINA_LOG_ERR("Impossible to create a log domain for the ecore input evas_module.");
        return --_ecore_event_evas_init_count;
     }

   if (!ecore_init())
     {
        return --_ecore_event_evas_init_count;
     }

   if (!ecore_event_init())
     {
        goto shutdown_ecore;
     }

   ecore_event_evas_handlers[0] = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
                                                          ecore_event_evas_key_down,
                                                          NULL);
   ecore_event_evas_handlers[1] = ecore_event_handler_add(ECORE_EVENT_KEY_UP,
                                                          ecore_event_evas_key_up,
                                                          NULL);
   ecore_event_evas_handlers[2] = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
                                                          ecore_event_evas_mouse_button_down,
                                                          NULL);
   ecore_event_evas_handlers[3] = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
                                                          ecore_event_evas_mouse_button_up,
                                                          NULL);
   ecore_event_evas_handlers[4] = ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE,
                                                          ecore_event_evas_mouse_move,
                                                          NULL);
   ecore_event_evas_handlers[5] = ecore_event_handler_add(ECORE_EVENT_MOUSE_WHEEL,
                                                          ecore_event_evas_mouse_wheel,
                                                          NULL);
   ecore_event_evas_handlers[6] = ecore_event_handler_add(ECORE_EVENT_MOUSE_IN,
                                                          ecore_event_evas_mouse_in,
                                                          NULL);
   ecore_event_evas_handlers[7] = ecore_event_handler_add(ECORE_EVENT_MOUSE_OUT,
                                                          ecore_event_evas_mouse_out,
                                                          NULL);
   ecore_event_evas_handlers[8] = ecore_event_handler_add(ECORE_EVENT_AXIS_UPDATE,
                                                          ecore_event_evas_axis_update,
                                                          NULL);

   _window_hash = eina_hash_pointer_new(free);

   if (getenv("ECORE_INPUT_FIX"))
     {
        const char *tmp;

        _last_events_enable = EINA_TRUE;

        tmp = getenv("ECORE_INPUT_TIMEOUT_FIX");
        if (tmp)
          _last_events_timeout = ((double) atoi(tmp)) / 60;
     }

   return _ecore_event_evas_init_count;

   shutdown_ecore:
   ecore_shutdown();

   return --_ecore_event_evas_init_count;
}

EAPI int
ecore_event_evas_shutdown(void)
{
   size_t i;

   if (--_ecore_event_evas_init_count != 0)
     return _ecore_event_evas_init_count;

   eina_hash_free(_window_hash);
   _window_hash = NULL;
   for (i = 0; i < sizeof(ecore_event_evas_handlers) / sizeof(Ecore_Event_Handler *); i++)
     {
        ecore_event_handler_del(ecore_event_evas_handlers[i]);
        ecore_event_evas_handlers[i] = NULL;
     }

   ecore_event_shutdown();
   ecore_shutdown();

   eina_log_domain_unregister(_ecore_input_evas_log_dom);
   _ecore_input_evas_log_dom = -1;

   return _ecore_event_evas_init_count;
}