aboutsummaryrefslogblamecommitdiffstats
path: root/src/lib/evas/canvas/evas_callbacks.c
blob: a1ada65f22f954f4cfa7d1b6e858a9a89a434cad (plain) (tree)
1
2
3
4
5
6
7
8
9
                                
                         
 
                            
 

                     

                                     
                                                               
                                      
                                                                
                                       
 
                                                                
                                       
 
                                                             
                                               
                                                              
                                                
                                                                     
                                                
                                                                      
                                                 
                                                                    
                                                      
                                                                     
                                                       
 
                                                                   
                                             
                                                                    
                                                     


                                   
                                                                                    
 






















                                        






                                       
                                

                                  
                                    

                                    
  
































                                                                                                          
    
                                                               


                          

                                                                           
 
                                            
                 
                 



                                                           
                                                            
           
                                      
      
                 



                   
                                          
 
                                                                    
                          
 

                                     
                                      
      


    
                                                       
 

                                 
                                                                                  
 
                    
                               
                                                      
      
                                                   
                                                                                     
 


                                                                     


      
    
                                                       
 
                                              

 
    
                                       
 

                                 
                                                                    
 
                  
                             


                                                    
                                               
                                                                              




                                                                   


    
                                       
 
                                     


    
                                                                               
 
                                                                                            


    
                                                                                                                                              
 
               
                                              
                       
 
                    
                                                 
                                       
                                              








                                                                
                              
                               
                                       
 
                 
      

                     



























                                                                                              
           
 
                                                                                                     
 









                                                    
      
 
                          
      

                                                                  
           
                                                                                                                
                                                                                                          
           

                   

 
         
                                                                                                                         
 
                                                        
                                                                                       


         
                                                                                                                                                                   
 
                                                                                  
 
                                               

                     
 
                    
                     
 



                                                                  
 
                                                                        
                                                                                                      


                                                                   

 
           
                                                                                                       
 
                                 
 
                                               

                     
                                                                                  
 
                         
                          
 
                                    
 
                                                    
      
                                                         
           
                                    
                                                        
                                                                                    
 


                                                                          

                        
      

               
 
           
                                                                                                                              
 
                                 
 
                                               

                     
                                                                                  
 
                         



                                    
                                            
      
                                                                               
           
                                    
                                                        
                                                                                    
 


                                                                          

                        


               
 
         
                                                                                                  
 
                                                                               
                                                


         
                                                                                                                                            
 
                                                                    
 
                                       




                     



                                                           
 
                                                                        
                                                                                           

                                                                             


           
                                                                                
 
                                                                    
                          
 
                                       


                     
                       



                                  
                                          
      
                                                         
           
                                    
                                                    
                                                                             




                                                                        
           




               
                                                                                                       
 
                          
 
                                       

                     
                                                                    
 
                       



                                  
                                          
      
                                                                                 
           
                                    
                                                    
                                                                             
 


                                                                        

                        



               
         
                                                                                           

                          
 
                                       

                     
 
                                                                    
                  

                                                                             
                   
                                                     
                            
 




                                                          
         
                                                                           


                          
 
                                       

                     
 
                                                                    
                  









                                           
         
                                                                                                  


                          
 
                                       

                     
 
                                                                    
                  








                                                     
#include "evas_common_private.h"
#include "evas_private.h"

int _evas_event_counter = 0;

EVAS_MEMPOOL(_mp_pc);

extern Eina_Hash* signals_hash_table;

EAPI const Eo_Event_Description _EVAS_CANVAS_EVENT_RENDER_PRE =
   EO_EVENT_DESCRIPTION("Render Pre");
EAPI const Eo_Event_Description _EVAS_CANVAS_EVENT_RENDER_POST =
   EO_EVENT_DESCRIPTION("Render Post");

EAPI const Eo_Event_Description _EVAS_CANVAS_EVENT_AXIS_UPDATE =
   EO_EVENT_DESCRIPTION("Axis Update");

EAPI const Eo_Event_Description _EVAS_CANVAS_EVENT_FOCUS_IN =
   EO_EVENT_DESCRIPTION_HOT("Canvas Focus In");
EAPI const Eo_Event_Description _EVAS_CANVAS_EVENT_FOCUS_OUT =
   EO_EVENT_DESCRIPTION_HOT("Canvas Focus Out");
EAPI const Eo_Event_Description _EVAS_CANVAS_EVENT_RENDER_FLUSH_PRE =
   EO_EVENT_DESCRIPTION_HOT("Render Flush Pre");
EAPI const Eo_Event_Description _EVAS_CANVAS_EVENT_RENDER_FLUSH_POST =
   EO_EVENT_DESCRIPTION_HOT("Render Flush Post");
