oooh you'd love to know why this is here.. won't you? :)
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 4 May 2010 15:58:10 +0000 (15:58 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 4 May 2010 15:58:10 +0000 (15:58 +0000)
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@48613 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/Evas.h
src/lib/canvas/evas_callbacks.c
src/lib/canvas/evas_events.c
src/lib/canvas/evas_focus.c
src/lib/canvas/evas_main.c
src/lib/canvas/evas_object_inform.c
src/lib/canvas/evas_object_main.c
src/lib/include/evas_private.h

index 5ee2ccf..0590049 100644 (file)
@@ -591,9 +591,10 @@ typedef enum _Evas_Object_Pointer_Mode
    EVAS_OBJECT_POINTER_MODE_NOGRAB
 } Evas_Object_Pointer_Mode; /**< How mouse pointer should be handled by Evas. */
 
-typedef void (*Evas_Smart_Cb) (void *data, Evas_Object *obj, void *event_info);
-typedef void (*Evas_Event_Cb) (void *data, Evas *e, void *event_info);
-typedef void (*Evas_Object_Event_Cb) (void *data, Evas *e, Evas_Object *obj, void *event_info);
+typedef void      (*Evas_Smart_Cb) (void *data, Evas_Object *obj, void *event_info);
+typedef void      (*Evas_Event_Cb) (void *data, Evas *e, void *event_info);
+typedef Eina_Bool (*Evas_Object_Event_Post_Cb) (void *data, Evas *e);
+typedef void      (*Evas_Object_Event_Cb) (void *data, Evas *e, Evas_Object *obj, void *event_info);
 
 #ifdef __cplusplus
 extern "C" {
@@ -769,10 +770,13 @@ extern "C" {
  * @ingroup Evas_Canvas
  */
 
-   EAPI void              evas_event_callback_add           (Evas *e, Evas_Callback_Type type, Evas_Event_Cb func, const void *data) EINA_ARG_NONNULL(1, 3);
-   EAPI void             *evas_event_callback_del           (Evas *e, Evas_Callback_Type type, Evas_Event_Cb func) EINA_ARG_NONNULL(1, 3);
-   EAPI void             *evas_event_callback_del_full      (Evas *e, Evas_Callback_Type type, Evas_Event_Cb func, const void *data) EINA_ARG_NONNULL(1, 3);
-
+   EAPI void              evas_event_callback_add              (Evas *e, Evas_Callback_Type type, Evas_Event_Cb func, const void *data) EINA_ARG_NONNULL(1, 3);
+   EAPI void             *evas_event_callback_del              (Evas *e, Evas_Callback_Type type, Evas_Event_Cb func) EINA_ARG_NONNULL(1, 3);
+   EAPI void             *evas_event_callback_del_full         (Evas *e, Evas_Callback_Type type, Evas_Event_Cb func, const void *data) EINA_ARG_NONNULL(1, 3);
+   EAPI void              evas_post_event_callback_push        (Evas *e, Evas_Object_Event_Post_Cb func, const void *data);
+   EAPI void              evas_post_event_callback_remove      (Evas *e, Evas_Object_Event_Post_Cb func);
+   EAPI void              evas_post_event_callback_remove_full (Evas *e, Evas_Object_Event_Post_Cb func, const void *data);
+       
 /**
  * @defgroup Evas_Image_Group Image Functions
  *
index fb90314..30ea8e5 100644 (file)
@@ -6,6 +6,37 @@ static void evas_event_callback_clear(Evas *e);
 int _evas_event_counter = 0;
 
 void
+_evas_post_event_callback_call(Evas *e)
+{
+   Evas_Post_Callback *pc;
+   int skip = 0;
+
+   if (e->delete_me) return;
+   _evas_walk(e);
+   EINA_LIST_FREE(e->post_events, pc)
+     {
+        if ((!skip) && (!e->delete_me) && (!pc->delete_me))
+          {
+             if (!pc->func(e, pc->data)) skip = 1;
+          }
+        free(pc);
+     }
+   _evas_unwalk(e);
+}
+
+void
+_evas_post_event_callback_free(Evas *e)
+{
+   Evas_Post_Callback *pc;
+   
+   EINA_LIST_FREE(e->post_events, pc)
+     {
+        free(pc);
+     }
+   _evas_unwalk(e);
+}
+
+void
 evas_event_callback_list_post_free(Eina_Inlist **list)
 {
    Eina_Inlist *l;
@@ -749,5 +780,108 @@ evas_event_callback_del_full(Evas *e, Evas_Callback_Type type, Evas_Event_Cb fun
 }
 
 /**
+ * Push a callback on the post-event callback stack
+ *
+ * @param e Canvas to push the callback on
+ * @param func The function that to be called when the stack is unwound
+ * @param data The data pointer to be passed to the callback
+ *
+ * Evas has a stack of callbacks that get called after all the callbacks for
+ * an event have triggered (all the objects it triggers on and al the callbacks
+ * in each object triggered). When all these have been called, the stack is
+ * unwond from most recently to least recently pushed item and removed from the
+ * stack calling the callback set for it.
+ * 
+ * This is intended for doing reverse logic-like processing, example - when a
+ * child object that happens to get the event later is meant to be able to
+ * "steal" functions from a parent and thus on unwind of this stack hav its
+ * function called first, thus being able to set flags, or return 0 from the
+ * post-callback that stops all other post-callbacks in the current stack from
+ * being called (thus basically allowing a child to take control, if the event
+ * callback prepares information ready for taking action, but the post callback
+ * actually does the action).
+ *
+ */
+EAPI void
+evas_post_event_callback_push(Evas *e, Evas_Object_Event_Post_Cb func, const void *data)
+{
+   Evas_Post_Callback *pc;
+   
+   MAGIC_CHECK(e, Evas, MAGIC_EVAS);
+   return;
+   MAGIC_CHECK_END();
+   
+   pc = evas_mem_calloc(sizeof(Evas_Post_Callback));
+   if (!pc) return;
+   if (e->delete_me) return;
+   
+   pc->func = func;
+   pc->data = data;
+   e->post_events = eina_list_prepend(e->post_events, pc);
+}
+
+/**
+ * Remove a callback from the post-event callback stack
+ * 
+ * @param e Canvas to push the callback on
+ * @param func The function that to be called when the stack is unwound
+ * 
+ * This removes a callback from the stack added with
+ * evas_post_event_callback_push(). The first instance of the function in
+ * the callback stack is removed from being executed when the stack is
+ * unwound. Further instances may still be run on unwind.
+ */
+EAPI void
+evas_post_event_callback_remove(Evas *e, Evas_Object_Event_Post_Cb func)
+{
+   Evas_Post_Callback *pc;
+   Eina_List *l;
+   
+   MAGIC_CHECK(e, Evas, MAGIC_EVAS);
+   return;
+   MAGIC_CHECK_END();
+   
+   EINA_LIST_FOREACH(e->post_events, l, pc)
+     {
+        if (pc->func == func)
+          {
+             pc->delete_me = 1;
+             return;
+          }
+     }
+}
+
+/**
+ * Remove a callback from the post-event callback stack
+ * 
+ * @param e Canvas to push the callback on
+ * @param func The function that to be called when the stack is unwound
+ * @param data The data pointer to be passed to the callback
+ * 
+ * This removes a callback from the stack added with
+ * evas_post_event_callback_push(). The first instance of the function and data
+ * in the callback stack is removed from being executed when the stack is
+ * unwound. Further instances may still be run on unwind.
+ */
+EAPI void
+evas_post_event_callback_remove_full(Evas *e, Evas_Object_Event_Post_Cb func, const void *data)
+{
+   Evas_Post_Callback *pc;
+   Eina_List *l;
+   
+   MAGIC_CHECK(e, Evas, MAGIC_EVAS);
+   return;
+   MAGIC_CHECK_END();
+   
+   EINA_LIST_FOREACH(e->post_events, l, pc)
+     {
+        if ((pc->func == func) && (pc->data == data))
+          {
+             pc->delete_me = 1;
+             return;
+          }
+     }
+}
+/**
  * @}
  */
index 39a3a30..76ce007 100644 (file)
@@ -343,6 +343,7 @@ evas_event_feed_mouse_down(Evas *e, int b, Evas_Button_Flags flags, unsigned int
      }
    if (copy) eina_list_free(copy);
    e->last_mouse_down_counter++;
+   _evas_post_event_callback_call(e);
    _evas_unwalk(e);
 }
 
@@ -413,6 +414,7 @@ evas_event_feed_mouse_up(Evas *e, int b, Evas_Button_Flags flags, unsigned int t
          }
        if (copy) copy = eina_list_free(copy);
        e->last_mouse_up_counter++;
+        _evas_post_event_callback_call(e);
      }
 
    if (!e->pointer.button)
