1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ppapi_simple/ps_event.h"
12 #include "ppapi_simple/ps_instance.h"
13 #include "ppapi_simple/ps_interface.h"
18 struct PSMessageHandlerInfo
{
20 PSMessageHandler_t func
;
22 struct PSMessageHandlerInfo
* prev
;
23 struct PSMessageHandlerInfo
* next
;
26 static uint32_t s_events_enabled
= PSE_NONE
;
27 static struct PSEvent
* s_event_head
;
28 static struct PSEvent
* s_event_tail
;
29 static pthread_mutex_t s_lock
= PTHREAD_MUTEX_INITIALIZER
;
30 static pthread_cond_t s_cond
= PTHREAD_COND_INITIALIZER
;
31 static struct PSMessageHandlerInfo
* s_handler_head
;
32 static struct PSMessageHandlerInfo
* s_handler_tail
;
34 static struct PSMessageHandlerInfo
* FindMessageHandler(
35 const char* message_name
) {
36 struct PSMessageHandlerInfo
* info
= s_handler_head
;
38 if (strcmp(info
->message_name
, message_name
) == 0) {
48 static void EnqueueEvent(struct PSEvent
* event
) {
49 pthread_mutex_lock(&s_lock
);
52 s_event_head
= s_event_tail
= event
;
55 s_event_tail
->next
= event
;
59 pthread_cond_signal(&s_cond
);
60 pthread_mutex_unlock(&s_lock
);
63 static struct PSEvent
* DequeueEvent(int block
) {
64 pthread_mutex_lock(&s_lock
);
67 while (s_event_head
== NULL
) {
68 pthread_cond_wait(&s_cond
, &s_lock
);
72 if (s_event_head
== NULL
) {
73 pthread_mutex_unlock(&s_lock
);
77 struct PSEvent
* item
= s_event_head
;
79 if (s_event_head
== s_event_tail
) {
80 s_event_head
= s_event_tail
= NULL
;
82 s_event_head
= s_event_head
->next
;
85 pthread_mutex_unlock(&s_lock
);
90 struct PSEvent
* PSEventTryAcquire() {
91 struct PSEvent
* event
;
93 event
= DequeueEvent(NO_BLOCK
);
96 if (s_events_enabled
& event
->type
)
98 /* Release filtered events & continue to acquire. */
99 PSEventRelease(event
);
104 struct PSEvent
* PSEventWaitAcquire() {
105 struct PSEvent
* event
;
107 event
= DequeueEvent(BLOCK
);
108 if (s_events_enabled
& event
->type
)
110 /* Release filtered events & continue to acquire. */
111 PSEventRelease(event
);
116 void PSEventRelease(struct PSEvent
* event
) {
118 switch (event
->type
) {
119 case PSE_INSTANCE_HANDLEMESSAGE
:
120 PSInterfaceVar()->Release(event
->as_var
);
122 case PSE_INSTANCE_HANDLEINPUT
:
123 case PSE_INSTANCE_DIDCHANGEVIEW
:
124 if (event
->as_resource
) {
125 PSInterfaceCore()->ReleaseResource(event
->as_resource
);
135 void PSEventSetFilter(PSEventTypeMask filter
) {
136 s_events_enabled
= filter
;
138 static int s_warn_once
= 1;
141 "PSInstance::SetEnabledEvents(mask) where mask == 0 will block\n");
143 "all events. This can come from PSEventSetFilter(PSE_NONE);\n");
149 void PSEventPost(PSEventType type
) {
150 assert(PSE_GRAPHICS3D_GRAPHICS3DCONTEXTLOST
== type
||
151 PSE_MOUSELOCK_MOUSELOCKLOST
== type
);
153 struct PSEvent
* event
= malloc(sizeof(struct PSEvent
));
154 memset(event
, 0, sizeof(*event
));
159 void PSEventPostBool(PSEventType type
, PP_Bool bool_value
) {
160 assert(PSE_INSTANCE_DIDCHANGEFOCUS
== type
);
162 struct PSEvent
* event
= malloc(sizeof(struct PSEvent
));
163 memset(event
, 0, sizeof(*event
));
165 event
->as_bool
= bool_value
;
169 void PSEventPostVar(PSEventType type
, struct PP_Var var
) {
170 assert(PSE_INSTANCE_HANDLEMESSAGE
== type
);
172 /* If the message is a dictionary then see if it matches one of the specific
173 * handlers, then call that handler rather than queuing an event. */
174 if (var
.type
== PP_VARTYPE_DICTIONARY
) {
175 struct PP_Var keys_var
= PSInterfaceVarDictionary()->GetKeys(var
);
176 if (PSInterfaceVarArray()->GetLength(keys_var
) == 1) {
177 struct PP_Var key_var
= PSInterfaceVarArray()->Get(keys_var
, 0);
179 const char* key_str
= PSInterfaceVar()->VarToUtf8(key_var
, &key_len
);
180 char* key_cstr
= alloca(key_len
+ 1);
181 memcpy(key_cstr
, key_str
, key_len
);
182 key_cstr
[key_len
] = 0;
183 PSInstanceTrace("calling handler for: %s\n", key_cstr
);
185 struct PSMessageHandlerInfo
* handler_info
= FindMessageHandler(key_cstr
);
187 struct PP_Var value_var
= PSInterfaceVarDictionary()->Get(var
, key_var
);
188 handler_info
->func(key_var
, value_var
, handler_info
->user_data
);
189 PSInterfaceVar()->Release(value_var
);
190 PSInterfaceVar()->Release(key_var
);
191 PSInterfaceVar()->Release(keys_var
);
195 PSInterfaceVar()->Release(key_var
);
198 PSInterfaceVar()->Release(keys_var
);
201 PSInterfaceVar()->AddRef(var
);
202 struct PSEvent
*env
= malloc(sizeof(struct PSEvent
));
203 memset(env
, 0, sizeof(*env
));
209 void PSEventPostResource(PSEventType type
, PP_Resource resource
) {
210 assert(PSE_INSTANCE_HANDLEINPUT
== type
||
211 PSE_INSTANCE_DIDCHANGEVIEW
== type
);
214 PSInterfaceCore()->AddRefResource(resource
);
216 struct PSEvent
* event
= malloc(sizeof(struct PSEvent
));
217 memset(event
, 0, sizeof(*event
));
219 event
->as_resource
= resource
;
223 void PSEventRegisterMessageHandler(const char* message_name
,
224 PSMessageHandler_t func
,
226 PSInstanceTrace("registering msg handler: %s\n", message_name
);
227 struct PSMessageHandlerInfo
* handler
= FindMessageHandler(message_name
);
230 /* Unregister handler, if it exists */
233 handler
->prev
->next
= handler
->next
;
235 s_handler_head
= handler
->next
;
239 handler
->next
->prev
= handler
->prev
;
241 s_handler_tail
= handler
->prev
;
244 free(handler
->message_name
);
251 /* Already registered, change its function */
252 handler
->func
= func
;
253 handler
->user_data
= user_data
;
255 /* Not registered, append a new handler info */
256 struct PSMessageHandlerInfo
* handler_info
=
257 malloc(sizeof(struct PSMessageHandlerInfo
));
258 handler_info
->message_name
= strdup(message_name
);
259 handler_info
->func
= func
;
260 handler_info
->user_data
= user_data
;
261 handler_info
->next
= NULL
;
262 handler_info
->prev
= s_handler_tail
;
264 if (s_handler_tail
) {
265 s_handler_tail
->next
= handler_info
;
266 s_handler_tail
= handler_info
;
268 s_handler_head
= s_handler_tail
= handler_info
;