EAPI const Eo_Event_Description _EVAS_CANVAS_EVENT_OBJECT_FOCUS_IN =
   EO_EVENT_DESCRIPTION_HOT("Canvas Object Focus In");
EAPI const Eo_Event_Description _EVAS_CANVAS_EVENT_OBJECT_FOCUS_OUT =
   EO_EVENT_DESCRIPTION_HOT("Canvas Object Focus Out");

EAPI const Eo_Event_Description _EVAS_CANVAS_EVENT_DEVICE_CHANGED =
  EO_EVENT_DESCRIPTION_HOT("Device changed");
EAPI const Eo_Event_Description _EVAS_CANVAS_EVENT_VIEWPORT_RESIZE =
  EO_EVENT_DESCRIPTION_HOT("Canvas viewport resize");
/**
 * Evas events descriptions for Eo.
 */
static const Eo_Event_Description *_legacy_evas_callback_table[EVAS_CALLBACK_LAST] =
{
   EVAS_OBJECT_EVENT_MOUSE_IN,
   EVAS_OBJECT_EVENT_MOUSE_OUT,
   EVAS_OBJECT_EVENT_MOUSE_DOWN,
   EVAS_OBJECT_EVENT_MOUSE_UP,
   EVAS_OBJECT_EVENT_MOUSE_MOVE,
   EVAS_OBJECT_EVENT_MOUSE_WHEEL,
   EVAS_OBJECT_EVENT_MULTI_DOWN,
   EVAS_OBJECT_EVENT_MULTI_UP,
   EVAS_OBJECT_EVENT_MULTI_MOVE,
   EVAS_OBJECT_EVENT_FREE,
   EVAS_OBJECT_EVENT_KEY_DOWN,
   EVAS_OBJECT_EVENT_KEY_UP,
   EVAS_OBJECT_EVENT_FOCUS_IN,
   EVAS_OBJECT_EVENT_FOCUS_OUT,
   EVAS_OBJECT_EVENT_SHOW,
   EVAS_OBJECT_EVENT_HIDE,
   EVAS_OBJECT_EVENT_MOVE,
   EVAS_OBJECT_EVENT_RESIZE,
   EVAS_OBJECT_EVENT_RESTACK,
   EVAS_OBJECT_EVENT_DEL,
   EVAS_OBJECT_EVENT_HOLD,
   EVAS_OBJECT_EVENT_CHANGED_SIZE_HINTS,
   EVAS_OBJECT_EVENT_IMAGE_PRELOADED,
   EVAS_CANVAS_EVENT_FOCUS_IN,
   EVAS_CANVAS_EVENT_FOCUS_OUT,
   EVAS_CANVAS_EVENT_RENDER_FLUSH_PRE,
   EVAS_CANVAS_EVENT_RENDER_FLUSH_POST,
   EVAS_CANVAS_EVENT_OBJECT_FOCUS_IN,
   EVAS_CANVAS_EVENT_OBJECT_FOCUS_OUT,
   EVAS_OBJECT_EVENT_IMAGE_UNLOADED,
   EVAS_CANVAS_EVENT_RENDER_PRE,
   EVAS_CANVAS_EVENT_RENDER_POST,
   EVAS_OBJECT_EVENT_IMAGE_RESIZE,
   EVAS_CANVAS_EVENT_DEVICE_CHANGED,
   EVAS_CANVAS_EVENT_AXIS_UPDATE,
   EVAS_CANVAS_EVENT_VIEWPORT_RESIZE
};

typedef struct
{
   EINA_INLIST;
   Evas_Object_Event_Cb func;
   void *data;
   Evas_Callback_Type type;
} _eo_evas_object_cb_info;