@@ -455,6 +457,7 @@ evas_event_feed_mouse_up(Evas *e, int b, Evas_Button_Flags flags, unsigned int t
                    }
                  if (e->delete_me) break;
               }
+             _evas_post_event_callback_call(e);
          }
        if (copy) copy = eina_list_free(copy);
        if (e->pointer.inside)
@@ -489,6 +492,7 @@ evas_event_feed_mouse_up(Evas *e, int b, Evas_Button_Flags flags, unsigned int t
                    }
                  if (e->delete_me) break;
               }
+             _evas_post_event_callback_call(e);
          }
        else
          {
@@ -603,6 +607,7 @@ evas_event_feed_mouse_wheel(Evas *e, int direction, int z, unsigned int timestam
        if (e->delete_me) break;
      }
    if (copy) copy = eina_list_free(copy);
+   _evas_post_event_callback_call(e);
 
    _evas_unwalk(e);
 }
@@ -695,6 +700,7 @@ evas_event_feed_mouse_move(Evas *e, int x, int y, unsigned int timestamp, const
                    outs = eina_list_append(outs, obj);
                  if (e->delete_me) break;
               }
+             _evas_post_event_callback_call(e);
          }
          {
             Evas_Event_Mouse_Out ev;
@@ -730,6 +736,7 @@ evas_event_feed_mouse_move(Evas *e, int x, int y, unsigned int timestamp, const
                          evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_OUT, &ev);
                    }
               }
