forked from enlightenment/efl
Compare commits
14 Commits
master
...
devs/bu5hm
Author | SHA1 | Date |
---|---|---|
Xavi Artigas | 54b2ddd88e | |
Xavi Artigas | 8cdc8e9c8f | |
Xavi Artigas | c78841efcf | |
Vincent Torri | 9abd2604fa | |
Marcel Hollerbach | 61075d45cc | |
Marcel Hollerbach | 072a5fa525 | |
Marcel Hollerbach | 87901ea2ff | |
Marcel Hollerbach | 447fecd32e | |
Marcel Hollerbach | c391870366 | |
Marcel Hollerbach | 2951c69c49 | |
Marcel Hollerbach | 6b337ed19b | |
Marcel Hollerbach | ce070a8fdf | |
Marcel Hollerbach | ff4cba32c3 | |
Marcel Hollerbach | c872940bae |
|
@ -196,22 +196,6 @@ struct _Ecore_Cocoa_Event_Window_Destroy
|
||||||
Ecore_Cocoa_Object *cocoa_window; /**< Handler of the Cocoa window */
|
Ecore_Cocoa_Object *cocoa_window; /**< Handler of the Cocoa window */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef Ecore_Cocoa_Cnp_Type
|
|
||||||
* Type used to interact with the Cocoa pasteboard.
|
|
||||||
* It holds types that can apply to a context.
|
|
||||||
* @since 1.18
|
|
||||||
*/
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
ECORE_COCOA_CNP_TYPE_UNKNOWN = 0, /**< Undefined type */
|
|
||||||
ECORE_COCOA_CNP_TYPE_STRING = (1 << 0), /**< String type (pure text) */
|
|
||||||
ECORE_COCOA_CNP_TYPE_MARKUP = (1 << 1), /**< Elementary markup */
|
|
||||||
ECORE_COCOA_CNP_TYPE_IMAGE = (1 << 2), /**< Image (all formats) */
|
|
||||||
ECORE_COCOA_CNP_TYPE_HTML = (1 << 3) /**< HTML */
|
|
||||||
} Ecore_Cocoa_Cnp_Type;
|
|
||||||
|
|
||||||
|
|
||||||
/*============================================================================*
|
/*============================================================================*
|
||||||
* Core *
|
* Core *
|
||||||
*============================================================================*/
|
*============================================================================*/
|
||||||
|
@ -561,27 +545,22 @@ EAPI void ecore_cocoa_terminate_cb_set(Ecore_Cocoa_Terminate_Cb cb)
|
||||||
* Sets the clipboard of Cocoa (NSPasteboard)
|
* Sets the clipboard of Cocoa (NSPasteboard)
|
||||||
* @param data The contents to be set in the clipboard
|
* @param data The contents to be set in the clipboard
|
||||||
* @param size The size in bytes of @c data
|
* @param size The size in bytes of @c data
|
||||||
* @param type
|
* @param mine_type
|
||||||
* @return EINA_TRUE on success, EINA_FALSE on failure
|
* @return EINA_TRUE on success, EINA_FALSE on failure
|
||||||
*/
|
*/
|
||||||
EAPI Eina_Bool ecore_cocoa_clipboard_set(const void *data,
|
EAPI Eina_Bool ecore_cocoa_clipboard_set(const void *data,
|
||||||
int size,
|
int size,
|
||||||
Ecore_Cocoa_Cnp_Type type);
|
const char *mime_type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Gets the contents of the Cocoa clipboard
|
* Gets the contents of the Cocoa clipboard
|
||||||
* @param size Pointer used to retrieve the size of the received contents
|
* @param size Pointer used to retrieve the size of the received contents
|
||||||
* @param type The type of object to retrieve from the clipboard
|
* @param mine_type The type of object to retrieve from the clipboard
|
||||||
* @param retrieved_types The types of objects retrieved from the clipboard
|
|
||||||
* @return The data retrieved from the clipboard. NULL on failure
|
* @return The data retrieved from the clipboard. NULL on failure
|
||||||
*
|
*
|
||||||
* If @c type was ECORE_COCOA_CNP_TYPE_STRING or ECORE_COCOA_CNP_TYPE_MARKUP,
|
|
||||||
* @c retrieved_types will contain ECORE_COCOA_CNP_TYPE_STRING and the data
|
|
||||||
* will be a C string (char*) that must be freed after use.
|
|
||||||
*/
|
*/
|
||||||
EAPI void *ecore_cocoa_clipboard_get(int *size,
|
EAPI void *ecore_cocoa_clipboard_get(int *size,
|
||||||
Ecore_Cocoa_Cnp_Type type,
|
const char *mime_type)
|
||||||
Ecore_Cocoa_Cnp_Type *retrieved_types)
|
|
||||||
EINA_WARN_UNUSED_RESULT;
|
EINA_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -589,6 +568,11 @@ EAPI void *ecore_cocoa_clipboard_get(int *size,
|
||||||
*/
|
*/
|
||||||
EAPI void ecore_cocoa_clipboard_clear(void);
|
EAPI void ecore_cocoa_clipboard_clear(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns true when the clipboard contains data that can be received.
|
||||||
|
*/
|
||||||
|
EAPI Eina_Bool ecore_cocoa_clipboard_exists(void);
|
||||||
|
|
||||||
#endif /* EFL_BETA_API_SUPPORT */
|
#endif /* EFL_BETA_API_SUPPORT */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -9,16 +9,17 @@
|
||||||
#import "ecore_cocoa_app.h"
|
#import "ecore_cocoa_app.h"
|
||||||
|
|
||||||
EAPI Eina_Bool
|
EAPI Eina_Bool
|
||||||
ecore_cocoa_clipboard_set(const void *data,
|
ecore_cocoa_clipboard_set(const void *data,
|
||||||
int size,
|
int size,
|
||||||
Ecore_Cocoa_Cnp_Type type)
|
const char *raw_mime_type)
|
||||||
{
|
{
|
||||||
NSMutableArray *objects;
|
NSMutableArray *objects;
|
||||||
NSString *str = nil;
|
NSString *str = nil;
|
||||||
BOOL ok = YES;
|
BOOL ok = YES;
|
||||||
|
NSString *mime_type = [NSString stringWithUTF8String:raw_mime_type];
|
||||||
|
|
||||||
objects = [[NSMutableArray alloc] init];
|
objects = [[NSMutableArray alloc] init];
|
||||||
if (type & ECORE_COCOA_CNP_TYPE_STRING)
|
if ([mime_type hasPrefix:@"text/"])
|
||||||
{
|
{
|
||||||
str = [[NSString alloc] initWithBytes: data
|
str = [[NSString alloc] initWithBytes: data
|
||||||
length: size
|
length: size
|
||||||
|
@ -26,18 +27,9 @@ ecore_cocoa_clipboard_set(const void *data,
|
||||||
if (str)
|
if (str)
|
||||||
[objects addObject: str];
|
[objects addObject: str];
|
||||||
}
|
}
|
||||||
if (type & ECORE_COCOA_CNP_TYPE_MARKUP)
|
else
|
||||||
{
|
{
|
||||||
WRN("Markup CNP: NOT IMPLEMENTED");
|
ERR("Mimetype %s is not handled yet", raw_mime_type);
|
||||||
}
|
|
||||||
|
|
||||||
if (type & ECORE_COCOA_CNP_TYPE_IMAGE)
|
|
||||||
{
|
|
||||||
WRN("Image CNP: NOT IMPLEMENTED");
|
|
||||||
}
|
|
||||||
if (type & ECORE_COCOA_CNP_TYPE_HTML)
|
|
||||||
{
|
|
||||||
WRN("HTML CNP: NOT IMPLEMENTED");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write to pasteboard */
|
/* Write to pasteboard */
|
||||||
|
@ -54,35 +46,45 @@ ecore_cocoa_clipboard_set(const void *data,
|
||||||
return (ok) ? EINA_TRUE : EINA_FALSE;
|
return (ok) ? EINA_TRUE : EINA_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
ecore_cocoa_clipboard_exists(void)
|
||||||
|
{
|
||||||
|
NSDictionary *options;
|
||||||
|
NSPasteboard *pb;
|
||||||
|
NSArray *items;
|
||||||
|
NSMutableArray *classes;
|
||||||
|
|
||||||
|
classes = [[NSMutableArray alloc] init];
|
||||||
|
[classes addObject: [NSString class]]; // we only support strings for now
|
||||||
|
pb = [NSPasteboard generalPasteboard];
|
||||||
|
options = [NSDictionary dictionary];
|
||||||
|
return [pb canReadItemWithDataConformingToTypes: classes];
|
||||||
|
}
|
||||||
|
|
||||||
EAPI void *
|
EAPI void *
|
||||||
ecore_cocoa_clipboard_get(int *size,
|
ecore_cocoa_clipboard_get(int *size,
|
||||||
Ecore_Cocoa_Cnp_Type type,
|
const char *raw_mime_type)
|
||||||
Ecore_Cocoa_Cnp_Type *retrieved_types)
|
|
||||||
{
|
{
|
||||||
NSMutableArray *classes;
|
NSMutableArray *classes;
|
||||||
void *data;
|
void *data = NULL;
|
||||||
NSDictionary *options;
|
NSDictionary *options;
|
||||||
NSPasteboard *pb;
|
NSPasteboard *pb;
|
||||||
NSArray *items;
|
NSArray *items;
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
BOOL string_class = NO;
|
BOOL string_class = NO;
|
||||||
Ecore_Cocoa_Cnp_Type types = 0;
|
NSString *mime_type = [NSString stringWithUTF8String:raw_mime_type];
|
||||||
|
|
||||||
classes = [[NSMutableArray alloc] init];
|
classes = [[NSMutableArray alloc] init];
|
||||||
|
|
||||||
if (type & ECORE_COCOA_CNP_TYPE_STRING)
|
if ([mime_type hasPrefix:@"text/"])
|
||||||
{
|
{
|
||||||
string_class = YES;
|
string_class = YES;
|
||||||
[classes addObject: [NSString class]];
|
[classes addObject: [NSString class]];
|
||||||
}
|
}
|
||||||
if (type & ECORE_COCOA_CNP_TYPE_IMAGE)
|
else
|
||||||
{
|
{
|
||||||
WRN("Image CNP: NOT IMPLEMENTED");
|
ERR("Mimetype %s is not handled yet", raw_mime_type);
|
||||||
}
|
goto fail;
|
||||||
if (type & ECORE_COCOA_CNP_TYPE_HTML)
|
|
||||||
{
|
|
||||||
WRN("HTML CNP: NOT IMPLEMENTED");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([classes count] <= 0)
|
if ([classes count] <= 0)
|
||||||
|
@ -112,7 +114,7 @@ ecore_cocoa_clipboard_get(int *size,
|
||||||
NSString *str = [items objectAtIndex: 0];
|
NSString *str = [items objectAtIndex: 0];
|
||||||
data = (void *)[str UTF8String];
|
data = (void *)[str UTF8String];
|
||||||
len = [str lengthOfBytesUsingEncoding: NSUTF8StringEncoding];
|
len = [str lengthOfBytesUsingEncoding: NSUTF8StringEncoding];
|
||||||
data = eina_strndup((const char *)data, len);
|
data = strndup((const char *)data, len);
|
||||||
|
|
||||||
if (EINA_UNLIKELY(!data))
|
if (EINA_UNLIKELY(!data))
|
||||||
{
|
{
|
||||||
|
@ -120,7 +122,6 @@ ecore_cocoa_clipboard_get(int *size,
|
||||||
(const char *)data, len);
|
(const char *)data, len);
|
||||||
goto remove_fail;
|
goto remove_fail;
|
||||||
}
|
}
|
||||||
types |= ECORE_COCOA_CNP_TYPE_STRING;
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (type & ECORE_COCOA_CNP_TYPE_MARKUP)
|
if (type & ECORE_COCOA_CNP_TYPE_MARKUP)
|
||||||
|
@ -139,7 +140,7 @@ ecore_cocoa_clipboard_get(int *size,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!types)
|
if (!data)
|
||||||
{
|
{
|
||||||
ERR("No types retrieved!");
|
ERR("No types retrieved!");
|
||||||
goto remove_fail;
|
goto remove_fail;
|
||||||
|
@ -148,14 +149,12 @@ ecore_cocoa_clipboard_get(int *size,
|
||||||
[classes removeAllObjects];
|
[classes removeAllObjects];
|
||||||
|
|
||||||
if (size) *size = len;
|
if (size) *size = len;
|
||||||
if (retrieved_types) *retrieved_types = types;
|
|
||||||
return data;
|
return data;
|
||||||
|
|
||||||
remove_fail:
|
remove_fail:
|
||||||
[classes removeAllObjects];
|
[classes removeAllObjects];
|
||||||
fail:
|
fail:
|
||||||
if (size) *size = 0;
|
if (size) *size = 0;
|
||||||
if (retrieved_types) *retrieved_types = 0;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3669,6 +3669,216 @@ EAPI unsigned long ecore_evas_pixmap_colormap_get(const Ecore_Evas *ee);
|
||||||
*/
|
*/
|
||||||
EAPI int ecore_evas_pixmap_depth_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.
|
||||||
|
*
|
||||||
|
* @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_Cb)(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_Cb 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_Drag_State_Changed_Cb)(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_Drag_State_Changed_Cb 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_Drag_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_Drag_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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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_Drag_State_Changed_Cb, Ecore_Evas_Drag_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 +3895,4 @@ EAPI int ecore_evas_pixmap_depth_get(const Ecore_Evas *ee);
|
||||||
#define EAPI
|
#define EAPI
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -652,6 +652,10 @@ ecore_evas_init(void)
|
||||||
iface.del = _ecore_evas_animator_del;
|
iface.del = _ecore_evas_animator_del;
|
||||||
ecore_evas_object_animator_init(&iface);
|
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;
|
return _ecore_evas_init_count;
|
||||||
|
|
||||||
shutdown_ecore:
|
shutdown_ecore:
|
||||||
|
@ -3524,6 +3528,9 @@ _ecore_evas_free(Ecore_Evas *ee)
|
||||||
free(iface);
|
free(iface);
|
||||||
|
|
||||||
ee->engine.ifaces = NULL;
|
ee->engine.ifaces = NULL;
|
||||||
|
|
||||||
|
if (ee->fallback_interface)
|
||||||
|
fallback_selection_shutdown(ee);
|
||||||
free(ee);
|
free(ee);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5449,3 +5456,344 @@ _ecore_evas_animator_thaw(Ecore_Animator *in)
|
||||||
EINA_INLIST_GET(animator));
|
EINA_INLIST_GET(animator));
|
||||||
_ticking_start(ee);
|
_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_Cb 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_Drag_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_Drag_State_Changed_Cb cb)
|
||||||
|
{
|
||||||
|
ECORE_EVAS_CHECK(ee);
|
||||||
|
ee->func.fn_dnd_state_change = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI void
|
||||||
|
ecore_evas_callback_drop_drop_set(Ecore_Evas *ee, Ecore_Evas_Drop_Cb cb)
|
||||||
|
{
|
||||||
|
ECORE_EVAS_CHECK(ee);
|
||||||
|
ee->func.fn_dnd_drop = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Eina_Array *available_mime_types;
|
||||||
|
Eina_Position2D pos;
|
||||||
|
} Ecore_Evas_Active_Dnd;
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ecore_evas_active_dnd_free(Ecore_Evas_Active_Dnd *dnd)
|
||||||
|
{
|
||||||
|
eina_array_free(dnd->available_mime_types);
|
||||||
|
free(dnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI void
|
||||||
|
ecore_evas_dnd_enter(Ecore_Evas *ee, unsigned int seat, Eina_Iterator *available_types, Eina_Position2D pos)
|
||||||
|
{
|
||||||
|
Eina_Stringshare *s;
|
||||||
|
Ecore_Evas_Active_Dnd *dnd;
|
||||||
|
|
||||||
|
ECORE_EVAS_CHECK(ee);
|
||||||
|
if (!ee->active_drags)
|
||||||
|
{
|
||||||
|
ee->active_drags = eina_hash_int32_new((Eina_Free_Cb)_ecore_evas_active_dnd_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
dnd = calloc(1, sizeof(Ecore_Evas_Active_Dnd));
|
||||||
|
dnd->available_mime_types = eina_array_new(5);
|
||||||
|
eina_hash_add(ee->active_drags, &seat, dnd);
|
||||||
|
|
||||||
|
EINA_ITERATOR_FOREACH(available_types, s)
|
||||||
|
{
|
||||||
|
eina_array_push(dnd->available_mime_types, s);
|
||||||
|
}
|
||||||
|
eina_iterator_free(available_types);
|
||||||
|
|
||||||
|
if (ee->func.fn_dnd_state_change)
|
||||||
|
ee->func.fn_dnd_state_change(ee, seat, pos, EINA_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI void
|
||||||
|
ecore_evas_dnd_position_set(Ecore_Evas *ee, unsigned int seat, Eina_Position2D pos)
|
||||||
|
{
|
||||||
|
Ecore_Evas_Active_Dnd *dnd;
|
||||||
|
|
||||||
|
ECORE_EVAS_CHECK(ee);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(ee->active_drags);
|
||||||
|
dnd = eina_hash_find(ee->active_drags, &seat);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(dnd);
|
||||||
|
dnd->pos = pos;
|
||||||
|
if (ee->func.fn_dnd_motion)
|
||||||
|
ee->func.fn_dnd_motion(ee, seat, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI void
|
||||||
|
ecore_evas_dnd_leave(Ecore_Evas *ee, unsigned int seat, Eina_Position2D pos)
|
||||||
|
{
|
||||||
|
Ecore_Evas_Active_Dnd *dnd;
|
||||||
|
|
||||||
|
ECORE_EVAS_CHECK(ee);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(ee->active_drags);
|
||||||
|
dnd = eina_hash_find(ee->active_drags, &seat);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(dnd);
|
||||||
|
|
||||||
|
if (ee->func.fn_dnd_state_change)
|
||||||
|
ee->func.fn_dnd_state_change(ee, seat, pos, EINA_FALSE);
|
||||||
|
eina_hash_del(ee->active_drags, &seat, dnd);
|
||||||
|
if (eina_hash_population(ee->active_drags) == 0)
|
||||||
|
{
|
||||||
|
eina_hash_free(ee->active_drags);
|
||||||
|
ee->active_drags = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Position2D
|
||||||
|
ecore_evas_dnd_pos_get(Ecore_Evas *ee, unsigned int seat)
|
||||||
|
{
|
||||||
|
Ecore_Evas_Active_Dnd *dnd;
|
||||||
|
|
||||||
|
ECORE_EVAS_CHECK_GOTO(ee, err);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(ee->active_drags, EINA_POSITION2D(0, 0));
|
||||||
|
dnd = eina_hash_find(ee->active_drags, &seat);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(dnd, EINA_POSITION2D(0, 0));
|
||||||
|
|
||||||
|
return dnd->pos;
|
||||||
|
err:
|
||||||
|
return EINA_POSITION2D(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Accessor*
|
||||||
|
ecore_evas_drop_available_types_get(Ecore_Evas *ee, unsigned int seat)
|
||||||
|
{
|
||||||
|
Ecore_Evas_Active_Dnd *dnd;
|
||||||
|
|
||||||
|
ECORE_EVAS_CHECK_GOTO(ee, err);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(ee->active_drags, NULL);
|
||||||
|
dnd = eina_hash_find(ee->active_drags, &seat);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(dnd, NULL);
|
||||||
|
|
||||||
|
return eina_array_accessor_new(dnd->available_mime_types);
|
||||||
|
err:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Ecore.h>
|
||||||
|
#include "ecore_private.h"
|
||||||
|
#include "Ecore_Evas.h"
|
||||||
|
#include "ecore_evas_private.h"
|
||||||
|
#include <Efl_Core.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Ecore_Evas_Selection_Callbacks callbacks[ECORE_EVAS_SELECTION_BUFFER_LAST];
|
||||||
|
int seat;
|
||||||
|
} Ecore_Evas_Fallback_Selection_Data;
|
||||||
|
|
||||||
|
static Ecore_Evas_Fallback_Selection_Data data[ECORE_EVAS_SELECTION_BUFFER_LAST];
|
||||||
|
|
||||||
|
void
|
||||||
|
fallback_selection_shutdown(Ecore_Evas *ee)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
|
||||||
|
{
|
||||||
|
if (data->callbacks[i].cancel)
|
||||||
|
data->callbacks[i].cancel(ee, data->seat, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Bool
|
||||||
|
fallback_selection_claim(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection, Eina_Array *available_types, Ecore_Evas_Internal_Delivery delivery, Ecore_Evas_Internal_Cancel cancel)
|
||||||
|
{
|
||||||
|
Ecore_Evas_Selection_Callbacks *callbacks = &data->callbacks[selection];
|
||||||
|
|
||||||
|
if (callbacks->cancel)
|
||||||
|
{
|
||||||
|
callbacks->cancel(ee, data->seat, selection);
|
||||||
|
eina_array_free(callbacks->available_types);
|
||||||
|
}
|
||||||
|
|
||||||
|
callbacks->delivery = delivery;
|
||||||
|
callbacks->cancel = cancel;
|
||||||
|
callbacks->available_types = available_types;
|
||||||
|
data->seat = seat;
|
||||||
|
|
||||||
|
if (ee->func.fn_selection_changed)
|
||||||
|
ee->func.fn_selection_changed(ee, seat, selection);
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Bool
|
||||||
|
fallback_selection_has_owner(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection EINA_UNUSED)
|
||||||
|
{
|
||||||
|
return EINA_FALSE; //if the real selection buffer does not contain it, then we dont know it either.
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Stringshare*
|
||||||
|
available_types(Eina_Array *acceptable_types, Eina_Array *available_types)
|
||||||
|
{
|
||||||
|
unsigned int found_type_id = INT_MAX;
|
||||||
|
Eina_Stringshare *found_type = NULL;
|
||||||
|
Eina_Stringshare *type;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < eina_array_count_get(acceptable_types); ++i)
|
||||||
|
{
|
||||||
|
unsigned int out = -1;
|
||||||
|
|
||||||
|
type = eina_array_data_get(acceptable_types, i);
|
||||||
|
|
||||||
|
if (!eina_array_find(available_types, type, &out))
|
||||||
|
continue;
|
||||||
|
if (out >= found_type_id)
|
||||||
|
continue;
|
||||||
|
found_type_id = out;
|
||||||
|
found_type = type;
|
||||||
|
eina_stringshare_del(type);
|
||||||
|
}
|
||||||
|
eina_array_free(acceptable_types);
|
||||||
|
|
||||||
|
return found_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Future*
|
||||||
|
fallback_selection_request(Ecore_Evas *ee EINA_UNUSED, unsigned int seat, Ecore_Evas_Selection_Buffer selection, Eina_Array *acceptable_type)
|
||||||
|
{
|
||||||
|
Ecore_Evas_Selection_Callbacks callbacks = data->callbacks[selection];
|
||||||
|
Eina_Content *result;
|
||||||
|
Eina_Stringshare *serving_type;
|
||||||
|
Eina_Rw_Slice slice_data;
|
||||||
|
Eina_Value value;
|
||||||
|
|
||||||
|
if (!callbacks.delivery)
|
||||||
|
return eina_future_resolved(efl_loop_future_scheduler_get(efl_main_loop_get()), eina_value_int_init(0));
|
||||||
|
|
||||||
|
serving_type = available_types(acceptable_type, callbacks.available_types);
|
||||||
|
if (!serving_type)
|
||||||
|
return NULL; //Silent return cause we cannot deliver a good type
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_FALSE_RETURN_VAL(callbacks.delivery(ee, seat, selection, serving_type, &slice_data), NULL);
|
||||||
|
result = eina_content_new(eina_rw_slice_slice_get(slice_data), serving_type);
|
||||||
|
value = eina_value_content_init(result);
|
||||||
|
eina_content_free(result);
|
||||||
|
|
||||||
|
return eina_future_resolved(efl_loop_future_scheduler_get(efl_main_loop_get()), value);
|
||||||
|
}
|
||||||
|
Eina_Bool
|
||||||
|
fallback_dnd_start(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, Eina_Array *available_types EINA_UNUSED, Ecore_Evas *drag_rep EINA_UNUSED, Ecore_Evas_Internal_Delivery delivery EINA_UNUSED, Ecore_Evas_Internal_Cancel cancel EINA_UNUSED, const char* action EINA_UNUSED)
|
||||||
|
{
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Bool
|
||||||
|
fallback_dnd_stop(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED)
|
||||||
|
{
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
|
@ -33,6 +33,10 @@
|
||||||
|
|
||||||
EAPI extern int _ecore_evas_log_dom;
|
EAPI 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
|
#ifdef ECORE_EVAS_DEFAULT_LOG_COLOR
|
||||||
# undef ECORE_EVAS_DEFAULT_LOG_COLOR
|
# undef ECORE_EVAS_DEFAULT_LOG_COLOR
|
||||||
#endif
|
#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_Aux_Hint Ecore_Evas_Aux_Hint;
|
||||||
typedef struct _Ecore_Evas_Cursor Ecore_Evas_Cursor;
|
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 */
|
/* Engines interfaces */
|
||||||
struct _Ecore_Evas_Engine_Func
|
struct _Ecore_Evas_Engine_Func
|
||||||
{
|
{
|
||||||
|
@ -171,6 +182,12 @@ struct _Ecore_Evas_Engine_Func
|
||||||
Eina_Bool (*fn_prepare)(Ecore_Evas *ee);
|
Eina_Bool (*fn_prepare)(Ecore_Evas *ee);
|
||||||
|
|
||||||
double (*fn_last_tick_get)(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
|
struct _Ecore_Evas_Interface
|
||||||
|
@ -202,6 +219,11 @@ struct _Ecore_Evas_Cursor {
|
||||||
int pos_y;
|
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
|
struct _Ecore_Evas
|
||||||
{
|
{
|
||||||
EINA_INLIST;
|
EINA_INLIST;
|
||||||
|
@ -224,6 +246,8 @@ struct _Ecore_Evas
|
||||||
|
|
||||||
Eina_List *vnc_server; /* @since 1.19 */
|
Eina_List *vnc_server; /* @since 1.19 */
|
||||||
|
|
||||||
|
Eina_Hash *selection_buffers;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int x, y, w, h;
|
int x, y, w, h;
|
||||||
} req;
|
} req;
|
||||||
|
@ -323,6 +347,10 @@ struct _Ecore_Evas
|
||||||
void (*fn_focus_device_out) (Ecore_Evas *ee, Efl_Input_Device *seat);
|
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_in) (Ecore_Evas *ee, Efl_Input_Device *mouse);
|
||||||
void (*fn_device_mouse_out) (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;
|
} func;
|
||||||
|
|
||||||
Ecore_Evas_Engine engine;
|
Ecore_Evas_Engine engine;
|
||||||
|
@ -353,6 +381,14 @@ struct _Ecore_Evas
|
||||||
unsigned char rotation_changed : 1;
|
unsigned char rotation_changed : 1;
|
||||||
} delayed;
|
} delayed;
|
||||||
|
|
||||||
|
Eina_Hash *active_drags;
|
||||||
|
struct {
|
||||||
|
Ecore_Evas *rep;
|
||||||
|
void *data;
|
||||||
|
Ecore_Evas_Drag_Finished_Cb free;
|
||||||
|
Eina_Bool accepted;
|
||||||
|
} drag;
|
||||||
|
|
||||||
int refcount;
|
int refcount;
|
||||||
//#define ECORE_EVAS_ASYNC_RENDER_DEBUG 1 /* TODO: remove me */
|
//#define ECORE_EVAS_ASYNC_RENDER_DEBUG 1 /* TODO: remove me */
|
||||||
#ifdef ECORE_EVAS_ASYNC_RENDER_DEBUG
|
#ifdef ECORE_EVAS_ASYNC_RENDER_DEBUG
|
||||||
|
@ -374,6 +410,7 @@ struct _Ecore_Evas
|
||||||
unsigned char first_frame : 1;
|
unsigned char first_frame : 1;
|
||||||
unsigned char self_del : 1;
|
unsigned char self_del : 1;
|
||||||
unsigned char evas_dying : 1;
|
unsigned char evas_dying : 1;
|
||||||
|
unsigned char fallback_interface : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Ecore_Evas_Aux_Hint
|
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 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_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
|
#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_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);
|
EAPI Ecore_Evas *_wayland_egl_new(const char *disp_name, Ecore_Window parent, int x, int y, int w, int h, Eina_Bool frame, const int *opt);
|
||||||
|
|
|
@ -23,7 +23,8 @@ ecore_evas_src = [
|
||||||
'ecore_evas_cocoa.h',
|
'ecore_evas_cocoa.h',
|
||||||
'ecore_evas_win32.h',
|
'ecore_evas_win32.h',
|
||||||
'ecore_evas_x11.h',
|
'ecore_evas_x11.h',
|
||||||
'ecore_evas_util.c'
|
'ecore_evas_util.c',
|
||||||
|
'ecore_evas_fallback_selection.c'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -215,21 +215,6 @@ typedef enum
|
||||||
ECORE_WIN32_DND_EVENT_DROP = 4 /**< Drop */
|
ECORE_WIN32_DND_EVENT_DROP = 4 /**< Drop */
|
||||||
} Ecore_Win32_DnD_State;
|
} Ecore_Win32_DnD_State;
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef Ecore_Win32_Selection
|
|
||||||
* Type of the selection.
|
|
||||||
*
|
|
||||||
* @since 1.16
|
|
||||||
*/
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
ECORE_WIN32_SELECTION_PRIMARY,
|
|
||||||
ECORE_WIN32_SELECTION_SECONDARY,
|
|
||||||
ECORE_WIN32_SELECTION_DND,
|
|
||||||
ECORE_WIN32_SELECTION_CLIPBOARD,
|
|
||||||
ECORE_WIN32_SELECTION_OTHER
|
|
||||||
} Ecore_Win32_Selection;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef Ecore_Win32_Window
|
* @typedef Ecore_Win32_Window
|
||||||
* Abstract type for a window.
|
* Abstract type for a window.
|
||||||
|
@ -326,7 +311,7 @@ typedef struct _Ecore_Win32_Event_Window_Delete_Request Ecore_Win32_Event_Window
|
||||||
* @typedef Ecore_Win32_Event_Selection_Clear
|
* @typedef Ecore_Win32_Event_Selection_Clear
|
||||||
* Event sent when the content of the clipboard has been removed.
|
* Event sent when the content of the clipboard has been removed.
|
||||||
*
|
*
|
||||||
* @since 1.16
|
* @since 1.24
|
||||||
*/
|
*/
|
||||||
typedef struct _Ecore_Win32_Event_Selection_Clear Ecore_Win32_Event_Selection_Clear;
|
typedef struct _Ecore_Win32_Event_Selection_Clear Ecore_Win32_Event_Selection_Clear;
|
||||||
|
|
||||||
|
@ -334,7 +319,7 @@ typedef struct _Ecore_Win32_Event_Selection_Clear Ecore_Win32_Event_Selection_Cl
|
||||||
* @typedef Ecore_Win32_Event_Selection_Notify
|
* @typedef Ecore_Win32_Event_Selection_Notify
|
||||||
* Event sent when the content of the clipboard has been added.
|
* Event sent when the content of the clipboard has been added.
|
||||||
*
|
*
|
||||||
* @since 1.16
|
* @since 1.24
|
||||||
*/
|
*/
|
||||||
typedef struct _Ecore_Win32_Event_Selection_Notify Ecore_Win32_Event_Selection_Notify;
|
typedef struct _Ecore_Win32_Event_Selection_Notify Ecore_Win32_Event_Selection_Notify;
|
||||||
|
|
||||||
|
@ -490,26 +475,26 @@ struct _Ecore_Win32_Event_Window_Delete_Request
|
||||||
* @struct _Ecore_Win32_Event_Selection_Clear
|
* @struct _Ecore_Win32_Event_Selection_Clear
|
||||||
* Event sent when the content of the clipboard has been removed.
|
* Event sent when the content of the clipboard has been removed.
|
||||||
*
|
*
|
||||||
* @since 1.16
|
* @since 1.24
|
||||||
*/
|
*/
|
||||||
struct _Ecore_Win32_Event_Selection_Clear
|
struct _Ecore_Win32_Event_Selection_Clear
|
||||||
{
|
{
|
||||||
Ecore_Win32_Window *window; /**< The window that received the event */
|
Ecore_Win32_Window *window; /**< The window that received the event */
|
||||||
unsigned long timestamp; /**< The time the event occurred */
|
unsigned long timestamp; /**< The time the event occurred */
|
||||||
Ecore_Win32_Selection selection; /**< The type of the selection */
|
char *selection; /**< The type of the selection */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @struct _Ecore_Win32_Event_Selection_Notify
|
* @struct _Ecore_Win32_Event_Selection_Notify
|
||||||
* Event sent when the content of the clipboard has been added.
|
* Event sent when the content of the clipboard has been added.
|
||||||
*
|
*
|
||||||
* @since 1.16
|
* @since 1.24
|
||||||
*/
|
*/
|
||||||
struct _Ecore_Win32_Event_Selection_Notify
|
struct _Ecore_Win32_Event_Selection_Notify
|
||||||
{
|
{
|
||||||
Ecore_Win32_Window *window; /**< The window that received the event */
|
Ecore_Win32_Window *window; /**< The window that received the event */
|
||||||
unsigned long timestamp; /**< The time the event occurred */
|
unsigned long timestamp; /**< The time the event occurred */
|
||||||
Ecore_Win32_Selection selection; /**< The type of the selection */
|
char *selection; /**< The type of the selection */
|
||||||
void *data; /**< The data of the selection */
|
void *data; /**< The data of the selection */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -698,6 +683,7 @@ EAPI void ecore_win32_dnd_unregister_drop_target(Ecore_Win32_Window *window
|
||||||
* @param[in] window The window that owns the clipboard.
|
* @param[in] window The window that owns the clipboard.
|
||||||
* @param[in] data The data to set.
|
* @param[in] data The data to set.
|
||||||
* @param[in] size The size of the data.
|
* @param[in] size The size of the data.
|
||||||
|
* @param[in] mime_type The mime type describing the data in the clipboard.
|
||||||
* @return #EINA_TRUE on success, #EINA_FALSE otherwise.
|
* @return #EINA_TRUE on success, #EINA_FALSE otherwise.
|
||||||
*
|
*
|
||||||
* This function sets @p data of size @p size in the clipboard owned by
|
* This function sets @p data of size @p size in the clipboard owned by
|
||||||
|
@ -705,11 +691,12 @@ EAPI void ecore_win32_dnd_unregister_drop_target(Ecore_Win32_Window *window
|
||||||
* #EINA_FALSE otherwise. If @p window or @p data are @c NULL, or @p size
|
* #EINA_FALSE otherwise. If @p window or @p data are @c NULL, or @p size
|
||||||
* is less than or equal to 0, this function returns #EINA_FALSE.
|
* is less than or equal to 0, this function returns #EINA_FALSE.
|
||||||
*
|
*
|
||||||
* @since 1.16
|
* @since 1.24
|
||||||
*/
|
*/
|
||||||
EAPI Eina_Bool ecore_win32_clipboard_set(const Ecore_Win32_Window *window,
|
EAPI Eina_Bool ecore_win32_clipboard_set(const Ecore_Win32_Window *window,
|
||||||
const void *data,
|
const void *data,
|
||||||
int size);
|
size_t size,
|
||||||
|
const char *mime_type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get data from the clipboard.
|
* @brief Get data from the clipboard.
|
||||||
|
@ -717,6 +704,7 @@ EAPI Eina_Bool ecore_win32_clipboard_set(const Ecore_Win32_Window *window,
|
||||||
* @param[in] window The window that owns the clipboard.
|
* @param[in] window The window that owns the clipboard.
|
||||||
* @param[out] data The retrieved data.
|
* @param[out] data The retrieved data.
|
||||||
* @param[out] size The size of the data.
|
* @param[out] size The size of the data.
|
||||||
|
* @param[in] mime_type The mime type describing the data in the clipboard.
|
||||||
* @return #EINA_TRUE on success, #EINA_FALSE otherwise.
|
* @return #EINA_TRUE on success, #EINA_FALSE otherwise.
|
||||||
*
|
*
|
||||||
* This function gets @p data of size @p size from the clipboard owned by
|
* This function gets @p data of size @p size from the clipboard owned by
|
||||||
|
@ -724,25 +712,24 @@ EAPI Eina_Bool ecore_win32_clipboard_set(const Ecore_Win32_Window *window,
|
||||||
* #EINA_FALSE otherwise. If @p window is @c NULL, this function returns
|
* #EINA_FALSE otherwise. If @p window is @c NULL, this function returns
|
||||||
* #EINA_FALSE. @p data and @p size must be valid buffers.
|
* #EINA_FALSE. @p data and @p size must be valid buffers.
|
||||||
*
|
*
|
||||||
* @since 1.16
|
* @since 1.24
|
||||||
*/
|
*/
|
||||||
EAPI Eina_Bool ecore_win32_clipboard_get(const Ecore_Win32_Window *window,
|
EAPI void * ecore_win32_clipboard_get(const Ecore_Win32_Window *window,
|
||||||
void **data,
|
size_t *size,
|
||||||
int *size);
|
const char *mime_type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Cleat the clipboard.
|
* @brief Cleat the clipboard.
|
||||||
*
|
*
|
||||||
* @param[in] window The window that owns the clipboard.
|
* @param[in] window The window that owns the clipboard.
|
||||||
* @return #EINA_TRUE on success, #EINA_FALSE otherwise.
|
|
||||||
*
|
*
|
||||||
* This function clears the clipboard owned by @p window. This
|
* This function clears the clipboard owned by @p window. This
|
||||||
* function returns #EINA_TRUE on success, and #EINA_FALSE otherwise.
|
* function returns #EINA_TRUE on success, and #EINA_FALSE otherwise.
|
||||||
* If @p window is @c NULL, this function returns #EINA_FALSE.
|
* If @p window is @c NULL, this function returns #EINA_FALSE.
|
||||||
*
|
*
|
||||||
* @since 1.16
|
* @since 1.24
|
||||||
*/
|
*/
|
||||||
EAPI Eina_Bool ecore_win32_clipboard_clear(const Ecore_Win32_Window *window);
|
EAPI void ecore_win32_clipboard_clear(const Ecore_Win32_Window *window);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef Ecore_Win32_Monitor
|
* @typedef Ecore_Win32_Monitor
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#undef WIN32_LEAN_AND_MEAN
|
#undef WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
|
#include <evil_private.h> /* utf-8 and utf-16 conversion */
|
||||||
#include <Eina.h>
|
#include <Eina.h>
|
||||||
|
|
||||||
#include "Ecore_Win32.h"
|
#include "Ecore_Win32.h"
|
||||||
|
@ -39,10 +40,12 @@
|
||||||
EAPI Eina_Bool
|
EAPI Eina_Bool
|
||||||
ecore_win32_clipboard_set(const Ecore_Win32_Window *window,
|
ecore_win32_clipboard_set(const Ecore_Win32_Window *window,
|
||||||
const void *data,
|
const void *data,
|
||||||
int size)
|
size_t size,
|
||||||
|
const char *mime_type)
|
||||||
{
|
{
|
||||||
HGLOBAL global;
|
HGLOBAL global;
|
||||||
char *d;
|
char *d;
|
||||||
|
Eina_Bool res = EINA_FALSE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See: https://msdn.microsoft.com/en-us/library/windows/desktop/ms649016%28v=vs.85%29.aspx#_win32_Copying_Information_to_the_Clipboard
|
* See: https://msdn.microsoft.com/en-us/library/windows/desktop/ms649016%28v=vs.85%29.aspx#_win32_Copying_Information_to_the_Clipboard
|
||||||
|
@ -54,47 +57,78 @@ ecore_win32_clipboard_set(const Ecore_Win32_Window *window,
|
||||||
|
|
||||||
INF("setting data to the clipboard");
|
INF("setting data to the clipboard");
|
||||||
|
|
||||||
if (!window || !data || (size <= 0))
|
if (!eina_str_has_prefix(mime_type, "text/"))
|
||||||
return EINA_FALSE;
|
{
|
||||||
|
ERR("Mimetype %s is not handled yet", mime_type);
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!OpenClipboard(window->window))
|
if (!window || !data || (size <= 0) || !OpenClipboard(window->window))
|
||||||
return EINA_FALSE;
|
return EINA_FALSE;
|
||||||
|
|
||||||
if (!EmptyClipboard())
|
if (!EmptyClipboard())
|
||||||
goto close_clipboard;
|
goto close_clipboard;
|
||||||
|
|
||||||
global = GlobalAlloc(GMEM_MOVEABLE, size + 1);
|
if (eina_str_has_prefix(mime_type, "text/"))
|
||||||
if (!global)
|
{
|
||||||
goto close_clipboard;
|
wchar_t *text16;
|
||||||
|
size_t size16;
|
||||||
|
|
||||||
d = (char *)GlobalLock(global);
|
/* CF_TEXT (UTF-8) */
|
||||||
if (!d)
|
|
||||||
goto unlock_global;
|
|
||||||
|
|
||||||
memcpy(d, data, size);
|
global = GlobalAlloc(GMEM_MOVEABLE, size);
|
||||||
d[size] = '\0';
|
if (global)
|
||||||
GlobalUnlock(global);
|
{
|
||||||
SetClipboardData(CF_TEXT, global);
|
d = (char *)GlobalLock(global);
|
||||||
CloseClipboard();
|
if (d)
|
||||||
|
{
|
||||||
|
memcpy(d, data, size);
|
||||||
|
GlobalUnlock(global);
|
||||||
|
SetClipboardData(CF_TEXT, global);
|
||||||
|
res = EINA_TRUE;
|
||||||
|
}
|
||||||
|
GlobalUnlock(global);
|
||||||
|
}
|
||||||
|
|
||||||
return EINA_TRUE;
|
/* CF_UNICODETEXT (UTF-16) */
|
||||||
|
|
||||||
|
text16 = evil_utf8_to_utf16(data);
|
||||||
|
if (text16)
|
||||||
|
{
|
||||||
|
size16 = (wcslen(text16) + 1) * sizeof(wchar_t);
|
||||||
|
|
||||||
|
global = GlobalAlloc(GMEM_MOVEABLE, size16);
|
||||||
|
if (global)
|
||||||
|
{
|
||||||
|
d = (char *)GlobalLock(global);
|
||||||
|
if (d)
|
||||||
|
{
|
||||||
|
memcpy(d, text16, size16);
|
||||||
|
SetClipboardData(CF_UNICODETEXT, global);
|
||||||
|
free(text16);
|
||||||
|
res = EINA_TRUE;
|
||||||
|
}
|
||||||
|
GlobalUnlock(global);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(text16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unlock_global:
|
|
||||||
GlobalUnlock(global);
|
|
||||||
close_clipboard:
|
close_clipboard:
|
||||||
CloseClipboard();
|
CloseClipboard();
|
||||||
|
|
||||||
return EINA_FALSE;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
EAPI Eina_Bool
|
EAPI void *
|
||||||
ecore_win32_clipboard_get(const Ecore_Win32_Window *window,
|
ecore_win32_clipboard_get(const Ecore_Win32_Window *window,
|
||||||
void **data,
|
size_t *size,
|
||||||
int *size)
|
const char *mime_type)
|
||||||
{
|
{
|
||||||
HGLOBAL global;
|
HGLOBAL global;
|
||||||
|
void *data;
|
||||||
void *d;
|
void *d;
|
||||||
void *p;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See https://msdn.microsoft.com/en-us/library/windows/desktop/ms649016%28v=vs.85%29.aspx#_win32_Pasting_Information_from_the_Clipboard
|
* See https://msdn.microsoft.com/en-us/library/windows/desktop/ms649016%28v=vs.85%29.aspx#_win32_Pasting_Information_from_the_Clipboard
|
||||||
|
@ -107,80 +141,93 @@ ecore_win32_clipboard_get(const Ecore_Win32_Window *window,
|
||||||
|
|
||||||
INF("getting data from the clipboard");
|
INF("getting data from the clipboard");
|
||||||
|
|
||||||
if (!window)
|
|
||||||
return EINA_FALSE;
|
|
||||||
|
|
||||||
if (!IsClipboardFormatAvailable(CF_TEXT))
|
|
||||||
return EINA_FALSE;
|
|
||||||
|
|
||||||
if (!OpenClipboard(window->window))
|
|
||||||
goto set_val;
|
|
||||||
|
|
||||||
/* { */
|
|
||||||
/* UINT fmt = 0; */
|
|
||||||
|
|
||||||
/* while (1) */
|
|
||||||
/* { */
|
|
||||||
/* fmt = EnumClipboardFormats(fmt); */
|
|
||||||
/* printf(" $ Format : %x\n", fmt); */
|
|
||||||
/* if (!fmt) */
|
|
||||||
/* break; */
|
|
||||||
/* } */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
global = GetClipboardData(CF_TEXT);
|
|
||||||
if (!global)
|
|
||||||
goto close_clipboard;
|
|
||||||
|
|
||||||
d = GlobalLock(global);
|
|
||||||
if (!d)
|
|
||||||
goto unlock_global;
|
|
||||||
|
|
||||||
*size = strlen(d);
|
|
||||||
p = malloc(*size);
|
|
||||||
if (!p)
|
|
||||||
goto unlock_global;
|
|
||||||
|
|
||||||
memcpy(p, d, *size);
|
|
||||||
*data = p;
|
|
||||||
GlobalUnlock(global);
|
|
||||||
CloseClipboard();
|
|
||||||
|
|
||||||
return EINA_TRUE;
|
|
||||||
|
|
||||||
unlock_global:
|
|
||||||
GlobalUnlock(global);
|
|
||||||
close_clipboard:
|
|
||||||
CloseClipboard();
|
|
||||||
set_val:
|
|
||||||
*data = NULL;
|
|
||||||
*size = 0;
|
*size = 0;
|
||||||
|
|
||||||
return EINA_FALSE;
|
if (!eina_str_has_prefix(mime_type, "text/"))
|
||||||
|
{
|
||||||
|
ERR("Mimetype %s is not handled yet", mime_type);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!window || !OpenClipboard(window->window))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
UINT fmt = 0;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
fmt = EnumClipboardFormats(fmt);
|
||||||
|
fprintf(stderr, " $ Format : %x\n", fmt);
|
||||||
|
fflush(stderr);
|
||||||
|
if (!fmt)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (eina_str_has_prefix(mime_type, "text/"))
|
||||||
|
{
|
||||||
|
/* first check if UTF-16 text is available */
|
||||||
|
global = GetClipboardData(CF_UNICODETEXT);
|
||||||
|
if (global)
|
||||||
|
{
|
||||||
|
d = GlobalLock(global);
|
||||||
|
if (d)
|
||||||
|
{
|
||||||
|
data = evil_utf16_to_utf8(d);
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
*size = strlen(data);
|
||||||
|
GlobalUnlock(global);
|
||||||
|
CloseClipboard();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* otherwise, we unlock global and try CF_TEXT (UTF-8/ANSI) */
|
||||||
|
GlobalUnlock(global);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* secondly check if UTF-8/ANSI text is available */
|
||||||
|
global = GetClipboardData(CF_TEXT);
|
||||||
|
if (global)
|
||||||
|
{
|
||||||
|
d = GlobalLock(global);
|
||||||
|
if (d)
|
||||||
|
{
|
||||||
|
*size = strlen(d) + 1;
|
||||||
|
data = malloc(*size);
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
memcpy(data, d, *size);
|
||||||
|
GlobalUnlock(global);
|
||||||
|
CloseClipboard();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalUnlock(global);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseClipboard();
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
EAPI Eina_Bool
|
EAPI void
|
||||||
ecore_win32_clipboard_clear(const Ecore_Win32_Window *window)
|
ecore_win32_clipboard_clear(const Ecore_Win32_Window *window)
|
||||||
{
|
{
|
||||||
INF("clearing the clipboard");
|
INF("clearing the clipboard");
|
||||||
|
|
||||||
if (!window)
|
if (!window || !OpenClipboard(window->window))
|
||||||
return EINA_FALSE;
|
return;
|
||||||
|
|
||||||
if (!OpenClipboard(window->window))
|
|
||||||
return EINA_FALSE;
|
|
||||||
|
|
||||||
if (!EmptyClipboard())
|
|
||||||
goto close_clipboard;
|
|
||||||
|
|
||||||
|
EmptyClipboard();
|
||||||
CloseClipboard();
|
CloseClipboard();
|
||||||
|
|
||||||
return EINA_TRUE;
|
|
||||||
|
|
||||||
close_clipboard:
|
|
||||||
CloseClipboard();
|
|
||||||
|
|
||||||
return EINA_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1958,66 +1958,104 @@ _ecore_win32_event_handle_selection_notify(Ecore_Win32_Callback_Data *msg)
|
||||||
{
|
{
|
||||||
Ecore_Win32_Event_Selection_Notify *e;
|
Ecore_Win32_Event_Selection_Notify *e;
|
||||||
HGLOBAL global;
|
HGLOBAL global;
|
||||||
char *str;
|
|
||||||
|
|
||||||
INF("selection_notify");
|
INF("selection_notify");
|
||||||
|
|
||||||
|
e = calloc(1, sizeof(Ecore_Win32_Event_Selection_Notify));
|
||||||
|
if (!e) return;
|
||||||
|
|
||||||
|
e->window = (void *)GetWindowLongPtr(msg->window, GWLP_USERDATA);
|
||||||
|
e->timestamp = _ecore_win32_event_last_time;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we have text data in clipboard but no data before,
|
* we have data in clipboard but no data before,
|
||||||
* so text data has just been added
|
* so data has just been added
|
||||||
*/
|
*/
|
||||||
if (IsClipboardFormatAvailable(CF_TEXT) && !_ecore_win32_clipboard_has_data)
|
if (!_ecore_win32_clipboard_has_data)
|
||||||
{
|
{
|
||||||
e = calloc(1, sizeof(Ecore_Win32_Event_Selection_Notify));
|
/* if case someone else is owning the clipboard, we can't do anything */
|
||||||
if (!e) return;
|
|
||||||
|
|
||||||
e->window = (void *)GetWindowLongPtr(msg->window, GWLP_USERDATA);
|
|
||||||
e->timestamp = _ecore_win32_event_last_time;
|
|
||||||
e->selection = ECORE_WIN32_SELECTION_CLIPBOARD;
|
|
||||||
|
|
||||||
if (!OpenClipboard(msg->window))
|
if (!OpenClipboard(msg->window))
|
||||||
goto free_e;
|
|
||||||
|
|
||||||
global = GetClipboardData(CF_TEXT);
|
|
||||||
if (!global)
|
|
||||||
goto close_clipboard;
|
|
||||||
|
|
||||||
str = GlobalLock(global);
|
|
||||||
if (str)
|
|
||||||
{
|
{
|
||||||
e->data = strdup(str);
|
free(e);
|
||||||
GlobalUnlock(global);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsClipboardFormatAvailable(CF_UNICODETEXT))
|
||||||
|
{
|
||||||
|
global = GetClipboardData(CF_UNICODETEXT);
|
||||||
|
if (global)
|
||||||
|
{
|
||||||
|
e->selection = strdup("text/plain;charset=utf-8");
|
||||||
|
if (e->selection)
|
||||||
|
{
|
||||||
|
wchar_t *d;
|
||||||
|
|
||||||
|
d = (wchar_t *)GlobalLock(global);
|
||||||
|
if (d)
|
||||||
|
e->data = evil_utf16_to_utf8(d);
|
||||||
|
|
||||||
|
GlobalUnlock(global);
|
||||||
|
if (e->data)
|
||||||
|
{
|
||||||
|
ecore_event_add(ECORE_WIN32_EVENT_SELECTION_NOTIFY, e, NULL, NULL);
|
||||||
|
_ecore_win32_clipboard_has_data = EINA_TRUE;
|
||||||
|
CloseClipboard();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsClipboardFormatAvailable(CF_TEXT))
|
||||||
|
{
|
||||||
|
global = GetClipboardData(CF_TEXT);
|
||||||
|
if (global)
|
||||||
|
{
|
||||||
|
e->selection = strdup("text/plain;charset=utf-8");
|
||||||
|
if (e->selection)
|
||||||
|
{
|
||||||
|
char *d;
|
||||||
|
|
||||||
|
d = (char *)GlobalLock(global);
|
||||||
|
if (d)
|
||||||
|
e->data = strdup(d);
|
||||||
|
|
||||||
|
GlobalUnlock(global);
|
||||||
|
if (e->data)
|
||||||
|
{
|
||||||
|
ecore_event_add(ECORE_WIN32_EVENT_SELECTION_NOTIFY, e, NULL, NULL);
|
||||||
|
|
||||||
|
_ecore_win32_clipboard_has_data = EINA_TRUE;
|
||||||
|
CloseClipboard();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(e->data);
|
||||||
|
free(e->selection);
|
||||||
|
free(e);
|
||||||
CloseClipboard();
|
CloseClipboard();
|
||||||
|
|
||||||
ecore_event_add(ECORE_WIN32_EVENT_SELECTION_NOTIFY, e, NULL, NULL);
|
|
||||||
|
|
||||||
_ecore_win32_clipboard_has_data = EINA_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we have no more text data in clipboard and data before,
|
* we have no more text data in clipboard and data before,
|
||||||
* so text data has just been removed
|
* so text data has just been removed
|
||||||
*/
|
*/
|
||||||
if (!IsClipboardFormatAvailable(CF_TEXT) && _ecore_win32_clipboard_has_data)
|
if (_ecore_win32_clipboard_has_data)
|
||||||
{
|
{
|
||||||
e = calloc(1, sizeof(Ecore_Win32_Event_Selection_Clear));
|
if (!IsClipboardFormatAvailable(CF_UNICODETEXT) ||
|
||||||
if (!e) return;
|
!IsClipboardFormatAvailable(CF_TEXT))
|
||||||
|
{
|
||||||
e->window = (void *)GetWindowLongPtr(msg->window, GWLP_USERDATA);
|
e->selection = strdup("text/plain;charset=utf-8");
|
||||||
e->timestamp = _ecore_win32_event_last_time;
|
if (e->selection)
|
||||||
e->selection = ECORE_WIN32_SELECTION_CLIPBOARD;
|
{
|
||||||
|
ecore_event_add(ECORE_WIN32_EVENT_SELECTION_CLEAR, e, NULL, NULL);
|
||||||
ecore_event_add(ECORE_WIN32_EVENT_SELECTION_CLEAR, e, NULL, NULL);
|
_ecore_win32_clipboard_has_data = EINA_FALSE;
|
||||||
|
return;
|
||||||
_ecore_win32_clipboard_has_data = EINA_FALSE;
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
close_clipboard:
|
|
||||||
CloseClipboard();
|
|
||||||
free_e:
|
|
||||||
free(e);
|
free(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2444,6 +2444,15 @@ EAPI void ecore_x_root_screen_barriers_set(Ecore_X_Rectangle *scre
|
||||||
*/
|
*/
|
||||||
EAPI Eina_Bool ecore_x_fixes_selection_notification_request(Ecore_X_Atom selection);
|
EAPI Eina_Bool ecore_x_fixes_selection_notification_request(Ecore_X_Atom selection);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xfixes selection notification request.
|
||||||
|
*
|
||||||
|
* In addition to ecore_x_fixes_selection_notification_request you can also specify for which window you want to get them
|
||||||
|
* @since 1.24
|
||||||
|
*/
|
||||||
|
EAPI Eina_Bool ecore_x_fixes_window_selection_notification_request(Ecore_X_Window window, Ecore_X_Atom selection);
|
||||||
|
|
||||||
|
|
||||||
/* XComposite Extension Support */
|
/* XComposite Extension Support */
|
||||||
EAPI Eina_Bool ecore_x_composite_query(void);
|
EAPI Eina_Bool ecore_x_composite_query(void);
|
||||||
EAPI void ecore_x_composite_redirect_window(Ecore_X_Window win, Ecore_X_Composite_Update_Type type);
|
EAPI void ecore_x_composite_redirect_window(Ecore_X_Window win, Ecore_X_Composite_Update_Type type);
|
||||||
|
|
|
@ -112,6 +112,26 @@ ecore_x_fixes_selection_notification_request(Ecore_X_Atom selection)
|
||||||
return EINA_FALSE;
|
return EINA_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
ecore_x_fixes_window_selection_notification_request(Ecore_X_Window window, Ecore_X_Atom selection)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(_ecore_x_disp, EINA_FALSE);
|
||||||
|
|
||||||
|
#ifdef ECORE_XFIXES
|
||||||
|
if (_fixes_available)
|
||||||
|
{
|
||||||
|
XFixesSelectSelectionInput (_ecore_x_disp,
|
||||||
|
window,
|
||||||
|
selection,
|
||||||
|
XFixesSetSelectionOwnerNotifyMask |
|
||||||
|
XFixesSelectionWindowDestroyNotifyMask |
|
||||||
|
XFixesSelectionClientCloseNotifyMask);
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
EAPI Ecore_X_Region
|
EAPI Ecore_X_Region
|
||||||
ecore_x_region_new(Ecore_X_Rectangle *rects,
|
ecore_x_region_new(Ecore_X_Rectangle *rects,
|
||||||
int num)
|
int num)
|
||||||
|
|
|
@ -990,15 +990,15 @@ _ecore_x_selection_parser_targets(const char *target EINA_UNUSED,
|
||||||
if (!sel) return NULL;
|
if (!sel) return NULL;
|
||||||
targets = data;
|
targets = data;
|
||||||
|
|
||||||
sel->num_targets = size - 2;
|
sel->num_targets = size;
|
||||||
sel->targets = malloc((size - 2) * sizeof(char *));
|
sel->targets = malloc((sel->num_targets) * sizeof(char *));
|
||||||
if (!sel->targets)
|
if (!sel->targets)
|
||||||
{
|
{
|
||||||
free(sel);
|
free(sel);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
for (i = 2; i < size; i++)
|
for (i = 0; i < size; i++)
|
||||||
sel->targets[i - 2] = XGetAtomName(_ecore_x_disp, targets[i]);
|
sel->targets[i] = XGetAtomName(_ecore_x_disp, targets[i]);
|
||||||
|
|
||||||
ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_targets_free;
|
ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_targets_free;
|
||||||
ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TARGETS;
|
ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TARGETS;
|
||||||
|
|
|
@ -272,6 +272,7 @@ extern "C" {
|
||||||
#include <eina_debug.h>
|
#include <eina_debug.h>
|
||||||
#include <eina_promise.h>
|
#include <eina_promise.h>
|
||||||
#include <eina_vpath.h>
|
#include <eina_vpath.h>
|
||||||
|
#include <eina_abstract_content.h>
|
||||||
|
|
||||||
#undef EAPI
|
#undef EAPI
|
||||||
#define EAPI
|
#define EAPI
|
||||||
|
|
|
@ -0,0 +1,443 @@
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Eina.h>
|
||||||
|
#include "eina_abstract_content.h"
|
||||||
|
|
||||||
|
struct _Eina_Content
|
||||||
|
{
|
||||||
|
Eina_Rw_Slice data;
|
||||||
|
const char *type;
|
||||||
|
const char *file;
|
||||||
|
EINA_REFCOUNT;
|
||||||
|
};
|
||||||
|
EAPI const Eina_Value_Type *EINA_VALUE_TYPE_CONTENT;
|
||||||
|
|
||||||
|
static int _eina_abstract_content_log_domain = -1;
|
||||||
|
|
||||||
|
#ifdef ERR
|
||||||
|
#undef ERR
|
||||||
|
#endif
|
||||||
|
#define ERR(...) EINA_LOG_DOM_ERR(_eina_abstract_content_log_domain, __VA_ARGS__)
|
||||||
|
|
||||||
|
#ifdef DBG
|
||||||
|
#undef DBG
|
||||||
|
#endif
|
||||||
|
#define DBG(...) EINA_LOG_DOM_DBG(_eina_abstract_content_log_domain, __VA_ARGS__)
|
||||||
|
|
||||||
|
static Eina_Hash *conversion_callbacks;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *to;
|
||||||
|
Eina_Content_Conversion_Callback callback;
|
||||||
|
} Eina_Content_Conversion_Node;
|
||||||
|
|
||||||
|
static void
|
||||||
|
_eina_content_ref(Eina_Content *content)
|
||||||
|
{
|
||||||
|
EINA_REFCOUNT_REF(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
eina_content_converter_conversion_register(const char *from, const char *to, Eina_Content_Conversion_Callback conversion)
|
||||||
|
{
|
||||||
|
Eina_Content_Conversion_Node *node = calloc(1, sizeof(Eina_Content_Conversion_Node));
|
||||||
|
|
||||||
|
Eina_Stringshare *shared_from = eina_stringshare_add(from);
|
||||||
|
|
||||||
|
if (eina_content_converter_convert_can(from, to))
|
||||||
|
{
|
||||||
|
ERR("Convertion from %s to %s is already possible", from, to);
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->to = eina_stringshare_add(to);
|
||||||
|
node->callback = conversion;
|
||||||
|
|
||||||
|
eina_hash_list_append(conversion_callbacks, shared_from, node);
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Eina_List*
|
||||||
|
_conversion_callback_fetch_possible(const char *from)
|
||||||
|
{
|
||||||
|
Eina_Stringshare *shared_from = eina_stringshare_add(from);
|
||||||
|
Eina_List *res = eina_hash_find(conversion_callbacks, shared_from);
|
||||||
|
eina_stringshare_del(shared_from);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Eina_Content_Conversion_Callback
|
||||||
|
_conversion_callback_fetch(const char *from, const char *to)
|
||||||
|
{
|
||||||
|
Eina_List *possibilities = _conversion_callback_fetch_possible(from);
|
||||||
|
Eina_Content_Conversion_Node *n;
|
||||||
|
Eina_Content_Conversion_Callback result = NULL;
|
||||||
|
Eina_List *l;
|
||||||
|
Eina_Stringshare *shared_to = eina_stringshare_add(to);
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(possibilities, l, n)
|
||||||
|
{
|
||||||
|
if (n->to == shared_to)
|
||||||
|
{
|
||||||
|
result = n->callback;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
eina_stringshare_del(shared_to);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
eina_content_converter_convert_can(const char *from, const char *to)
|
||||||
|
{
|
||||||
|
return !!_conversion_callback_fetch(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const void*
|
||||||
|
_process_cb(const void *container EINA_UNUSED, void *data, void *fdata EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Eina_Content_Conversion_Node *n = data;
|
||||||
|
|
||||||
|
return n->to;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Iterator*
|
||||||
|
eina_content_converter_possible_conversions(const char *from)
|
||||||
|
{
|
||||||
|
Eina_List *possibilities = _conversion_callback_fetch_possible(from);
|
||||||
|
|
||||||
|
return eina_iterator_processed_new(eina_list_iterator_new(possibilities) , EINA_PROCESS_CB(_process_cb), NULL, possibilities);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Content*
|
||||||
|
eina_content_new(Eina_Slice data, const char *type)
|
||||||
|
{
|
||||||
|
Eina_Content *content;
|
||||||
|
|
||||||
|
if (!strncmp(type, "text", strlen("text")))
|
||||||
|
{
|
||||||
|
//last char in the mem must be \0
|
||||||
|
if (((char*)data.mem)[data.len - 1] != '\0')
|
||||||
|
{
|
||||||
|
ERR("Last character is not a null character! but type is text!");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
content = calloc(1, sizeof(Eina_Content));
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(content, NULL);
|
||||||
|
content->data = eina_slice_dup(data);
|
||||||
|
content->type = eina_stringshare_add(type);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(content->data.mem, NULL);
|
||||||
|
|
||||||
|
_eina_content_ref(content);
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI void
|
||||||
|
eina_content_free(Eina_Content *content)
|
||||||
|
{
|
||||||
|
EINA_REFCOUNT_UNREF(content)
|
||||||
|
{
|
||||||
|
if (content->file)
|
||||||
|
eina_tmpstr_del(content->file);
|
||||||
|
free(content->data.mem);
|
||||||
|
free(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI const char*
|
||||||
|
eina_content_as_file(Eina_Content *content)
|
||||||
|
{
|
||||||
|
if (!content->file)
|
||||||
|
{
|
||||||
|
Eina_Tmpstr *path;
|
||||||
|
int fd = eina_file_mkstemp("prefixXXXXXX.ext", &path);
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
ERR("Failed to create tmp file");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write(fd, content->data.mem, content->data.len) < 0)
|
||||||
|
{
|
||||||
|
ERR("Failed to write to a file");
|
||||||
|
eina_tmpstr_del(path);
|
||||||
|
close(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
content->file = path;
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
return content->file;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI const char*
|
||||||
|
eina_content_type_get(Eina_Content *content)
|
||||||
|
{
|
||||||
|
return content->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI const Eina_Slice
|
||||||
|
eina_content_data_get(Eina_Content *content)
|
||||||
|
{
|
||||||
|
return eina_rw_slice_slice_get(content->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Content*
|
||||||
|
eina_content_convert(Eina_Content *content, const char *new_type)
|
||||||
|
{
|
||||||
|
Eina_Content_Conversion_Callback callback = _conversion_callback_fetch(content->type, new_type);
|
||||||
|
|
||||||
|
if (!callback)
|
||||||
|
{
|
||||||
|
ERR("No suitable conversion found");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return callback(content, new_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Content*
|
||||||
|
_copy_converter(Eina_Content *from, const char *to_type)
|
||||||
|
{
|
||||||
|
Eina_Slice slice = eina_content_data_get(from);
|
||||||
|
return eina_content_new(slice, to_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Content*
|
||||||
|
_latin1_to_utf8_converter(Eina_Content *from, const char *to_type)
|
||||||
|
{
|
||||||
|
Eina_Slice slice = eina_content_data_get(from);
|
||||||
|
Eina_Strbuf *out = eina_strbuf_new();
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < slice.len; ++i)
|
||||||
|
{
|
||||||
|
const unsigned char c = ((char*)slice.mem)[i];
|
||||||
|
if (c < 128)
|
||||||
|
eina_strbuf_append_char(out, c);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eina_strbuf_append_char(out, 0xc0 | c >> 6);
|
||||||
|
eina_strbuf_append_char(out, 0x80 | (c & 0x3f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Eina_Slice new;
|
||||||
|
new.len = eina_strbuf_length_get(out);
|
||||||
|
new.mem = eina_strbuf_string_get(out);
|
||||||
|
Eina_Content *c = eina_content_new(new, to_type);
|
||||||
|
eina_strbuf_free(out);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_eina_value_type_content_setup(const Eina_Value_Type *type EINA_UNUSED, void *mem)
|
||||||
|
{
|
||||||
|
memset(mem, 0, sizeof(Eina_Content*));
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_eina_value_type_content_flush(const Eina_Value_Type *type EINA_UNUSED,
|
||||||
|
void *mem EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Eina_Content **content = mem;
|
||||||
|
|
||||||
|
eina_content_free(*content);
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_eina_value_type_content_copy(const Eina_Value_Type *type EINA_UNUSED, const void *src, void *dst)
|
||||||
|
{
|
||||||
|
Eina_Content * const *srcc = src;
|
||||||
|
Eina_Content **dstc = dst;
|
||||||
|
|
||||||
|
*dstc = *srcc;
|
||||||
|
_eina_content_ref(*dstc);
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_eina_value_type_content_compare(const Eina_Value_Type *type EINA_UNUSED, const void *a, const void *b)
|
||||||
|
{
|
||||||
|
Eina_Content * const *ra = a;
|
||||||
|
Eina_Content * const *rb = b;
|
||||||
|
|
||||||
|
if ((*ra)->type != (*rb)->type)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return eina_rw_slice_compare((*ra)->data, (*rb)->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_eina_value_type_content_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert EINA_UNUSED, const void *type_mem EINA_UNUSED, void *convert_mem EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Eina_Content * const *ra = type_mem;
|
||||||
|
|
||||||
|
if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
|
||||||
|
convert == EINA_VALUE_TYPE_STRING)
|
||||||
|
{
|
||||||
|
const char *type = eina_content_type_get(*ra);
|
||||||
|
if (eina_streq(type, "text/plain;charset=utf-8"))
|
||||||
|
{
|
||||||
|
Eina_Slice data = eina_content_data_get(*ra);
|
||||||
|
return eina_value_type_pset(convert, convert_mem, &data.mem);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Eina_Iterator *iter = eina_content_possible_conversions(*ra);
|
||||||
|
const char *type;
|
||||||
|
|
||||||
|
EINA_ITERATOR_FOREACH(iter, type)
|
||||||
|
{
|
||||||
|
if (eina_streq(type, "text/plain;charset=utf-8"))
|
||||||
|
{
|
||||||
|
Eina_Content *conv_result = eina_content_convert(*ra, type);
|
||||||
|
|
||||||
|
Eina_Slice data = eina_content_data_get(conv_result);
|
||||||
|
Eina_Bool success = eina_value_type_pset(convert, convert_mem, &data.mem);
|
||||||
|
eina_content_free(conv_result);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//create some fallback
|
||||||
|
{
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
char *tmp = (char*) &buf;
|
||||||
|
snprintf(buf, sizeof(buf), "Content %p cannot be converted to \"text/plain;charset=utf-8\"", *ra);
|
||||||
|
return eina_value_type_pset(convert, convert_mem, &tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_eina_value_type_content_convert_from(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert EINA_UNUSED, void *type_mem EINA_UNUSED, const void *convert_mem EINA_UNUSED)
|
||||||
|
{
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_eina_value_type_content_pset(const Eina_Value_Type *type EINA_UNUSED, void *mem, const void *ptr)
|
||||||
|
{
|
||||||
|
Eina_Content * const *srcc = ptr;
|
||||||
|
Eina_Content **dstc = mem;
|
||||||
|
|
||||||
|
*dstc = *srcc;
|
||||||
|
_eina_content_ref(*dstc);
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_eina_value_type_content_vset(const Eina_Value_Type *type EINA_UNUSED, void *mem, va_list args)
|
||||||
|
{
|
||||||
|
Eina_Content **dst = mem;
|
||||||
|
Eina_Content *content = va_arg(args, Eina_Content*);
|
||||||
|
|
||||||
|
*dst = content;
|
||||||
|
_eina_content_ref(*dst);
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_eina_value_type_content_pget(const Eina_Value_Type *type EINA_UNUSED, const void *mem, void *ptr)
|
||||||
|
{
|
||||||
|
Eina_Content * const *src = mem;
|
||||||
|
Eina_Content **dst = ptr;
|
||||||
|
|
||||||
|
*dst = *src;
|
||||||
|
_eina_content_ref(*dst);
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI const Eina_Value_Type _EINA_VALUE_TYPE_CONTENT ={
|
||||||
|
EINA_VALUE_TYPE_VERSION,
|
||||||
|
sizeof(Eina_Content*),
|
||||||
|
"Eina_Abstract_Content",
|
||||||
|
_eina_value_type_content_setup,
|
||||||
|
_eina_value_type_content_flush,
|
||||||
|
_eina_value_type_content_copy,
|
||||||
|
_eina_value_type_content_compare,
|
||||||
|
_eina_value_type_content_convert_to,
|
||||||
|
_eina_value_type_content_convert_from,
|
||||||
|
_eina_value_type_content_vset,
|
||||||
|
_eina_value_type_content_pset,
|
||||||
|
_eina_value_type_content_pget
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
_free_node(void *v)
|
||||||
|
{
|
||||||
|
Eina_Content_Conversion_Node *n;
|
||||||
|
EINA_LIST_FREE(v, n)
|
||||||
|
{
|
||||||
|
eina_stringshare_del(n->to);
|
||||||
|
free(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Bool
|
||||||
|
eina_abstract_content_init(void)
|
||||||
|
{
|
||||||
|
_eina_abstract_content_log_domain = eina_log_domain_register("eina_abstract_content", "white");
|
||||||
|
conversion_callbacks = eina_hash_stringshared_new(_free_node);
|
||||||
|
|
||||||
|
EINA_VALUE_TYPE_CONTENT = &_EINA_VALUE_TYPE_CONTENT;
|
||||||
|
|
||||||
|
// text/plain is assumed to be charset "US-ASCII"
|
||||||
|
|
||||||
|
eina_content_converter_conversion_register("text/plain", "text/plain;charset=utf-8", _copy_converter);
|
||||||
|
eina_content_converter_conversion_register("text/plain", "text/plain;charset=iso-8859-1", _copy_converter);
|
||||||
|
eina_content_converter_conversion_register("text/plain;charset=iso-8859-1", "text/plain;charset=utf-8", _latin1_to_utf8_converter);
|
||||||
|
eina_content_converter_conversion_register("text/plain;charset=iso-8859-1", "text/plain", _copy_converter);
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Bool
|
||||||
|
eina_abstract_content_shutdown(void)
|
||||||
|
{
|
||||||
|
eina_hash_free(conversion_callbacks);
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Value*
|
||||||
|
eina_value_content_new(Eina_Content *content)
|
||||||
|
{
|
||||||
|
Eina_Value *v = eina_value_new(EINA_VALUE_TYPE_CONTENT);
|
||||||
|
|
||||||
|
eina_value_pset(v, &content);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Eina_Value
|
||||||
|
eina_value_content_init(Eina_Content *content)
|
||||||
|
{
|
||||||
|
Eina_Value v;
|
||||||
|
|
||||||
|
eina_value_setup(&v, EINA_VALUE_TYPE_CONTENT);
|
||||||
|
eina_value_pset(&v, &content);
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Eina_Content*
|
||||||
|
eina_value_to_content(const Eina_Value *value)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_FALSE_RETURN_VAL(eina_value_type_get(value) == EINA_VALUE_TYPE_CONTENT, NULL);
|
||||||
|
Eina_Content *result = calloc(1, sizeof(Eina_Content));
|
||||||
|
eina_value_pget(value, &result);
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,154 @@
|
||||||
|
#ifndef EINA_ABSTRACT_CONTENT_H
|
||||||
|
#define EINA_ABSTRACT_CONTENT_H
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef Eina_Content
|
||||||
|
* Container for any type of content.
|
||||||
|
*
|
||||||
|
* Each Eina_Content is made of an Eina_Slice of memory and an IANA MIME type:
|
||||||
|
* https://www.iana.org/assignments/media-types/media-types.xhtml
|
||||||
|
*
|
||||||
|
* @note if the type is a text-style type, the last byte of the slice must be \0.
|
||||||
|
*
|
||||||
|
* @since 1.24
|
||||||
|
*/
|
||||||
|
typedef struct _Eina_Content Eina_Content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef Eina_Content_Conversion_Callback
|
||||||
|
*
|
||||||
|
* Method called when conversion from one type to another is requested.
|
||||||
|
* The from and to types are specified when the callback is registered.
|
||||||
|
* The to type is also passed in the callback here.
|
||||||
|
* The type of the from pointer does not need to be checked.
|
||||||
|
*/
|
||||||
|
typedef Eina_Content* (*Eina_Content_Conversion_Callback)(Eina_Content *from, const char *to_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the path to a file, containing the slice memory as content.
|
||||||
|
*
|
||||||
|
* @param[in] content The content that will be in the file.
|
||||||
|
*
|
||||||
|
* @return The path to the file. Do not free this.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
EAPI const char* eina_content_as_file(Eina_Content *content);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the content of the object to another type.
|
||||||
|
*
|
||||||
|
* In case the conversion cannot be performed, NULL is returned.
|
||||||
|
*
|
||||||
|
* @param[in] content The content to convert.
|
||||||
|
* @param[in] new_type The new type the returned content will have.
|
||||||
|
*
|
||||||
|
* @return A new content object. The caller of this function is owning this.
|
||||||
|
*/
|
||||||
|
EAPI Eina_Content* eina_content_convert(Eina_Content *content, const char *new_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type of the passed content.
|
||||||
|
*
|
||||||
|
* @param[in] content The content to fetch the type from.
|
||||||
|
*
|
||||||
|
* @return The type of this content. Do no free this.
|
||||||
|
*/
|
||||||
|
EAPI const char* eina_content_type_get(Eina_Content *content);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Eina_Slice of the passed content.
|
||||||
|
*
|
||||||
|
* @param[in] content The content to fetch the data from.
|
||||||
|
*
|
||||||
|
* @return An Eina_Slice containing the data. Do not free.
|
||||||
|
*/
|
||||||
|
EAPI const Eina_Slice eina_content_data_get(Eina_Content *content);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new content object, with the provided data and type.
|
||||||
|
*
|
||||||
|
* @param[in] data A slice of memory. The memory is copied.
|
||||||
|
* @param[in] type The type this data represents.
|
||||||
|
*
|
||||||
|
* @return The new content object. The caller owns this object.
|
||||||
|
*/
|
||||||
|
EAPI Eina_Content* eina_content_new(Eina_Slice data, const char *type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free the content object.
|
||||||
|
*
|
||||||
|
* @param[in] content The content to free.
|
||||||
|
*/
|
||||||
|
EAPI void eina_content_free(Eina_Content *content);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new conversion callback.
|
||||||
|
*
|
||||||
|
* @param[in] from The type to convert from.
|
||||||
|
* @param[in] to The type to convert to.
|
||||||
|
*
|
||||||
|
* @return True if the callback was successfully registered.
|
||||||
|
*/
|
||||||
|
EAPI Eina_Bool eina_content_converter_conversion_register(const char *from, const char *to, Eina_Content_Conversion_Callback convertion);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a specific conversion can be performed.
|
||||||
|
*
|
||||||
|
* A conversion can only be performed if a callback is registered.
|
||||||
|
*
|
||||||
|
* @param[in] from The type to convert from.
|
||||||
|
* @param[in] to The type to convert to.
|
||||||
|
*
|
||||||
|
* @return True if the conversion can be performed.
|
||||||
|
*/
|
||||||
|
EAPI Eina_Bool eina_content_converter_convert_can(const char *from, const char *to);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an iterator containing all the target types that the provided source type can be converted to.
|
||||||
|
*
|
||||||
|
* @param[in] from The type to convert from.
|
||||||
|
*
|
||||||
|
* @return An Iterator containing MIME type strings. Free this via eina_iterator_free.
|
||||||
|
*/
|
||||||
|
EAPI Eina_Iterator* eina_content_converter_possible_conversions(const char *from);
|
||||||
|
|
||||||
|
EAPI extern const Eina_Value_Type *EINA_VALUE_TYPE_CONTENT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the Eina_Content object to an Eina_Value.
|
||||||
|
*
|
||||||
|
* @param[in] content The Eina_Content struct that will be converted to an Eina_Value.
|
||||||
|
*
|
||||||
|
* @return An newly-allocated Eina_Value. Caller owns it.
|
||||||
|
*/
|
||||||
|
EAPI Eina_Value* eina_value_content_new(Eina_Content *content);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an Eina_Value from an Eina_Content.
|
||||||
|
*
|
||||||
|
* @param[in] content The Eina_Content struct that will be converted to an Eina_Value.
|
||||||
|
*
|
||||||
|
* @return An Eina_Value with type EINA_VALUE_TYPE_CONTENT.
|
||||||
|
*/
|
||||||
|
EAPI Eina_Value eina_value_content_init(Eina_Content *content);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the content from the Eina_Value.
|
||||||
|
*
|
||||||
|
* If the value is not of the type EINA_VALUE_TYPE_CONTENT, NULL will be returned and an error will be printed.
|
||||||
|
*
|
||||||
|
* @param[in] value The value to get the content from
|
||||||
|
*
|
||||||
|
* @return A newly-allocated Eina_Content. Caller owns it.
|
||||||
|
*/
|
||||||
|
EAPI Eina_Content* eina_value_to_content(const Eina_Value *value);
|
||||||
|
|
||||||
|
|
||||||
|
static inline Eina_Iterator*
|
||||||
|
eina_content_possible_conversions(Eina_Content *content)
|
||||||
|
{
|
||||||
|
return eina_content_converter_possible_conversions(eina_content_type_get(content));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -154,6 +154,7 @@ extern Eina_Lock _sysmon_lock;
|
||||||
S(slstr);
|
S(slstr);
|
||||||
S(promise);
|
S(promise);
|
||||||
S(vpath);
|
S(vpath);
|
||||||
|
S(abstract_content);
|
||||||
#undef S
|
#undef S
|
||||||
|
|
||||||
struct eina_desc_setup
|
struct eina_desc_setup
|
||||||
|
@ -202,6 +203,7 @@ static const struct eina_desc_setup _eina_desc_setup[] = {
|
||||||
S(safepointer),
|
S(safepointer),
|
||||||
S(slstr),
|
S(slstr),
|
||||||
S(promise),
|
S(promise),
|
||||||
|
S(abstract_content)
|
||||||
#undef S
|
#undef S
|
||||||
};
|
};
|
||||||
static const size_t _eina_desc_setup_len = sizeof(_eina_desc_setup) /
|
static const size_t _eina_desc_setup_len = sizeof(_eina_desc_setup) /
|
||||||
|
|
|
@ -464,6 +464,30 @@ static inline char *eina_rw_slice_strdup(const Eina_Rw_Slice rw_slice);
|
||||||
#else
|
#else
|
||||||
#define EINA_SLICE_STR(str) {.len = strlen((str)), .mem = (str)}
|
#define EINA_SLICE_STR(str) {.len = strlen((str)), .mem = (str)}
|
||||||
#endif
|
#endif
|
||||||
|
/**
|
||||||
|
* @def EINA_SLICE_STR_FULL(str)
|
||||||
|
*
|
||||||
|
* Same as EINA_SLICE_STR_FULL, but it also contains the \0 element of the string
|
||||||
|
*
|
||||||
|
* @param[in] str The string to create the slice from.
|
||||||
|
* @return The initialized slice object.
|
||||||
|
*
|
||||||
|
* @note This macro is usable with both Eina_Slice or Eina_Rw_Slice.
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* Eina_Slice ro_slice = EINA_SLICE_STR_FULL("hello world");
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* @see EINA_SLICE_STR_FULL() for specific version using literals.
|
||||||
|
*
|
||||||
|
* @since 1.24
|
||||||
|
*/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define EINA_SLICE_STR_FULL(str) {strlen((str)) + 1, (str)}
|
||||||
|
#else
|
||||||
|
#define EINA_SLICE_STR_FULL(str) {.len = strlen((str)) + 1, .mem = (str)}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @def EINA_SLICE_STR_FMT
|
* @def EINA_SLICE_STR_FMT
|
||||||
|
|
|
@ -107,6 +107,7 @@ public_sub_headers = [
|
||||||
'eina_freeq.h',
|
'eina_freeq.h',
|
||||||
'eina_slstr.h',
|
'eina_slstr.h',
|
||||||
'eina_vpath.h',
|
'eina_vpath.h',
|
||||||
|
'eina_abstract_content.h'
|
||||||
]
|
]
|
||||||
|
|
||||||
public_headers = [
|
public_headers = [
|
||||||
|
@ -188,7 +189,8 @@ sources = [
|
||||||
'eina_freeq.c',
|
'eina_freeq.c',
|
||||||
'eina_slstr.c',
|
'eina_slstr.c',
|
||||||
'eina_vpath.c',
|
'eina_vpath.c',
|
||||||
'eina_vpath_xdg.c'
|
'eina_vpath_xdg.c',
|
||||||
|
'eina_abstract_content.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
if sys_windows == true
|
if sys_windows == true
|
||||||
|
|
|
@ -119,8 +119,6 @@ extern EAPI Eina_Error EFL_UI_THEME_APPLY_ERROR_NONE;
|
||||||
|
|
||||||
// EO types. Defined for legacy-only builds as legacy uses typedef of EO types.
|
// EO types. Defined for legacy-only builds as legacy uses typedef of EO types.
|
||||||
#include "efl_ui.eot.h"
|
#include "efl_ui.eot.h"
|
||||||
#include "efl_ui_selection_types.eot.h"
|
|
||||||
#include "efl_ui_dnd_types.eot.h"
|
|
||||||
|
|
||||||
//define focus manager earlier since focus object and manager is circular
|
//define focus manager earlier since focus object and manager is circular
|
||||||
typedef Eo Efl_Ui_Focus_Manager;
|
typedef Eo Efl_Ui_Focus_Manager;
|
||||||
|
@ -322,7 +320,6 @@ typedef Eo Efl_Ui_Spotlight_Indicator;
|
||||||
# include <efl_ui_widget_focus_manager.eo.h>
|
# include <efl_ui_widget_focus_manager.eo.h>
|
||||||
# include <efl_ui_selection.eo.h>
|
# include <efl_ui_selection.eo.h>
|
||||||
# include <efl_ui_dnd.eo.h>
|
# include <efl_ui_dnd.eo.h>
|
||||||
# include <efl_ui_dnd_container.eo.h>
|
|
||||||
|
|
||||||
# include <efl_ui_timepicker.eo.h>
|
# include <efl_ui_timepicker.eo.h>
|
||||||
# include <efl_ui_datepicker.eo.h>
|
# include <efl_ui_datepicker.eo.h>
|
||||||
|
|
|
@ -12,838 +12,140 @@
|
||||||
#include <Elementary_Cursor.h>
|
#include <Elementary_Cursor.h>
|
||||||
#include "elm_priv.h"
|
#include "elm_priv.h"
|
||||||
|
|
||||||
typedef struct _Efl_Ui_Dnd_Container_Data Efl_Ui_Dnd_Container_Data;
|
typedef struct {
|
||||||
struct _Efl_Ui_Dnd_Container_Data
|
Ecore_Evas *ee;
|
||||||
{
|
Eina_Bool registered;
|
||||||
unsigned int drag_delay_time;
|
} Efl_Ui_Dnd_Data;
|
||||||
};
|
|
||||||
|
|
||||||
extern int _wl_default_seat_id_get(Evas_Object *obj);
|
typedef struct {
|
||||||
#ifdef HAVE_ELEMENTARY_WL2
|
Eo *win;
|
||||||
Ecore_Wl2_Window *_wl_window_get(const Evas_Object *obj);
|
Efl_Ui_Dnd *obj;
|
||||||
#endif
|
} Efl_Ui_Drag_Start;
|
||||||
|
|
||||||
Eo*
|
|
||||||
_efl_ui_selection_manager_get(Eo *obj)
|
|
||||||
{
|
|
||||||
if (!efl_isa(obj, EFL_UI_WIDGET_CLASS)) return NULL;
|
|
||||||
Eo *app = efl_app_main_get();
|
|
||||||
Eo *sel_man = efl_key_data_get(app, "__selection_manager");
|
|
||||||
if (!sel_man)
|
|
||||||
{
|
|
||||||
sel_man = efl_add(EFL_UI_SELECTION_MANAGER_CLASS, app);
|
|
||||||
efl_key_data_set(app, "__selection_manager", sel_man);
|
|
||||||
}
|
|
||||||
return sel_man;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
_efl_ui_dnd_shutdown(void)
|
|
||||||
{
|
|
||||||
Eo *app = efl_app_main_get();
|
|
||||||
Eo *sel_man = efl_key_data_get(app, "__selection_manager");
|
|
||||||
|
|
||||||
efl_del(sel_man);
|
|
||||||
}
|
|
||||||
|
|
||||||
EOLIAN static void
|
|
||||||
_efl_ui_dnd_drag_start(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Format format, Eina_Slice data,
|
|
||||||
Efl_Ui_Selection_Action action, void *icon_func_data, Efl_Dnd_Drag_Icon_Create icon_func, Eina_Free_Cb icon_func_free_cb,
|
|
||||||
unsigned int seat)
|
|
||||||
{
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
|
||||||
efl_ui_selection_manager_drag_start(sel_man, obj, format, data, action,
|
|
||||||
icon_func_data, icon_func, icon_func_free_cb,
|
|
||||||
seat);
|
|
||||||
}
|
|
||||||
|
|
||||||
EOLIAN static void
|
|
||||||
_efl_ui_dnd_drag_cancel(Eo *obj, void *pd EINA_UNUSED, unsigned int seat)
|
|
||||||
{
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
|
||||||
efl_ui_selection_manager_drag_cancel(sel_man, obj, seat);
|
|
||||||
}
|
|
||||||
|
|
||||||
EOLIAN static void
|
|
||||||
_efl_ui_dnd_drag_action_set(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Action action, unsigned int seat)
|
|
||||||
{
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
|
||||||
efl_ui_selection_manager_drag_action_set(sel_man, obj, action, seat);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
EOLIAN static void
|
|
||||||
_efl_ui_dnd_drop_target_add(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Format format, unsigned int seat)
|
|
||||||
{
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
|
||||||
efl_ui_selection_manager_drop_target_add(sel_man, obj, format, seat);
|
|
||||||
}
|
|
||||||
|
|
||||||
EOLIAN static void
|
|
||||||
_efl_ui_dnd_drop_target_del(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Format format, unsigned int seat)
|
|
||||||
{
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
|
||||||
efl_ui_selection_manager_drop_target_del(sel_man, obj, format, seat);
|
|
||||||
}
|
|
||||||
|
|
||||||
EOLIAN static double
|
|
||||||
_efl_ui_dnd_container_drag_delay_time_get(const Eo *obj EINA_UNUSED, Efl_Ui_Dnd_Container_Data *pd)
|
|
||||||
{
|
|
||||||
return pd->drag_delay_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
EOLIAN static void
|
|
||||||
_efl_ui_dnd_container_drag_delay_time_set(Eo *obj EINA_UNUSED, Efl_Ui_Dnd_Container_Data *pd, double drag_delay_time)
|
|
||||||
{
|
|
||||||
pd->drag_delay_time = drag_delay_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
EOLIAN static void
|
|
||||||
_efl_ui_dnd_container_drag_item_add(Eo *obj, Efl_Ui_Dnd_Container_Data *pd,
|
|
||||||
void *data_func_data, Efl_Dnd_Drag_Data_Get data_func, Eina_Free_Cb data_func_free_cb,
|
|
||||||
void *item_func_data, Efl_Dnd_Item_Get item_func, Eina_Free_Cb item_func_free_cb,
|
|
||||||
void *icon_func_data, Efl_Dnd_Drag_Icon_Create icon_func, Eina_Free_Cb icon_func_free_cb,
|
|
||||||
void *icon_list_func_data, Efl_Dnd_Drag_Icon_List_Create icon_list_func, Eina_Free_Cb icon_list_func_free_cb,
|
|
||||||
unsigned int seat)
|
|
||||||
{
|
|
||||||
double drag_delay_time = pd->drag_delay_time;
|
|
||||||
double anim_time = elm_config_drag_anim_duration_get();
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
|
||||||
efl_ui_selection_manager_container_drag_item_add(sel_man, obj, drag_delay_time, anim_time,
|
|
||||||
data_func_data, data_func, data_func_free_cb,
|
|
||||||
item_func_data, item_func, item_func_free_cb,
|
|
||||||
icon_func_data, icon_func, icon_func_free_cb,
|
|
||||||
icon_list_func_data, icon_list_func, icon_list_func_free_cb,
|
|
||||||
seat);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_efl_ui_dnd_container_drag_item_del(Eo *obj, Efl_Ui_Dnd_Container_Data *pd EINA_UNUSED, unsigned int seat)
|
_ecore_evas_drag_terminated(Ecore_Evas *ee EINA_UNUSED, unsigned int seat, void *data, Eina_Bool accepted)
|
||||||
{
|
{
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
Efl_Ui_Drag_Start *start = data;
|
||||||
efl_ui_selection_manager_container_drag_item_del(sel_man, obj, seat);
|
Efl_Ui_Drag_Finished_Event ev = {seat, accepted};
|
||||||
|
efl_event_callback_call(start->obj, EFL_UI_DND_EVENT_DRAG_FINISHED, &ev);
|
||||||
|
efl_del(start->win);
|
||||||
|
free(start);
|
||||||
}
|
}
|
||||||
EOLIAN static void
|
|
||||||
_efl_ui_dnd_container_drop_item_add(Eo *obj, Efl_Ui_Dnd_Container_Data *pd EINA_UNUSED,
|
EOLIAN static Efl_Content*
|
||||||
Efl_Ui_Selection_Format format,
|
_efl_ui_dnd_drag_start(Eo *obj, Efl_Ui_Dnd_Data *pd, Eina_Content *content, const char* action, unsigned int seat)
|
||||||
void *item_func_data, Efl_Dnd_Item_Get item_func, Eina_Free_Cb item_func_free_cb,
|
|
||||||
unsigned int seat)
|
|
||||||
{
|
{
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
Eo *drag_win;
|
||||||
efl_ui_selection_manager_container_drop_item_add(sel_man, obj, format, item_func_data, item_func, item_func_free_cb, seat);
|
Efl_Ui_Drag_Start *start;
|
||||||
|
Efl_Ui_Drag_Started_Event ev = {seat};
|
||||||
|
Ecore_Evas *drag_ee;
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN_VAL(pd->ee, NULL);
|
||||||
|
|
||||||
|
start = calloc(1, sizeof(Efl_Ui_Drag_Start));
|
||||||
|
start->obj = obj;
|
||||||
|
start->win = drag_win = elm_win_add(NULL, "Elm-Drag", ELM_WIN_DND);
|
||||||
|
elm_win_alpha_set(drag_win, EINA_TRUE);
|
||||||
|
elm_win_override_set(drag_win, EINA_TRUE);
|
||||||
|
elm_win_borderless_set(drag_win, EINA_TRUE);
|
||||||
|
drag_ee = ecore_evas_ecore_evas_get(evas_object_evas_get(drag_win));
|
||||||
|
|
||||||
|
ecore_evas_drag_start(pd->ee, seat, content, drag_ee, action, _ecore_evas_drag_terminated, start);
|
||||||
|
|
||||||
|
evas_object_show(drag_win);
|
||||||
|
|
||||||
|
efl_event_callback_call(obj, EFL_UI_DND_EVENT_DRAG_STARTED, &ev);
|
||||||
|
|
||||||
|
return drag_win;
|
||||||
}
|
}
|
||||||
|
|
||||||
EOLIAN static void
|
EOLIAN static void
|
||||||
_efl_ui_dnd_container_drop_item_del(Eo *obj, Efl_Ui_Dnd_Container_Data *pd EINA_UNUSED, unsigned int seat)
|
_efl_ui_dnd_drag_cancel(Eo *obj EINA_UNUSED, Efl_Ui_Dnd_Data *pd, unsigned int seat)
|
||||||
{
|
{
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
ecore_evas_drag_cancel(pd->ee, seat);
|
||||||
efl_ui_selection_manager_container_drop_item_del(sel_man, obj, seat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EOLIAN static Eina_Future*
|
||||||
///////////
|
_efl_ui_dnd_drop_data_get(Eo *obj EINA_UNUSED, Efl_Ui_Dnd_Data *pd, unsigned int seat, Eina_Iterator *acceptable_types)
|
||||||
typedef struct _Dnd_Icon_Create Dnd_Icon_Create;
|
|
||||||
typedef struct _Dnd_Drag_Pos Dnd_Drag_Pos;
|
|
||||||
typedef struct _Dnd_Drag_Accept Dnd_Drag_Accept;
|
|
||||||
typedef struct _Dnd_Drag_Done Dnd_Drag_Done;
|
|
||||||
typedef struct _Dnd_Drag_State Dnd_Drag_State;
|
|
||||||
typedef struct _Dnd_Drop Dnd_Drop;
|
|
||||||
typedef struct _Dnd_Cont_Drag_Pos Dnd_Cont_Drag_Pos;
|
|
||||||
typedef struct _Dnd_Cont_Drop Dnd_Cont_Drop;
|
|
||||||
typedef struct _Item_Container_Drag_Info Item_Container_Drag_Info;
|
|
||||||
|
|
||||||
struct _Dnd_Icon_Create
|
|
||||||
{
|
{
|
||||||
void *icon_data;
|
return ecore_evas_selection_get(pd->ee, seat, ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER, acceptable_types);
|
||||||
Elm_Drag_Icon_Create_Cb icon_cb;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _Dnd_Drag_Pos
|
|
||||||
{
|
|
||||||
void *pos_data;
|
|
||||||
Elm_Drag_Pos pos_cb;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _Dnd_Drag_Accept
|
|
||||||
{
|
|
||||||
void *accept_data;
|
|
||||||
Elm_Drag_Accept accept_cb;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _Dnd_Drag_Done
|
|
||||||
{
|
|
||||||
void *done_data;
|
|
||||||
Elm_Drag_State done_cb;
|
|
||||||
|
|
||||||
//for deleting
|
|
||||||
Dnd_Drag_Pos *pos;
|
|
||||||
Dnd_Drag_Accept *accept;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _Dnd_Drag_State
|
|
||||||
{
|
|
||||||
void *state_data;
|
|
||||||
Elm_Drag_State state_cb;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _Dnd_Drop
|
|
||||||
{
|
|
||||||
Efl_Object *obj;
|
|
||||||
Elm_Sel_Format format;
|
|
||||||
void *drop_data;
|
|
||||||
Elm_Drop_Cb drop_cb;
|
|
||||||
|
|
||||||
//for deleting
|
|
||||||
Dnd_Drag_State *enter;
|
|
||||||
Dnd_Drag_State *leave;
|
|
||||||
Dnd_Drag_Pos *pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _Dnd_Cont_Drag_Pos
|
|
||||||
{
|
|
||||||
void *pos_data;
|
|
||||||
Elm_Drag_Item_Container_Pos pos_cb;
|
|
||||||
Elm_Xy_Item_Get_Cb item_get_cb;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _Dnd_Cont_Drop
|
|
||||||
{
|
|
||||||
Efl_Object *obj;
|
|
||||||
Elm_Sel_Format format;
|
|
||||||
void *drop_data;
|
|
||||||
Elm_Drop_Item_Container_Cb drop_cb;
|
|
||||||
Elm_Xy_Item_Get_Cb item_get_cb;
|
|
||||||
|
|
||||||
//for deleting
|
|
||||||
Dnd_Drag_State *enter;
|
|
||||||
Dnd_Drag_State *leave;
|
|
||||||
Dnd_Cont_Drag_Pos *pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _Item_Container_Drag_Info
|
|
||||||
{
|
|
||||||
Elm_Drag_User_Info user_info;
|
|
||||||
Elm_Object_Item *it;
|
|
||||||
Elm_Item_Container_Data_Get_Cb data_get_cb;
|
|
||||||
Elm_Xy_Item_Get_Cb item_get_cb;
|
|
||||||
};
|
|
||||||
|
|
||||||
static Efl_Object *
|
|
||||||
_dnd_icon_create_cb(void *data, Efl_Object *win, Efl_Object *drag_obj EINA_UNUSED, Eina_Position2D *pos_ret)
|
|
||||||
{
|
|
||||||
Dnd_Icon_Create *ic = data;
|
|
||||||
Efl_Object *ret = ic->icon_cb(ic->icon_data, win, &pos_ret->x, &pos_ret->y);
|
|
||||||
|
|
||||||
free(ic);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
EOLIAN static Efl_Object *
|
||||||
_dnd_drag_pos_cb(void *data, const Efl_Event *event)
|
_efl_ui_dnd_efl_object_constructor(Eo *obj, Efl_Ui_Dnd_Data *pd)
|
||||||
{
|
{
|
||||||
Dnd_Drag_Pos *pos = data;
|
if (!efl_constructor(efl_super(obj, EFL_UI_DND_MIXIN)))
|
||||||
Efl_Dnd_Drag_Pos *ddata = event->info;
|
return NULL;
|
||||||
|
|
||||||
if (pos->pos_cb)
|
pd->ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
|
||||||
pos->pos_cb(pos->pos_data, event->object, ddata->pos.x, ddata->pos.y,
|
|
||||||
(Elm_Xdnd_Action)ddata->action);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_dnd_drag_accept_cb(void *data, const Efl_Event *event)
|
|
||||||
{
|
|
||||||
Dnd_Drag_Accept *accept = data;
|
|
||||||
|
|
||||||
if (accept->accept_cb)
|
|
||||||
accept->accept_cb(accept->accept_data, event->object, *(Eina_Bool *)event->info);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_dnd_drag_done_cb(void *data, const Efl_Event *event)
|
|
||||||
{
|
|
||||||
Dnd_Drag_Done *done = data;
|
|
||||||
|
|
||||||
if (done->done_cb)
|
|
||||||
done->done_cb(done->done_data, event->object);
|
|
||||||
|
|
||||||
efl_event_callback_del(event->object, EFL_UI_DND_EVENT_DRAG_POS,
|
|
||||||
_dnd_drag_pos_cb, done->pos);
|
|
||||||
efl_event_callback_del(event->object, EFL_UI_DND_EVENT_DRAG_ACCEPT,
|
|
||||||
_dnd_drag_accept_cb, done->accept);
|
|
||||||
efl_event_callback_del(event->object, EFL_UI_DND_EVENT_DRAG_DONE,
|
|
||||||
_dnd_drag_done_cb, done);
|
|
||||||
free(done->pos);
|
|
||||||
free(done->accept);
|
|
||||||
free(done);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_dnd_drag_enter_leave_cb(void *data, const Efl_Event *event)
|
|
||||||
{
|
|
||||||
Dnd_Drag_State *state = data;
|
|
||||||
|
|
||||||
if (state->state_cb)
|
|
||||||
state->state_cb(state->state_data, event->object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_dnd_drop_cb(void *data, const Efl_Event *event)
|
|
||||||
{
|
|
||||||
Dnd_Drop *drop = data;
|
|
||||||
Efl_Ui_Selection_Data *org_ddata = event->info;
|
|
||||||
Elm_Selection_Data ddata;
|
|
||||||
|
|
||||||
ddata.x = org_ddata->pos.x;
|
|
||||||
ddata.y = org_ddata->pos.y;
|
|
||||||
ddata.format = (Elm_Sel_Format)org_ddata->format;
|
|
||||||
ddata.action = (Elm_Xdnd_Action)org_ddata->action;
|
|
||||||
ddata.data = calloc(1, org_ddata->content.len);
|
|
||||||
if (!ddata.data) return;
|
|
||||||
ddata.data = memcpy(ddata.data, org_ddata->content.mem, org_ddata->content.len);
|
|
||||||
ddata.len = org_ddata->content.len;
|
|
||||||
if (drop->drop_cb)
|
|
||||||
drop->drop_cb(drop->drop_data, event->object, &ddata);
|
|
||||||
free(ddata.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI Eina_Bool
|
|
||||||
elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data,
|
|
||||||
Elm_Xdnd_Action action,
|
|
||||||
Elm_Drag_Icon_Create_Cb icon_create_cb, void *icon_create_data,
|
|
||||||
Elm_Drag_Pos drag_pos_cb, void *drag_pos_data,
|
|
||||||
Elm_Drag_Accept drag_accept_cb, void *drag_accept_data,
|
|
||||||
Elm_Drag_State drag_done_cb, void *drag_done_data)
|
|
||||||
{
|
|
||||||
if (!data) return EINA_FALSE;
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
|
||||||
int seatid = 1;
|
|
||||||
Eina_Slice sl;
|
|
||||||
Dnd_Drag_Pos *pos = calloc(1, sizeof(Dnd_Drag_Pos));
|
|
||||||
Dnd_Drag_Accept *accept = calloc(1, sizeof(Dnd_Drag_Accept));
|
|
||||||
Dnd_Drag_Done *done = calloc(1, sizeof(Dnd_Drag_Done));
|
|
||||||
Dnd_Icon_Create *ic = calloc(1, sizeof(Dnd_Icon_Create));
|
|
||||||
if (!pos || !accept || !done || !ic) goto on_error;
|
|
||||||
|
|
||||||
pos->pos_data = drag_pos_data;
|
|
||||||
pos->pos_cb = drag_pos_cb;
|
|
||||||
|
|
||||||
accept->accept_data = drag_accept_data;
|
|
||||||
accept->accept_cb = drag_accept_cb;
|
|
||||||
|
|
||||||
done->done_data = drag_done_data;
|
|
||||||
done->done_cb = drag_done_cb;
|
|
||||||
done->pos = pos;
|
|
||||||
done->accept = accept;
|
|
||||||
|
|
||||||
efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_POS, _dnd_drag_pos_cb, pos);
|
|
||||||
efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_ACCEPT, _dnd_drag_accept_cb, accept);
|
|
||||||
efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_DONE, _dnd_drag_done_cb, done);
|
|
||||||
sl.mem = data;
|
|
||||||
sl.len = strlen(data);
|
|
||||||
#ifdef HAVE_ELEMENTARY_WL2
|
|
||||||
if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ic->icon_data = icon_create_data;
|
|
||||||
ic->icon_cb = icon_create_cb;
|
|
||||||
efl_ui_selection_manager_drag_start(sel_man, obj, (Efl_Ui_Selection_Format)format, sl,
|
|
||||||
(Efl_Ui_Selection_Action)action,
|
|
||||||
ic, _dnd_icon_create_cb, NULL, seatid);
|
|
||||||
|
|
||||||
return EINA_TRUE;
|
|
||||||
|
|
||||||
on_error:
|
|
||||||
if (pos) free(pos);
|
|
||||||
if (accept) free(accept);
|
|
||||||
if (done) free(done);
|
|
||||||
if (ic) free(ic);
|
|
||||||
|
|
||||||
return EINA_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI Eina_Bool
|
|
||||||
elm_drag_action_set(Evas_Object *obj, Elm_Xdnd_Action action)
|
|
||||||
{
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
|
||||||
int seatid = 1;
|
|
||||||
|
|
||||||
#ifdef HAVE_ELEMENTARY_WL2
|
|
||||||
if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
|
|
||||||
#endif
|
|
||||||
efl_ui_selection_manager_drag_action_set(sel_man, obj, (Efl_Ui_Selection_Action)action, seatid);
|
|
||||||
|
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI Eina_Bool
|
|
||||||
elm_drag_cancel(Evas_Object *obj)
|
|
||||||
{
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
|
||||||
int seatid = 1;
|
|
||||||
|
|
||||||
#ifdef HAVE_ELEMENTARY_WL2
|
|
||||||
if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
efl_ui_selection_manager_drag_cancel(sel_man, obj, seatid);
|
|
||||||
|
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_drop_obj_del_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
|
|
||||||
{
|
|
||||||
Eina_List *drop_list;
|
|
||||||
Dnd_Drop *drop;
|
|
||||||
|
|
||||||
drop_list = efl_key_data_get(obj, "__drop_list");
|
|
||||||
EINA_LIST_FREE(drop_list, drop)
|
|
||||||
{
|
|
||||||
efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_ENTER,
|
|
||||||
_dnd_drag_enter_leave_cb, drop->enter);
|
|
||||||
efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_LEAVE,
|
|
||||||
_dnd_drag_enter_leave_cb, drop->leave);
|
|
||||||
efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_POS,
|
|
||||||
_dnd_drag_pos_cb, drop->pos);
|
|
||||||
efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_DROP,
|
|
||||||
_dnd_drop_cb, drop);
|
|
||||||
free(drop->enter);
|
|
||||||
free(drop->leave);
|
|
||||||
free(drop->pos);
|
|
||||||
free(drop);
|
|
||||||
}
|
|
||||||
efl_key_data_set(obj, "__drop_list", NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI Eina_Bool
|
|
||||||
elm_drop_target_add(Evas_Object *obj, Elm_Sel_Format format,
|
|
||||||
Elm_Drag_State enter_cb, void *enter_data,
|
|
||||||
Elm_Drag_State leave_cb, void *leave_data,
|
|
||||||
Elm_Drag_Pos pos_cb, void *pos_data,
|
|
||||||
Elm_Drop_Cb drop_cb, void *drop_data)
|
|
||||||
{
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
|
||||||
int seatid = 1;
|
|
||||||
Dnd_Drag_State *enter, *leave;
|
|
||||||
Dnd_Drag_Pos *pos;
|
|
||||||
Dnd_Drop *drop;
|
|
||||||
Eina_List *drop_list;
|
|
||||||
|
|
||||||
enter = calloc(1, sizeof(Dnd_Drag_State));
|
|
||||||
leave = calloc(1, sizeof(Dnd_Drag_State));
|
|
||||||
pos = calloc(1, sizeof(Dnd_Drag_Pos));
|
|
||||||
drop = calloc(1, sizeof(Dnd_Drop));
|
|
||||||
if (!enter || !leave || !pos || !drop) goto on_error;
|
|
||||||
#ifdef HAVE_ELEMENTARY_WL2
|
|
||||||
if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
|
|
||||||
#endif
|
|
||||||
enter->state_cb = enter_cb;
|
|
||||||
enter->state_data = enter_data;
|
|
||||||
leave->state_cb = leave_cb;
|
|
||||||
leave->state_data = leave_data;
|
|
||||||
pos->pos_cb = pos_cb;
|
|
||||||
pos->pos_data = pos_data;
|
|
||||||
drop->obj = obj;
|
|
||||||
drop->format = format;
|
|
||||||
drop->drop_cb = drop_cb;
|
|
||||||
drop->drop_data = drop_data;
|
|
||||||
drop->enter = enter;
|
|
||||||
drop->leave = leave;
|
|
||||||
drop->pos = pos;
|
|
||||||
|
|
||||||
drop_list = efl_key_data_get(obj, "__drop_list");
|
|
||||||
drop_list = eina_list_append(drop_list, drop);
|
|
||||||
efl_key_data_set(obj, "__drop_list", drop_list);
|
|
||||||
evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
|
|
||||||
_drop_obj_del_cb, NULL);
|
|
||||||
efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_ENTER,
|
|
||||||
_dnd_drag_enter_leave_cb, enter);
|
|
||||||
efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_LEAVE,
|
|
||||||
_dnd_drag_enter_leave_cb, leave);
|
|
||||||
efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_POS,
|
|
||||||
_dnd_drag_pos_cb, pos);
|
|
||||||
efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_DROP,
|
|
||||||
_dnd_drop_cb, drop);
|
|
||||||
efl_ui_selection_manager_drop_target_add(sel_man, obj, (Efl_Ui_Selection_Format)format, seatid);
|
|
||||||
|
|
||||||
return EINA_TRUE;
|
|
||||||
|
|
||||||
on_error:
|
|
||||||
if (enter) free(enter);
|
|
||||||
if (leave) free(leave);
|
|
||||||
if (pos) free(pos);
|
|
||||||
if (drop) free(drop);
|
|
||||||
|
|
||||||
return EINA_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI Eina_Bool
|
|
||||||
elm_drop_target_del(Evas_Object *obj, Elm_Sel_Format format,
|
|
||||||
Elm_Drag_State enter_cb, void *enter_data,
|
|
||||||
Elm_Drag_State leave_cb, void *leave_data,
|
|
||||||
Elm_Drag_Pos pos_cb, void *pos_data,
|
|
||||||
Elm_Drop_Cb drop_cb, void *drop_data)
|
|
||||||
{
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
|
||||||
int seatid = 1;
|
|
||||||
//Eina_List *l, *l2;
|
|
||||||
Eina_List *drop_list;
|
|
||||||
Dnd_Drop *drop;
|
|
||||||
|
|
||||||
#ifdef HAVE_ELEMENTARY_WL2
|
|
||||||
if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
drop_list = efl_key_data_get(obj, "__drop_list");
|
|
||||||
drop = eina_list_data_get(drop_list);
|
|
||||||
if (drop &&
|
|
||||||
(drop->format == format) &&
|
|
||||||
(drop->enter->state_cb == enter_cb) &&
|
|
||||||
(drop->enter->state_data == enter_data) &&
|
|
||||||
(drop->leave->state_cb == leave_cb) &&
|
|
||||||
(drop->leave->state_data == leave_data) &&
|
|
||||||
(drop->pos->pos_cb == pos_cb) &&
|
|
||||||
(drop->pos->pos_data == pos_data) &&
|
|
||||||
(drop->drop_cb == drop_cb) &&
|
|
||||||
(drop->drop_data == drop_data))
|
|
||||||
{
|
|
||||||
drop_list = eina_list_remove(drop_list, drop);
|
|
||||||
efl_key_data_set(obj, "__drop_list", drop_list);
|
|
||||||
evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _drop_obj_del_cb);
|
|
||||||
efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_ENTER,
|
|
||||||
_dnd_drag_enter_leave_cb, drop->enter);
|
|
||||||
efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_LEAVE,
|
|
||||||
_dnd_drag_enter_leave_cb, drop->leave);
|
|
||||||
efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_POS,
|
|
||||||
_dnd_drag_pos_cb, drop->pos);
|
|
||||||
efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_DROP,
|
|
||||||
_dnd_drop_cb, drop);
|
|
||||||
free(drop->enter);
|
|
||||||
free(drop->leave);
|
|
||||||
free(drop->pos);
|
|
||||||
free(drop);
|
|
||||||
}
|
|
||||||
efl_ui_selection_manager_drop_target_del(sel_man, obj, (Efl_Ui_Selection_Format)format, seatid);
|
|
||||||
|
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Efl_Object *
|
|
||||||
_dnd_item_func(void *data, Efl_Canvas_Object *item, Eina_Position2D pos, Eina_Position2D *pos_ret)
|
|
||||||
{
|
|
||||||
Elm_Xy_Item_Get_Cb item_get_cb = data;
|
|
||||||
Evas_Coord x, y;
|
|
||||||
Efl_Object *obj = NULL;
|
|
||||||
|
|
||||||
x = y = 0;
|
|
||||||
if (item_get_cb)
|
|
||||||
obj = item_get_cb(item, pos.x, pos.y, &x, &y);
|
|
||||||
if (pos_ret)
|
|
||||||
{
|
|
||||||
pos_ret->x = x;
|
|
||||||
pos_ret->y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
EOLIAN static void
|
||||||
_dnd_cont_drag_pos_cb(void *data, const Efl_Event *event)
|
_efl_ui_dnd_efl_object_invalidate(Eo *obj, Efl_Ui_Dnd_Data *pd)
|
||||||
{
|
{
|
||||||
Dnd_Cont_Drag_Pos *pos = data;
|
if (pd->registered)
|
||||||
Efl_Dnd_Drag_Pos *ddata = event->info;
|
|
||||||
Evas_Coord xret = 0, yret = 0;
|
|
||||||
|
|
||||||
if (pos->item_get_cb)
|
|
||||||
{
|
{
|
||||||
Evas_Coord x, y;
|
_drop_event_unregister(obj);
|
||||||
evas_object_geometry_get(event->object, &x, &y, NULL, NULL);
|
|
||||||
pos->item_get_cb(event->object, ddata->pos.x + x, ddata->pos.y + y,
|
|
||||||
&xret, &yret);
|
|
||||||
}
|
}
|
||||||
if (pos->pos_cb)
|
efl_invalidate(efl_super(obj, EFL_UI_DND_MIXIN));
|
||||||
pos->pos_cb(pos->pos_data, event->object, ddata->item, ddata->pos.x, ddata->pos.y,
|
|
||||||
xret, yret, (Elm_Xdnd_Action)ddata->action);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
#define IS_DROP_EVENT(D) ( \
|
||||||
_dnd_cont_drop_cb(void *data, const Efl_Event *event)
|
(D == EFL_UI_DND_EVENT_DROP_POSITION_CHANGED) || \
|
||||||
|
(D == EFL_UI_DND_EVENT_DROP_DROPPED) || \
|
||||||
|
(D == EFL_UI_DND_EVENT_DROP_LEFT) || \
|
||||||
|
(D == EFL_UI_DND_EVENT_DROP_ENTERED) \
|
||||||
|
)
|
||||||
|
|
||||||
|
EOLIAN static Efl_Object*
|
||||||
|
_efl_ui_dnd_efl_object_finalize(Eo *obj, Efl_Ui_Dnd_Data *pd)
|
||||||
{
|
{
|
||||||
Dnd_Cont_Drop *drop = data;
|
if (pd->registered)
|
||||||
Efl_Ui_Selection_Data *org_ddata = event->info;
|
_drop_event_register(obj);
|
||||||
Elm_Selection_Data ddata;
|
|
||||||
Evas_Coord xret = 0, yret = 0;
|
|
||||||
|
|
||||||
ddata.x = org_ddata->pos.x;
|
return efl_finalize(efl_super(obj, EFL_UI_DND_MIXIN));
|
||||||
ddata.y = org_ddata->pos.y;
|
}
|
||||||
ddata.format = (Elm_Sel_Format)org_ddata->format;
|
|
||||||
ddata.action = (Elm_Xdnd_Action)org_ddata->action;
|
|
||||||
ddata.data = calloc(1, org_ddata->content.len);
|
|
||||||
if (!ddata.data) return;
|
|
||||||
ddata.data = memcpy(ddata.data, org_ddata->content.mem, org_ddata->content.len);
|
|
||||||
ddata.len = org_ddata->content.len;
|
|
||||||
|
|
||||||
if (drop->item_get_cb)
|
|
||||||
|
EOLIAN static Eina_Bool
|
||||||
|
_efl_ui_dnd_efl_object_event_callback_priority_add(Eo *obj, Efl_Ui_Dnd_Data *pd,
|
||||||
|
const Efl_Event_Description *desc,
|
||||||
|
Efl_Callback_Priority priority,
|
||||||
|
Efl_Event_Cb func,
|
||||||
|
const void *user_data)
|
||||||
|
{
|
||||||
|
if (IS_DROP_EVENT(desc) && !pd->registered)
|
||||||
|
{
|
||||||
|
pd->registered = EINA_TRUE;
|
||||||
|
if (efl_finalized_get(obj))
|
||||||
|
_drop_event_register(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
return efl_event_callback_priority_add(efl_super(obj, EFL_UI_DND_MIXIN), desc, priority, func, user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN static Eina_Bool
|
||||||
|
_efl_ui_dnd_efl_object_event_callback_array_priority_add(Eo *obj, Efl_Ui_Dnd_Data *pd,
|
||||||
|
const Efl_Callback_Array_Item *array,
|
||||||
|
Efl_Callback_Priority priority,
|
||||||
|
const void *user_data)
|
||||||
|
{
|
||||||
|
for (int i = 0; array[i].desc; ++i)
|
||||||
{
|
{
|
||||||
Evas_Coord x, y;
|
if (IS_DROP_EVENT(array[i].desc) && !pd->registered)
|
||||||
evas_object_geometry_get(event->object, &x, &y, NULL, NULL);
|
|
||||||
drop->item_get_cb(event->object, ddata.x + x, ddata.y + y,
|
|
||||||
&xret, &yret);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (drop->drop_cb)
|
|
||||||
drop->drop_cb(drop->drop_data, event->object, org_ddata->item,
|
|
||||||
&ddata, xret, yret);
|
|
||||||
free(ddata.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_cont_drop_free_data(Evas_Object *obj)
|
|
||||||
{
|
|
||||||
Eina_List *cont_drop_list;
|
|
||||||
Dnd_Cont_Drop *drop;
|
|
||||||
|
|
||||||
cont_drop_list = efl_key_data_get(obj, "__cont_drop_item");
|
|
||||||
drop = eina_list_data_get(cont_drop_list);
|
|
||||||
if (drop)
|
|
||||||
{
|
|
||||||
efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_ENTER,
|
|
||||||
_dnd_drag_enter_leave_cb, drop->enter);
|
|
||||||
efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_LEAVE,
|
|
||||||
_dnd_drag_enter_leave_cb, drop->leave);
|
|
||||||
efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_POS,
|
|
||||||
_dnd_cont_drag_pos_cb, drop->pos);
|
|
||||||
efl_event_callback_del(drop->obj, EFL_UI_DND_EVENT_DRAG_DROP,
|
|
||||||
_dnd_cont_drop_cb, drop);
|
|
||||||
free(drop->enter);
|
|
||||||
free(drop->leave);
|
|
||||||
free(drop->pos);
|
|
||||||
cont_drop_list = eina_list_remove(cont_drop_list, drop);
|
|
||||||
efl_key_data_set(obj, "__cont_drop_item", cont_drop_list);
|
|
||||||
free(drop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_cont_drop_obj_del_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *info EINA_UNUSED)
|
|
||||||
{
|
|
||||||
_cont_drop_free_data(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI Eina_Bool
|
|
||||||
elm_drop_item_container_add(Evas_Object *obj,
|
|
||||||
Elm_Sel_Format format,
|
|
||||||
Elm_Xy_Item_Get_Cb item_get_cb,
|
|
||||||
Elm_Drag_State enter_cb, void *enter_data,
|
|
||||||
Elm_Drag_State leave_cb, void *leave_data,
|
|
||||||
Elm_Drag_Item_Container_Pos pos_cb, void *pos_data,
|
|
||||||
Elm_Drop_Item_Container_Cb drop_cb, void *drop_data)
|
|
||||||
{
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
|
||||||
int seatid = 1;
|
|
||||||
Dnd_Drag_State *enter = NULL, *leave = NULL;
|
|
||||||
Dnd_Cont_Drag_Pos *pos = NULL;
|
|
||||||
Dnd_Cont_Drop *drop = NULL;
|
|
||||||
Eina_List *cont_drop_list;
|
|
||||||
|
|
||||||
enter = calloc(1, sizeof(Dnd_Drag_State));
|
|
||||||
leave = calloc(1, sizeof(Dnd_Drag_State));
|
|
||||||
pos = calloc(1, sizeof(Dnd_Cont_Drag_Pos));
|
|
||||||
drop = calloc(1, sizeof(Dnd_Cont_Drop));
|
|
||||||
if (!enter || !leave || !pos || !drop) goto on_error;
|
|
||||||
#ifdef HAVE_ELEMENTARY_WL2
|
|
||||||
if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enter->state_cb = enter_cb;
|
|
||||||
enter->state_data = enter_data;
|
|
||||||
leave->state_cb = leave_cb;
|
|
||||||
leave->state_data = leave_data;
|
|
||||||
pos->pos_cb = pos_cb;
|
|
||||||
pos->pos_data = pos_data;
|
|
||||||
pos->item_get_cb = item_get_cb;
|
|
||||||
drop->obj = obj;
|
|
||||||
drop->format = format;
|
|
||||||
drop->drop_cb = drop_cb;
|
|
||||||
drop->drop_data = drop_data;
|
|
||||||
drop->enter = enter;
|
|
||||||
drop->leave = leave;
|
|
||||||
drop->pos = pos;
|
|
||||||
|
|
||||||
cont_drop_list = efl_key_data_get(obj, "__cont_drop_item");
|
|
||||||
cont_drop_list = eina_list_append(cont_drop_list, drop);
|
|
||||||
efl_key_data_set(obj, "__cont_drop_item", cont_drop_list);
|
|
||||||
evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
|
|
||||||
_cont_drop_obj_del_cb, NULL);
|
|
||||||
efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_ENTER,
|
|
||||||
_dnd_drag_enter_leave_cb, enter);
|
|
||||||
efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_LEAVE,
|
|
||||||
_dnd_drag_enter_leave_cb, leave);
|
|
||||||
efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_POS,
|
|
||||||
_dnd_cont_drag_pos_cb, pos);
|
|
||||||
efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_DROP,
|
|
||||||
_dnd_cont_drop_cb, drop);
|
|
||||||
efl_ui_selection_manager_container_drop_item_add(sel_man, obj, (Efl_Ui_Selection_Format)format,
|
|
||||||
item_get_cb, _dnd_item_func, NULL,
|
|
||||||
seatid);
|
|
||||||
|
|
||||||
return EINA_TRUE;
|
|
||||||
|
|
||||||
on_error:
|
|
||||||
if (enter) free(enter);
|
|
||||||
if (leave) free(leave);
|
|
||||||
if (pos) free(pos);
|
|
||||||
if (drop) free(drop);
|
|
||||||
|
|
||||||
return EINA_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI Eina_Bool
|
|
||||||
elm_drop_item_container_del(Evas_Object *obj)
|
|
||||||
{
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
|
||||||
int seatid = 1;
|
|
||||||
|
|
||||||
#ifdef HAVE_ELEMENTARY_WL2
|
|
||||||
if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
_cont_drop_free_data(obj);
|
|
||||||
evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _cont_drop_obj_del_cb);
|
|
||||||
efl_ui_selection_manager_container_drop_item_del(sel_man, obj, seatid);
|
|
||||||
|
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_cont_drag_data_func(void *data, Efl_Object *obj, Efl_Ui_Selection_Format *format,
|
|
||||||
Eina_Rw_Slice *drag_data, Efl_Ui_Selection_Action *action)
|
|
||||||
{
|
|
||||||
Item_Container_Drag_Info *di;
|
|
||||||
|
|
||||||
di = data;
|
|
||||||
if (!di) return;
|
|
||||||
di->data_get_cb(obj, di->it, &di->user_info);
|
|
||||||
if (format) *format = (Efl_Ui_Selection_Format)di->user_info.format;
|
|
||||||
if (drag_data)
|
|
||||||
{
|
|
||||||
if (di->user_info.data)
|
|
||||||
{
|
{
|
||||||
drag_data->mem = (void *)di->user_info.data;
|
pd->registered = EINA_TRUE;
|
||||||
drag_data->len = strlen(di->user_info.data);
|
if (efl_finalized_get(obj))
|
||||||
|
_drop_event_register(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (action) *action = (Efl_Ui_Selection_Action)di->user_info.action;
|
return efl_event_callback_array_priority_add(efl_super(obj, EFL_UI_DND_MIXIN), array, priority, user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Eina_List *
|
#define EFL_UI_DND_EXTRA_OPS \
|
||||||
_cont_drag_icon_list_create(void *data, Efl_Object *obj EINA_UNUSED)
|
EFL_OBJECT_OP_FUNC(efl_event_callback_priority_add, _efl_ui_dnd_efl_object_event_callback_priority_add), \
|
||||||
{
|
EFL_OBJECT_OP_FUNC(efl_event_callback_array_priority_add, _efl_ui_dnd_efl_object_event_callback_array_priority_add), \
|
||||||
Item_Container_Drag_Info *di;
|
|
||||||
|
|
||||||
di = data;
|
|
||||||
return di->user_info.icons;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Efl_Object *
|
|
||||||
_cont_drag_icon_create(void *data, Efl_Object *win, Efl_Object *drag_obj EINA_UNUSED, Eina_Position2D *pos_ret)
|
|
||||||
{
|
|
||||||
Item_Container_Drag_Info *di;
|
|
||||||
Elm_Object_Item *it = NULL;
|
|
||||||
|
|
||||||
di = data;
|
|
||||||
if (!di) return NULL;
|
|
||||||
if (!di->user_info.createicon) return NULL;
|
|
||||||
it = di->user_info.createicon(di->user_info.createdata, win, &pos_ret->x, &pos_ret->y);
|
|
||||||
di->it = it;
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Efl_Object *
|
|
||||||
_cont_drag_item_func(void *data, Efl_Canvas_Object *item, Eina_Position2D pos, Eina_Position2D *pos_ret)
|
|
||||||
{
|
|
||||||
Item_Container_Drag_Info *di = data;
|
|
||||||
Evas_Coord x, y;
|
|
||||||
Efl_Object *obj = NULL;
|
|
||||||
|
|
||||||
x = y = 0;
|
|
||||||
if (di->item_get_cb)
|
|
||||||
obj = di->item_get_cb(item, pos.x, pos.y, &x, &y);
|
|
||||||
if (pos_ret)
|
|
||||||
{
|
|
||||||
pos_ret->x = x;
|
|
||||||
pos_ret->y = y;
|
|
||||||
}
|
|
||||||
di->it = obj;
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_cont_drag_free_data(Evas_Object *obj)
|
|
||||||
{
|
|
||||||
Eina_List *di_list;
|
|
||||||
Item_Container_Drag_Info *di;
|
|
||||||
|
|
||||||
di_list = efl_key_data_get(obj, "__cont_drag_item");
|
|
||||||
di = eina_list_data_get(di_list);
|
|
||||||
di_list = eina_list_remove(di_list, di);
|
|
||||||
efl_key_data_set(obj, "__cont_drag_item", di_list);
|
|
||||||
free(di);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_cont_drag_obj_del_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event EINA_UNUSED)
|
|
||||||
{
|
|
||||||
_cont_drag_free_data(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI Eina_Bool
|
|
||||||
elm_drag_item_container_add(Evas_Object *obj, double anim_tm, double tm_to_drag,
|
|
||||||
Elm_Xy_Item_Get_Cb item_get_cb, Elm_Item_Container_Data_Get_Cb data_get_cb)
|
|
||||||
{
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
|
||||||
int seatid = 1;
|
|
||||||
Eina_List *di_list;
|
|
||||||
Item_Container_Drag_Info *di;
|
|
||||||
|
|
||||||
#ifdef HAVE_ELEMENTARY_WL2
|
|
||||||
if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
di = calloc(1, sizeof(Item_Container_Drag_Info));
|
|
||||||
if (!di) return EINA_FALSE;
|
|
||||||
di->data_get_cb = data_get_cb;
|
|
||||||
di->item_get_cb = item_get_cb;
|
|
||||||
di_list = efl_key_data_get(obj, "__cont_drag_item");
|
|
||||||
di_list = eina_list_append(di_list, di);
|
|
||||||
efl_key_data_set(obj, "__cont_drag_item", di_list);
|
|
||||||
evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _cont_drag_obj_del_cb, NULL);
|
|
||||||
efl_ui_selection_manager_container_drag_item_add(sel_man, obj, tm_to_drag, anim_tm,
|
|
||||||
di, _cont_drag_data_func, NULL,
|
|
||||||
di, _cont_drag_item_func, NULL,
|
|
||||||
di, _cont_drag_icon_create, NULL,
|
|
||||||
di, _cont_drag_icon_list_create, NULL,
|
|
||||||
seatid);
|
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI Eina_Bool
|
|
||||||
elm_drag_item_container_del(Evas_Object *obj)
|
|
||||||
{
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
|
||||||
int seatid = 1;
|
|
||||||
|
|
||||||
#ifdef HAVE_ELEMENTARY_WL2
|
|
||||||
if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
_cont_drag_free_data(obj);
|
|
||||||
evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _cont_drag_obj_del_cb);
|
|
||||||
efl_ui_selection_manager_container_drag_item_del(sel_man, obj, seatid);
|
|
||||||
|
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "efl_ui_dnd.eo.c"
|
#include "efl_ui_dnd.eo.c"
|
||||||
#include "efl_ui_dnd_container.eo.c"
|
|
||||||
|
|
|
@ -1,63 +1,93 @@
|
||||||
import efl_ui_dnd_types;
|
import eina_types;
|
||||||
|
|
||||||
mixin @beta Efl.Ui.Dnd {
|
struct @beta Efl.Ui.Drop_Event {
|
||||||
data: null;
|
[[Information sent along Drag & Drop events.]]
|
||||||
|
position : Eina.Position2D; [[The position where the drop event occurred, in window coordinates.]]
|
||||||
|
seat : uint; [[Which seat triggered the event.]]
|
||||||
|
available_types : accessor<string>; [[Types with automatic conversion available. Use one of them in the call to
|
||||||
|
@Efl.Ui.Dnd.drop_data_get.
|
||||||
|
|
||||||
|
Types are IANA MIME types:
|
||||||
|
https://www.iana.org/assignments/media-types/media-types.xhtml
|
||||||
|
]]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct @beta Efl.Ui.Drop_Dropped_Event {
|
||||||
|
[[Information sent along Drop events.]]
|
||||||
|
dnd : Efl.Ui.Drop_Event; [[Common information.]]
|
||||||
|
action : string; [[Requested action to perform upon reception of this data.]]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct @beta Efl.Ui.Drag_Started_Event {
|
||||||
|
[[Information sent along @Efl.Ui.Drag_Started_Event events.]]
|
||||||
|
seat : uint; [[Which seat triggered the event.]]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct @beta Efl.Ui.Drag_Finished_Event {
|
||||||
|
[[Information sent along @Efl.Ui.Drag_Finished_Event events.]]
|
||||||
|
seat : uint; [[Which seat triggered the event.]]
|
||||||
|
accepted : bool; [[$true if the operation completed with a Drop, or $false if it was cancelled.]]
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin @beta Efl.Ui.Dnd requires Efl.Object {
|
||||||
|
[[This mixin provides the ability to interact with the system's Drag & Drop facilities.
|
||||||
|
|
||||||
|
Applications starting a Drag & Drop operation operation are said to perform a "Drag" and use
|
||||||
|
the methods prefixed "drag_".
|
||||||
|
On the other hand, applications receiving dragged content are said to perform a "Drop" operation and use
|
||||||
|
the methods prefixed "drop_".
|
||||||
|
]]
|
||||||
methods {
|
methods {
|
||||||
drag_start {
|
drag_start {
|
||||||
[[Start a drag and drop process at the drag side.
|
[[Starts a drag from this client.
|
||||||
During dragging, there are three events emitted as belows:
|
|
||||||
- EFL_UI_DND_EVENT_DRAG_POS
|
@[Efl.Ui.Dnd.drag,started] is emitted each time a successful drag is started.
|
||||||
- EFL_UI_DND_EVENT_DRAG_ACCEPT
|
@[Efl.Ui.Dnd.drag,finished] is emitted every time a drag is finished.
|
||||||
- EFL_UI_DND_EVENT_DRAG_DONE
|
|
||||||
]]
|
]]
|
||||||
params {
|
params {
|
||||||
@in format: Efl.Ui.Selection_Format; [[The data format]]
|
content : Eina.Content @by_ref; [[The content being dragged.]]
|
||||||
@in data: Eina.Slice; [[The drag data]]
|
@in action: string; [[Requested action to perform by the receiver once content is transferred.]]
|
||||||
@in action: Efl.Ui.Selection_Action; [[Action when data is transferred]]
|
@in seat: uint; [[Seat starting the drag operation. When in doubt use 0.]]
|
||||||
@in icon_func: Efl.Dnd.Drag_Icon_Create; [[Function pointer to create icon]]
|
|
||||||
@in seat: uint; [[Specified seat for multiple seats case.]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drag_action_set {
|
|
||||||
[[Set the action for the drag]]
|
|
||||||
params {
|
|
||||||
@in action: Efl.Ui.Selection_Action; [[Drag action]]
|
|
||||||
@in seat: uint; [[Specified seat for multiple seats case.]]
|
|
||||||
}
|
}
|
||||||
|
return : Efl.Content; [[An Efl.Ui element which you can use to render a visual representation
|
||||||
|
of the content being dragged (like a thumbnail, for example).
|
||||||
|
Use @Efl.Content.content.set on it to do so.]]
|
||||||
}
|
}
|
||||||
drag_cancel {
|
drag_cancel {
|
||||||
[[Cancel the on-going drag]]
|
[[Cancels an on-going drag operation.]]
|
||||||
params {
|
params {
|
||||||
@in seat: uint; [[Specified seat for multiple seats case.]]
|
@in seat: uint; [[Seat that started the drag operation. When in doubt use 0.]]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drop_target_add {
|
drop_data_get {
|
||||||
[[Make the current object as drop target.
|
[[Retrieves the dropped data.]]
|
||||||
There are four events emitted:
|
|
||||||
- EFL_UI_DND_EVENT_DRAG_ENTER
|
|
||||||
- EFL_UI_DND_EVENT_DRAG_LEAVE
|
|
||||||
- EFL_UI_DND_EVENT_DRAG_POS
|
|
||||||
- EFL_UI_DND_EVENT_DRAG_DROP.]]
|
|
||||||
params {
|
params {
|
||||||
@in format: Efl.Ui.Selection_Format; [[Accepted data format]]
|
@in seat: uint; [[Seat that started the drag operation. When in doubt use 0.]]
|
||||||
@in seat: uint; [[Specified seat for multiple seats case.]]
|
@in acceptable_types : iterator<string>; [[List of strings describing the type of content the application
|
||||||
}
|
can accept. Types are IANA MIME types:
|
||||||
}
|
https://www.iana.org/assignments/media-types/media-types.xhtml.]]
|
||||||
drop_target_del {
|
|
||||||
[[Delete the dropable status from object]]
|
|
||||||
params {
|
|
||||||
@in format: Efl.Ui.Selection_Format; [[Accepted data format]]
|
|
||||||
@in seat: uint; [[Specified seat for multiple seats case.]]
|
|
||||||
}
|
}
|
||||||
|
return : future<Eina.Content> @move; [[This future is fulfilled when the content is received (asynchronously)
|
||||||
|
and ready to use.
|
||||||
|
The Eina.Content specifies the type of the data.
|
||||||
|
If no matching type was found it returns an error.
|
||||||
|
]]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
events {
|
events {
|
||||||
/* FIXME: This is not very future-proof. Better return a struct. */
|
drop,entered : Efl.Ui.Drop_Event; [[Dragged content entered the window. Its type can already be checked with
|
||||||
drag,accept: ptr(bool); [[accept drag data]]
|
@.drop_data_get to react before it is dropped, for example.]]
|
||||||
drag,done: void; [[drag is done (mouse up)]]
|
drop,left : Efl.Ui.Drop_Event; [[Dragged content left the window.]]
|
||||||
drag,enter: void; [[called when the drag object enters this object]]
|
drop,position,changed : Efl.Ui.Drop_Event; [[Dragged content moved over the window. Its type can already be
|
||||||
drag,leave: void; [[called when the drag object leaves this object]]
|
checked with @.drop_data_get to react before it is dropped,
|
||||||
drag,pos: Efl.Dnd.Drag_Pos; [[called when the drag object changes drag position]]
|
for example.]]
|
||||||
drag,drop: Efl.Ui.Selection_Data; [[called when the drag object dropped on this object]]
|
drop,dropped : Efl.Ui.Drop_Dropped_Event; [[Dragged content was dropped over the window.]]
|
||||||
|
drag,started : Efl.Ui.Drag_Started_Event; [[A Drag operation started.]]
|
||||||
|
drag,finished : Efl.Ui.Drag_Finished_Event;[[A Drag operation finished.]]
|
||||||
|
}
|
||||||
|
implements {
|
||||||
|
Efl.Object.constructor;
|
||||||
|
Efl.Object.invalidate;
|
||||||
|
Efl.Object.finalize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
import efl_ui_dnd_types;
|
|
||||||
|
|
||||||
mixin @beta Efl.Ui.Dnd_Container {
|
|
||||||
methods {
|
|
||||||
@property drag_delay_time {
|
|
||||||
[[The time since mouse down happens to drag starts.]]
|
|
||||||
set {
|
|
||||||
}
|
|
||||||
get {
|
|
||||||
}
|
|
||||||
values {
|
|
||||||
time: double; [[The drag delay time]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drag_item_add {
|
|
||||||
[[This registers a drag for items in a container. Many items can be
|
|
||||||
dragged at a time. During dragging, there are three events emitted:
|
|
||||||
EFL_DND_EVENT_DRAG_POS, EFL_DND_EVENT_DRAG_ACCEPT, EFL_DND_EVENT_DRAG_DONE.]]
|
|
||||||
params {
|
|
||||||
@in data_func: Efl.Dnd.Drag_Data_Get; [[Data and its format]]
|
|
||||||
@in item_func: Efl.Dnd.Item_Get; [[Item to determine drag start]]
|
|
||||||
@in icon_func: Efl.Dnd.Drag_Icon_Create; [[Icon used during drag]]
|
|
||||||
@in icon_list_func: Efl.Dnd.Drag_Icon_List_Create; [[Icons used for animations CHECKING ]]
|
|
||||||
@in seat: uint; [[Specified seat for multiple seats case.]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drag_item_del {
|
|
||||||
[[Remove drag function of items in the container object.]]
|
|
||||||
params {
|
|
||||||
@in seat: uint; [[Specified seat for multiple seats case.]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drop_item_add {
|
|
||||||
params {
|
|
||||||
@in format: Efl.Ui.Selection_Format; [[Accepted data formats]]
|
|
||||||
@in item_func: Efl.Dnd.Item_Get; [[Get item at specific position]]
|
|
||||||
@in seat: uint; [[Specified seat for multiple seats case.]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drop_item_del {
|
|
||||||
params {
|
|
||||||
@in seat: uint; [[Specified seat for multiple seats case.]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
import efl_ui_selection_types;
|
|
||||||
|
|
||||||
function @beta Efl.Dnd.Drag_Icon_Create {
|
|
||||||
[[Function pointer for creating icon at the drag side.]]
|
|
||||||
params {
|
|
||||||
@in win: Efl.Canvas.Object; [[The window to create the objects relative to]]
|
|
||||||
@in drag_obj: Efl.Canvas.Object; [[The drag object]]
|
|
||||||
@out off: Eina.Position2D; [[Offset from the icon position to the cursor]]
|
|
||||||
}
|
|
||||||
return: Efl.Canvas.Object; [[The drag icon object]]
|
|
||||||
};
|
|
||||||
|
|
||||||
function @beta Efl.Dnd.Drag_Data_Get {
|
|
||||||
[[Function pointer for getting data and format at the drag side.]]
|
|
||||||
params {
|
|
||||||
@in obj: Efl.Canvas.Object; [[The container object]]
|
|
||||||
@out format: Efl.Ui.Selection_Format; [[Data format]]
|
|
||||||
@out drag_data: Eina.Rw_Slice; [[Data]]
|
|
||||||
@out action: Efl.Ui.Selection_Action; [[The drag action]]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function @beta Efl.Dnd.Item_Get {
|
|
||||||
[[Function pointer to find out which item is under position (x, y)]]
|
|
||||||
params {
|
|
||||||
@in obj: Efl.Canvas.Object; [[The container object]]
|
|
||||||
@in pos: Eina.Position2D; [[The coordinates to get item]]
|
|
||||||
@out posret: Eina.Position2D; [[position relative to item (left (-1), middle (0), right (1)]]
|
|
||||||
}
|
|
||||||
return: Efl.Object; [[Object under x,y coordinates or NULL if not found]]
|
|
||||||
};
|
|
||||||
|
|
||||||
function @beta Efl.Dnd.Drag_Icon_List_Create {
|
|
||||||
[[Function pointer to create list of icons at the drag side.
|
|
||||||
These icons are used for animation on combining selection icons
|
|
||||||
to one icon.]]
|
|
||||||
params {
|
|
||||||
@in obj: Efl.Canvas.Object; [[The container object]]
|
|
||||||
}
|
|
||||||
return: list<Efl.Canvas.Object>;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct @beta Efl.Dnd.Drag_Accept {
|
|
||||||
accepted: bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct @beta Efl.Dnd.Drag_Pos {
|
|
||||||
[[Dragging position information.]]
|
|
||||||
pos: Eina.Position2D; [[Evas Coordinate]]
|
|
||||||
action: Efl.Ui.Selection_Action; [[The drag action]]
|
|
||||||
format: Efl.Ui.Selection_Format; [[The drag format]]
|
|
||||||
item: Efl.Canvas.Object; [[The item object. It is only available for container object.]]
|
|
||||||
}
|
|
||||||
|
|
||||||
struct @beta Efl.Dnd.Drag_Item_Container_Drop {
|
|
||||||
[[Drop information for a drag&drop operation.]]
|
|
||||||
item: Efl.Canvas.Object; [[The item object]]
|
|
||||||
data: Efl.Ui.Selection_Data; [[The selection data]]
|
|
||||||
pos: Eina.Position2D; [[Position relative to item (left (-1), middle (0), right (1)]]
|
|
||||||
}
|
|
|
@ -9,278 +9,115 @@
|
||||||
#define MY_CLASS EFL_UI_SELECTION_MIXIN
|
#define MY_CLASS EFL_UI_SELECTION_MIXIN
|
||||||
#define MY_CLASS_NAME "Efl.Ui.Selection"
|
#define MY_CLASS_NAME "Efl.Ui.Selection"
|
||||||
|
|
||||||
#ifdef HAVE_ELEMENTARY_WL2
|
typedef struct {
|
||||||
Ecore_Wl2_Window *_wl_window_get(const Evas_Object *obj);
|
Ecore_Evas *ee;
|
||||||
#endif
|
Eina_Bool registered : 1;
|
||||||
|
} Efl_Ui_Selection_Data;
|
||||||
|
|
||||||
EOLIAN static void
|
static inline Ecore_Evas_Selection_Buffer
|
||||||
_efl_ui_selection_selection_get(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Type type, Efl_Ui_Selection_Format format,
|
_ee_buffer_get(Efl_Ui_Cnp_Buffer buffer)
|
||||||
void *data_func_data, Efl_Ui_Selection_Data_Ready data_func, Eina_Free_Cb data_func_free_cb, unsigned int seat)
|
|
||||||
{
|
{
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
if (buffer == EFL_UI_CNP_BUFFER_SELECTION)
|
||||||
efl_ui_selection_manager_selection_get(sel_man, obj, type, format,
|
return ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER;
|
||||||
data_func_data, data_func,
|
else
|
||||||
data_func_free_cb, seat);
|
return ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER;
|
||||||
}
|
}
|
||||||
|
|
||||||
EOLIAN static Eina_Future *
|
EOLIAN static Eina_Future*
|
||||||
_efl_ui_selection_selection_set(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Type type, Efl_Ui_Selection_Format format, Eina_Slice data, unsigned int seat)
|
_efl_ui_selection_selection_get(Eo *obj EINA_UNUSED, Efl_Ui_Selection_Data *pd, Efl_Ui_Cnp_Buffer buffer, unsigned int seat, Eina_Iterator *acceptable_types)
|
||||||
{
|
{
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
return ecore_evas_selection_get(pd->ee, seat, _ee_buffer_get(buffer), acceptable_types);
|
||||||
return efl_ui_selection_manager_selection_set(sel_man, obj, type, format, data, seat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EOLIAN static void
|
EOLIAN static void
|
||||||
_efl_ui_selection_selection_clear(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Type type, unsigned int seat)
|
_efl_ui_selection_selection_set(Eo *obj, Efl_Ui_Selection_Data *pd, Efl_Ui_Cnp_Buffer buffer, Eina_Content *content, unsigned int seat)
|
||||||
{
|
{
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
_register_selection_changed(obj);
|
||||||
efl_ui_selection_manager_selection_clear(sel_man, obj, type, seat);
|
ecore_evas_selection_set(pd->ee, seat, _ee_buffer_get(buffer), content);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN static void
|
||||||
|
_efl_ui_selection_selection_clear(Eo *obj EINA_UNUSED, Efl_Ui_Selection_Data *pd, Efl_Ui_Cnp_Buffer buffer, unsigned int seat)
|
||||||
|
{
|
||||||
|
ecore_evas_selection_set(pd->ee, seat, _ee_buffer_get(buffer), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
EOLIAN static Eina_Bool
|
EOLIAN static Eina_Bool
|
||||||
_efl_ui_selection_has_owner(Eo *obj, void *pd EINA_UNUSED, Efl_Ui_Selection_Type type, unsigned int seat)
|
_efl_ui_selection_has_selection(Eo *obj EINA_UNUSED, Efl_Ui_Selection_Data *pd, Efl_Ui_Cnp_Buffer buffer, unsigned int seat)
|
||||||
{
|
{
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
return ecore_evas_selection_exists(pd->ee, seat, _ee_buffer_get(buffer));
|
||||||
return efl_ui_selection_manager_selection_has_owner(sel_man, obj, type, seat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EOLIAN static Efl_Object*
|
||||||
////////// Support legacy APIs
|
_efl_ui_selection_efl_object_constructor(Eo *obj, Efl_Ui_Selection_Data *pd)
|
||||||
|
|
||||||
//TODO: Clear this list (when sel_man is deleted)
|
|
||||||
Eina_List *lost_cb_list = NULL;
|
|
||||||
|
|
||||||
#ifdef HAVE_ELEMENTARY_WL2
|
|
||||||
static Ecore_Evas *
|
|
||||||
_wl_is_wl(const Evas_Object *obj)
|
|
||||||
{
|
{
|
||||||
Ecore_Evas *ee;
|
if (!efl_constructor(efl_super(obj, EFL_UI_SELECTION_MIXIN)))
|
||||||
Evas *evas;
|
return NULL;
|
||||||
const char *engine_name;
|
|
||||||
|
|
||||||
if (!(evas = evas_object_evas_get(obj)))
|
pd->ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
|
||||||
return NULL;
|
|
||||||
if (!(ee = ecore_evas_ecore_evas_get(evas)))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
engine_name = ecore_evas_engine_name_get(ee);
|
return obj;
|
||||||
if (!strcmp(engine_name, ELM_BUFFER))
|
}
|
||||||
|
|
||||||
|
EOLIAN static void
|
||||||
|
_efl_ui_selection_efl_object_invalidate(Eo *obj, Efl_Ui_Selection_Data *pd)
|
||||||
|
{
|
||||||
|
if (pd->registered)
|
||||||
{
|
{
|
||||||
ee = ecore_evas_buffer_ecore_evas_parent_get(ee);
|
_selection_changed_event_unregister(obj);
|
||||||
if (!ee) return NULL;
|
|
||||||
engine_name = ecore_evas_engine_name_get(ee);
|
|
||||||
}
|
}
|
||||||
if (!strncmp(engine_name, "wayland", sizeof("wayland") - 1))
|
efl_invalidate(efl_super(obj, EFL_UI_SELECTION_MIXIN));
|
||||||
return ee;
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
EOLIAN static Eina_Bool
|
||||||
_wl_default_seat_id_get(Evas_Object *obj)
|
_efl_ui_selection_efl_object_event_callback_priority_add(Eo *obj, Efl_Ui_Selection_Data *pd,
|
||||||
|
const Efl_Event_Description *desc,
|
||||||
|
Efl_Callback_Priority priority,
|
||||||
|
Efl_Event_Cb func,
|
||||||
|
const void *user_data)
|
||||||
{
|
{
|
||||||
Ecore_Wl2_Window *win = _wl_window_get(obj);
|
if (desc == EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED && !pd->registered)
|
||||||
Eo *seat, *parent2, *ewin;
|
{
|
||||||
Eina_Bool is_wl = EINA_FALSE;
|
|
||||||
|
|
||||||
if (obj)
|
pd->registered = EINA_TRUE;
|
||||||
|
if (efl_finalized_get(obj))
|
||||||
|
_selection_changed_event_register(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
return efl_event_callback_priority_add(efl_super(obj, EFL_UI_SELECTION_MIXIN), desc, priority, func, user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN static Eina_Bool
|
||||||
|
_efl_ui_selection_efl_object_event_callback_array_priority_add(Eo *obj, Efl_Ui_Selection_Data *pd,
|
||||||
|
const Efl_Callback_Array_Item *array,
|
||||||
|
Efl_Callback_Priority priority,
|
||||||
|
const void *user_data)
|
||||||
|
{
|
||||||
|
for (int i = 0; array[i].desc; ++i)
|
||||||
{
|
{
|
||||||
if (_wl_is_wl(obj)) is_wl = EINA_TRUE;
|
if (array[i].desc == EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED && !pd->registered)
|
||||||
if (efl_isa(obj, EFL_UI_WIDGET_CLASS))
|
|
||||||
{
|
{
|
||||||
Eo *top = elm_widget_top_get(obj);
|
pd->registered = EINA_TRUE;
|
||||||
if (efl_isa(top, EFL_UI_WIN_INLINED_CLASS))
|
if (efl_finalized_get(obj))
|
||||||
{
|
_selection_changed_event_register(obj);
|
||||||
parent2 = efl_ui_win_inlined_parent_get(top);
|
|
||||||
if (parent2) obj = elm_widget_top_get(parent2) ?: parent2;
|
|
||||||
}
|
|
||||||
/* fake win means canvas seat id will not match protocol seat id */
|
|
||||||
ewin = elm_win_get(obj);
|
|
||||||
if (elm_win_type_get(ewin) == ELM_WIN_FAKE) obj = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return efl_event_callback_array_priority_add(efl_super(obj, EFL_UI_SELECTION_MIXIN), array, priority, user_data);
|
||||||
if (!obj)
|
|
||||||
{
|
|
||||||
if (is_wl)
|
|
||||||
{
|
|
||||||
Ecore_Wl2_Input *input;
|
|
||||||
Eina_Iterator *it;
|
|
||||||
|
|
||||||
it = ecore_wl2_display_inputs_get(ecore_wl2_window_display_get(win));
|
|
||||||
EINA_ITERATOR_FOREACH(it, input) break;
|
|
||||||
eina_iterator_free(it);
|
|
||||||
if (input)
|
|
||||||
return ecore_wl2_input_seat_id_get(input);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
seat = evas_default_device_get(evas_object_evas_get(obj), EFL_INPUT_DEVICE_TYPE_SEAT);
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(seat, 1);
|
|
||||||
return evas_device_seat_id_get(seat);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct _Cnp_Data_Cb_Wrapper Cnp_Data_Cb_Wrapper;
|
|
||||||
struct _Cnp_Data_Cb_Wrapper
|
|
||||||
{
|
|
||||||
void *udata;
|
|
||||||
Elm_Drop_Cb datacb;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
_selection_data_ready_cb(void *data, Efl_Object *obj, Efl_Ui_Selection_Data *seldata)
|
|
||||||
{
|
|
||||||
Cnp_Data_Cb_Wrapper *wdata = data;
|
|
||||||
if (!wdata) return;
|
|
||||||
Elm_Selection_Data ddata;
|
|
||||||
|
|
||||||
ddata.data = calloc(1, seldata->content.len + 1);
|
|
||||||
if (!ddata.data) return;
|
|
||||||
ddata.data = memcpy(ddata.data, seldata->content.mem, seldata->content.len);
|
|
||||||
ddata.len = seldata->content.len;
|
|
||||||
ddata.x = seldata->pos.x;
|
|
||||||
ddata.y = seldata->pos.y;
|
|
||||||
ddata.format = (Elm_Sel_Format)seldata->format;
|
|
||||||
ddata.action = (Elm_Xdnd_Action)seldata->action;
|
|
||||||
wdata->datacb(wdata->udata, obj, &ddata);
|
|
||||||
free(ddata.data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _Sel_Lost_Data Sel_Lost_Data;
|
|
||||||
struct _Sel_Lost_Data
|
EOLIAN static Efl_Object*
|
||||||
|
_efl_ui_selection_efl_object_finalize(Eo *obj, Efl_Ui_Selection_Data *pd)
|
||||||
{
|
{
|
||||||
const Evas_Object *obj;
|
if (pd->registered)
|
||||||
Elm_Sel_Type type;
|
_selection_changed_event_register(obj);
|
||||||
void *udata;
|
|
||||||
Elm_Selection_Loss_Cb loss_cb;
|
|
||||||
};
|
|
||||||
|
|
||||||
static Eina_Value
|
return efl_finalize(efl_super(obj, MY_CLASS));
|
||||||
_selection_lost_cb(void *data, const Eina_Value value)
|
|
||||||
{
|
|
||||||
Eina_List *l, *l2;
|
|
||||||
Sel_Lost_Data *ldata, *ldata2;
|
|
||||||
|
|
||||||
ldata = data;
|
|
||||||
EINA_LIST_FOREACH_SAFE(lost_cb_list, l, l2, ldata2)
|
|
||||||
{
|
|
||||||
if ((ldata->obj == ldata2->obj) &&
|
|
||||||
(ldata->type == ldata2->type))
|
|
||||||
{
|
|
||||||
ldata2->loss_cb(ldata2->udata, ldata2->type);
|
|
||||||
lost_cb_list = eina_list_remove(lost_cb_list, ldata2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(ldata);
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EAPI Eina_Bool
|
|
||||||
elm_cnp_selection_get(const Evas_Object *obj, Elm_Sel_Type type,
|
|
||||||
Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata)
|
|
||||||
{
|
|
||||||
int seatid = 1;
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get((Evas_Object *)obj);
|
|
||||||
Cnp_Data_Cb_Wrapper *wdata = calloc(1, sizeof(Cnp_Data_Cb_Wrapper));
|
|
||||||
|
|
||||||
if (!wdata) return EINA_FALSE;
|
#define EFL_UI_SELECTION_EXTRA_OPS \
|
||||||
|
EFL_OBJECT_OP_FUNC(efl_event_callback_priority_add, _efl_ui_selection_efl_object_event_callback_priority_add), \
|
||||||
#ifdef HAVE_ELEMENTARY_WL2
|
EFL_OBJECT_OP_FUNC(efl_event_callback_array_priority_add, _efl_ui_selection_efl_object_event_callback_array_priority_add), \
|
||||||
if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get((Evas_Object *)obj);
|
|
||||||
#endif
|
|
||||||
wdata->udata = udata;
|
|
||||||
wdata->datacb = datacb;
|
|
||||||
efl_ui_selection_manager_selection_get(sel_man, (Evas_Object *)obj, (Efl_Ui_Selection_Type)type,
|
|
||||||
(Efl_Ui_Selection_Format)format,
|
|
||||||
wdata, _selection_data_ready_cb, NULL, seatid);
|
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI Eina_Bool
|
|
||||||
elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type type,
|
|
||||||
Elm_Sel_Format format, const void *selbuf, size_t buflen)
|
|
||||||
{
|
|
||||||
int seatid = 1;
|
|
||||||
Eina_Future *f;
|
|
||||||
Sel_Lost_Data *ldata;
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get(obj);
|
|
||||||
Eina_Slice data;
|
|
||||||
|
|
||||||
ldata = calloc(1, sizeof(Sel_Lost_Data));
|
|
||||||
if (!ldata) return EINA_FALSE;
|
|
||||||
data.mem = selbuf;
|
|
||||||
data.len = buflen;
|
|
||||||
#ifdef HAVE_ELEMENTARY_WL2
|
|
||||||
if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
|
|
||||||
#endif
|
|
||||||
f = efl_ui_selection_manager_selection_set(sel_man, obj, (Efl_Ui_Selection_Type)type,
|
|
||||||
(Efl_Ui_Selection_Format)format, data, seatid);
|
|
||||||
|
|
||||||
ldata->obj = obj;
|
|
||||||
ldata->type = type;
|
|
||||||
eina_future_then_easy(f, _selection_lost_cb, NULL, NULL, EINA_VALUE_TYPE_UINT, ldata);
|
|
||||||
|
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI Eina_Bool
|
|
||||||
elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type type)
|
|
||||||
{
|
|
||||||
int seatid = 1;
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get((Evas_Object *)obj);
|
|
||||||
|
|
||||||
#ifdef HAVE_ELEMENTARY_WL2
|
|
||||||
if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
|
|
||||||
#endif
|
|
||||||
efl_ui_selection_manager_selection_clear(sel_man, obj, (Efl_Ui_Selection_Type)type, seatid);
|
|
||||||
|
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI void
|
|
||||||
elm_cnp_selection_loss_callback_set(Evas_Object *obj, Elm_Sel_Type type,
|
|
||||||
Elm_Selection_Loss_Cb func, const void *data)
|
|
||||||
{
|
|
||||||
Sel_Lost_Data *ldata = calloc(1, sizeof(Sel_Lost_Data));
|
|
||||||
#if HAVE_ELEMENTARY_COCOA
|
|
||||||
// Currently, we have no way to track changes in Cocoa pasteboard.
|
|
||||||
// Therefore, don't track this...
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
if (!ldata) return;
|
|
||||||
ldata->obj = obj;
|
|
||||||
ldata->type = type;
|
|
||||||
ldata->udata = (void *)data;
|
|
||||||
ldata->loss_cb = func;
|
|
||||||
lost_cb_list = eina_list_append(lost_cb_list, ldata);
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI Eina_Bool
|
|
||||||
elm_selection_selection_has_owner(Evas_Object *obj)
|
|
||||||
{
|
|
||||||
int seatid = 1;
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get((Evas_Object *)obj);
|
|
||||||
|
|
||||||
#ifdef HAVE_ELEMENTARY_WL2
|
|
||||||
if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return efl_ui_selection_manager_selection_has_owner(sel_man, obj,
|
|
||||||
EFL_UI_SELECTION_TYPE_CLIPBOARD, seatid);
|
|
||||||
}
|
|
||||||
|
|
||||||
EAPI Eina_Bool
|
|
||||||
elm_cnp_clipboard_selection_has_owner(Evas_Object *obj)
|
|
||||||
{
|
|
||||||
int seatid = 1;
|
|
||||||
Eo *sel_man = _efl_ui_selection_manager_get((Evas_Object *)obj);
|
|
||||||
|
|
||||||
#ifdef HAVE_ELEMENTARY_WL2
|
|
||||||
if (_wl_window_get(obj)) seatid = _wl_default_seat_id_get(obj);
|
|
||||||
#endif
|
|
||||||
return efl_ui_selection_manager_selection_has_owner(sel_man, obj,
|
|
||||||
EFL_UI_SELECTION_TYPE_CLIPBOARD, seatid);
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "efl_ui_selection.eo.c"
|
#include "efl_ui_selection.eo.c"
|
||||||
|
|
|
@ -1,45 +1,85 @@
|
||||||
import efl_ui_selection_types;
|
import eina_types;
|
||||||
|
|
||||||
mixin @beta Efl.Ui.Selection {
|
enum @beta Efl.Ui.Cnp_Buffer {
|
||||||
[[Efl Ui Selection class]]
|
[[System buffer to use in Copy & Paste operations.]]
|
||||||
data: null;
|
selection = 0, [[Buffer typically used when the user selects (highlights) some text without explicitly
|
||||||
methods {
|
requesting to copy it.]]
|
||||||
selection_set {
|
copy_and_paste = 1, [[Buffer used when the user requests that the current selection is copied (using
|
||||||
[[Set the selection data to the object]]
|
Ctrl+C, for example).]]
|
||||||
params {
|
}
|
||||||
@in type: Efl.Ui.Selection_Type; [[Selection Type]]
|
|
||||||
@in format: Efl.Ui.Selection_Format; [[Selection Format]]
|
struct @beta Efl.Ui.Wm_Selection_Changed {
|
||||||
@in data: Eina.Slice; [[Selection data]]
|
[[Information sent along the @[Efl.Ui.Selection.wm_selection,changed] event.]]
|
||||||
@in seat: uint;[[Specified seat for multiple seats case.]]
|
buffer : Efl.Ui.Cnp_Buffer; [[The system buffer that has changed.]]
|
||||||
}
|
caused_by : Efl.Ui.Selection; [[The EFL widget that triggered the change. $NULL if it is not an EFL widget.]]
|
||||||
return: future<void>; [[Future for tracking when the selection is lost]]
|
seat : uint; [[The seat that triggered the change.]]
|
||||||
}
|
}
|
||||||
selection_get {
|
|
||||||
[[Get the data from the object that has selection]]
|
mixin @beta Efl.Ui.Selection requires Efl.Object {
|
||||||
params {
|
[[This mixin provides the ability to interact with the system's Copy & Paste facilities.
|
||||||
@in type: Efl.Ui.Selection_Type; [[Selection Type]]
|
]]
|
||||||
@in format: Efl.Ui.Selection_Format; [[Selection Format]]
|
methods {
|
||||||
@in data_func: Efl.Ui.Selection_Data_Ready; [[Data ready function pointer]]
|
selection_set {
|
||||||
@in seat: uint;[[Specified seat for multiple seats case.]]
|
[[Sets the current selection.
|
||||||
}
|
|
||||||
}
|
This sends the selected data to the system's specified buffer, making it available to other
|
||||||
selection_clear {
|
applications for "pasting" it.
|
||||||
[[Clear the selection data from the object]]
|
|
||||||
params {
|
This is typically used when the user requests a "copy" operation.
|
||||||
@in type: Efl.Ui.Selection_Type; [[Selection Type]]
|
]]
|
||||||
@in seat: uint; [[Specified seat for multiple seats case.]]
|
params {
|
||||||
}
|
buffer : Efl.Ui.Cnp_Buffer; [[System buffer to use.]]
|
||||||
}
|
content : Eina.Content @by_ref; [[Data to copy.]]
|
||||||
has_owner {
|
seat : uint; [[Seat the data comes from. Use 0 when in doubt.]]
|
||||||
[[Determine whether the selection data has owner]]
|
}
|
||||||
params {
|
}
|
||||||
@in type: Efl.Ui.Selection_Type; [[Selection type]]
|
selection_clear {
|
||||||
@in seat: uint; [[Specified seat for multiple seats case.]]
|
[[Clears the current selection.
|
||||||
}
|
|
||||||
return: bool; [[EINA_TRUE if there is object owns selection, otherwise EINA_FALSE]]
|
No data will be available to other applications to paste (until something else is selected).
|
||||||
}
|
]]
|
||||||
}
|
params {
|
||||||
events {
|
buffer : Efl.Ui.Cnp_Buffer; [[System buffer to clear.]]
|
||||||
wm_selection,changed: Efl.Ui.Selection_Changed; [[Called when display server's selection has changed]]
|
seat : uint; [[Seat to clear. Use 0 when in doubt.]]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
selection_get {
|
||||||
|
[[Retrieves the data currently held in the specified buffer.
|
||||||
|
|
||||||
|
This is typically used when the user requests a "paste" operation.
|
||||||
|
|
||||||
|
This method is time consuming (since data can potentially be provided by another application), therefore,
|
||||||
|
it is recommended to verify the existence of a selection using @.has_selection before calling it.
|
||||||
|
]]
|
||||||
|
params {
|
||||||
|
buffer : Efl.Ui.Cnp_Buffer; [[System buffer to use.]]
|
||||||
|
seat : uint; [[Seat where the data should be pasted. Use 0 when in doubt.]]
|
||||||
|
acceptable_types : iterator<string>; [[List of accepted IANA MIME types:
|
||||||
|
https://www.iana.org/assignments/media-types/media-types.xhtml
|
||||||
|
If automatic conversion cannot be provided to any of the accepted
|
||||||
|
types, an error will be returned.
|
||||||
|
]]
|
||||||
|
}
|
||||||
|
return : future<Eina.Content> @move; [[A future that will be resolved to the requested content, or to an
|
||||||
|
error if type conversion is not available or the requested buffer
|
||||||
|
is empty.]]
|
||||||
|
}
|
||||||
|
has_selection {
|
||||||
|
[[Checks if the specified system buffer has content.]]
|
||||||
|
params {
|
||||||
|
buffer : Efl.Ui.Cnp_Buffer; [[System buffer to query.]]
|
||||||
|
seat : uint; [[Seat to query. Use 0 when in doubt.]]
|
||||||
|
}
|
||||||
|
return : bool; [[$true if there is data available in the requested buffer.]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
implements {
|
||||||
|
Efl.Object.constructor;
|
||||||
|
Efl.Object.invalidate;
|
||||||
|
Efl.Object.finalize;
|
||||||
|
}
|
||||||
|
events {
|
||||||
|
wm_selection,changed : Efl.Ui.Wm_Selection_Changed; [[Event emitted when the content of one of the system's
|
||||||
|
buffers changes.]]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,139 +0,0 @@
|
||||||
import efl_ui_dnd_types;
|
|
||||||
|
|
||||||
class @beta Efl.Ui.Selection_Manager extends Efl.Object {
|
|
||||||
methods {
|
|
||||||
selection_set @beta {
|
|
||||||
[[Set selection]]
|
|
||||||
params {
|
|
||||||
@in owner: Efl.Object; [[Seleciton owner]]
|
|
||||||
@in type: Efl.Ui.Selection_Type; [[Selection type]]
|
|
||||||
@in format: Efl.Ui.Selection_Format; [[Selection format]]
|
|
||||||
@in data: Eina.Slice; [[Selection data]]
|
|
||||||
@in seat: uint @optional;[[Specified seat for multiple seats case.]]
|
|
||||||
}
|
|
||||||
return: future<void>; [[Future for tracking when the selection is lost]]
|
|
||||||
}
|
|
||||||
selection_get @beta {
|
|
||||||
[[Get selection]]
|
|
||||||
params {
|
|
||||||
@in request: const(Efl.Object); [[Seleciton owner]]
|
|
||||||
@in type: Efl.Ui.Selection_Type; [[Selection type]]
|
|
||||||
@in format: Efl.Ui.Selection_Format; [[Selection Format]]
|
|
||||||
@in data_func: Efl.Ui.Selection_Data_Ready; [[Data ready function pointer]]
|
|
||||||
@in seat: uint @optional;[[Specified seat for multiple seats case.]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
selection_clear @beta {
|
|
||||||
params {
|
|
||||||
@in owner: Efl.Object; [[Seleciton owner]]
|
|
||||||
@in type: Efl.Ui.Selection_Type; [[Selection type]]
|
|
||||||
@in seat: uint @optional; [[Specified seat for multiple seats case.]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
selection_has_owner @beta {
|
|
||||||
[[Check if the request object has selection or not]]
|
|
||||||
params {
|
|
||||||
@in request: Efl.Object; [[Request object]]
|
|
||||||
@in type: Efl.Ui.Selection_Type; [[Selection type]]
|
|
||||||
@in seat: uint @optional; [[Specified seat for multiple seats case.]]
|
|
||||||
}
|
|
||||||
return: bool; [[EINA_TRUE if the request object has selection, otherwise, EINA_FALSE]]
|
|
||||||
}
|
|
||||||
drag_start @beta {
|
|
||||||
[[This starts a drag and drop process at the drag side.
|
|
||||||
During dragging, there are three events emitted as belows:
|
|
||||||
- EFL_UI_DND_EVENT_DRAG_POS
|
|
||||||
- EFL_UI_DND_EVENT_DRAG_ACCEPT
|
|
||||||
- EFL_UI_DND_EVENT_DRAG_DONE
|
|
||||||
]]
|
|
||||||
params {
|
|
||||||
@in drag_obj: Efl.Object; [[Drag object]]
|
|
||||||
@in format: Efl.Ui.Selection_Format; [[Data format]]
|
|
||||||
@in data: Eina.Slice; [[Data to transfer]]
|
|
||||||
@in action: Efl.Ui.Selection_Action; [[Action when data is transferred]]
|
|
||||||
@in icon_func: Efl.Dnd.Drag_Icon_Create; [[Function pointer to create icon]]
|
|
||||||
@in seat: uint; [[Specified seat for multiple seats case.]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drag_action_set @beta {
|
|
||||||
[[This sets the action for the drag]]
|
|
||||||
params {
|
|
||||||
@in drag_obj: Efl.Object; [[Drag object]]
|
|
||||||
@in action: Efl.Ui.Selection_Action; [[Drag action]]
|
|
||||||
@in seat: uint; [[Specified seat for multiple seats case.]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drag_cancel @beta {
|
|
||||||
[[This cancels the on-going drag]]
|
|
||||||
params {
|
|
||||||
@in drag_obj: Efl.Object; [[Drag object]]
|
|
||||||
@in seat: uint; [[Specified seat for multiple seats case.]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
container_drag_item_add @beta {
|
|
||||||
[[This registers a drag for items in a container. Many items can be
|
|
||||||
dragged at a time. During dragging, there are three events emitted:
|
|
||||||
- EFL_UI_DND_EVENT_DRAG_POS
|
|
||||||
- EFL_UI_DND_EVENT_DRAG_ACCEPT
|
|
||||||
- EFL_UI_DND_EVENT_DRAG_DONE.]]
|
|
||||||
params {
|
|
||||||
@in cont: Efl.Object; [[Container object]]
|
|
||||||
@in time_to_drag: double; [[Time since mouse down happens to drag starts]]
|
|
||||||
@in anim_duration: double; [[animation duration]]
|
|
||||||
@in data_func: Efl.Dnd.Drag_Data_Get; [[Data and its format]]
|
|
||||||
@in item_func: Efl.Dnd.Item_Get; [[Item to determine drag start]]
|
|
||||||
@in icon_func: Efl.Dnd.Drag_Icon_Create; [[Icon used during drag]]
|
|
||||||
@in icon_list_func: Efl.Dnd.Drag_Icon_List_Create; [[Icons used for animations]]
|
|
||||||
@in seat: uint; [[Specified seat for multiple seats case]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
container_drag_item_del @beta {
|
|
||||||
[[Remove drag function of items in the container object.]]
|
|
||||||
params {
|
|
||||||
@in cont: Efl.Object; [[Container object]]
|
|
||||||
@in seat: uint; [[Specified seat for multiple seats case]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drop_target_add @beta {
|
|
||||||
[[Add a dropable target. There are four events emitted:
|
|
||||||
- EFL_UI_DND_DROP_DRAG_ENTER
|
|
||||||
- EFL_UI_DND_DROP_DRAG_LEAVE
|
|
||||||
- EFL_UI_DND_DROP_DRAG_POS
|
|
||||||
- EFL_UI_DND_DROP_DRAG_DROP.]]
|
|
||||||
params {
|
|
||||||
@in target_obj: Efl.Object; [[Drop target]]
|
|
||||||
@in format: Efl.Ui.Selection_Format; [[Accepted data format]]
|
|
||||||
@in seat: uint; [[Specified seat for multiple seats case.]]
|
|
||||||
}
|
|
||||||
return: bool; [[$true on success, $false otherwise]]
|
|
||||||
}
|
|
||||||
drop_target_del @beta {
|
|
||||||
[[Remove a dropable target]]
|
|
||||||
params {
|
|
||||||
@in target_obj: Efl.Object; [[Drop target]]
|
|
||||||
@in format: Efl.Ui.Selection_Format; [[Accepted data format]]
|
|
||||||
@in seat: uint; [[Specified seat for multiple seats case.]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
container_drop_item_add @beta {
|
|
||||||
[[Add dropable target for a container in which items can drop to it]]
|
|
||||||
params {
|
|
||||||
@in cont: Efl.Object; [[Container object]]
|
|
||||||
@in format: Efl.Ui.Selection_Format; [[Accepted data formats]]
|
|
||||||
@in item_func: Efl.Dnd.Item_Get; [[Get item at specific position]]
|
|
||||||
@in seat: uint; [[Specified seat for multiple seats case.]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
container_drop_item_del @beta {
|
|
||||||
[[Remove dropable target for the container]]
|
|
||||||
params {
|
|
||||||
@in cont: Efl.Object; [[Container object]]
|
|
||||||
@in seat: uint; [[Specified seat for multiple seats case.]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
implements {
|
|
||||||
Efl.Object.constructor;
|
|
||||||
Efl.Object.destructor;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
enum @beta Efl.Ui.Selection_Type
|
|
||||||
{
|
|
||||||
[[Selection type]]
|
|
||||||
primary, [[Primary text selection (highlighted or selected text)]]
|
|
||||||
secondary, [[Used when primary selection is in use]]
|
|
||||||
dnd, [[Drag and Drop]]
|
|
||||||
clipboard [[Clipboard selection (ctrl+C)]]
|
|
||||||
}
|
|
||||||
|
|
||||||
enum @beta Efl.Ui.Selection_Format
|
|
||||||
{
|
|
||||||
[[Selection format]]
|
|
||||||
targets = -1, [[For matching every possible atom]]
|
|
||||||
none = 0x0, [[Content is from outside of EFL]]
|
|
||||||
text = 0x01, [[Plain unformatted text: Used for things that don't want rich markup]]
|
|
||||||
markup = 0x2, [[Edje textblock markup, including inline images]]
|
|
||||||
image = 0x4, [[Images]]
|
|
||||||
vcard = 0x08, [[Vcards]]
|
|
||||||
html = 0x10 [[Raw HTML-like data (eg. webkit)]]
|
|
||||||
}
|
|
||||||
|
|
||||||
enum @beta Efl.Ui.Selection_Action
|
|
||||||
{
|
|
||||||
[[Defines the kind of action associated with the drop data]]
|
|
||||||
unknown, [[Action type is unknown]]
|
|
||||||
copy, [[Copy the data]]
|
|
||||||
move, [[Move the data]]
|
|
||||||
private, [[Private action type]]
|
|
||||||
ask, [[Ask the user what to do]]
|
|
||||||
list, [[List the data]]
|
|
||||||
link, [[Link the data]]
|
|
||||||
description [[Describe the data]]
|
|
||||||
}
|
|
||||||
|
|
||||||
struct @beta Efl.Ui.Selection_Data
|
|
||||||
{
|
|
||||||
[[Structure holding the info about selected data]]
|
|
||||||
pos: Eina.Position2D; [[Coordinates of the drop (DND operations only)]]
|
|
||||||
format: Efl.Ui.Selection_Format; [[Format of the selection]]
|
|
||||||
content: Eina.Slice; [[Selection data]]
|
|
||||||
action: Efl.Ui.Selection_Action; [[Action to perform with the data]]
|
|
||||||
item: Efl.Object; [[Item under the drag position. It is only available for container]]
|
|
||||||
}
|
|
||||||
|
|
||||||
function @beta Efl.Ui.Selection_Data_Ready {
|
|
||||||
[[Function pointer for getting selection]]
|
|
||||||
params {
|
|
||||||
@in obj: Efl.Object; [[Object which requested for the selection]]
|
|
||||||
@in seldata: ptr(Efl.Ui.Selection_Data); [[Selection data]]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct @beta Efl.Ui.Selection_Changed
|
|
||||||
{
|
|
||||||
[[Selection-changed specific information.]] // TODO: This needs to be filled in.
|
|
||||||
type: Efl.Ui.Selection_Type; [[Selection type]]
|
|
||||||
seat: int; [[The seat on which the selection changed, or NULL for "default"]]
|
|
||||||
display: void_ptr; [[The display connection object, NULL under X11]]
|
|
||||||
exist: bool; [[EINA_TRUE if the selection has an owner]]
|
|
||||||
}
|
|
|
@ -757,7 +757,7 @@ _view_init(Evas_Object *obj, Efl_Ui_Tags_Data *sd)
|
||||||
sd->entry = efl_add(EFL_UI_TEXTBOX_CLASS, sd->box,
|
sd->entry = efl_add(EFL_UI_TEXTBOX_CLASS, sd->box,
|
||||||
efl_text_multiline_set(efl_added, EINA_FALSE),
|
efl_text_multiline_set(efl_added, EINA_FALSE),
|
||||||
efl_text_set(efl_added, ""),
|
efl_text_set(efl_added, ""),
|
||||||
efl_ui_textbox_cnp_mode_set(efl_added, EFL_UI_SELECTION_FORMAT_MARKUP),
|
efl_ui_textbox_cnp_dnd_mode_set(efl_added, EFL_UI_TEXTBOX_CNP_CONTENT_MARKUP),
|
||||||
efl_input_text_input_panel_autoshow_set(efl_added, EINA_FALSE),
|
efl_input_text_input_panel_autoshow_set(efl_added, EINA_FALSE),
|
||||||
efl_text_interactive_editable_set(efl_added, EINA_TRUE),
|
efl_text_interactive_editable_set(efl_added, EINA_TRUE),
|
||||||
efl_composite_attach(obj, efl_added));
|
efl_composite_attach(obj, efl_added));
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
typedef struct _Efl_Ui_Textbox_Data Efl_Ui_Textbox_Data;
|
typedef struct _Efl_Ui_Textbox_Data Efl_Ui_Textbox_Data;
|
||||||
typedef struct _Efl_Ui_Text_Rectangle Efl_Ui_Text_Rectangle;
|
typedef struct _Efl_Ui_Text_Rectangle Efl_Ui_Text_Rectangle;
|
||||||
typedef struct _Anchor Anchor;
|
typedef struct _Anchor Anchor;
|
||||||
typedef struct _Selection_Loss_Data Selection_Loss_Data;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base widget smart data extended with entry instance data.
|
* Base widget smart data extended with entry instance data.
|
||||||
|
@ -69,7 +68,7 @@ struct _Efl_Ui_Textbox_Data
|
||||||
const char *hover_style; /**< style of a hover object */
|
const char *hover_style; /**< style of a hover object */
|
||||||
} anchor_hover;
|
} anchor_hover;
|
||||||
|
|
||||||
Efl_Ui_Selection_Format cnp_mode;
|
const char *cnp_mime_type;
|
||||||
Elm_Sel_Format drop_format;
|
Elm_Sel_Format drop_format;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -81,11 +80,7 @@ struct _Efl_Ui_Textbox_Data
|
||||||
Eina_Size2D scroll;
|
Eina_Size2D scroll;
|
||||||
Eina_Size2D layout;
|
Eina_Size2D layout;
|
||||||
} last;
|
} last;
|
||||||
struct
|
Efl_Ui_Textbox_Cnp_Content content;
|
||||||
{
|
|
||||||
Eina_Future *primary;
|
|
||||||
Eina_Future *clipboard;
|
|
||||||
} sel_future;
|
|
||||||
Eina_Bool sel_handles_enabled : 1;
|
Eina_Bool sel_handles_enabled : 1;
|
||||||
Eina_Bool start_handler_down : 1;
|
Eina_Bool start_handler_down : 1;
|
||||||
Eina_Bool start_handler_shown : 1;
|
Eina_Bool start_handler_shown : 1;
|
||||||
|
@ -147,12 +142,6 @@ struct _Efl_Ui_Text_Rectangle
|
||||||
Evas_Object *obj_bg, *obj_fg, *obj;
|
Evas_Object *obj_bg, *obj_fg, *obj;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Selection_Loss_Data
|
|
||||||
{
|
|
||||||
Eo *obj;
|
|
||||||
Efl_Ui_Selection_Type stype;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MY_CLASS EFL_UI_TEXTBOX_CLASS
|
#define MY_CLASS EFL_UI_TEXTBOX_CLASS
|
||||||
#define MY_CLASS_PFX efl_ui_textbox
|
#define MY_CLASS_PFX efl_ui_textbox
|
||||||
#define MY_CLASS_NAME "Efl.Ui.Textbox"
|
#define MY_CLASS_NAME "Efl.Ui.Textbox"
|
||||||
|
@ -208,7 +197,7 @@ static void _anchors_free(Efl_Ui_Textbox_Data *sd);
|
||||||
static void _selection_defer(Eo *obj, Efl_Ui_Textbox_Data *sd);
|
static void _selection_defer(Eo *obj, Efl_Ui_Textbox_Data *sd);
|
||||||
static Eina_Position2D _decoration_calc_offset(Efl_Ui_Textbox_Data *sd);
|
static Eina_Position2D _decoration_calc_offset(Efl_Ui_Textbox_Data *sd);
|
||||||
static void _update_text_theme(Eo *obj, Efl_Ui_Textbox_Data *sd);
|
static void _update_text_theme(Eo *obj, Efl_Ui_Textbox_Data *sd);
|
||||||
static void _efl_ui_textbox_selection_paste_type(Eo *obj, Efl_Ui_Selection_Type type);
|
static void _efl_ui_textbox_selection_paste_type(Eo *obj, Efl_Ui_Textbox_Data *sd, Efl_Ui_Cnp_Buffer type);
|
||||||
|
|
||||||
static Eina_Bool _key_action_copy(Evas_Object *obj, const char *params);
|
static Eina_Bool _key_action_copy(Evas_Object *obj, const char *params);
|
||||||
static Eina_Bool _key_action_paste(Evas_Object *obj, const char *params);
|
static Eina_Bool _key_action_paste(Evas_Object *obj, const char *params);
|
||||||
|
@ -407,16 +396,19 @@ _update_selection_handler(Eo *obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static Eina_Value
|
||||||
_selection_data_cb(void *data EINA_UNUSED, Eo *obj,
|
_selection_data_cb(Efl_Ui_Textbox *obj, void *data EINA_UNUSED, const Eina_Value value)
|
||||||
Efl_Ui_Selection_Data *sel_data)
|
|
||||||
{
|
{
|
||||||
|
Eina_Content *content;
|
||||||
|
Eina_Slice slice;
|
||||||
Efl_Text_Cursor *cur, *start, *end;
|
Efl_Text_Cursor *cur, *start, *end;
|
||||||
Efl_Text_Change_Info info = { NULL, 0, 0, 0, 0 };
|
Efl_Text_Change_Info info = { NULL, 0, 0, 0, 0 };
|
||||||
|
|
||||||
char *buf = eina_slice_strdup(sel_data->content);
|
if (eina_value_type_get(&value) != EINA_VALUE_TYPE_CONTENT)
|
||||||
size_t len = sel_data->content.len;
|
return EINA_VALUE_EMPTY;
|
||||||
|
|
||||||
|
content = eina_value_to_content(&value);
|
||||||
|
slice = eina_content_data_get(content);
|
||||||
efl_text_interactive_selection_cursors_get(obj, &start, &end);
|
efl_text_interactive_selection_cursors_get(obj, &start, &end);
|
||||||
if (!efl_text_cursor_equal(start, end))
|
if (!efl_text_cursor_equal(start, end))
|
||||||
{
|
{
|
||||||
|
@ -426,83 +418,130 @@ _selection_data_cb(void *data EINA_UNUSED, Eo *obj,
|
||||||
cur = efl_text_interactive_main_cursor_get(obj);
|
cur = efl_text_interactive_main_cursor_get(obj);
|
||||||
info.type = EFL_TEXT_CHANGE_TYPE_INSERT;
|
info.type = EFL_TEXT_CHANGE_TYPE_INSERT;
|
||||||
info.position = efl_text_cursor_position_get(cur);
|
info.position = efl_text_cursor_position_get(cur);
|
||||||
info.length = len;
|
info.length = slice.len;
|
||||||
info.content = buf;
|
info.content = slice.mem;
|
||||||
if (sel_data->format == EFL_UI_SELECTION_FORMAT_MARKUP)
|
if (eina_streq(eina_content_type_get(content), "application/x-elementary-markup"))
|
||||||
{
|
{
|
||||||
efl_text_cursor_markup_insert(cur, buf);
|
efl_text_cursor_markup_insert(cur, slice.mem);
|
||||||
|
}
|
||||||
|
else if (!strncmp(eina_content_type_get(content), "image/", strlen("image/")))
|
||||||
|
{
|
||||||
|
Eina_Strbuf *result = eina_strbuf_new();
|
||||||
|
eina_strbuf_append_printf(result, "<item absize=240x180 href=");
|
||||||
|
eina_strbuf_append_slice(result, slice);
|
||||||
|
eina_strbuf_append_printf(result, "></item>");
|
||||||
|
efl_text_cursor_markup_insert(cur, eina_strbuf_string_get(result));
|
||||||
|
eina_strbuf_free(result);
|
||||||
}
|
}
|
||||||
else // TEXT
|
else // TEXT
|
||||||
{
|
{
|
||||||
efl_text_cursor_text_insert(cur, buf);
|
efl_text_cursor_text_insert(cur, slice.mem);
|
||||||
}
|
}
|
||||||
efl_event_callback_call(obj, EFL_TEXT_INTERACTIVE_EVENT_CHANGED_USER, &info);
|
efl_event_callback_call(obj, EFL_TEXT_INTERACTIVE_EVENT_CHANGED_USER, &info);
|
||||||
free(buf);
|
|
||||||
|
return EINA_VALUE_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Array*
|
||||||
|
_figure_out_types(Eo *obj EINA_UNUSED, Efl_Ui_Textbox_Data *sd)
|
||||||
|
{
|
||||||
|
Eina_Array *types = eina_array_new(10);
|
||||||
|
|
||||||
|
if (sd->content & EFL_UI_TEXTBOX_CNP_CONTENT_MARKUP)
|
||||||
|
eina_array_push(types, "application/x-elementary-markup");
|
||||||
|
if (sd->content & EFL_UI_TEXTBOX_CNP_CONTENT_IMAGE)
|
||||||
|
{
|
||||||
|
eina_array_push(types, "image/png");
|
||||||
|
eina_array_push(types, "image/jpeg");
|
||||||
|
eina_array_push(types, "image/x-ms-bmp");
|
||||||
|
eina_array_push(types, "image/gif");
|
||||||
|
eina_array_push(types, "image/tiff");
|
||||||
|
eina_array_push(types, "image/svg+xml");
|
||||||
|
eina_array_push(types, "image/x-xpixmap");
|
||||||
|
eina_array_push(types, "image/x-tga");
|
||||||
|
eina_array_push(types, "image/x-portable-pixmap");
|
||||||
|
}
|
||||||
|
if (sd->content & EFL_UI_TEXTBOX_CNP_CONTENT_TEXT)
|
||||||
|
eina_array_push(types, "text/plain;charset=utf-8");
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_accepting_drops(Eo *obj, Efl_Ui_Textbox_Data *sd, Eina_Accessor *mime_types)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
const char *mime_type;
|
||||||
|
|
||||||
|
if (efl_ui_widget_disabled_get(obj)) return EINA_FALSE;
|
||||||
|
|
||||||
|
EINA_ACCESSOR_FOREACH(mime_types, i, mime_type)
|
||||||
|
{
|
||||||
|
if (sd->content & EFL_UI_TEXTBOX_CNP_CONTENT_TEXT &&
|
||||||
|
eina_streq(mime_type, "text/plain;charset=utf-8"))
|
||||||
|
return EINA_TRUE;
|
||||||
|
|
||||||
|
if (sd->content & EFL_UI_TEXTBOX_CNP_CONTENT_IMAGE &&
|
||||||
|
strncmp(mime_type, "image/", strlen("image/")))
|
||||||
|
return EINA_TRUE;
|
||||||
|
|
||||||
|
if (sd->content & EFL_UI_TEXTBOX_CNP_CONTENT_MARKUP &&
|
||||||
|
eina_streq(mime_type, "application/x-elementary-markup"))
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
return EINA_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_dnd_enter_cb(void *data EINA_UNUSED,
|
_dnd_enter_cb(void *data EINA_UNUSED,
|
||||||
Evas_Object *obj)
|
const Efl_Event *ev)
|
||||||
{
|
{
|
||||||
efl_ui_focus_util_focus(obj);
|
Efl_Ui_Drop_Event *dnd_enter = ev->info;
|
||||||
|
EFL_UI_TEXT_DATA_GET(ev->object, sd);
|
||||||
|
if (_accepting_drops(ev->object, sd, dnd_enter->available_types))
|
||||||
|
efl_ui_focus_util_focus(ev->object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_dnd_leave_cb(void *data EINA_UNUSED,
|
_dnd_pos_cb(void *data EINA_UNUSED, const Efl_Event *ev)
|
||||||
Evas_Object *obj EINA_UNUSED)
|
|
||||||
{
|
{
|
||||||
}
|
Efl_Ui_Drop_Event *dnd_pos = ev->info;
|
||||||
|
Eina_Position2D po, pe, pos;
|
||||||
|
EFL_UI_TEXT_DATA_GET(ev->object, sd);
|
||||||
|
int cursor_pos;
|
||||||
|
|
||||||
static void
|
if (!_accepting_drops(ev->object, sd, dnd_pos->available_types))
|
||||||
_dnd_pos_cb(void *data EINA_UNUSED,
|
return;
|
||||||
Evas_Object *obj,
|
|
||||||
Evas_Coord x,
|
|
||||||
Evas_Coord y,
|
|
||||||
Elm_Xdnd_Action action EINA_UNUSED)
|
|
||||||
{
|
|
||||||
int pos;
|
|
||||||
Eina_Rect o, e;
|
|
||||||
|
|
||||||
EFL_UI_TEXT_DATA_GET(obj, sd);
|
po = efl_gfx_entity_position_get(ev->object);
|
||||||
|
pe = efl_gfx_entity_position_get(sd->entry_edje);
|
||||||
o = efl_gfx_entity_geometry_get(obj);
|
pos.x = dnd_pos->position.x + po.x - pe.x;
|
||||||
e = efl_gfx_entity_geometry_get(sd->entry_edje);
|
pos.y = dnd_pos->position.y + po.x - pe.y;
|
||||||
x = x + o.x - e.x;
|
|
||||||
y = y + o.y - e.y;
|
|
||||||
|
|
||||||
edje_object_part_text_cursor_coord_set
|
edje_object_part_text_cursor_coord_set
|
||||||
(sd->entry_edje, "efl.text", EDJE_CURSOR_USER, x, y);
|
(sd->entry_edje, "efl.text", EDJE_CURSOR_USER, pos.x, pos.y);
|
||||||
pos = edje_object_part_text_cursor_pos_get
|
cursor_pos = edje_object_part_text_cursor_pos_get
|
||||||
(sd->entry_edje, "efl.text", EDJE_CURSOR_USER);
|
(sd->entry_edje, "efl.text", EDJE_CURSOR_USER);
|
||||||
edje_object_part_text_cursor_pos_set(sd->entry_edje, "efl.text",
|
edje_object_part_text_cursor_pos_set(sd->entry_edje, "efl.text",
|
||||||
EDJE_CURSOR_MAIN, pos);
|
EDJE_CURSOR_MAIN, cursor_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Eina_Bool
|
static void
|
||||||
_dnd_drop_cb(void *data EINA_UNUSED,
|
_dnd_drop_cb(void *data EINA_UNUSED, const Efl_Event *ev)
|
||||||
Evas_Object *obj,
|
|
||||||
Elm_Selection_Data *drop)
|
|
||||||
{
|
{
|
||||||
Eina_Bool rv;
|
Efl_Ui_Drop_Event *drop = ev->info;
|
||||||
|
Eina_Future *future;
|
||||||
|
Eina_Array *types;
|
||||||
|
|
||||||
EFL_UI_TEXT_DATA_GET(obj, sd);
|
EFL_UI_TEXT_DATA_GET(ev->object, sd);
|
||||||
|
types = _figure_out_types(ev->object, sd);
|
||||||
|
|
||||||
rv = edje_object_part_text_cursor_coord_set
|
if (!_accepting_drops(ev->object, sd, drop->available_types))
|
||||||
(sd->entry_edje, "efl.text", EDJE_CURSOR_MAIN, drop->x, drop->y);
|
return;
|
||||||
|
|
||||||
if (!rv) WRN("Warning: Failed to position cursor: paste anyway");
|
future = efl_ui_dnd_drop_data_get(ev->object, 0, eina_array_iterator_new(types));
|
||||||
|
eina_array_free(types);
|
||||||
|
|
||||||
//rv = _selection_data_cb(NULL, obj, drop);
|
efl_future_then(ev->object, future, _selection_data_cb);
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Elm_Sel_Format
|
|
||||||
_get_drop_format(Evas_Object *obj)
|
|
||||||
{
|
|
||||||
if (efl_text_interactive_editable_get(obj) && (efl_text_multiline_get(obj)) && (!efl_text_password_get(obj)) && (!efl_ui_widget_disabled_get(obj)))
|
|
||||||
return EFL_UI_SELECTION_FORMAT_MARKUP | EFL_UI_SELECTION_FORMAT_IMAGE;
|
|
||||||
return EFL_UI_SELECTION_FORMAT_MARKUP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we can't reuse layout's here, because it's on entry_edje only */
|
/* we can't reuse layout's here, because it's on entry_edje only */
|
||||||
|
@ -516,12 +555,6 @@ _efl_ui_textbox_efl_ui_widget_disabled_set(Eo *obj, Efl_Ui_Textbox_Data *sd, Ein
|
||||||
|
|
||||||
efl_ui_widget_disabled_set(efl_super(obj, MY_CLASS), disabled);
|
efl_ui_widget_disabled_set(efl_super(obj, MY_CLASS), disabled);
|
||||||
|
|
||||||
elm_drop_target_del(obj, sd->drop_format,
|
|
||||||
_dnd_enter_cb, NULL,
|
|
||||||
_dnd_leave_cb, NULL,
|
|
||||||
_dnd_pos_cb, NULL,
|
|
||||||
_dnd_drop_cb, NULL);
|
|
||||||
|
|
||||||
emission = efl_ui_widget_disabled_get(obj) ? "efl,state,disabled" : "efl,state,enabled";
|
emission = efl_ui_widget_disabled_get(obj) ? "efl,state,disabled" : "efl,state,enabled";
|
||||||
efl_layout_signal_emit(sd->entry_edje, emission, "efl");
|
efl_layout_signal_emit(sd->entry_edje, emission, "efl");
|
||||||
if (sd->scroll)
|
if (sd->scroll)
|
||||||
|
@ -529,15 +562,6 @@ _efl_ui_textbox_efl_ui_widget_disabled_set(Eo *obj, Efl_Ui_Textbox_Data *sd, Ein
|
||||||
efl_ui_scrollable_scroll_freeze_set(obj, efl_ui_widget_disabled_get(obj));
|
efl_ui_scrollable_scroll_freeze_set(obj, efl_ui_widget_disabled_get(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!efl_ui_widget_disabled_get(obj))
|
|
||||||
{
|
|
||||||
sd->drop_format = _get_drop_format(obj);
|
|
||||||
elm_drop_target_add(obj, sd->drop_format,
|
|
||||||
_dnd_enter_cb, NULL,
|
|
||||||
_dnd_leave_cb, NULL,
|
|
||||||
_dnd_pos_cb, NULL,
|
|
||||||
_dnd_drop_cb, NULL);
|
|
||||||
}
|
|
||||||
_update_text_theme(obj, sd);
|
_update_text_theme(obj, sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -804,83 +828,36 @@ _popup_position(Evas_Object *obj)
|
||||||
efl_gfx_entity_geometry_set(sd->popup, EINA_RECT(r.x + cx, r.y + cy, m.w, m.h));
|
efl_gfx_entity_geometry_set(sd->popup, EINA_RECT(r.x + cx, r.y + cy, m.w, m.h));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Eina_Value
|
static void
|
||||||
_selection_lost_cb(void *data, const Eina_Value value)
|
_selection_lost_cb(void *data EINA_UNUSED, const Efl_Event *ev)
|
||||||
{
|
{
|
||||||
Selection_Loss_Data *sdata = data;
|
Efl_Ui_Wm_Selection_Changed *changed = ev->info;
|
||||||
EFL_UI_TEXT_DATA_GET(sdata->obj, sd);
|
EFL_UI_TEXT_DATA_GET(ev->object, sd);
|
||||||
|
|
||||||
efl_text_interactive_all_unselect(sdata->obj);
|
if (changed->buffer == EFL_UI_CNP_BUFFER_SELECTION && changed->caused_by != ev->object)
|
||||||
_selection_defer(sdata->obj, sd);
|
|
||||||
switch (sdata->stype)
|
|
||||||
{
|
{
|
||||||
case EFL_UI_SELECTION_TYPE_CLIPBOARD:
|
efl_text_interactive_all_unselect(ev->object);
|
||||||
sd->sel_future.clipboard = NULL;
|
_selection_defer(ev->object, sd);
|
||||||
break;
|
|
||||||
case EFL_UI_SELECTION_TYPE_PRIMARY:
|
|
||||||
default:
|
|
||||||
sd->sel_future.primary = NULL;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_selection_store(Efl_Ui_Selection_Type seltype,
|
_selection_store(Efl_Ui_Cnp_Buffer buffer,
|
||||||
Evas_Object *obj)
|
Evas_Object *obj)
|
||||||
{
|
{
|
||||||
char *sel;
|
char *sel;
|
||||||
Efl_Text_Cursor *start, *end;
|
Efl_Text_Cursor *start, *end;
|
||||||
Efl_Ui_Selection_Format selformat = EFL_UI_SELECTION_FORMAT_MARKUP;
|
Eina_Content *content;
|
||||||
Eina_Slice slice;
|
|
||||||
Selection_Loss_Data *ldata;
|
|
||||||
Eina_Future *f;
|
|
||||||
|
|
||||||
EFL_UI_TEXT_DATA_GET(obj, sd);
|
|
||||||
|
|
||||||
efl_text_interactive_selection_cursors_get(obj, &start, &end);
|
efl_text_interactive_selection_cursors_get(obj, &start, &end);
|
||||||
sel = efl_text_cursor_range_markup_get(start, end);
|
sel = efl_text_cursor_range_markup_get(start, end);
|
||||||
|
|
||||||
if ((!sel) || (!sel[0])) return; /* avoid deleting our own selection */
|
if ((!sel) || (!sel[0])) return; /* avoid deleting our own selection */
|
||||||
|
|
||||||
slice.len = strlen(sel);
|
content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(sel), "application/x-elementary-markup");
|
||||||
slice.mem = sel;
|
|
||||||
|
|
||||||
switch (seltype)
|
efl_ui_selection_set(obj, buffer, content, 0);
|
||||||
{
|
|
||||||
case EFL_UI_SELECTION_TYPE_CLIPBOARD:
|
|
||||||
if (sd->sel_future.clipboard)
|
|
||||||
{
|
|
||||||
eina_future_cancel(sd->sel_future.clipboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
f = sd->sel_future.clipboard = efl_ui_selection_set(obj, seltype,
|
|
||||||
selformat, slice, 1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EFL_UI_SELECTION_TYPE_PRIMARY:
|
|
||||||
default:
|
|
||||||
if (sd->sel_future.primary)
|
|
||||||
{
|
|
||||||
eina_future_cancel(sd->sel_future.primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
f = sd->sel_future.primary = efl_ui_selection_set(obj, seltype,
|
|
||||||
selformat, slice, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ldata = calloc(1, sizeof(Selection_Loss_Data));
|
|
||||||
if (!ldata) goto end;
|
|
||||||
|
|
||||||
ldata->obj = obj;
|
|
||||||
eina_future_then_easy(f, _selection_lost_cb, NULL, NULL, EINA_VALUE_TYPE_UINT, ldata);
|
|
||||||
|
|
||||||
//if (seltype == EFL_UI_SELECTION_TYPE_CLIPBOARD)
|
|
||||||
// eina_stringshare_replace(&sd->cut_sel, sel);
|
|
||||||
|
|
||||||
end:
|
|
||||||
free(sel);
|
free(sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -956,7 +933,7 @@ _menu_call(Evas_Object *obj)
|
||||||
{
|
{
|
||||||
Eina_Bool ownersel;
|
Eina_Bool ownersel;
|
||||||
|
|
||||||
ownersel = elm_selection_selection_has_owner(obj);
|
ownersel = elm_cnp_clipboard_selection_has_owner(obj);
|
||||||
/* prevent stupid blank hoversel */
|
/* prevent stupid blank hoversel */
|
||||||
if (efl_text_interactive_have_selection_get(obj) && efl_text_password_get(obj)) return;
|
if (efl_text_interactive_have_selection_get(obj) && efl_text_password_get(obj)) return;
|
||||||
if (_elm_config->desktop_entry && (!efl_text_interactive_have_selection_get(obj)) && ((!efl_text_interactive_editable_get(obj)) || (!ownersel)))
|
if (_elm_config->desktop_entry && (!efl_text_interactive_have_selection_get(obj)) && ((!efl_text_interactive_editable_get(obj)) || (!ownersel)))
|
||||||
|
@ -1133,7 +1110,7 @@ _mouse_down_cb(void *data, const Efl_Event *event)
|
||||||
|
|
||||||
if (ev->button == 2)
|
if (ev->button == 2)
|
||||||
{
|
{
|
||||||
_efl_ui_textbox_selection_paste_type(data, EFL_UI_SELECTION_TYPE_PRIMARY);
|
_efl_ui_textbox_selection_paste_type(data, sd, EFL_UI_CNP_BUFFER_SELECTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If right button is pressed and context menu disabled is true,
|
/* If right button is pressed and context menu disabled is true,
|
||||||
|
@ -1654,10 +1631,18 @@ _efl_ui_textbox_efl_object_constructor(Eo *obj, Efl_Ui_Textbox_Data *sd)
|
||||||
{
|
{
|
||||||
Eo *text_obj;
|
Eo *text_obj;
|
||||||
|
|
||||||
|
sd->content = EFL_UI_TEXTBOX_CNP_CONTENT_MARKUP;
|
||||||
|
|
||||||
ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
|
ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
|
||||||
|
|
||||||
if (!elm_widget_theme_klass_get(obj))
|
if (!elm_widget_theme_klass_get(obj))
|
||||||
elm_widget_theme_klass_set(obj, "text");
|
elm_widget_theme_klass_set(obj, "text");
|
||||||
|
|
||||||
|
efl_event_callback_add(obj, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, _selection_lost_cb, NULL);
|
||||||
|
efl_event_callback_add(obj, EFL_UI_DND_EVENT_DROP_ENTERED, _dnd_enter_cb, NULL);
|
||||||
|
efl_event_callback_add(obj, EFL_UI_DND_EVENT_DROP_POSITION_CHANGED, _dnd_pos_cb, NULL);
|
||||||
|
efl_event_callback_add(obj, EFL_UI_DND_EVENT_DROP_DROPPED, _dnd_drop_cb, NULL);
|
||||||
|
|
||||||
obj = efl_constructor(efl_super(obj, MY_CLASS));
|
obj = efl_constructor(efl_super(obj, MY_CLASS));
|
||||||
efl_event_callback_add(obj, EFL_INPUT_EVENT_LONGPRESSED, _long_press_cb, obj);
|
efl_event_callback_add(obj, EFL_INPUT_EVENT_LONGPRESSED, _long_press_cb, obj);
|
||||||
|
|
||||||
|
@ -1674,11 +1659,9 @@ _efl_ui_textbox_efl_object_constructor(Eo *obj, Efl_Ui_Textbox_Data *sd)
|
||||||
efl_composite_attach(obj, text_obj);
|
efl_composite_attach(obj, text_obj);
|
||||||
|
|
||||||
sd->entry_edje = wd->resize_obj;
|
sd->entry_edje = wd->resize_obj;
|
||||||
sd->cnp_mode = EFL_UI_SELECTION_FORMAT_TEXT;
|
|
||||||
sd->context_menu_enabled = EINA_TRUE;
|
sd->context_menu_enabled = EINA_TRUE;
|
||||||
efl_text_interactive_editable_set(obj, EINA_TRUE);
|
efl_text_interactive_editable_set(obj, EINA_TRUE);
|
||||||
efl_text_interactive_selection_allowed_set(obj, EINA_TRUE);
|
efl_text_interactive_selection_allowed_set(obj, EINA_TRUE);
|
||||||
sd->drop_format = EFL_UI_SELECTION_FORMAT_MARKUP | EFL_UI_SELECTION_FORMAT_IMAGE;
|
|
||||||
sd->last.scroll = EINA_SIZE2D(0, 0);
|
sd->last.scroll = EINA_SIZE2D(0, 0);
|
||||||
sd->sel_handles_enabled = EINA_FALSE;
|
sd->sel_handles_enabled = EINA_FALSE;
|
||||||
|
|
||||||
|
@ -1691,12 +1674,6 @@ _efl_ui_textbox_efl_object_finalize(Eo *obj,
|
||||||
{
|
{
|
||||||
obj = efl_finalize(efl_super(obj, MY_CLASS));
|
obj = efl_finalize(efl_super(obj, MY_CLASS));
|
||||||
|
|
||||||
elm_drop_target_add(obj, sd->drop_format,
|
|
||||||
_dnd_enter_cb, NULL,
|
|
||||||
_dnd_leave_cb, NULL,
|
|
||||||
_dnd_pos_cb, NULL,
|
|
||||||
_dnd_drop_cb, NULL);
|
|
||||||
|
|
||||||
efl_access_object_role_set(obj, EFL_ACCESS_ROLE_ENTRY);
|
efl_access_object_role_set(obj, EFL_ACCESS_ROLE_ENTRY);
|
||||||
|
|
||||||
_update_guide_text(obj, sd);
|
_update_guide_text(obj, sd);
|
||||||
|
@ -1805,11 +1782,6 @@ _efl_ui_textbox_efl_text_format_password_set(Eo *obj, Efl_Ui_Textbox_Data *sd, E
|
||||||
efl_text_replacement_char_set(obj, ENTRY_PASSWORD_MASK_CHARACTER_UTF8);
|
efl_text_replacement_char_set(obj, ENTRY_PASSWORD_MASK_CHARACTER_UTF8);
|
||||||
efl_text_password_set(sd->text_obj, password);
|
efl_text_password_set(sd->text_obj, password);
|
||||||
|
|
||||||
elm_drop_target_del(obj, sd->drop_format,
|
|
||||||
_dnd_enter_cb, NULL,
|
|
||||||
_dnd_leave_cb, NULL,
|
|
||||||
_dnd_pos_cb, NULL,
|
|
||||||
_dnd_drop_cb, NULL);
|
|
||||||
if (password)
|
if (password)
|
||||||
{
|
{
|
||||||
efl_text_multiline_set(obj, EINA_FALSE);
|
efl_text_multiline_set(obj, EINA_FALSE);
|
||||||
|
@ -1819,12 +1791,6 @@ _efl_ui_textbox_efl_text_format_password_set(Eo *obj, Efl_Ui_Textbox_Data *sd, E
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
efl_text_multiline_set(obj, EINA_TRUE);
|
efl_text_multiline_set(obj, EINA_TRUE);
|
||||||
sd->drop_format = _get_drop_format(obj);
|
|
||||||
elm_drop_target_add(obj, sd->drop_format,
|
|
||||||
_dnd_enter_cb, NULL,
|
|
||||||
_dnd_leave_cb, NULL,
|
|
||||||
_dnd_pos_cb, NULL,
|
|
||||||
_dnd_drop_cb, NULL);
|
|
||||||
efl_input_text_input_content_type_set(obj, ((efl_input_text_input_content_type_get(obj) | EFL_INPUT_TEXT_CONTENT_TYPE_AUTO_COMPLETE) & ~EFL_INPUT_TEXT_CONTENT_TYPE_SENSITIVE_DATA));
|
efl_input_text_input_content_type_set(obj, ((efl_input_text_input_content_type_get(obj) | EFL_INPUT_TEXT_CONTENT_TYPE_AUTO_COMPLETE) & ~EFL_INPUT_TEXT_CONTENT_TYPE_SENSITIVE_DATA));
|
||||||
efl_access_object_role_set(obj, EFL_ACCESS_ROLE_ENTRY);
|
efl_access_object_role_set(obj, EFL_ACCESS_ROLE_ENTRY);
|
||||||
}
|
}
|
||||||
|
@ -1891,19 +1857,8 @@ _efl_ui_textbox_efl_text_interactive_editable_set(Eo *obj, Efl_Ui_Textbox_Data *
|
||||||
efl_ui_widget_theme_apply(obj);
|
efl_ui_widget_theme_apply(obj);
|
||||||
efl_ui_widget_focus_allow_set(obj, editable);
|
efl_ui_widget_focus_allow_set(obj, editable);
|
||||||
|
|
||||||
elm_drop_target_del(obj, sd->drop_format,
|
|
||||||
_dnd_enter_cb, NULL,
|
|
||||||
_dnd_leave_cb, NULL,
|
|
||||||
_dnd_pos_cb, NULL,
|
|
||||||
_dnd_drop_cb, NULL);
|
|
||||||
if (editable)
|
if (editable)
|
||||||
{
|
{
|
||||||
sd->drop_format = _get_drop_format(obj);
|
|
||||||
elm_drop_target_add(obj, sd->drop_format,
|
|
||||||
_dnd_enter_cb, NULL,
|
|
||||||
_dnd_leave_cb, NULL,
|
|
||||||
_dnd_pos_cb, NULL,
|
|
||||||
_dnd_drop_cb, NULL);
|
|
||||||
if (sd->cursor)
|
if (sd->cursor)
|
||||||
{
|
{
|
||||||
efl_gfx_entity_visible_set(sd->cursor, EINA_TRUE);
|
efl_gfx_entity_visible_set(sd->cursor, EINA_TRUE);
|
||||||
|
@ -1961,7 +1916,7 @@ _efl_ui_textbox_selection_cut(Eo *obj, Efl_Ui_Textbox_Data *sd)
|
||||||
|
|
||||||
/*In password mode, cut will remove text only*/
|
/*In password mode, cut will remove text only*/
|
||||||
if (!efl_text_password_get(obj))
|
if (!efl_text_password_get(obj))
|
||||||
_selection_store(EFL_UI_SELECTION_TYPE_CLIPBOARD, obj);
|
_selection_store(EFL_UI_CNP_BUFFER_COPY_AND_PASTE, obj);
|
||||||
efl_text_interactive_selection_cursors_get(obj, &start, &end);
|
efl_text_interactive_selection_cursors_get(obj, &start, &end);
|
||||||
|
|
||||||
start_pos = efl_text_cursor_position_get(start);
|
start_pos = efl_text_cursor_position_get(start);
|
||||||
|
@ -1993,25 +1948,27 @@ _efl_ui_textbox_selection_copy(Eo *obj, Efl_Ui_Textbox_Data *sd)
|
||||||
efl_layout_signal_emit(sd->entry_edje, "efl,state,select,off", "efl");
|
efl_layout_signal_emit(sd->entry_edje, "efl,state,select,off", "efl");
|
||||||
efl_ui_widget_scroll_hold_pop(obj);
|
efl_ui_widget_scroll_hold_pop(obj);
|
||||||
}
|
}
|
||||||
_selection_store(EFL_UI_SELECTION_TYPE_CLIPBOARD, obj);
|
_selection_store(EFL_UI_CNP_BUFFER_COPY_AND_PASTE, obj);
|
||||||
efl_event_callback_call(obj, EFL_UI_TEXTBOX_EVENT_SELECTION_COPY, NULL);
|
efl_event_callback_call(obj, EFL_UI_TEXTBOX_EVENT_SELECTION_COPY, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_efl_ui_textbox_selection_paste_type(Eo *obj, Efl_Ui_Selection_Type type)
|
_efl_ui_textbox_selection_paste_type(Eo *obj, Efl_Ui_Textbox_Data *sd, Efl_Ui_Cnp_Buffer type)
|
||||||
{
|
{
|
||||||
Efl_Ui_Selection_Format formats = EFL_UI_SELECTION_FORMAT_TEXT | EFL_UI_SELECTION_FORMAT_MARKUP;
|
Eina_Future *future;
|
||||||
|
Eina_Array *types = _figure_out_types(obj, sd);
|
||||||
|
|
||||||
efl_ui_selection_get(obj, type, formats,
|
future = efl_ui_selection_get(obj, type, 0, eina_array_iterator_new(types));
|
||||||
NULL, _selection_data_cb, NULL, 1);
|
|
||||||
|
efl_future_then(obj, future, _selection_data_cb);
|
||||||
|
|
||||||
efl_event_callback_call(obj, EFL_UI_TEXTBOX_EVENT_SELECTION_PASTE, NULL);
|
efl_event_callback_call(obj, EFL_UI_TEXTBOX_EVENT_SELECTION_PASTE, NULL);
|
||||||
|
eina_array_free(types);
|
||||||
}
|
}
|
||||||
|
|
||||||
EOLIAN static void
|
EOLIAN static void
|
||||||
_efl_ui_textbox_selection_paste(Eo *obj, Efl_Ui_Textbox_Data *sd EINA_UNUSED)
|
_efl_ui_textbox_selection_paste(Eo *obj, Efl_Ui_Textbox_Data *sd)
|
||||||
{
|
{
|
||||||
_efl_ui_textbox_selection_paste_type(obj, EFL_UI_SELECTION_TYPE_CLIPBOARD);
|
_efl_ui_textbox_selection_paste_type(obj, sd, EFL_UI_CNP_BUFFER_COPY_AND_PASTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
EOLIAN static void
|
EOLIAN static void
|
||||||
|
@ -2028,44 +1985,15 @@ _efl_ui_textbox_context_menu_enabled_get(const Eo *obj EINA_UNUSED, Efl_Ui_Textb
|
||||||
}
|
}
|
||||||
|
|
||||||
EOLIAN static void
|
EOLIAN static void
|
||||||
_efl_ui_textbox_cnp_mode_set(Eo *obj, Efl_Ui_Textbox_Data *sd, Efl_Ui_Selection_Format cnp_mode)
|
_efl_ui_textbox_cnp_dnd_mode_set(Eo *obj EINA_UNUSED, Efl_Ui_Textbox_Data *sd, Efl_Ui_Textbox_Cnp_Content content)
|
||||||
{
|
{
|
||||||
Elm_Sel_Format dnd_format = EFL_UI_SELECTION_FORMAT_MARKUP;
|
sd->content = content;
|
||||||
|
|
||||||
if (cnp_mode != EFL_UI_SELECTION_FORMAT_TARGETS)
|
|
||||||
{
|
|
||||||
if (cnp_mode & EFL_UI_SELECTION_FORMAT_VCARD)
|
|
||||||
ERR("VCARD format not supported for copy & paste!");
|
|
||||||
else if (cnp_mode & EFL_UI_SELECTION_FORMAT_HTML)
|
|
||||||
ERR("HTML format not supported for copy & paste!");
|
|
||||||
cnp_mode &= ~EFL_UI_SELECTION_FORMAT_VCARD;
|
|
||||||
cnp_mode &= ~EFL_UI_SELECTION_FORMAT_HTML;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sd->cnp_mode == cnp_mode) return;
|
|
||||||
sd->cnp_mode = cnp_mode;
|
|
||||||
if (sd->cnp_mode == EFL_UI_SELECTION_FORMAT_TEXT)
|
|
||||||
dnd_format = EFL_UI_SELECTION_FORMAT_TEXT;
|
|
||||||
else if (cnp_mode == EFL_UI_SELECTION_FORMAT_IMAGE)
|
|
||||||
dnd_format |= EFL_UI_SELECTION_FORMAT_IMAGE;
|
|
||||||
|
|
||||||
elm_drop_target_del(obj, sd->drop_format,
|
|
||||||
_dnd_enter_cb, NULL,
|
|
||||||
_dnd_leave_cb, NULL,
|
|
||||||
_dnd_pos_cb, NULL,
|
|
||||||
_dnd_drop_cb, NULL);
|
|
||||||
sd->drop_format = dnd_format;
|
|
||||||
elm_drop_target_add(obj, sd->drop_format,
|
|
||||||
_dnd_enter_cb, NULL,
|
|
||||||
_dnd_leave_cb, NULL,
|
|
||||||
_dnd_pos_cb, NULL,
|
|
||||||
_dnd_drop_cb, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EOLIAN static Efl_Ui_Selection_Format
|
EOLIAN static Efl_Ui_Textbox_Cnp_Content
|
||||||
_efl_ui_textbox_cnp_mode_get(const Eo *obj EINA_UNUSED, Efl_Ui_Textbox_Data *sd)
|
_efl_ui_textbox_cnp_dnd_mode_get(const Eo *obj EINA_UNUSED, Efl_Ui_Textbox_Data *sd)
|
||||||
{
|
{
|
||||||
return sd->cnp_mode;
|
return sd->content;
|
||||||
}
|
}
|
||||||
|
|
||||||
EOLIAN static void
|
EOLIAN static void
|
||||||
|
@ -3279,7 +3207,7 @@ _efl_ui_textbox_selection_changed_cb(void *data, const Efl_Event *event EINA_UNU
|
||||||
Eo *obj = data;
|
Eo *obj = data;
|
||||||
EFL_UI_TEXT_DATA_GET(obj, sd);
|
EFL_UI_TEXT_DATA_GET(obj, sd);
|
||||||
_edje_signal_emit(sd, "selection,changed", "efl.text");
|
_edje_signal_emit(sd, "selection,changed", "efl.text");
|
||||||
_selection_store(EFL_UI_SELECTION_TYPE_PRIMARY, obj);
|
_selection_store(EFL_UI_CNP_BUFFER_SELECTION, obj);
|
||||||
_selection_defer(obj, sd);
|
_selection_defer(obj, sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,15 @@
|
||||||
|
enum @beta Efl.Ui.Textbox_Cnp_Content {
|
||||||
|
[[What kind of content can be pasted into this widget using Copy & Paste or Drag & Drop functionality.
|
||||||
|
|
||||||
|
Multiple options can be OR-ed together.
|
||||||
|
]]
|
||||||
|
Nothing = 0, [[Nothing can be pasted or dropped into this widget.]]
|
||||||
|
Text = 1, [[Plain text can be pasted or dropped into this widget.]]
|
||||||
|
Markup = 3, [[Markup text can be pasted or dropped into this widget
|
||||||
|
(This includes Plain text).]]
|
||||||
|
Image = 4, [[Images can be pasted or dropped into this widget.]]
|
||||||
|
}
|
||||||
|
|
||||||
class @beta Efl.Ui.Textbox extends Efl.Ui.Layout_Base implements Efl.Input.Clickable,
|
class @beta Efl.Ui.Textbox extends Efl.Ui.Layout_Base implements Efl.Input.Clickable,
|
||||||
Efl.Access.Text, Efl.Access.Editable.Text
|
Efl.Access.Text, Efl.Access.Editable.Text
|
||||||
composites
|
composites
|
||||||
|
@ -31,20 +43,17 @@ class @beta Efl.Ui.Textbox extends Efl.Ui.Layout_Base implements Efl.Input.Click
|
||||||
enabled: bool; [[$true to enable the contextual menu.]]
|
enabled: bool; [[$true to enable the contextual menu.]]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@property cnp_mode @beta {
|
@property cnp_dnd_mode @beta {
|
||||||
/* FIXME: Efl.Ui.Selection_Format does not allow markup without images! */
|
[[Controls the type of content which can be pasted into the widget.
|
||||||
[[Control pasting of text and images for the widget.
|
|
||||||
|
|
||||||
Normally the entry allows both text and images to be pasted.
|
By default, both text and images are allowed..
|
||||||
|
|
||||||
Note: This only changes the behaviour of text.
|
|
||||||
]]
|
]]
|
||||||
set {
|
set {
|
||||||
}
|
}
|
||||||
get {
|
get {
|
||||||
}
|
}
|
||||||
values {
|
values {
|
||||||
format: Efl.Ui.Selection_Format; [[Format for copy & paste.]]
|
allowed_formats : Efl.Ui.Textbox_Cnp_Content; [[Allowed content types.]]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@property selection_handles_enabled {
|
@property selection_handles_enabled {
|
||||||
|
|
|
@ -213,6 +213,9 @@ struct _Efl_Ui_Win_Data
|
||||||
int ignore_frame_resize;
|
int ignore_frame_resize;
|
||||||
Eina_Bool req_wh : 1;
|
Eina_Bool req_wh : 1;
|
||||||
Eina_Bool req_xy : 1;
|
Eina_Bool req_xy : 1;
|
||||||
|
Eina_Array *selection_changed;
|
||||||
|
Eina_Array *planned_changes;
|
||||||
|
Eina_Inarray *drop_target;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
short pointer_move;
|
short pointer_move;
|
||||||
|
@ -382,6 +385,8 @@ static void _elm_win_frame_style_update(Efl_Ui_Win_Data *sd, Eina_Bool force_emi
|
||||||
static inline void _elm_win_need_frame_adjust(Efl_Ui_Win_Data *sd, const char *engine);
|
static inline void _elm_win_need_frame_adjust(Efl_Ui_Win_Data *sd, const char *engine);
|
||||||
static void _elm_win_resize_objects_eval(Evas_Object *obj, Eina_Bool force_resize);
|
static void _elm_win_resize_objects_eval(Evas_Object *obj, Eina_Bool force_resize);
|
||||||
static void _elm_win_frame_obj_update(Efl_Ui_Win_Data *sd, Eina_Bool force);
|
static void _elm_win_frame_obj_update(Efl_Ui_Win_Data *sd, Eina_Bool force);
|
||||||
|
static void _ee_backbone_init(Efl_Ui_Win *obj, Efl_Ui_Win_Data *pd);
|
||||||
|
static void _ee_backbone_shutdown(Efl_Ui_Win *obj, Efl_Ui_Win_Data *pd);
|
||||||
|
|
||||||
static inline Efl_Ui_Win_Type
|
static inline Efl_Ui_Win_Type
|
||||||
_elm_win_type_to_efl_ui_win_type(Elm_Win_Type type)
|
_elm_win_type_to_efl_ui_win_type(Elm_Win_Type type)
|
||||||
|
@ -5930,6 +5935,7 @@ _efl_ui_win_efl_object_finalize(Eo *obj, Efl_Ui_Win_Data *sd)
|
||||||
efl_file_mmap_get(efl_super(efl_part(obj, "background"), EFL_UI_WIN_PART_CLASS)))
|
efl_file_mmap_get(efl_super(efl_part(obj, "background"), EFL_UI_WIN_PART_CLASS)))
|
||||||
efl_file_load(efl_part(obj, "background"));
|
efl_file_load(efl_part(obj, "background"));
|
||||||
}
|
}
|
||||||
|
_ee_backbone_init(obj, sd);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5965,6 +5971,8 @@ _efl_ui_win_efl_object_destructor(Eo *obj, Efl_Ui_Win_Data *pd EINA_UNUSED)
|
||||||
if (pd->finalize_future)
|
if (pd->finalize_future)
|
||||||
eina_future_cancel(pd->finalize_future);
|
eina_future_cancel(pd->finalize_future);
|
||||||
|
|
||||||
|
_ee_backbone_shutdown(obj, pd);
|
||||||
|
|
||||||
efl_destructor(efl_super(obj, MY_CLASS));
|
efl_destructor(efl_super(obj, MY_CLASS));
|
||||||
|
|
||||||
efl_unref(pd->provider);
|
efl_unref(pd->provider);
|
||||||
|
@ -5981,6 +5989,7 @@ _efl_ui_win_efl_object_constructor(Eo *obj, Efl_Ui_Win_Data *pd)
|
||||||
pd->provider = efl_add_ref(EFL_UI_FOCUS_PARENT_PROVIDER_STANDARD_CLASS, NULL);
|
pd->provider = efl_add_ref(EFL_UI_FOCUS_PARENT_PROVIDER_STANDARD_CLASS, NULL);
|
||||||
pd->profile.available = eina_array_new(4);
|
pd->profile.available = eina_array_new(4);
|
||||||
pd->max_w = pd->max_h = -1;
|
pd->max_w = pd->max_h = -1;
|
||||||
|
pd->planned_changes = eina_array_new(10);
|
||||||
|
|
||||||
// For bindings: if no parent, allow simple unref
|
// For bindings: if no parent, allow simple unref
|
||||||
if (!efl_parent_get(obj))
|
if (!efl_parent_get(obj))
|
||||||
|
@ -9184,6 +9193,249 @@ elm_win_teamwork_uri_open(Efl_Ui_Win *obj EINA_UNUSED, const char *uri EINA_UNUS
|
||||||
ERR("Calling deprecrated function '%s'", __FUNCTION__);
|
ERR("Calling deprecrated function '%s'", __FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* What here follows is code that implements the glue between ecore evas and efl_ui* side */
|
||||||
|
typedef struct {
|
||||||
|
Eo *obj;
|
||||||
|
Eina_Bool currently_inside;
|
||||||
|
} Ui_Dnd_Target;
|
||||||
|
|
||||||
|
static inline Efl_Ui_Cnp_Buffer
|
||||||
|
_ui_buffer_get(Ecore_Evas_Selection_Buffer buffer)
|
||||||
|
{
|
||||||
|
if (buffer == ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER)
|
||||||
|
return EFL_UI_CNP_BUFFER_SELECTION;
|
||||||
|
else if (buffer == ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER)
|
||||||
|
return EFL_UI_CNP_BUFFER_COPY_AND_PASTE;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_register_selection_changed(Efl_Ui_Selection *selection)
|
||||||
|
{
|
||||||
|
ELM_WIN_DATA_GET(efl_provider_find(selection, EFL_UI_WIN_CLASS), pd);
|
||||||
|
|
||||||
|
eina_array_push(pd->planned_changes, selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_remove_object(void *data, void *gdata)
|
||||||
|
{
|
||||||
|
if (data == gdata)
|
||||||
|
return EINA_FALSE;
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_selection_changed_cb(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection)
|
||||||
|
{
|
||||||
|
Efl_Ui_Win_Data *pd = _elm_win_associate_get(ee);
|
||||||
|
Efl_Ui_Wm_Selection_Changed changed = {
|
||||||
|
.seat = seat,
|
||||||
|
.buffer = _ui_buffer_get(selection),
|
||||||
|
.caused_by = eina_array_count(pd->planned_changes) > 0 ? eina_array_data_get(pd->planned_changes, 0) : NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < eina_array_count(pd->selection_changed); ++i)
|
||||||
|
{
|
||||||
|
Eo *obj = eina_array_data_get(pd->selection_changed, i);
|
||||||
|
|
||||||
|
efl_event_callback_call(obj, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, &changed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed.caused_by)
|
||||||
|
eina_array_remove(pd->planned_changes, _remove_object, changed.caused_by);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_motion_cb(Ecore_Evas *ee, unsigned int seat, Eina_Position2D p)
|
||||||
|
{
|
||||||
|
Efl_Ui_Win_Data *pd = _elm_win_associate_get(ee);
|
||||||
|
for (unsigned int i = 0; i < eina_inarray_count(pd->drop_target); ++i)
|
||||||
|
{
|
||||||
|
Ui_Dnd_Target *target = eina_inarray_nth(pd->drop_target, i);
|
||||||
|
Eina_Rect rect = efl_gfx_entity_geometry_get(target->obj);
|
||||||
|
Eina_Bool inside = eina_rectangle_coords_inside(&rect.rect, p.x, p.y);
|
||||||
|
Efl_Ui_Drop_Event ev = {p, seat, ecore_evas_drop_available_types_get(ee, seat)};
|
||||||
|
|
||||||
|
if (target->currently_inside && !inside)
|
||||||
|
{
|
||||||
|
target->currently_inside = EINA_FALSE;
|
||||||
|
efl_event_callback_call(target->obj, EFL_UI_DND_EVENT_DROP_LEFT, &ev);
|
||||||
|
}
|
||||||
|
else if (!target->currently_inside && inside)
|
||||||
|
{
|
||||||
|
target->currently_inside = EINA_TRUE;
|
||||||
|
efl_event_callback_call(target->obj, EFL_UI_DND_EVENT_DROP_ENTERED, &ev);
|
||||||
|
}
|
||||||
|
else if (target->currently_inside && inside)
|
||||||
|
{
|
||||||
|
efl_event_callback_call(target->obj, EFL_UI_DND_EVENT_DROP_POSITION_CHANGED, &ev);
|
||||||
|
}
|
||||||
|
eina_accessor_free(ev.available_types);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_enter_state_change_cb(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Eina_Position2D p, Eina_Bool move_inside)
|
||||||
|
{
|
||||||
|
Efl_Ui_Win_Data *pd = _elm_win_associate_get(ee);
|
||||||
|
for (unsigned int i = 0; i < eina_inarray_count(pd->drop_target); ++i)
|
||||||
|
{
|
||||||
|
Ui_Dnd_Target *target = eina_inarray_nth(pd->drop_target, i);
|
||||||
|
Eina_Rect rect = efl_gfx_entity_geometry_get(target->obj);
|
||||||
|
Eina_Bool inside = eina_rectangle_coords_inside(&rect.rect, p.x, p.y);
|
||||||
|
Efl_Ui_Drop_Event ev = {p, seat, ecore_evas_drop_available_types_get(ee, seat)};
|
||||||
|
|
||||||
|
if (inside && move_inside)
|
||||||
|
{
|
||||||
|
target->currently_inside = EINA_TRUE;
|
||||||
|
efl_event_callback_call(target->obj, EFL_UI_DND_EVENT_DROP_ENTERED, &ev);
|
||||||
|
}
|
||||||
|
else if (!move_inside && !target->currently_inside)
|
||||||
|
{
|
||||||
|
target->currently_inside = EINA_FALSE;
|
||||||
|
efl_event_callback_call(target->obj, EFL_UI_DND_EVENT_DROP_LEFT, &ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_drop_cb(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Eina_Position2D p, const char *action)
|
||||||
|
{
|
||||||
|
Eina_List *itr, *top_objects_list = NULL;
|
||||||
|
Efl_Ui_Win_Data *pd = _elm_win_associate_get(ee);
|
||||||
|
Eina_Array *tmp = eina_array_new(10);
|
||||||
|
Eo *top_obj;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < eina_inarray_count(pd->drop_target); ++i)
|
||||||
|
{
|
||||||
|
Ui_Dnd_Target *target = eina_inarray_nth(pd->drop_target, i);
|
||||||
|
Eina_Rect rect = efl_gfx_entity_geometry_get(target->obj);
|
||||||
|
Eina_Bool inside = eina_rectangle_coords_inside(&rect.rect, p.x, p.y);
|
||||||
|
|
||||||
|
if (inside)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_FALSE_GOTO(target->currently_inside, end);
|
||||||
|
eina_array_push(tmp, target->obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We retrieve the (non-smart) objects pointed by (px, py) */
|
||||||
|
top_objects_list = evas_tree_objects_at_xy_get(ecore_evas_get(ee), NULL, p.x, p.y);
|
||||||
|
/* We walk on this list from the last because if the list contains more than one
|
||||||
|
* element, all but the last will repeat events. The last one can repeat events
|
||||||
|
* or not. Anyway, this last one is the first that has to be taken into account
|
||||||
|
* for the determination of the drop target.
|
||||||
|
*/
|
||||||
|
EINA_LIST_REVERSE_FOREACH(top_objects_list, itr, top_obj)
|
||||||
|
{
|
||||||
|
Evas_Object *object = top_obj;
|
||||||
|
/* We search for the dropable data into the object. If not found, we search into its parent.
|
||||||
|
* For example, if a button is a drop target, the first object will be an (internal) image.
|
||||||
|
* The drop target is attached to the button, i.e to image's parent. That's why we need to
|
||||||
|
* walk on the parents until NULL.
|
||||||
|
* If we find this dropable data, we found our drop target.
|
||||||
|
*/
|
||||||
|
while (object)
|
||||||
|
{
|
||||||
|
unsigned int out_idx;
|
||||||
|
if (!eina_array_find(tmp, object, &out_idx))
|
||||||
|
{
|
||||||
|
object = evas_object_smart_parent_get(object);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Efl_Ui_Drop_Dropped_Event ev = {{p, seat, ecore_evas_drop_available_types_get(ee, seat)}, action};
|
||||||
|
efl_event_callback_call(object, EFL_UI_DND_EVENT_DROP_DROPPED, &ev);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
eina_list_free(top_objects_list);
|
||||||
|
eina_array_free(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ee_backbone_init(Efl_Ui_Win *obj EINA_UNUSED, Efl_Ui_Win_Data *pd)
|
||||||
|
{
|
||||||
|
pd->selection_changed = eina_array_new(1);
|
||||||
|
pd->drop_target = eina_inarray_new(sizeof(Ui_Dnd_Target), 1);
|
||||||
|
|
||||||
|
ecore_evas_callback_selection_changed_set(pd->ee, _selection_changed_cb);
|
||||||
|
ecore_evas_callback_drop_drop_set(pd->ee, _drop_cb);
|
||||||
|
ecore_evas_callback_drop_motion_set(pd->ee, _motion_cb);
|
||||||
|
ecore_evas_callback_drop_state_changed_set(pd->ee, _enter_state_change_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ee_backbone_shutdown(Efl_Ui_Win *obj EINA_UNUSED, Efl_Ui_Win_Data *pd)
|
||||||
|
{
|
||||||
|
ecore_evas_callback_selection_changed_set(pd->ee, NULL);
|
||||||
|
ecore_evas_callback_drop_drop_set(pd->ee, NULL);
|
||||||
|
ecore_evas_callback_drop_motion_set(pd->ee, NULL);
|
||||||
|
ecore_evas_callback_drop_state_changed_set(pd->ee, NULL);
|
||||||
|
|
||||||
|
eina_array_free(pd->selection_changed);
|
||||||
|
pd->selection_changed = NULL;
|
||||||
|
eina_inarray_free(pd->drop_target);
|
||||||
|
pd->drop_target = NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_remove(void *data, void *gdata)
|
||||||
|
{
|
||||||
|
if (data == gdata)
|
||||||
|
return EINA_FALSE;
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_drop_event_register(Eo *obj)
|
||||||
|
{
|
||||||
|
Ui_Dnd_Target target = {obj, EINA_FALSE};
|
||||||
|
Efl_Ui_Win_Data *pd = efl_data_scope_safe_get(efl_provider_find(obj, MY_CLASS), MY_CLASS);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(pd);
|
||||||
|
|
||||||
|
eina_inarray_push(pd->drop_target, &target);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_drop_event_unregister(Eo *obj)
|
||||||
|
{
|
||||||
|
int idx = -1;
|
||||||
|
Efl_Ui_Win_Data *pd = efl_data_scope_safe_get(efl_provider_find(obj, MY_CLASS), MY_CLASS);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < eina_inarray_count(pd->drop_target); ++i)
|
||||||
|
{
|
||||||
|
Ui_Dnd_Target *target = eina_inarray_nth(pd->drop_target, i);
|
||||||
|
if (target->obj == obj)
|
||||||
|
{
|
||||||
|
//FIXME emit drop
|
||||||
|
target->currently_inside = EINA_FALSE;
|
||||||
|
idx = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (idx != -1)
|
||||||
|
eina_inarray_remove_at(pd->drop_target, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_selection_changed_event_register(Eo *obj)
|
||||||
|
{
|
||||||
|
Efl_Ui_Win_Data *pd = efl_data_scope_safe_get(efl_provider_find(obj, MY_CLASS), MY_CLASS);
|
||||||
|
|
||||||
|
eina_array_push(pd->selection_changed, obj);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
_selection_changed_event_unregister(Eo *obj)
|
||||||
|
{
|
||||||
|
Efl_Ui_Win_Data *pd = efl_data_scope_safe_get(efl_provider_find(obj, MY_CLASS), MY_CLASS);
|
||||||
|
|
||||||
|
eina_array_remove(pd->selection_changed, _remove, obj);
|
||||||
|
}
|
||||||
/* Internal EO APIs and hidden overrides */
|
/* Internal EO APIs and hidden overrides */
|
||||||
|
|
||||||
ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(efl_ui_win, Efl_Ui_Win_Data)
|
ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(efl_ui_win, Efl_Ui_Win_Data)
|
||||||
|
|
|
@ -0,0 +1,244 @@
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "elementary_config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Elementary.h>
|
||||||
|
#include <Ecore_Evas.h>
|
||||||
|
|
||||||
|
#include "elm_priv.h"
|
||||||
|
#include "elm_entry_eo.h"
|
||||||
|
|
||||||
|
static inline Ecore_Evas_Selection_Buffer
|
||||||
|
_elm_sel_type_to_ee_type(Elm_Sel_Type type)
|
||||||
|
{
|
||||||
|
if (type == ELM_SEL_TYPE_PRIMARY)
|
||||||
|
return ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER;
|
||||||
|
if (type == ELM_SEL_TYPE_XDND)
|
||||||
|
return ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER;
|
||||||
|
if (type == ELM_SEL_TYPE_CLIPBOARD)
|
||||||
|
return ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER;
|
||||||
|
return ECORE_EVAS_SELECTION_BUFFER_LAST;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Eina_Array*
|
||||||
|
_elm_sel_format_to_mime_type(Elm_Sel_Format format)
|
||||||
|
{
|
||||||
|
Eina_Array *ret = eina_array_new(10);
|
||||||
|
if (format & ELM_SEL_FORMAT_TEXT)
|
||||||
|
eina_array_push(ret, "text/plain;charset=utf-8");
|
||||||
|
if (format & ELM_SEL_FORMAT_MARKUP)
|
||||||
|
eina_array_push(ret, "application/x-elementary-markup");
|
||||||
|
if (format & ELM_SEL_FORMAT_IMAGE)
|
||||||
|
{
|
||||||
|
eina_array_push(ret, "image/png");
|
||||||
|
eina_array_push(ret, "image/jpeg");
|
||||||
|
eina_array_push(ret, "image/x-ms-bmp");
|
||||||
|
eina_array_push(ret, "image/gif");
|
||||||
|
eina_array_push(ret, "image/tiff");
|
||||||
|
eina_array_push(ret, "image/svg+xml");
|
||||||
|
eina_array_push(ret, "image/x-xpixmap");
|
||||||
|
eina_array_push(ret, "image/x-tga");
|
||||||
|
eina_array_push(ret, "image/x-portable-pixmap");
|
||||||
|
}
|
||||||
|
if (format & ELM_SEL_FORMAT_VCARD)
|
||||||
|
eina_array_push(ret, "text/vcard");
|
||||||
|
if (format & ELM_SEL_FORMAT_HTML)
|
||||||
|
eina_array_push(ret, "application/xhtml+xml");
|
||||||
|
|
||||||
|
if (eina_array_count(ret) == 0)
|
||||||
|
ERR("Specified mime type is not available");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const Elm_Sel_Format
|
||||||
|
_mime_type_to_elm_sel_format(const char *mime_type)
|
||||||
|
{
|
||||||
|
if (eina_streq(mime_type, "text/vcard"))
|
||||||
|
return ELM_SEL_FORMAT_VCARD;
|
||||||
|
else if (eina_streq(mime_type, "application/x-elementary-markup"))
|
||||||
|
return ELM_SEL_FORMAT_MARKUP;
|
||||||
|
else if (eina_streq(mime_type, "application/xhtml+xml"))
|
||||||
|
return ELM_SEL_FORMAT_HTML;
|
||||||
|
else if (!strncmp(mime_type, "text/", strlen("text/")))
|
||||||
|
return ELM_SEL_FORMAT_TEXT;
|
||||||
|
else if (!strncmp(mime_type, "image/", strlen("image/")))
|
||||||
|
return ELM_SEL_FORMAT_IMAGE;
|
||||||
|
|
||||||
|
return ELM_SEL_FORMAT_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_default_seat(const Eo *obj)
|
||||||
|
{
|
||||||
|
return evas_device_seat_id_get(evas_default_device_get(evas_object_evas_get(obj), EFL_INPUT_DEVICE_TYPE_SEAT));
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection,
|
||||||
|
Elm_Sel_Format format,
|
||||||
|
const void *buf, size_t buflen)
|
||||||
|
{
|
||||||
|
Eina_Content *content;
|
||||||
|
Ecore_Evas *ee;
|
||||||
|
const char *mime_type;
|
||||||
|
Eina_Slice data;
|
||||||
|
Eina_Array *tmp;
|
||||||
|
|
||||||
|
if (format == ELM_SEL_FORMAT_TEXT && ((char*)buf)[buflen - 1] != '\0')
|
||||||
|
{
|
||||||
|
data.mem = eina_memdup((unsigned char *)buf, buflen, EINA_TRUE);
|
||||||
|
data.len = buflen + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data.mem = buf;
|
||||||
|
data.len = buflen;
|
||||||
|
}
|
||||||
|
|
||||||
|
ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
|
||||||
|
|
||||||
|
tmp = _elm_sel_format_to_mime_type(format);
|
||||||
|
if (eina_array_count(tmp) != 1)
|
||||||
|
{
|
||||||
|
ERR("You cannot specify more than one format when setting selection");
|
||||||
|
}
|
||||||
|
mime_type = eina_array_data_get(tmp, 0);
|
||||||
|
content = eina_content_new(data, mime_type);
|
||||||
|
_register_selection_changed(obj);
|
||||||
|
|
||||||
|
return ecore_evas_selection_set(ee, _default_seat(obj), _elm_sel_type_to_ee_type(selection), content);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
elm_object_cnp_selection_clear(Evas_Object *obj,
|
||||||
|
Elm_Sel_Type selection)
|
||||||
|
{
|
||||||
|
Ecore_Evas *ee;
|
||||||
|
|
||||||
|
ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
|
||||||
|
return ecore_evas_selection_set(ee, _default_seat(obj), _elm_sel_type_to_ee_type(selection), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
elm_cnp_clipboard_selection_has_owner(Evas_Object *obj)
|
||||||
|
{
|
||||||
|
Ecore_Evas *ee;
|
||||||
|
|
||||||
|
ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
|
||||||
|
return ecore_evas_selection_exists(ee, _default_seat(obj), ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct _Sel_Lost_Data Sel_Lost_Data;
|
||||||
|
struct _Sel_Lost_Data
|
||||||
|
{
|
||||||
|
const Evas_Object *obj;
|
||||||
|
Elm_Sel_Type type;
|
||||||
|
void *udata;
|
||||||
|
Elm_Selection_Loss_Cb loss_cb;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
_selection_changed_cb(void *data, const Efl_Event *ev)
|
||||||
|
{
|
||||||
|
Sel_Lost_Data *ldata = data;
|
||||||
|
Efl_Ui_Wm_Selection_Changed *changed = ev->info;
|
||||||
|
|
||||||
|
if (changed->buffer == EFL_UI_CNP_BUFFER_SELECTION && ldata->type != ELM_SEL_TYPE_PRIMARY)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (changed->buffer == EFL_UI_CNP_BUFFER_COPY_AND_PASTE && ldata->type != ELM_SEL_TYPE_CLIPBOARD)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ldata->obj == changed->caused_by)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ldata->loss_cb(ldata->udata, ldata->type);
|
||||||
|
free(data);
|
||||||
|
efl_event_callback_del(ev->object, ev->desc, _selection_changed_cb, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI void
|
||||||
|
elm_cnp_selection_loss_callback_set(Evas_Object *obj, Elm_Sel_Type type, Elm_Selection_Loss_Cb func, const void *data)
|
||||||
|
{
|
||||||
|
Sel_Lost_Data *ldata = calloc(1, sizeof(Sel_Lost_Data));
|
||||||
|
|
||||||
|
if (!ldata) return;
|
||||||
|
ldata->obj = obj;
|
||||||
|
ldata->type = type;
|
||||||
|
ldata->udata = (void *)data;
|
||||||
|
ldata->loss_cb = func;
|
||||||
|
efl_event_callback_add(obj, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, _selection_changed_cb, ldata);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Elm_Drop_Cb data_cb;
|
||||||
|
void *data;
|
||||||
|
Elm_Sel_Format format;
|
||||||
|
} Callback_Storage;
|
||||||
|
|
||||||
|
static Eina_Value
|
||||||
|
_callback_storage_deliver(Eo *obj, void *data, const Eina_Value value)
|
||||||
|
{
|
||||||
|
Callback_Storage *cb_storage = data;
|
||||||
|
Eina_Content *content = eina_value_to_content(&value);
|
||||||
|
Elm_Sel_Format format = _mime_type_to_elm_sel_format(eina_content_type_get(content));
|
||||||
|
Eina_Slice cdata;
|
||||||
|
|
||||||
|
cdata = eina_content_data_get(content);
|
||||||
|
Elm_Selection_Data d = { 0 };
|
||||||
|
d.data = eina_memdup((unsigned char*)cdata.bytes, cdata.len, EINA_FALSE);
|
||||||
|
d.len = cdata.len;
|
||||||
|
d.format = _mime_type_to_elm_sel_format(eina_content_type_get(content));
|
||||||
|
|
||||||
|
if (cb_storage->data_cb)
|
||||||
|
{
|
||||||
|
cb_storage->data_cb(cb_storage->data, obj, &d);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_FALSE_RETURN_VAL(format == ELM_SEL_FORMAT_TEXT || format == ELM_SEL_FORMAT_MARKUP || format == ELM_SEL_FORMAT_HTML, EINA_VALUE_EMPTY);
|
||||||
|
|
||||||
|
_elm_entry_entry_paste(obj, (const char *) d.data);
|
||||||
|
}
|
||||||
|
free(d.data);
|
||||||
|
|
||||||
|
return EINA_VALUE_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Value
|
||||||
|
_callback_storage_error(Eo *obj EINA_UNUSED, void *data EINA_UNUSED, Eina_Error error)
|
||||||
|
{
|
||||||
|
ERR("Content cound not be received because of %s.", eina_error_msg_get(error));
|
||||||
|
return EINA_VALUE_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_callback_storage_free(Eo *obj EINA_UNUSED, void *data, const Eina_Future *dead_future EINA_UNUSED)
|
||||||
|
{
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
elm_cnp_selection_get(const Evas_Object *obj, Elm_Sel_Type selection,
|
||||||
|
Elm_Sel_Format format,
|
||||||
|
Elm_Drop_Cb data_cb, void *udata)
|
||||||
|
{
|
||||||
|
Ecore_Evas *ee;
|
||||||
|
Eina_Array *mime_types;
|
||||||
|
Eina_Future *future;
|
||||||
|
Callback_Storage *storage;
|
||||||
|
|
||||||
|
ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
|
||||||
|
mime_types = _elm_sel_format_to_mime_type(format);
|
||||||
|
future = ecore_evas_selection_get(ee, _default_seat(obj), _elm_sel_type_to_ee_type(selection), eina_array_iterator_new(mime_types));
|
||||||
|
storage = calloc(1,sizeof(Callback_Storage));
|
||||||
|
storage->data_cb = data_cb;
|
||||||
|
storage->data = udata;
|
||||||
|
storage->format = format;
|
||||||
|
|
||||||
|
efl_future_then(obj, future, _callback_storage_deliver, _callback_storage_error, _callback_storage_free, EINA_VALUE_TYPE_CONTENT, storage);
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
|
@ -43,8 +43,6 @@
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
# include <efl_ui_selection_types.eot.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event notifying that the selection has changed
|
* Event notifying that the selection has changed
|
||||||
* @see Elm_Cnp_Event_Selection_Changed
|
* @see Elm_Cnp_Event_Selection_Changed
|
||||||
|
|
|
@ -0,0 +1,812 @@
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "elementary_config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <Elementary.h>
|
||||||
|
#include "elm_priv.h"
|
||||||
|
|
||||||
|
int ELM_CNP_EVENT_SELECTION_CHANGED;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *enter_data, *leave_data, *pos_data, *drop_data;
|
||||||
|
Elm_Drag_State enter_cb;
|
||||||
|
Elm_Drag_State leave_cb;
|
||||||
|
Elm_Drag_Pos pos_cb;
|
||||||
|
Elm_Drop_Cb drop_cb;
|
||||||
|
Eina_Array *mime_types;
|
||||||
|
Elm_Sel_Format format;
|
||||||
|
Elm_Xdnd_Action action;
|
||||||
|
} Elm_Drop_Target;
|
||||||
|
|
||||||
|
static int
|
||||||
|
_default_seat(const Eo *obj)
|
||||||
|
{
|
||||||
|
return evas_device_seat_id_get(evas_default_device_get(evas_object_evas_get(obj), EFL_INPUT_DEVICE_TYPE_SEAT));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char*
|
||||||
|
_action_to_string(Elm_Xdnd_Action action)
|
||||||
|
{
|
||||||
|
if (action == ELM_XDND_ACTION_COPY) return "copy";
|
||||||
|
if (action == ELM_XDND_ACTION_MOVE) return "move";
|
||||||
|
if (action == ELM_XDND_ACTION_PRIVATE) return "private";
|
||||||
|
if (action == ELM_XDND_ACTION_ASK) return "ask";
|
||||||
|
if (action == ELM_XDND_ACTION_LIST) return "list";
|
||||||
|
if (action == ELM_XDND_ACTION_LINK) return "link";
|
||||||
|
if (action == ELM_XDND_ACTION_DESCRIPTION) return "description";
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
static Elm_Xdnd_Action
|
||||||
|
_string_to_action(const char* action)
|
||||||
|
{
|
||||||
|
if (eina_streq(action, "copy")) return ELM_XDND_ACTION_COPY;
|
||||||
|
else if (eina_streq(action, "move")) return ELM_XDND_ACTION_MOVE;
|
||||||
|
else if (eina_streq(action, "private")) return ELM_XDND_ACTION_PRIVATE;
|
||||||
|
else if (eina_streq(action, "ask")) return ELM_XDND_ACTION_ASK;
|
||||||
|
else if (eina_streq(action, "list")) return ELM_XDND_ACTION_LIST;
|
||||||
|
else if (eina_streq(action, "link")) return ELM_XDND_ACTION_LINK;
|
||||||
|
else if (eina_streq(action, "description")) return ELM_XDND_ACTION_DESCRIPTION;
|
||||||
|
return ELM_XDND_ACTION_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_enter_cb(void *data, const Efl_Event *ev)
|
||||||
|
{
|
||||||
|
Elm_Drop_Target *target = data;
|
||||||
|
|
||||||
|
if (target->enter_cb)
|
||||||
|
target->enter_cb(target->enter_data, ev->object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_leave_cb(void *data, const Efl_Event *ev)
|
||||||
|
{
|
||||||
|
Elm_Drop_Target *target = data;
|
||||||
|
|
||||||
|
if (target->leave_cb)
|
||||||
|
target->leave_cb(target->leave_data, ev->object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_pos_cb(void *data, const Efl_Event *ev)
|
||||||
|
{
|
||||||
|
Elm_Drop_Target *target = data;
|
||||||
|
Efl_Ui_Drop_Event *event = ev->info;
|
||||||
|
|
||||||
|
if (target->pos_cb)
|
||||||
|
target->pos_cb(target->pos_data, ev->object, event->position.x, event->position.y, target->action); //FIXME action
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Value
|
||||||
|
_deliver_content(Eo *obj, void *data, const Eina_Value value)
|
||||||
|
{
|
||||||
|
Elm_Drop_Target *target = data;
|
||||||
|
Elm_Selection_Data sel_data;
|
||||||
|
Eina_Content *content = eina_value_to_content(&value);
|
||||||
|
|
||||||
|
sel_data.data = (void*)eina_content_data_get(content).mem;
|
||||||
|
sel_data.len = eina_content_data_get(content).len;
|
||||||
|
sel_data.action = target->action;
|
||||||
|
sel_data.format = target->format;
|
||||||
|
|
||||||
|
if (target->drop_cb)
|
||||||
|
target->drop_cb(target->drop_data, obj, &sel_data);
|
||||||
|
|
||||||
|
return EINA_VALUE_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_drop_cb(void *data, const Efl_Event *ev)
|
||||||
|
{
|
||||||
|
Efl_Ui_Drop_Dropped_Event *event = ev->info;
|
||||||
|
Elm_Drop_Target *target = data;
|
||||||
|
target->action = _string_to_action(event->action);
|
||||||
|
efl_future_then(ev->object, efl_ui_dnd_drop_data_get(ev->object, _default_seat(ev->object), eina_array_iterator_new(target->mime_types)),
|
||||||
|
.success = _deliver_content,
|
||||||
|
.data = target
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_inv_cb(void *data, const Efl_Event *ev)
|
||||||
|
{
|
||||||
|
Elm_Drop_Target *target = data;
|
||||||
|
elm_drop_target_del(ev->object, target->format, target->enter_cb, target->enter_data, target->leave_cb,
|
||||||
|
target->leave_data, target->pos_cb, target->pos_data, target->drop_cb, target->drop_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFL_CALLBACKS_ARRAY_DEFINE(drop_target_cb,
|
||||||
|
{EFL_UI_DND_EVENT_DROP_ENTERED, _enter_cb},
|
||||||
|
{EFL_UI_DND_EVENT_DROP_LEFT, _leave_cb},
|
||||||
|
{EFL_UI_DND_EVENT_DROP_POSITION_CHANGED, _pos_cb},
|
||||||
|
{EFL_UI_DND_EVENT_DROP_DROPPED, _drop_cb},
|
||||||
|
{EFL_EVENT_INVALIDATE, _inv_cb}
|
||||||
|
)
|
||||||
|
|
||||||
|
static Eina_Hash *target_register = NULL;
|
||||||
|
|
||||||
|
static Eina_Array*
|
||||||
|
_format_to_mime_array(Elm_Sel_Format format)
|
||||||
|
{
|
||||||
|
Eina_Array *ret = eina_array_new(10);
|
||||||
|
|
||||||
|
if (format & ELM_SEL_FORMAT_TEXT)
|
||||||
|
eina_array_push(ret, "text/plain;charset=utf-8");
|
||||||
|
if (format & ELM_SEL_FORMAT_MARKUP)
|
||||||
|
eina_array_push(ret, "application/x-elementary-markup");
|
||||||
|
if (format & ELM_SEL_FORMAT_IMAGE)
|
||||||
|
{
|
||||||
|
eina_array_push(ret, "image/png");
|
||||||
|
eina_array_push(ret, "image/jpeg");
|
||||||
|
eina_array_push(ret, "image/x-ms-bmp");
|
||||||
|
eina_array_push(ret, "image/gif");
|
||||||
|
eina_array_push(ret, "image/tiff");
|
||||||
|
eina_array_push(ret, "image/svg+xml");
|
||||||
|
eina_array_push(ret, "image/x-xpixmap");
|
||||||
|
eina_array_push(ret, "image/x-tga");
|
||||||
|
eina_array_push(ret, "image/x-portable-pixmap");
|
||||||
|
}
|
||||||
|
if (format & ELM_SEL_FORMAT_VCARD)
|
||||||
|
eina_array_push(ret, "text/vcard");
|
||||||
|
if (format & ELM_SEL_FORMAT_HTML)
|
||||||
|
eina_array_push(ret, "text/html");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
elm_drop_target_add(Evas_Object *obj, Elm_Sel_Format format,
|
||||||
|
Elm_Drag_State enter_cb, void *enter_data,
|
||||||
|
Elm_Drag_State leave_cb, void *leave_data,
|
||||||
|
Elm_Drag_Pos pos_cb, void *pos_data,
|
||||||
|
Elm_Drop_Cb drop_cb, void *drop_data)
|
||||||
|
{
|
||||||
|
|
||||||
|
Elm_Drop_Target *target = calloc(1, sizeof(Elm_Drop_Target));
|
||||||
|
target->enter_cb = enter_cb;
|
||||||
|
target->enter_data = enter_data;
|
||||||
|
target->leave_cb = leave_cb;
|
||||||
|
target->leave_data = leave_data;
|
||||||
|
target->pos_cb = pos_cb;
|
||||||
|
target->pos_data = pos_data;
|
||||||
|
target->drop_cb = drop_cb;
|
||||||
|
target->drop_data = drop_data;
|
||||||
|
target->mime_types = _format_to_mime_array(format);
|
||||||
|
target->format = format;
|
||||||
|
|
||||||
|
efl_event_callback_array_add(obj, drop_target_cb(), target);
|
||||||
|
|
||||||
|
if (!target_register)
|
||||||
|
target_register = eina_hash_pointer_new(NULL);
|
||||||
|
eina_hash_list_append(target_register, &obj, target);
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
elm_drop_target_del(Evas_Object *obj, Elm_Sel_Format format,
|
||||||
|
Elm_Drag_State enter_cb, void *enter_data,
|
||||||
|
Elm_Drag_State leave_cb, void *leave_data,
|
||||||
|
Elm_Drag_Pos pos_cb, void *pos_data,
|
||||||
|
Elm_Drop_Cb drop_cb, void *drop_data)
|
||||||
|
{
|
||||||
|
Elm_Drop_Target *target;
|
||||||
|
Eina_List *n, *found = NULL;
|
||||||
|
|
||||||
|
if (!target_register)
|
||||||
|
return EINA_TRUE;
|
||||||
|
Eina_List *targets = eina_hash_find(target_register, &obj);
|
||||||
|
|
||||||
|
if (!targets)
|
||||||
|
return EINA_TRUE;
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(targets, n, target)
|
||||||
|
{
|
||||||
|
if (target->enter_cb == enter_cb && target->enter_data == enter_data &&
|
||||||
|
target->leave_cb == leave_cb && target->leave_data == leave_data &&
|
||||||
|
target->pos_cb == pos_cb && target->pos_data == pos_data &&
|
||||||
|
target->drop_cb == drop_cb && target->drop_data == drop_data &&
|
||||||
|
target->format == format)
|
||||||
|
{
|
||||||
|
|
||||||
|
found = n;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
efl_event_callback_array_del(obj, drop_target_cb(), eina_list_data_get(found));
|
||||||
|
eina_hash_list_remove(target_register, &obj, target);
|
||||||
|
eina_array_free(target->mime_types);
|
||||||
|
free(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct _Item_Container_Drag_Info
|
||||||
|
{ /* Info kept for containers to support drag */
|
||||||
|
Evas_Object *obj;
|
||||||
|
Ecore_Timer *tm; /* When this expires, start drag */
|
||||||
|
double anim_tm; /* Time period to set tm */
|
||||||
|
double tm_to_drag; /* Time period to set tm */
|
||||||
|
Elm_Xy_Item_Get_Cb itemgetcb;
|
||||||
|
Elm_Item_Container_Data_Get_Cb data_get;
|
||||||
|
|
||||||
|
Evas_Coord x_down; /* Mouse down x cord when drag starts */
|
||||||
|
Evas_Coord y_down; /* Mouse down y cord when drag starts */
|
||||||
|
|
||||||
|
/* Some extra information needed to impl default anim */
|
||||||
|
Evas *e;
|
||||||
|
Eina_List *icons; /* List of icons to animate (Anim_Icon) */
|
||||||
|
int final_icon_w; /* We need the w and h of the final icon for the animation */
|
||||||
|
int final_icon_h;
|
||||||
|
Ecore_Animator *ea;
|
||||||
|
|
||||||
|
Elm_Drag_User_Info user_info;
|
||||||
|
};
|
||||||
|
typedef struct _Item_Container_Drag_Info Item_Container_Drag_Info;
|
||||||
|
|
||||||
|
struct _Anim_Icon
|
||||||
|
{
|
||||||
|
int start_x;
|
||||||
|
int start_y;
|
||||||
|
int start_w;
|
||||||
|
int start_h;
|
||||||
|
Evas_Object *o;
|
||||||
|
};
|
||||||
|
typedef struct _Anim_Icon Anim_Icon;
|
||||||
|
static Eina_List *cont_drag_tg = NULL; /* List of Item_Container_Drag_Info */
|
||||||
|
|
||||||
|
static Eina_Bool elm_drag_item_container_del_internal(Evas_Object *obj, Eina_Bool full);
|
||||||
|
static void _cont_obj_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info);
|
||||||
|
static void _cont_obj_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info);
|
||||||
|
static void _cont_obj_mouse_down(void *data, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info);
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cont_drag_done_cb(void *data, Evas_Object *obj EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Item_Container_Drag_Info *st = data;
|
||||||
|
elm_widget_scroll_freeze_pop(st->obj);
|
||||||
|
if (st->user_info.dragdone)
|
||||||
|
st->user_info.dragdone(st->user_info.donecbdata, NULL, EINA_FALSE); /*FIXME*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_cont_obj_drag_start(void *data)
|
||||||
|
{ /* Start a drag-action when timer expires */
|
||||||
|
Item_Container_Drag_Info *st = data;
|
||||||
|
st->tm = NULL;
|
||||||
|
Elm_Drag_User_Info *info = &st->user_info;
|
||||||
|
if (info->dragstart) info->dragstart(info->startcbdata, st->obj);
|
||||||
|
elm_widget_scroll_freeze_push(st->obj);
|
||||||
|
evas_object_event_callback_del_full
|
||||||
|
(st->obj, EVAS_CALLBACK_MOUSE_MOVE, _cont_obj_mouse_move, st);
|
||||||
|
elm_drag_start( /* Commit the start only if data_get successful */
|
||||||
|
st->obj, info->format,
|
||||||
|
info->data, info->action,
|
||||||
|
info->createicon, info->createdata,
|
||||||
|
info->dragpos, info->dragdata,
|
||||||
|
info->acceptcb, info->acceptdata,
|
||||||
|
_cont_drag_done_cb, st);
|
||||||
|
ELM_SAFE_FREE(info->data, free);
|
||||||
|
|
||||||
|
return ECORE_CALLBACK_CANCEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Eina_List *
|
||||||
|
_anim_icons_make(Eina_List *icons)
|
||||||
|
{ /* Make local copies of all icons, add them to list */
|
||||||
|
Eina_List *list = NULL, *itr;
|
||||||
|
Evas_Object *o;
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(icons, itr, o)
|
||||||
|
{ /* Now add icons to animation window */
|
||||||
|
Anim_Icon *st = calloc(1, sizeof(*st));
|
||||||
|
|
||||||
|
if (!st)
|
||||||
|
{
|
||||||
|
ERR("Failed to allocate memory for icon!");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
evas_object_geometry_get(o, &st->start_x, &st->start_y, &st->start_w, &st->start_h);
|
||||||
|
evas_object_show(o);
|
||||||
|
st->o = o;
|
||||||
|
list = eina_list_append(list, st);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_drag_anim_play(void *data, double pos)
|
||||||
|
{ /* Impl of the animation of icons, called on frame time */
|
||||||
|
Item_Container_Drag_Info *st = data;
|
||||||
|
Eina_List *l;
|
||||||
|
Anim_Icon *sti;
|
||||||
|
|
||||||
|
if (st->ea)
|
||||||
|
{
|
||||||
|
if (pos > 0.99)
|
||||||
|
{
|
||||||
|
st->ea = NULL; /* Avoid deleting on mouse up */
|
||||||
|
EINA_LIST_FOREACH(st->icons, l, sti)
|
||||||
|
evas_object_hide(sti->o);
|
||||||
|
|
||||||
|
_cont_obj_drag_start(st); /* Start dragging */
|
||||||
|
return ECORE_CALLBACK_CANCEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Evas_Coord xm, ym;
|
||||||
|
evas_pointer_canvas_xy_get(st->e, &xm, &ym);
|
||||||
|
EINA_LIST_FOREACH(st->icons, l, sti)
|
||||||
|
{
|
||||||
|
int x, y, h, w;
|
||||||
|
w = sti->start_w + ((st->final_icon_w - sti->start_w) * pos);
|
||||||
|
h = sti->start_h + ((st->final_icon_h - sti->start_h) * pos);
|
||||||
|
x = sti->start_x - (pos * ((sti->start_x + (w/2) - xm)));
|
||||||
|
y = sti->start_y - (pos * ((sti->start_y + (h/2) - ym)));
|
||||||
|
evas_object_move(sti->o, x, y);
|
||||||
|
evas_object_resize(sti->o, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ECORE_CALLBACK_RENEW;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ECORE_CALLBACK_CANCEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Eina_Bool
|
||||||
|
_drag_anim_start(void *data)
|
||||||
|
{ /* Start default animation */
|
||||||
|
Item_Container_Drag_Info *st = data;
|
||||||
|
|
||||||
|
st->tm = NULL;
|
||||||
|
/* Now we need to build an (Anim_Icon *) list */
|
||||||
|
st->icons = _anim_icons_make(st->user_info.icons);
|
||||||
|
if (st->user_info.createicon)
|
||||||
|
{
|
||||||
|
Evas_Object *temp_win = elm_win_add(NULL, "Temp", ELM_WIN_DND);
|
||||||
|
Evas_Object *final_icon = st->user_info.createicon(st->user_info.createdata, temp_win, NULL, NULL);
|
||||||
|
evas_object_geometry_get(final_icon, NULL, NULL, &st->final_icon_w, &st->final_icon_h);
|
||||||
|
evas_object_del(final_icon);
|
||||||
|
evas_object_del(temp_win);
|
||||||
|
}
|
||||||
|
st->ea = ecore_animator_timeline_add(st->anim_tm, _drag_anim_play, st);
|
||||||
|
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_cont_obj_anim_start(void *data)
|
||||||
|
{ /* Start a drag-action when timer expires */
|
||||||
|
Item_Container_Drag_Info *st = data;
|
||||||
|
int xposret, yposret; /* Unused */
|
||||||
|
Elm_Object_Item *it = (st->itemgetcb) ?
|
||||||
|
(st->itemgetcb(st->obj, st->x_down, st->y_down, &xposret, &yposret))
|
||||||
|
: NULL;
|
||||||
|
|
||||||
|
st->tm = NULL;
|
||||||
|
st->user_info.format = ELM_SEL_FORMAT_TARGETS; /* Default */
|
||||||
|
st->icons = NULL;
|
||||||
|
st->user_info.data = NULL;
|
||||||
|
st->user_info.action = ELM_XDND_ACTION_COPY; /* Default */
|
||||||
|
|
||||||
|
if (!it) /* Failed to get mouse-down item, abort drag */
|
||||||
|
return ECORE_CALLBACK_CANCEL;
|
||||||
|
|
||||||
|
if (st->data_get)
|
||||||
|
{ /* collect info then start animation or start dragging */
|
||||||
|
if (st->data_get( /* Collect drag info */
|
||||||
|
st->obj, /* The container object */
|
||||||
|
it, /* Drag started on this item */
|
||||||
|
&st->user_info))
|
||||||
|
{
|
||||||
|
if (st->user_info.icons)
|
||||||
|
_drag_anim_start(st);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (st->anim_tm)
|
||||||
|
{
|
||||||
|
// even if we don't manage the icons animation, we have
|
||||||
|
// to wait until it is finished before beginning drag.
|
||||||
|
st->tm = ecore_timer_add(st->anim_tm, _cont_obj_drag_start, st);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_cont_obj_drag_start(st); /* Start dragging, no anim */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ECORE_CALLBACK_CANCEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_drag_item_container_cmp(const void *d1,
|
||||||
|
const void *d2)
|
||||||
|
{
|
||||||
|
const Item_Container_Drag_Info *st = d1;
|
||||||
|
return (((uintptr_t) (st->obj)) - ((uintptr_t) d2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_anim_st_free(Item_Container_Drag_Info *st)
|
||||||
|
{ /* Stops and free mem of ongoing animation */
|
||||||
|
if (st)
|
||||||
|
{
|
||||||
|
ELM_SAFE_FREE(st->ea, ecore_animator_del);
|
||||||
|
Anim_Icon *sti;
|
||||||
|
|
||||||
|
EINA_LIST_FREE(st->icons, sti)
|
||||||
|
{
|
||||||
|
evas_object_del(sti->o);
|
||||||
|
free(sti);
|
||||||
|
}
|
||||||
|
|
||||||
|
st->icons = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cont_obj_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
|
||||||
|
{ /* Cancel any drag waiting to start on timeout */
|
||||||
|
Item_Container_Drag_Info *st = data;
|
||||||
|
|
||||||
|
if (((Evas_Event_Mouse_Up *)event_info)->button != 1)
|
||||||
|
return; /* We only process left-click at the moment */
|
||||||
|
|
||||||
|
evas_object_event_callback_del_full
|
||||||
|
(st->obj, EVAS_CALLBACK_MOUSE_MOVE, _cont_obj_mouse_move, st);
|
||||||
|
evas_object_event_callback_del_full
|
||||||
|
(st->obj, EVAS_CALLBACK_MOUSE_UP, _cont_obj_mouse_up, st);
|
||||||
|
|
||||||
|
ELM_SAFE_FREE(st->tm, ecore_timer_del);
|
||||||
|
|
||||||
|
_anim_st_free(st);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cont_obj_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
|
||||||
|
{ /* Cancel any drag waiting to start on timeout */
|
||||||
|
if (((Evas_Event_Mouse_Move *)event_info)->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
|
||||||
|
{
|
||||||
|
Item_Container_Drag_Info *st = data;
|
||||||
|
|
||||||
|
evas_object_event_callback_del_full
|
||||||
|
(st->obj, EVAS_CALLBACK_MOUSE_MOVE, _cont_obj_mouse_move, st);
|
||||||
|
evas_object_event_callback_del_full
|
||||||
|
(st->obj, EVAS_CALLBACK_MOUSE_UP, _cont_obj_mouse_up, st);
|
||||||
|
elm_drag_item_container_del_internal(obj, EINA_FALSE);
|
||||||
|
|
||||||
|
ELM_SAFE_FREE(st->tm, ecore_timer_del);
|
||||||
|
|
||||||
|
_anim_st_free(st);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
elm_drag_item_container_del_internal(Evas_Object *obj, Eina_Bool full)
|
||||||
|
{
|
||||||
|
Item_Container_Drag_Info *st =
|
||||||
|
eina_list_search_unsorted(cont_drag_tg, _drag_item_container_cmp, obj);
|
||||||
|
|
||||||
|
if (st)
|
||||||
|
{
|
||||||
|
ELM_SAFE_FREE(st->tm, ecore_timer_del); /* Cancel drag-start timer */
|
||||||
|
|
||||||
|
if (st->ea) /* Cancel ongoing default animation */
|
||||||
|
_anim_st_free(st);
|
||||||
|
|
||||||
|
if (full)
|
||||||
|
{
|
||||||
|
st->itemgetcb = NULL;
|
||||||
|
st->data_get = NULL;
|
||||||
|
evas_object_event_callback_del_full
|
||||||
|
(obj, EVAS_CALLBACK_MOUSE_DOWN, _cont_obj_mouse_down, st);
|
||||||
|
|
||||||
|
cont_drag_tg = eina_list_remove(cont_drag_tg, st);
|
||||||
|
ELM_SAFE_FREE(st->user_info.data, free);
|
||||||
|
free(st);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cont_obj_mouse_down(void *data, Evas *e, Evas_Object *obj EINA_UNUSED, void *event_info)
|
||||||
|
{ /* Launch a timer to start dragging */
|
||||||
|
Evas_Event_Mouse_Down *ev = event_info;
|
||||||
|
if (ev->button != 1)
|
||||||
|
return; /* We only process left-click at the moment */
|
||||||
|
|
||||||
|
Item_Container_Drag_Info *st = data;
|
||||||
|
evas_object_event_callback_add(st->obj, EVAS_CALLBACK_MOUSE_MOVE,
|
||||||
|
_cont_obj_mouse_move, st);
|
||||||
|
|
||||||
|
evas_object_event_callback_add(st->obj, EVAS_CALLBACK_MOUSE_UP,
|
||||||
|
_cont_obj_mouse_up, st);
|
||||||
|
|
||||||
|
ecore_timer_del(st->tm);
|
||||||
|
|
||||||
|
st->e = e;
|
||||||
|
st->x_down = ev->canvas.x;
|
||||||
|
st->y_down = ev->canvas.y;
|
||||||
|
st->tm = ecore_timer_add(st->tm_to_drag, _cont_obj_anim_start, st);
|
||||||
|
}
|
||||||
|
EAPI Eina_Bool
|
||||||
|
elm_drag_item_container_del(Evas_Object *obj)
|
||||||
|
{
|
||||||
|
return elm_drag_item_container_del_internal(obj, EINA_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
elm_drag_item_container_add(Evas_Object *obj,
|
||||||
|
double anim_tm,
|
||||||
|
double tm_to_drag,
|
||||||
|
Elm_Xy_Item_Get_Cb itemgetcb,
|
||||||
|
Elm_Item_Container_Data_Get_Cb data_get)
|
||||||
|
{
|
||||||
|
Item_Container_Drag_Info *st;
|
||||||
|
|
||||||
|
if (elm_drag_item_container_del_internal(obj, EINA_FALSE))
|
||||||
|
{ /* Updating info of existing obj */
|
||||||
|
st = eina_list_search_unsorted(cont_drag_tg, _drag_item_container_cmp, obj);
|
||||||
|
if (!st) return EINA_FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
st = calloc(1, sizeof(*st));
|
||||||
|
if (!st) return EINA_FALSE;
|
||||||
|
|
||||||
|
st->obj = obj;
|
||||||
|
cont_drag_tg = eina_list_append(cont_drag_tg, st);
|
||||||
|
|
||||||
|
/* Register for mouse callback for container to start/abort drag */
|
||||||
|
evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
|
||||||
|
_cont_obj_mouse_down, st);
|
||||||
|
}
|
||||||
|
|
||||||
|
st->tm = NULL;
|
||||||
|
st->anim_tm = anim_tm;
|
||||||
|
st->tm_to_drag = tm_to_drag;
|
||||||
|
st->itemgetcb = itemgetcb;
|
||||||
|
st->data_get = data_get;
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_List *cont_drop_tg = NULL; /* List of Item_Container_Drop_Info */
|
||||||
|
|
||||||
|
struct _Item_Container_Drop_Info
|
||||||
|
{ /* Info kept for containers to support drop */
|
||||||
|
Evas_Object *obj;
|
||||||
|
Elm_Xy_Item_Get_Cb itemgetcb;
|
||||||
|
Elm_Drop_Item_Container_Cb dropcb;
|
||||||
|
Elm_Drag_Item_Container_Pos poscb;
|
||||||
|
};
|
||||||
|
typedef struct _Item_Container_Drop_Info Item_Container_Drop_Info;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Evas_Object *obj;
|
||||||
|
/* FIXME: Cache window */
|
||||||
|
Eina_Inlist *cbs_list; /* List of Dropable_Cbs * */
|
||||||
|
struct {
|
||||||
|
Evas_Coord x, y;
|
||||||
|
Eina_Bool in : 1;
|
||||||
|
const char *type;
|
||||||
|
Elm_Sel_Format format;
|
||||||
|
} last;
|
||||||
|
} Dropable;
|
||||||
|
|
||||||
|
static int
|
||||||
|
_drop_item_container_cmp(const void *d1,
|
||||||
|
const void *d2)
|
||||||
|
{
|
||||||
|
const Item_Container_Drop_Info *st = d1;
|
||||||
|
return (((uintptr_t) (st->obj)) - ((uintptr_t) d2));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_elm_item_container_pos_cb(void *data, Evas_Object *obj, Evas_Coord x, Evas_Coord y, Elm_Xdnd_Action action)
|
||||||
|
{ /* obj is the container pointer */
|
||||||
|
Elm_Object_Item *it = NULL;
|
||||||
|
int xposret = 0;
|
||||||
|
int yposret = 0;
|
||||||
|
|
||||||
|
Item_Container_Drop_Info *st =
|
||||||
|
eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj);
|
||||||
|
|
||||||
|
if (st && st->poscb)
|
||||||
|
{ /* Call container drop func with specific item pointer */
|
||||||
|
int xo = 0;
|
||||||
|
int yo = 0;
|
||||||
|
|
||||||
|
evas_object_geometry_get(obj, &xo, &yo, NULL, NULL);
|
||||||
|
if (st->itemgetcb)
|
||||||
|
it = st->itemgetcb(obj, x+xo, y+yo, &xposret, &yposret);
|
||||||
|
|
||||||
|
st->poscb(data, obj, it, x, y, xposret, yposret, action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_elm_item_container_drop_cb(void *data, Evas_Object *obj , Elm_Selection_Data *ev)
|
||||||
|
{ /* obj is the container pointer */
|
||||||
|
Elm_Object_Item *it = NULL;
|
||||||
|
int xposret = 0;
|
||||||
|
int yposret = 0;
|
||||||
|
|
||||||
|
Item_Container_Drop_Info *st =
|
||||||
|
eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj);
|
||||||
|
|
||||||
|
if (st && st->dropcb)
|
||||||
|
{ /* Call container drop func with specific item pointer */
|
||||||
|
int xo = 0;
|
||||||
|
int yo = 0;
|
||||||
|
|
||||||
|
evas_object_geometry_get(obj, &xo, &yo, NULL, NULL);
|
||||||
|
if (st->itemgetcb)
|
||||||
|
it = st->itemgetcb(obj, ev->x+xo, ev->y+yo, &xposret, &yposret);
|
||||||
|
|
||||||
|
return st->dropcb(data, obj, it, ev, xposret, yposret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
elm_drop_item_container_del_internal(Evas_Object *obj, Eina_Bool full)
|
||||||
|
{
|
||||||
|
Item_Container_Drop_Info *st =
|
||||||
|
eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj);
|
||||||
|
|
||||||
|
if (st)
|
||||||
|
{
|
||||||
|
// temp until st is stored inside data of obj.
|
||||||
|
//FIXME delete this drop container
|
||||||
|
st->itemgetcb= NULL;
|
||||||
|
st->poscb = NULL;
|
||||||
|
st->dropcb = NULL;
|
||||||
|
|
||||||
|
if (full)
|
||||||
|
{
|
||||||
|
cont_drop_tg = eina_list_remove(cont_drop_tg, st);
|
||||||
|
free(st);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
elm_drop_item_container_add(Evas_Object *obj,
|
||||||
|
Elm_Sel_Format format,
|
||||||
|
Elm_Xy_Item_Get_Cb itemgetcb,
|
||||||
|
Elm_Drag_State entercb, void *enterdata,
|
||||||
|
Elm_Drag_State leavecb, void *leavedata,
|
||||||
|
Elm_Drag_Item_Container_Pos poscb, void *posdata,
|
||||||
|
Elm_Drop_Item_Container_Cb dropcb, void *dropdata)
|
||||||
|
{
|
||||||
|
Item_Container_Drop_Info *st;
|
||||||
|
|
||||||
|
if (elm_drop_item_container_del_internal(obj, EINA_FALSE))
|
||||||
|
{ /* Updating info of existing obj */
|
||||||
|
st = eina_list_search_unsorted(cont_drop_tg, _drop_item_container_cmp, obj);
|
||||||
|
if (!st) return EINA_FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
st = calloc(1, sizeof(*st));
|
||||||
|
if (!st) return EINA_FALSE;
|
||||||
|
|
||||||
|
st->obj = obj;
|
||||||
|
cont_drop_tg = eina_list_append(cont_drop_tg, st);
|
||||||
|
}
|
||||||
|
|
||||||
|
st->itemgetcb = itemgetcb;
|
||||||
|
st->poscb = poscb;
|
||||||
|
st->dropcb = dropcb;
|
||||||
|
elm_drop_target_add(obj, format,
|
||||||
|
entercb, enterdata,
|
||||||
|
leavecb, leavedata,
|
||||||
|
_elm_item_container_pos_cb, posdata,
|
||||||
|
_elm_item_container_drop_cb, dropdata);
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
elm_drop_item_container_del(Evas_Object *obj)
|
||||||
|
{
|
||||||
|
return elm_drop_item_container_del_internal(obj, EINA_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *dragdata, *acceptdata, *donecbdata;
|
||||||
|
Elm_Drag_Pos dragposcb;
|
||||||
|
Elm_Drag_Accept acceptcb;
|
||||||
|
Elm_Drag_State dragdonecb;
|
||||||
|
} Elm_Drag_Data;
|
||||||
|
|
||||||
|
static void
|
||||||
|
_drag_finished_cb(void *data, const Efl_Event *ev)
|
||||||
|
{
|
||||||
|
Elm_Drag_Data *dd = data;
|
||||||
|
Eina_Bool *accepted = ev->info;
|
||||||
|
|
||||||
|
if (dd->acceptcb)
|
||||||
|
dd->acceptcb(dd->acceptdata, ev->object, *accepted);
|
||||||
|
|
||||||
|
if (dd->dragdonecb)
|
||||||
|
dd->dragdonecb(dd->donecbdata, ev->object);
|
||||||
|
|
||||||
|
efl_event_callback_del(ev->object, EFL_UI_DND_EVENT_DRAG_FINISHED, _drag_finished_cb, dd);
|
||||||
|
free(dd);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
elm_drag_start(Evas_Object *obj, Elm_Sel_Format format,
|
||||||
|
const char *data, Elm_Xdnd_Action action,
|
||||||
|
Elm_Drag_Icon_Create_Cb createicon,
|
||||||
|
void *createdata,
|
||||||
|
Elm_Drag_Pos dragpos, void *dragdata,
|
||||||
|
Elm_Drag_Accept acceptcb, void *acceptdata,
|
||||||
|
Elm_Drag_State dragdone, void *donecbdata)
|
||||||
|
{
|
||||||
|
Eina_Array *mime_types;
|
||||||
|
Eina_Content *content;
|
||||||
|
Efl_Content *ui;
|
||||||
|
int x, y, w, h;
|
||||||
|
Efl_Ui_Widget *widget;
|
||||||
|
Elm_Drag_Data *dd;
|
||||||
|
const char *str_action;
|
||||||
|
|
||||||
|
str_action = _action_to_string(action);
|
||||||
|
dd = calloc(1, sizeof(Elm_Drag_Data));
|
||||||
|
dd->dragposcb = dragpos;
|
||||||
|
dd->dragdata = dragdata;
|
||||||
|
dd->acceptcb = acceptcb;
|
||||||
|
dd->acceptdata = acceptdata;
|
||||||
|
dd->dragdonecb = dragdone;
|
||||||
|
dd->donecbdata = donecbdata;
|
||||||
|
mime_types = _format_to_mime_array(format);
|
||||||
|
if (eina_array_count(mime_types) != 1)
|
||||||
|
{
|
||||||
|
WRN("You passed more than one format, this is not going to work well");
|
||||||
|
}
|
||||||
|
content = eina_content_new((Eina_Slice) EINA_SLICE_STR_FULL(data), eina_array_data_get(mime_types, 0));
|
||||||
|
ui = efl_ui_dnd_drag_start(obj, content, str_action, _default_seat(obj));
|
||||||
|
widget = createicon(createdata, ui, &x, &y);
|
||||||
|
evas_object_geometry_get(widget, NULL, NULL, &w, &h);
|
||||||
|
evas_object_show(widget);
|
||||||
|
efl_content_set(ui, widget);
|
||||||
|
efl_gfx_entity_size_set(ui, EINA_SIZE2D(w, h));
|
||||||
|
eina_array_free(mime_types);
|
||||||
|
|
||||||
|
efl_event_callback_add(obj, EFL_UI_DND_EVENT_DRAG_FINISHED, _drag_finished_cb, dd);
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
elm_drag_cancel(Evas_Object *obj)
|
||||||
|
{
|
||||||
|
efl_ui_dnd_drag_cancel(obj, _default_seat(obj));
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Eina_Bool
|
||||||
|
elm_drag_action_set(Evas_Object *obj EINA_UNUSED, Elm_Xdnd_Action action EINA_UNUSED)
|
||||||
|
{
|
||||||
|
ERR("This operation is not supported anymore.");
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
|
@ -708,7 +708,7 @@ _selection_data_cb(void *data EINA_UNUSED,
|
||||||
char *entry_tag;
|
char *entry_tag;
|
||||||
int len;
|
int len;
|
||||||
static const char *tag_string =
|
static const char *tag_string =
|
||||||
"<item absize=240x180 href=file://%s></item>";
|
"<item absize=240x180 href=%s></item>";
|
||||||
|
|
||||||
len = strlen(tag_string) + strlen(buf);
|
len = strlen(tag_string) + strlen(buf);
|
||||||
entry_tag = alloca(len + 1);
|
entry_tag = alloca(len + 1);
|
||||||
|
@ -1628,7 +1628,7 @@ _selection_store(Elm_Sel_Type seltype,
|
||||||
if ((!sel) || (!sel[0])) return; /* avoid deleting our own selection */
|
if ((!sel) || (!sel[0])) return; /* avoid deleting our own selection */
|
||||||
|
|
||||||
elm_cnp_selection_set
|
elm_cnp_selection_set
|
||||||
(obj, seltype, ELM_SEL_FORMAT_MARKUP, sel, strlen(sel));
|
(obj, seltype, ELM_SEL_FORMAT_MARKUP, sel, strlen(sel) + 1);
|
||||||
elm_cnp_selection_loss_callback_set(obj, seltype, _selection_clear, obj);
|
elm_cnp_selection_loss_callback_set(obj, seltype, _selection_clear, obj);
|
||||||
if (seltype == ELM_SEL_TYPE_CLIPBOARD)
|
if (seltype == ELM_SEL_TYPE_CLIPBOARD)
|
||||||
eina_stringshare_replace(&sd->cut_sel, sel);
|
eina_stringshare_replace(&sd->cut_sel, sel);
|
||||||
|
@ -1731,7 +1731,7 @@ _menu_call(Evas_Object *obj)
|
||||||
const char *context_menu_orientation;
|
const char *context_menu_orientation;
|
||||||
Eina_Bool ownersel;
|
Eina_Bool ownersel;
|
||||||
|
|
||||||
ownersel = elm_selection_selection_has_owner(obj);
|
ownersel = elm_cnp_clipboard_selection_has_owner(obj);
|
||||||
if (!sd->items)
|
if (!sd->items)
|
||||||
{
|
{
|
||||||
/* prevent stupid blank hoversel */
|
/* prevent stupid blank hoversel */
|
||||||
|
|
|
@ -216,6 +216,6 @@ static const Efl_Class_Description _elm_label_class_desc = {
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
EFL_DEFINE_CLASS(elm_label_class_get, &_elm_label_class_desc, EFL_UI_LAYOUT_BASE_CLASS, ELM_LAYOUT_MIXIN, EFL_UI_LEGACY_INTERFACE, NULL);
|
EFL_DEFINE_CLASS(elm_label_class_get, &_elm_label_class_desc, EFL_UI_LAYOUT_BASE_CLASS, ELM_LAYOUT_MIXIN, EFL_UI_LEGACY_INTERFACE, EFL_ACCESS_WIDGET_ACTION_MIXIN, NULL);
|
||||||
|
|
||||||
#include "elm_label_eo.legacy.c"
|
#include "elm_label_eo.legacy.c"
|
||||||
|
|
|
@ -910,7 +910,6 @@ elm_quicklaunch_sub_shutdown(void)
|
||||||
_elm_module_shutdown();
|
_elm_module_shutdown();
|
||||||
if (_elm_prefs_initted)
|
if (_elm_prefs_initted)
|
||||||
_elm_prefs_shutdown();
|
_elm_prefs_shutdown();
|
||||||
_efl_ui_dnd_shutdown();
|
|
||||||
elm_color_class_shutdown();
|
elm_color_class_shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -165,7 +165,6 @@
|
||||||
|
|
||||||
# include "efl_ui_focus_parent_provider.eo.h"
|
# include "efl_ui_focus_parent_provider.eo.h"
|
||||||
# include "efl_ui_focus_parent_provider_standard.eo.h"
|
# include "efl_ui_focus_parent_provider_standard.eo.h"
|
||||||
# include "efl_ui_selection_manager.eo.h"
|
|
||||||
# include "efl_datetime_manager.eo.h"
|
# include "efl_datetime_manager.eo.h"
|
||||||
|
|
||||||
extern const char *_efl_model_property_itemw;
|
extern const char *_efl_model_property_itemw;
|
||||||
|
@ -668,9 +667,6 @@ void _elm_prefs_data_init(void);
|
||||||
void _elm_prefs_data_shutdown(void);
|
void _elm_prefs_data_shutdown(void);
|
||||||
|
|
||||||
/* init functions for dnd and cnp */
|
/* init functions for dnd and cnp */
|
||||||
Eo* _efl_ui_selection_manager_get(Eo *obj);
|
|
||||||
void _efl_ui_dnd_shutdown(void);
|
|
||||||
|
|
||||||
int _elm_ews_wm_init(void);
|
int _elm_ews_wm_init(void);
|
||||||
void _elm_ews_wm_shutdown(void);
|
void _elm_ews_wm_shutdown(void);
|
||||||
void _elm_ews_wm_rescale(Elm_Theme *th,
|
void _elm_ews_wm_rescale(Elm_Theme *th,
|
||||||
|
@ -1060,4 +1056,10 @@ typedef struct
|
||||||
|
|
||||||
Efl_Ui_Shared_Win_Data* efl_ui_win_shared_data_get(Efl_Ui_Win *win);
|
Efl_Ui_Shared_Win_Data* efl_ui_win_shared_data_get(Efl_Ui_Win *win);
|
||||||
|
|
||||||
|
void _selection_changed_event_register(Eo *obj);
|
||||||
|
void _selection_changed_event_unregister(Eo *obj);
|
||||||
|
void _drop_event_register(Eo *obj);
|
||||||
|
void _drop_event_unregister(Eo *obj);
|
||||||
|
void _register_selection_changed(Efl_Ui_Selection *selection);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -142,7 +142,6 @@ pub_eo_files = [
|
||||||
'elm_code_widget.eo',
|
'elm_code_widget.eo',
|
||||||
'efl_ui_selection.eo',
|
'efl_ui_selection.eo',
|
||||||
'efl_ui_dnd.eo',
|
'efl_ui_dnd.eo',
|
||||||
'efl_ui_dnd_container.eo',
|
|
||||||
'efl_ui_focus_manager_window_root.eo',
|
'efl_ui_focus_manager_window_root.eo',
|
||||||
'efl_ui_spotlight_container.eo',
|
'efl_ui_spotlight_container.eo',
|
||||||
'efl_ui_spotlight_manager.eo',
|
'efl_ui_spotlight_manager.eo',
|
||||||
|
@ -210,8 +209,6 @@ endforeach
|
||||||
pub_eo_types_files = [
|
pub_eo_types_files = [
|
||||||
'elm_general.eot',
|
'elm_general.eot',
|
||||||
'efl_ui.eot',
|
'efl_ui.eot',
|
||||||
'efl_ui_selection_types.eot',
|
|
||||||
'efl_ui_dnd_types.eot'
|
|
||||||
]
|
]
|
||||||
|
|
||||||
foreach eo_file : pub_eo_types_files
|
foreach eo_file : pub_eo_types_files
|
||||||
|
@ -235,7 +232,6 @@ priv_eo_files = [
|
||||||
'efl_ui_focus_parent_provider.eo',
|
'efl_ui_focus_parent_provider.eo',
|
||||||
'efl_ui_focus_parent_provider_standard.eo',
|
'efl_ui_focus_parent_provider_standard.eo',
|
||||||
'efl_ui_state_model.eo',
|
'efl_ui_state_model.eo',
|
||||||
'efl_ui_selection_manager.eo',
|
|
||||||
'efl_datetime_manager.eo',
|
'efl_datetime_manager.eo',
|
||||||
'efl_ui_size_model.eo',
|
'efl_ui_size_model.eo',
|
||||||
'efl_ui_homogeneous_model.eo',
|
'efl_ui_homogeneous_model.eo',
|
||||||
|
@ -785,6 +781,8 @@ elementary_src = [
|
||||||
'elm_icon.c',
|
'elm_icon.c',
|
||||||
'efl_ui_image.c',
|
'efl_ui_image.c',
|
||||||
'elm_index.c',
|
'elm_index.c',
|
||||||
|
'elm_cnp.c',
|
||||||
|
'elm_dnd.c',
|
||||||
'efl_access_object.c',
|
'efl_access_object.c',
|
||||||
'efl_access_action.c',
|
'efl_access_action.c',
|
||||||
'efl_access_component.c',
|
'efl_access_component.c',
|
||||||
|
@ -907,7 +905,6 @@ elementary_src = [
|
||||||
'efl_ui_scroller.c',
|
'efl_ui_scroller.c',
|
||||||
'efl_ui_scroll_manager.c',
|
'efl_ui_scroll_manager.c',
|
||||||
'efl_ui_pan.c',
|
'efl_ui_pan.c',
|
||||||
'efl_ui_selection_manager.c',
|
|
||||||
'efl_ui_selection_manager_private.h',
|
'efl_ui_selection_manager_private.h',
|
||||||
'efl_ui_selection.c',
|
'efl_ui_selection.c',
|
||||||
'efl_datetime_manager.c',
|
'efl_datetime_manager.c',
|
||||||
|
@ -947,7 +944,7 @@ elementary_src = [
|
||||||
'efl_ui_collection_view.c',
|
'efl_ui_collection_view.c',
|
||||||
'efl_ui_pager.c',
|
'efl_ui_pager.c',
|
||||||
'efl_ui_stack.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]
|
elementary_deps = [emile, eo, efl, edje, ethumb, ethumb_client, emotion, ecore_imf, ecore_con, eldbus, efreet, efreet_mime, efreet_trash, eio, atspi, dl, intl]
|
||||||
|
|
|
@ -60,6 +60,17 @@ struct @extern Eina.Matrix3 {
|
||||||
zz: double; [[ZZ value.]]
|
zz: double; [[ZZ value.]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct @extern Eina.Content; [[
|
||||||
|
Container for any type of content.
|
||||||
|
|
||||||
|
Each @Eina.Content is made of an @Eina.Slice of memory and an IANA MIME type:
|
||||||
|
https://www.iana.org/assignments/media-types/media-types.xhtml
|
||||||
|
|
||||||
|
If the type is a text-style type, the last byte of the slice must be \0.
|
||||||
|
|
||||||
|
@since 1.24
|
||||||
|
]]
|
||||||
|
|
||||||
struct @extern Eina.Matrix4 {
|
struct @extern Eina.Matrix4 {
|
||||||
[[A bidimensional array of floating point values with 4 rows and 4 columns.
|
[[A bidimensional array of floating point values with 4 rows and 4 columns.
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,21 @@ _efl_gfx_image_load_error_to_evas_load_error(Eina_Error err)
|
||||||
return EVAS_LOAD_ERROR_GENERIC;
|
return EVAS_LOAD_ERROR_GENERIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Eina_Content*
|
||||||
|
_markup_to_utf8(Eina_Content *from, const char *to_type)
|
||||||
|
{
|
||||||
|
Eina_Slice slice = eina_content_data_get(from);
|
||||||
|
char *utf8 = evas_textblock_text_markup_to_utf8(NULL, slice.mem);
|
||||||
|
return eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(utf8), to_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Content*
|
||||||
|
_utf8_to_markup(Eina_Content *from, const char *to_type)
|
||||||
|
{
|
||||||
|
Eina_Slice slice = eina_content_data_get(from);
|
||||||
|
char *markup = evas_textblock_text_utf8_to_markup(NULL, slice.mem);
|
||||||
|
return eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(markup), to_type);
|
||||||
|
}
|
||||||
|
|
||||||
EAPI int
|
EAPI int
|
||||||
evas_init(void)
|
evas_init(void)
|
||||||
|
@ -179,6 +194,9 @@ evas_init(void)
|
||||||
|
|
||||||
_efl_gfx_image_load_error_init();
|
_efl_gfx_image_load_error_init();
|
||||||
|
|
||||||
|
eina_content_converter_conversion_register("application/x-elementary-markup", "text/plain;charset=utf-8", _markup_to_utf8);
|
||||||
|
eina_content_converter_conversion_register("text/plain;charset=utf-8", "application/x-elementary-markup", _utf8_to_markup);
|
||||||
|
|
||||||
return _evas_init_count;
|
return _evas_init_count;
|
||||||
|
|
||||||
shutdown_filter:
|
shutdown_filter:
|
||||||
|
|
|
@ -34,6 +34,11 @@ static Ecore_Event_Handler *ecore_evas_event_handlers[4];
|
||||||
static const char *_iface_name = "opengl_cocoa";
|
static const char *_iface_name = "opengl_cocoa";
|
||||||
static const int _iface_version = 1;
|
static const int _iface_version = 1;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Ecore_Evas_Selection_Callbacks clipboard;
|
||||||
|
Eina_Future *delivery;
|
||||||
|
} Ecore_Evas_Cocoa_Engine_Data;
|
||||||
|
|
||||||
static inline Ecore_Evas *
|
static inline Ecore_Evas *
|
||||||
_ecore_evas_cocoa_match(Ecore_Cocoa_Object *cocoa_win)
|
_ecore_evas_cocoa_match(Ecore_Cocoa_Object *cocoa_win)
|
||||||
{
|
{
|
||||||
|
@ -422,6 +427,125 @@ _ecore_evas_callback_delete_request_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func
|
||||||
ee->func.fn_delete_request = func;
|
ee->func.fn_delete_request = func;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Eina_Value
|
||||||
|
_delivery(void *data, const Eina_Value value EINA_UNUSED, const Eina_Future *dead_future EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Ecore_Evas *ee = data;
|
||||||
|
Ecore_Evas_Cocoa_Engine_Data *edata = ee->engine.data;
|
||||||
|
Eina_Rw_Slice slice;
|
||||||
|
const char *mime_type = NULL;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_GOTO(edata->delivery, end);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < eina_array_count(edata->clipboard.available_types); ++i)
|
||||||
|
{
|
||||||
|
mime_type = eina_array_data_get(edata->clipboard.available_types, i);
|
||||||
|
if (!strncmp("text/", mime_type, strlen("text/")))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (mime_type)
|
||||||
|
{
|
||||||
|
edata->clipboard.delivery(ee, 1, ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER, mime_type, &slice);
|
||||||
|
EINA_SAFETY_ON_FALSE_GOTO(ecore_cocoa_clipboard_set(slice.mem, slice.len, mime_type), end);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("No compatible mime type found");
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
return EINA_VALUE_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_cocoa_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)
|
||||||
|
{
|
||||||
|
if (selection != ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER)
|
||||||
|
return EINA_FALSE;
|
||||||
|
|
||||||
|
if (!delivery && !cancel)
|
||||||
|
{
|
||||||
|
ecore_cocoa_clipboard_clear();
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Ecore_Evas_Cocoa_Engine_Data *edata = ee->engine.data;
|
||||||
|
|
||||||
|
if (edata->clipboard.cancel)
|
||||||
|
{
|
||||||
|
edata->clipboard.cancel(ee, seat, selection);
|
||||||
|
eina_array_free(edata->clipboard.available_types);
|
||||||
|
}
|
||||||
|
|
||||||
|
edata->delivery = efl_loop_job(efl_main_loop_get());
|
||||||
|
eina_future_then(edata->delivery, _delivery, ee);
|
||||||
|
edata->clipboard.delivery = delivery;
|
||||||
|
edata->clipboard.cancel = cancel;
|
||||||
|
edata->clipboard.available_types = available_types;
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Future*
|
||||||
|
_ecore_evas_cocoa_selection_request(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection, Eina_Array *acceptable_type)
|
||||||
|
{
|
||||||
|
Eina_Future *future;
|
||||||
|
Eina_Promise *promise;
|
||||||
|
const char *mime_type;
|
||||||
|
|
||||||
|
if (selection != ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER)
|
||||||
|
return eina_future_rejected(efl_loop_future_scheduler_get(efl_main_loop_get()), ecore_evas_no_selection);
|
||||||
|
|
||||||
|
promise = efl_loop_promise_new(efl_main_loop_get());
|
||||||
|
future = eina_future_new(promise);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < eina_array_count(acceptable_type); ++i)
|
||||||
|
{
|
||||||
|
mime_type = eina_array_data_get(acceptable_type, i);
|
||||||
|
if (!strncmp("text/", mime_type, strlen("text/")))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!mime_type)
|
||||||
|
{
|
||||||
|
eina_promise_reject(promise, ecore_evas_no_matching_type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
void *data;
|
||||||
|
Eina_Content *content;
|
||||||
|
Eina_Rw_Slice slice;
|
||||||
|
|
||||||
|
data = ecore_cocoa_clipboard_get(&size, mime_type);
|
||||||
|
if (!strncmp(mime_type, "text", strlen("text")))
|
||||||
|
{
|
||||||
|
//ensure that we always have a \0 at the end, there is no assertion that \0 is included here.
|
||||||
|
slice.len = size + 1;
|
||||||
|
slice.mem = eina_memdup(data, size, EINA_TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
slice.len = size;
|
||||||
|
slice.mem = data;
|
||||||
|
}
|
||||||
|
content = eina_content_new(eina_rw_slice_slice_get(slice), mime_type);
|
||||||
|
if (!content) // construction can fail because of some validation reasons
|
||||||
|
eina_promise_reject(promise, ecore_evas_no_matching_type);
|
||||||
|
else
|
||||||
|
eina_promise_resolve(promise, eina_value_content_init(content));
|
||||||
|
}
|
||||||
|
return future;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_cocoa_selection_has_owner(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection EINA_UNUSED)
|
||||||
|
{
|
||||||
|
if (selection == ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER)
|
||||||
|
return ecore_cocoa_clipboard_exists();
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static Ecore_Evas_Engine_Func _ecore_cocoa_engine_func =
|
static Ecore_Evas_Engine_Func _ecore_cocoa_engine_func =
|
||||||
{
|
{
|
||||||
_ecore_evas_cocoa_free,
|
_ecore_evas_cocoa_free,
|
||||||
|
@ -508,6 +632,11 @@ static Ecore_Evas_Engine_Func _ecore_cocoa_engine_func =
|
||||||
NULL, //fn_pointer_device_xy_get
|
NULL, //fn_pointer_device_xy_get
|
||||||
NULL, //fn_prepare
|
NULL, //fn_prepare
|
||||||
NULL, //fn_last_tick_get
|
NULL, //fn_last_tick_get
|
||||||
|
_ecore_evas_cocoa_selection_claim, //fn_selection_claim
|
||||||
|
_ecore_evas_cocoa_selection_has_owner, //fn_selection_has_owner
|
||||||
|
_ecore_evas_cocoa_selection_request, //fn_selection_request
|
||||||
|
NULL, //fn_dnd_start
|
||||||
|
NULL, //fn_dnd_stop
|
||||||
};
|
};
|
||||||
|
|
||||||
static Ecore_Cocoa_Window *
|
static Ecore_Cocoa_Window *
|
||||||
|
@ -517,11 +646,11 @@ _ecore_evas_cocoa_window_get(const Ecore_Evas *ee)
|
||||||
return (Ecore_Cocoa_Window *)(ee->prop.window);
|
return (Ecore_Cocoa_Window *)(ee->prop.window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EAPI Ecore_Evas *
|
EAPI Ecore_Evas *
|
||||||
ecore_evas_cocoa_new_internal(Ecore_Cocoa_Window *parent EINA_UNUSED, int x, int y, int w, int h)
|
ecore_evas_cocoa_new_internal(Ecore_Cocoa_Window *parent EINA_UNUSED, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
Ecore_Evas *ee;
|
Ecore_Evas *ee;
|
||||||
|
Ecore_Evas_Cocoa_Engine_Data *edata;
|
||||||
Ecore_Evas_Interface_Cocoa *iface;
|
Ecore_Evas_Interface_Cocoa *iface;
|
||||||
|
|
||||||
if (!ecore_cocoa_init())
|
if (!ecore_cocoa_init())
|
||||||
|
@ -532,6 +661,10 @@ ecore_evas_cocoa_new_internal(Ecore_Cocoa_Window *parent EINA_UNUSED, int x, int
|
||||||
ee = calloc(1, sizeof(Ecore_Evas));
|
ee = calloc(1, sizeof(Ecore_Evas));
|
||||||
if (!ee)
|
if (!ee)
|
||||||
goto shutdown_ecore_cocoa;
|
goto shutdown_ecore_cocoa;
|
||||||
|
edata = calloc(1, sizeof(Ecore_Evas_Cocoa_Engine_Data));
|
||||||
|
if (!edata)
|
||||||
|
goto shutdown_ecore_cocoa_engine_data;
|
||||||
|
ee->engine.data = edata;
|
||||||
|
|
||||||
ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
|
ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
|
||||||
|
|
||||||
|
@ -606,6 +739,8 @@ ecore_evas_cocoa_new_internal(Ecore_Cocoa_Window *parent EINA_UNUSED, int x, int
|
||||||
free(ee->name);
|
free(ee->name);
|
||||||
//free_ee:
|
//free_ee:
|
||||||
_ecore_evas_cocoa_shutdown();
|
_ecore_evas_cocoa_shutdown();
|
||||||
|
free(edata);
|
||||||
|
shutdown_ecore_cocoa_engine_data:
|
||||||
free(ee);
|
free(ee);
|
||||||
shutdown_ecore_cocoa:
|
shutdown_ecore_cocoa:
|
||||||
ecore_cocoa_shutdown();
|
ecore_cocoa_shutdown();
|
||||||
|
|
|
@ -455,6 +455,9 @@ static Ecore_Evas_Engine_Func _ecore_sdl_engine_func =
|
||||||
NULL, //fn_pointer_device_xy_get
|
NULL, //fn_pointer_device_xy_get
|
||||||
NULL, //fn_prepare
|
NULL, //fn_prepare
|
||||||
NULL, //fn_last_tick_get
|
NULL, //fn_last_tick_get
|
||||||
|
NULL, //fn_selection_claim
|
||||||
|
NULL, //fn_selection_has_owner
|
||||||
|
NULL, //fn_selection_request
|
||||||
};
|
};
|
||||||
|
|
||||||
static Ecore_Evas*
|
static Ecore_Evas*
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "ecore_evas_wayland_private.h"
|
#include "ecore_evas_wayland_private.h"
|
||||||
#include <Evas_Engine_Wayland.h>
|
#include <Evas_Engine_Wayland.h>
|
||||||
|
#include "ecore_wl2_internal.h"
|
||||||
|
|
||||||
extern EAPI Eina_List *_evas_canvas_image_data_unset(Evas *eo_e);
|
extern EAPI Eina_List *_evas_canvas_image_data_unset(Evas *eo_e);
|
||||||
extern EAPI void _evas_canvas_image_data_regenerate(Eina_List *list);
|
extern EAPI void _evas_canvas_image_data_regenerate(Eina_List *list);
|
||||||
|
@ -32,6 +33,7 @@ static Eina_Array *_ecore_evas_wl_event_hdls;
|
||||||
|
|
||||||
static void _ecore_evas_wayland_resize(Ecore_Evas *ee, int location);
|
static void _ecore_evas_wayland_resize(Ecore_Evas *ee, int location);
|
||||||
static void _ecore_evas_wl_common_rotation_set(Ecore_Evas *ee, int rotation, int resize);
|
static void _ecore_evas_wl_common_rotation_set(Ecore_Evas *ee, int rotation, int resize);
|
||||||
|
static void _ecore_evas_wl_selection_init(Ecore_Evas *ee);
|
||||||
|
|
||||||
/* local functions */
|
/* local functions */
|
||||||
static void
|
static void
|
||||||
|
@ -1440,6 +1442,15 @@ _ecore_evas_wl_common_free(Ecore_Evas *ee)
|
||||||
if (wdata->frame) ecore_wl2_window_frame_callback_del(wdata->frame);
|
if (wdata->frame) ecore_wl2_window_frame_callback_del(wdata->frame);
|
||||||
wdata->frame = NULL;
|
wdata->frame = NULL;
|
||||||
ecore_event_handler_del(wdata->sync_handler);
|
ecore_event_handler_del(wdata->sync_handler);
|
||||||
|
ecore_event_handler_del(wdata->changed_handler);
|
||||||
|
ecore_event_handler_del(wdata->send_handler);
|
||||||
|
ecore_event_handler_del(wdata->offer_handler);
|
||||||
|
ecore_event_handler_del(wdata->dnd_leave_handler);
|
||||||
|
ecore_event_handler_del(wdata->dnd_enter_handler);
|
||||||
|
ecore_event_handler_del(wdata->dnd_motion_handler);
|
||||||
|
ecore_event_handler_del(wdata->dnd_drop_handler);
|
||||||
|
ecore_event_handler_del(wdata->dnd_end_handler);
|
||||||
|
|
||||||
if (wdata->win)
|
if (wdata->win)
|
||||||
{
|
{
|
||||||
ecore_wl2_window_close_callback_set(wdata->win, NULL, NULL);
|
ecore_wl2_window_close_callback_set(wdata->win, NULL, NULL);
|
||||||
|
@ -2389,6 +2400,457 @@ _ecore_wl2_devices_setup(Ecore_Evas *ee, Ecore_Wl2_Display *display)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_reeval_seat(unsigned int *seat, Ecore_Evas *ee)
|
||||||
|
{
|
||||||
|
if (*seat == 0)
|
||||||
|
*seat = evas_device_seat_id_get(evas_default_device_get(ee->evas, EFL_INPUT_DEVICE_TYPE_SEAT));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_clear_selection(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection)
|
||||||
|
{
|
||||||
|
Ecore_Evas_Engine_Wl_Data *edata = ee->engine.data;
|
||||||
|
Ecore_Evas_Selection_Callbacks *cbs = &edata->selection_data[selection].callbacks;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_FALSE_RETURN(cbs->cancel);
|
||||||
|
|
||||||
|
cbs->cancel(ee, seat, selection);
|
||||||
|
eina_array_free(cbs->available_types);
|
||||||
|
memset(cbs, 0, sizeof(Ecore_Evas_Selection_Callbacks));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_store_selection_cbs(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_Wl_Selection_Data *sdata;
|
||||||
|
Ecore_Evas_Engine_Wl_Data *edata;
|
||||||
|
Ecore_Evas_Selection_Callbacks *cbs;
|
||||||
|
|
||||||
|
edata = ee->engine.data;
|
||||||
|
sdata = &edata->selection_data[selection];
|
||||||
|
cbs = &sdata->callbacks;
|
||||||
|
|
||||||
|
if (cbs->cancel)
|
||||||
|
{
|
||||||
|
_clear_selection(ee, seat, selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
cbs->delivery = delivery;
|
||||||
|
cbs->cancel = cancel;
|
||||||
|
cbs->available_types = available_types;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Ecore_Wl2_Input*
|
||||||
|
_fetch_input(Ecore_Evas *ee, unsigned int seat)
|
||||||
|
{
|
||||||
|
Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data;
|
||||||
|
return ecore_wl2_display_input_find(ecore_wl2_window_display_get(wdata->win), seat);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_wl_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_Engine_Wl_Data *wdata = ee->engine.data;
|
||||||
|
Ecore_Evas_Wl_Selection_Data *data = &wdata->selection_data[selection];
|
||||||
|
char *tmp_array[eina_array_count(available_types) + 1];
|
||||||
|
|
||||||
|
if (selection == ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER)
|
||||||
|
{
|
||||||
|
_store_selection_cbs(ee, seat, selection, available_types, delivery, cancel);
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_reeval_seat(&seat, ee);
|
||||||
|
_store_selection_cbs(ee, seat, selection, available_types, delivery, cancel);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < eina_array_count(available_types); ++i)
|
||||||
|
{
|
||||||
|
tmp_array[i] = eina_array_data_get(available_types, i);
|
||||||
|
}
|
||||||
|
tmp_array[eina_array_count(available_types)] = NULL;
|
||||||
|
|
||||||
|
data->sent_serial = ecore_wl2_dnd_selection_set(_fetch_input(ee, seat), (const char**)tmp_array);
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Eina_Future*
|
||||||
|
_ecore_evas_wl_selection_request(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection, Eina_Array *acceptable_types)
|
||||||
|
{
|
||||||
|
Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data;
|
||||||
|
Ecore_Evas_Wl_Selection_Data *data = &wdata->selection_data[selection];
|
||||||
|
Ecore_Wl2_Input *input;
|
||||||
|
Ecore_Wl2_Offer *offer = NULL;
|
||||||
|
Eina_Future *future;
|
||||||
|
|
||||||
|
_reeval_seat(&seat, ee);
|
||||||
|
input = _fetch_input(ee, seat);
|
||||||
|
|
||||||
|
if (data->delivery)
|
||||||
|
{
|
||||||
|
eina_promise_reject(data->delivery, ecore_evas_request_replaced);
|
||||||
|
data->delivery = NULL;
|
||||||
|
}
|
||||||
|
data->delivery = efl_loop_promise_new(efl_main_loop_get());
|
||||||
|
future = eina_future_new(data->delivery);
|
||||||
|
|
||||||
|
if (selection == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER)
|
||||||
|
{
|
||||||
|
offer = data->offer = wdata->external_offer;
|
||||||
|
}
|
||||||
|
else if (selection == ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER)
|
||||||
|
{
|
||||||
|
offer = data->offer = ecore_wl2_dnd_selection_get(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!offer)
|
||||||
|
{
|
||||||
|
eina_promise_reject(data->delivery, ecore_evas_no_selection);
|
||||||
|
data->delivery = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Eina_Array *available_types = ecore_wl2_offer_mimes_get(offer);
|
||||||
|
char *selected_type = NULL;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < eina_array_count(available_types) && !selected_type; ++i)
|
||||||
|
{
|
||||||
|
char *available_type = eina_array_data_get(available_types, i);
|
||||||
|
for (unsigned int j = 0; j < eina_array_count(acceptable_types) && !selected_type; ++j)
|
||||||
|
{
|
||||||
|
char *acceptable_type = eina_array_data_get(acceptable_types, j);
|
||||||
|
if (eina_streq(acceptable_type, available_type))
|
||||||
|
{
|
||||||
|
selected_type = available_type;
|
||||||
|
data->later_convert = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *convert_available_type;
|
||||||
|
Eina_Iterator *convertions = eina_content_converter_possible_conversions(available_type);
|
||||||
|
EINA_ITERATOR_FOREACH(convertions, convert_available_type)
|
||||||
|
{
|
||||||
|
if (eina_streq(convert_available_type, acceptable_type))
|
||||||
|
{
|
||||||
|
selected_type = available_type;
|
||||||
|
data->later_convert = acceptable_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eina_iterator_free(convertions);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (selected_type)
|
||||||
|
{
|
||||||
|
ecore_wl2_offer_receive(offer, selected_type);
|
||||||
|
ecore_wl2_display_flush(ecore_wl2_input_display_get(input));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eina_promise_reject(data->delivery, ecore_evas_no_matching_type);
|
||||||
|
data->delivery = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return future;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_wl_selection_has_owner(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer selection EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data;
|
||||||
|
Ecore_Wl2_Input *input;
|
||||||
|
|
||||||
|
_reeval_seat(&seat, ee);
|
||||||
|
input = _fetch_input(ee, seat);
|
||||||
|
|
||||||
|
if (selection == ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER )
|
||||||
|
return !!ecore_wl2_dnd_selection_get(input);
|
||||||
|
else if (selection == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER)
|
||||||
|
{
|
||||||
|
Ecore_Evas_Wl_Selection_Data *data = &wdata->selection_data[selection];
|
||||||
|
return !!data->offer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINA_FALSE; //the selection buffer is not supportet in wayland
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_wl_selection_changed(void *data, int type EINA_UNUSED, void *event EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Ecore_Wl2_Event_Seat_Selection *sel = event;
|
||||||
|
Ecore_Evas *ee = data;
|
||||||
|
Ecore_Wl2_Input *input;
|
||||||
|
unsigned int seat = sel->seat;
|
||||||
|
|
||||||
|
_reeval_seat(&seat, ee);
|
||||||
|
input = _fetch_input(ee, seat);
|
||||||
|
if (!ecore_wl2_dnd_selection_get(input))
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
|
||||||
|
if (ee->func.fn_selection_changed)
|
||||||
|
ee->func.fn_selection_changed(ee, 0, ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER);
|
||||||
|
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Eina_Rw_Slice slice;
|
||||||
|
unsigned int written_bytes;
|
||||||
|
} Delayed_Writing;
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_write_to_fd(void *data, Ecore_Fd_Handler *fd_handler)
|
||||||
|
{
|
||||||
|
int fd = ecore_main_fd_handler_fd_get(fd_handler);
|
||||||
|
Delayed_Writing *slice = data;
|
||||||
|
|
||||||
|
size_t len = write(fd, slice->slice.mem + slice->written_bytes, slice->slice.len - slice->written_bytes);
|
||||||
|
|
||||||
|
slice->written_bytes += len;
|
||||||
|
if (slice->written_bytes != slice->slice.len)
|
||||||
|
{
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ecore_main_fd_handler_del(fd_handler);
|
||||||
|
free(slice->slice.mem);
|
||||||
|
free(slice);
|
||||||
|
close(fd);
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_wl_interaction_send(void *data, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_Wl2_Event_Data_Source_Send *ev = event;
|
||||||
|
Ecore_Evas *ee = data;
|
||||||
|
Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data;
|
||||||
|
Ecore_Evas_Wl_Selection_Data *selection = NULL;
|
||||||
|
Delayed_Writing *forign_slice = calloc(1, sizeof(Delayed_Writing));
|
||||||
|
Ecore_Evas_Selection_Buffer buffer = ECORE_EVAS_SELECTION_BUFFER_LAST;
|
||||||
|
|
||||||
|
if (ev->serial == wdata->selection_data[ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER].sent_serial)
|
||||||
|
buffer = ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER;
|
||||||
|
else if (ev->serial == wdata->selection_data[ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER].sent_serial)
|
||||||
|
{
|
||||||
|
buffer = ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER;
|
||||||
|
ee->drag.accepted = EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer == ECORE_EVAS_SELECTION_BUFFER_LAST)
|
||||||
|
{
|
||||||
|
//silent return, this send request was *not* for this window
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
selection = &wdata->selection_data[buffer];
|
||||||
|
EINA_SAFETY_ON_NULL_GOTO(selection, end);
|
||||||
|
EINA_SAFETY_ON_NULL_GOTO(selection->callbacks.delivery, end);
|
||||||
|
EINA_SAFETY_ON_FALSE_GOTO(selection->callbacks.delivery(ee, ev->seat, buffer, ev->type, &forign_slice->slice), end);
|
||||||
|
ecore_main_fd_handler_add(ev->fd, ECORE_FD_WRITE, _write_to_fd, forign_slice, NULL, NULL);
|
||||||
|
end:
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_wl_selection_receive(void *data, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_Evas *ee = data;
|
||||||
|
Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data;
|
||||||
|
Ecore_Wl2_Event_Offer_Data_Ready *ready = event;
|
||||||
|
Ecore_Evas_Selection_Buffer selection = ECORE_EVAS_SELECTION_BUFFER_LAST;
|
||||||
|
|
||||||
|
for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
|
||||||
|
{
|
||||||
|
if (wdata->selection_data[i].offer == ready->offer)
|
||||||
|
{
|
||||||
|
selection = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selection == ECORE_EVAS_SELECTION_BUFFER_LAST)
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
|
||||||
|
//Now deliver the content
|
||||||
|
Eina_Slice slice;
|
||||||
|
|
||||||
|
if (!strncmp(ready->mimetype, "text", strlen("text")))
|
||||||
|
{
|
||||||
|
//ensure that we always have a \0 at the end, there is no assertion that \0 is included here.
|
||||||
|
slice.len = ready->len + 1;
|
||||||
|
slice.mem = eina_memdup((unsigned char*)ready->data, ready->len, EINA_TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
slice.len = ready->len;
|
||||||
|
slice.mem = ready->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Content *content = eina_content_new(slice, ready->mimetype);
|
||||||
|
|
||||||
|
if (wdata->selection_data[selection].later_convert)
|
||||||
|
{
|
||||||
|
Eina_Content *tmp = eina_content_convert(content, wdata->selection_data[selection].later_convert);
|
||||||
|
wdata->selection_data[selection].later_convert = NULL;
|
||||||
|
eina_content_free(content);
|
||||||
|
content = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
eina_promise_resolve(wdata->selection_data[selection].delivery, eina_value_content_init(content));
|
||||||
|
wdata->selection_data[selection].delivery = NULL;
|
||||||
|
eina_content_free(content);
|
||||||
|
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_wl_selection_dnd_leave(void *data, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_Evas *ee = data;
|
||||||
|
Eina_Position2D cpos;
|
||||||
|
Eina_Position2D fpos = EINA_POSITION2D(0, 0);
|
||||||
|
Ecore_Wl2_Event_Dnd_Leave *ev = event;
|
||||||
|
Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data;
|
||||||
|
|
||||||
|
if (ee->prop.window != (Ecore_Window)ev->win) return ECORE_CALLBACK_PASS_ON;
|
||||||
|
|
||||||
|
//evas_output_framespace_get(ee->evas, &fpos.x, &fpos.y, NULL, NULL);
|
||||||
|
ecore_wl2_input_pointer_xy_get(ecore_wl2_display_input_find(ev->display, ev->seat), &cpos.x, &cpos.y);
|
||||||
|
ecore_evas_dnd_leave(data, ev->seat, EINA_POSITION2D(cpos.x - fpos.x, cpos.y - fpos.y));
|
||||||
|
wdata->external_offer = NULL;
|
||||||
|
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_wl_selection_dnd_motion(void *data, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_Evas *ee = data;
|
||||||
|
Ecore_Wl2_Event_Dnd_Motion *ev = event;
|
||||||
|
Eina_Position2D fpos = EINA_POSITION2D(0, 0);
|
||||||
|
|
||||||
|
if (ee->prop.window != (Ecore_Window)ev->win) return ECORE_CALLBACK_PASS_ON;
|
||||||
|
|
||||||
|
evas_output_framespace_get(ee->evas, &fpos.x, &fpos.y, NULL, NULL);
|
||||||
|
ecore_evas_dnd_position_set(data, ev->seat, EINA_POSITION2D(ev->x - fpos.x, ev->y - fpos.y));
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
}
|
||||||
|
static Eina_Bool
|
||||||
|
_wl_selection_dnd_enter(void *data, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_Evas *ee = data;
|
||||||
|
Ecore_Wl2_Event_Dnd_Enter *ev = event;
|
||||||
|
Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data;
|
||||||
|
Eina_Position2D fpos = EINA_POSITION2D(0, 0);
|
||||||
|
|
||||||
|
if (ee->prop.window != (Ecore_Window)ev->win) return ECORE_CALLBACK_PASS_ON;
|
||||||
|
|
||||||
|
evas_output_framespace_get(ee->evas, &fpos.x, &fpos.y, NULL, NULL);
|
||||||
|
ecore_evas_dnd_enter(data, ev->seat, eina_array_iterator_new(ecore_wl2_offer_mimes_get(ev->offer)), EINA_POSITION2D(ev->x - fpos.x, ev->y - fpos.y));
|
||||||
|
ecore_wl2_offer_mimes_set(ev->offer, ecore_wl2_offer_mimes_get(ev->offer));
|
||||||
|
wdata->external_offer = ev->offer;
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_wl_selection_dnd_drop(void *data, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_Evas *ee = data;
|
||||||
|
Ecore_Wl2_Event_Dnd_Drop *ev = event;
|
||||||
|
Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data;
|
||||||
|
if (ee->prop.window != (Ecore_Window)ev->win) return ECORE_CALLBACK_PASS_ON;
|
||||||
|
wdata = ee->engine.data;
|
||||||
|
|
||||||
|
if (ee->func.fn_dnd_drop)
|
||||||
|
ee->func.fn_dnd_drop(ee, ev->seat, ecore_evas_dnd_pos_get(ee, ev->seat), "ask");
|
||||||
|
|
||||||
|
ecore_wl2_dnd_drag_end(_fetch_input(ee, ev->seat));
|
||||||
|
wdata->external_offer = NULL;
|
||||||
|
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
}
|
||||||
|
static Eina_Bool
|
||||||
|
_wl_selection_dnd_end(void *data, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_Evas *ee = data;
|
||||||
|
Ecore_Wl2_Event_Dnd_End *ev = event;
|
||||||
|
|
||||||
|
if (ee->prop.window != (Ecore_Window)ev->win) return ECORE_CALLBACK_PASS_ON;
|
||||||
|
|
||||||
|
|
||||||
|
if (ee->drag.free)
|
||||||
|
ee->drag.free(ee, ev->seat, ee->drag.data, ee->drag.accepted);
|
||||||
|
ee->drag.free = NULL;
|
||||||
|
//we got dropped, we should call
|
||||||
|
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ecore_evas_wl_selection_init(Ecore_Evas *ee)
|
||||||
|
{
|
||||||
|
Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data;
|
||||||
|
|
||||||
|
wdata->changed_handler = ecore_event_handler_add(ECORE_WL2_EVENT_SEAT_SELECTION,
|
||||||
|
_wl_selection_changed, ee);
|
||||||
|
wdata->send_handler = ecore_event_handler_add(ECORE_WL2_EVENT_DATA_SOURCE_SEND,
|
||||||
|
_wl_interaction_send, ee);
|
||||||
|
wdata->offer_handler = ecore_event_handler_add(ECORE_WL2_EVENT_OFFER_DATA_READY,
|
||||||
|
_wl_selection_receive, ee);
|
||||||
|
wdata->dnd_leave_handler = ecore_event_handler_add(ECORE_WL2_EVENT_DND_LEAVE,
|
||||||
|
_wl_selection_dnd_leave, ee);
|
||||||
|
wdata->dnd_motion_handler = ecore_event_handler_add(ECORE_WL2_EVENT_DND_MOTION,
|
||||||
|
_wl_selection_dnd_motion, ee);
|
||||||
|
wdata->dnd_enter_handler = ecore_event_handler_add(ECORE_WL2_EVENT_DND_ENTER,
|
||||||
|
_wl_selection_dnd_enter, ee);
|
||||||
|
wdata->dnd_drop_handler = ecore_event_handler_add(ECORE_WL2_EVENT_DND_DROP,
|
||||||
|
_wl_selection_dnd_drop, ee);
|
||||||
|
wdata->dnd_end_handler = ecore_event_handler_add(ECORE_WL2_EVENT_DATA_SOURCE_DROP,
|
||||||
|
_wl_selection_dnd_end, ee);
|
||||||
|
for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
|
||||||
|
{
|
||||||
|
wdata->selection_data[i].callbacks.available_types = NULL;
|
||||||
|
wdata->selection_data[i].callbacks.delivery = NULL;
|
||||||
|
wdata->selection_data[i].callbacks.cancel = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_wl_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_UNUSED)
|
||||||
|
{
|
||||||
|
Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data;
|
||||||
|
const char *tmp_array[eina_array_count(available_types) + 1];
|
||||||
|
|
||||||
|
_reeval_seat(&seat, ee);
|
||||||
|
_store_selection_cbs(ee, seat, ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER, available_types, delivery, cancel);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < eina_array_count(available_types); ++i)
|
||||||
|
{
|
||||||
|
tmp_array[i] = eina_array_data_get(available_types, i);
|
||||||
|
}
|
||||||
|
tmp_array[eina_array_count(available_types)] = NULL;
|
||||||
|
|
||||||
|
ecore_wl2_dnd_drag_types_set(_fetch_input(ee, seat), (const char**)tmp_array);
|
||||||
|
wdata->selection_data[ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER].sent_serial =
|
||||||
|
ecore_wl2_dnd_drag_start(_fetch_input(ee, seat), _ecore_evas_wayland_window_get(ee), _ecore_evas_wayland_window_get(drag_rep));
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_wl_dnd_stop(Ecore_Evas *ee, unsigned int seat)
|
||||||
|
{
|
||||||
|
_clear_selection(ee, seat, ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER);
|
||||||
|
_reeval_seat(&seat, ee);
|
||||||
|
ecore_wl2_dnd_drag_end(_fetch_input(ee, seat));
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static Ecore_Evas_Engine_Func _ecore_wl_engine_func =
|
static Ecore_Evas_Engine_Func _ecore_wl_engine_func =
|
||||||
{
|
{
|
||||||
_ecore_evas_wl_common_free,
|
_ecore_evas_wl_common_free,
|
||||||
|
@ -2474,6 +2936,11 @@ static Ecore_Evas_Engine_Func _ecore_wl_engine_func =
|
||||||
_ecore_evas_wl_common_pointer_device_xy_get,
|
_ecore_evas_wl_common_pointer_device_xy_get,
|
||||||
_ecore_evas_wl_common_prepare,
|
_ecore_evas_wl_common_prepare,
|
||||||
NULL, //fn_last_tick_get
|
NULL, //fn_last_tick_get
|
||||||
|
_ecore_evas_wl_selection_claim, //fn_selection_claim
|
||||||
|
_ecore_evas_wl_selection_has_owner, //fn_selection_has_owner
|
||||||
|
_ecore_evas_wl_selection_request, //fn_selection_request
|
||||||
|
_ecore_evas_wl_dnd_start, //fn_dnd_start
|
||||||
|
_ecore_evas_wl_dnd_stop, //fn_dnd_stop
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2650,6 +3117,7 @@ _ecore_evas_wl_common_new_internal(const char *disp_name, Ecore_Window parent, i
|
||||||
}
|
}
|
||||||
|
|
||||||
_ecore_evas_wl_common_wm_rotation_protocol_set(ee);
|
_ecore_evas_wl_common_wm_rotation_protocol_set(ee);
|
||||||
|
_ecore_evas_wl_selection_init(ee);
|
||||||
|
|
||||||
ecore_evas_done(ee, EINA_FALSE);
|
ecore_evas_done(ee, EINA_FALSE);
|
||||||
|
|
||||||
|
|
|
@ -34,12 +34,23 @@
|
||||||
|
|
||||||
typedef struct _Ecore_Evas_Engine_Wl_Data Ecore_Evas_Engine_Wl_Data;
|
typedef struct _Ecore_Evas_Engine_Wl_Data Ecore_Evas_Engine_Wl_Data;
|
||||||
|
|
||||||
|
typedef struct _Ecore_Evas_Wl_Selection_Data Ecore_Evas_Wl_Selection_Data;
|
||||||
|
|
||||||
|
struct _Ecore_Evas_Wl_Selection_Data
|
||||||
|
{
|
||||||
|
Ecore_Evas_Selection_Callbacks callbacks;
|
||||||
|
Eina_Promise *delivery;
|
||||||
|
Ecore_Wl2_Offer *offer;
|
||||||
|
const char *later_convert;
|
||||||
|
uint32_t sent_serial; //The serial of the last sent selection op
|
||||||
|
};
|
||||||
|
|
||||||
struct _Ecore_Evas_Engine_Wl_Data
|
struct _Ecore_Evas_Engine_Wl_Data
|
||||||
{
|
{
|
||||||
Ecore_Wl2_Display *display;
|
Ecore_Wl2_Display *display;
|
||||||
Eina_List *regen_objs;
|
Eina_List *regen_objs;
|
||||||
Ecore_Wl2_Window *parent, *win;
|
Ecore_Wl2_Window *parent, *win;
|
||||||
Ecore_Event_Handler *sync_handler;
|
Ecore_Event_Handler *sync_handler, *changed_handler, *end_handler, *send_handler, *offer_handler, *dnd_leave_handler, *dnd_motion_handler, *dnd_enter_handler, *dnd_drop_handler, *dnd_end_handler;
|
||||||
int fx, fy, fw, fh;
|
int fx, fy, fw, fh;
|
||||||
Ecore_Wl2_Frame_Cb_Handle *frame;
|
Ecore_Wl2_Frame_Cb_Handle *frame;
|
||||||
int x_rel;
|
int x_rel;
|
||||||
|
@ -47,7 +58,8 @@ struct _Ecore_Evas_Engine_Wl_Data
|
||||||
uint32_t timestamp;
|
uint32_t timestamp;
|
||||||
Eina_List *devices_list;
|
Eina_List *devices_list;
|
||||||
int cw, ch;
|
int cw, ch;
|
||||||
|
Ecore_Evas_Wl_Selection_Data selection_data[ECORE_EVAS_SELECTION_BUFFER_LAST];
|
||||||
|
Ecore_Wl2_Offer *external_offer;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
Eina_Bool supported : 1;
|
Eina_Bool supported : 1;
|
||||||
|
|
|
@ -62,11 +62,15 @@ static const int interface_win32_version = 1;
|
||||||
|
|
||||||
typedef struct _Ecore_Evas_Engine_Data_Win32 Ecore_Evas_Engine_Data_Win32;
|
typedef struct _Ecore_Evas_Engine_Data_Win32 Ecore_Evas_Engine_Data_Win32;
|
||||||
|
|
||||||
struct _Ecore_Evas_Engine_Data_Win32 {
|
struct _Ecore_Evas_Engine_Data_Win32
|
||||||
|
{
|
||||||
Ecore_Win32_Window *parent;
|
Ecore_Win32_Window *parent;
|
||||||
struct {
|
Ecore_Evas_Selection_Callbacks clipboard;
|
||||||
unsigned char region : 1;
|
Eina_Future *delivery;
|
||||||
unsigned char fullscreen : 1;
|
struct
|
||||||
|
{
|
||||||
|
unsigned char region : 1;
|
||||||
|
unsigned char fullscreen : 1;
|
||||||
} state;
|
} state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1197,93 +1201,215 @@ _ecore_evas_win32_screen_dpi_get(const Ecore_Evas *ee, int *xdpi, int *ydpi)
|
||||||
*ydpi = y_dpi;
|
*ydpi = y_dpi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Eina_Value
|
||||||
|
_delivery(void *data, const Eina_Value value EINA_UNUSED, const Eina_Future *dead_future EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Ecore_Evas *ee = data;
|
||||||
|
Ecore_Evas_Engine_Data_Win32 *edata = ee->engine.data;
|
||||||
|
Eina_Rw_Slice slice;
|
||||||
|
const char *mime_type = NULL;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_GOTO(edata->delivery, end);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < eina_array_count(edata->clipboard.available_types); ++i)
|
||||||
|
{
|
||||||
|
mime_type = eina_array_data_get(edata->clipboard.available_types, i);
|
||||||
|
if (eina_str_has_prefix(mime_type, "text/"))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (mime_type)
|
||||||
|
{
|
||||||
|
edata->clipboard.delivery(ee, 0, ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER, mime_type, &slice);
|
||||||
|
EINA_SAFETY_ON_FALSE_GOTO(ecore_win32_clipboard_set((Ecore_Win32_Window *)ee->prop.window, slice.mem, slice.len, mime_type), end);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("No compatible mime type found");
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
return EINA_VALUE_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_win32_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)
|
||||||
|
{
|
||||||
|
if (selection != ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER)
|
||||||
|
return EINA_FALSE;
|
||||||
|
|
||||||
|
if (!delivery && !cancel)
|
||||||
|
{
|
||||||
|
ecore_win32_clipboard_clear((Ecore_Win32_Window *)ee->prop.window);
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Ecore_Evas_Engine_Data_Win32 *edata = ee->engine.data;
|
||||||
|
|
||||||
|
if (edata->clipboard.cancel)
|
||||||
|
{
|
||||||
|
edata->clipboard.cancel(ee, seat, selection);
|
||||||
|
eina_array_free(edata->clipboard.available_types);
|
||||||
|
}
|
||||||
|
|
||||||
|
edata->delivery = efl_loop_job(efl_main_loop_get());
|
||||||
|
eina_future_then(edata->delivery, _delivery, ee);
|
||||||
|
edata->clipboard.delivery = delivery;
|
||||||
|
edata->clipboard.cancel = cancel;
|
||||||
|
edata->clipboard.available_types = available_types;
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Future*
|
||||||
|
_ecore_evas_win32_selection_request(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection, Eina_Array *acceptable_type)
|
||||||
|
{
|
||||||
|
Eina_Future *future;
|
||||||
|
Eina_Promise *promise;
|
||||||
|
const char *mime_type = NULL;
|
||||||
|
|
||||||
|
if (selection != ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER)
|
||||||
|
return eina_future_rejected(efl_loop_future_scheduler_get(efl_main_loop_get()), ecore_evas_no_selection);
|
||||||
|
|
||||||
|
promise = efl_loop_promise_new(efl_main_loop_get());
|
||||||
|
future = eina_future_new(promise);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < eina_array_count(acceptable_type); ++i)
|
||||||
|
{
|
||||||
|
mime_type = eina_array_data_get(acceptable_type, i);
|
||||||
|
if (eina_str_has_prefix(mime_type, "text/"))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!mime_type)
|
||||||
|
{
|
||||||
|
eina_promise_reject(promise, ecore_evas_no_matching_type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
void *data;
|
||||||
|
Eina_Content *content;
|
||||||
|
Eina_Rw_Slice slice;
|
||||||
|
|
||||||
|
data = ecore_win32_clipboard_get((Ecore_Win32_Window *)ee->prop.window, &size, mime_type);
|
||||||
|
if (eina_str_has_prefix(mime_type, "text/"))
|
||||||
|
{
|
||||||
|
//ensure that we always have a \0 at the end, there is no assertion that \0 is included here.
|
||||||
|
slice.len = size + 1;
|
||||||
|
slice.mem = eina_memdup(data, size, EINA_TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
slice.len = size;
|
||||||
|
slice.mem = data;
|
||||||
|
}
|
||||||
|
content = eina_content_new(eina_rw_slice_slice_get(slice), mime_type);
|
||||||
|
if (!content) // construction can fail because of some validation reasons
|
||||||
|
eina_promise_reject(promise, ecore_evas_no_matching_type);
|
||||||
|
else
|
||||||
|
eina_promise_resolve(promise, eina_value_content_init(content));
|
||||||
|
}
|
||||||
|
return future;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_win32_selection_has_owner(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection)
|
||||||
|
{
|
||||||
|
return (selection == ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
static Ecore_Evas_Engine_Func _ecore_win32_engine_func =
|
static Ecore_Evas_Engine_Func _ecore_win32_engine_func =
|
||||||
{
|
{
|
||||||
_ecore_evas_win32_free,
|
_ecore_evas_win32_free,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
_ecore_evas_win32_callback_delete_request_set,
|
_ecore_evas_win32_callback_delete_request_set,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
_ecore_evas_win32_move,
|
_ecore_evas_win32_move,
|
||||||
NULL,
|
NULL,
|
||||||
_ecore_evas_win32_resize,
|
_ecore_evas_win32_resize,
|
||||||
_ecore_evas_win32_move_resize,
|
_ecore_evas_win32_move_resize,
|
||||||
_ecore_evas_win32_rotation_set,
|
_ecore_evas_win32_rotation_set,
|
||||||
_ecore_evas_win32_shaped_set,
|
_ecore_evas_win32_shaped_set,
|
||||||
_ecore_evas_win32_show,
|
_ecore_evas_win32_show,
|
||||||
_ecore_evas_win32_hide,
|
_ecore_evas_win32_hide,
|
||||||
_ecore_evas_win32_raise,
|
_ecore_evas_win32_raise,
|
||||||
_ecore_evas_win32_lower,
|
_ecore_evas_win32_lower,
|
||||||
_ecore_evas_win32_activate,
|
_ecore_evas_win32_activate,
|
||||||
_ecore_evas_win32_title_set,
|
_ecore_evas_win32_title_set,
|
||||||
NULL, /* _ecore_evas_x_name_class_set */
|
NULL, /* _ecore_evas_x_name_class_set */
|
||||||
_ecore_evas_win32_size_min_set,
|
_ecore_evas_win32_size_min_set,
|
||||||
_ecore_evas_win32_size_max_set,
|
_ecore_evas_win32_size_max_set,
|
||||||
_ecore_evas_win32_size_base_set,
|
_ecore_evas_win32_size_base_set,
|
||||||
_ecore_evas_win32_size_step_set,
|
_ecore_evas_win32_size_step_set,
|
||||||
_ecore_evas_win32_object_cursor_set,
|
_ecore_evas_win32_object_cursor_set,
|
||||||
_ecore_evas_win32_object_cursor_unset,
|
_ecore_evas_win32_object_cursor_unset,
|
||||||
NULL, /* _ecore_evas_x_layer_set */
|
NULL, /* _ecore_evas_x_layer_set */
|
||||||
_ecore_evas_win32_focus_set,
|
_ecore_evas_win32_focus_set,
|
||||||
_ecore_evas_win32_iconified_set,
|
_ecore_evas_win32_iconified_set,
|
||||||
_ecore_evas_win32_borderless_set,
|
_ecore_evas_win32_borderless_set,
|
||||||
_ecore_evas_win32_override_set,
|
_ecore_evas_win32_override_set,
|
||||||
NULL,
|
NULL,
|
||||||
_ecore_evas_win32_fullscreen_set,
|
_ecore_evas_win32_fullscreen_set,
|
||||||
NULL, /* _ecore_evas_x_avoid_damage_set */
|
NULL, /* _ecore_evas_x_avoid_damage_set */
|
||||||
NULL, /* _ecore_evas_x_withdrawn_set */
|
NULL, /* _ecore_evas_x_withdrawn_set */
|
||||||
NULL, /* _ecore_evas_x_sticky_set */
|
NULL, /* _ecore_evas_x_sticky_set */
|
||||||
NULL, /* _ecore_evas_x_ignore_events_set */
|
NULL, /* _ecore_evas_x_ignore_events_set */
|
||||||
_ecore_evas_win32_alpha_set,
|
_ecore_evas_win32_alpha_set,
|
||||||
NULL, //transparent
|
NULL, //transparent
|
||||||
NULL, // profiles_set
|
NULL, // profiles_set
|
||||||
NULL, // profile_set
|
NULL, // profile_set
|
||||||
|
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
|
||||||
NULL, // render
|
NULL, // render
|
||||||
_ecore_evas_win32_screen_geometry_get,
|
_ecore_evas_win32_screen_geometry_get,
|
||||||
_ecore_evas_win32_screen_dpi_get,
|
_ecore_evas_win32_screen_dpi_get,
|
||||||
NULL,
|
NULL,
|
||||||
NULL, // msg_send
|
NULL, // msg_send
|
||||||
|
|
||||||
NULL, // pointer_xy_get
|
NULL, // pointer_xy_get
|
||||||
NULL, // pointer_warp
|
NULL, // pointer_warp
|
||||||
|
|
||||||
NULL, // wm_rot_preferred_rotation_set
|
NULL, // wm_rot_preferred_rotation_set
|
||||||
NULL, // wm_rot_available_rotations_set
|
NULL, // wm_rot_available_rotations_set
|
||||||
NULL, // wm_rot_manual_rotation_done_set
|
NULL, // wm_rot_manual_rotation_done_set
|
||||||
NULL, // wm_rot_manual_rotation_done
|
NULL, // wm_rot_manual_rotation_done
|
||||||
|
|
||||||
NULL, // aux_hints_set
|
NULL, // aux_hints_set
|
||||||
|
|
||||||
NULL, // fn_animator_register
|
NULL, // fn_animator_register
|
||||||
NULL, // fn_animator_unregister
|
NULL, // fn_animator_unregister
|
||||||
|
|
||||||
NULL, // fn_evas_changed
|
NULL, // fn_evas_changed
|
||||||
NULL, //fn_focus_device_set
|
NULL, //fn_focus_device_set
|
||||||
NULL, //fn_callback_focus_device_in_set
|
NULL, //fn_callback_focus_device_in_set
|
||||||
NULL, //fn_callback_focus_device_out_set
|
NULL, //fn_callback_focus_device_out_set
|
||||||
NULL, //fn_callback_device_mouse_in_set
|
NULL, //fn_callback_device_mouse_in_set
|
||||||
NULL, //fn_callback_device_mouse_out_set
|
NULL, //fn_callback_device_mouse_out_set
|
||||||
NULL, //fn_pointer_device_xy_get
|
NULL, //fn_pointer_device_xy_get
|
||||||
NULL, //fn_prepare
|
NULL, //fn_prepare
|
||||||
NULL, //fn_last_tick_get
|
NULL, //fn_last_tick_get
|
||||||
|
_ecore_evas_win32_selection_claim, //fn_selection_claim
|
||||||
|
_ecore_evas_win32_selection_has_owner, //fn_selection_has_owner
|
||||||
|
_ecore_evas_win32_selection_request, //fn_selection_request
|
||||||
|
NULL, //fn_dnd_start
|
||||||
|
NULL, //fn_dnd_stop
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* BUILD_ECORE_EVAS_WIN32 */
|
#endif /* BUILD_ECORE_EVAS_WIN32 */
|
||||||
|
|
|
@ -73,6 +73,16 @@ static Eina_Bool wm_exists;
|
||||||
|
|
||||||
typedef struct _Ecore_Evas_Engine_Data_X11 Ecore_Evas_Engine_Data_X11;
|
typedef struct _Ecore_Evas_Engine_Data_X11 Ecore_Evas_Engine_Data_X11;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Ecore_Evas_Selection_Callbacks callbacks;
|
||||||
|
Ecore_Evas_Selection_Buffer buffer;
|
||||||
|
Ecore_Evas *ee;
|
||||||
|
Eina_Promise *delivery;
|
||||||
|
Eina_Array *acceptable_type;
|
||||||
|
Eina_Stringshare *requested_type;
|
||||||
|
Eina_Stringshare *later_conversion;
|
||||||
|
} Ecore_Evas_X11_Selection_Data;
|
||||||
|
|
||||||
struct _Ecore_Evas_Engine_Data_X11 {
|
struct _Ecore_Evas_Engine_Data_X11 {
|
||||||
Ecore_X_Window win_root;
|
Ecore_X_Window win_root;
|
||||||
Eina_List *win_extra;
|
Eina_List *win_extra;
|
||||||
|
@ -128,6 +138,11 @@ struct _Ecore_Evas_Engine_Data_X11 {
|
||||||
void *visual; // store visual used to create pixmap
|
void *visual; // store visual used to create pixmap
|
||||||
unsigned long colormap; // store colormap used to create pixmap
|
unsigned long colormap; // store colormap used to create pixmap
|
||||||
} pixmap;
|
} pixmap;
|
||||||
|
Ecore_Evas_X11_Selection_Data selection_data[ECORE_EVAS_SELECTION_BUFFER_LAST];
|
||||||
|
Eina_Array *xserver_atom_name_during_dnd;
|
||||||
|
Ecore_Event_Handler *mouse_up_handler;
|
||||||
|
Ecore_Job *init_job;
|
||||||
|
int skip_clean_event;
|
||||||
Eina_Bool destroyed : 1; // X window has been deleted and cannot be used
|
Eina_Bool destroyed : 1; // X window has been deleted and cannot be used
|
||||||
Eina_Bool fully_obscured : 1; // X window is fully obscured
|
Eina_Bool fully_obscured : 1; // X window is fully obscured
|
||||||
Eina_Bool configured : 1; // X window has been configured
|
Eina_Bool configured : 1; // X window has been configured
|
||||||
|
@ -151,6 +166,8 @@ static void _alpha_do(Ecore_Evas *, int);
|
||||||
static void _transparent_do(Ecore_Evas *, int);
|
static void _transparent_do(Ecore_Evas *, int);
|
||||||
static void _avoid_damage_do(Ecore_Evas *, int);
|
static void _avoid_damage_do(Ecore_Evas *, int);
|
||||||
static void _rotation_do(Ecore_Evas *, int, int);
|
static void _rotation_do(Ecore_Evas *, int, int);
|
||||||
|
static void _ecore_evas_x_selection_init(void);
|
||||||
|
static void _ecore_evas_x_selection_window_init(Ecore_Evas *ee);
|
||||||
|
|
||||||
#define SWAP_INT(a, b) do { a ^= b; b ^= a; a ^= b; } while (0)
|
#define SWAP_INT(a, b) do { a ^= b; b ^= a; a ^= b; } while (0)
|
||||||
|
|
||||||
|
@ -1970,6 +1987,7 @@ _ecore_evas_x_init(void)
|
||||||
ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CREATE,
|
ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CREATE,
|
||||||
_ecore_evas_x_event_window_create, NULL);
|
_ecore_evas_x_event_window_create, NULL);
|
||||||
ecore_event_evas_init();
|
ecore_event_evas_init();
|
||||||
|
_ecore_evas_x_selection_init();
|
||||||
return _ecore_evas_init_count;
|
return _ecore_evas_init_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1997,6 +2015,7 @@ _ecore_evas_x_free(Ecore_Evas *ee)
|
||||||
{
|
{
|
||||||
Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
|
Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
|
||||||
|
|
||||||
|
ecore_job_del(edata->init_job);
|
||||||
if (edata->pixmap.back)
|
if (edata->pixmap.back)
|
||||||
ecore_x_pixmap_free(edata->pixmap.back);
|
ecore_x_pixmap_free(edata->pixmap.back);
|
||||||
if (edata->pixmap.front)
|
if (edata->pixmap.front)
|
||||||
|
@ -2696,6 +2715,7 @@ _alpha_do(Ecore_Evas *ee, int alpha)
|
||||||
_ecore_evas_x_aux_hints_supported_update(ee);
|
_ecore_evas_x_aux_hints_supported_update(ee);
|
||||||
_ecore_evas_x_aux_hints_update(ee);
|
_ecore_evas_x_aux_hints_update(ee);
|
||||||
_ecore_evas_x_size_pos_hints_update(ee);
|
_ecore_evas_x_size_pos_hints_update(ee);
|
||||||
|
_ecore_evas_x_selection_window_init(ee);
|
||||||
#endif /* BUILD_ECORE_EVAS_SOFTWARE_X11 */
|
#endif /* BUILD_ECORE_EVAS_SOFTWARE_X11 */
|
||||||
if ((id = getenv("DESKTOP_STARTUP_ID")))
|
if ((id = getenv("DESKTOP_STARTUP_ID")))
|
||||||
{
|
{
|
||||||
|
@ -2850,6 +2870,7 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha)
|
||||||
_ecore_evas_x_aux_hints_supported_update(ee);
|
_ecore_evas_x_aux_hints_supported_update(ee);
|
||||||
_ecore_evas_x_aux_hints_update(ee);
|
_ecore_evas_x_aux_hints_update(ee);
|
||||||
_ecore_evas_x_size_pos_hints_update(ee);
|
_ecore_evas_x_size_pos_hints_update(ee);
|
||||||
|
_ecore_evas_x_selection_window_init(ee);
|
||||||
#endif /* BUILD_ECORE_EVAS_OPENGL_X11 */
|
#endif /* BUILD_ECORE_EVAS_OPENGL_X11 */
|
||||||
if ((id = getenv("DESKTOP_STARTUP_ID")))
|
if ((id = getenv("DESKTOP_STARTUP_ID")))
|
||||||
{
|
{
|
||||||
|
@ -3667,6 +3688,731 @@ _ecore_evas_x_aux_hints_set(Ecore_Evas *ee, const char *hints)
|
||||||
(ee->prop.window, ECORE_X_ATOM_E_WINDOW_AUX_HINT);
|
(ee->prop.window, ECORE_X_ATOM_E_WINDOW_AUX_HINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Ecore_X_Atom ecore_evas_selection_to_atom[] = {0, 0, 0, 0};
|
||||||
|
static Ecore_Event_Handler *ecore_evas_selection_handlers[8];
|
||||||
|
|
||||||
|
static inline Ecore_Evas_Selection_Buffer
|
||||||
|
_atom_to_selection(Ecore_X_Atom atom)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
|
||||||
|
{
|
||||||
|
if (ecore_evas_selection_to_atom[i] == atom)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return ECORE_EVAS_SELECTION_BUFFER_LAST;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Stringshare*
|
||||||
|
_decrypt_type(const char *target)
|
||||||
|
{
|
||||||
|
// reference https://tronche.com/gui/x/icccm/sec-2.html
|
||||||
|
if (eina_streq(target, "TEXT")) return eina_stringshare_add("text/plain");
|
||||||
|
//FIXME no support in eina_content for that so far
|
||||||
|
if (eina_streq(target, "COMPOUND_TEXT")) return eina_stringshare_add("text/plain");
|
||||||
|
// reference https://tronche.com/gui/x/icccm/sec-2.html
|
||||||
|
if (eina_streq(target, "STRING")) return eina_stringshare_add("text/plain;charset=iso-8859-1");
|
||||||
|
if (eina_streq(target, "UTF8_STRING")) return eina_stringshare_add("text/plain;charset=utf-8");
|
||||||
|
|
||||||
|
return eina_stringshare_add(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Stringshare*
|
||||||
|
_mime_to_xserver_type(const char *target)
|
||||||
|
{
|
||||||
|
// FIXME // reference https://tronche.com/gui/x/icccm/sec-2.html says it is in the owners choice of encoding, not sure what this means directly here
|
||||||
|
if (eina_streq(target, "text/plain")) return eina_stringshare_add("TEXT");
|
||||||
|
// reference https://tronche.com/gui/x/icccm/sec-2.html
|
||||||
|
if (eina_streq(target, "text/plain;charset=iso-8859-1")) return eina_stringshare_add("STRING");
|
||||||
|
if (eina_streq(target, "text/plain;charset=utf-8")) return eina_stringshare_add("UTF8_STRING");
|
||||||
|
|
||||||
|
return eina_stringshare_add(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_clear_selection(Ecore_Evas *ee, Ecore_Evas_Selection_Buffer selection)
|
||||||
|
{
|
||||||
|
Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
|
||||||
|
Ecore_Evas_Selection_Callbacks *cbs = &edata->selection_data[selection].callbacks;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_FALSE_RETURN(cbs->cancel);
|
||||||
|
|
||||||
|
cbs->cancel(ee, 1, selection);
|
||||||
|
eina_array_free(cbs->available_types);
|
||||||
|
|
||||||
|
cbs->delivery = NULL;
|
||||||
|
cbs->cancel = NULL;
|
||||||
|
cbs->available_types = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_clear_selection_delivery(Ecore_Evas *ee, Ecore_Evas_Selection_Buffer selection)
|
||||||
|
{
|
||||||
|
Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
|
||||||
|
eina_stringshare_replace(&edata->selection_data[selection].requested_type, NULL);
|
||||||
|
eina_stringshare_replace(&edata->selection_data[selection].later_conversion, NULL);
|
||||||
|
edata->selection_data[selection].delivery = NULL;
|
||||||
|
eina_array_free(edata->selection_data[selection].acceptable_type);
|
||||||
|
edata->selection_data[selection].acceptable_type = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ecore_x_selection_request(Ecore_X_Window win, Ecore_Evas_Selection_Buffer selection, const char *type)
|
||||||
|
{
|
||||||
|
if (selection == ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER)
|
||||||
|
ecore_x_selection_primary_request(win, type);
|
||||||
|
else if (selection == ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER)
|
||||||
|
ecore_x_selection_clipboard_request(win, type);
|
||||||
|
else
|
||||||
|
ecore_x_selection_xdnd_request(win, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_search_fitting_type(Ecore_Evas *ee, Ecore_Evas_Engine_Data_X11 *edata, Ecore_Evas_Selection_Buffer selection, Eina_Array *arr)
|
||||||
|
{
|
||||||
|
Eina_Stringshare *mime_type;
|
||||||
|
Eina_Bool found_conversion = EINA_FALSE;
|
||||||
|
|
||||||
|
#define HANDLE_TYPE() \
|
||||||
|
{ \
|
||||||
|
edata->selection_data[selection].requested_type = eina_stringshare_add(x11_name); \
|
||||||
|
edata->selection_data[selection].later_conversion = eina_stringshare_add(acceptable_type);\
|
||||||
|
found_conversion = EINA_TRUE; \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(edata->selection_data[selection].acceptable_type);
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < eina_array_count(arr) && !found_conversion; ++i)
|
||||||
|
{
|
||||||
|
const char *x11_name = eina_array_data_get(arr, i);
|
||||||
|
mime_type = _decrypt_type(x11_name);
|
||||||
|
|
||||||
|
for (unsigned int j = 0; j < eina_array_count(edata->selection_data[selection].acceptable_type) && !found_conversion; ++j)
|
||||||
|
{
|
||||||
|
const char *acceptable_type = (const char*) eina_array_data_get(edata->selection_data[selection].acceptable_type, j);
|
||||||
|
|
||||||
|
if (mime_type == acceptable_type)
|
||||||
|
HANDLE_TYPE()
|
||||||
|
|
||||||
|
//if there is no available type yet, check if we can convert to the desired type via this type
|
||||||
|
if (!found_conversion)
|
||||||
|
{
|
||||||
|
const char *convertion_type = NULL;
|
||||||
|
Eina_Iterator *iter = eina_content_converter_possible_conversions(mime_type);
|
||||||
|
EINA_ITERATOR_FOREACH(iter, convertion_type)
|
||||||
|
{
|
||||||
|
if (convertion_type == acceptable_type)
|
||||||
|
HANDLE_TYPE()
|
||||||
|
}
|
||||||
|
eina_iterator_free(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eina_stringshare_del(mime_type);
|
||||||
|
}
|
||||||
|
if (found_conversion)
|
||||||
|
{
|
||||||
|
_ecore_x_selection_request(ee->prop.window, selection, edata->selection_data[selection].requested_type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eina_promise_resolve(edata->selection_data[selection].delivery, eina_value_error_init(ecore_evas_no_matching_type));
|
||||||
|
_clear_selection_delivery(ee, selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef HANDLE_TYPE
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_search_fitting_type_from_event(Ecore_Evas *ee, Ecore_Evas_Engine_Data_X11 *edata, Ecore_Evas_Selection_Buffer selection, Ecore_X_Event_Selection_Notify *ev)
|
||||||
|
{
|
||||||
|
Ecore_X_Atom *available_atoms;
|
||||||
|
Ecore_X_Selection_Data_Targets *targets;
|
||||||
|
Eina_Array *tmp = eina_array_new(10);
|
||||||
|
|
||||||
|
targets = ev->data;
|
||||||
|
available_atoms = (Ecore_X_Atom *)targets->data.data;
|
||||||
|
for (int i = 0; i < targets->data.length; ++i)
|
||||||
|
{
|
||||||
|
Ecore_X_Atom atom = available_atoms[i];
|
||||||
|
eina_array_push(tmp, ecore_x_atom_name_get(atom));
|
||||||
|
}
|
||||||
|
_search_fitting_type(ee, edata, selection, tmp);
|
||||||
|
eina_array_free(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_deliver_content(Ecore_Evas *ee, Ecore_Evas_Engine_Data_X11 *edata, Ecore_Evas_Selection_Buffer selection, Ecore_X_Event_Selection_Notify *ev)
|
||||||
|
{
|
||||||
|
Ecore_X_Selection_Data *x11_data = ev->data;
|
||||||
|
Eina_Rw_Slice data;
|
||||||
|
Eina_Content *result;
|
||||||
|
Eina_Stringshare *mime_type = _decrypt_type(edata->selection_data[selection].requested_type);
|
||||||
|
|
||||||
|
if (!strncmp(mime_type, "text", strlen("text")))
|
||||||
|
{
|
||||||
|
//ensure that we always have a \0 at the end, there is no assertion that \0 is included here.
|
||||||
|
data.len = x11_data->length + 1;
|
||||||
|
data.mem = eina_memdup(x11_data->data, x11_data->length, EINA_TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data.len = x11_data->length;
|
||||||
|
data.mem = x11_data->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = eina_content_new(eina_rw_slice_slice_get(data), mime_type);
|
||||||
|
|
||||||
|
//ensure that we deliver the correct type, we might have choosen a convertion before
|
||||||
|
if (edata->selection_data[selection].later_conversion != mime_type)
|
||||||
|
{
|
||||||
|
Eina_Content *tmp = eina_content_convert(result, edata->selection_data[selection].later_conversion);
|
||||||
|
eina_content_free(result);
|
||||||
|
result = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
eina_promise_resolve(edata->selection_data[selection].delivery, eina_value_content_init(result));
|
||||||
|
eina_content_free(result);
|
||||||
|
_clear_selection_delivery(ee, selection);
|
||||||
|
|
||||||
|
if (selection == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER)
|
||||||
|
ecore_x_dnd_send_finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_x_selection_notify(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_X_Event_Selection_Notify *ev = event;
|
||||||
|
Ecore_Evas_Selection_Buffer selection;
|
||||||
|
Ecore_Evas_Engine_Data_X11 *edata;
|
||||||
|
Ecore_Evas *ee;
|
||||||
|
|
||||||
|
ee = ecore_event_window_match(ev->win);
|
||||||
|
selection = _atom_to_selection(ev->atom);
|
||||||
|
EINA_SAFETY_ON_FALSE_GOTO(!!ee, end);
|
||||||
|
EINA_SAFETY_ON_FALSE_GOTO(selection != ECORE_EVAS_SELECTION_BUFFER_LAST, end);
|
||||||
|
edata = ee->engine.data;
|
||||||
|
|
||||||
|
//if dnd drops above us, and even if we did not request anything, we are getting notified, refuse to do anything
|
||||||
|
if (selection == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER &&
|
||||||
|
!edata->selection_data[selection].later_conversion)
|
||||||
|
{
|
||||||
|
ecore_x_dnd_send_finished();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (eina_streq(ev->target, "TARGETS") || eina_streq(ev->target, "ATOMS"))
|
||||||
|
{
|
||||||
|
//This will decide for a type, and will sent that via _ecore_x_selection_request
|
||||||
|
EINA_SAFETY_ON_FALSE_RETURN_VAL(!edata->selection_data[selection].later_conversion, EINA_FALSE);
|
||||||
|
EINA_SAFETY_ON_FALSE_RETURN_VAL(!edata->selection_data[selection].requested_type, EINA_FALSE);
|
||||||
|
_search_fitting_type_from_event(ee, edata, selection, ev);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//This will read the data, fill it into a Eina_Content apply all conversions required.
|
||||||
|
EINA_SAFETY_ON_FALSE_RETURN_VAL(edata->selection_data[selection].later_conversion, EINA_FALSE);
|
||||||
|
EINA_SAFETY_ON_FALSE_RETURN_VAL(edata->selection_data[selection].requested_type, EINA_FALSE);
|
||||||
|
_deliver_content(ee, edata, selection, ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_x_selection_clear(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_X_Event_Selection_Clear *ev = event;
|
||||||
|
Ecore_Evas_Selection_Callbacks *cbs;
|
||||||
|
Ecore_Evas_Engine_Data_X11 *edata;
|
||||||
|
Ecore_Evas_Selection_Buffer selection;
|
||||||
|
Ecore_Evas *ee;
|
||||||
|
|
||||||
|
ee = ecore_event_window_match(ev->win);
|
||||||
|
selection = _atom_to_selection(ev->atom);
|
||||||
|
EINA_SAFETY_ON_FALSE_GOTO(ee, end);
|
||||||
|
EINA_SAFETY_ON_FALSE_GOTO(selection != ECORE_EVAS_SELECTION_BUFFER_LAST, end);
|
||||||
|
edata = ee->engine.data;
|
||||||
|
cbs = &edata->selection_data[selection].callbacks;
|
||||||
|
|
||||||
|
//skip clean event
|
||||||
|
if (edata->skip_clean_event)
|
||||||
|
{
|
||||||
|
edata->skip_clean_event --;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cbs->cancel)
|
||||||
|
_clear_selection(ee, selection);
|
||||||
|
end:
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_force_stop_self_dnd(Ecore_Evas *ee)
|
||||||
|
{
|
||||||
|
Ecore_Evas_Engine_Data_X11 *edata;
|
||||||
|
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(ee);
|
||||||
|
edata = ee->engine.data;
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(edata);
|
||||||
|
|
||||||
|
//Never clear the buffer for selection here.
|
||||||
|
//Selection buffer is freed as a response to the FINISHED event.
|
||||||
|
ecore_x_pointer_ungrab();
|
||||||
|
ecore_x_dnd_self_drop();
|
||||||
|
ecore_x_dnd_aware_set(ee->prop.window, EINA_FALSE);
|
||||||
|
ecore_event_handler_del(edata->mouse_up_handler);
|
||||||
|
edata->mouse_up_handler = NULL;
|
||||||
|
|
||||||
|
if (ee->drag.free)
|
||||||
|
ee->drag.free(ee, 1, ee->drag.data, ee->drag.accepted);
|
||||||
|
ee->drag.free = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_x_selection_fixes_notify(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_X_Event_Fixes_Selection_Notify *ev = event;
|
||||||
|
Ecore_Evas *ee;
|
||||||
|
Ecore_Evas_Selection_Buffer selection;
|
||||||
|
|
||||||
|
ee = ecore_event_window_match(ev->win);
|
||||||
|
selection = _atom_to_selection(ev->atom);
|
||||||
|
EINA_SAFETY_ON_FALSE_GOTO(!!ee, end);
|
||||||
|
EINA_SAFETY_ON_FALSE_GOTO(selection != ECORE_EVAS_SELECTION_BUFFER_LAST, end);
|
||||||
|
|
||||||
|
//notify that the selection has changed on this ecore evas
|
||||||
|
if (ee->func.fn_selection_changed)
|
||||||
|
ee->func.fn_selection_changed(ee, 0, selection);
|
||||||
|
end:
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_eina_content_converter(char *target, void *data, int size EINA_UNUSED, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize)
|
||||||
|
{
|
||||||
|
Ecore_Evas_X11_Selection_Data *sdata = data;
|
||||||
|
Eina_Bool ret = EINA_FALSE;;
|
||||||
|
if (eina_streq(target, "TARGETS") || eina_streq(target, "ATOM"))
|
||||||
|
{
|
||||||
|
//list all available types that we have currently
|
||||||
|
Ecore_X_Atom *result = calloc(eina_array_count(sdata->callbacks.available_types), sizeof(Ecore_X_Atom));
|
||||||
|
for (unsigned int i = 0; i < eina_array_count(sdata->callbacks.available_types); ++i)
|
||||||
|
{
|
||||||
|
result[i] = ecore_x_atom_get(eina_array_data_get(sdata->callbacks.available_types, i));
|
||||||
|
}
|
||||||
|
*size_ret = eina_array_count(sdata->callbacks.available_types);
|
||||||
|
*data_ret = result;
|
||||||
|
*ttype = ECORE_X_ATOM_ATOM;
|
||||||
|
*typesize = 32; /* urk */
|
||||||
|
ret = EINA_TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char *mime_type = _decrypt_type(target);
|
||||||
|
for (unsigned int i = 0; i < eina_array_count(sdata->callbacks.available_types); ++i)
|
||||||
|
{
|
||||||
|
if (mime_type == eina_array_data_get(sdata->callbacks.available_types, i))
|
||||||
|
{
|
||||||
|
Eina_Rw_Slice slice;
|
||||||
|
sdata->callbacks.delivery(sdata->ee, 1, sdata->buffer, mime_type, &slice);
|
||||||
|
*size_ret = slice.len;
|
||||||
|
*data_ret = slice.mem;
|
||||||
|
*ttype = ecore_x_atom_get(target); //use here target in order to get the correct atom
|
||||||
|
//FIXME in selection manager we never set here the typesize, isn't that weird ?
|
||||||
|
ret = EINA_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eina_stringshare_del(mime_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_x_dnd_enter(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_X_Event_Xdnd_Enter *enter = event;
|
||||||
|
Eina_Array *mime_tmp;
|
||||||
|
Ecore_Evas_Engine_Data_X11 *edata;
|
||||||
|
Ecore_Evas *ee;
|
||||||
|
|
||||||
|
mime_tmp = eina_array_new(10);
|
||||||
|
ee = ecore_event_window_match(enter->win);
|
||||||
|
EINA_SAFETY_ON_NULL_GOTO(ee, end);
|
||||||
|
edata = ee->engine.data;
|
||||||
|
edata->xserver_atom_name_during_dnd = eina_array_new(10);
|
||||||
|
for (int i = 0; i < enter->num_types; ++i)
|
||||||
|
{
|
||||||
|
const char *mime_type = _decrypt_type(enter->types[i]);
|
||||||
|
eina_array_push(mime_tmp, mime_type);
|
||||||
|
eina_array_push(edata->xserver_atom_name_during_dnd, eina_stringshare_add(enter->types[i]));
|
||||||
|
}
|
||||||
|
ecore_evas_dnd_enter(ee, 1, eina_array_iterator_new(mime_tmp), EINA_POSITION2D(0,0)); //FIXME
|
||||||
|
eina_array_free(mime_tmp);
|
||||||
|
|
||||||
|
end:
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_x_dnd_leave(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_X_Event_Xdnd_Leave *leave = event;
|
||||||
|
Ecore_Evas_Engine_Data_X11 *edata;
|
||||||
|
Ecore_Evas *ee;
|
||||||
|
|
||||||
|
ee = ecore_event_window_match(leave->win);
|
||||||
|
EINA_SAFETY_ON_NULL_GOTO(ee, end);
|
||||||
|
edata = ee->engine.data;
|
||||||
|
ecore_evas_dnd_leave(ee, 1, EINA_POSITION2D(0,0));
|
||||||
|
for (unsigned int i = 0; i < eina_array_count(edata->xserver_atom_name_during_dnd); ++i)
|
||||||
|
{
|
||||||
|
eina_stringshare_del(eina_array_data_get(edata->xserver_atom_name_during_dnd, i));
|
||||||
|
}
|
||||||
|
eina_array_free(edata->xserver_atom_name_during_dnd);
|
||||||
|
edata->xserver_atom_name_during_dnd = NULL;
|
||||||
|
end:
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Ecore_X_Atom
|
||||||
|
_x11_dnd_action_rev_map(const char* action)
|
||||||
|
{
|
||||||
|
if (eina_streq(action, "copy")) return ECORE_X_ATOM_XDND_ACTION_COPY;
|
||||||
|
if (eina_streq(action, "move")) return ECORE_X_ATOM_XDND_ACTION_MOVE;
|
||||||
|
else if (eina_streq(action, "privat")) return ECORE_X_ATOM_XDND_ACTION_PRIVATE;
|
||||||
|
else if (eina_streq(action, "ask")) return ECORE_X_ATOM_XDND_ACTION_ASK;
|
||||||
|
else if (eina_streq(action, "list")) return ECORE_X_ATOM_XDND_ACTION_LIST;
|
||||||
|
else if (eina_streq(action, "link")) return ECORE_X_ATOM_XDND_ACTION_LINK;
|
||||||
|
else if (eina_streq(action, "description")) return ECORE_X_ATOM_XDND_ACTION_DESCRIPTION;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char*
|
||||||
|
_x11_dnd_action_map(Ecore_X_Atom action)
|
||||||
|
{
|
||||||
|
if (action == ECORE_X_DND_ACTION_COPY) return "copy";
|
||||||
|
if (action == ECORE_X_ATOM_XDND_ACTION_MOVE) return "move";
|
||||||
|
if (action == ECORE_X_ATOM_XDND_ACTION_PRIVATE) return "privat";
|
||||||
|
if (action == ECORE_X_ATOM_XDND_ACTION_ASK) return "ask";
|
||||||
|
if (action == ECORE_X_ATOM_XDND_ACTION_LIST) return "list";
|
||||||
|
if (action == ECORE_X_ATOM_XDND_ACTION_LINK) return "link";
|
||||||
|
if (action == ECORE_X_ATOM_XDND_ACTION_DESCRIPTION) return "description";
|
||||||
|
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_x_dnd_position(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_X_Event_Xdnd_Position *pos = event;
|
||||||
|
int x, y, w, h;
|
||||||
|
Ecore_Evas *ee;
|
||||||
|
|
||||||
|
ee = ecore_event_window_match(pos->win);
|
||||||
|
EINA_SAFETY_ON_NULL_GOTO(ee, end);
|
||||||
|
ecore_evas_geometry_get(ee, &x, &y, &w, &h);
|
||||||
|
ecore_evas_dnd_position_set(ee, 1, EINA_POSITION2D(pos->position.x - x, pos->position.y - y));
|
||||||
|
ecore_x_dnd_send_status(EINA_TRUE, EINA_FALSE, (Ecore_X_Rectangle){x,y,w,h}, pos->action);
|
||||||
|
end:
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_x_dnd_drop(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_X_Event_Xdnd_Drop *drop = event;
|
||||||
|
Ecore_Evas_Engine_Data_X11 *edata;
|
||||||
|
Ecore_Evas *ee;
|
||||||
|
|
||||||
|
ee = ecore_event_window_match(drop->win);
|
||||||
|
EINA_SAFETY_ON_NULL_GOTO(ee, end);
|
||||||
|
edata = ee->engine.data;
|
||||||
|
if (ee->func.fn_dnd_drop)
|
||||||
|
ee->func.fn_dnd_drop(ee, 1, ecore_evas_dnd_pos_get(ee, 1), _x11_dnd_action_map(drop->action));
|
||||||
|
if (!edata->selection_data[ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER].requested_type)
|
||||||
|
{
|
||||||
|
ecore_x_dnd_send_finished();
|
||||||
|
}
|
||||||
|
ecore_evas_dnd_leave(ee, 1, EINA_POSITION2D(drop->position.x ,drop->position.y));
|
||||||
|
eina_array_free(edata->xserver_atom_name_during_dnd);
|
||||||
|
edata->xserver_atom_name_during_dnd = NULL;
|
||||||
|
end:
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_x_finished(void *udata EINA_UNUSED, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_X_Event_Xdnd_Finished *finished = event;
|
||||||
|
Ecore_Evas *ee;
|
||||||
|
|
||||||
|
ee = ecore_event_window_match(finished->win);
|
||||||
|
EINA_SAFETY_ON_NULL_GOTO(ee, end);
|
||||||
|
|
||||||
|
_clear_selection(ee, ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER);
|
||||||
|
end:
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ecore_evas_x_selection_init(void)
|
||||||
|
{
|
||||||
|
Ecore_X_Atom _ecore_evas_selection_to_atom[] = {ECORE_X_ATOM_SELECTION_PRIMARY, ECORE_X_ATOM_SELECTION_CLIPBOARD, ECORE_X_ATOM_SELECTION_XDND};
|
||||||
|
|
||||||
|
for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
|
||||||
|
{
|
||||||
|
ecore_evas_selection_to_atom[i] = _ecore_evas_selection_to_atom[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
ecore_evas_selection_handlers[0] =
|
||||||
|
ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY,
|
||||||
|
_ecore_evas_x_selection_notify, NULL);
|
||||||
|
ecore_evas_selection_handlers[1] =
|
||||||
|
ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR,
|
||||||
|
_ecore_evas_x_selection_clear, NULL);
|
||||||
|
if (ECORE_X_EVENT_FIXES_SELECTION_NOTIFY)
|
||||||
|
ecore_evas_selection_handlers[2] =
|
||||||
|
ecore_event_handler_add(ECORE_X_EVENT_FIXES_SELECTION_NOTIFY,
|
||||||
|
_ecore_evas_x_selection_fixes_notify, NULL);
|
||||||
|
|
||||||
|
ecore_evas_selection_handlers[3] = ecore_event_handler_add(ECORE_X_EVENT_XDND_ENTER,
|
||||||
|
_ecore_evas_x_dnd_enter, NULL);
|
||||||
|
ecore_evas_selection_handlers[4] = ecore_event_handler_add(ECORE_X_EVENT_XDND_LEAVE,
|
||||||
|
_ecore_evas_x_dnd_leave, NULL);
|
||||||
|
ecore_evas_selection_handlers[5] = ecore_event_handler_add(ECORE_X_EVENT_XDND_POSITION,
|
||||||
|
_ecore_evas_x_dnd_position, NULL);
|
||||||
|
ecore_evas_selection_handlers[6] = ecore_event_handler_add(ECORE_X_EVENT_XDND_DROP,
|
||||||
|
_ecore_evas_x_dnd_drop, NULL);
|
||||||
|
ecore_evas_selection_handlers[7] = ecore_event_handler_add(ECORE_X_EVENT_XDND_FINISHED,
|
||||||
|
_ecore_evas_x_finished, NULL);
|
||||||
|
/* for us known type */
|
||||||
|
char *supported_types[] = {
|
||||||
|
"text/plain",
|
||||||
|
"text/plain;charset=utf-8",
|
||||||
|
"image/png",
|
||||||
|
"image/jpeg",
|
||||||
|
"image/x-ms-bmp",
|
||||||
|
"image/gif",
|
||||||
|
"image/tiff",
|
||||||
|
"image/svg+xml",
|
||||||
|
"image/x-xpixmap",
|
||||||
|
"image/x-tga",
|
||||||
|
"image/x-portable-pixmap",
|
||||||
|
"TEXT",
|
||||||
|
"COMPOUND_TEXT",
|
||||||
|
"STRING",
|
||||||
|
"UTF8_STRING",
|
||||||
|
"text/x-vcard",
|
||||||
|
"text/uri-list",
|
||||||
|
"application/x-elementary-markup",
|
||||||
|
"ATOM",
|
||||||
|
"TARGETS",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
for (int i = 0; supported_types[i]; ++i)
|
||||||
|
{
|
||||||
|
ecore_x_selection_converter_add(supported_types[i], _eina_content_converter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_x_selection_has_owner(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection)
|
||||||
|
{
|
||||||
|
return !!ecore_x_selection_owner_get(ecore_evas_selection_to_atom[selection]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_deliver_selection_changed(void *data)
|
||||||
|
{
|
||||||
|
Ecore_Evas *ee = data;
|
||||||
|
Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
|
||||||
|
|
||||||
|
if (!ee->func.fn_selection_changed)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if (_ecore_evas_x_selection_has_owner(ee, 1, ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER))
|
||||||
|
ee->func.fn_selection_changed(ee, 1, ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER);
|
||||||
|
if (_ecore_evas_x_selection_has_owner(ee, 1, ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER))
|
||||||
|
ee->func.fn_selection_changed(ee, 1, ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER);
|
||||||
|
if (_ecore_evas_x_selection_has_owner(ee, 1, ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER))
|
||||||
|
ee->func.fn_selection_changed(ee, 1, ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER);
|
||||||
|
end:
|
||||||
|
edata->init_job = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ecore_evas_x_selection_window_init(Ecore_Evas *ee)
|
||||||
|
{
|
||||||
|
Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
|
||||||
|
for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
|
||||||
|
{
|
||||||
|
ecore_x_fixes_window_selection_notification_request(ee->prop.window, ecore_evas_selection_to_atom[i]);
|
||||||
|
edata->selection_data[i].ee = ee;
|
||||||
|
edata->selection_data[i].buffer = i;
|
||||||
|
}
|
||||||
|
ecore_x_dnd_aware_set(ee->prop.window, EINA_TRUE);
|
||||||
|
edata->init_job = ecore_job_add(_deliver_selection_changed, ee);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_store_selection_cbs(Ecore_Evas *ee, Ecore_Evas_Selection_Buffer selection, Eina_Array *available_types, Eina_Bool (*delivery)(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer, const char *type, Eina_Rw_Slice *slice), void (*cancel)(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer))
|
||||||
|
{
|
||||||
|
Ecore_Evas_X11_Selection_Data *sdata;
|
||||||
|
Ecore_Evas_Engine_Data_X11 *edata;
|
||||||
|
Ecore_Evas_Selection_Callbacks *cbs;
|
||||||
|
|
||||||
|
edata = ee->engine.data;
|
||||||
|
sdata = &edata->selection_data[selection];
|
||||||
|
cbs = &sdata->callbacks;
|
||||||
|
|
||||||
|
if (cbs->cancel)
|
||||||
|
{
|
||||||
|
_clear_selection(ee, selection);
|
||||||
|
edata->skip_clean_event ++; //we are going to overwrite our own selection, this will emit a clean event, but we already freed it.
|
||||||
|
}
|
||||||
|
|
||||||
|
cbs->delivery = delivery;
|
||||||
|
cbs->cancel = cancel;
|
||||||
|
cbs->available_types = available_types;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_x_selection_claim(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection, Eina_Array *available_types, Ecore_Evas_Internal_Delivery delivery, Ecore_Evas_Internal_Cancel cancel)
|
||||||
|
{
|
||||||
|
Ecore_Evas_X11_Selection_Data *sdata;
|
||||||
|
Ecore_Evas_Engine_Data_X11 *edata;
|
||||||
|
|
||||||
|
edata = ee->engine.data;
|
||||||
|
sdata = &edata->selection_data[selection];
|
||||||
|
|
||||||
|
_store_selection_cbs(ee, selection, available_types, delivery, cancel);
|
||||||
|
|
||||||
|
if (eina_array_count(available_types) > 0)
|
||||||
|
{
|
||||||
|
//the commands below will *copy* the content of sdata, this you have to ensure that clear is called when sdata is changed.
|
||||||
|
if (selection == ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER)
|
||||||
|
ecore_x_selection_primary_set(ee->prop.window, sdata, sizeof(Ecore_Evas_X11_Selection_Data));
|
||||||
|
else if (selection == ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER)
|
||||||
|
ecore_x_selection_clipboard_set(ee->prop.window, sdata, sizeof(Ecore_Evas_X11_Selection_Data));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (selection == ECORE_EVAS_SELECTION_BUFFER_SELECTION_BUFFER)
|
||||||
|
ecore_x_selection_primary_clear();
|
||||||
|
else if (selection == ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER)
|
||||||
|
ecore_x_selection_clipboard_clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//for drag and drop, we are not calling anything in here
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Future*
|
||||||
|
_ecore_evas_x_selection_request(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection, Eina_Array *acceptable_type)
|
||||||
|
{
|
||||||
|
Ecore_Evas_X11_Selection_Data *sdata;
|
||||||
|
Ecore_Evas_Engine_Data_X11 *edata;
|
||||||
|
Eina_Future *future;
|
||||||
|
|
||||||
|
edata = ee->engine.data;
|
||||||
|
sdata = &edata->selection_data[selection];
|
||||||
|
|
||||||
|
if (sdata->delivery)
|
||||||
|
{
|
||||||
|
eina_promise_reject(sdata->delivery, ecore_evas_request_replaced);
|
||||||
|
_clear_selection_delivery(ee, selection);
|
||||||
|
}
|
||||||
|
sdata->delivery = efl_loop_promise_new(efl_main_loop_get());
|
||||||
|
sdata->acceptable_type = acceptable_type;
|
||||||
|
future = eina_future_new(sdata->delivery);
|
||||||
|
|
||||||
|
if (selection == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER)
|
||||||
|
{
|
||||||
|
//when in dnd - we are requesting out of the set that we know from the enter event
|
||||||
|
EINA_SAFETY_ON_FALSE_RETURN_VAL(!edata->selection_data[selection].later_conversion, NULL);
|
||||||
|
EINA_SAFETY_ON_FALSE_RETURN_VAL(!edata->selection_data[selection].requested_type, NULL);
|
||||||
|
_search_fitting_type(ee, edata, selection, edata->xserver_atom_name_during_dnd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//when not dnd - we are first wanting to know what is available
|
||||||
|
_ecore_x_selection_request(ee->prop.window, selection, ECORE_X_SELECTION_TARGET_TARGETS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return future;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_x11_drag_move(void *data, Ecore_X_Xdnd_Position *pos)
|
||||||
|
{
|
||||||
|
Ecore_Evas *ee = data;
|
||||||
|
Eina_Rect rect;
|
||||||
|
|
||||||
|
ecore_evas_geometry_get(ee->drag.rep, &rect.x, &rect.y, &rect.w, &rect.h);
|
||||||
|
|
||||||
|
ecore_evas_move(ee->drag.rep, pos->position.x - rect.w / 2, pos->position.y - rect.h/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_x11_drag_mouse_up(void *data, int etype EINA_UNUSED, void *event EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Ecore_Evas *ee = data;
|
||||||
|
|
||||||
|
_force_stop_self_dnd(ee);
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_x_dnd_start(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Eina_Array *available_types, Ecore_Evas *drag_rep, Eina_Bool (*delivery)(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer, const char *type, Eina_Rw_Slice *slice), void (*cancel)(Ecore_Evas *ee, unsigned int seat, Ecore_Evas_Selection_Buffer buffer), const char* action)
|
||||||
|
{
|
||||||
|
Ecore_Evas_X11_Selection_Data *sdata;
|
||||||
|
Ecore_Evas_Engine_Data_X11 *edata;
|
||||||
|
Ecore_X_Atom actx;
|
||||||
|
|
||||||
|
edata = ee->engine.data;
|
||||||
|
sdata = &edata->selection_data[ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER];
|
||||||
|
_store_selection_cbs(ee, ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER, available_types, delivery, cancel);
|
||||||
|
|
||||||
|
//first set all types we have
|
||||||
|
ecore_x_dnd_types_set(ee->prop.window, NULL, 0);
|
||||||
|
for (unsigned int i = 0; i < eina_array_count(available_types); ++i)
|
||||||
|
{
|
||||||
|
const char *xserver_mime_type = _mime_to_xserver_type(eina_array_data_get(available_types, i));
|
||||||
|
ecore_x_dnd_type_set(ee->prop.window, xserver_mime_type, EINA_TRUE);
|
||||||
|
eina_stringshare_del(xserver_mime_type);
|
||||||
|
}
|
||||||
|
ecore_x_dnd_aware_set(ee->prop.window, EINA_TRUE);
|
||||||
|
ecore_x_dnd_callback_pos_update_set(_x11_drag_move, ee);
|
||||||
|
ecore_x_dnd_self_begin(ee->prop.window, (unsigned char*)sdata, sizeof(Ecore_Evas_X11_Selection_Data));
|
||||||
|
actx = _x11_dnd_action_rev_map(action);
|
||||||
|
ecore_x_dnd_source_action_set(actx);
|
||||||
|
ecore_x_pointer_grab(ee->prop.window);
|
||||||
|
|
||||||
|
ecore_x_window_ignore_set(drag_rep->prop.window, EINA_TRUE);
|
||||||
|
|
||||||
|
if (edata->mouse_up_handler)
|
||||||
|
ecore_event_handler_del(edata->mouse_up_handler);
|
||||||
|
edata->mouse_up_handler = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
|
||||||
|
_x11_drag_mouse_up, ee);
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ecore_evas_x_dnd_stop(Ecore_Evas *ee, unsigned int seat EINA_UNUSED)
|
||||||
|
{
|
||||||
|
_force_stop_self_dnd(ee);
|
||||||
|
_clear_selection(ee, ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER);
|
||||||
|
ecore_x_selection_xdnd_clear(); //This is needed otherwise a outdated sdata struct will be accessed
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static Ecore_Evas_Engine_Func _ecore_x_engine_func =
|
static Ecore_Evas_Engine_Func _ecore_x_engine_func =
|
||||||
{
|
{
|
||||||
_ecore_evas_x_free,
|
_ecore_evas_x_free,
|
||||||
|
@ -3754,6 +4500,11 @@ static Ecore_Evas_Engine_Func _ecore_x_engine_func =
|
||||||
NULL, //fn_pointer_device_xy_get
|
NULL, //fn_pointer_device_xy_get
|
||||||
NULL, //fn_prepare
|
NULL, //fn_prepare
|
||||||
NULL, //fn_last_tick_get
|
NULL, //fn_last_tick_get
|
||||||
|
_ecore_evas_x_selection_claim, //fn_selection_claim
|
||||||
|
_ecore_evas_x_selection_has_owner, //fn_selection_has_owner
|
||||||
|
_ecore_evas_x_selection_request, //fn_selection_request
|
||||||
|
_ecore_evas_x_dnd_start, //fn_dnd_start
|
||||||
|
_ecore_evas_x_dnd_stop, //fn_dnd_stop
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -4117,6 +4868,7 @@ ecore_evas_software_x11_new_internal(const char *disp_name, Ecore_X_Window paren
|
||||||
_ecore_evas_x_wm_rotation_protocol_set(ee);
|
_ecore_evas_x_wm_rotation_protocol_set(ee);
|
||||||
_ecore_evas_x_aux_hints_supported_update(ee);
|
_ecore_evas_x_aux_hints_supported_update(ee);
|
||||||
_ecore_evas_x_aux_hints_update(ee);
|
_ecore_evas_x_aux_hints_update(ee);
|
||||||
|
_ecore_evas_x_selection_window_init(ee);
|
||||||
|
|
||||||
ee->engine.func->fn_render = _ecore_evas_x_render;
|
ee->engine.func->fn_render = _ecore_evas_x_render;
|
||||||
ee->draw_block = EINA_TRUE;
|
ee->draw_block = EINA_TRUE;
|
||||||
|
@ -4553,6 +5305,7 @@ ecore_evas_gl_x11_options_new_internal(const char *disp_name, Ecore_X_Window par
|
||||||
_ecore_evas_x_wm_rotation_protocol_set(ee);
|
_ecore_evas_x_wm_rotation_protocol_set(ee);
|
||||||
_ecore_evas_x_aux_hints_supported_update(ee);
|
_ecore_evas_x_aux_hints_supported_update(ee);
|
||||||
_ecore_evas_x_aux_hints_update(ee);
|
_ecore_evas_x_aux_hints_update(ee);
|
||||||
|
_ecore_evas_x_selection_window_init(ee);
|
||||||
|
|
||||||
ee->draw_block = 1;
|
ee->draw_block = 1;
|
||||||
if (!wm_exists) edata->configured = 1;
|
if (!wm_exists) edata->configured = 1;
|
||||||
|
|
|
@ -30,6 +30,7 @@ static const Efl_Test_Case etc[] = {
|
||||||
{ "Ecore_Job", ecore_test_ecore_job },
|
{ "Ecore_Job", ecore_test_ecore_job },
|
||||||
{ "Ecore_Args", ecore_test_ecore_args },
|
{ "Ecore_Args", ecore_test_ecore_args },
|
||||||
{ "Ecore_Pipe", ecore_test_ecore_pipe },
|
{ "Ecore_Pipe", ecore_test_ecore_pipe },
|
||||||
|
{ "Ecore_Evas_Selection", ecore_test_ecore_evas_selection },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -23,5 +23,6 @@ void ecore_test_ecore_file(TCase *tc);
|
||||||
void ecore_test_ecore_job(TCase *tc);
|
void ecore_test_ecore_job(TCase *tc);
|
||||||
void ecore_test_ecore_args(TCase *tc);
|
void ecore_test_ecore_args(TCase *tc);
|
||||||
void ecore_test_ecore_pipe(TCase *tc);
|
void ecore_test_ecore_pipe(TCase *tc);
|
||||||
|
void ecore_test_ecore_evas_selection(TCase *tc);
|
||||||
|
|
||||||
#endif /* _ECORE_SUITE_H */
|
#endif /* _ECORE_SUITE_H */
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <Ecore_Evas.h>
|
#include <Ecore_Evas.h>
|
||||||
|
#include <Efl_Core.h>
|
||||||
|
|
||||||
#include "ecore_suite.h"
|
#include "ecore_suite.h"
|
||||||
|
|
||||||
|
@ -70,8 +71,51 @@ EFL_START_TEST(ecore_test_ecore_evas_cocoa)
|
||||||
}
|
}
|
||||||
EFL_END_TEST
|
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)
|
void ecore_test_ecore_evas(TCase *tc)
|
||||||
{
|
{
|
||||||
tcase_add_test(tc, ecore_test_ecore_evas_associate);
|
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_cocoa);
|
||||||
|
tcase_add_test(tc, ecore_test_ecore_evas_fallback_selection);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Ecore_Evas.h>
|
||||||
|
#include <Efl_Core.h>
|
||||||
|
|
||||||
|
#include "ecore_suite.h"
|
||||||
|
|
||||||
|
#define WINDOW_HEIGHT 200
|
||||||
|
#define WINDOW_WIDTH 200
|
||||||
|
|
||||||
|
static int log_abort;
|
||||||
|
static int log_abort_level;
|
||||||
|
|
||||||
|
void
|
||||||
|
fail_on_errors_teardown(void)
|
||||||
|
{
|
||||||
|
eina_log_abort_on_critical_set(log_abort);
|
||||||
|
eina_log_abort_on_critical_level_set(log_abort_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fail_on_errors_setup(void)
|
||||||
|
{
|
||||||
|
log_abort = eina_log_abort_on_critical_get();
|
||||||
|
log_abort_level = eina_log_abort_on_critical_level_get();
|
||||||
|
eina_log_abort_on_critical_level_set(2);
|
||||||
|
eina_log_abort_on_critical_set(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Ecore_Evas *ee;
|
||||||
|
|
||||||
|
void
|
||||||
|
_setup(void)
|
||||||
|
{
|
||||||
|
ecore_evas_init();
|
||||||
|
ee = ecore_evas_buffer_new(50, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_teardown(void)
|
||||||
|
{
|
||||||
|
ecore_evas_free(ee);
|
||||||
|
ecore_evas_shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
EFL_START_TEST(ecore_test_selection_get_twice)
|
||||||
|
{
|
||||||
|
//this is just running this and checking that we do not error
|
||||||
|
for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
|
||||||
|
{
|
||||||
|
if (i == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER) continue;
|
||||||
|
const char *types[] = {eina_stringshare_add("text/plain")};
|
||||||
|
ck_assert_ptr_ne(ecore_evas_selection_get(ee, 0, i, EINA_C_ARRAY_ITERATOR_NEW(types)), NULL);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
|
||||||
|
{
|
||||||
|
if (i == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER) continue;
|
||||||
|
const char *types[] = {eina_stringshare_add("text/plain")};
|
||||||
|
ck_assert_ptr_ne(ecore_evas_selection_get(ee, 0, i, EINA_C_ARRAY_ITERATOR_NEW(types)), NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EFL_END_TEST
|
||||||
|
|
||||||
|
EFL_START_TEST(ecore_test_selection_claim_twice)
|
||||||
|
{
|
||||||
|
//this is just running this and checking that we do not error
|
||||||
|
for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
|
||||||
|
{
|
||||||
|
if (i == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER) continue;
|
||||||
|
Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL("asdf"), "text/plain");
|
||||||
|
ck_assert_int_eq(ecore_evas_selection_set(ee, 0, i, content), EINA_TRUE);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
|
||||||
|
{
|
||||||
|
if (i == ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER) continue;
|
||||||
|
Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL("asdf"), "text/plain");
|
||||||
|
ck_assert_int_eq(ecore_evas_selection_set(ee, 0, i, content), EINA_TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EFL_END_TEST
|
||||||
|
void ecore_test_ecore_evas_selection(TCase *tc)
|
||||||
|
{
|
||||||
|
tcase_add_checked_fixture(tc, fail_on_errors_setup, fail_on_errors_teardown);
|
||||||
|
tcase_add_checked_fixture(tc, _setup, _teardown);
|
||||||
|
tcase_add_test(tc, ecore_test_selection_get_twice);
|
||||||
|
tcase_add_test(tc, ecore_test_selection_claim_twice);
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ ecore_suite_src = [
|
||||||
'ecore_test_job.c',
|
'ecore_test_job.c',
|
||||||
'ecore_test_args.c',
|
'ecore_test_args.c',
|
||||||
'ecore_test_pipe.c',
|
'ecore_test_pipe.c',
|
||||||
|
'ecore_test_ecore_evas_selection.c',
|
||||||
'ecore_suite.h'
|
'ecore_suite.h'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -499,15 +499,14 @@ internal class TestStructTuples
|
||||||
#if EFL_BETA
|
#if EFL_BETA
|
||||||
public static void test_complex_fields_assign_conversion() {
|
public static void test_complex_fields_assign_conversion() {
|
||||||
var pos = new Eina.Position2D(1, 2);
|
var pos = new Eina.Position2D(1, 2);
|
||||||
var action = Efl.Ui.SelectionAction.Unknown;
|
uint seat = 3;
|
||||||
var format = Efl.Ui.SelectionFormat.None;
|
var types = new System.String[] {"text", "markup"};
|
||||||
var item = null as Efl.Canvas.Vg.Object;
|
|
||||||
|
|
||||||
Efl.Dnd.DragPos attr = (pos, action, format, item);
|
Efl.Ui.DropEvent attr = (pos, seat, types);
|
||||||
Test.AssertEquals(attr.Pos, pos);
|
Test.AssertEquals(attr.Position, pos);
|
||||||
Test.AssertEquals(attr.Action, action);
|
Test.AssertEquals(attr.Seat, seat);
|
||||||
Test.AssertEquals(attr.Format, format);
|
Test.AssertEquals(attr.AvailableTypes.ElementAt(0), types[0]);
|
||||||
Test.AssertEquals(attr.Item, item);
|
Test.AssertEquals(attr.AvailableTypes.ElementAt(1), types[1]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,7 @@ static const Efl_Test_Case etc[] = {
|
||||||
{ "slstr", eina_test_slstr },
|
{ "slstr", eina_test_slstr },
|
||||||
{ "Vpath", eina_test_vpath },
|
{ "Vpath", eina_test_vpath },
|
||||||
{ "debug", eina_test_debug },
|
{ "debug", eina_test_debug },
|
||||||
|
{ "Abstract Content", eina_test_abstract_content },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -78,5 +78,6 @@ void eina_test_freeq(TCase *tc);
|
||||||
void eina_test_slstr(TCase *tc);
|
void eina_test_slstr(TCase *tc);
|
||||||
void eina_test_vpath(TCase *tc);
|
void eina_test_vpath(TCase *tc);
|
||||||
void eina_test_debug(TCase *tc);
|
void eina_test_debug(TCase *tc);
|
||||||
|
void eina_test_abstract_content(TCase *tc);
|
||||||
|
|
||||||
#endif /* EINA_SUITE_H_ */
|
#endif /* EINA_SUITE_H_ */
|
||||||
|
|
|
@ -0,0 +1,223 @@
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <Eina.h>
|
||||||
|
|
||||||
|
#include "eina_suite.h"
|
||||||
|
|
||||||
|
EFL_START_TEST(eina_test_content_create_destroy)
|
||||||
|
{
|
||||||
|
const char *text_str = "TestAsDf";
|
||||||
|
Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(text_str), "text/plain");
|
||||||
|
|
||||||
|
ck_assert_str_eq(eina_content_type_get(content), "text/plain");
|
||||||
|
ck_assert_int_eq(eina_content_data_get(content).len, strlen(text_str) + 1);
|
||||||
|
ck_assert_str_eq(eina_content_data_get(content).mem, text_str);
|
||||||
|
|
||||||
|
eina_content_free(content);
|
||||||
|
}
|
||||||
|
EFL_END_TEST
|
||||||
|
|
||||||
|
EFL_START_TEST(eina_test_content_as_file)
|
||||||
|
{
|
||||||
|
const char *text_str = "TestAsDf";
|
||||||
|
Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(text_str), "text/plain");
|
||||||
|
Eina_File *f;
|
||||||
|
const char *file_path = eina_content_as_file(content);
|
||||||
|
|
||||||
|
f = eina_file_open(file_path, EINA_FALSE);
|
||||||
|
const char *file_content = eina_file_map_all(f, EINA_FILE_POPULATE);
|
||||||
|
ck_assert_str_eq(file_content, text_str);
|
||||||
|
eina_file_close(f);
|
||||||
|
|
||||||
|
eina_content_free(content);
|
||||||
|
|
||||||
|
const char *file_path2 = eina_content_as_file(content);
|
||||||
|
ck_assert_str_eq(file_path, file_path2);
|
||||||
|
}
|
||||||
|
EFL_END_TEST
|
||||||
|
|
||||||
|
EFL_START_TEST(eina_test_content_convert_none_existing)
|
||||||
|
{
|
||||||
|
const char *text_str = "TestAsDf";
|
||||||
|
Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(text_str), "text/plain");
|
||||||
|
|
||||||
|
EXPECT_ERROR_START;
|
||||||
|
ck_assert_ptr_eq(eina_content_convert(content, "ThisIsReallyNotHere"), NULL);
|
||||||
|
EXPECT_ERROR_END;
|
||||||
|
}
|
||||||
|
EFL_END_TEST
|
||||||
|
|
||||||
|
EFL_START_TEST(eina_test_content_convert_ascii_to_utf8)
|
||||||
|
{
|
||||||
|
const char *text_str = "TestAsDf";
|
||||||
|
Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(text_str), "text/plain");
|
||||||
|
Eina_Content *c = eina_content_convert(content, "text/plain;charset=utf-8");
|
||||||
|
|
||||||
|
ck_assert_str_eq(eina_content_type_get(c), "text/plain;charset=utf-8");
|
||||||
|
ck_assert_str_eq(eina_content_data_get(c).mem, text_str);
|
||||||
|
}
|
||||||
|
EFL_END_TEST
|
||||||
|
|
||||||
|
EFL_START_TEST(eina_test_content_convert_ascii_to_latin)
|
||||||
|
{
|
||||||
|
const char *text_str = "TestAsDf";
|
||||||
|
Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(text_str), "text/plain");
|
||||||
|
Eina_Content *c = eina_content_convert(content, "text/plain;charset=iso-8859-1");
|
||||||
|
|
||||||
|
ck_assert_str_eq(eina_content_type_get(c), "text/plain;charset=iso-8859-1");
|
||||||
|
ck_assert_str_eq(eina_content_data_get(c).mem, text_str);
|
||||||
|
}
|
||||||
|
EFL_END_TEST
|
||||||
|
|
||||||
|
EFL_START_TEST(eina_test_content_convert_utf8_to_latin)
|
||||||
|
{
|
||||||
|
//this means AÄÜÖß
|
||||||
|
const char text_str[] = {'A', 0xc3, 0x84, 0xc3, 0x9c, 0xc3, 0x96, 0xc3, 0x9f, 0};
|
||||||
|
const char text_str_latin[] = {'A', 0xC4, 0xDC, 0xD6, 0xDF, 0};
|
||||||
|
Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(text_str_latin), "text/plain;charset=iso-8859-1");
|
||||||
|
Eina_Content *c = eina_content_convert(content, "text/plain;charset=utf-8");
|
||||||
|
|
||||||
|
ck_assert_str_eq(eina_content_type_get(c), "text/plain;charset=utf-8");
|
||||||
|
ck_assert_int_eq(sizeof(text_str), eina_content_data_get(c).len);
|
||||||
|
for (unsigned int i = 0; i < eina_content_data_get(c).len; ++i)
|
||||||
|
{
|
||||||
|
ck_assert_int_eq(text_str[i], ((char*)eina_content_data_get(c).mem)[i]);
|
||||||
|
}
|
||||||
|
ck_assert_str_eq(eina_content_data_get(c).mem, text_str);
|
||||||
|
}
|
||||||
|
EFL_END_TEST
|
||||||
|
|
||||||
|
EFL_START_TEST(eina_test_content_possible_converstions)
|
||||||
|
{
|
||||||
|
ck_assert_int_eq(eina_content_converter_convert_can("text/plain", "text/plain;charset=utf-8"), 1);
|
||||||
|
ck_assert_int_eq(eina_content_converter_convert_can("text/plain", "ThisDoesNotExist"), 0);
|
||||||
|
ck_assert_int_eq(eina_content_converter_convert_can("ThisDoesNotExist", "text/plain;charset=utf-8"), 0);
|
||||||
|
Eina_Iterator *iterator = eina_content_converter_possible_conversions("text/plain");
|
||||||
|
char *text;
|
||||||
|
int i = 0, j = 0;
|
||||||
|
|
||||||
|
EINA_ITERATOR_FOREACH(iterator, text)
|
||||||
|
{
|
||||||
|
if (eina_streq(text, "text/plain;charset=utf-8"))
|
||||||
|
i ++;
|
||||||
|
if (eina_streq(text, "text/plain;charset=iso-8859-1"))
|
||||||
|
j ++;
|
||||||
|
}
|
||||||
|
ck_assert_int_eq(i, 1);
|
||||||
|
ck_assert_int_eq(j, 1);
|
||||||
|
eina_iterator_free(iterator);
|
||||||
|
}
|
||||||
|
EFL_END_TEST
|
||||||
|
|
||||||
|
static Eina_Bool getting_called = EINA_FALSE;
|
||||||
|
|
||||||
|
static Eina_Content*
|
||||||
|
_test_cb(Eina_Content *content EINA_UNUSED, const char *type EINA_UNUSED)
|
||||||
|
{
|
||||||
|
getting_called = EINA_TRUE;
|
||||||
|
return eina_content_new(eina_content_data_get(content), type);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFL_START_TEST(eina_test_register_illegal)
|
||||||
|
{
|
||||||
|
const char *test_str = "AbCdEfG";
|
||||||
|
eina_content_converter_conversion_register("Test", "Test2", _test_cb);
|
||||||
|
EXPECT_ERROR_START;
|
||||||
|
eina_content_converter_conversion_register("Test", "Test2", _test_cb);
|
||||||
|
EXPECT_ERROR_END;
|
||||||
|
|
||||||
|
Eina_Content *c = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(test_str), "Test");
|
||||||
|
Eina_Content *c2 = eina_content_convert(c, "Test2");
|
||||||
|
ck_assert_ptr_ne(c2, NULL);
|
||||||
|
ck_assert_int_eq(getting_called, EINA_TRUE);
|
||||||
|
}
|
||||||
|
EFL_END_TEST
|
||||||
|
|
||||||
|
EFL_START_TEST(eina_test_content_value)
|
||||||
|
{
|
||||||
|
const char *str_a = "All";
|
||||||
|
const char *str_b = "Out";
|
||||||
|
Eina_Content *a = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(str_a), "text/plain");
|
||||||
|
Eina_Content *b = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(str_b), "text/plain");
|
||||||
|
Eina_Content *c = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(str_a), "text/plain");
|
||||||
|
Eina_Content *d = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(str_a), "Not_Text");
|
||||||
|
Eina_Value *va = eina_value_content_new(a);
|
||||||
|
Eina_Value *vb = eina_value_content_new(b);
|
||||||
|
Eina_Value *vc = eina_value_content_new(c);
|
||||||
|
Eina_Value *vd = eina_value_content_new(d);
|
||||||
|
Eina_Value *vcopy = eina_value_new(EINA_VALUE_TYPE_CONTENT);
|
||||||
|
Eina_Content *content;
|
||||||
|
|
||||||
|
ck_assert_int_eq(eina_value_compare(va, vc), 0);
|
||||||
|
ck_assert_int_ne(eina_value_compare(va, vb), 0);
|
||||||
|
ck_assert_int_ne(eina_value_compare(va, vd), 0);
|
||||||
|
ck_assert_int_eq(eina_value_compare(vd, vd), 0);
|
||||||
|
|
||||||
|
ck_assert_int_eq(eina_value_copy(va, vcopy), 1);
|
||||||
|
ck_assert_int_eq(eina_value_compare(va, vcopy), 0);
|
||||||
|
|
||||||
|
content = eina_value_to_content(vcopy);
|
||||||
|
Eina_Slice slice = eina_content_data_get(content);
|
||||||
|
ck_assert_int_eq(slice.len, strlen(str_a) + 1);
|
||||||
|
ck_assert_str_eq(slice.mem, str_a);
|
||||||
|
|
||||||
|
ck_assert_str_eq(eina_content_type_get(content), "text/plain");
|
||||||
|
eina_content_free(content);
|
||||||
|
}
|
||||||
|
EFL_END_TEST
|
||||||
|
|
||||||
|
EFL_START_TEST(eina_test_content_value_set)
|
||||||
|
{
|
||||||
|
const char *str_a = "All";
|
||||||
|
Eina_Content *a = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(str_a), "text/plain");
|
||||||
|
Eina_Value *acopy = eina_value_new(EINA_VALUE_TYPE_CONTENT);
|
||||||
|
Eina_Content *content;
|
||||||
|
|
||||||
|
eina_value_set(acopy, a);
|
||||||
|
content = eina_value_to_content(acopy);
|
||||||
|
Eina_Slice slice = eina_content_data_get(content);
|
||||||
|
ck_assert_int_eq(slice.len, strlen(str_a) + 1);
|
||||||
|
ck_assert_str_eq(slice.mem, str_a);
|
||||||
|
|
||||||
|
ck_assert_str_eq(eina_content_type_get(content), "text/plain");
|
||||||
|
eina_content_free(content);
|
||||||
|
}
|
||||||
|
EFL_END_TEST
|
||||||
|
|
||||||
|
EFL_START_TEST(eina_test_content_value_convertion)
|
||||||
|
{
|
||||||
|
const char *str_a = "All";
|
||||||
|
const char *str_b = "Out";
|
||||||
|
const char *str_c = "Life";
|
||||||
|
Eina_Content *a = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(str_a), "text/plain;charset=utf-8");
|
||||||
|
Eina_Content *b = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(str_b), "text/plain");
|
||||||
|
Eina_Content *c = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(str_c), "application/x-elementary-markup");
|
||||||
|
Eina_Value *av = eina_value_content_new(a);
|
||||||
|
Eina_Value *bv = eina_value_content_new(b);
|
||||||
|
Eina_Value *cv = eina_value_content_new(c);
|
||||||
|
|
||||||
|
ck_assert_str_eq(eina_value_to_string(av), str_a);
|
||||||
|
ck_assert_str_eq(eina_value_to_string(bv), str_b);
|
||||||
|
ck_assert_str_ne(eina_value_to_string(cv), str_c);
|
||||||
|
}
|
||||||
|
EFL_END_TEST
|
||||||
|
|
||||||
|
void
|
||||||
|
eina_test_abstract_content(TCase *tc)
|
||||||
|
{
|
||||||
|
tcase_add_test(tc, eina_test_content_create_destroy);
|
||||||
|
tcase_add_test(tc, eina_test_content_as_file);
|
||||||
|
tcase_add_test(tc, eina_test_content_convert_none_existing);
|
||||||
|
tcase_add_test(tc, eina_test_content_convert_ascii_to_utf8);
|
||||||
|
tcase_add_test(tc, eina_test_content_convert_ascii_to_latin);
|
||||||
|
tcase_add_test(tc, eina_test_content_convert_utf8_to_latin);
|
||||||
|
tcase_add_test(tc, eina_test_content_possible_converstions);
|
||||||
|
tcase_add_test(tc, eina_test_register_illegal);
|
||||||
|
tcase_add_test(tc, eina_test_content_value);
|
||||||
|
tcase_add_test(tc, eina_test_content_value_set);
|
||||||
|
tcase_add_test(tc, eina_test_content_value_convertion);
|
||||||
|
}
|
|
@ -54,7 +54,8 @@ eina_test_src = files(
|
||||||
'eina_test_slice.c',
|
'eina_test_slice.c',
|
||||||
'eina_test_freeq.c',
|
'eina_test_freeq.c',
|
||||||
'eina_test_slstr.c',
|
'eina_test_slstr.c',
|
||||||
'eina_test_vpath.c'
|
'eina_test_vpath.c',
|
||||||
|
'eina_test_abstract_content.c',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,12 @@ EFL_START_TEST(text_cnp)
|
||||||
}
|
}
|
||||||
EFL_END_TEST
|
EFL_END_TEST
|
||||||
|
|
||||||
|
static void
|
||||||
|
_stop_event_soon(void *data EINA_UNUSED, const Efl_Event *ev)
|
||||||
|
{
|
||||||
|
efl_event_callback_stop(ev->object);
|
||||||
|
}
|
||||||
|
|
||||||
EFL_START_TEST(text_all_select_all_unselect)
|
EFL_START_TEST(text_all_select_all_unselect)
|
||||||
{
|
{
|
||||||
Eo *txt;
|
Eo *txt;
|
||||||
|
@ -57,7 +63,7 @@ EFL_START_TEST(text_all_select_all_unselect)
|
||||||
efl_event_callback_add(efl_added, EFL_TEXT_INTERACTIVE_EVENT_SELECTION_CHANGED,
|
efl_event_callback_add(efl_added, EFL_TEXT_INTERACTIVE_EVENT_SELECTION_CHANGED,
|
||||||
increment_int_changed, &i_selection)
|
increment_int_changed, &i_selection)
|
||||||
);
|
);
|
||||||
|
efl_event_callback_priority_add(txt, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, _stop_event_soon, NULL);
|
||||||
efl_text_set(txt, "Hello");
|
efl_text_set(txt, "Hello");
|
||||||
efl_text_interactive_all_select(txt);
|
efl_text_interactive_all_select(txt);
|
||||||
Efl_Text_Cursor *c1=NULL, *c2 =NULL;
|
Efl_Text_Cursor *c1=NULL, *c2 =NULL;
|
||||||
|
@ -122,6 +128,7 @@ EFL_START_TEST(text_selection)
|
||||||
Eo *win = win_add();
|
Eo *win = win_add();
|
||||||
|
|
||||||
txt = efl_add(EFL_UI_TEXTBOX_CLASS, win);
|
txt = efl_add(EFL_UI_TEXTBOX_CLASS, win);
|
||||||
|
efl_event_callback_priority_add(txt, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, _stop_event_soon, NULL);
|
||||||
efl_gfx_entity_size_set(txt, EINA_SIZE2D(300, 300));
|
efl_gfx_entity_size_set(txt, EINA_SIZE2D(300, 300));
|
||||||
efl_text_set(txt, "Hello");
|
efl_text_set(txt, "Hello");
|
||||||
get_me_to_those_events(txt);
|
get_me_to_those_events(txt);
|
||||||
|
@ -160,7 +167,7 @@ EFL_START_TEST(text_user_change)
|
||||||
txt = efl_add(EFL_UI_TEXTBOX_CLASS, win,
|
txt = efl_add(EFL_UI_TEXTBOX_CLASS, win,
|
||||||
efl_event_callback_add(efl_added, EFL_TEXT_INTERACTIVE_EVENT_CHANGED_USER, user_changed, &info)
|
efl_event_callback_add(efl_added, EFL_TEXT_INTERACTIVE_EVENT_CHANGED_USER, user_changed, &info)
|
||||||
);
|
);
|
||||||
|
efl_event_callback_priority_add(txt, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, _stop_event_soon, NULL);
|
||||||
efl_text_set(txt, "Hello");
|
efl_text_set(txt, "Hello");
|
||||||
efl_gfx_entity_size_set(txt, EINA_SIZE2D(300, 300));
|
efl_gfx_entity_size_set(txt, EINA_SIZE2D(300, 300));
|
||||||
efl_text_interactive_all_select(txt);
|
efl_text_interactive_all_select(txt);
|
||||||
|
@ -177,6 +184,7 @@ EFL_START_TEST(text_scroll_mode)
|
||||||
Eo *txt, *win, *cur;
|
Eo *txt, *win, *cur;
|
||||||
win = win_add();
|
win = win_add();
|
||||||
txt = efl_add(EFL_UI_TEXTBOX_CLASS, win);
|
txt = efl_add(EFL_UI_TEXTBOX_CLASS, win);
|
||||||
|
efl_event_callback_priority_add(txt, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, _stop_event_soon, NULL);
|
||||||
cur = efl_text_interactive_main_cursor_get(txt);
|
cur = efl_text_interactive_main_cursor_get(txt);
|
||||||
efl_text_set(txt, "Hello");
|
efl_text_set(txt, "Hello");
|
||||||
/*scroll mode is false by default*/
|
/*scroll mode is false by default*/
|
||||||
|
@ -199,6 +207,7 @@ EFL_START_TEST(text_change_event)
|
||||||
Eo *win = win_add();
|
Eo *win = win_add();
|
||||||
|
|
||||||
txt = efl_add(EFL_UI_TEXTBOX_CLASS, win);
|
txt = efl_add(EFL_UI_TEXTBOX_CLASS, win);
|
||||||
|
efl_event_callback_priority_add(txt, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, _stop_event_soon, NULL);
|
||||||
efl_gfx_entity_size_set(txt, EINA_SIZE2D(300, 300));
|
efl_gfx_entity_size_set(txt, EINA_SIZE2D(300, 300));
|
||||||
efl_text_set(txt, "Hello");
|
efl_text_set(txt, "Hello");
|
||||||
int i_changed = 0;
|
int i_changed = 0;
|
||||||
|
@ -223,6 +232,7 @@ EFL_START_TEST(text_keys_handler)
|
||||||
Eo *win = win_add();
|
Eo *win = win_add();
|
||||||
|
|
||||||
txt = efl_add(EFL_UI_TEXTBOX_CLASS, win);
|
txt = efl_add(EFL_UI_TEXTBOX_CLASS, win);
|
||||||
|
efl_event_callback_priority_add(txt, EFL_UI_SELECTION_EVENT_WM_SELECTION_CHANGED, EFL_CALLBACK_PRIORITY_BEFORE, _stop_event_soon, NULL);
|
||||||
efl_gfx_entity_size_set(txt, EINA_SIZE2D(300, 300));
|
efl_gfx_entity_size_set(txt, EINA_SIZE2D(300, 300));
|
||||||
efl_text_set(txt, "Hello");
|
efl_text_set(txt, "Hello");
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,191 @@
|
||||||
|
#define EFL_BETA_API_SUPPORT 1
|
||||||
|
|
||||||
|
#include <Efl.h>
|
||||||
|
#include <Efl_Ui.h>
|
||||||
|
#include <Elementary.h>
|
||||||
|
#include "efl_ui_grid_view.eo.h"
|
||||||
|
|
||||||
|
static Ecore_Evas *ee;
|
||||||
|
|
||||||
|
static Eina_Value
|
||||||
|
_deliverty_cb(void *data, const Eina_Value value, const Eina_Future *dead_future EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Ecore_Evas_Selection_Buffer buffer = (intptr_t)data;
|
||||||
|
Eina_Content *content;
|
||||||
|
|
||||||
|
if (eina_value_type_get(&value) != EINA_VALUE_TYPE_CONTENT)
|
||||||
|
{
|
||||||
|
char *error = eina_value_to_string(&value);
|
||||||
|
printf("Value not a content, message: \"%s\"\n", error);
|
||||||
|
return EINA_VALUE_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
content = eina_value_to_content(&value);
|
||||||
|
printf("Got Content of selection %d with type %s\n", buffer, eina_content_type_get(content));
|
||||||
|
if (!strncmp(eina_content_type_get(content), "text", strlen("text")))
|
||||||
|
{
|
||||||
|
printf("Content: %s\n", (char*)eina_content_data_get(content).mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINA_VALUE_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_selection_changed(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection)
|
||||||
|
{
|
||||||
|
printf("Selection %d of %p has changed\n", selection, ee);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_request_selection(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Ecore_Evas_Selection_Buffer selection)
|
||||||
|
{
|
||||||
|
const char *types[] = {eina_stringshare_add("text/plain"), eina_stringshare_add("text/plain;charset=utf-8")};
|
||||||
|
printf("Selection %d of %p has changed\n", selection, ee);
|
||||||
|
Eina_Future *future = ecore_evas_selection_get(ee, 0, selection, EINA_C_ARRAY_ITERATOR_NEW(types));
|
||||||
|
eina_future_then(future, _deliverty_cb, .data = ((void*)(intptr_t)selection));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_motion_cb(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Eina_Position2D p)
|
||||||
|
{
|
||||||
|
printf("Drag and Drop has moved on the window %p (%d, %d)\n", ee, p.x, p.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_enter_state_change_cb(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Eina_Position2D p, Eina_Bool inside)
|
||||||
|
{
|
||||||
|
if (inside)
|
||||||
|
printf("Drag and Drop has entered the window %p (%d, %d)\n", ee, p.x, p.y);
|
||||||
|
else
|
||||||
|
printf("Drag and Drop has left the window %p (%d, %d)\n", ee, p.x, p.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_drop_cb(Ecore_Evas *ee, unsigned int seat EINA_UNUSED, Eina_Position2D p, const char *action EINA_UNUSED)
|
||||||
|
{
|
||||||
|
const char *types[] = {eina_stringshare_add("text/plain")};
|
||||||
|
printf("Drag and Drop has droped on the window %p (%d, %d)\n", ee, p.x, p.y);
|
||||||
|
Eina_Future *f = ecore_evas_selection_get(ee, 0, ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER, EINA_C_ARRAY_ITERATOR_NEW(types));
|
||||||
|
eina_future_then(f, _deliverty_cb, .data = ((void*)(intptr_t)ECORE_EVAS_SELECTION_BUFFER_DRAG_AND_DROP_BUFFER));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_efl_ui_terminated(Ecore_Evas *ee EINA_UNUSED, unsigned int seat EINA_UNUSED, void *data, Eina_Bool accepted EINA_UNUSED)
|
||||||
|
{
|
||||||
|
efl_del(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eo*
|
||||||
|
_start_dnd(Ecore_Evas *ee)
|
||||||
|
{
|
||||||
|
Ecore_Evas *ee2;
|
||||||
|
Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL("This is sample content"), "text/plain");
|
||||||
|
Efl_Ui_Win *win;
|
||||||
|
Efl_Ui_Button *btn;
|
||||||
|
|
||||||
|
win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get());
|
||||||
|
ee2 = ecore_evas_ecore_evas_get(evas_object_evas_get(win));
|
||||||
|
|
||||||
|
btn = efl_add(EFL_UI_BUTTON_CLASS, win);
|
||||||
|
efl_text_set(btn, "Test");
|
||||||
|
efl_content_set(win, btn);
|
||||||
|
|
||||||
|
evas_object_geometry_set(win, 0, 0, 100, 100);
|
||||||
|
|
||||||
|
ecore_evas_drag_start(ee, 0, content, ee2, "copy", _efl_ui_terminated, win);
|
||||||
|
|
||||||
|
return win;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_start_op(void *data, const Efl_Event *ev EINA_UNUSED)
|
||||||
|
{
|
||||||
|
_start_dnd(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Value
|
||||||
|
_delete_cb(Eo *obj, void *data EINA_UNUSED, const Eina_Value value EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Ecore_Evas *ee ;
|
||||||
|
ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
|
||||||
|
|
||||||
|
ecore_evas_drag_cancel(ee, 0);
|
||||||
|
|
||||||
|
return EINA_VALUE_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_start_delayed_del_op(void *data, const Efl_Event *ev EINA_UNUSED)
|
||||||
|
{
|
||||||
|
_start_dnd(data);
|
||||||
|
efl_future_then(ev->object, efl_loop_timeout(efl_main_loop_get(), 2.0), _delete_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI_MAIN void
|
||||||
|
efl_main(void *data EINA_UNUSED, const Efl_Event *ev)
|
||||||
|
{
|
||||||
|
Efl_Ui_Textbox *txt, *win, *bx, *btn;
|
||||||
|
Efl_Loop_Arguments *args = ev->info;
|
||||||
|
char *goal;
|
||||||
|
|
||||||
|
win = efl_add(EFL_UI_WIN_CLASS, efl_main_loop_get());
|
||||||
|
ee = ecore_evas_ecore_evas_get(evas_object_evas_get(win));
|
||||||
|
|
||||||
|
bx = efl_add(EFL_UI_BOX_CLASS, win);
|
||||||
|
|
||||||
|
txt = efl_add(EFL_UI_TEXTBOX_CLASS, win);
|
||||||
|
efl_text_set(txt, "Sample for CNP and DND interaction");
|
||||||
|
efl_pack_end(bx, txt);
|
||||||
|
|
||||||
|
btn = efl_add(EFL_UI_BUTTON_CLASS, win);
|
||||||
|
efl_gfx_hint_weight_set(btn, 1.0, 0.0);
|
||||||
|
efl_event_callback_add(btn, EFL_INPUT_EVENT_PRESSED, _start_op, ee);
|
||||||
|
efl_text_set(btn, "Start DND op");
|
||||||
|
efl_pack_end(bx, btn);
|
||||||
|
|
||||||
|
btn = efl_add(EFL_UI_BUTTON_CLASS, win);
|
||||||
|
efl_gfx_hint_weight_set(btn, 1.0, 0.0);
|
||||||
|
efl_event_callback_add(btn, EFL_INPUT_EVENT_PRESSED, _start_delayed_del_op, ee);
|
||||||
|
efl_text_set(btn, "Start DND op self destroy after 2 sec");
|
||||||
|
efl_pack_end(bx, btn);
|
||||||
|
|
||||||
|
efl_content_set(win, bx);
|
||||||
|
efl_gfx_entity_size_set(win, EINA_SIZE2D(320, 320));
|
||||||
|
|
||||||
|
goal = eina_array_data_get(args->argv, 1);
|
||||||
|
|
||||||
|
if (eina_streq(goal, "--monitor"))
|
||||||
|
{
|
||||||
|
ecore_evas_callback_selection_changed_set(ee, _selection_changed);
|
||||||
|
ecore_evas_callback_drop_drop_set(ee, _drop_cb);
|
||||||
|
ecore_evas_callback_drop_motion_set(ee, _motion_cb);
|
||||||
|
ecore_evas_callback_drop_state_changed_set(ee, _enter_state_change_cb);
|
||||||
|
}
|
||||||
|
else if (eina_streq(goal, "--show-selections"))
|
||||||
|
{
|
||||||
|
ecore_evas_callback_selection_changed_set(ee, _request_selection);
|
||||||
|
}
|
||||||
|
else if (eina_streq(goal, "--set-selection"))
|
||||||
|
{
|
||||||
|
if (eina_array_count(args->argv) < 3)
|
||||||
|
{
|
||||||
|
printf("Error, --set-selection only requires exactly 1 keyword (The selection to set).\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char *selection = eina_array_data_get(args->argv, 2);
|
||||||
|
Eina_Content *content = eina_content_new((Eina_Slice)EINA_SLICE_STR_FULL(selection), "text/plain");
|
||||||
|
ecore_evas_selection_set(ee, 0, ECORE_EVAS_SELECTION_BUFFER_COPY_AND_PASTE_BUFFER, content);
|
||||||
|
}
|
||||||
|
else if (eina_streq(goal, "--show-owner"))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ECORE_EVAS_SELECTION_BUFFER_LAST; ++i)
|
||||||
|
{
|
||||||
|
printf("Selection buffer %d : %d\n", i, ecore_evas_selection_exists(ee, 0, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Error, goal %s not found\n", goal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EFL_MAIN()
|
|
@ -187,6 +187,11 @@ efl_ui_compile_test = executable('efl_ui_compile_test',
|
||||||
dependencies: [elementary, eio],
|
dependencies: [elementary, eio],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
executable('efl_ui_window_cnp_dnd_slave',
|
||||||
|
'efl_ui_window_cnp_dnd_slave.c',
|
||||||
|
dependencies: [elementary],
|
||||||
|
)
|
||||||
|
|
||||||
test('elementary-suite', elementary_suite,
|
test('elementary-suite', elementary_suite,
|
||||||
env : test_env
|
env : test_env
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue