ecore_evas: Introduce cnp / dnd API for ecore evas
The idea of copy and paste here is: - The user specifies the content he wants to have in the selection buffer with a Eina_Content, these content pointer ownerships are passed to the called. Internally ecore_evas code will memorieze the pointer, and pass on function callbacks to the modules, which then do not have to deal with the ownership. - In case the module does not specify these APIs, the callback implementation will be called, which only works for cnp *not* dnd. - Action and mime types are handled as strings, which allows way better custom organisations. (The docs needs improvement) Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> Differential Revision: https://phab.enlightenment.org/D11192
This commit is contained in:
parent
40a62ddf94
commit
39f3ce42dc
|
@ -3669,6 +3669,219 @@ EAPI unsigned long ecore_evas_pixmap_colormap_get(const Ecore_Evas *ee);
|
|||
*/
|
||||
EAPI int ecore_evas_pixmap_depth_get(const Ecore_Evas *ee);
|
||||
|
||||
typedef enum {
|
||||
ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER = 0, /**< Stores selected / highlighted selection */
|
||||
ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER = 1, /**< Stores copied things (Ctrl + C) */
|
||||
ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER = 2, /**< Stores dragged things while drag and drop is happening. */
|
||||
ECORE_EVAS_SELECTION_BUFFER_LAST = 3,
|
||||
} Ecore_Evas_Selection_Buffer;
|
||||
|
||||
/**
|
||||
* @brief Callback called when the content of one of the selection buffers changes.
|
||||
*
|
||||
* @param[in] ee The Ecore_Evas that handles this selection.
|
||||
* @param[in] selection The selection buffer that has changed.
|
||||
*/
|
||||
typedef void (*Ecore_Evas_Selection_Changed_Cb)(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection);
|
||||
|
||||
/**
|
||||
* @brief Sets a callback for Ecore_Evas to be called when a selection buffer changes.
|
||||
*
|
||||
* @param[in] ee The Ecore_Evas to set the callback on.
|
||||
* @param[in] cb The function to call.
|
||||
*
|
||||
* A call to this function will set a callback on an Ecore_Evas, causing
|
||||
* @p func to be called whenever @p ee selections change.
|
||||
* Only one such callback can exist for each Ecore_Evas. Calling this method multiple
|
||||
* times overwrites previous functions. Use a NULL @p func to stop being notified.
|
||||
*
|
||||
* You will not be notified about selection changes caused by yourself. (TODO: bu5hm4n?)
|
||||
*
|
||||
* @warning If and when this function is called depends on the underlying
|
||||
* windowing system.
|
||||
*/
|
||||
EAPI void ecore_evas_callback_selection_changed_set(Ecore_Evas *ee, Ecore_Evas_Selection_Changed_Cb cb);
|
||||
|
||||
/**
|
||||
* @brief Sets the content of the specified selection buffer.
|
||||
*
|
||||
* @param[in] ee The Ecore_Evas to set the selection buffer on.
|
||||
* @param[in] buffer The selection buffer to set.
|
||||
* @param[in] content Content to set to the selection buffer. The Eina_Content specifies the MIME type of the data.
|
||||
* Ownership of the content is transferred.
|
||||
*
|
||||
* @note Only ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER and ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER
|
||||
* buffers can be set. Drag and drop operations use a different set of methods.
|
||||
*/
|
||||
EAPI Eina_Bool ecore_evas_selection_set(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer, Eina_Content *content);
|
||||
|
||||
/**
|
||||
* @brief Checks if the specified selection buffer has content.
|
||||
*
|
||||
* @param[in] ee The ecore evas to query
|
||||
* @param[in] buffer Which selection buffer to ask
|
||||
*
|
||||
* @return EINA_TRUE if there is an available selection for the specified buffer.
|
||||
*
|
||||
* EINA_TRUE is also returned when the selection is in the window associated with @p ee
|
||||
*
|
||||
* @note Due to the asynchronous nature of selection buffers, this method might not return
|
||||
* the right result when invoked from the selection callback set with ecore_evas_callback_selection_changed_set.
|
||||
*/
|
||||
EAPI Eina_Bool ecore_evas_selection_exists(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer);
|
||||
|
||||
/**
|
||||
* @brief Retrieves the content of the specified selection buffer.
|
||||
*
|
||||
* @param[in] ee The ecore evas to query.
|
||||
* @param[in] buffer Selection buffer to retrieve.
|
||||
* @param[in] acceptable_types MIME types which are acceptable for the returned Eina_Content.
|
||||
* The iterator contains plain strings (char *). Ownership is transferred for the iterator but not for the strings.
|
||||
* This is convenient for the usual case of a hard-coded array of strings, since the iterator can be generated
|
||||
* on the fly, used and forgotten.
|
||||
*
|
||||
* @return An Eina_Future containing an Eina_Content which has one of the types in @p acceptable_type.
|
||||
* An error is delivered when no matching type is found or when the requested selection buffer is empty.
|
||||
*
|
||||
* This method is time consuming, therefore, it is recommended to verify the existence of a selection
|
||||
* using ecore_evas_selection_exists before calling it.
|
||||
*/
|
||||
EAPI Eina_Future* ecore_evas_selection_get(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer, Eina_Iterator *acceptable_types);
|
||||
|
||||
/**
|
||||
* @brief This method is called when the mouse pointer enters or exits the specified window while
|
||||
* performing a drag operation.
|
||||
*
|
||||
* @param[in] ee The Ecore Evas the drag operation started on.
|
||||
* @param[in] p Position (in window coordinates) where the event occurred.
|
||||
* @param[in] inside @c EINA_TRUE if the pointer just entered this window. @c EINA_FALSE if it has just exited.
|
||||
*
|
||||
* Set this callback using ecore_evas_callback_drop_state_changed_set.
|
||||
*/
|
||||
typedef void (*Ecore_Evas_Drag_Finished)(Ecore_Evas *ee, unsigned int seat, void *data, Eina_Bool accepted);
|
||||
|
||||
/**
|
||||
* @brief Starts a new drag operation.
|
||||
*
|
||||
* @param[in] ee The Ecore Evas the drag operation started on.
|
||||
* @param[in] content The content to delivery at the drop site (ownership is transferred).
|
||||
* The Eina_Content has data and its associated MIME type, plus a list of alternate types that can be provided.
|
||||
* @param[in] drag_rep An Ecore_Evas used as a visual representation of the content being dragged.
|
||||
* It must have the same type as @p ee. This is the transparent object dragged along the mouse pointer to indicate that
|
||||
* a drag operation is in progress.
|
||||
* @p terminate_cb will be called when @p drag_rep is not needed anymore and it must be disposed of.
|
||||
* Use @p data to convey @p drag_rep to @p terminate_cb. For example, if @p drag_rep is owned by an Efl_Window, @p data
|
||||
* can point to that window.
|
||||
* @param[in] action Action the target application should perform upon receiving this content. It is entirely up to the
|
||||
* target application to honor (or even understand) this request.
|
||||
* @return @c EINA_TRUE if the drag operation has been successfully started.
|
||||
*
|
||||
* This method must be called when a drag operation is initiated in order to provide the necessary information.
|
||||
*/
|
||||
EAPI Eina_Bool ecore_evas_drag_start(Ecore_Evas *ee, unsigned int seat, Eina_Content *content, Ecore_Evas *drag_rep, const char* action, Ecore_Evas_Drag_Finished terminate_cb, void *data);
|
||||
|
||||
/**
|
||||
* @brief Cancels an ongoing drag operation.
|
||||
*
|
||||
* @param[in] ee The Ecore Evas the drag operation started on.
|
||||
* @return @c EINA_TRUE if the drag operation has been successfully cancelled.
|
||||
*
|
||||
* The initiator of a drag operation can call this method to abort it.
|
||||
*/
|
||||
EAPI Eina_Bool ecore_evas_drag_cancel(Ecore_Evas *ee, unsigned int seat);
|
||||
|
||||
/**
|
||||
* @brief This method is called when the mouse pointer enters or exits the specified window while
|
||||
* performing a drag operation.
|
||||
*
|
||||
* @param[in] ee The Ecore Evas the drag operation started on.
|
||||
* @param[in] p Position (in window coordinates) where the event occurred.
|
||||
* @param[in] inside @c EINA_TRUE if the pointer just entered this window. @c EINA_FALSE if it has just exited.
|
||||
*
|
||||
* Set this callback using ecore_evas_callback_drop_state_changed_set.
|
||||
*/
|
||||
typedef void (*Ecore_Evas_State_Changed)(Ecore_Evas *ee, unsigned int seat, Eina_Position2D p, Eina_Bool inside);
|
||||
|
||||
/**
|
||||
* @brief Sets the method (callback) to call when the mouse pointer enters or exits the specified window while
|
||||
* performing a drag operation.
|
||||
*
|
||||
* @param[in] ee The Ecore Evas the drag operation started on.
|
||||
* @param[in] cb Method to call when the events are received.
|
||||
*
|
||||
* Only one such callback can exist for each Ecore_Evas. Calling this method multiple
|
||||
* times overwrites previous functions. Use a NULL @cb func to stop being notified.
|
||||
*/
|
||||
EAPI void ecore_evas_callback_drop_state_changed_set(Ecore_Evas *ee, Ecore_Evas_State_Changed cb);
|
||||
|
||||
/**
|
||||
* @brief This method is called when the mouse pointer moves over the specified window while
|
||||
* performing a drag operation.
|
||||
*
|
||||
* @param[in] ee The Ecore Evas the drag operation started on.
|
||||
* @param[in] p Position (in window coordinates) where the event occurred.
|
||||
*
|
||||
* Set this callback using ecore_evas_callback_drop_motion_set.
|
||||
*/
|
||||
|
||||
typedef void (*Ecore_Evas_Motion_Cb)(Ecore_Evas *ee, unsigned int seat, Eina_Position2D p);
|
||||
/**
|
||||
* @brief Sets the method (callback) to call when the mouse pointer moves over the specified window while
|
||||
* performing a drag operation.
|
||||
*
|
||||
* @param[in] ee The Ecore Evas the drag operation started on.
|
||||
* @param[in] cb Method to call when the events are received.
|
||||
*
|
||||
* Only one such callback can exist for each Ecore_Evas. Calling this method multiple
|
||||
* times overwrites previous functions. Use a NULL @cb func to stop being notified.
|
||||
*/
|
||||
EAPI void ecore_evas_callback_drop_motion_set(Ecore_Evas *ee, Ecore_Evas_Motion_Cb cb);
|
||||
|
||||
/**
|
||||
* @brief This method is called when the mouse pointer is released over the specified window while
|
||||
* performing a drag operation (thus dropping the dragged content over the window).
|
||||
*
|
||||
* @param[in] ee The Ecore Evas the drag operation started on.
|
||||
* @param[in] p Position (in window coordinates) where the event occurred.
|
||||
*
|
||||
* The dropped data can be retrieved using ecore_evas_selection_get and the
|
||||
* ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER buffer.
|
||||
*
|
||||
* Set this callback using ecore_evas_callback_drop_drop_set.
|
||||
*/
|
||||
typedef void (*Ecore_Evas_Drop_Cb)(Ecore_Evas *ee, unsigned int seat, Eina_Position2D p, const char *action);
|
||||
|
||||
/**
|
||||
* @brief Sets the method (callback) to call when the mouse pointer is released over the specified window while
|
||||
* performing a drag operation (thus dropping the dragged content over the window).
|
||||
*
|
||||
* @param[in] ee The Ecore Evas the drag operation started on.
|
||||
* @param[in] cb Method to call when the events are received.
|
||||
*
|
||||
* Only one such callback can exist for each Ecore_Evas. Calling this method multiple
|
||||
* times overwrites previous functions. Use a NULL @cb func to stop being notified.
|
||||
*/
|
||||
EAPI void ecore_evas_callback_drop_drop_set(Ecore_Evas *ee, Ecore_Evas_Drop_Cb cb);
|
||||
|
||||
// app calls this (from one of the motion cb's, for example) to know the type (and auto conversion) of the thing being dragged.
|
||||
// This is the same as calling selection_get and retrieving the types from there (but faster).
|
||||
/**
|
||||
* @brief Retrieves the list of types the data currently being dragged can be automatically converted to.
|
||||
*
|
||||
* @param[in] ee The Ecore Evas the drag operation started on.
|
||||
* @return
|
||||
*
|
||||
* This can be used in any of the drag and drop callbacks (Ecore_Evas_State_Changed, Ecore_Evas_Motion_Cb and
|
||||
* Ecore_Evas_Drop_Cb) to check if the data being dragged is acceptable and give the user some early feedback
|
||||
* before the data is actually dropped on the window.
|
||||
*
|
||||
* This is functionally equivalent to calling ecore_evas_selection_get and examining the available types in the
|
||||
* returned Eina_Content, but much faster since the actual data does not have to be asynchronously requested to the
|
||||
* initiator application.
|
||||
*/
|
||||
EAPI Eina_Accessor* ecore_evas_drop_available_types_get(Ecore_Evas *ee, unsigned int seat);
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
@ -3685,3 +3898,4 @@ EAPI int ecore_evas_pixmap_depth_get(const Ecore_Evas *ee);
|
|||
#define EAPI
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -652,6 +652,10 @@ ecore_evas_init(void)
|
|||
iface.del = _ecore_evas_animator_del;
|
||||
ecore_evas_object_animator_init(&iface);
|
||||
|
||||
ecore_evas_no_matching_type = eina_error_msg_register("No fitting type could be found");
|
||||
ecore_evas_no_selection = eina_error_msg_register("No selection available");
|
||||
ecore_evas_request_replaced = eina_error_msg_register("Selection request replaced");
|
||||
|
||||
return _ecore_evas_init_count;
|
||||
|
||||
shutdown_ecore:
|
||||
|
@ -3524,6 +3528,9 @@ _ecore_evas_free(Ecore_Evas *ee)
|
|||
free(iface);
|
||||
|
||||
ee->engine.ifaces = NULL;
|
||||
|
||||
if (ee->fallback_interface)
|
||||
fallback_selection_shutdown(ee);
|
||||
free(ee);
|
||||
}
|
||||
|
||||
|
@ -5449,3 +5456,344 @@ _ecore_evas_animator_thaw(Ecore_Animator *in)
|
|||
EINA_INLIST_GET(animator));
|
||||
_ticking_start(ee);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_evas_callback_selection_changed_set(Ecore_Evas *ee, Ecore_Evas_Selection_Changed_Cb func)
|
||||
{
|
||||
ECORE_EVAS_CHECK(ee);
|
||||
ee->func.fn_selection_changed = func;
|
||||
}
|
||||
|
||||
static Ecore_Evas_Selection_Seat_Buffers*
|
||||
_fetch_selection_buffers_of_seat(Ecore_Evas *ee, unsigned int seat, Eina_Bool create)
|
||||
{
|
||||
Ecore_Evas_Selection_Seat_Buffers *buffers;
|
||||
if (!ee->selection_buffers)
|
||||
ee->selection_buffers = eina_hash_int32_new(free);
|
||||
|
||||
buffers = eina_hash_find(ee->selection_buffers, &seat);
|
||||
|
||||
if (!buffers && create)
|
||||
{
|
||||
buffers = calloc(1, sizeof(Ecore_Evas_Selection_Seat_Buffers));
|
||||
buffers->seat = seat;
|
||||
eina_hash_add(ee->selection_buffers, &seat, buffers);
|
||||
}
|
||||
return buffers;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_deliver_cb(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer, const char *type, Eina_Rw_Slice *slice)
|
||||
{
|
||||
Ecore_Evas_Selection_Seat_Buffers *buffers;
|
||||
Eina_Content *content;
|
||||
Eina_Content *converted = NULL;
|
||||
Eina_Bool result = EINA_FALSE;
|
||||
|
||||
INF("Delivery request on seat %d in buffer %d", seat, buffer);
|
||||
|
||||
buffers = _fetch_selection_buffers_of_seat(ee, seat, EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_GOTO(buffers, free_everything);
|
||||
content = buffers->selection_buffer[buffer];
|
||||
EINA_SAFETY_ON_NULL_GOTO(content, free_everything);
|
||||
if (!eina_streq(type, eina_content_type_get(content)))
|
||||
converted = eina_content_convert(content, type);
|
||||
else
|
||||
converted = content;
|
||||
|
||||
EINA_SAFETY_ON_NULL_GOTO(converted, free_everything);
|
||||
*slice = eina_slice_dup(eina_content_data_get(converted));
|
||||
result = EINA_TRUE;
|
||||
|
||||
if (buffer == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER)
|
||||
{
|
||||
ee->drag.accepted = EINA_TRUE;
|
||||
}
|
||||
|
||||
free_everything:
|
||||
if (converted && content && !eina_streq(type, eina_content_type_get(content)))
|
||||
eina_content_free(converted);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
_cancel_cb(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer)
|
||||
{
|
||||
Ecore_Evas_Selection_Seat_Buffers *buffers;
|
||||
|
||||
INF("Cancel request on seat %d in buffer %d", seat, buffer);
|
||||
|
||||
buffers = _fetch_selection_buffers_of_seat(ee, seat, EINA_FALSE);
|
||||
EINA_SAFETY_ON_FALSE_RETURN(buffers);
|
||||
EINA_SAFETY_ON_FALSE_RETURN(buffers->selection_buffer[buffer]);
|
||||
eina_content_free(buffers->selection_buffer[buffer]);
|
||||
buffers->selection_buffer[buffer] = NULL;
|
||||
|
||||
if (buffer == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER)
|
||||
{
|
||||
ee->drag.rep = NULL;
|
||||
if (ee->drag.free)
|
||||
ee->drag.free(ee, seat, ee->drag.data, EINA_FALSE);
|
||||
ee->drag.free = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define CALL(call) (ee->engine.func->fn_ ##call ? : fallback_ ##call)
|
||||
|
||||
static Eina_Array*
|
||||
_iterator_to_array(Eina_Iterator *iter, const char *existing_type)
|
||||
{
|
||||
Eina_Array *ret = eina_array_new(10);
|
||||
const char *type;
|
||||
|
||||
if (existing_type)
|
||||
eina_array_push(ret, existing_type);
|
||||
|
||||
EINA_ITERATOR_FOREACH(iter, type)
|
||||
{
|
||||
eina_array_push(ret, type);
|
||||
}
|
||||
eina_iterator_free(iter);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_evas_selection_set(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer, Eina_Content *content)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ee, EINA_FALSE);
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(buffer >= 0 && buffer < ECORE_EVAS_SELECTION_BUFFER_LAST, EINA_FALSE);
|
||||
Eina_Iterator *available_type = NULL;
|
||||
Eina_Bool success;
|
||||
Ecore_Evas_Selection_Seat_Buffers *buffers;
|
||||
|
||||
INF("Selection set on seat %d in buffer %d", seat, buffer);
|
||||
|
||||
buffers = _fetch_selection_buffers_of_seat(ee, seat, EINA_TRUE);
|
||||
|
||||
if (content)
|
||||
available_type = eina_content_possible_conversions(content);
|
||||
|
||||
if (buffer == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER)
|
||||
{
|
||||
ERR("You cannot set a selection with this API, please use the API to start a drag operation");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
success = CALL(selection_claim)(ee, seat, buffer, _iterator_to_array(available_type, content ? eina_content_type_get(content) : NULL), content ? _deliver_cb : NULL, content ? _cancel_cb : NULL);
|
||||
if (success)
|
||||
{
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(buffers->selection_buffer[buffer] == NULL, EINA_FALSE);
|
||||
//keep this after the claim, the claim might call cancel, which would overwrite this.
|
||||
buffers->selection_buffer[buffer] = content;
|
||||
}
|
||||
else
|
||||
{
|
||||
eina_content_free(content);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_evas_selection_exists(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ee, EINA_FALSE);
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(buffer >= 0 && buffer < ECORE_EVAS_SELECTION_BUFFER_LAST, EINA_FALSE);
|
||||
Ecore_Evas_Selection_Seat_Buffers *buffers;
|
||||
|
||||
INF("Exists request on seat %d in buffer %d", seat, buffer);
|
||||
|
||||
buffers = _fetch_selection_buffers_of_seat(ee, seat, EINA_TRUE);
|
||||
if (buffers->selection_buffer[buffer])
|
||||
return EINA_TRUE;
|
||||
else
|
||||
{
|
||||
return CALL(selection_has_owner)(ee, seat, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static Eina_Array*
|
||||
_iterator_to_array_stringshared(Eina_Iterator *iter)
|
||||
{
|
||||
Eina_Array *ret = eina_array_new(10);
|
||||
const char *type;
|
||||
|
||||
EINA_ITERATOR_FOREACH(iter, type)
|
||||
{
|
||||
eina_array_push(ret, eina_stringshare_add(type));
|
||||
}
|
||||
eina_iterator_free(iter);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EAPI Eina_Future*
|
||||
ecore_evas_selection_get(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer, Eina_Iterator *acceptable_types)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ee, NULL);
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(buffer >= 0 && buffer < ECORE_EVAS_SELECTION_BUFFER_LAST, NULL);
|
||||
|
||||
INF("Selection get request on seat %d in buffer %d", seat, buffer);
|
||||
|
||||
return CALL(selection_request)(ee, seat, buffer, _iterator_to_array_stringshared(acceptable_types));
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_evas_drag_start(Ecore_Evas *ee, unsigned int seat, Eina_Content *content, Ecore_Evas *drag_rep, const char* action, Ecore_Evas_Drag_Finished terminate_cb, void *data)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ee, EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(content, EINA_FALSE);
|
||||
Eina_Iterator *available_type = eina_content_possible_conversions(content);
|
||||
Eina_Bool success;
|
||||
Ecore_Evas_Selection_Seat_Buffers *buffers;
|
||||
|
||||
INF("Drag start on seat %d", seat);
|
||||
|
||||
buffers = _fetch_selection_buffers_of_seat(ee, seat, EINA_TRUE);
|
||||
success = CALL(dnd_start)(ee, seat, _iterator_to_array(available_type, eina_content_type_get(content)), drag_rep, _deliver_cb, _cancel_cb, action);
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(buffers->selection_buffer[ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER] == NULL, EINA_FALSE);
|
||||
//keep this after the claim, the claim might call cancel, which would overwrite this.
|
||||
buffers->selection_buffer[ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER] = content;
|
||||
|
||||
ee->drag.rep = drag_rep;
|
||||
ee->drag.free = terminate_cb;
|
||||
ee->drag.data = data;
|
||||
ee->drag.accepted = EINA_FALSE;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
ecore_evas_drag_cancel(Ecore_Evas *ee, unsigned int seat)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ee, EINA_FALSE);
|
||||
|
||||
INF("Drag cancel on seat %d", seat);
|
||||
|
||||
return CALL(dnd_stop)(ee, seat);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_evas_callback_drop_motion_set(Ecore_Evas *ee, Ecore_Evas_Motion_Cb cb)
|
||||
{
|
||||
ECORE_EVAS_CHECK(ee);
|
||||
ee->func.fn_dnd_motion = cb;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_evas_callback_drop_state_changed_set(Ecore_Evas *ee, Ecore_Evas_State_Changed cb)
|
||||
{
|
||||
ECORE_EVAS_CHECK(ee);
|
||||
ee->func.fn_dnd_state_change = cb;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_evas_callback_drop_drop_set(Ecore_Evas *ee, Ecore_Evas_Drop_Cb cb)
|
||||
{
|
||||
ECORE_EVAS_CHECK(ee);
|
||||
ee->func.fn_dnd_drop = cb;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
Eina_Array *available_mime_types;
|
||||
Eina_Position2D pos;
|
||||
} Ecore_Evas_Active_Dnd;
|
||||
|
||||
static void
|
||||
_ecore_evas_active_dnd_free(Ecore_Evas_Active_Dnd *dnd)
|
||||
{
|
||||
eina_array_free(dnd->available_mime_types);
|
||||
free(dnd);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_evas_dnd_enter(Ecore_Evas *ee, unsigned int seat, Eina_Iterator *available_types, Eina_Position2D pos)
|
||||
{
|
||||
Eina_Stringshare *s;
|
||||
Ecore_Evas_Active_Dnd *dnd;
|
||||
|
||||
ECORE_EVAS_CHECK(ee);
|
||||
if (!ee->active_drags)
|
||||
{
|
||||
ee->active_drags = eina_hash_int32_new((Eina_Free_Cb)_ecore_evas_active_dnd_free);
|
||||
}
|
||||
|
||||
dnd = calloc(1, sizeof(Ecore_Evas_Active_Dnd));
|
||||
dnd->available_mime_types = eina_array_new(5);
|
||||
eina_hash_add(ee->active_drags, &seat, dnd);
|
||||
|
||||
EINA_ITERATOR_FOREACH(available_types, s)
|
||||
{
|
||||
eina_array_push(dnd->available_mime_types, s);
|
||||
}
|
||||
eina_iterator_free(available_types);
|
||||
|
||||
if (ee->func.fn_dnd_state_change)
|
||||
ee->func.fn_dnd_state_change(ee, seat, pos, EINA_TRUE);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_evas_dnd_position_set(Ecore_Evas *ee, unsigned int seat, Eina_Position2D pos)
|
||||
{
|
||||
Ecore_Evas_Active_Dnd *dnd;
|
||||
|
||||
ECORE_EVAS_CHECK(ee);
|
||||
EINA_SAFETY_ON_NULL_RETURN(ee->active_drags);
|
||||
dnd = eina_hash_find(ee->active_drags, &seat);
|
||||
EINA_SAFETY_ON_NULL_RETURN(dnd);
|
||||
dnd->pos = pos;
|
||||
if (ee->func.fn_dnd_motion)
|
||||
ee->func.fn_dnd_motion(ee, seat, pos);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
ecore_evas_dnd_leave(Ecore_Evas *ee, unsigned int seat, Eina_Position2D pos)
|
||||
{
|
||||
Ecore_Evas_Active_Dnd *dnd;
|
||||
|
||||
ECORE_EVAS_CHECK(ee);
|
||||
EINA_SAFETY_ON_NULL_RETURN(ee->active_drags);
|
||||
dnd = eina_hash_find(ee->active_drags, &seat);
|
||||
EINA_SAFETY_ON_NULL_RETURN(dnd);
|
||||
|
||||
if (ee->func.fn_dnd_state_change)
|
||||
ee->func.fn_dnd_state_change(ee, seat, pos, EINA_FALSE);
|
||||
eina_hash_del(ee->active_drags, &seat, dnd);
|
||||
if (eina_hash_population(ee->active_drags) == 0)
|
||||
{
|
||||
eina_hash_free(ee->active_drags);
|
||||
ee->active_drags = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
EAPI Eina_Position2D
|
||||
ecore_evas_dnd_pos_get(Ecore_Evas *ee, unsigned int seat)
|
||||
{
|
||||
Ecore_Evas_Active_Dnd *dnd;
|
||||
|
||||
ECORE_EVAS_CHECK_GOTO(ee, err);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ee->active_drags, EINA_POSITION2D(0, 0));
|
||||
dnd = eina_hash_find(ee->active_drags, &seat);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(dnd, EINA_POSITION2D(0, 0));
|
||||
|
||||
return dnd->pos;
|
||||
err:
|
||||
return EINA_POSITION2D(0, 0);
|
||||
}
|
||||
|
||||
EAPI Eina_Accessor*
|
||||
ecore_evas_drop_available_types_get(Ecore_Evas *ee, unsigned int seat)
|
||||
{
|
||||
Ecore_Evas_Active_Dnd *dnd;
|
||||
|
||||
ECORE_EVAS_CHECK_GOTO(ee, err);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(ee->active_drags, NULL);
|
||||
dnd = eina_hash_find(ee->active_drags, &seat);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(dnd, NULL);
|
||||
|
||||
return eina_array_accessor_new(dnd->available_mime_types);
|
||||
err:
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <Ecore.h>
|
||||
#include "ecore_private.h"
|
||||
#include "Ecore_Evas.h"
|
||||
#include "ecore_evas_private.h"
|
||||
#include <Efl_Core.h>
|
||||
|
||||
typedef struct {
|
||||
Ecore_Evas_Selection_Callbacks callbacks[ECORE_EVAS_SELECTION_BUFFER_LAST];
|
||||
int seat;
|
||||
} Ecore_Evas_Fallback_Selection_Data;
|
||||
|
||||
static Ecore_Evas_Fallback_Selection_Data data[ECORE_EVAS_SELECTION_BUFFER_LAST];
|
||||
|
||||
void
|
||||
fallback_selection_shutdown(Ecore_Evas *ee)
|
||||
{
|
||||
for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
|
||||
{
|
||||
if (data->callbacks[i].cancel)
|
||||
data->callbacks[i].cancel(ee, data->seat, i);
|
||||
}
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
fallback_selection_claim(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection, Eina_Array *available_types, Ecore_Evas_Internal_Delivery delivery, Ecore_Evas_Internal_Cancel cancel)
|
||||
{
|
||||
Ecore_Evas_Selection_Callbacks *callbacks = &data->callbacks[selection];
|
||||
|
||||
if (callbacks->cancel)
|
||||
{
|
||||
callbacks->cancel(ee, data->seat, selection);
|
||||
eina_array_free(callbacks->available_types);
|
||||
}
|
||||
|
||||
callbacks->delivery = delivery;
|
||||
callbacks->cancel = cancel;
|
||||
callbacks->available_types = available_types;
|
||||
data->seat = seat;
|
||||
|
||||
if (ee->func.fn_selection_changed)
|
||||
ee->func.fn_selection_changed(ee, seat, selection);
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
fallback_selection_has_owner(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection EINA_UNUSED)
|
||||
{
|
||||
return EINA_FALSE; //if the real selection buffer does not contain it, then we dont know it either.
|
||||
}
|
||||
|
||||
Eina_Stringshare*
|
||||
available_types(Eina_Array *acceptable_types, Eina_Array *available_types)
|
||||
{
|
||||
unsigned int found_type_id = INT_MAX;
|
||||
Eina_Stringshare *found_type = NULL;
|
||||
Eina_Stringshare *type;
|
||||
|
||||
for (unsigned int i = 0; i < eina_array_count_get(acceptable_types); ++i)
|
||||
{
|
||||
unsigned int out = -1;
|
||||
|
||||
type = eina_array_data_get(acceptable_types, i);
|
||||
|
||||
if (!eina_array_find(available_types, type, &out))
|
||||
continue;
|
||||
if (out >= found_type_id)
|
||||
continue;
|
||||
found_type_id = out;
|
||||
found_type = type;
|
||||
eina_stringshare_del(type);
|
||||
}
|
||||
eina_array_free(acceptable_types);
|
||||
|
||||
return found_type;
|
||||
}
|
||||
|
||||
Eina_Future*
|
||||
fallback_selection_request(Ecore_Evas *ee EINA_UNUSED, unsigned int seat, Ecore_Evas_Selection_Buffer selection, Eina_Array *acceptable_type)
|
||||
{
|
||||
Ecore_Evas_Selection_Callbacks callbacks = data->callbacks[selection];
|
||||
Eina_Content *result;
|
||||
Eina_Stringshare *serving_type;
|
||||
Eina_Rw_Slice slice_data;
|
||||
Eina_Value value;
|
||||
|
||||
if (!callbacks.delivery)
|
||||
return eina_future_resolved(efl_loop_future_scheduler_get(efl_main_loop_get()), eina_value_int_init(0));
|
||||
|
||||
serving_type = available_types(acceptable_type, callbacks.available_types);
|
||||
if (!serving_type)
|
||||
return NULL; //Silent return cause we cannot deliver a good type
|
||||
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL(callbacks.delivery(ee, seat, selection, serving_type, &slice_data), NULL);
|
||||
result = eina_content_new(eina_rw_slice_slice_get(slice_data), serving_type);
|
||||
value = eina_value_content_init(result);
|
||||
eina_content_free(result);
|
||||
|
||||
return eina_future_resolved(efl_loop_future_scheduler_get(efl_main_loop_get()), value);
|
||||
}
|
||||
Eina_Bool
|
||||
fallback_dnd_start(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, Eina_Array *available_types EINA_UNUSED, Ecore_Evas *drag_rep EINA_UNUSED, Ecore_Evas_Internal_Delivery delivery EINA_UNUSED, Ecore_Evas_Internal_Cancel cancel EINA_UNUSED, const char* action EINA_UNUSED)
|
||||
{
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
fallback_dnd_stop(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED)
|
||||
{
|
||||
return EINA_FALSE;
|
||||
}
|
|
@ -33,6 +33,10 @@
|
|||
|
||||
EAPI extern int _ecore_evas_log_dom;
|
||||
|
||||
EAPI Eina_Error ecore_evas_no_matching_type;
|
||||
EAPI Eina_Error ecore_evas_no_selection;
|
||||
EAPI Eina_Error ecore_evas_request_replaced;
|
||||
|
||||
#ifdef ECORE_EVAS_DEFAULT_LOG_COLOR
|
||||
# undef ECORE_EVAS_DEFAULT_LOG_COLOR
|
||||
#endif
|
||||
|
@ -78,6 +82,13 @@ typedef struct _Ecore_Evas_Interface Ecore_Evas_Interface;
|
|||
typedef struct _Ecore_Evas_Aux_Hint Ecore_Evas_Aux_Hint;
|
||||
typedef struct _Ecore_Evas_Cursor Ecore_Evas_Cursor;
|
||||
|
||||
typedef Eina_Bool (*Ecore_Evas_Internal_Delivery)(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer, const char *type, Eina_Rw_Slice *slice);
|
||||
typedef void (*Ecore_Evas_Internal_Cancel)(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer);
|
||||
typedef struct {
|
||||
Ecore_Evas_Internal_Delivery delivery;
|
||||
Ecore_Evas_Internal_Cancel cancel;
|
||||
Eina_Array *available_types;
|
||||
} Ecore_Evas_Selection_Callbacks;
|
||||
/* Engines interfaces */
|
||||
struct _Ecore_Evas_Engine_Func
|
||||
{
|
||||
|
@ -171,6 +182,12 @@ struct _Ecore_Evas_Engine_Func
|
|||
Eina_Bool (*fn_prepare)(Ecore_Evas *ee);
|
||||
|
||||
double (*fn_last_tick_get)(Ecore_Evas *ee);
|
||||
|
||||
Eina_Bool (*fn_selection_claim)(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection, Eina_Array *available_types, Ecore_Evas_Internal_Delivery delivery, Ecore_Evas_Internal_Cancel cancel);
|
||||
Eina_Bool (*fn_selection_has_owner)(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection);
|
||||
Eina_Future* (*fn_selection_request)(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection, Eina_Array *acceptable_types); // a future containing a Eina_Content, type must be in acceptable_types
|
||||
Eina_Bool (*fn_dnd_start)(Ecore_Evas *ee, unsigned int seat, Eina_Array *available_types, Ecore_Evas *drag_rep, Ecore_Evas_Internal_Delivery delivery, Ecore_Evas_Internal_Cancel cancel, const char *action);
|
||||
Eina_Bool (*fn_dnd_stop)(Ecore_Evas *ee, unsigned int seat);
|
||||
};
|
||||
|
||||
struct _Ecore_Evas_Interface
|
||||
|
@ -202,6 +219,11 @@ struct _Ecore_Evas_Cursor {
|
|||
int pos_y;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
unsigned int seat;
|
||||
Eina_Content *selection_buffer[ECORE_EVAS_SELECTION_BUFFER_LAST];
|
||||
} Ecore_Evas_Selection_Seat_Buffers;
|
||||
|
||||
struct _Ecore_Evas
|
||||
{
|
||||
EINA_INLIST;
|
||||
|
@ -224,6 +246,8 @@ struct _Ecore_Evas
|
|||
|
||||
Eina_List *vnc_server; /* @since 1.19 */
|
||||
|
||||
Eina_Hash *selection_buffers;
|
||||
|
||||
struct {
|
||||
int x, y, w, h;
|
||||
} req;
|
||||
|
@ -323,6 +347,10 @@ struct _Ecore_Evas
|
|||
void (*fn_focus_device_out) (Ecore_Evas *ee, Efl_Input_Device *seat);
|
||||
void (*fn_device_mouse_in) (Ecore_Evas *ee, Efl_Input_Device *mouse);
|
||||
void (*fn_device_mouse_out) (Ecore_Evas *ee, Efl_Input_Device *mouse);
|
||||
void (*fn_selection_changed) (Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection);
|
||||
void (*fn_dnd_motion) (Ecore_Evas *ee, unsigned int seat, Eina_Position2D p);
|
||||
void (*fn_dnd_state_change) (Ecore_Evas *ee, unsigned int seat, Eina_Position2D p, Eina_Bool inside);
|
||||
void (*fn_dnd_drop)(Ecore_Evas *ee, unsigned int seat, Eina_Position2D p, const char *action);
|
||||
} func;
|
||||
|
||||
Ecore_Evas_Engine engine;
|
||||
|
@ -353,6 +381,14 @@ struct _Ecore_Evas
|
|||
unsigned char rotation_changed : 1;
|
||||
} delayed;
|
||||
|
||||
Eina_Hash *active_drags;
|
||||
struct {
|
||||
Ecore_Evas *rep;
|
||||
void *data;
|
||||
Ecore_Evas_Drag_Finished free;
|
||||
Eina_Bool accepted;
|
||||
} drag;
|
||||
|
||||
int refcount;
|
||||
//#define ECORE_EVAS_ASYNC_RENDER_DEBUG 1 /* TODO: remove me */
|
||||
#ifdef ECORE_EVAS_ASYNC_RENDER_DEBUG
|
||||
|
@ -374,6 +410,7 @@ struct _Ecore_Evas
|
|||
unsigned char first_frame : 1;
|
||||
unsigned char self_del : 1;
|
||||
unsigned char evas_dying : 1;
|
||||
unsigned char fallback_interface : 1;
|
||||
};
|
||||
|
||||
struct _Ecore_Evas_Aux_Hint
|
||||
|
@ -486,6 +523,20 @@ EAPI Eina_Bool ecore_evas_render(Ecore_Evas *ee);
|
|||
EAPI Evas *ecore_evas_evas_new(Ecore_Evas *ee, int w, int h);
|
||||
EAPI void ecore_evas_done(Ecore_Evas *ee, Eina_Bool single_window);
|
||||
|
||||
EAPI void ecore_evas_dnd_position_set(Ecore_Evas *ee, unsigned int seat, Eina_Position2D pos);
|
||||
EAPI void ecore_evas_dnd_leave(Ecore_Evas *ee, unsigned int seat, Eina_Position2D pos);
|
||||
EAPI void ecore_evas_dnd_enter(Ecore_Evas *ee, unsigned int seat, Eina_Iterator *available_types, Eina_Position2D pos);
|
||||
EAPI Eina_Position2D ecore_evas_dnd_pos_get(Ecore_Evas *ee, unsigned int seat);
|
||||
|
||||
|
||||
void fallback_selection_init(Ecore_Evas *ee);
|
||||
void fallback_selection_shutdown(Ecore_Evas *ee);
|
||||
Eina_Bool fallback_selection_claim(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection, Eina_Array *available_types, Ecore_Evas_Internal_Delivery delivery, Ecore_Evas_Internal_Cancel cancel);
|
||||
Eina_Bool fallback_selection_has_owner(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection);
|
||||
Eina_Future* fallback_selection_request(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection, Eina_Array *acceptable_type);
|
||||
Eina_Bool fallback_dnd_start(Ecore_Evas *ee, unsigned int seat, Eina_Array *available_types, Ecore_Evas *drag_rep, Ecore_Evas_Internal_Delivery delivery, Ecore_Evas_Internal_Cancel cancel, const char* action);
|
||||
Eina_Bool fallback_dnd_stop(Ecore_Evas *ee, unsigned int seat);
|
||||
|
||||
#ifdef IPA_YLNO_ESU_LANRETNI_MLE
|
||||
EAPI Ecore_Evas *_wayland_shm_new(const char *disp_name, Ecore_Window parent, int x, int y, int w, int h, Eina_Bool frame);
|
||||
EAPI Ecore_Evas *_wayland_egl_new(const char *disp_name, Ecore_Window parent, int x, int y, int w, int h, Eina_Bool frame, const int *opt);
|
||||
|
|
|
@ -23,7 +23,8 @@ ecore_evas_src = [
|
|||
'ecore_evas_cocoa.h',
|
||||
'ecore_evas_win32.h',
|
||||
'ecore_evas_x11.h',
|
||||
'ecore_evas_util.c'
|
||||
'ecore_evas_util.c',
|
||||
'ecore_evas_fallback_selection.c'
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -947,7 +947,7 @@ elementary_src = [
|
|||
'efl_ui_collection_view.c',
|
||||
'efl_ui_pager.c',
|
||||
'efl_ui_stack.c',
|
||||
'efl_ui_separator.c'
|
||||
'efl_ui_separator.c',
|
||||
]
|
||||
|
||||
elementary_deps = [emile, eo, efl, edje, ethumb, ethumb_client, emotion, ecore_imf, ecore_con, eldbus, efreet, efreet_mime, efreet_trash, eio, atspi, dl, intl]
|
||||
|
|
|
@ -455,6 +455,9 @@ static Ecore_Evas_Engine_Func _ecore_sdl_engine_func =
|
|||
NULL, //fn_pointer_device_xy_get
|
||||
NULL, //fn_prepare
|
||||
NULL, //fn_last_tick_get
|
||||
NULL, //fn_selection_claim
|
||||
NULL, //fn_selection_has_owner
|
||||
NULL, //fn_selection_request
|
||||
};
|
||||
|
||||
static Ecore_Evas*
|
||||
|
|
|
@ -2474,6 +2474,9 @@ static Ecore_Evas_Engine_Func _ecore_wl_engine_func =
|
|||
_ecore_evas_wl_common_pointer_device_xy_get,
|
||||
_ecore_evas_wl_common_prepare,
|
||||
NULL, //fn_last_tick_get
|
||||
NULL, //fn_selection_claim
|
||||
NULL, //fn_selection_has_owner
|
||||
NULL, //fn_selection_request
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
|
@ -1284,6 +1284,9 @@ static Ecore_Evas_Engine_Func _ecore_win32_engine_func =
|
|||
NULL, //fn_pointer_device_xy_get
|
||||
NULL, //fn_prepare
|
||||
NULL, //fn_last_tick_get
|
||||
NULL, //fn_selection_claim
|
||||
NULL, //fn_selection_has_owner
|
||||
NULL, //fn_selection_request
|
||||
};
|
||||
|
||||
#endif /* BUILD_ECORE_EVAS_WIN32 */
|
||||
|
|
|
@ -3754,6 +3754,9 @@ static Ecore_Evas_Engine_Func _ecore_x_engine_func =
|
|||
NULL, //fn_pointer_device_xy_get
|
||||
NULL, //fn_prepare
|
||||
NULL, //fn_last_tick_get
|
||||
NULL, //fn_selection_claim
|
||||
NULL, //fn_selection_has_owner
|
||||
NULL, //fn_selection_request
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -30,6 +30,7 @@ static const Efl_Test_Case etc[] = {
|
|||
{ "Ecore_Job", ecore_test_ecore_job },
|
||||
{ "Ecore_Args", ecore_test_ecore_args },
|
||||
{ "Ecore_Pipe", ecore_test_ecore_pipe },
|
||||
{ "Ecore_Evas_Selection", ecore_test_ecore_evas_selection },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -23,5 +23,6 @@ void ecore_test_ecore_file(TCase *tc);
|
|||
void ecore_test_ecore_job(TCase *tc);
|
||||
void ecore_test_ecore_args(TCase *tc);
|
||||
void ecore_test_ecore_pipe(TCase *tc);
|
||||
void ecore_test_ecore_evas_selection(TCase *tc);
|
||||
|
||||
#endif /* _ECORE_SUITE_H */
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#endif
|
||||
|
||||
#include <Ecore_Evas.h>
|
||||
#include <Efl_Core.h>
|
||||
|
||||
#include "ecore_suite.h"
|
||||
|
||||
|
@ -70,8 +71,51 @@ EFL_START_TEST(ecore_test_ecore_evas_cocoa)
|
|||
}
|
||||
EFL_END_TEST
|
||||
|
||||
static Eina_Value
|
||||
_verify_and_exit(void *data, const Eina_Value value, const Eina_Future *dead_future EINA_UNUSED)
|
||||
{
|
||||
ck_assert_ptr_eq(eina_value_type_get(&value), EINA_VALUE_TYPE_CONTENT);
|
||||
Eina_Content *content = eina_value_to_content(&value);
|
||||
Eina_Content *reference = data;
|
||||
|
||||
ck_assert_int_eq(eina_content_data_get(content).len, eina_content_data_get(reference).len);
|
||||
ck_assert_str_eq(eina_content_data_get(content).mem, eina_content_data_get(reference).mem);
|
||||
ck_assert_str_eq(eina_content_type_get(content), eina_content_type_get(reference));
|
||||
|
||||
efl_loop_quit(efl_main_loop_get(), eina_value_int_init(0));
|
||||
|
||||
return EINA_VALUE_EMPTY;
|
||||
}
|
||||
|
||||
EFL_START_TEST(ecore_test_ecore_evas_fallback_selection)
|
||||
{
|
||||
Ecore_Evas *ee;
|
||||
ecore_evas_init();
|
||||
|
||||
ee = ecore_evas_buffer_new(WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
fail_if(ee == NULL);
|
||||
|
||||
for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
|
||||
{
|
||||
ck_assert_int_eq(ecore_evas_selection_exists(ee, 0, i), EINA_FALSE);
|
||||
}
|
||||
Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL("asdf"), "text/plain");
|
||||
Eina_Content *ref = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL("asdf"), "text/plain");
|
||||
ecore_evas_selection_set(ee, 0, ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER, content);
|
||||
|
||||
const char *types[] = {eina_stringshare_add("text/plain")};
|
||||
|
||||
Eina_Future *f = ecore_evas_selection_get(ee, 0, ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER, EINA_C_ARRAY_ITERATOR_NEW(types));
|
||||
ck_assert_ptr_ne(f, NULL);
|
||||
eina_future_then(f, _verify_and_exit, ref);
|
||||
efl_task_run(efl_main_loop_get());
|
||||
ecore_evas_shutdown();
|
||||
}
|
||||
EFL_END_TEST
|
||||
|
||||
void ecore_test_ecore_evas(TCase *tc)
|
||||
{
|
||||
tcase_add_test(tc, ecore_test_ecore_evas_associate);
|
||||
tcase_add_test(tc, ecore_test_ecore_evas_cocoa);
|
||||
tcase_add_test(tc, ecore_test_ecore_evas_fallback_selection);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <Ecore_Evas.h>
|
||||
#include <Efl_Core.h>
|
||||
|
||||
#include "ecore_suite.h"
|
||||
|
||||
#define WINDOW_HEIGHT 200
|
||||
#define WINDOW_WIDTH 200
|
||||
|
||||
static int log_abort;
|
||||
static int log_abort_level;
|
||||
|
||||
void
|
||||
fail_on_errors_teardown(void)
|
||||
{
|
||||
eina_log_abort_on_critical_set(log_abort);
|
||||
eina_log_abort_on_critical_level_set(log_abort_level);
|
||||
}
|
||||
|
||||
void
|
||||
fail_on_errors_setup(void)
|
||||
{
|
||||
log_abort = eina_log_abort_on_critical_get();
|
||||
log_abort_level = eina_log_abort_on_critical_level_get();
|
||||
eina_log_abort_on_critical_level_set(2);
|
||||
eina_log_abort_on_critical_set(1);
|
||||
}
|
||||
|
||||
static Ecore_Evas *ee;
|
||||
|
||||
void
|
||||
_setup(void)
|
||||
{
|
||||
ecore_evas_init();
|
||||
ee = ecore_evas_buffer_new(50, 50);
|
||||
}
|
||||
|
||||
void
|
||||
_teardown(void)
|
||||
{
|
||||
ecore_evas_free(ee);
|
||||
ecore_evas_shutdown();
|
||||
}
|
||||
|
||||
EFL_START_TEST(ecore_test_selection_get_twice)
|
||||
{
|
||||
//this is just running this and checking that we do not error
|
||||
for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
|
||||
{
|
||||
if (i == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER) continue;
|
||||
const char *types[] = {eina_stringshare_add("text/plain")};
|
||||
ck_assert_ptr_ne(ecore_evas_selection_get(ee, 0, i, EINA_C_ARRAY_ITERATOR_NEW(types)), NULL);
|
||||
}
|
||||
for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
|
||||
{
|
||||
if (i == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER) continue;
|
||||
const char *types[] = {eina_stringshare_add("text/plain")};
|
||||
ck_assert_ptr_ne(ecore_evas_selection_get(ee, 0, i, EINA_C_ARRAY_ITERATOR_NEW(types)), NULL);
|
||||
}
|
||||
}
|
||||
EFL_END_TEST
|
||||
|
||||
EFL_START_TEST(ecore_test_selection_claim_twice)
|
||||
{
|
||||
//this is just running this and checking that we do not error
|
||||
for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
|
||||
{
|
||||
if (i == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER) continue;
|
||||
Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL("asdf"), "text/plain");
|
||||
ck_assert_int_eq(ecore_evas_selection_set(ee, 0, i, content), EINA_TRUE);
|
||||
}
|
||||
for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
|
||||
{
|
||||
if (i == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER) continue;
|
||||
Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL("asdf"), "text/plain");
|
||||
ck_assert_int_eq(ecore_evas_selection_set(ee, 0, i, content), EINA_TRUE);
|
||||
}
|
||||
}
|
||||
EFL_END_TEST
|
||||
void ecore_test_ecore_evas_selection(TCase *tc)
|
||||
{
|
||||
tcase_add_checked_fixture(tc, fail_on_errors_setup, fail_on_errors_teardown);
|
||||
tcase_add_checked_fixture(tc, _setup, _teardown);
|
||||
tcase_add_test(tc, ecore_test_selection_get_twice);
|
||||
tcase_add_test(tc, ecore_test_selection_claim_twice);
|
||||
}
|
|
@ -13,6 +13,7 @@ ecore_suite_src = [
|
|||
'ecore_test_job.c',
|
||||
'ecore_test_args.c',
|
||||
'ecore_test_pipe.c',
|
||||
'ecore_test_ecore_evas_selection.c',
|
||||
'ecore_suite.h'
|
||||
]
|
||||
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
#define EFL_BETA_API_SUPPORT 1
|
||||
|
||||
#include <Efl.h>
|
||||
#include <Efl_Ui.h>
|
||||
#include <Elementary.h>
|
||||
#include "efl_ui_grid_view.eo.h"
|
||||
|
||||
static Ecore_Evas *ee;
|
||||
|
||||
static Eina_Value
|
||||
_deliverty_cb(void *data, const Eina_Value value, const Eina_Future *dead_future EINA_UNUSED)
|
||||
{
|
||||
Ecore_Evas_Selection_Buffer buffer = (intptr_t)data;
|
||||
Eina_Content *content;
|
||||
|
||||
if (eina_value_type_get(&value) != EINA_VALUE_TYPE_CONTENT)
|
||||
{
|
||||
char *error = eina_value_to_string(&value);
|
||||
printf("Value not a content, message: \"%s\"\n", error);
|
||||
return EINA_VALUE_EMPTY;
|
||||
}
|
||||
|
||||
content = eina_value_to_content(&value);
|
||||
printf("Got Content of selection %d with type %s\n", buffer, eina_content_type_get(content));
|
||||
if (!strncmp(eina_content_type_get(content), "text", strlen("text")))
|
||||
{
|
||||
printf("Content: %s\n", (char*)eina_content_data_get(content).mem);
|
||||
}
|
||||
|
||||
return EINA_VALUE_EMPTY;
|
||||
}
|
||||
|
||||
static void
|
||||
_selection_changed(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection)
|
||||
{
|
||||
printf("Selection %d of %p has changed\n", selection, ee);
|
||||
}
|
||||
|
||||
static void
|
||||
_request_selection(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection)
|
||||
{
|
||||
const char *types[] = {eina_stringshare_add("text/plain"), eina_stringshare_add("text/plain;charset=utf-8")};
|
||||
printf("Selection %d of %p has changed\n", selection, ee);
|
||||
Eina_Future *future = ecore_evas_selection_get(ee, 0, selection, EINA_C_ARRAY_ITERATOR_NEW(types));
|
||||
eina_future_then(future, _deliverty_cb, .data = ((void*)(intptr_t)selection));
|
||||
}
|
||||
|
||||
static void
|
||||
_motion_cb(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Eina_Position2D p)
|
||||
{
|
||||
printf("Drag and Drop has moved on the window %p (%d, %d)\n", ee, p.x, p.y);
|
||||
}
|
||||
|
||||
static void
|
||||
_enter_state_change_cb(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Eina_Position2D p, Eina_Bool inside)
|
||||
{
|
||||
if (inside)
|
||||
printf("Drag and Drop has entered the window %p (%d, %d)\n", ee, p.x, p.y);
|
||||
else
|
||||
printf("Drag and Drop has left the window %p (%d, %d)\n", ee, p.x, p.y);
|
||||
}
|
||||
|
||||
static void
|
||||
_drop_cb(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Eina_Position2D p, const char *action EINA_UNUSED)
|
||||
{
|
||||
const char *types[] = {eina_stringshare_add("text/plain")};
|
||||
printf("Drag and Drop has droped on the window %p (%d, %d)\n", ee, p.x, p.y);
|
||||
Eina_Future *f = ecore_evas_selection_get(ee, 0, ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER, EINA_C_ARRAY_ITERATOR_NEW(types));
|
||||
eina_future_then(f, _deliverty_cb, .data = ((void*)(intptr_t)ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER));
|
||||
}
|
||||
|
||||
static void
|
||||
_efl_ui_terminated(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, void *data, Eina_Bool accepted EINA_UNUSED)
|
||||
{
|
||||
efl_del(data);
|
||||
}
|
||||
|
||||
static Eo*
|
||||
_start_dnd(Ecore_Evas *ee)
|
||||
{
|
||||
Ecore_Evas *ee2;
|
||||
Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL("This is sample content"), "text/plain");
|
||||
Efl_Ui_Win *win;
|
||||
Efl_Ui_Button *btn;
|
||||
|
||||
win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get());
|
||||
ee2 = ecore_evas_ecore_evas_get(evas_object_evas_get(win));
|
||||
|
||||
btn = efl_add(EFL_UI_BUTTON_CLASS, win);
|
||||
efl_text_set(btn, "Test");
|
||||
efl_content_set(win, btn);
|
||||
|
||||
evas_object_geometry_set(win, 0, 0, 100, 100);
|
||||
|
||||
ecore_evas_drag_start(ee, 0, content, ee2, "copy", _efl_ui_terminated, win);
|
||||
|
||||
return win;
|
||||
}
|
||||
|
||||
static void
|
||||
_start_op(void *data, const Efl_Event *ev EINA_UNUSED)
|
||||
{
|
||||
_start_dnd(data);
|
||||
}
|
||||
|
||||
static Eina_Value
|
||||
_delete_cb(Eo *obj, void *data EINA_UNUSED, const Eina_Value value EINA_UNUSED)
|
||||
{
|
||||
Ecore_Evas *ee ;
|
||||
ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
|
||||
|
||||
ecore_evas_drag_cancel(ee, 0);
|
||||
|
||||
return EINA_VALUE_EMPTY;
|
||||
}
|
||||
|
||||
static void
|
||||
_start_delayed_del_op(void *data, const Efl_Event *ev EINA_UNUSED)
|
||||
{
|
||||
_start_dnd(data);
|
||||
efl_future_then(ev->object, efl_loop_timeout(efl_main_loop_get(), 2.0), _delete_cb);
|
||||
}
|
||||
|
||||
EAPI_MAIN void
|
||||
efl_main(void *data EINA_UNUSED, const Efl_Event *ev)
|
||||
{
|
||||
Efl_Ui_Textbox *txt, *win, *bx, *btn;
|
||||
Efl_Loop_Arguments *args = ev->info;
|
||||
char *goal;
|
||||
|
||||
win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get());
|
||||
ee = ecore_evas_ecore_evas_get(evas_object_evas_get(win));
|
||||
|
||||
bx = efl_add(EFL_UI_BOX_CLASS, win);
|
||||
|
||||
txt = efl_add(EFL_UI_TEXTBOX_CLASS, win);
|
||||
efl_text_set(txt, "Sample for CNP and DND interaction");
|
||||
efl_pack_end(bx, txt);
|
||||
|
||||
btn = efl_add(EFL_UI_BUTTON_CLASS, win);
|
||||
efl_gfx_hint_weight_set(btn, 1.0, 0.0);
|
||||
efl_event_callback_add(btn, EFL_INPUT_EVENT_PRESSED, _start_op, ee);
|
||||
efl_text_set(btn, "Start DND op");
|
||||
efl_pack_end(bx, btn);
|
||||
|
||||
btn = efl_add(EFL_UI_BUTTON_CLASS, win);
|
||||
efl_gfx_hint_weight_set(btn, 1.0, 0.0);
|
||||
efl_event_callback_add(btn, EFL_INPUT_EVENT_PRESSED, _start_delayed_del_op, ee);
|
||||
efl_text_set(btn, "Start DND op self destroy after 2 sec");
|
||||
efl_pack_end(bx, btn);
|
||||
|
||||
efl_content_set(win, bx);
|
||||
efl_gfx_entity_size_set(win, EINA_SIZE2D(320, 320));
|
||||
|
||||
goal = eina_array_data_get(args->argv, 1);
|
||||
|
||||
if (eina_streq(goal, "--monitor"))
|
||||
{
|
||||
ecore_evas_callback_selection_changed_set(ee, _selection_changed);
|
||||
ecore_evas_callback_drop_drop_set(ee, _drop_cb);
|
||||
ecore_evas_callback_drop_motion_set(ee, _motion_cb);
|
||||
ecore_evas_callback_drop_state_changed_set(ee, _enter_state_change_cb);
|
||||
}
|
||||
else if (eina_streq(goal, "--show-selections"))
|
||||
{
|
||||
ecore_evas_callback_selection_changed_set(ee, _request_selection);
|
||||
}
|
||||
else if (eina_streq(goal, "--set-selection"))
|
||||
{
|
||||
if (eina_array_count(args->argv) < 3)
|
||||
{
|
||||
printf("Error, --set-selection only requires exactly 1 keyword (The selection to set).\n");
|
||||
return;
|
||||
}
|
||||
char *selection = eina_array_data_get(args->argv, 2);
|
||||
Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(selection), "text/plain");
|
||||
ecore_evas_selection_set(ee, 0, ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER, content);
|
||||
}
|
||||
else if (eina_streq(goal, "--show-owner"))
|
||||
{
|
||||
for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
|
||||
{
|
||||
printf("Selection buffer %d : %d\n", i, ecore_evas_selection_exists(ee, 0, i));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error, goal %s not found\n", goal);
|
||||
}
|
||||
}
|
||||
EFL_MAIN()
|
|
@ -187,6 +187,11 @@ efl_ui_compile_test = executable('efl_ui_compile_test',
|
|||
dependencies: [elementary, eio],
|
||||
)
|
||||
|
||||
executable('efl_ui_window_cnp_dnd_slave',
|
||||
'efl_ui_window_cnp_dnd_slave.c',
|
||||
dependencies: [elementary],
|
||||
)
|
||||
|
||||
test('elementary-suite', elementary_suite,
|
||||
env : test_env
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue