1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4 
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <math.h>
10 
11 #include "Ecore.h"
12 #include "ecore_private.h"
13 
14 #define MY_CLASS EFL_LOOP_MESSAGE_HANDLER_CLASS
15 
16 #include "ecore_main_common.h"
17 
18 typedef struct _Efl_Loop_Message_Handler_Data Efl_Loop_Message_Handler_Data;
19 
20 struct _Efl_Loop_Message_Handler_Data
21 {
22    Eo *loop;
23    Efl_Loop_Data *loop_data;
24 };
25 
26 EOLIAN static Efl_Loop_Message *
_efl_loop_message_handler_message_add(Eo * obj,Efl_Loop_Message_Handler_Data * pd EINA_UNUSED)27 _efl_loop_message_handler_message_add(Eo *obj, Efl_Loop_Message_Handler_Data *pd EINA_UNUSED)
28 {
29    // XXX: implement message object cache
30    Efl_Loop_Message *message = efl_add(EFL_LOOP_MESSAGE_CLASS, obj);
31    if (!message) return NULL;
32    // XXX: track added messages not sent yet ...
33    return message;
34 }
35 
36 EOLIAN static void
_efl_loop_message_handler_message_send(Eo * obj,Efl_Loop_Message_Handler_Data * pd,Efl_Loop_Message * message)37 _efl_loop_message_handler_message_send(Eo *obj, Efl_Loop_Message_Handler_Data *pd, Efl_Loop_Message *message)
38 {
39    Message *msg;
40 
41    if (EINA_UNLIKELY(!pd->loop))
42      {
43         pd->loop = efl_provider_find(obj, EFL_LOOP_CLASS);
44         if (!pd->loop) return;
45         pd->loop_data = efl_data_scope_get(pd->loop, EFL_LOOP_CLASS);
46         if (!pd->loop_data)
47           {
48              pd->loop = NULL;
49              return;
50           }
51      }
52    msg = calloc(1, sizeof(Message));
53    if (msg)
54      {
55         msg->handler = obj;
56         msg->message = message;
57         if (pd->loop_data->message_walking > 0)
58           {
59              pd->loop_data->message_pending_queue = eina_inlist_append
60                 (pd->loop_data->message_pending_queue, EINA_INLIST_GET(msg));
61           }
62         else
63           {
64              pd->loop_data->message_queue = eina_inlist_append
65                 (pd->loop_data->message_queue, EINA_INLIST_GET(msg));
66           }
67         _efl_loop_message_send_info_set(message, EINA_INLIST_GET(msg),
68                                        pd->loop, pd->loop_data);
69         return;
70      }
71    efl_del(message);
72 }
73 
74 EOLIAN static void
_efl_loop_message_handler_message_call(Eo * obj,Efl_Loop_Message_Handler_Data * pd,Efl_Loop_Message * message)75 _efl_loop_message_handler_message_call(Eo *obj, Efl_Loop_Message_Handler_Data *pd, Efl_Loop_Message *message)
76 {
77    Message *msg;
78    unsigned int n = 0;
79    Eina_Bool found = EINA_FALSE;
80 
81    if (!pd->loop) return;
82    EINA_INLIST_FOREACH(pd->loop_data->message_queue, msg)
83      {
84         n++;
85         if (msg->message != message) continue;
86         found = EINA_TRUE;
87         msg->message = NULL;
88         msg->handler = NULL;
89         _efl_loop_message_send_info_set(message, NULL, NULL, NULL);
90         if ((pd->loop_data->message_walking == 0) || (n == 1))
91           {
92              pd->loop_data->message_queue =
93                eina_inlist_remove(pd->loop_data->message_queue,
94                                   EINA_INLIST_GET(msg));
95              free(msg);
96           }
97         else
98           msg->delete_me = EINA_TRUE;
99         break;
100      }
101    efl_event_callback_call(message, EFL_LOOP_MESSAGE_EVENT_MESSAGE,
102                            message);
103    efl_event_callback_call(obj, EFL_LOOP_MESSAGE_HANDLER_EVENT_MESSAGE,
104                            message);
105    // XXX: implement message object cache...
106    if (message) efl_del(message);
107    if (found) return;
108    ERR("Cannot find message called object %p on message queue", message);
109 }
110 
111 EOLIAN static Eina_Bool
_efl_loop_message_handler_message_clear(Eo * obj,Efl_Loop_Message_Handler_Data * pd)112 _efl_loop_message_handler_message_clear(Eo *obj, Efl_Loop_Message_Handler_Data *pd)
113 {
114    Eina_Inlist *tmp;
115    Message *msg;
116 
117    if (!pd->loop) return EINA_FALSE;
118    if (!pd->loop_data->message_queue) return EINA_FALSE;
119    EINA_INLIST_FOREACH_SAFE(pd->loop_data->message_queue, tmp, msg)
120      {
121         if (msg->handler == obj)
122           {
123              Eo *message = msg->message;
124 
125              msg->delete_me = EINA_TRUE;
126              msg->handler = NULL;
127              msg->message = NULL;
128              _efl_loop_message_send_info_set(message, NULL, NULL, NULL);
129              if (pd->loop_data->message_walking == 0)
130                {
131                   pd->loop_data->message_queue =
132                     eina_inlist_remove(pd->loop_data->message_queue,
133                                        EINA_INLIST_GET(msg));
134                   free(msg);
135                }
136              if (message) efl_del(message);
137           }
138      }
139    return EINA_FALSE;
140 }
141 
142 EOLIAN static Efl_Object *
_efl_loop_message_handler_efl_object_constructor(Eo * obj,Efl_Loop_Message_Handler_Data * pd EINA_UNUSED)143 _efl_loop_message_handler_efl_object_constructor(Eo *obj, Efl_Loop_Message_Handler_Data *pd EINA_UNUSED)
144 {
145    obj = efl_constructor(efl_super(obj, MY_CLASS));
146    return obj;
147 }
148 
149 EOLIAN static void
_efl_loop_message_handler_efl_object_destructor(Eo * obj,Efl_Loop_Message_Handler_Data * pd EINA_UNUSED)150 _efl_loop_message_handler_efl_object_destructor(Eo *obj, Efl_Loop_Message_Handler_Data *pd EINA_UNUSED)
151 {
152    efl_destructor(efl_super(obj, MY_CLASS));
153 }
154 
155 #include "efl_loop_message_handler.eo.c"
156