summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Hollerbach <mail@marcel-hollerbach.de>2020-01-05 15:05:36 +0100
committerMarcel Hollerbach <mail@marcel-hollerbach.de>2020-03-04 17:26:29 +0100
commitce070a8fdfc9436e837b18f140f30ddc8a67793e (patch)
treeff8a8b31b95739276ad65401ea311254de78c14b
parentff4cba32c3ec316eb9a748165bc0014906256f81 (diff)
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) Differential Revision: https://phab.enlightenment.org/D11192
-rw-r--r--src/lib/ecore_evas/Ecore_Evas.h214
-rw-r--r--src/lib/ecore_evas/ecore_evas.c362
-rw-r--r--src/lib/ecore_evas/ecore_evas_fallback_selection.c115
-rw-r--r--src/lib/ecore_evas/ecore_evas_private.h53
-rw-r--r--src/lib/ecore_evas/meson.build3
-rw-r--r--src/lib/elementary/meson.build2
-rw-r--r--src/modules/ecore_evas/engines/sdl/ecore_evas_sdl.c3
-rw-r--r--src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c7
-rw-r--r--src/modules/ecore_evas/engines/win32/ecore_evas_win32.c3
-rw-r--r--src/modules/ecore_evas/engines/x/ecore_evas_x.c73
-rw-r--r--src/tests/ecore/ecore_suite.c1
-rw-r--r--src/tests/ecore/ecore_suite.h1
-rw-r--r--src/tests/ecore/ecore_test_ecore_evas.c44
-rw-r--r--src/tests/ecore/ecore_test_ecore_evas_selection.c89
-rw-r--r--src/tests/ecore/meson.build1
-rw-r--r--src/tests/elementary/efl_ui_window_cnp_dnd_slave.c191
-rw-r--r--src/tests/elementary/meson.build5
17 files changed, 1120 insertions, 47 deletions
diff --git a/src/lib/ecore_evas/Ecore_Evas.h b/src/lib/ecore_evas/Ecore_Evas.h
index d59900d788..ddc3622741 100644
--- a/src/lib/ecore_evas/Ecore_Evas.h
+++ b/src/lib/ecore_evas/Ecore_Evas.h
@@ -3669,6 +3669,219 @@ EAPI unsigned long ecore_evas_pixmap_colormap_get(const Ecore_Evas *ee);
3669 */ 3669 */
3670EAPI int ecore_evas_pixmap_depth_get(const Ecore_Evas *ee); 3670EAPI int ecore_evas_pixmap_depth_get(const Ecore_Evas *ee);
3671 3671
3672typedef enum {
3673 ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER = 0, /**< Stores selected / highlighted selection */
3674 ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER = 1, /**< Stores copied things (Ctrl + C) */
3675 ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER = 2, /**< Stores dragged things while drag and drop is happening. */
3676 ECORE_EVAS_SELECTION_BUFFER_LAST = 3,
3677} Ecore_Evas_Selection_Buffer;
3678
3679/**
3680 * @brief Callback called when the content of one of the selection buffers changes.
3681 *
3682 * @param[in] ee The Ecore_Evas that handles this selection.
3683 * @param[in] selection The selection buffer that has changed.
3684 */
3685typedef void (*Ecore_Evas_Selection_Changed_Cb)(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection);
3686
3687/**
3688 * @brief Sets a callback for Ecore_Evas to be called when a selection buffer changes.
3689 *
3690 * @param[in] ee The Ecore_Evas to set the callback on.
3691 * @param[in] cb The function to call.
3692 *
3693 * A call to this function will set a callback on an Ecore_Evas, causing
3694 * @p func to be called whenever @p ee selections change.
3695 * Only one such callback can exist for each Ecore_Evas. Calling this method multiple
3696 * times overwrites previous functions. Use a NULL @p func to stop being notified.
3697 *
3698 * You will not be notified about selection changes caused by yourself. (TODO: bu5hm4n?)
3699 *
3700 * @warning If and when this function is called depends on the underlying
3701 * windowing system.
3702 */
3703EAPI void ecore_evas_callback_selection_changed_set(Ecore_Evas *ee, Ecore_Evas_Selection_Changed_Cb cb);
3704
3705/**
3706 * @brief Sets the content of the specified selection buffer.
3707 *
3708 * @param[in] ee The Ecore_Evas to set the selection buffer on.
3709 * @param[in] buffer The selection buffer to set.
3710 * @param[in] content Content to set to the selection buffer. The Eina_Content specifies the MIME type of the data.
3711 * Ownership of the content is transferred.
3712 *
3713 * @note Only ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER and ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER
3714 * buffers can be set. Drag and drop operations use a different set of methods.
3715 */
3716EAPI Eina_Bool ecore_evas_selection_set(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer, Eina_Content *content);
3717
3718/**
3719 * @brief Checks if the specified selection buffer has content.
3720 *
3721 * @param[in] ee The ecore evas to query
3722 * @param[in] buffer Which selection buffer to ask
3723 *
3724 * @return EINA_TRUE if there is an available selection for the specified buffer.
3725 *
3726 * EINA_TRUE is also returned when the selection is in the window associated with @p ee
3727 *
3728 * @note Due to the asynchronous nature of selection buffers, this method might not return
3729 * the right result when invoked from the selection callback set with ecore_evas_callback_selection_changed_set.
3730 */
3731EAPI Eina_Bool ecore_evas_selection_exists(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer);
3732
3733/**
3734 * @brief Retrieves the content of the specified selection buffer.
3735 *
3736 * @param[in] ee The ecore evas to query.
3737 * @param[in] buffer Selection buffer to retrieve.
3738 * @param[in] acceptable_types MIME types which are acceptable for the returned Eina_Content.
3739 * The iterator contains plain strings (char *). Ownership is transferred for the iterator but not for the strings.
3740 * This is convenient for the usual case of a hard-coded array of strings, since the iterator can be generated
3741 * on the fly, used and forgotten.
3742 *
3743 * @return An Eina_Future containing an Eina_Content which has one of the types in @p acceptable_type.
3744 * An error is delivered when no matching type is found or when the requested selection buffer is empty.
3745 *
3746 * This method is time consuming, therefore, it is recommended to verify the existence of a selection
3747 * using ecore_evas_selection_exists before calling it.
3748 */
3749EAPI Eina_Future* ecore_evas_selection_get(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer, Eina_Iterator *acceptable_types);
3750
3751/**
3752 * @brief This method is called when the mouse pointer enters or exits the specified window while
3753 * performing a drag operation.
3754 *
3755 * @param[in] ee The Ecore Evas the drag operation started on.
3756 * @param[in] p Position (in window coordinates) where the event occurred.
3757 * @param[in] inside @c EINA_TRUE if the pointer just entered this window. @c EINA_FALSE if it has just exited.
3758 *
3759 * Set this callback using ecore_evas_callback_drop_state_changed_set.
3760 */
3761typedef void (*Ecore_Evas_Drag_Finished)(Ecore_Evas *ee, unsigned int seat, void *data, Eina_Bool accepted);
3762
3763/**
3764 * @brief Starts a new drag operation.
3765 *
3766 * @param[in] ee The Ecore Evas the drag operation started on.
3767 * @param[in] content The content to delivery at the drop site (ownership is transferred).
3768 * The Eina_Content has data and its associated MIME type, plus a list of alternate types that can be provided.
3769 * @param[in] drag_rep An Ecore_Evas used as a visual representation of the content being dragged.
3770 * It must have the same type as @p ee. This is the transparent object dragged along the mouse pointer to indicate that
3771 * a drag operation is in progress.
3772 * @p terminate_cb will be called when @p drag_rep is not needed anymore and it must be disposed of.
3773 * 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
3774 * can point to that window.
3775 * @param[in] action Action the target application should perform upon receiving this content. It is entirely up to the
3776 * target application to honor (or even understand) this request.
3777 * @return @c EINA_TRUE if the drag operation has been successfully started.
3778 *
3779 * This method must be called when a drag operation is initiated in order to provide the necessary information.
3780 */
3781EAPI 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);
3782
3783/**
3784 * @brief Cancels an ongoing drag operation.
3785 *
3786 * @param[in] ee The Ecore Evas the drag operation started on.
3787 * @return @c EINA_TRUE if the drag operation has been successfully cancelled.
3788 *
3789 * The initiator of a drag operation can call this method to abort it.
3790 */
3791EAPI Eina_Bool ecore_evas_drag_cancel(Ecore_Evas *ee, unsigned int seat);
3792
3793/**
3794 * @brief This method is called when the mouse pointer enters or exits the specified window while
3795 * performing a drag operation.
3796 *
3797 * @param[in] ee The Ecore Evas the drag operation started on.
3798 * @param[in] p Position (in window coordinates) where the event occurred.
3799 * @param[in] inside @c EINA_TRUE if the pointer just entered this window. @c EINA_FALSE if it has just exited.
3800 *
3801 * Set this callback using ecore_evas_callback_drop_state_changed_set.
3802 */
3803typedef void (*Ecore_Evas_State_Changed)(Ecore_Evas *ee, unsigned int seat, Eina_Position2D p, Eina_Bool inside);
3804
3805/**
3806 * @brief Sets the method (callback) to call when the mouse pointer enters or exits the specified window while
3807 * performing a drag operation.
3808 *
3809 * @param[in] ee The Ecore Evas the drag operation started on.
3810 * @param[in] cb Method to call when the events are received.
3811 *
3812 * Only one such callback can exist for each Ecore_Evas. Calling this method multiple
3813 * times overwrites previous functions. Use a NULL @cb func to stop being notified.
3814 */
3815EAPI void ecore_evas_callback_drop_state_changed_set(Ecore_Evas *ee, Ecore_Evas_State_Changed cb);
3816
3817/**
3818 * @brief This method is called when the mouse pointer moves over the specified window while
3819 * performing a drag operation.
3820 *
3821 * @param[in] ee The Ecore Evas the drag operation started on.
3822 * @param[in] p Position (in window coordinates) where the event occurred.
3823 *
3824 * Set this callback using ecore_evas_callback_drop_motion_set.
3825 */
3826
3827typedef void (*Ecore_Evas_Motion_Cb)(Ecore_Evas *ee, unsigned int seat, Eina_Position2D p);
3828/**
3829 * @brief Sets the method (callback) to call when the mouse pointer moves over the specified window while
3830 * performing a drag operation.
3831 *
3832 * @param[in] ee The Ecore Evas the drag operation started on.
3833 * @param[in] cb Method to call when the events are received.
3834 *
3835 * Only one such callback can exist for each Ecore_Evas. Calling this method multiple
3836 * times overwrites previous functions. Use a NULL @cb func to stop being notified.
3837 */
3838EAPI void ecore_evas_callback_drop_motion_set(Ecore_Evas *ee, Ecore_Evas_Motion_Cb cb);
3839
3840/**
3841 * @brief This method is called when the mouse pointer is released over the specified window while
3842 * performing a drag operation (thus dropping the dragged content over the window).
3843 *
3844 * @param[in] ee The Ecore Evas the drag operation started on.
3845 * @param[in] p Position (in window coordinates) where the event occurred.
3846 *
3847 * The dropped data can be retrieved using ecore_evas_selection_get and the
3848 * ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER buffer.
3849 *
3850 * Set this callback using ecore_evas_callback_drop_drop_set.
3851 */
3852typedef void (*Ecore_Evas_Drop_Cb)(Ecore_Evas *ee, unsigned int seat, Eina_Position2D p, const char *action);
3853
3854/**
3855 * @brief Sets the method (callback) to call when the mouse pointer is released over the specified window while
3856 * performing a drag operation (thus dropping the dragged content over the window).
3857 *
3858 * @param[in] ee The Ecore Evas the drag operation started on.
3859 * @param[in] cb Method to call when the events are received.
3860 *
3861 * Only one such callback can exist for each Ecore_Evas. Calling this method multiple
3862 * times overwrites previous functions. Use a NULL @cb func to stop being notified.
3863 */
3864EAPI void ecore_evas_callback_drop_drop_set(Ecore_Evas *ee, Ecore_Evas_Drop_Cb cb);
3865
3866// app calls this (from one of the motion cb's, for example) to know the type (and auto conversion) of the thing being dragged.
3867// This is the same as calling selection_get and retrieving the types from there (but faster).
3868/**
3869 * @brief Retrieves the list of types the data currently being dragged can be automatically converted to.
3870 *
3871 * @param[in] ee The Ecore Evas the drag operation started on.
3872 * @return
3873 *
3874 * This can be used in any of the drag and drop callbacks (Ecore_Evas_State_Changed, Ecore_Evas_Motion_Cb and
3875 * Ecore_Evas_Drop_Cb) to check if the data being dragged is acceptable and give the user some early feedback
3876 * before the data is actually dropped on the window.
3877 *
3878 * This is functionally equivalent to calling ecore_evas_selection_get and examining the available types in the
3879 * returned Eina_Content, but much faster since the actual data does not have to be asynchronously requested to the
3880 * initiator application.
3881 */
3882EAPI Eina_Accessor* ecore_evas_drop_available_types_get(Ecore_Evas *ee, unsigned int seat);
3883
3884
3672/** 3885/**
3673 * @} 3886 * @}
3674 */ 3887 */
@@ -3685,3 +3898,4 @@ EAPI int ecore_evas_pixmap_depth_get(const Ecore_Evas *ee);
3685#define EAPI 3898#define EAPI
3686 3899
3687#endif 3900#endif
3901
diff --git a/src/lib/ecore_evas/ecore_evas.c b/src/lib/ecore_evas/ecore_evas.c
index d3c26ddb19..a95f7903d8 100644
--- a/src/lib/ecore_evas/ecore_evas.c
+++ b/src/lib/ecore_evas/ecore_evas.c
@@ -652,6 +652,10 @@ ecore_evas_init(void)
652 iface.del = _ecore_evas_animator_del; 652 iface.del = _ecore_evas_animator_del;
653 ecore_evas_object_animator_init(&iface); 653 ecore_evas_object_animator_init(&iface);
654 654
655 ecore_evas_no_matching_type = eina_error_msg_register("No fitting type could be found");
656 ecore_evas_no_selection = eina_error_msg_register("No selection available");
657 ecore_evas_request_replaced = eina_error_msg_register("Selection request replaced");
658
655 return _ecore_evas_init_count; 659 return _ecore_evas_init_count;
656 660
657 shutdown_ecore: 661 shutdown_ecore:
@@ -2818,7 +2822,7 @@ ecore_evas_shadow_geometry_get(const Ecore_Evas *ee, int *l, int *r, int *t, int
2818 if (b) *b = ee->shadow.b; 2822 if (b) *b = ee->shadow.b;
2819} 2823}
2820 2824
2821EAPI void 2825EAPI void
2822ecore_evas_pointer_xy_get(const Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y) 2826ecore_evas_pointer_xy_get(const Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y)
2823{ 2827{
2824 if (x) *x = 0; 2828 if (x) *x = 0;
@@ -2828,7 +2832,7 @@ ecore_evas_pointer_xy_get(const Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y)
2828 IFE; 2832 IFE;
2829} 2833}
2830 2834
2831EAPI Eina_Bool 2835EAPI Eina_Bool
2832ecore_evas_pointer_warp(const Ecore_Evas *ee, Evas_Coord x, Evas_Coord y) 2836ecore_evas_pointer_warp(const Ecore_Evas *ee, Evas_Coord x, Evas_Coord y)
2833{ 2837{
2834 ECORE_EVAS_CHECK(ee, EINA_FALSE); 2838 ECORE_EVAS_CHECK(ee, EINA_FALSE);
@@ -2905,7 +2909,7 @@ ecore_evas_pixmap_visual_get(const Ecore_Evas *ee)
2905 return NULL; 2909 return NULL;
2906} 2910}
2907 2911
2908EAPI unsigned long 2912EAPI unsigned long
2909ecore_evas_pixmap_colormap_get(const Ecore_Evas *ee) 2913ecore_evas_pixmap_colormap_get(const Ecore_Evas *ee)
2910{ 2914{
2911 ECORE_EVAS_CHECK(ee, 0); 2915 ECORE_EVAS_CHECK(ee, 0);
@@ -2932,7 +2936,7 @@ ecore_evas_pixmap_colormap_get(const Ecore_Evas *ee)
2932 return 0; 2936 return 0;
2933} 2937}
2934 2938
2935EAPI int 2939EAPI int
2936ecore_evas_pixmap_depth_get(const Ecore_Evas *ee) 2940ecore_evas_pixmap_depth_get(const Ecore_Evas *ee)
2937{ 2941{
2938 ECORE_EVAS_CHECK(ee, 0); 2942 ECORE_EVAS_CHECK(ee, 0);
@@ -3524,6 +3528,9 @@ _ecore_evas_free(Ecore_Evas *ee)
3524 free(iface); 3528 free(iface);
3525 3529
3526 ee->engine.ifaces = NULL; 3530 ee->engine.ifaces = NULL;
3531
3532 if (ee->fallback_interface)
3533 fallback_selection_shutdown(ee);
3527 free(ee); 3534 free(ee);
3528} 3535}
3529 3536
@@ -3542,7 +3549,7 @@ _ecore_evas_idle_timeout_update(Ecore_Evas *ee)
3542{ 3549{
3543 if (ee->engine.idle_flush_timer) 3550 if (ee->engine.idle_flush_timer)
3544 ecore_timer_del(ee->engine.idle_flush_timer); 3551 ecore_timer_del(ee->engine.idle_flush_timer);
3545 ee->engine.idle_flush_timer = 3552 ee->engine.idle_flush_timer =
3546 ecore_timer_loop_add(IDLE_FLUSH_TIME, _ecore_evas_cb_idle_flush, ee); 3553 ecore_timer_loop_add(IDLE_FLUSH_TIME, _ecore_evas_cb_idle_flush, ee);
3547} 3554}
3548 3555
@@ -4007,7 +4014,7 @@ ecore_evas_software_x11_pixmap_new(const char *disp_name, Ecore_X_Window parent,
4007 4014
4008} 4015}
4009 4016
4010EAPI Ecore_X_Pixmap 4017EAPI Ecore_X_Pixmap
4011ecore_evas_software_x11_pixmap_get(const Ecore_Evas *ee) 4018ecore_evas_software_x11_pixmap_get(const Ecore_Evas *ee)
4012{ 4019{
4013 Ecore_Evas_Interface_Software_X11 *iface; 4020 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
4082 4089
4083} 4090}
4084 4091
4085EAPI Ecore_X_Pixmap 4092EAPI Ecore_X_Pixmap
4086ecore_evas_gl_x11_pixmap_get(const Ecore_Evas *ee) 4093ecore_evas_gl_x11_pixmap_get(const Ecore_Evas *ee)
4087{ 4094{
4088 Ecore_Evas_Interface_Gl_X11 *iface; 4095 Ecore_Evas_Interface_Gl_X11 *iface;
@@ -5449,3 +5456,344 @@ _ecore_evas_animator_thaw(Ecore_Animator *in)
5449 EINA_INLIST_GET(animator)); 5456 EINA_INLIST_GET(animator));
5450 _ticking_start(ee); 5457 _ticking_start(ee);
5451} 5458}
5459
5460EAPI void
5461ecore_evas_callback_selection_changed_set(Ecore_Evas *ee, Ecore_Evas_Selection_Changed_Cb func)
5462{
5463 ECORE_EVAS_CHECK(ee);
5464 ee->func.fn_selection_changed = func;
5465}
5466
5467static Ecore_Evas_Selection_Seat_Buffers*
5468_fetch_selection_buffers_of_seat(Ecore_Evas *ee, unsigned int seat, Eina_Bool create)
5469{
5470 Ecore_Evas_Selection_Seat_Buffers *buffers;
5471 if (!ee->selection_buffers)
5472 ee->selection_buffers = eina_hash_int32_new(free);
5473
5474 buffers = eina_hash_find(ee->selection_buffers, &seat);
5475
5476 if (!buffers && create)
5477 {
5478 buffers = calloc(1, sizeof(Ecore_Evas_Selection_Seat_Buffers));
5479 buffers->seat = seat;
5480 eina_hash_add(ee->selection_buffers, &seat, buffers);
5481 }
5482 return buffers;
5483}
5484
5485static Eina_Bool
5486_deliver_cb(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer, const char *type, Eina_Rw_Slice *slice)
5487{
5488 Ecore_Evas_Selection_Seat_Buffers *buffers;
5489 Eina_Content *content;
5490 Eina_Content *converted = NULL;
5491 Eina_Bool result = EINA_FALSE;
5492
5493 INF("Delivery request on seat %d in buffer %d", seat, buffer);
5494
5495 buffers = _fetch_selection_buffers_of_seat(ee, seat, EINA_FALSE);
5496 EINA_SAFETY_ON_NULL_GOTO(buffers, free_everything);
5497 content = buffers->selection_buffer[buffer];
5498 EINA_SAFETY_ON_NULL_GOTO(content, free_everything);
5499 if (!eina_streq(type, eina_content_type_get(content)))
5500 converted = eina_content_convert(content, type);
5501 else
5502 converted = content;
5503
5504 EINA_SAFETY_ON_NULL_GOTO(converted, free_everything);
5505 *slice = eina_slice_dup(eina_content_data_get(converted));
5506 result = EINA_TRUE;
5507
5508 if (buffer == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER)
5509 {
5510 ee->drag.accepted = EINA_TRUE;
5511 }
5512
5513free_everything:
5514 if (converted && content && !eina_streq(type, eina_content_type_get(content)))
5515 eina_content_free(converted);
5516
5517 return result;
5518}
5519
5520static void
5521_cancel_cb(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer)
5522{
5523 Ecore_Evas_Selection_Seat_Buffers *buffers;
5524
5525 INF("Cancel request on seat %d in buffer %d", seat, buffer);
5526
5527 buffers = _fetch_selection_buffers_of_seat(ee, seat, EINA_FALSE);
5528 EINA_SAFETY_ON_FALSE_RETURN(buffers);
5529 EINA_SAFETY_ON_FALSE_RETURN(buffers->selection_buffer[buffer]);
5530 eina_content_free(buffers->selection_buffer[buffer]);
5531 buffers->selection_buffer[buffer] = NULL;
5532
5533 if (buffer == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER)
5534 {
5535 ee->drag.rep = NULL;
5536 if (ee->drag.free)
5537 ee->drag.free(ee, seat, ee->drag.data, EINA_FALSE);
5538 ee->drag.free = NULL;
5539 }
5540}
5541
5542#define CALL(call) (ee->engine.func->fn_ ##call ? : fallback_ ##call)
5543
5544static Eina_Array*
5545_iterator_to_array(Eina_Iterator *iter, const char *existing_type)
5546{
5547 Eina_Array *ret = eina_array_new(10);
5548 const char *type;
5549
5550 if (existing_type)
5551 eina_array_push(ret, existing_type);
5552
5553 EINA_ITERATOR_FOREACH(iter, type)
5554 {
5555 eina_array_push(ret, type);
5556 }
5557 eina_iterator_free(iter);
5558
5559 return ret;
5560}
5561
5562EAPI Eina_Bool
5563ecore_evas_selection_set(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer, Eina_Content *content)
5564{
5565 EINA_SAFETY_ON_NULL_RETURN_VAL(ee, EINA_FALSE);
5566 EINA_SAFETY_ON_FALSE_RETURN_VAL(buffer >= 0 && buffer < ECORE_EVAS_SELECTION_BUFFER_LAST, EINA_FALSE);
5567 Eina_Iterator *available_type = NULL;
5568 Eina_Bool success;
5569 Ecore_Evas_Selection_Seat_Buffers *buffers;
5570
5571 INF("Selection set on seat %d in buffer %d", seat, buffer);
5572
5573 buffers = _fetch_selection_buffers_of_seat(ee, seat, EINA_TRUE);
5574
5575 if (content)
5576 available_type = eina_content_possible_conversions(content);
5577
5578 if (buffer == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER)
5579 {
5580 ERR("You cannot set a selection with this API, please use the API to start a drag operation");
5581 return EINA_FALSE;
5582 }
5583
5584 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);
5585 if (success)
5586 {
5587 EINA_SAFETY_ON_FALSE_RETURN_VAL(buffers->selection_buffer[buffer] == NULL, EINA_FALSE);
5588 //keep this after the claim, the claim might call cancel, which would overwrite this.
5589 buffers->selection_buffer[buffer] = content;
5590 }
5591 else
5592 {
5593 eina_content_free(content);
5594 }
5595
5596 return success;
5597}
5598
5599EAPI Eina_Bool
5600ecore_evas_selection_exists(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer)
5601{
5602 EINA_SAFETY_ON_NULL_RETURN_VAL(ee, EINA_FALSE);
5603 EINA_SAFETY_ON_FALSE_RETURN_VAL(buffer >= 0 && buffer < ECORE_EVAS_SELECTION_BUFFER_LAST, EINA_FALSE);
5604 Ecore_Evas_Selection_Seat_Buffers *buffers;
5605
5606 INF("Exists request on seat %d in buffer %d", seat, buffer);
5607
5608 buffers = _fetch_selection_buffers_of_seat(ee, seat, EINA_TRUE);
5609 if (buffers->selection_buffer[buffer])
5610 return EINA_TRUE;
5611 else
5612 {
5613 return CALL(selection_has_owner)(ee, seat, buffer);
5614 }
5615}
5616
5617static Eina_Array*
5618_iterator_to_array_stringshared(Eina_Iterator *iter)
5619{
5620 Eina_Array *ret = eina_array_new(10);
5621 const char *type;
5622
5623 EINA_ITERATOR_FOREACH(iter, type)
5624 {
5625 eina_array_push(ret, eina_stringshare_add(type));
5626 }
5627 eina_iterator_free(iter);
5628
5629 return ret;
5630}
5631
5632EAPI Eina_Future*
5633ecore_evas_selection_get(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer, Eina_Iterator *acceptable_types)
5634{
5635 EINA_SAFETY_ON_NULL_RETURN_VAL(ee, NULL);
5636 EINA_SAFETY_ON_FALSE_RETURN_VAL(buffer >= 0 && buffer < ECORE_EVAS_SELECTION_BUFFER_LAST, NULL);
5637
5638 INF("Selection get request on seat %d in buffer %d", seat, buffer);
5639
5640 return CALL(selection_request)(ee, seat, buffer, _iterator_to_array_stringshared(acceptable_types));
5641}
5642
5643EAPI Eina_Bool
5644ecore_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)
5645{
5646 EINA_SAFETY_ON_NULL_RETURN_VAL(ee, EINA_FALSE);
5647 EINA_SAFETY_ON_NULL_RETURN_VAL(content, EINA_FALSE);
5648 Eina_Iterator *available_type = eina_content_possible_conversions(content);
5649 Eina_Bool success;
5650 Ecore_Evas_Selection_Seat_Buffers *buffers;
5651
5652 INF("Drag start on seat %d", seat);
5653
5654 buffers = _fetch_selection_buffers_of_seat(ee, seat, EINA_TRUE);
5655 success = CALL(dnd_start)(ee, seat, _iterator_to_array(available_type, eina_content_type_get(content)), drag_rep, _deliver_cb, _cancel_cb, action);
5656 EINA_SAFETY_ON_FALSE_RETURN_VAL(buffers->selection_buffer[ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER] == NULL, EINA_FALSE);
5657 //keep this after the claim, the claim might call cancel, which would overwrite this.
5658 buffers->selection_buffer[ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER] = content;
5659
5660 ee->drag.rep = drag_rep;
5661 ee->drag.free = terminate_cb;
5662 ee->drag.data = data;
5663 ee->drag.accepted = EINA_FALSE;
5664
5665 return success;
5666}
5667
5668EAPI Eina_Bool
5669ecore_evas_drag_cancel(Ecore_Evas *ee, unsigned int seat)
5670{
5671 EINA_SAFETY_ON_NULL_RETURN_VAL(ee, EINA_FALSE);
5672
5673 INF("Drag cancel on seat %d", seat);
5674
5675 return CALL(dnd_stop)(ee, seat);
5676}
5677
5678EAPI void
5679ecore_evas_callback_drop_motion_set(Ecore_Evas *ee, Ecore_Evas_Motion_Cb cb)
5680{
5681 ECORE_EVAS_CHECK(ee);
5682 ee->func.fn_dnd_motion = cb;
5683}
5684
5685EAPI void
5686ecore_evas_callback_drop_state_changed_set(Ecore_Evas *ee, Ecore_Evas_State_Changed cb)
5687{
5688 ECORE_EVAS_CHECK(ee);
5689 ee->func.fn_dnd_state_change = cb;
5690}
5691
5692EAPI void
5693ecore_evas_callback_drop_drop_set(Ecore_Evas *ee, Ecore_Evas_Drop_Cb cb)
5694{
5695 ECORE_EVAS_CHECK(ee);
5696 ee->func.fn_dnd_drop = cb;
5697}
5698
5699typedef struct {
5700 Eina_Array *available_mime_types;
5701 Eina_Position2D pos;
5702} Ecore_Evas_Active_Dnd;
5703
5704static void
5705_ecore_evas_active_dnd_free(Ecore_Evas_Active_Dnd *dnd)
5706{
5707 eina_array_free(dnd->available_mime_types);
5708 free(dnd);
5709}
5710
5711EAPI void
5712ecore_evas_dnd_enter(Ecore_Evas *ee, unsigned int seat, Eina_Iterator *available_types, Eina_Position2D pos)
5713{
5714 Eina_Stringshare *s;
5715 Ecore_Evas_Active_Dnd *dnd;
5716
5717 ECORE_EVAS_CHECK(ee);
5718 if (!ee->active_drags)
5719 {
5720 ee->active_drags = eina_hash_int32_new((Eina_Free_Cb)_ecore_evas_active_dnd_free);
5721 }
5722
5723 dnd = calloc(1, sizeof(Ecore_Evas_Active_Dnd));
5724 dnd->available_mime_types = eina_array_new(5);
5725 eina_hash_add(ee->active_drags, &seat, dnd);
5726
5727 EINA_ITERATOR_FOREACH(available_types, s)
5728 {
5729 eina_array_push(dnd->available_mime_types, s);
5730 }
5731 eina_iterator_free(available_types);
5732
5733 if (ee->func.fn_dnd_state_change)
5734 ee->func.fn_dnd_state_change(ee, seat, pos, EINA_TRUE);
5735}
5736
5737EAPI void
5738ecore_evas_dnd_position_set(Ecore_Evas *ee, unsigned int seat, Eina_Position2D pos)
5739{
5740 Ecore_Evas_Active_Dnd *dnd;
5741
5742 ECORE_EVAS_CHECK(ee);
5743 EINA_SAFETY_ON_NULL_RETURN(ee->active_drags);
5744 dnd = eina_hash_find(ee->active_drags, &seat);
5745 EINA_SAFETY_ON_NULL_RETURN(dnd);
5746 dnd->pos = pos;
5747 if (ee->func.fn_dnd_motion)
5748 ee->func.fn_dnd_motion(ee, seat, pos);
5749}
5750
5751EAPI void
5752ecore_evas_dnd_leave(Ecore_Evas *ee, unsigned int seat, Eina_Position2D pos)
5753{
5754 Ecore_Evas_Active_Dnd *dnd;
5755
5756 ECORE_EVAS_CHECK(ee);
5757 EINA_SAFETY_ON_NULL_RETURN(ee->active_drags);
5758 dnd = eina_hash_find(ee->active_drags, &seat);
5759 EINA_SAFETY_ON_NULL_RETURN(dnd);
5760
5761 if (ee->func.fn_dnd_state_change)
5762 ee->func.fn_dnd_state_change(ee, seat, pos, EINA_FALSE);
5763 eina_hash_del(ee->active_drags, &seat, dnd);
5764 if (eina_hash_population(ee->active_drags) == 0)
5765 {
5766 eina_hash_free(ee->active_drags);
5767 ee->active_drags = NULL;
5768 }
5769}
5770
5771EAPI Eina_Position2D
5772ecore_evas_dnd_pos_get(Ecore_Evas *ee, unsigned int seat)
5773{
5774 Ecore_Evas_Active_Dnd *dnd;
5775
5776 ECORE_EVAS_CHECK_GOTO(ee, err);
5777 EINA_SAFETY_ON_NULL_RETURN_VAL(ee->active_drags, EINA_POSITION2D(0, 0));
5778 dnd = eina_hash_find(ee->active_drags, &seat);
5779 EINA_SAFETY_ON_NULL_RETURN_VAL(dnd, EINA_POSITION2D(0, 0));
5780
5781 return dnd->pos;
5782err:
5783 return EINA_POSITION2D(0, 0);
5784}
5785
5786EAPI Eina_Accessor*
5787ecore_evas_drop_available_types_get(Ecore_Evas *ee, unsigned int seat)
5788{
5789 Ecore_Evas_Active_Dnd *dnd;
5790
5791 ECORE_EVAS_CHECK_GOTO(ee, err);
5792 EINA_SAFETY_ON_NULL_RETURN_VAL(ee->active_drags, NULL);
5793 dnd = eina_hash_find(ee->active_drags, &seat);
5794 EINA_SAFETY_ON_NULL_RETURN_VAL(dnd, NULL);
5795
5796 return eina_array_accessor_new(dnd->available_mime_types);
5797err:
5798 return NULL;
5799}
diff --git a/src/lib/ecore_evas/ecore_evas_fallback_selection.c b/src/lib/ecore_evas/ecore_evas_fallback_selection.c
new file mode 100644
index 0000000000..1088e617f7
--- /dev/null
+++ b/src/lib/ecore_evas/ecore_evas_fallback_selection.c
@@ -0,0 +1,115 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <Ecore.h>
6#include "ecore_private.h"
7#include "Ecore_Evas.h"
8#include "ecore_evas_private.h"
9#include <Efl_Core.h>
10
11typedef struct {
12 Ecore_Evas_Selection_Callbacks callbacks[ECORE_EVAS_SELECTION_BUFFER_LAST];
13 int seat;
14} Ecore_Evas_Fallback_Selection_Data;
15
16static Ecore_Evas_Fallback_Selection_Data data[ECORE_EVAS_SELECTION_BUFFER_LAST];
17
18void
19fallback_selection_shutdown(Ecore_Evas *ee)
20{
21 for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
22 {
23 if (data->callbacks[i].cancel)
24 data->callbacks[i].cancel(ee, data->seat, i);
25 }
26}
27
28Eina_Bool
29fallback_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)
30{
31 Ecore_Evas_Selection_Callbacks *callbacks = &data->callbacks[selection];
32
33 if (callbacks->cancel)
34 {
35 callbacks->cancel(ee, data->seat, selection);
36 eina_array_free(callbacks->available_types);
37 }
38
39 callbacks->delivery = delivery;
40 callbacks->cancel = cancel;
41 callbacks->available_types = available_types;
42 data->seat = seat;
43
44 if (ee->func.fn_selection_changed)
45 ee->func.fn_selection_changed(ee, seat, selection);
46
47 return EINA_TRUE;
48}
49
50Eina_Bool
51fallback_selection_has_owner(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection EINA_UNUSED)
52{
53 return EINA_FALSE; //if the real selection buffer does not contain it, then we dont know it either.
54}
55
56Eina_Stringshare*
57available_types(Eina_Array *acceptable_types, Eina_Array *available_types)
58{
59 unsigned int found_type_id = INT_MAX;
60 Eina_Stringshare *found_type = NULL;
61 Eina_Stringshare *type;
62
63 for (unsigned int i = 0; i < eina_array_count_get(acceptable_types); ++i)
64 {
65 unsigned int out = -1;
66
67 type = eina_array_data_get(acceptable_types, i);
68
69 if (!eina_array_find(available_types, type, &out))
70 continue;
71 if (out >= found_type_id)
72 continue;
73 found_type_id = out;
74 found_type = type;
75 eina_stringshare_del(type);
76 }
77 eina_array_free(acceptable_types);
78
79 return found_type;
80}
81
82Eina_Future*
83fallback_selection_request(Ecore_Evas *ee EINA_UNUSED, unsigned int seat, Ecore_Evas_Selection_Buffer selection, Eina_Array *acceptable_type)
84{
85 Ecore_Evas_Selection_Callbacks callbacks = data->callbacks[selection];
86 Eina_Content *result;
87 Eina_Stringshare *serving_type;
88 Eina_Rw_Slice slice_data;
89 Eina_Value value;
90
91 if (!callbacks.delivery)
92 return eina_future_resolved(efl_loop_future_scheduler_get(efl_main_loop_get()), eina_value_int_init(0));
93
94 serving_type = available_types(acceptable_type, callbacks.available_types);
95 if (!serving_type)
96 return NULL; //Silent return cause we cannot deliver a good type
97
98 EINA_SAFETY_ON_FALSE_RETURN_VAL(callbacks.delivery(ee, seat, selection, serving_type, &slice_data), NULL);
99 result = eina_content_new(eina_rw_slice_slice_get(slice_data), serving_type);
100 value = eina_value_content_init(result);
101 eina_content_free(result);
102
103 return eina_future_resolved(efl_loop_future_scheduler_get(efl_main_loop_get()), value);
104}
105Eina_Bool
106fallback_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)
107{
108 return EINA_FALSE;
109}
110
111Eina_Bool
112fallback_dnd_stop(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED)
113{
114 return EINA_FALSE;
115}
diff --git a/src/lib/ecore_evas/ecore_evas_private.h b/src/lib/ecore_evas/ecore_evas_private.h
index 474b7a35ed..10191b0152 100644
--- a/src/lib/ecore_evas/ecore_evas_private.h
+++ b/src/lib/ecore_evas/ecore_evas_private.h
@@ -33,6 +33,10 @@
33 33
34EAPI extern int _ecore_evas_log_dom; 34EAPI extern int _ecore_evas_log_dom;
35 35
36EAPI Eina_Error ecore_evas_no_matching_type;
37EAPI Eina_Error ecore_evas_no_selection;
38EAPI Eina_Error ecore_evas_request_replaced;
39
36#ifdef ECORE_EVAS_DEFAULT_LOG_COLOR 40#ifdef ECORE_EVAS_DEFAULT_LOG_COLOR
37# undef ECORE_EVAS_DEFAULT_LOG_COLOR 41# undef ECORE_EVAS_DEFAULT_LOG_COLOR
38#endif 42#endif
@@ -78,6 +82,13 @@ typedef struct _Ecore_Evas_Interface Ecore_Evas_Interface;
78typedef struct _Ecore_Evas_Aux_Hint Ecore_Evas_Aux_Hint; 82typedef struct _Ecore_Evas_Aux_Hint Ecore_Evas_Aux_Hint;
79typedef struct _Ecore_Evas_Cursor Ecore_Evas_Cursor; 83typedef struct _Ecore_Evas_Cursor Ecore_Evas_Cursor;
80 84
85typedef Eina_Bool (*Ecore_Evas_Internal_Delivery)(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer, const char *type, Eina_Rw_Slice *slice);
86typedef void (*Ecore_Evas_Internal_Cancel)(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer);
87typedef struct {
88 Ecore_Evas_Internal_Delivery delivery;
89 Ecore_Evas_Internal_Cancel cancel;
90 Eina_Array *available_types;
91} Ecore_Evas_Selection_Callbacks;
81/* Engines interfaces */ 92/* Engines interfaces */
82struct _Ecore_Evas_Engine_Func 93struct _Ecore_Evas_Engine_Func
83{ 94{
@@ -171,6 +182,12 @@ struct _Ecore_Evas_Engine_Func
171 Eina_Bool (*fn_prepare)(Ecore_Evas *ee); 182 Eina_Bool (*fn_prepare)(Ecore_Evas *ee);
172 183
173 double (*fn_last_tick_get)(Ecore_Evas *ee); 184 double (*fn_last_tick_get)(Ecore_Evas *ee);
185
186 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);
187 Eina_Bool (*fn_selection_has_owner)(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection);
188 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
189 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);
190 Eina_Bool (*fn_dnd_stop)(Ecore_Evas *ee, unsigned int seat);
174}; 191};
175 192
176struct _Ecore_Evas_Interface 193struct _Ecore_Evas_Interface
@@ -202,6 +219,11 @@ struct _Ecore_Evas_Cursor {
202 int pos_y; 219 int pos_y;
203}; 220};
204 221
222typedef struct {
223 unsigned int seat;
224 Eina_Content *selection_buffer[ECORE_EVAS_SELECTION_BUFFER_LAST];
225} Ecore_Evas_Selection_Seat_Buffers;
226
205struct _Ecore_Evas 227struct _Ecore_Evas
206{ 228{
207 EINA_INLIST; 229 EINA_INLIST;
@@ -224,6 +246,8 @@ struct _Ecore_Evas
224 246
225 Eina_List *vnc_server; /* @since 1.19 */ 247 Eina_List *vnc_server; /* @since 1.19 */
226 248
249 Eina_Hash *selection_buffers;
250
227 struct { 251 struct {
228 int x, y, w, h; 252 int x, y, w, h;
229 } req; 253 } req;
@@ -259,7 +283,7 @@ struct _Ecore_Evas
259 Eina_Bool supported; // indicate that the underlying window system supports window manager rotation protocol 283 Eina_Bool supported; // indicate that the underlying window system supports window manager rotation protocol
260 Eina_Bool app_set; // indicate that the ee supports window manager rotation protocol 284 Eina_Bool app_set; // indicate that the ee supports window manager rotation protocol
261 Eina_Bool win_resize; // indicate that the ee will be resized by the WM 285 Eina_Bool win_resize; // indicate that the ee will be resized by the WM
262 int angle; // rotation value which is decided by the WM 286 int angle; // rotation value which is decided by the WM
263 int w, h; // window size to rotate 287 int w, h; // window size to rotate
264 int preferred_rot; // preferred rotation hint 288 int preferred_rot; // preferred rotation hint
265 int *available_rots; // array of avaialable rotation values 289 int *available_rots; // array of avaialable rotation values
@@ -323,6 +347,10 @@ struct _Ecore_Evas
323 void (*fn_focus_device_out) (Ecore_Evas *ee, Efl_Input_Device *seat); 347 void (*fn_focus_device_out) (Ecore_Evas *ee, Efl_Input_Device *seat);
324 void (*fn_device_mouse_in) (Ecore_Evas *ee, Efl_Input_Device *mouse); 348 void (*fn_device_mouse_in) (Ecore_Evas *ee, Efl_Input_Device *mouse);
325 void (*fn_device_mouse_out) (Ecore_Evas *ee, Efl_Input_Device *mouse); 349 void (*fn_device_mouse_out) (Ecore_Evas *ee, Efl_Input_Device *mouse);
350 void (*fn_selection_changed) (Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection);
351 void (*fn_dnd_motion) (Ecore_Evas *ee, unsigned int seat, Eina_Position2D p);
352 void (*fn_dnd_state_change) (Ecore_Evas *ee, unsigned int seat, Eina_Position2D p, Eina_Bool inside);
353 void (*fn_dnd_drop)(Ecore_Evas *ee, unsigned int seat, Eina_Position2D p, const char *action);
326 } func; 354 } func;
327 355
328 Ecore_Evas_Engine engine; 356 Ecore_Evas_Engine engine;
@@ -353,6 +381,14 @@ struct _Ecore_Evas
353 unsigned char rotation_changed : 1; 381 unsigned char rotation_changed : 1;
354 } delayed; 382 } delayed;
355 383
384 Eina_Hash *active_drags;
385 struct {
386 Ecore_Evas *rep;
387 void *data;
388 Ecore_Evas_Drag_Finished free;
389 Eina_Bool accepted;
390 } drag;
391
356 int refcount; 392 int refcount;
357//#define ECORE_EVAS_ASYNC_RENDER_DEBUG 1 /* TODO: remove me */ 393//#define ECORE_EVAS_ASYNC_RENDER_DEBUG 1 /* TODO: remove me */
358#ifdef ECORE_EVAS_ASYNC_RENDER_DEBUG 394#ifdef ECORE_EVAS_ASYNC_RENDER_DEBUG
@@ -374,6 +410,7 @@ struct _Ecore_Evas
374 unsigned char first_frame : 1; 410 unsigned char first_frame : 1;
375 unsigned char self_del : 1; 411 unsigned char self_del : 1;
376 unsigned char evas_dying : 1; 412 unsigned char evas_dying : 1;
413 unsigned char fallback_interface : 1;
377}; 414};
378 415
379struct _Ecore_Evas_Aux_Hint 416struct _Ecore_Evas_Aux_Hint
@@ -486,6 +523,20 @@ EAPI Eina_Bool ecore_evas_render(Ecore_Evas *ee);
486EAPI Evas *ecore_evas_evas_new(Ecore_Evas *ee, int w, int h); 523EAPI Evas *ecore_evas_evas_new(Ecore_Evas *ee, int w, int h);
487EAPI void ecore_evas_done(Ecore_Evas *ee, Eina_Bool single_window); 524EAPI void ecore_evas_done(Ecore_Evas *ee, Eina_Bool single_window);
488 525
526EAPI void ecore_evas_dnd_position_set(Ecore_Evas *ee, unsigned int seat, Eina_Position2D pos);
527EAPI void ecore_evas_dnd_leave(Ecore_Evas *ee, unsigned int seat, Eina_Position2D pos);
528EAPI void ecore_evas_dnd_enter(Ecore_Evas *ee, unsigned int seat, Eina_Iterator *available_types, Eina_Position2D pos);
529EAPI Eina_Position2D ecore_evas_dnd_pos_get(Ecore_Evas *ee, unsigned int seat);
530
531
532void fallback_selection_init(Ecore_Evas *ee);
533void fallback_selection_shutdown(Ecore_Evas *ee);
534Eina_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);
535Eina_Bool fallback_selection_has_owner(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection);
536Eina_Future* fallback_selection_request(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection, Eina_Array *acceptable_type);
537Eina_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);
538Eina_Bool fallback_dnd_stop(Ecore_Evas *ee, unsigned int seat);
539
489#ifdef IPA_YLNO_ESU_LANRETNI_MLE 540#ifdef IPA_YLNO_ESU_LANRETNI_MLE
490EAPI Ecore_Evas *_wayland_shm_new(const char *disp_name, Ecore_Window parent, int x, int y, int w, int h, Eina_Bool frame); 541EAPI Ecore_Evas *_wayland_shm_new(const char *disp_name, Ecore_Window parent, int x, int y, int w, int h, Eina_Bool frame);
491EAPI 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); 542EAPI 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);
diff --git a/src/lib/ecore_evas/meson.build b/src/lib/ecore_evas/meson.build
index c0fb459a56..890e3c42b3 100644
--- a/src/lib/ecore_evas/meson.build
+++ b/src/lib/ecore_evas/meson.build
@@ -23,7 +23,8 @@ ecore_evas_src = [
23 'ecore_evas_cocoa.h', 23 'ecore_evas_cocoa.h',
24 'ecore_evas_win32.h', 24 'ecore_evas_win32.h',
25 'ecore_evas_x11.h', 25 'ecore_evas_x11.h',
26 'ecore_evas_util.c' 26 'ecore_evas_util.c',
27 'ecore_evas_fallback_selection.c'
27] 28]
28 29
29 30
diff --git a/src/lib/elementary/meson.build b/src/lib/elementary/meson.build
index 145d958e21..0cb3fc7db9 100644
--- a/src/lib/elementary/meson.build
+++ b/src/lib/elementary/meson.build
@@ -947,7 +947,7 @@ elementary_src = [
947 'efl_ui_collection_view.c', 947 'efl_ui_collection_view.c',
948 'efl_ui_pager.c', 948 'efl_ui_pager.c',
949 'efl_ui_stack.c', 949 'efl_ui_stack.c',
950 'efl_ui_separator.c' 950 'efl_ui_separator.c',
951] 951]
952 952
953elementary_deps = [emile, eo, efl, edje, ethumb, ethumb_client, emotion, ecore_imf, ecore_con, eldbus, efreet, efreet_mime, efreet_trash, eio, atspi, dl, intl] 953elementary_deps = [emile, eo, efl, edje, ethumb, ethumb_client, emotion, ecore_imf, ecore_con, eldbus, efreet, efreet_mime, efreet_trash, eio, atspi, dl, intl]
diff --git a/src/modules/ecore_evas/engines/sdl/ecore_evas_sdl.c b/src/modules/ecore_evas/engines/sdl/ecore_evas_sdl.c
index 8abc7401b6..ef4ba057b9 100644
--- a/src/modules/ecore_evas/engines/sdl/ecore_evas_sdl.c
+++ b/src/modules/ecore_evas/engines/sdl/ecore_evas_sdl.c
@@ -455,6 +455,9 @@ static Ecore_Evas_Engine_Func _ecore_sdl_engine_func =
455 NULL, //fn_pointer_device_xy_get 455 NULL, //fn_pointer_device_xy_get
456 NULL, //fn_prepare 456 NULL, //fn_prepare
457 NULL, //fn_last_tick_get 457 NULL, //fn_last_tick_get
458 NULL, //fn_selection_claim
459 NULL, //fn_selection_has_owner
460 NULL, //fn_selection_request
458}; 461};
459 462
460static Ecore_Evas* 463static Ecore_Evas*
diff --git a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c
index c14bdbcd33..e0e2094e2f 100644
--- a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c
+++ b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c
@@ -881,14 +881,14 @@ _rotation_do(Ecore_Evas *ee, int rotation, int resize)
881 { 881 {
882 /* resize the canvas */ 882 /* resize the canvas */
883 evas_output_size_set(ee->evas, ee->req.w, ee->req.h); 883 evas_output_size_set(ee->evas, ee->req.w, ee->req.h);
884 evas_output_viewport_set(ee->evas, 0, 0, 884 evas_output_viewport_set(ee->evas, 0, 0,
885 ee->req.w, ee->req.h); 885 ee->req.w, ee->req.h);
886 } 886 }
887 else 887 else
888 { 888 {
889 /* resize the canvas */ 889 /* resize the canvas */
890 evas_output_size_set(ee->evas, ee->req.h, ee->req.w); 890 evas_output_size_set(ee->evas, ee->req.h, ee->req.w);
891 evas_output_viewport_set(ee->evas, 0, 0, 891 evas_output_viewport_set(ee->evas, 0, 0,
892 ee->req.h, ee->req.w); 892 ee->req.h, ee->req.w);
893 } 893 }
894 } 894 }
@@ -2474,6 +2474,9 @@ static Ecore_Evas_Engine_Func _ecore_wl_engine_func =
2474 _ecore_evas_wl_common_pointer_device_xy_get, 2474 _ecore_evas_wl_common_pointer_device_xy_get,
2475 _ecore_evas_wl_common_prepare, 2475 _ecore_evas_wl_common_prepare,
2476 NULL, //fn_last_tick_get 2476 NULL, //fn_last_tick_get
2477 NULL, //fn_selection_claim
2478 NULL, //fn_selection_has_owner
2479 NULL, //fn_selection_request
2477}; 2480};
2478 2481
2479static void 2482static void
diff --git a/src/modules/ecore_evas/engines/win32/ecore_evas_win32.c b/src/modules/ecore_evas/engines/win32/ecore_evas_win32.c
index 39def9d49f..6198ed4bac 100644
--- a/src/modules/ecore_evas/engines/win32/ecore_evas_win32.c
+++ b/src/modules/ecore_evas/engines/win32/ecore_evas_win32.c
@@ -1284,6 +1284,9 @@ static Ecore_Evas_Engine_Func _ecore_win32_engine_func =
1284 NULL, //fn_pointer_device_xy_get 1284 NULL, //fn_pointer_device_xy_get
1285 NULL, //fn_prepare 1285 NULL, //fn_prepare
1286 NULL, //fn_last_tick_get 1286 NULL, //fn_last_tick_get
1287 NULL, //fn_selection_claim
1288 NULL, //fn_selection_has_owner
1289 NULL, //fn_selection_request
1287}; 1290};
1288 1291
1289#endif /* BUILD_ECORE_EVAS_WIN32 */ 1292#endif /* BUILD_ECORE_EVAS_WIN32 */
diff --git a/src/modules/ecore_evas/engines/x/ecore_evas_x.c b/src/modules/ecore_evas/engines/x/ecore_evas_x.c
index abea314d33..fb6eaa63f1 100644
--- a/src/modules/ecore_evas/engines/x/ecore_evas_x.c
+++ b/src/modules/ecore_evas/engines/x/ecore_evas_x.c
@@ -361,7 +361,7 @@ _ecore_evas_x_aux_hints_supported_update(Ecore_Evas *ee)
361 for (i = 0; i < num; i++) 361 for (i = 0; i < num; i++)
362 { 362 {
363 hint = eina_stringshare_add(str[i]); 363 hint = eina_stringshare_add(str[i]);
364 ee->prop.aux_hint.supported_list = 364 ee->prop.aux_hint.supported_list =
365 eina_list_append(ee->prop.aux_hint.supported_list, hint); 365 eina_list_append(ee->prop.aux_hint.supported_list, hint);
366 } 366 }
367 367
@@ -414,7 +414,7 @@ _ecore_evas_x_gl_window_new(Ecore_Evas *ee, Ecore_X_Window parent, int x, int y,
414 op++; 414 op++;
415 einfo->vsync = opt[op]; 415 einfo->vsync = opt[op];
416 } 416 }
417#ifdef EVAS_ENGINE_GL_X11_SWAP_MODE_EXISTS 417#ifdef EVAS_ENGINE_GL_X11_SWAP_MODE_EXISTS
418 else if (opt[op] == ECORE_EVAS_GL_X11_OPT_SWAP_MODE) 418 else if (opt[op] == ECORE_EVAS_GL_X11_OPT_SWAP_MODE)
419 { 419 {
420 op++; 420 op++;
@@ -845,7 +845,7 @@ _ecore_evas_x_event_property_change(void *data EINA_UNUSED, int type EINA_UNUSED
845 Eina_Bool focus_skip : 1; 845 Eina_Bool focus_skip : 1;
846 } prop; 846 } prop;
847 } prev; 847 } prev;
848 848
849 prev.x.modal = edata->state.modal; 849 prev.x.modal = edata->state.modal;
850 prev.x.sticky = edata->state.sticky; 850 prev.x.sticky = edata->state.sticky;
851 prev.x.maximized_v = edata->state.maximized_v; 851 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
856 prev.x.fullscreen = edata->state.fullscreen; 856 prev.x.fullscreen = edata->state.fullscreen;
857 prev.x.above = edata->state.above; 857 prev.x.above = edata->state.above;
858 prev.x.below = edata->state.below; 858 prev.x.below = edata->state.below;
859 859
860 prev.prop.modal = ee->prop.modal; 860 prev.prop.modal = ee->prop.modal;
861 prev.prop.maximized = ee->prop.maximized; 861 prev.prop.maximized = ee->prop.maximized;
862 prev.prop.sticky = ee->prop.sticky; 862 prev.prop.sticky = ee->prop.sticky;
@@ -879,7 +879,7 @@ _ecore_evas_x_event_property_change(void *data EINA_UNUSED, int type EINA_UNUSED
879 ee->prop.sticky = EINA_FALSE; 879 ee->prop.sticky = EINA_FALSE;
880 ee->prop.fullscreen = EINA_FALSE; 880 ee->prop.fullscreen = EINA_FALSE;
881// ee->prop.focus_skip = EINA_FALSE; 881// ee->prop.focus_skip = EINA_FALSE;
882 882
883 ecore_x_netwm_window_state_get(e->win, &state, &num); 883 ecore_x_netwm_window_state_get(e->win, &state, &num);
884 if (state) 884 if (state)
885 { 885 {
@@ -1253,7 +1253,7 @@ _ecore_evas_x_event_mouse_in(void *data EINA_UNUSED, int type EINA_UNUSED, void
1253 if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; /* pass on event */ 1253 if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1254 if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON; 1254 if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
1255 edata = ee->engine.data; 1255 edata = ee->engine.data;
1256/* 1256/*
1257 { 1257 {
1258 time_t t; 1258 time_t t;
1259 char *ct; 1259 char *ct;
@@ -1304,7 +1304,7 @@ _ecore_evas_x_event_mouse_in(void *data EINA_UNUSED, int type EINA_UNUSED, void
1304 edata->outdelay = NULL; 1304 edata->outdelay = NULL;
1305 _fake_out(ee); 1305 _fake_out(ee);
1306 } 1306 }
1307 1307
1308 /* if (e->mode != ECORE_X_EVENT_MODE_NORMAL) return 0; */ 1308 /* if (e->mode != ECORE_X_EVENT_MODE_NORMAL) return 0; */
1309 if (!_ecore_evas_mouse_in_check(ee, NULL)) 1309 if (!_ecore_evas_mouse_in_check(ee, NULL))
1310 { 1310 {
@@ -1388,7 +1388,7 @@ _ecore_evas_x_event_mouse_out(void *data EINA_UNUSED, int type EINA_UNUSED, void
1388 ecore_timer_del(edata->outdelay); 1388 ecore_timer_del(edata->outdelay);
1389 edata->outdelay = NULL; 1389 edata->outdelay = NULL;
1390 } 1390 }
1391 1391
1392// if (e->mode != ECORE_X_EVENT_MODE_NORMAL) return 0; 1392// if (e->mode != ECORE_X_EVENT_MODE_NORMAL) return 0;
1393// printf("OUT: ee->in=%i, e->mode=%i, e->detail=%i, dount_count=%i\n", 1393// printf("OUT: ee->in=%i, e->mode=%i, e->detail=%i, dount_count=%i\n",
1394// ee->in, e->mode, e->detail, evas_event_down_count_get(ee->evas)); 1394// 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
1417 ee = ecore_event_window_match(e->win); 1417 ee = ecore_event_window_match(e->win);
1418 if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; /* pass on event */ 1418 if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1419 if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON; 1419 if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
1420//xx// filtering with these doesnt help 1420//xx// filtering with these doesnt help
1421//xx// if (e->mode == ECORE_X_EVENT_MODE_UNGRAB) return ECORE_CALLBACK_PASS_ON; 1421//xx// if (e->mode == ECORE_X_EVENT_MODE_UNGRAB) return ECORE_CALLBACK_PASS_ON;
1422 _ecore_evas_focus_device_set(ee, NULL, EINA_TRUE); 1422 _ecore_evas_focus_device_set(ee, NULL, EINA_TRUE);
1423 return ECORE_CALLBACK_PASS_ON; 1423 return ECORE_CALLBACK_PASS_ON;
@@ -1433,7 +1433,7 @@ _ecore_evas_x_event_window_focus_out(void *data EINA_UNUSED, int type EINA_UNUSE
1433 ee = ecore_event_window_match(e->win); 1433 ee = ecore_event_window_match(e->win);
1434 if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; /* pass on event */ 1434 if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON; /* pass on event */
1435 if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON; 1435 if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
1436//xx// filtering with these doesnt help 1436//xx// filtering with these doesnt help
1437//xx// if (e->mode == ECORE_X_EVENT_MODE_GRAB) return ECORE_CALLBACK_PASS_ON; 1437//xx// if (e->mode == ECORE_X_EVENT_MODE_GRAB) return ECORE_CALLBACK_PASS_ON;
1438 1438
1439// if (ee->prop.fullscreen) 1439// if (ee->prop.fullscreen)
@@ -2145,7 +2145,7 @@ _ecore_evas_x_resize(Ecore_Evas *ee, int w, int h)
2145 } 2145 }
2146 2146
2147 /* check for valid property window 2147 /* check for valid property window
2148 * 2148 *
2149 * NB: If we do not have one, check for valid pixmap rendering */ 2149 * NB: If we do not have one, check for valid pixmap rendering */
2150 if (!ee->prop.window) 2150 if (!ee->prop.window)
2151 { 2151 {
@@ -2153,7 +2153,7 @@ _ecore_evas_x_resize(Ecore_Evas *ee, int w, int h)
2153 if ((edata->pixmap.w != vw) || (edata->pixmap.h != vh)) 2153 if ((edata->pixmap.w != vw) || (edata->pixmap.h != vh))
2154 { 2154 {
2155 /* free the backing pixmap */ 2155 /* free the backing pixmap */
2156 if (edata->pixmap.back) 2156 if (edata->pixmap.back)
2157 ecore_x_pixmap_free(edata->pixmap.back); 2157 ecore_x_pixmap_free(edata->pixmap.back);
2158 } 2158 }
2159 } 2159 }
@@ -2918,7 +2918,7 @@ _ecore_evas_x_aspect_set(Ecore_Evas *ee, double aspect)
2918 2918
2919 ee->prop.aspect = aspect; 2919 ee->prop.aspect = aspect;
2920 _ecore_evas_x_size_pos_hints_update(ee); 2920 _ecore_evas_x_size_pos_hints_update(ee);
2921// netwm state 2921// netwm state
2922// if (ee->should_be_visible) 2922// if (ee->should_be_visible)
2923// ecore_x_netwm_state_request_send(ee->prop.window, ee->engine.x.win_root, 2923// ecore_x_netwm_state_request_send(ee->prop.window, ee->engine.x.win_root,
2924// ECORE_X_WINDOW_STATE_STICKY, -1, sticky); 2924// ECORE_X_WINDOW_STATE_STICKY, -1, sticky);
@@ -3545,14 +3545,14 @@ norandr:
3545 if (!found) goto norandr; 3545 if (!found) goto norandr;
3546} 3546}
3547 3547
3548static void 3548static void
3549_ecore_evas_x_pointer_xy_get(const Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y) 3549_ecore_evas_x_pointer_xy_get(const Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y)
3550{ 3550{
3551 if (ee->prop.window) 3551 if (ee->prop.window)
3552 ecore_x_pointer_xy_get(ee->prop.window, x, y); 3552 ecore_x_pointer_xy_get(ee->prop.window, x, y);
3553} 3553}
3554 3554
3555static Eina_Bool 3555static Eina_Bool
3556_ecore_evas_x_pointer_warp(const Ecore_Evas *ee, Evas_Coord x, Evas_Coord y) 3556_ecore_evas_x_pointer_warp(const Ecore_Evas *ee, Evas_Coord x, Evas_Coord y)
3557{ 3557{
3558 return ecore_x_pointer_warp(ee->prop.window, x, y); 3558 return ecore_x_pointer_warp(ee->prop.window, x, y);
@@ -3754,6 +3754,9 @@ static Ecore_Evas_Engine_Func _ecore_x_engine_func =
3754 NULL, //fn_pointer_device_xy_get 3754 NULL, //fn_pointer_device_xy_get
3755 NULL, //fn_prepare 3755 NULL, //fn_prepare
3756 NULL, //fn_last_tick_get 3756 NULL, //fn_last_tick_get
3757 NULL, //fn_selection_claim
3758 NULL, //fn_selection_has_owner
3759 NULL, //fn_selection_request
3757}; 3760};
3758 3761
3759/* 3762/*
@@ -3772,19 +3775,19 @@ _ecore_evas_x_render_pre(void *data, Evas *e EINA_UNUSED, void *event_info EINA_
3772 /* printf("\tPixman Size: %d %d\n", edata->pixmap.w, edata->pixmap.h); */ 3775 /* printf("\tPixman Size: %d %d\n", edata->pixmap.w, edata->pixmap.h); */
3773 /* printf("\tEE Size: %d %d\n", ee->w, ee->h); */ 3776 /* printf("\tEE Size: %d %d\n", ee->w, ee->h); */
3774 3777
3775 /* before rendering to the back buffer pixmap, we should check the 3778 /* before rendering to the back buffer pixmap, we should check the
3776 * size. If the back buffer is not the proper size, destroy it and 3779 * size. If the back buffer is not the proper size, destroy it and
3777 * create a new one at the proper size */ 3780 * create a new one at the proper size */
3778 if ((edata->pixmap.w != ee->w) || (edata->pixmap.h != ee->h)) 3781 if ((edata->pixmap.w != ee->w) || (edata->pixmap.h != ee->h))
3779 { 3782 {
3780 int fw = 0, fh = 0; 3783 int fw = 0, fh = 0;
3781 3784
3782 /* free the backing pixmap */ 3785 /* free the backing pixmap */
3783 if (edata->pixmap.back) 3786 if (edata->pixmap.back)
3784 ecore_x_pixmap_free(edata->pixmap.back); 3787 ecore_x_pixmap_free(edata->pixmap.back);
3785 3788
3786 edata->pixmap.back = 3789 edata->pixmap.back =
3787 ecore_x_pixmap_new(edata->win_root, ee->w, ee->h, 3790 ecore_x_pixmap_new(edata->win_root, ee->w, ee->h,
3788 edata->pixmap.depth); 3791 edata->pixmap.depth);
3789 3792
3790 evas_output_framespace_get(ee->evas, NULL, NULL, &fw, &fh); 3793 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_
3803 3806
3804 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) 3807 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
3805 { 3808 {
3806 ERR("evas_engine_info_set() init engine '%s' failed.", 3809 ERR("evas_engine_info_set() init engine '%s' failed.",
3807 ee->driver); 3810 ee->driver);
3808 } 3811 }
3809 } 3812 }
@@ -3821,7 +3824,7 @@ _ecore_evas_x_render_pre(void *data, Evas *e EINA_UNUSED, void *event_info EINA_
3821 3824
3822 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) 3825 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
3823 { 3826 {
3824 ERR("evas_engine_info_set() init engine '%s' failed.", 3827 ERR("evas_engine_info_set() init engine '%s' failed.",
3825 ee->driver); 3828 ee->driver);
3826 } 3829 }
3827 } 3830 }
@@ -3844,8 +3847,8 @@ _ecore_evas_x_flush_post(void *data, Evas *e EINA_UNUSED, void *event_info EINA_
3844 /* printf("\tBack Pixmap: %d\n", edata->pixmap.back); */ 3847 /* printf("\tBack Pixmap: %d\n", edata->pixmap.back); */
3845 /* printf("\tFront Pixmap: %d\n", edata->pixmap.front); */ 3848 /* printf("\tFront Pixmap: %d\n", edata->pixmap.front); */
3846 3849
3847 /* done drawing to the back buffer. flip it to the front so that 3850 /* done drawing to the back buffer. flip it to the front so that
3848 * any calls to "fetch pixmap" will return the front buffer already 3851 * any calls to "fetch pixmap" will return the front buffer already
3849 * pre-rendered */ 3852 * pre-rendered */
3850 3853
3851 /* record the current front buffer */ 3854 /* record the current front buffer */
@@ -3870,7 +3873,7 @@ _ecore_evas_x_flush_post(void *data, Evas *e EINA_UNUSED, void *event_info EINA_
3870 3873
3871 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) 3874 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
3872 { 3875 {
3873 ERR("evas_engine_info_set() init engine '%s' failed.", 3876 ERR("evas_engine_info_set() init engine '%s' failed.",
3874 ee->driver); 3877 ee->driver);
3875 } 3878 }
3876 } 3879 }
@@ -3888,7 +3891,7 @@ _ecore_evas_x_flush_post(void *data, Evas *e EINA_UNUSED, void *event_info EINA_
3888 3891
3889 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) 3892 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
3890 { 3893 {
3891 ERR("evas_engine_info_set() init engine '%s' failed.", 3894 ERR("evas_engine_info_set() init engine '%s' failed.",
3892 ee->driver); 3895 ee->driver);
3893 } 3896 }
3894 } 3897 }
@@ -4307,9 +4310,9 @@ ecore_evas_software_x11_pixmap_new_internal(const char *disp_name, Ecore_X_Windo
4307 edata->pixmap.colormap = einfo->info.colormap; 4310 edata->pixmap.colormap = einfo->info.colormap;
4308 4311
4309 /* create front and back pixmaps for double-buffer rendering */ 4312 /* create front and back pixmaps for double-buffer rendering */
4310 edata->pixmap.front = 4313 edata->pixmap.front =
4311 ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth); 4314 ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth);
4312 edata->pixmap.back = 4315 edata->pixmap.back =
4313 ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth); 4316 ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth);
4314 4317
4315 einfo->info.drawable = edata->pixmap.back; 4318 einfo->info.drawable = edata->pixmap.back;
@@ -4322,7 +4325,7 @@ ecore_evas_software_x11_pixmap_new_internal(const char *disp_name, Ecore_X_Windo
4322 } 4325 }
4323 } 4326 }
4324 4327
4325 /* FIXME: Allow of these set properties or do something with the 4328 /* FIXME: Allow of these set properties or do something with the
4326 * ee->prop.window (x window), which we do not have in pixmap case */ 4329 * ee->prop.window (x window), which we do not have in pixmap case */
4327 4330
4328 /* _ecore_evas_x_hints_update(ee); */ 4331 /* _ecore_evas_x_hints_update(ee); */
@@ -4370,7 +4373,7 @@ _ecore_evas_software_x11_pixmap_visual_get(const Ecore_Evas *ee)
4370 return edata->pixmap.visual; 4373 return edata->pixmap.visual;
4371} 4374}
4372 4375
4373static unsigned long 4376static unsigned long
4374_ecore_evas_software_x11_pixmap_colormap_get(const Ecore_Evas *ee) 4377_ecore_evas_software_x11_pixmap_colormap_get(const Ecore_Evas *ee)
4375{ 4378{
4376 if (!(!strcmp(ee->driver, "software_x11"))) return 0; 4379 if (!(!strcmp(ee->driver, "software_x11"))) return 0;
@@ -4378,7 +4381,7 @@ _ecore_evas_software_x11_pixmap_colormap_get(const Ecore_Evas *ee)
4378 return edata->pixmap.colormap; 4381 return edata->pixmap.colormap;
4379} 4382}
4380 4383
4381static int 4384static int
4382_ecore_evas_software_x11_pixmap_depth_get(const Ecore_Evas *ee) 4385_ecore_evas_software_x11_pixmap_depth_get(const Ecore_Evas *ee)
4383{ 4386{
4384 if (!(!strcmp(ee->driver, "software_x11"))) return 0; 4387 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
4719 edata->pixmap.colormap = einfo->info.colormap; 4722 edata->pixmap.colormap = einfo->info.colormap;
4720 4723
4721 /* create front and back pixmaps for double-buffer rendering */ 4724 /* create front and back pixmaps for double-buffer rendering */
4722 edata->pixmap.front = 4725 edata->pixmap.front =
4723 ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth); 4726 ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth);
4724 edata->pixmap.back = 4727 edata->pixmap.back =
4725 ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth); 4728 ecore_x_pixmap_new(parent, w, h, edata->pixmap.depth);
4726 4729
4727 einfo->info.drawable = edata->pixmap.back; 4730 einfo->info.drawable = edata->pixmap.back;
@@ -4779,7 +4782,7 @@ _ecore_evas_gl_x11_pixmap_visual_get(const Ecore_Evas *ee)
4779 return edata->pixmap.visual; 4782 return edata->pixmap.visual;
4780} 4783}
4781 4784
4782static unsigned long 4785static unsigned long
4783_ecore_evas_gl_x11_pixmap_colormap_get(const Ecore_Evas *ee) 4786_ecore_evas_gl_x11_pixmap_colormap_get(const Ecore_Evas *ee)
4784{ 4787{
4785 if (!(!strcmp(ee->driver, "opengl_x11"))) return 0; 4788 if (!(!strcmp(ee->driver, "opengl_x11"))) return 0;
@@ -4787,7 +4790,7 @@ _ecore_evas_gl_x11_pixmap_colormap_get(const Ecore_Evas *ee)
4787 return edata->pixmap.colormap; 4790 return edata->pixmap.colormap;
4788} 4791}
4789 4792
4790static int 4793static int
4791_ecore_evas_gl_x11_pixmap_depth_get(const Ecore_Evas *ee) 4794_ecore_evas_gl_x11_pixmap_depth_get(const Ecore_Evas *ee)
4792{ 4795{
4793 if (!(!strcmp(ee->driver, "opengl_x11"))) return 0; 4796 if (!(!strcmp(ee->driver, "opengl_x11"))) return 0;
diff --git a/src/tests/ecore/ecore_suite.c b/src/tests/ecore/ecore_suite.c
index b9248a814a..a0f6d19aba 100644
--- a/src/tests/ecore/ecore_suite.c
+++ b/src/tests/ecore/ecore_suite.c
@@ -30,6 +30,7 @@ static const Efl_Test_Case etc[] = {
30 { "Ecore_Job", ecore_test_ecore_job }, 30 { "Ecore_Job", ecore_test_ecore_job },
31 { "Ecore_Args", ecore_test_ecore_args }, 31 { "Ecore_Args", ecore_test_ecore_args },
32 { "Ecore_Pipe", ecore_test_ecore_pipe }, 32 { "Ecore_Pipe", ecore_test_ecore_pipe },
33 { "Ecore_Evas_Selection", ecore_test_ecore_evas_selection },
33 { NULL, NULL } 34 { NULL, NULL }
34}; 35};
35 36
diff --git a/src/tests/ecore/ecore_suite.h b/src/tests/ecore/ecore_suite.h
index a3327412fe..2621535f59 100644
--- a/src/tests/ecore/ecore_suite.h
+++ b/src/tests/ecore/ecore_suite.h
@@ -23,5 +23,6 @@ void ecore_test_ecore_file(TCase *tc);
23void ecore_test_ecore_job(TCase *tc); 23void ecore_test_ecore_job(TCase *tc);
24void ecore_test_ecore_args(TCase *tc); 24void ecore_test_ecore_args(TCase *tc);
25void ecore_test_ecore_pipe(TCase *tc); 25void ecore_test_ecore_pipe(TCase *tc);
26void ecore_test_ecore_evas_selection(TCase *tc);
26 27
27#endif /* _ECORE_SUITE_H */ 28#endif /* _ECORE_SUITE_H */
diff --git a/src/tests/ecore/ecore_test_ecore_evas.c b/src/tests/ecore/ecore_test_ecore_evas.c
index 2e53f62082..0e7b09c41b 100644
--- a/src/tests/ecore/ecore_test_ecore_evas.c
+++ b/src/tests/ecore/ecore_test_ecore_evas.c
@@ -3,6 +3,7 @@
3#endif 3#endif
4 4
5#include <Ecore_Evas.h> 5#include <Ecore_Evas.h>
6#include <Efl_Core.h>
6 7
7#include "ecore_suite.h" 8#include "ecore_suite.h"
8 9
@@ -70,8 +71,51 @@ EFL_START_TEST(ecore_test_ecore_evas_cocoa)
70} 71}
71EFL_END_TEST 72EFL_END_TEST
72 73
74static Eina_Value
75_verify_and_exit(void *data, const Eina_Value value, const Eina_Future *dead_future EINA_UNUSED)
76{
77 ck_assert_ptr_eq(eina_value_type_get(&value), EINA_VALUE_TYPE_CONTENT);
78 Eina_Content *content = eina_value_to_content(&value);
79 Eina_Content *reference = data;
80
81 ck_assert_int_eq(eina_content_data_get(content).len, eina_content_data_get(reference).len);
82 ck_assert_str_eq(eina_content_data_get(content).mem, eina_content_data_get(reference).mem);
83 ck_assert_str_eq(eina_content_type_get(content), eina_content_type_get(reference));
84
85 efl_loop_quit(efl_main_loop_get(), eina_value_int_init(0));
86
87 return EINA_VALUE_EMPTY;
88}
89
90EFL_START_TEST(ecore_test_ecore_evas_fallback_selection)
91{
92 Ecore_Evas *ee;
93 ecore_evas_init();
94
95 ee = ecore_evas_buffer_new(WINDOW_WIDTH, WINDOW_HEIGHT);
96 fail_if(ee == NULL);
97
98 for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
99 {
100 ck_assert_int_eq(ecore_evas_selection_exists(ee, 0, i), EINA_FALSE);
101 }
102 Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL("asdf"), "text/plain");
103 Eina_Content *ref = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL("asdf"), "text/plain");
104 ecore_evas_selection_set(ee, 0, ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER, content);
105
106 const char *types[] = {eina_stringshare_add("text/plain")};
107
108 Eina_Future *f = ecore_evas_selection_get(ee, 0, ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER, EINA_C_ARRAY_ITERATOR_NEW(types));
109 ck_assert_ptr_ne(f, NULL);
110 eina_future_then(f, _verify_and_exit, ref);
111 efl_task_run(efl_main_loop_get());
112 ecore_evas_shutdown();
113}
114EFL_END_TEST
115
73void ecore_test_ecore_evas(TCase *tc) 116void ecore_test_ecore_evas(TCase *tc)
74{ 117{
75 tcase_add_test(tc, ecore_test_ecore_evas_associate); 118 tcase_add_test(tc, ecore_test_ecore_evas_associate);
76 tcase_add_test(tc, ecore_test_ecore_evas_cocoa); 119 tcase_add_test(tc, ecore_test_ecore_evas_cocoa);
120 tcase_add_test(tc, ecore_test_ecore_evas_fallback_selection);
77} 121}
diff --git a/src/tests/ecore/ecore_test_ecore_evas_selection.c b/src/tests/ecore/ecore_test_ecore_evas_selection.c
new file mode 100644
index 0000000000..9efc5fe722
--- /dev/null
+++ b/src/tests/ecore/ecore_test_ecore_evas_selection.c
@@ -0,0 +1,89 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <Ecore_Evas.h>
6#include <Efl_Core.h>
7
8#include "ecore_suite.h"
9
10#define WINDOW_HEIGHT 200
11#define WINDOW_WIDTH 200
12
13static int log_abort;
14static int log_abort_level;
15
16void
17fail_on_errors_teardown(void)
18{
19 eina_log_abort_on_critical_set(log_abort);
20 eina_log_abort_on_critical_level_set(log_abort_level);
21}
22
23void
24fail_on_errors_setup(void)
25{
26 log_abort = eina_log_abort_on_critical_get();
27 log_abort_level = eina_log_abort_on_critical_level_get();
28 eina_log_abort_on_critical_level_set(2);
29 eina_log_abort_on_critical_set(1);
30}
31
32static Ecore_Evas *ee;
33
34void
35_setup(void)
36{
37 ecore_evas_init();
38 ee = ecore_evas_buffer_new(50, 50);
39}
40
41void
42_teardown(void)
43{
44 ecore_evas_free(ee);
45 ecore_evas_shutdown();
46}
47
48EFL_START_TEST(ecore_test_selection_get_twice)
49{
50 //this is just running this and checking that we do not error
51 for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
52 {
53 if (i == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER) continue;
54 const char *types[] = {eina_stringshare_add("text/plain")};
55 ck_assert_ptr_ne(ecore_evas_selection_get(ee, 0, i, EINA_C_ARRAY_ITERATOR_NEW(types)), NULL);
56 }
57 for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
58 {
59 if (i == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER) continue;
60 const char *types[] = {eina_stringshare_add("text/plain")};
61 ck_assert_ptr_ne(ecore_evas_selection_get(ee, 0, i, EINA_C_ARRAY_ITERATOR_NEW(types)), NULL);
62 }
63}
64EFL_END_TEST
65
66EFL_START_TEST(ecore_test_selection_claim_twice)
67{
68 //this is just running this and checking that we do not error
69 for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
70 {
71 if (i == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER) continue;
72 Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL("asdf"), "text/plain");
73 ck_assert_int_eq(ecore_evas_selection_set(ee, 0, i, content), EINA_TRUE);
74 }
75 for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
76 {
77 if (i == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER) continue;
78 Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL("asdf"), "text/plain");
79 ck_assert_int_eq(ecore_evas_selection_set(ee, 0, i, content), EINA_TRUE);
80 }
81}
82EFL_END_TEST
83void ecore_test_ecore_evas_selection(TCase *tc)
84{
85 tcase_add_checked_fixture(tc, fail_on_errors_setup, fail_on_errors_teardown);
86 tcase_add_checked_fixture(tc, _setup, _teardown);
87 tcase_add_test(tc, ecore_test_selection_get_twice);
88 tcase_add_test(tc, ecore_test_selection_claim_twice);
89}
diff --git a/src/tests/ecore/meson.build b/src/tests/ecore/meson.build
index 9ce6848ce2..48c9350638 100644
--- a/src/tests/ecore/meson.build
+++ b/src/tests/ecore/meson.build
@@ -13,6 +13,7 @@ ecore_suite_src = [
13 'ecore_test_job.c', 13 'ecore_test_job.c',
14 'ecore_test_args.c', 14 'ecore_test_args.c',
15 'ecore_test_pipe.c', 15 'ecore_test_pipe.c',
16 'ecore_test_ecore_evas_selection.c',
16 'ecore_suite.h' 17 'ecore_suite.h'
17] 18]
18 19
diff --git a/src/tests/elementary/efl_ui_window_cnp_dnd_slave.c b/src/tests/elementary/efl_ui_window_cnp_dnd_slave.c
new file mode 100644
index 0000000000..bf8c6d50bd
--- /dev/null
+++ b/src/tests/elementary/efl_ui_window_cnp_dnd_slave.c
@@ -0,0 +1,191 @@
1#define EFL_BETA_API_SUPPORT 1
2
3#include <Efl.h>
4#include <Efl_Ui.h>
5#include <Elementary.h>
6#include "efl_ui_grid_view.eo.h"
7
8static Ecore_Evas *ee;
9
10static Eina_Value
11_deliverty_cb(void *data, const Eina_Value value, const Eina_Future *dead_future EINA_UNUSED)
12{
13 Ecore_Evas_Selection_Buffer buffer = (intptr_t)data;
14 Eina_Content *content;
15
16 if (eina_value_type_get(&value) != EINA_VALUE_TYPE_CONTENT)
17 {
18 char *error = eina_value_to_string(&value);
19 printf("Value not a content, message: \"%s\"\n", error);
20 return EINA_VALUE_EMPTY;
21 }
22
23 content = eina_value_to_content(&value);
24 printf("Got Content of selection %d with type %s\n", buffer, eina_content_type_get(content));
25 if (!strncmp(eina_content_type_get(content), "text", strlen("text")))
26 {
27 printf("Content: %s\n", (char*)eina_content_data_get(content).mem);
28 }
29
30 return EINA_VALUE_EMPTY;
31}
32
33static void
34_selection_changed(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection)
35{
36 printf("Selection %d of %p has changed\n", selection, ee);
37}
38
39static void
40_request_selection(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection)
41{
42 const char *types[] = {eina_stringshare_add("text/plain"), eina_stringshare_add("text/plain;charset=utf-8")};
43 printf("Selection %d of %p has changed\n", selection, ee);
44 Eina_Future *future = ecore_evas_selection_get(ee, 0, selection, EINA_C_ARRAY_ITERATOR_NEW(types));
45 eina_future_then(future, _deliverty_cb, .data = ((void*)(intptr_t)selection));
46}
47
48static void
49_motion_cb(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Eina_Position2D p)
50{
51 printf("Drag and Drop has moved on the window %p (%d, %d)\n", ee, p.x, p.y);
52}
53
54static void
55_enter_state_change_cb(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Eina_Position2D p, Eina_Bool inside)
56{
57 if (inside)
58 printf("Drag and Drop has entered the window %p (%d, %d)\n", ee, p.x, p.y);
59 else
60 printf("Drag and Drop has left the window %p (%d, %d)\n", ee, p.x, p.y);
61}
62
63static void
64_drop_cb(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Eina_Position2D p, const char *action EINA_UNUSED)
65{
66 const char *types[] = {eina_stringshare_add("text/plain")};
67 printf("Drag and Drop has droped on the window %p (%d, %d)\n", ee, p.x, p.y);
68 Eina_Future *f = ecore_evas_selection_get(ee, 0, ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER, EINA_C_ARRAY_ITERATOR_NEW(types));
69 eina_future_then(f, _deliverty_cb, .data = ((void*)(intptr_t)ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER));
70}
71
72static void
73_efl_ui_terminated(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, void *data, Eina_Bool accepted EINA_UNUSED)
74{
75 efl_del(data);
76}
77
78static Eo*
79_start_dnd(Ecore_Evas *ee)
80{
81 Ecore_Evas *ee2;
82 Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL("This is sample content"), "text/plain");
83 Efl_Ui_Win *win;
84 Efl_Ui_Button *btn;
85
86 win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get());
87 ee2 = ecore_evas_ecore_evas_get(evas_object_evas_get(win));
88
89 btn = efl_add(EFL_UI_BUTTON_CLASS, win);
90 efl_text_set(btn, "Test");
91 efl_content_set(win, btn);
92
93 evas_object_geometry_set(win, 0, 0, 100, 100);
94
95 ecore_evas_drag_start(ee, 0, content, ee2, "copy", _efl_ui_terminated, win);
96
97 return win;
98}
99
100static void
101_start_op(void *data, const Efl_Event *ev EINA_UNUSED)
102{
103 _start_dnd(data);
104}
105
106static Eina_Value
107_delete_cb(Eo *obj, void *data EINA_UNUSED, const Eina_Value value EINA_UNUSED)
108{
109 Ecore_Evas *ee ;
110 ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
111
112 ecore_evas_drag_cancel(ee, 0);
113
114 return EINA_VALUE_EMPTY;
115}
116
117static void
118_start_delayed_del_op(void *data, const Efl_Event *ev EINA_UNUSED)
119{
120 _start_dnd(data);
121 efl_future_then(ev->object, efl_loop_timeout(efl_main_loop_get(), 2.0), _delete_cb);
122}
123
124EAPI_MAIN void
125efl_main(void *data EINA_UNUSED, const Efl_Event *ev)
126{
127 Efl_Ui_Textbox *txt, *win, *bx, *btn;
128 Efl_Loop_Arguments *args = ev->info;
129 char *goal;
130
131 win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get());
132 ee = ecore_evas_ecore_evas_get(evas_object_evas_get(win));
133
134 bx = efl_add(EFL_UI_BOX_CLASS, win);
135
136 txt = efl_add(EFL_UI_TEXTBOX_CLASS, win);
137 efl_text_set(txt, "Sample for CNP and DND interaction");
138 efl_pack_end(bx, txt);
139
140 btn = efl_add(EFL_UI_BUTTON_CLASS, win);
141 efl_gfx_hint_weight_set(btn, 1.0, 0.0);
142 efl_event_callback_add(btn, EFL_INPUT_EVENT_PRESSED, _start_op, ee);
143 efl_text_set(btn, "Start DND op");
144 efl_pack_end(bx, btn);
145
146 btn = efl_add(EFL_UI_BUTTON_CLASS, win);
147 efl_gfx_hint_weight_set(btn, 1.0, 0.0);
148 efl_event_callback_add(btn, EFL_INPUT_EVENT_PRESSED, _start_delayed_del_op, ee);
149 efl_text_set(btn, "Start DND op self destroy after 2 sec");
150 efl_pack_end(bx, btn);
151
152 efl_content_set(win, bx);
153 efl_gfx_entity_size_set(win, EINA_SIZE2D(320, 320));
154
155 goal = eina_array_data_get(args->argv, 1);
156
157 if (eina_streq(goal, "--monitor"))
158 {
159 ecore_evas_callback_selection_changed_set(ee, _selection_changed);
160 ecore_evas_callback_drop_drop_set(ee, _drop_cb);
161 ecore_evas_callback_drop_motion_set(ee, _motion_cb);
162 ecore_evas_callback_drop_state_changed_set(ee, _enter_state_change_cb);
163 }
164 else if (eina_streq(goal, "--show-selections"))
165 {
166 ecore_evas_callback_selection_changed_set(ee, _request_selection);
167 }
168 else if (eina_streq(goal, "--set-selection"))
169 {
170 if (eina_array_count(args->argv) < 3)
171 {
172 printf("Error, --set-selection only requires exactly 1 keyword (The selection to set).\n");
173 return;
174 }
175 char *selection = eina_array_data_get(args->argv, 2);
176 Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(selection), "text/plain");
177 ecore_evas_selection_set(ee, 0, ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER, content);
178 }
179 else if (eina_streq(goal, "--show-owner"))
180 {
181 for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
182 {
183 printf("Selection buffer %d : %d\n", i, ecore_evas_selection_exists(ee, 0, i));
184 }
185 }
186 else
187 {
188 printf("Error, goal %s not found\n", goal);
189 }
190}
191EFL_MAIN()
diff --git a/src/tests/elementary/meson.build b/src/tests/elementary/meson.build
index 7f5fd03733..1b43da7064 100644
--- a/src/tests/elementary/meson.build
+++ b/src/tests/elementary/meson.build
@@ -187,6 +187,11 @@ efl_ui_compile_test = executable('efl_ui_compile_test',
187 dependencies: [elementary, eio], 187 dependencies: [elementary, eio],
188) 188)
189 189
190executable('efl_ui_window_cnp_dnd_slave',
191 'efl_ui_window_cnp_dnd_slave.c',
192 dependencies: [elementary],
193)
194
190test('elementary-suite', elementary_suite, 195test('elementary-suite', elementary_suite,
191 env : test_env 196 env : test_env
192) 197)