+             _evas_post_event_callback_call(e);
          }
      }
    else
@@ -820,6 +827,7 @@ evas_event_feed_mouse_move(Evas *e, int x, int y, unsigned int timestamp, const
               }
             if (e->delete_me) break;
          }
+        _evas_post_event_callback_call(e);
 
        _evas_object_event_new();
 
@@ -844,6 +852,7 @@ evas_event_feed_mouse_move(Evas *e, int x, int y, unsigned int timestamp, const
        eina_list_free(e->pointer.object.in);
        /* and set up the new one */
        e->pointer.object.in = ins;
+        _evas_post_event_callback_call(e);
      }
    _evas_unwalk(e);
 }
@@ -912,6 +921,7 @@ evas_event_feed_mouse_in(Evas *e, unsigned int timestamp, const void *data)
    e->pointer.object.in = eina_list_free(e->pointer.object.in);
    /* and set up the new one */
    e->pointer.object.in = ins;
+   _evas_post_event_callback_call(e);
    evas_event_feed_mouse_move(e, e->pointer.x, e->pointer.y, timestamp, data);
    _evas_unwalk(e);
 }
@@ -977,6 +987,7 @@ evas_event_feed_mouse_out(Evas *e, unsigned int timestamp, const void *data)
        if (copy) copy = eina_list_free(copy);
        /* free our old list of ins */
        e->pointer.object.in =  eina_list_free(e->pointer.object.in);
+        _evas_post_event_callback_call(e);
      }
    _evas_unwalk(e);
 }
@@ -1040,6 +1051,7 @@ evas_event_feed_multi_down(Evas *e,
        if (e->delete_me) break;
      }
    if (copy) eina_list_free(copy);
+   _evas_post_event_callback_call(e);
    _evas_unwalk(e);
 }
 
@@ -1102,7 +1114,7 @@ evas_event_feed_multi_up(Evas *e,
         if (e->delete_me) break;
      }
    if (copy) copy = eina_list_free(copy);
-   
+   _evas_post_event_callback_call(e);
    _evas_unwalk(e);
 }
 
@@ -1174,6 +1186,7 @@ evas_event_feed_multi_move(Evas *e,
               }
              if (e->delete_me) break;
          }
