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:
Marcel Hollerbach 2020-01-05 15:05:36 +01:00
parent 40a62ddf94
commit 39f3ce42dc
17 changed files with 1120 additions and 47 deletions

View File

@ -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

View File

@ -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:
@ -2818,7 +2822,7 @@ ecore_evas_shadow_geometry_get(const Ecore_Evas *ee, int *l, int *r, int *t, int
if (b) *b = ee->shadow.b;
}
EAPI void
EAPI void
ecore_evas_pointer_xy_get(const Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y)
{
if (x) *x = 0;
@ -2828,7 +2832,7 @@ ecore_evas_pointer_xy_get(const Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y)
IFE;
}
EAPI Eina_Bool
EAPI Eina_Bool
ecore_evas_pointer_warp(const Ecore_Evas *ee, Evas_Coord x, Evas_Coord y)
{
ECORE_EVAS_CHECK(ee, EINA_FALSE);
@ -2905,7 +2909,7 @@ ecore_evas_pixmap_visual_get(const Ecore_Evas *ee)
return NULL;
}
EAPI unsigned long
EAPI unsigned long
ecore_evas_pixmap_colormap_get(const Ecore_Evas *ee)
{
ECORE_EVAS_CHECK(ee, 0);
@ -2932,7 +2936,7 @@ ecore_evas_pixmap_colormap_get(const Ecore_Evas *ee)
return 0;
}
EAPI int
EAPI int
ecore_evas_pixmap_depth_get(const Ecore_Evas *ee)
{
ECORE_EVAS_CHECK(ee, 0);
@ -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);
}
@ -3542,7 +3549,7 @@ _ecore_evas_idle_timeout_update(Ecore_Evas *ee)
{
if (ee->engine.idle_flush_timer)
ecore_timer_del(ee->engine.idle_flush_timer);
ee->engine.idle_flush_timer =
ee->engine.idle_flush_timer =
ecore_timer_loop_add(IDLE_FLUSH_TIME, _ecore_evas_cb_idle_flush, ee);
}
@ -4007,7 +4014,7 @@ ecore_evas_software_x11_pixmap_new(const char *disp_name, Ecore_X_Window parent,
}
EAPI Ecore_X_Pixmap
EAPI Ecore_X_Pixmap
ecore_evas_software_x11_pixmap_get(const Ecore_Evas *ee)
{
Ecore_Evas_Interface_Software_X11 *iface;
@ -4082,7 +4089,7 @@ ecore_evas_gl_x11_pixmap_new(const char *disp_name, Ecore_X_Window parent, int x
}
EAPI Ecore_X_Pixmap
EAPI Ecore_X_Pixmap
ecore_evas_gl_x11_pixmap_get(const Ecore_Evas *ee)
{
Ecore_Evas_Interface_Gl_X11 *iface;
@ -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;
}

View File

@ -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;
}

View File

@ -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;
@ -259,7 +283,7 @@ struct _Ecore_Evas
Eina_Bool supported; // indicate that the underlying window system supports window manager rotation protocol
Eina_Bool app_set; // indicate that the ee supports window manager rotation protocol
Eina_Bool win_resize; // indicate that the ee will be resized by the WM
int angle; // rotation value which is decided by the WM
int angle; // rotation value which is decided by the WM
int w, h; // window size to rotate
int preferred_rot; // preferred rotation hint
int *available_rots; // array of avaialable rotation values
@ -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);

View File

@ -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'
]

View File

@ -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]

View File

@ -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*

View File

