Bool gf_dom_event_fire_ex(GF_Node *node, GF_DOM_Event *event, GF_List *use_stack)
{
	GF_SceneGraph *sg;
	GF_List *prev_use_stack;
	Bool prev_bub;
	GF_DOMEventTarget cur_target;
	u32 cur_par_idx;
	Bool can_bubble = GF_FALSE;
	if (!node || !event) return GF_FALSE;
	GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[DOM Events    ] Graph %p Time %f - Firing event  %s.%s\n", gf_node_get_graph(node), gf_node_get_scene_time(node), gf_node_get_log_name(node), gf_dom_event_get_name(event->type)));

	/*flush any pending add_listener
	see "determine the current target's candidate event listeners" in http://www.w3.org/TR/DOM-Level-3-Events/events.html */
	gf_dom_listener_process_add(node->sgprivate->scenegraph);

	event->consumed = 0;
	event->target = node;
	event->target_type = GF_DOM_EVENT_TARGET_NODE;
	if (node->sgprivate->interact && node->sgprivate->interact->dom_evt) {
		event->currentTarget = node->sgprivate->interact->dom_evt;
	} else {
		cur_target.ptr_type = GF_DOM_EVENT_TARGET_NODE;
		cur_target.ptr = node;
		cur_target.listeners = NULL;
		event->currentTarget = &cur_target;
	}

	/*capture phase - not 100% sure, the actual capture phase should be determined by the std using the DOM events
	SVGT doesn't use this phase, so we don't add it for now.*/
#if 0
	if ((0)) {
		Bool aborted = GF_FALSE;
		u32 i, count;
		GF_List *parents;
		event->event_phase = GF_DOM_EVENT_PHASE_CAPTURE;
		parents = gf_list_new();
		/*get all parents to top*/
		gf_sg_dom_stack_parents(gf_node_get_parent(node, 0), parents);
		count = gf_list_count(parents);
		for (i=0; i<count; i++) {
			GF_Node *n = (GF_Node *)gf_list_get(parents, i);
			if (n->sgprivate->interact)
				gf_sg_fire_dom_event(n->sgprivate->interact->dom_evt, event, node->sgprivate->scenegraph, n);

			/*event has been canceled*/
			if (event->event_phase & (GF_DOM_EVENT_PHASE_CANCEL|GF_DOM_EVENT_PHASE_CANCEL_ALL) ) {
				aborted = GF_TRUE;
				break;
			}
		}
		gf_list_del(parents);
		if (aborted) {
			event->currentTarget = NULL;
			return GF_TRUE;
		}
	}
#endif

	/*target phase*/
	event->event_phase = GF_DOM_EVENT_PHASE_AT_TARGET;
	cur_par_idx = 0;
	if (use_stack) {
		cur_par_idx = gf_list_count(use_stack);
		if (cur_par_idx) cur_par_idx--;
	}

	sg = node->sgprivate->scenegraph;

	prev_use_stack = sg->use_stack ;
	prev_bub = sg->abort_bubbling;
	sg->use_stack = use_stack;
	sg->abort_bubbling = GF_FALSE;

	if (node->sgprivate->interact) {
		can_bubble = gf_sg_fire_dom_event(node->sgprivate->interact->dom_evt, event, node->sgprivate->scenegraph, node);
	}
	if ( (!node->sgprivate->interact || can_bubble) && event->bubbles) {
		/*bubbling phase*/
		event->event_phase = GF_DOM_EVENT_PHASE_BUBBLE;
		gf_sg_dom_event_bubble(node, event, use_stack, cur_par_idx);
	}
	sg->use_stack = prev_use_stack;
	sg->abort_bubbling = prev_bub;
	event->currentTarget = NULL;
	return event->consumed ? GF_TRUE : GF_FALSE;
}
Bool gf_dom_event_fire_ex(GF_Node *node, GF_DOM_Event *event, GF_List *use_stack)
{
	GF_SceneGraph *sg;
	GF_List *prev_use_stack;
	Bool prev_bub;
	GF_DOMEventTarget cur_target;
	u32 cur_par_idx;
	Bool can_bubble = GF_FALSE;
	if (!node || !event) return GF_FALSE;
	GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[DOM Events    ] Graph %p Time %f - Firing event  %s.%s\n", gf_node_get_graph(node), gf_node_get_scene_time(node), gf_node_get_log_name(node), gf_dom_event_get_name(event->type)));

	 
	gf_dom_listener_process_add(node->sgprivate->scenegraph);

	event->consumed = 0;
	event->target = node;
	event->target_type = GF_DOM_EVENT_TARGET_NODE;
	if (node->sgprivate->interact && node->sgprivate->interact->dom_evt) {
		event->currentTarget = node->sgprivate->interact->dom_evt;
	} else {
		cur_target.ptr_type = GF_DOM_EVENT_TARGET_NODE;
		cur_target.ptr = node;
		cur_target.listeners = NULL;
		event->currentTarget = &cur_target;
	}

	 
#if 0
	if ((0)) {
		Bool aborted = GF_FALSE;
		u32 i, count;
		GF_List *parents;
		event->event_phase = GF_DOM_EVENT_PHASE_CAPTURE;
		parents = gf_list_new();
		 
		gf_sg_dom_stack_parents(gf_node_get_parent(node, 0), parents);
		count = gf_list_count(parents);
		for (i=0; i<count; i++) {
			GF_Node *n = (GF_Node *)gf_list_get(parents, i);
			if (n->sgprivate->interact)
				gf_sg_fire_dom_event(n->sgprivate->interact->dom_evt, event, node->sgprivate->scenegraph, n);

			 
			if (event->event_phase & (GF_DOM_EVENT_PHASE_CANCEL|GF_DOM_EVENT_PHASE_CANCEL_ALL) ) {
				aborted = GF_TRUE;
				break;
			}
		}
		gf_list_del(parents);
		if (aborted) {
			event->currentTarget = NULL;
			return GF_TRUE;
		}
	}
#endif

	 
	event->event_phase = GF_DOM_EVENT_PHASE_AT_TARGET;
	cur_par_idx = 0;
	if (use_stack) {
		cur_par_idx = gf_list_count(use_stack);
		if (cur_par_idx) cur_par_idx--;
	}

	sg = node->sgprivate->scenegraph;

	prev_use_stack = sg->use_stack ;
	prev_bub = sg->abort_bubbling;
	sg->use_stack = use_stack;
	sg->abort_bubbling = GF_FALSE;

	if (node->sgprivate->interact) {
		can_bubble = gf_sg_fire_dom_event(node->sgprivate->interact->dom_evt, event, node->sgprivate->scenegraph, node);
	}
	if ( (!node->sgprivate->interact || can_bubble) && event->bubbles) {
		 
		event->event_phase = GF_DOM_EVENT_PHASE_BUBBLE;
		gf_sg_dom_event_bubble(node, event, use_stack, cur_par_idx);
	}
	sg->use_stack = prev_use_stack;
	sg->abort_bubbling = prev_bub;
	event->currentTarget = NULL;
	return event->consumed ? GF_TRUE : GF_FALSE;
}