+        _evas_post_event_callback_call(e);
      }
    else
      {
@@ -1240,6 +1253,7 @@ evas_event_feed_multi_move(Evas *e,
        eina_list_free(e->pointer.object.in);
        /* and set up the new one */
        e->pointer.object.in = ins;
+        _evas_post_event_callback_call(e);
      }
    _evas_unwalk(e);
 }
@@ -1332,8 +1346,9 @@ evas_event_feed_key_down(Evas *e, const char *keyname, const char *key, const ch
        if ((e->focused) && (!exclusive))
          {
             if (e->events_frozen <= 0)
-              evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_DOWN, &ev);
+               evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_DOWN, &ev);
          }
+        _evas_post_event_callback_call(e);
      }
    _evas_unwalk(e);
 }
@@ -1426,8 +1441,9 @@ evas_event_feed_key_up(Evas *e, const char *keyname, const char *key, const char
        if ((e->focused) && (!exclusive))
          {
             if (e->events_frozen <= 0)
-              evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_UP, &ev);
+               evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_UP, &ev);
          }
+        _evas_post_event_callback_call(e);
      }
    _evas_unwalk(e);
 }
@@ -1473,8 +1489,8 @@ evas_event_feed_hold(Evas *e, int hold, unsigned int timestamp, const void *data
        if (e->delete_me) break;
      }
    if (copy) copy = eina_list_free(copy);
+   _evas_post_event_callback_call(e);
    _evas_unwalk(e);
-
    _evas_object_event_new();
 }
 
index 6e2ec5b..d63219a 100644 (file)
@@ -39,7 +39,7 @@ evas_object_focus_set(Evas_Object *obj, Eina_Bool focus)
 
    if (focus)
      {
-       if (obj->focused) return;
+       if (obj->focused) goto end;
        if (obj->layer->evas->focused)
          evas_object_focus_set(obj->layer->evas->focused, 0);
        obj->focused = 1;
@@ -48,11 +48,13 @@ evas_object_focus_set(Evas_Object *obj, Eina_Bool focus)
      }
    else
      {
-       if (!obj->focused) return;
+       if (!obj->focused) goto end;
        obj->focused = 0;
        obj->layer->evas->focused = NULL;
        evas_object_event_callback_call(obj, EVAS_CALLBACK_FOCUS_OUT, NULL);
      }