static Eina_Bool
_eo_evas_object_cb(void *data, Eo *eo_obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
{
   _eo_evas_object_cb_info *info = data;
   if (info->func) info->func(info->data, evas_object_evas_get(eo_obj), eo_obj, event_info);
   return EINA_TRUE;
}

typedef struct
{
   EINA_INLIST;
   Evas_Event_Cb func;
   void *data;
   Evas_Callback_Type type;
} _eo_evas_cb_info;

static Eina_Bool
_eo_evas_cb(void *data, Eo *eo_obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info)
{
   _eo_evas_cb_info *info = data;
   if (info->func) info->func(info->data, eo_obj, event_info);
   return EINA_TRUE;
}

void
_evas_post_event_callback_call(Evas *eo_e, Evas_Public_Data *e)
{
   Evas_Post_Callback *pc;
   int skip = 0;
   static int first_run = 1; // FIXME: This is a workaround to prevent this
                             // function from being called recursively.

   if (e->delete_me || (!first_run)) return;
   _evas_walk(e);
   first_run = 0;
   EINA_LIST_FREE(e->post_events, pc)
     {
        if ((!skip) && (!e->delete_me) && (!pc->delete_me))
          {
             if (!pc->func((void*)pc->data, eo_e)) skip = 1;
          }
        EVAS_MEMPOOL_FREE(_mp_pc, pc);
     }
   first_run = 1;
   _evas_unwalk(e);
}

void
_evas_post_event_callback_free(Evas *eo_e)
{
   Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
   Evas_Post_Callback *pc;

   EINA_LIST_FREE(e->post_events, pc)
     {
        EVAS_MEMPOOL_FREE(_mp_pc, pc);
     }
}

void
evas_object_event_callback_all_del(Evas_Object *eo_obj)
{
   _eo_evas_object_cb_info *info;
   Eina_Inlist *itr;
   Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);

   if (!obj) return;
   if (!obj->callbacks) return;
   EINA_INLIST_FOREACH_SAFE(obj->callbacks, itr, info)
     {
        eo_do(eo_obj, eo_event_callback_del(eo_obj,
                 _legacy_evas_callback_table[info->type], _eo_evas_object_cb, info));

        obj->callbacks =
           eina_inlist_remove(obj->callbacks, EINA_INLIST_GET(info));
        free(info);
     }
}

void
evas_object_event_callback_cleanup(Evas_Object *eo_obj)
{
   evas_object_event_callback_all_del(eo_obj);
}

void
evas_event_callback_all_del(Evas *eo_e)
{
   _eo_evas_object_cb_info *info;
   Eina_Inlist *itr;
   Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CANVAS_CLASS);

   if (!e) return;
   if (!e->callbacks) return;

   EINA_INLIST_FOREACH_SAFE(e->callbacks, itr, info)
     {
        eo_do(eo_e, eo_event_callback_del(eo_e,
                 _legacy_evas_callback_table[info->type], _eo_evas_cb, info));

        e->callbacks =
           eina_inlist_remove(e->callbacks, EINA_INLIST_GET(info));
        free(info);
     }
}

void
evas_event_callback_cleanup(Evas *eo_e)
{
   evas_event_callback_all_del(eo_e);
}

void
evas_event_callback_call(Evas *eo_e, Evas_Callback_Type type, void *event_info)
{
   eo_do(eo_e, eo_event_callback_call(eo_e, _legacy_evas_callback_table[type], event_info));
}

void
evas_object_event_callback_call(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, Evas_Callback_Type type, void *event_info, int event_id)
{
   /* MEM OK */
   Evas_Button_Flags flags = EVAS_BUTTON_NONE;
   Evas_Public_Data *e;

   if (!obj) return;
   if ((obj->delete_me) || (!obj->layer)) return;
   if ((obj->last_event == event_id) &&
       (obj->last_event_type == type)) return;
   if (obj->last_event > event_id)
     {
        if ((obj->last_event_type == EVAS_CALLBACK_MOUSE_OUT) &&
            ((type >= EVAS_CALLBACK_MOUSE_DOWN) &&
             (type <= EVAS_CALLBACK_MULTI_MOVE)))
          {
             return;
          }
     }
   obj->last_event = event_id;
   obj->last_event_type = type;
   if (!(e = obj->layer->evas)) return;

   _evas_walk(e);
     {
        switch (type)
          {
           case EVAS_CALLBACK_MOUSE_DOWN:
                {
                   Evas_Event_Mouse_Down *ev = event_info;

                   flags = ev->flags;
                   if (ev->flags & (EVAS_BUTTON_DOUBLE_CLICK | EVAS_BUTTON_TRIPLE_CLICK))
                     {
                        if (obj->last_mouse_down_counter < (e->last_mouse_down_counter - 1))
                          ev->flags &= ~(EVAS_BUTTON_DOUBLE_CLICK | EVAS_BUTTON_TRIPLE_CLICK);
                     }
                   obj->last_mouse_down_counter = e->last_mouse_down_counter;
                   break;
                }
           case EVAS_CALLBACK_MOUSE_UP:
                {
                   Evas_Event_Mouse_Up *ev = event_info;

                   flags = ev->flags;
                   if (ev->flags & (EVAS_BUTTON_DOUBLE_CLICK | EVAS_BUTTON_TRIPLE_CLICK))
                     {
                        if (obj->last_mouse_up_counter < (e->last_mouse_up_counter - 1))
                          ev->flags &= ~(EVAS_BUTTON_DOUBLE_CLICK | EVAS_BUTTON_TRIPLE_CLICK);
                     }
                   obj->last_mouse_up_counter = e->last_mouse_up_counter;
                   break;
                }
           default:
              break;
          }

        eo_do(eo_obj, eo_event_callback_call(eo_obj, _legacy_evas_callback_table[type], event_info));

        if (type == EVAS_CALLBACK_MOUSE_DOWN)
          {
             Evas_Event_Mouse_Down *ev = event_info;
             ev->flags = flags;
          }
        else if (type == EVAS_CALLBACK_MOUSE_UP)
          {
             Evas_Event_Mouse_Up *ev = event_info;
             ev->flags = flags;
          }
     }

   if (!obj->no_propagate)
     {
        if ((obj->smart.parent) && (type != EVAS_CALLBACK_FREE) &&
              (type <= EVAS_CALLBACK_KEY_UP))
          {
             Evas_Object_Protected_Data *smart_parent = eo_data_scope_get(obj->smart.parent, EVAS_OBJECT_CLASS);
             evas_object_event_callback_call(obj->smart.parent, smart_parent, type, event_info, event_id);
          }
     }
   _evas_unwalk(e);
}

