2016-11-18 07:00:34 -08:00
# define EFL_INTERNAL_UNSTABLE
# define EFL_INPUT_EVENT_PROTECTED
2013-06-20 03:53:29 -07:00
# include "evas_common_private.h"
2002-12-16 16:00:38 -08:00
# include "evas_private.h"
2018-05-10 02:55:43 -07:00
static int evas_focus_log_domain = - 1 ;
# define F_CRI(...) EINA_LOG_DOM_CRIT(evas_focus_log_domain, __VA_ARGS__)
# define F_ERR(...) EINA_LOG_DOM_ERR(evas_focus_log_domain, __VA_ARGS__)
# define F_WRN(...) EINA_LOG_DOM_WARN(evas_focus_log_domain, __VA_ARGS__)
# define F_INF(...) EINA_LOG_DOM_INFO(evas_focus_log_domain, __VA_ARGS__)
# define F_DBG(...) EINA_LOG_DOM_DBG(evas_focus_log_domain, __VA_ARGS__)
2002-12-16 16:00:38 -08:00
/* private calls */
/* local calls */
/* public calls */
2018-05-10 02:55:43 -07:00
void
evas_focus_init ( void )
{
evas_focus_log_domain = eina_log_domain_register ( " evas-focus " , " red " ) ;
}
void
evas_focus_shutdown ( void )
{
eina_log_domain_unregister ( evas_focus_log_domain ) ;
evas_focus_log_domain = - 1 ;
}
2016-10-19 06:02:18 -07:00
static Eina_Bool
_already_focused ( Eina_List * seats , Efl_Input_Device * seat )
2002-12-16 16:00:38 -08:00
{
2016-10-19 06:02:18 -07:00
Eina_List * l ;
const Efl_Input_Device * s ;
2012-10-08 18:58:41 -07:00
2016-10-19 06:02:18 -07:00
EINA_LIST_FOREACH ( seats , l , s )
{
if ( s = = seat )
return EINA_TRUE ;
}
return EINA_FALSE ;
}
static Efl_Input_Device *
2018-04-17 11:09:44 -07:00
_default_seat_get ( const Eo * evas_obj )
2016-10-19 06:02:18 -07:00
{
Evas_Public_Data * edata ;
2018-04-17 11:09:44 -07:00
Evas * evas = evas_object_evas_get ( ( Evas_Object * ) evas_obj ) ;
2016-10-19 06:02:18 -07:00
edata = efl_data_scope_get ( evas , EVAS_CANVAS_CLASS ) ;
2016-11-12 13:56:24 -08:00
if ( ! edata ) return NULL ;
2016-10-19 06:02:18 -07:00
return edata - > default_seat ;
}
2018-05-10 02:55:43 -07:00
# define DEBUG_TUPLE(v) v, (v ? efl_class_name_get(v) : "(null)")
2016-10-19 06:02:18 -07:00
static void
_evas_focus_set ( Eo * evas_obj , Efl_Input_Device * key , Eina_Bool focus )
{
Evas_Public_Data * edata ;
Evas * evas = evas_object_evas_get ( evas_obj ) ;
2017-07-19 22:22:07 -07:00
EINA_SAFETY_ON_NULL_RETURN ( evas ) ;
2016-10-19 06:02:18 -07:00
edata = efl_data_scope_get ( evas , EVAS_CANVAS_CLASS ) ;
2013-09-02 04:28:23 -07:00
2018-05-10 02:55:43 -07:00
F_DBG ( " Focus moved in %d from (%p,%s) to (%p,%s) " , efl_input_device_seat_id_get ( key ) , DEBUG_TUPLE ( eina_hash_find ( edata - > focused_objects , & key ) ) , DEBUG_TUPLE ( evas_obj ) ) ;
2002-12-16 16:00:38 -08:00
if ( focus )
2018-05-15 06:32:20 -07:00
{
Eo * foc ;
foc = eina_hash_set ( edata - > focused_objects , & key , evas_obj ) ;
if ( foc )
{
F_ERR ( " Element %p was focused while a other object was unfocused, this is not expected! No unfocus event will be sent to it " , foc ) ;
}
}
2016-10-19 06:02:18 -07:00
else
eina_hash_del_by_key ( edata - > focused_objects , & key ) ;
}
static Eo *
_current_focus_get ( Eo * evas_obj , Efl_Input_Device * key )
{
Evas_Public_Data * edata ;
Evas * evas = evas_object_evas_get ( evas_obj ) ;
2017-07-19 22:22:07 -07:00
EINA_SAFETY_ON_NULL_RETURN_VAL ( evas , NULL ) ;
2016-10-19 06:02:18 -07:00
edata = efl_data_scope_get ( evas , EVAS_CANVAS_CLASS ) ;
return eina_hash_find ( edata - > focused_objects , & key ) ;
}
2016-11-18 07:00:34 -08:00
void
_evas_focus_dispatch_event ( Evas_Object_Protected_Data * obj , Efl_Input_Device * seat , Eina_Bool in )
2016-10-19 06:02:18 -07:00
{
2016-11-18 07:00:34 -08:00
Efl_Input_Focus_Data * ev_data ;
Efl_Input_Focus * evt ;
Evas_Callback_Type cb_evas , cb_obj_evas ;
2016-11-18 08:56:20 -08:00
const Efl_Event_Description * efl_object_focus_event ;
2016-11-18 07:00:34 -08:00
2017-07-19 22:22:07 -07:00
EVAS_OBJECT_DATA_VALID_CHECK ( obj ) ;
2019-02-09 10:08:45 -08:00
evt = efl_input_focus_instance_get (
2017-04-12 04:13:59 -07:00
efl_provider_find ( obj - > object , EVAS_CANVAS_CLASS ) ,
( void * * ) & ev_data ) ;
2016-11-18 07:00:34 -08:00
if ( ! evt ) return ;
ev_data - > device = efl_ref ( seat ) ;
2017-09-27 19:27:56 -07:00
efl_wref_add ( obj - > object , & ev_data - > object_wref ) ;
2016-11-18 07:00:34 -08:00
ev_data - > timestamp = time ( NULL ) ;
if ( in )
{
cb_obj_evas = EVAS_CALLBACK_FOCUS_IN ;
cb_evas = EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN ;
2016-11-18 08:56:20 -08:00
efl_object_focus_event = EFL_EVENT_FOCUS_IN ;
2016-11-18 07:00:34 -08:00
}
else
{
cb_obj_evas = EVAS_CALLBACK_FOCUS_OUT ;
cb_evas = EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_OUT ;
2016-11-18 08:56:20 -08:00
efl_object_focus_event = EFL_EVENT_FOCUS_OUT ;
2016-11-18 07:00:34 -08:00
}
2016-10-19 06:02:18 -07:00
2016-11-18 08:56:20 -08:00
evas_object_event_callback_call ( obj - > object , obj ,
cb_obj_evas ,
evt , _evas_object_event_new ( ) ,
efl_object_focus_event ) ;
evas_event_callback_call ( obj - > layer - > evas - > evas , cb_evas , evt ) ;
2018-05-04 13:00:53 -07:00
efl_unref ( evt ) ;
2016-11-18 07:00:34 -08:00
}
static void
_evas_object_unfocus ( Evas_Object_Protected_Data * obj , Efl_Input_Device * seat )
{
2017-02-16 02:34:08 -08:00
int event_id = _evas_event_counter ;
2017-07-19 22:22:07 -07:00
EVAS_OBJECT_DATA_VALID_CHECK ( obj ) ;
2017-06-13 09:36:33 -07:00
EINA_COW_WRITE_BEGIN ( evas_object_events_cow , obj - > events , Evas_Object_Events_Data , events )
events - > focused_by_seats = eina_list_remove ( events - > focused_by_seats , seat ) ;
EINA_COW_WRITE_END ( evas_object_events_cow , obj - > events , events ) ;
2016-11-18 07:00:34 -08:00
_evas_focus_set ( obj - > object , seat , EINA_FALSE ) ;
_evas_focus_dispatch_event ( obj , seat , EINA_FALSE ) ;
2017-02-16 02:34:08 -08:00
_evas_post_event_callback_call ( obj - > layer - > evas - > evas , obj - > layer - > evas , event_id ) ;
2016-10-19 06:02:18 -07:00
}
void
2018-05-29 09:24:53 -07:00
_evas_focus_device_invalidate_cb ( void * data , const Efl_Event * ev )
2016-10-19 06:02:18 -07:00
{
_evas_object_unfocus ( data , ev - > object ) ;
}
EOLIAN Eina_Bool
_efl_canvas_object_seat_focus_del ( Eo * eo_obj ,
Evas_Object_Protected_Data * obj ,
Efl_Input_Device * seat )
{
Eina_List * l ;
2016-11-12 13:56:24 -08:00
Efl_Input_Device * dev ;
2017-06-16 12:03:09 -07:00
Eo * default_seat ;
2016-10-19 06:02:18 -07:00
MAGIC_CHECK ( eo_obj , Evas_Object , MAGIC_OBJ ) ;
return EINA_FALSE ;
MAGIC_CHECK_END ( ) ;
2017-06-16 12:03:09 -07:00
if ( seat ) default_seat = _default_seat_get ( eo_obj ) ;
else default_seat = seat = _default_seat_get ( eo_obj ) ;
2016-10-19 06:02:18 -07:00
2017-06-09 17:16:07 -07:00
if ( ( ! seat ) & & obj - > layer )
{
if ( obj - > layer - > evas - > pending_default_focus_obj = = eo_obj )
obj - > layer - > evas - > pending_default_focus_obj = NULL ;
}
2017-06-13 09:36:33 -07:00
EINA_LIST_FOREACH ( obj - > events - > focused_by_seats , l , dev )
2016-10-19 06:02:18 -07:00
{
if ( dev ! = seat )
continue ;
2017-06-16 12:03:09 -07:00
if ( obj - > interceptors & & obj - > interceptors - > focus_set . func & & obj - > interceptors - > device_focus_set . func )
{
CRI ( " Your object is trying to use both focus_set and device_focus_set intercept! Sad! " ) ;
return EINA_FALSE ;
}
if ( obj - > interceptors & & obj - > interceptors - > focus_set . func & & ( seat = = default_seat ) )
{
if ( _evas_object_intercept_call_evas ( obj , EVAS_OBJECT_INTERCEPT_CB_FOCUS_SET ,
1 , EINA_FALSE ) )
{
return EINA_FALSE ;
}
}
else if ( _evas_object_intercept_call_evas ( obj , EVAS_OBJECT_INTERCEPT_CB_DEVICE_FOCUS_SET ,
1 , EINA_FALSE , seat ) )
2016-10-19 06:02:18 -07:00
{
return EINA_FALSE ;
}
2018-05-29 09:24:53 -07:00
efl_event_callback_del ( dev , EFL_EVENT_INVALIDATE ,
_evas_focus_device_invalidate_cb , obj ) ;
2016-10-19 06:02:18 -07:00
_evas_object_unfocus ( obj , dev ) ;
return EINA_TRUE ;
}
return EINA_FALSE ;
}
EOLIAN Eina_Bool
_efl_canvas_object_seat_focus_add ( Eo * eo_obj ,
Evas_Object_Protected_Data * obj ,
Efl_Input_Device * seat )
{
Eo * current_focus ;
2017-02-16 02:34:08 -08:00
int event_id ;
2017-06-16 12:03:09 -07:00
Eo * default_seat ;
2016-10-19 06:02:18 -07:00
MAGIC_CHECK ( eo_obj , Evas_Object , MAGIC_OBJ ) ;
return EINA_FALSE ;
MAGIC_CHECK_END ( ) ;
2017-02-16 02:34:08 -08:00
event_id = _evas_event_counter ;
2017-06-16 12:03:09 -07:00
if ( seat ) default_seat = _default_seat_get ( eo_obj ) ;
else default_seat = seat = _default_seat_get ( eo_obj ) ;
2016-10-19 06:02:18 -07:00
2017-06-11 22:56:36 -07:00
if ( seat & & ( efl_input_device_type_get ( seat ) ! = EFL_INPUT_DEVICE_TYPE_SEAT ) )
2016-10-19 06:02:18 -07:00
return EINA_FALSE ;
2017-06-09 17:16:07 -07:00
if ( obj - > layer & & ( ! seat ) )
{
obj - > layer - > evas - > pending_default_focus_obj = eo_obj ;
return EINA_TRUE ; //questionable return
}
2016-12-06 08:36:50 -08:00
if ( ! efl_input_seat_event_filter_get ( eo_obj , seat ) )
return EINA_FALSE ;
2017-06-13 09:36:33 -07:00
if ( _already_focused ( obj - > events - > focused_by_seats , seat ) )
2016-10-19 06:02:18 -07:00
goto end ;
2017-06-16 12:03:09 -07:00
if ( obj - > interceptors & & obj - > interceptors - > focus_set . func & & obj - > interceptors - > device_focus_set . func )
{
CRI ( " Your object is trying to use both focus_set and device_focus_set intercept! Sad! " ) ;
return EINA_FALSE ;
}
if ( obj - > interceptors & & obj - > interceptors - > focus_set . func & & ( seat = = default_seat ) )
{
if ( _evas_object_intercept_call_evas ( obj , EVAS_OBJECT_INTERCEPT_CB_FOCUS_SET ,
1 , EINA_TRUE ) )
{
return EINA_FALSE ;
}
}
else if ( _evas_object_intercept_call_evas ( obj , EVAS_OBJECT_INTERCEPT_CB_DEVICE_FOCUS_SET ,
1 , EINA_TRUE , seat ) )
2002-12-16 16:00:38 -08:00
{
2016-10-19 06:02:18 -07:00
return EINA_FALSE ;
}
current_focus = _current_focus_get ( eo_obj , seat ) ;
if ( current_focus )
efl_canvas_object_seat_focus_del ( current_focus , seat ) ;
2016-11-14 10:24:47 -08:00
//In case intercept focus callback focused object we should return.
if ( _current_focus_get ( eo_obj , seat ) ) goto end ;
2018-05-29 09:24:53 -07:00
efl_event_callback_add ( seat , EFL_EVENT_INVALIDATE , _evas_focus_device_invalidate_cb , obj ) ;
2016-10-19 06:02:18 -07:00
2017-06-13 09:36:33 -07:00
EINA_COW_WRITE_BEGIN ( evas_object_events_cow , obj - > events , Evas_Object_Events_Data , events )
events - > focused_by_seats = eina_list_append ( events - > focused_by_seats , seat ) ;
EINA_COW_WRITE_END ( evas_object_events_cow , obj - > events , events ) ;
2016-10-19 06:02:18 -07:00
_evas_focus_set ( eo_obj , seat , EINA_TRUE ) ;
2016-11-12 13:56:24 -08:00
2016-11-18 07:00:34 -08:00
_evas_focus_dispatch_event ( obj , seat , EINA_TRUE ) ;
2013-09-02 04:28:23 -07:00
end :
2017-07-23 03:30:31 -07:00
if ( obj - > layer )
_evas_post_event_callback_call ( obj - > layer - > evas - > evas , obj - > layer - > evas , event_id ) ;
2016-10-19 06:02:18 -07:00
return EINA_TRUE ;
2002-12-16 16:00:38 -08:00
}
2014-03-11 04:51:35 -07:00
EOLIAN Eina_Bool
2018-04-17 11:09:44 -07:00
_efl_canvas_object_seat_focus_check ( const Eo * eo_obj ,
2016-10-19 06:02:18 -07:00
Evas_Object_Protected_Data * obj ,
Efl_Input_Device * seat )
2002-12-16 16:00:38 -08:00
{
2016-10-19 06:02:18 -07:00
Eina_List * l ;
Efl_Input_Device * s ;
MAGIC_CHECK ( eo_obj , Evas_Object , MAGIC_OBJ ) ;
return EINA_FALSE ;
MAGIC_CHECK_END ( ) ;
2016-11-12 13:56:24 -08:00
if ( ! seat ) seat = _default_seat_get ( eo_obj ) ;
2016-10-19 06:02:18 -07:00
2017-06-13 09:36:33 -07:00
EINA_LIST_FOREACH ( obj - > events - > focused_by_seats , l , s )
2016-10-19 06:02:18 -07:00
{
if ( s = = seat )
return EINA_TRUE ;
}
return EINA_FALSE ;
}
EOLIAN void
_efl_canvas_object_key_focus_set ( Eo * eo_obj , Evas_Object_Protected_Data * obj , Eina_Bool focus )
{
MAGIC_CHECK ( eo_obj , Evas_Object , MAGIC_OBJ ) ;
return ;
MAGIC_CHECK_END ( ) ;
2017-09-30 10:29:00 -07:00
if ( _efl_canvas_object_seat_focus_check ( eo_obj , obj , NULL ) = = focus ) return ;
2016-10-19 06:02:18 -07:00
if ( focus )
_efl_canvas_object_seat_focus_add ( eo_obj , obj , NULL ) ;
else
_efl_canvas_object_seat_focus_del ( eo_obj , obj , NULL ) ;
}
EOLIAN Eina_Bool
2018-04-17 11:09:44 -07:00
_efl_canvas_object_seat_focus_get ( const Eo * eo_obj , Evas_Object_Protected_Data * obj )
2016-10-19 06:02:18 -07:00
{
MAGIC_CHECK ( eo_obj , Evas_Object , MAGIC_OBJ ) ;
return EINA_FALSE ;
MAGIC_CHECK_END ( ) ;
2017-06-13 09:36:33 -07:00
return eina_list_count ( obj - > events - > focused_by_seats ) ? EINA_TRUE : EINA_FALSE ;
2016-10-19 06:02:18 -07:00
}
EOLIAN Eina_Bool
2018-04-17 11:09:44 -07:00
_efl_canvas_object_key_focus_get ( const Eo * eo_obj , Evas_Object_Protected_Data * obj )
2016-10-19 06:02:18 -07:00
{
return _efl_canvas_object_seat_focus_check ( eo_obj , obj , NULL ) ;
}
EOLIAN Evas_Object *
2018-04-17 11:09:44 -07:00
_evas_canvas_seat_focus_get ( const Eo * eo_obj EINA_UNUSED , Evas_Public_Data * e ,
2016-10-19 06:02:18 -07:00
Efl_Input_Device * seat )
{
if ( ! seat )
seat = e - > default_seat ;
return eina_hash_find ( e - > focused_objects , & seat ) ;
2002-12-16 16:00:38 -08:00
}
2014-03-11 23:53:00 -07:00
EOLIAN Evas_Object *
2018-04-17 11:09:44 -07:00
_evas_canvas_focus_get ( const Eo * eo_obj EINA_UNUSED , Evas_Public_Data * e )
2002-12-16 16:00:38 -08:00
{
2016-10-19 06:02:18 -07:00
return _evas_canvas_seat_focus_get ( eo_obj , e , NULL ) ;
}