@ -881,14 +881,14 @@ _rotation_do(Ecore_Evas *ee, int rotation, int resize)
{
/* resize the canvas */
evas_output_size_set(ee->evas, ee->req.w, ee->req.h);
evas_output_viewport_set(ee->evas, 0, 0,
evas_output_viewport_set(ee->evas, 0, 0,
ee->req.w, ee->req.h);
}
else
{
/* resize the canvas */
evas_output_size_set(ee->evas, ee->req.h, ee->req.w);
evas_output_viewport_set(ee->evas, 0, 0,
evas_output_viewport_set(ee->evas, 0, 0,
ee->req.h, ee->req.w);
}
}
@ -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

View File

@ -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 */

View File

@ -361,7 +361,7 @@ _ecore_evas_x_aux_hints_supported_update(Ecore_Evas *ee)
for (i = 0; i < num; i++)
{
hint = eina_stringshare_add(str[i]);
ee->prop.aux_hint.supported_list =
ee->prop.aux_hint.supported_list =
eina_list_append(ee->prop.aux_hint.supported_list, hint);
}
@ -414,7 +414,7 @@ _ecore_evas_x_gl_window_new(Ecore_Evas *ee, Ecore_X_Window parent, int x, int y,
op++;
einfo->vsync = opt[op];
}
#ifdef EVAS_ENGINE_GL_X11_SWAP_MODE_EXISTS
#ifdef EVAS_ENGINE_GL_X11_SWAP_MODE_EXISTS
else if (opt[op] == ECORE_EVAS_GL_X11_OPT_SWAP_MODE)
{
op++;
@ -845,7 +845,7 @@ _ecore_evas_x_event_property_change(void *data EINA_UNUSED, int type EINA_UNUSED
Eina_Bool focus_skip : 1;
} prop;
} prev;
prev.x.modal = edata->state.modal;
prev.x.sticky = edata->state.sticky;
prev.x.maximized_v = edata->state.maximized_v;
@ -856,7 +856,7 @@ _ecore_evas_x_event_property_change(void *data EINA_UNUSED, int type EINA_UNUSED
prev.x.fullscreen = edata->state.fullscreen;
prev.x.above = edata->state.above;
prev.x.below = edata->state.below;
prev.prop.modal = ee->prop.modal;
prev.prop.maximized = ee->prop.maximized;
prev.prop.sticky = ee->prop.sticky;
@ -879,7 +879,7 @@ _ecore_evas_x_event_property_change(void *data EINA_UNUSED, int type EINA_UNUSED
ee->prop.sticky = EINA_FALSE;
ee->prop.fullscreen = EINA_FALSE;
// ee->prop.focus_skip = EINA_FALSE;
ecore_x_netwm_window_state_get(e->win, &state, &num);
if (state)
{
@ -1253,7 +1253,7 @@ _ecore_evas_x_event_mouse_in(void *data EINA_UNUSED, int type EINA_UNUSED, void
if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; /* pass on event */
if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
edata = ee->engine.data;
/*
/*
{
time_t t;
char *ct;
@ -1304,7 +1304,7 @@ _ecore_evas_x_event_mouse_in(void *data EINA_UNUSED, int type EINA_UNUSED, void
edata->outdelay = NULL;
_fake_out(ee);
}
/* if (e->mode != ECORE_X_EVENT_MODE_NORMAL) return 0; */
if (!_ecore_evas_mouse_in_check(ee, NULL))
{
@ -1388,7 +1388,7 @@ _ecore_evas_x_event_mouse_out(void *data EINA_UNUSED, int type EINA_UNUSED, void
ecore_timer_del(edata->outdelay);
edata->outdelay = NULL;
}
// if (e->mode != ECORE_X_EVENT_MODE_NORMAL) return 0;
// printf("OUT: ee->in=%i, e->mode=%i, e->detail=%i, dount_count=%i\n",
// ee->in, e->mode, e->detail, evas_event_down_count_get(ee->evas));
@ -1417,7 +1417,7 @@ _ecore_evas_x_event_window_focus_in(void *data EINA_UNUSED, int type EINA_UNUSED
ee = ecore_event_window_match(e->win);
if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; /* pass on event */
if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
//xx// filtering with these doesnt help
//xx// filtering with these doesnt help
//xx// if (e->mode == ECORE_X_EVENT_MODE_UNGRAB) return ECORE_CALLBACK_PASS_ON;
_ecore_evas_focus_device_set(ee, NULL, EINA_TRUE);
return ECORE_CALLBACK_PASS_ON;
@ -1433,7 +1433,7 @@ _ecore_evas_x_event_window_focus_out(void *data EINA_UNUSED, int type EINA_UNUSE
ee = ecore_event_window_match(e->win);
if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; /* pass on event */
if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
//xx// filtering with these doesnt help
//xx// filtering with these doesnt help
//xx// if (e->mode == ECORE_X_EVENT_MODE_GRAB) return ECORE_CALLBACK_PASS_ON;
// if (ee->prop.fullscreen)
@ -2145,7 +2145,7 @@ _ecore_evas_x_resize(Ecore_Evas *ee, int w, int h)
}
/* check for valid property window
*
*
* NB: If we do not have one, check for valid pixmap rendering */
if (!ee->prop.window)
{
@ -2153,7 +2153,7 @@ _ecore_evas_x_resize(Ecore_Evas *ee, int w, int h)
if ((edata->pixmap.w != vw) || (edata->pixmap.h != vh))
{
/* free the backing pixmap */
if (edata->pixmap.back)
if (edata->pixmap.back)
ecore_x_pixmap_free(edata->pixmap.back);
}
}
@ -2918,7 +2918,7 @@ _ecore_evas_x_aspect_set(Ecore_Evas *ee, double aspect)
ee->prop.aspect = aspect;
_ecore_evas_x_size_pos_hints_update(ee);
// netwm state
// netwm state
// if (ee->should_be_visible)
// ecore_x_netwm_state_request_send(ee->prop.window, ee->engine.x.win_root,
// ECORE_X_WINDOW_STATE_STICKY, -1, sticky);
@ -3545,14 +3545,14 @@ norandr:
if (!found) goto norandr;
}
static void
static void
_ecore_evas_x_pointer_xy_get(const Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y)
{
if (ee->prop.window)
ecore_x_pointer_xy_get(ee->prop.window, x, y);
}
static Eina_Bool
static Eina_Bool
_ecore_evas_x_pointer_warp(const Ecore_Evas *ee, Evas_Coord x, Evas_Coord y)
{
return ecore_x_pointer_warp(ee->prop.window, x, y);
@ -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
};
/*
@ -3772,19 +3775,19 @@ _ecore_evas_x_render_pre(void *data, Evas *e EINA_UNUSED, void *event_info EINA_
/* printf("\tPixman Size: %d %d\n", edata->pixmap.w, edata->pixmap.h); */
/* printf("\tEE Size: %d %d\n", ee->w, ee->h); */
/* before rendering to the back buffer pixmap, we should check the
* size. If the back buffer is not the proper size, destroy it and
/* before rendering to the back buffer pixmap, we should check the
* size. If the back buffer is not the proper size, destroy it and
* create a new one at the proper size */
if ((edata->pixmap.w != ee->w) || (edata->pixmap.h != ee->h))
{
int fw = 0, fh = 0;
/* free the backing pixmap */
if (edata->pixmap.back)
if (edata->pixmap.back)
ecore_x_pixmap_free(edata->pixmap.back);
edata->pixmap.back =
ecore_x_pixmap_new(edata->win_root, ee->w, ee->h,
edata->pixmap.back =
ecore_x_pixmap_new(edata->win_root, ee->w, ee->h,
edata->pixmap.depth);
evas_output_framespace_get(ee->evas, NULL, NULL, &fw, &fh);
@ -3803,7 +3806,7 @@ _ecore_evas_x_render_pre(void *data, Evas *e EINA_UNUSED, void *event_info EINA_
if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
{
ERR("evas_engine_info_set() init engine '%s' failed.",
ERR("evas_engine_info_set() init engine '%s' failed.",
ee->driver);
}
}
@ -3821,7 +3824,7 @@ _ecore_evas_x_render_pre(void *data, Evas *e EINA_UNUSED, void *event_info EINA_
if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
{
ERR("evas_engine_info_set() init engine '%s' failed.",
ERR("evas_engine_info_set() init engine '%s' failed.",
ee->driver);
}
}
@ -3844,8 +3847,8 @@ _ecore_evas_x_flush_post(void *data, Evas *e EINA_UNUSED, void *event_info EINA_
/* printf("\tBack Pixmap: %d\n", edata->pixmap.back); */
/* printf("\tFront Pixmap: %d\n", edata->pixmap.front); */
/* done drawing to the back buffer. flip it to the front so that
* any calls to "fetch pixmap" will return the front buffer already
/* done drawing to the back buffer. flip it to the front so that
* any calls to "fetch pixmap" will return the front buffer already
* pre-rendered */
/* record the current front buffer */
@ -3870,7 +3873,7 @@ _ecore_evas_x_flush_post(void *data, Evas *e EINA_UNUSED, void *event_info EINA_
if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
{
ERR("evas_engine_info_set() init engine '%s' failed.",
ERR("evas_engine_info_set() init engine '%s' failed.",
ee->driver);
}
}
@ -3888,7 +3891,7 @@ _ecore_evas_x_flush_post(void *data, Evas *e EINA_UNUSED, void *event_info EINA_
if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
{
ERR("evas_engine_info_set() init engine '%s' failed.",
ERR("evas_engine_info_set() init engine '%s' failed.",
ee->driver);
}
}
@ -4307,9 +4310,9 @@ ecore_evas_software_x11_pixmap_new_internal(const char *disp_name, Ecore_X_Windo
edata->pixmap.colormap = einfo->info.colormap;
/* create front and back pixmaps for double-buffer rendering */
edata->pixmap.front =
edata->pixmap.front =
ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth);
edata->pixmap.back =
edata->pixmap.back =
ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth);
einfo->info.drawable = edata->pixmap.back;
@ -4322,7 +4325,7 @@ ecore_evas_software_x11_pixmap_new_internal(const char *disp_name, Ecore_X_Windo
}
}
/* FIXME: Allow of these set properties or do something with the
/* FIXME: Allow of these set properties or do something with the
* ee->prop.window (x window), which we do not have in pixmap case */
/* _ecore_evas_x_hints_update(ee); */
@ -4370,7 +4373,7 @@ _ecore_evas_software_x11_pixmap_visual_get(const Ecore_Evas *ee)
return edata->pixmap.visual;
}
static unsigned long
static unsigned long
_ecore_evas_software_x11_pixmap_colormap_get(const Ecore_Evas *ee)
{
if (!(!strcmp(ee->driver, "software_x11"))) return 0;
@ -4378,7 +4381,7 @@ _ecore_evas_software_x11_pixmap_colormap_get(const Ecore_Evas *ee)
return edata->pixmap.colormap;
}
static int
static int
_ecore_evas_software_x11_pixmap_depth_get(const Ecore_Evas *ee)
{
if (!(!strcmp(ee->driver, "software_x11"))) return 0;
@ -4719,9 +4722,9 @@ ecore_evas_gl_x11_pixmap_new_internal(const char *disp_name, Ecore_X_Window pare
edata->pixmap.colormap = einfo->info.colormap;
/* create front and back pixmaps for double-buffer rendering */
edata->pixmap.front =
edata->pixmap.front =
ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth);
edata->pixmap.back =
edata->pixmap.back =
ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth);
einfo->info.drawable = edata->pixmap.back;
@ -4779,7 +4782,7 @@ _ecore_evas_gl_x11_pixmap_visual_get(const Ecore_Evas *ee)
return edata->pixmap.visual;
}
static unsigned long
static unsigned long
_ecore_evas_gl_x11_pixmap_colormap_get(const Ecore_Evas *ee)
{
if (!(!strcmp(ee->driver, "opengl_x11"))) return 0;
@ -4787,7 +4790,7 @@ _ecore_evas_gl_x11_pixmap_colormap_get(const Ecore_Evas *ee)
return edata->pixmap.colormap;
}
static int
static int
_ecore_evas_gl_x11_pixmap_depth_get(const Ecore_Evas *ee)
{
if (!(!strcmp(ee->driver, "opengl_x11"))) return 0;

View File

@ -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 }
};

View File

@ -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 */

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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'
]

View File

@ -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()

View File

@ -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
)