EAPI void
evas_object_event_callback_add(Evas_Object *eo_obj, Evas_Callback_Type type, Evas_Object_Event_Cb func, const void *data)
{
   evas_object_event_callback_priority_add(eo_obj, type,
                                           EVAS_CALLBACK_PRIORITY_DEFAULT, func, data);
}

EAPI void
evas_object_event_callback_priority_add(Evas_Object *eo_obj, Evas_Callback_Type type, Evas_Callback_Priority priority, Evas_Object_Event_Cb func, const void *data)
{
   Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);

   MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
   return;
   MAGIC_CHECK_END();

   if (!obj) return;
   if (!func) return;

   _eo_evas_object_cb_info *cb_info = calloc(1, sizeof(*cb_info));
   cb_info->func = func;
   cb_info->data = (void *)data;
   cb_info->type = type;

   const Eo_Event_Description *desc = _legacy_evas_callback_table[type];
   eo_do(eo_obj, eo_event_callback_priority_add(eo_obj, desc, priority, _eo_evas_object_cb, cb_info));

   obj->callbacks =
      eina_inlist_append(obj->callbacks, EINA_INLIST_GET(cb_info));
}

EAPI void *
evas_object_event_callback_del(Evas_Object *eo_obj, Evas_Callback_Type type, Evas_Object_Event_Cb func)
{
   _eo_evas_object_cb_info *info;

   MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
   return NULL;
   MAGIC_CHECK_END();
   Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);

   if (!obj) return NULL;
   if (!func) return NULL;

   if (!obj->callbacks) return NULL;

   EINA_INLIST_REVERSE_FOREACH(obj->callbacks, info)
     {
        if ((info->func == func) && (info->type == type))
          {
             void *tmp = info->data;
             eo_do(eo_obj, eo_event_callback_del(eo_obj,
                      _legacy_evas_callback_table[type], _eo_evas_object_cb, info));

             obj->callbacks =
                eina_inlist_remove(obj->callbacks, EINA_INLIST_GET(info));
             free(info);
             return tmp;
          }
     }
   return NULL;
}

EAPI void *
evas_object_event_callback_del_full(Evas_Object *eo_obj, Evas_Callback_Type type, Evas_Object_Event_Cb func, const void *data)
{
   _eo_evas_object_cb_info *info;

   MAGIC_CHECK(eo_obj, Evas_Object, MAGIC_OBJ);
   return NULL;
   MAGIC_CHECK_END();
   Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);

   if (!obj) return NULL;
   if (!func) return NULL;

   if (!obj->callbacks) return NULL;

   EINA_INLIST_FOREACH(obj->callbacks, info)
     {
        if ((info->func == func) && (info->type == type) && info->data == data)
          {
             void *tmp = info->data;
             eo_do(eo_obj, eo_event_callback_del(eo_obj,
                      _legacy_evas_callback_table[type], _eo_evas_object_cb, info));

             obj->callbacks =
                eina_inlist_remove(obj->callbacks, EINA_INLIST_GET(info));
             free(info);
             return tmp;
          }
     }
   return NULL;
}

EAPI void
evas_event_callback_add(Evas *eo_e, Evas_Callback_Type type, Evas_Event_Cb func, const void *data)
{
   evas_event_callback_priority_add(eo_e, type, EVAS_CALLBACK_PRIORITY_DEFAULT,
                                    func, data);
}

EAPI void
evas_event_callback_priority_add(Evas *eo_e, Evas_Callback_Type type, Evas_Callback_Priority priority, Evas_Event_Cb func, const void *data)
{
   Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CANVAS_CLASS);

   MAGIC_CHECK(eo_e, Evas, MAGIC_EVAS);
   return;
   MAGIC_CHECK_END();

   if (!func) return;

   _eo_evas_cb_info *cb_info = calloc(1, sizeof(*cb_info));
   cb_info->func = func;
   cb_info->data = (void *)data;
   cb_info->type = type;

   const Eo_Event_Description *desc = _legacy_evas_callback_table[type];
   eo_do(eo_e, eo_event_callback_priority_add(eo_e, desc, priority, _eo_evas_cb, cb_info));

   e->callbacks = eina_inlist_append(e->callbacks, EINA_INLIST_GET(cb_info));
}

EAPI void *
evas_event_callback_del(Evas *eo_e, Evas_Callback_Type type, Evas_Event_Cb func)
{
   Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
   _eo_evas_cb_info *info;

   MAGIC_CHECK(eo_e, Evas, MAGIC_EVAS);
   return NULL;
   MAGIC_CHECK_END();

   if (!e) return NULL;
   if (!func) return NULL;

   if (!e->callbacks) return NULL;

   EINA_INLIST_FOREACH(e->callbacks, info)
     {
        if ((info->func == func) && (info->type == type))
          {
             void *tmp = info->data;
             eo_do(eo_e, eo_event_callback_del(eo_e,
                      _legacy_evas_callback_table[type], _eo_evas_cb, info));

             e->callbacks =
                eina_inlist_remove(e->callbacks, EINA_INLIST_GET(info));
             free(info);
             return tmp;
          }
     }
   return NULL;
}

EAPI void *
evas_event_callback_del_full(Evas *eo_e, Evas_Callback_Type type, Evas_Event_Cb func, const void *data)
{
   _eo_evas_cb_info *info;

   MAGIC_CHECK(eo_e, Evas, MAGIC_EVAS);
   return NULL;
   MAGIC_CHECK_END();
   Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CANVAS_CLASS);

   if (!e) return NULL;
   if (!func) return NULL;

   if (!e->callbacks) return NULL;

   EINA_INLIST_FOREACH(e->callbacks, info)
     {
        if ((info->func == func) && (info->type == type) && (info->data == data))
          {
             void *tmp = info->data;
             eo_do(eo_e, eo_event_callback_del(eo_e,
                      _legacy_evas_callback_table[type], _eo_evas_cb, info));

             e->callbacks =
                eina_inlist_remove(e->callbacks, EINA_INLIST_GET(info));
             free(info);
             return tmp;
          }
     }
   return NULL;
}

EAPI void
evas_post_event_callback_push(Evas *eo_e, Evas_Object_Event_Post_Cb func, const void *data)
{
   Evas_Post_Callback *pc;

   MAGIC_CHECK(eo_e, Evas, MAGIC_EVAS);
   return;
   MAGIC_CHECK_END();

   Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
   if (!e) return;
   EVAS_MEMPOOL_INIT(_mp_pc, "evas_post_callback", Evas_Post_Callback, 64, );
   pc = EVAS_MEMPOOL_ALLOC(_mp_pc, Evas_Post_Callback);
   if (!pc) return;
   EVAS_MEMPOOL_PREP(_mp_pc, pc, Evas_Post_Callback);
   if (e->delete_me) return;

   pc->func = func;
   pc->data = data;
   e->post_events = eina_list_prepend(e->post_events, pc);
}

EAPI void
evas_post_event_callback_remove(Evas *eo_e, Evas_Object_Event_Post_Cb func)
{
   Evas_Post_Callback *pc;
   Eina_List *l;

   MAGIC_CHECK(eo_e, Evas, MAGIC_EVAS);
   return;
   MAGIC_CHECK_END();

   Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
   if (!e) return;
   EINA_LIST_FOREACH(e->post_events, l, pc)
     {
        if (pc->func == func)
          {
             pc->delete_me = 1;
             return;
          }
     }
}

EAPI void
evas_post_event_callback_remove_full(Evas *eo_e, Evas_Object_Event_Post_Cb func, const void *data)
{
   Evas_Post_Callback *pc;
   Eina_List *l;

   MAGIC_CHECK(eo_e, Evas, MAGIC_EVAS);
   return;
   MAGIC_CHECK_END();

   Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
   if (!e) return;
   EINA_LIST_FOREACH(e->post_events, l, pc)
     {
        if ((pc->func == func) && (pc->data == data))
          {
             pc->delete_me = 1;
             return;
          }
     }
}