+   end:
+   _evas_post_event_callback_call(obj->layer->evas);
 }
 
 /**
index 56cb652..c60cb21 100644 (file)
@@ -194,6 +194,8 @@ evas_free(Evas *e)
        e->callbacks = NULL;
      }
    
+   _evas_post_event_callback_free(e);
+   
    del = 1;
    e->walking_list++;
    e->cleanup = 1;
index 8fbd040..90ead99 100644 (file)
@@ -9,6 +9,7 @@ evas_object_inform_call_show(Evas_Object *obj)
    _evas_object_event_new();
 
    evas_object_event_callback_call(obj, EVAS_CALLBACK_SHOW, NULL);
+   _evas_post_event_callback_call(obj->layer->evas);
 }
 
 void
@@ -17,6 +18,7 @@ evas_object_inform_call_hide(Evas_Object *obj)
    _evas_object_event_new();
 
    evas_object_event_callback_call(obj, EVAS_CALLBACK_HIDE, NULL);
+   _evas_post_event_callback_call(obj->layer->evas);
 }
 
 void
@@ -25,6 +27,7 @@ evas_object_inform_call_move(Evas_Object *obj)
    _evas_object_event_new();
 
    evas_object_event_callback_call(obj, EVAS_CALLBACK_MOVE, NULL);
+   _evas_post_event_callback_call(obj->layer->evas);
 }
 
 void
@@ -33,6 +36,7 @@ evas_object_inform_call_resize(Evas_Object *obj)
    _evas_object_event_new();
 
    evas_object_event_callback_call(obj, EVAS_CALLBACK_RESIZE, NULL);
+   _evas_post_event_callback_call(obj->layer->evas);
 }
 
 void
@@ -41,6 +45,7 @@ evas_object_inform_call_restack(Evas_Object *obj)
    _evas_object_event_new();
 
    evas_object_event_callback_call(obj, EVAS_CALLBACK_RESTACK, NULL);
+   _evas_post_event_callback_call(obj->layer->evas);
 }
 
 void
@@ -49,6 +54,7 @@ evas_object_inform_call_changed_size_hints(Evas_Object *obj)
    _evas_object_event_new();
 
    evas_object_event_callback_call(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, NULL);
+   _evas_post_event_callback_call(obj->layer->evas);
 }
 
 void
@@ -57,4 +63,5 @@ evas_object_inform_call_image_preloaded(Evas_Object *obj)
    _evas_object_event_new();
 
    evas_object_event_callback_call(obj, EVAS_CALLBACK_IMAGE_PRELOADED, NULL);
+   _evas_post_event_callback_call(obj->layer->evas);
 }
index 2dc2104..8173d4a 100644 (file)
@@ -371,6 +371,7 @@ evas_object_del(Evas_Object *obj)
    _evas_object_event_new();
 
    evas_object_event_callback_call(obj, EVAS_CALLBACK_DEL, NULL);
+   _evas_post_event_callback_call(obj->layer->evas);
    if (obj->name) evas_object_name_set(obj, NULL);
    if (!obj->layer)
      {
@@ -383,6 +384,7 @@ evas_object_del(Evas_Object *obj)
        obj->layer->evas->focused = NULL;
        _evas_object_event_new();
        evas_object_event_callback_call(obj, EVAS_CALLBACK_FOCUS_OUT, NULL);
+        _evas_post_event_callback_call(obj->layer->evas);
      }
    obj->layer->evas->pointer.mouse_grabbed -= obj->mouse_grabbed;
    obj->mouse_grabbed = 0;
@@ -394,6 +396,7 @@ evas_object_del(Evas_Object *obj)
    evas_object_map_set(obj, NULL);
    _evas_object_event_new();
    evas_object_event_callback_call(obj, EVAS_CALLBACK_FREE, NULL);
+   _evas_post_event_callback_call(obj->layer->evas);
    evas_object_smart_cleanup(obj);
    obj->delete_me = 1;
    evas_object_change(obj);
@@ -1174,6 +1177,7 @@ evas_object_hide(Evas_Object *obj)
                       ev.timestamp = obj->layer->evas->last_timestamp;
                       ev.event_flags = EVAS_EVENT_FLAG_NONE;
                        evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_OUT, &ev);
+                       _evas_post_event_callback_call(obj->layer->evas);
                    }
               }
          }
index 88ee0b2..2c01857 100644 (file)
@@ -50,6 +50,7 @@ typedef struct _Evas_Callbacks              Evas_Callbacks;
 typedef struct _Evas_Format                 Evas_Format;
 typedef struct _Evas_Map_Point              Evas_Map_Point;
 typedef struct _Evas_Smart_Cb_Description_Array Evas_Smart_Cb_Description_Array;
+typedef struct _Evas_Post_Callback          Evas_Post_Callback;
 
 #define MAGIC_EVAS                 0x70777770
 #define MAGIC_OBJ                  0x71777770
@@ -213,6 +214,14 @@ struct _Evas_Lock
    Evas_Modifier_Mask mask; /* we have a max of 64 locks */
 };
 
+struct _Evas_Post_Callback
+{
+   Evas_Object               *obj;
+   Evas_Object_Event_Post_Cb  func;
+   const void                *data;
+   unsigned char              delete_me : 1;
+};
+
 struct _Evas_Callbacks
 {
    Eina_Inlist *callbacks;
@@ -304,6 +313,8 @@ struct _Evas
    Eina_Array     calculate_objects;
    Eina_Array     clip_changes;
 
+   Eina_List     *post_events; // free me on evas_free
+   
    Evas_Callbacks *callbacks;
 
    int            delete_grabs;
@@ -790,6 +801,8 @@ void evas_object_smart_member_stack_below(Evas_Object *member, Evas_Object *othe
 const Eina_Inlist *evas_object_smart_members_get_direct(const Evas_Object *obj);
 void evas_call_smarts_calculate(Evas *e);
 void *evas_mem_calloc(int size);
+void _evas_post_event_callback_call(Evas *e);
+void _evas_post_event_callback_free(Evas *e);
 void evas_event_callback_list_post_free(Eina_Inlist **list);
 void evas_object_event_callback_all_del(Evas_Object *obj);
 void evas_object_event_callback_cleanup(Evas_Object *obj);