Ewl_Dnd: The files containing DND functions
Detailed Description
Tutorial
In order to make DND handling easier for the end programmer, we've added a simplification API to EWL. It currently supports receiving drops and some limited dragging of widgets. Getting started is fairly simple, even for some rather complicated widgets. As an example, I'll run through the DND support added to the entry widget.The first step to setup DND support on a widget is to decide which MIME types are allowed and understood by the widget. The entry displays text, so accepting the type "text/plain" is a safe choice. A NULL terminated list of type strings is passed to the ewl_dnd_accepted_types_set, which enables DND responses for the widget and helps to negotiate whether a drop will be accepted at a given position.
const char *text_types[] = { "text/plain", NULL }; ewl_dnd_accepted_types_set(EWL_WIDGET(e), text_types);
One key feature for DND support in the entry widget was to allow dragging text to arbitrary positions within the visible text area. This is accomplished by registering a callback for the EWL_CALLBACK_DND_POSITION event on the entry widget.
When the mouse moves during a DND event over the specified entry w the ewl_entry_cb_dnd_position function will be called. This function prototype looks like all other EWL callback prototypes:
void ewl_entry_cb_dnd_position(Ewl_Widget *w, void *ev, void *data);
In this case, the void *ev parameter points to a Ewl_Event_Dnd_Position struct, which contains more detailed information about the event. We can use the coordinates from the event to position the cursor within our entry to receive the dropped data. Since the entry widget inherits from the text widget, the text calls are used directly on the widget to alter the entry contents. The code to accomplish this is rather small when the extra debugging information is removed:
void ewl_entry_cb_dnd_position(Ewl_Widget *w, void *ev, void *data) { Ewl_Event_Dnd_Position *event; Ewl_Text *txt; event = ev; txt = EWL_TEXT(w); if (EWL_ENTRY(w)->editable && !DISABLED(w)) { ewl_widget_focus_send(w); ewl_text_cursor_position_set(txt, ewl_text_coord_index_map(txt, event->x, event->y)); } }
Once the cursor has been positioned, the only event we care about is receiving the data from the drop. This is accomplished by using the EWL_CALLBACK_DND_DATA_RECEIVED callback which should also be placed on the entry widget.
The function prototype for ewl_entry_cb_dnd_data is identical to ewl_entry_cb_dnd_position, but the void *ev parameter is of type Ewl_Event_Dnd_Data. Since we only registered to receive plain text data dropped on the entry, we can insert the event data directly into the entry at the current cursor position.
void ewl_entry_cb_dnd_data(Ewl_Widget *w, void *ev, void *data) { Ewl_Event_Dnd_Data *event; Ewl_Text *txt; event = ev; txt = EWL_TEXT(w); if (EWL_ENTRY(w)->editable && !DISABLED(w)) { ewl_text_text_insert(txt, event->data, ewl_text_cursor_position_get(txt)); } }
Considering the complicated nature of the Xdnd protocol, we are able to accomplish a considerable amount of work in very few lines of code. While some flexibility is sacrificed to achieve this, almost all of the protocol events are available for widgets to override as they please.
Check back for followup information to handle drag events on widgets.
Functions | |
| int | ewl_dnd_accepted_types_contains (Ewl_Widget *w, char *type) |
| : Verifies the specified widget accepts the given mimetype | |
| char ** | ewl_dnd_accepted_types_get (Ewl_Widget *w) |
| : Gets the mimetypes the designated widget can accept for DND | |
| void | ewl_dnd_accepted_types_set (Ewl_Widget *w, const char **types) |
| : Sets the mimetypes the designated widget can accept for DND | |
| void | ewl_dnd_disable (void) |
| Disables DND. | |
| void | ewl_dnd_drag_data_send (Ewl_Embed *emb, void *handle, void *data, int len) |
| void | ewl_dnd_drag_drop (Ewl_Widget *w) |
| Tells the widget to drop its data. | |
| void | ewl_dnd_drag_widget_clear (void) |
| Clears the current DND widget. | |
| Ewl_Widget * | ewl_dnd_drag_widget_get (void) |
| Retrieves the current DND widget. | |
| void | ewl_dnd_enable (void) |
| Enables DND. | |
| void | ewl_dnd_external_drag_start (Ewl_Widget *w) |
| Creates the proper condition for external dragging. | |
| int | ewl_dnd_init (void) |
| void | ewl_dnd_internal_drag_start (Ewl_Widget *w) |
| Creates the proper condition for internal dragging. | |
| int | ewl_dnd_provided_types_contains (Ewl_Widget *w, char *type) |
| : Verifies the specified widget provides the given mimetype | |
| char ** | ewl_dnd_provided_types_get (Ewl_Widget *w) |
| : Gets the mimetypes the designated widget can provide for DND | |
| void | ewl_dnd_provided_types_set (Ewl_Widget *w, const char **types) |
| : Sets the mimetypes the designated widget can provide for DND | |
| void | ewl_dnd_shutdown (void) |
| int | ewl_dnd_status_get (void) |
| Retrieves the current DND status. | |
Variables | |
| unsigned int | EWL_CALLBACK_DND_DATA_RECEIVED |
| unsigned int | EWL_CALLBACK_DND_DATA_REQUEST |
| unsigned int | EWL_CALLBACK_DND_DROP |
| unsigned int | EWL_CALLBACK_DND_ENTER |
| unsigned int | EWL_CALLBACK_DND_LEAVE |
| unsigned int | EWL_CALLBACK_DND_POSITION |
| unsigned int | EWL_CALLBACK_SELECTION_CLEAR |
Function Documentation
| int ewl_dnd_accepted_types_contains | ( | Ewl_Widget * | w, | |
| char * | type | |||
| ) |
: Verifies the specified widget accepts the given mimetype
- Parameters:
-
w,: The widget to test for an accepted type type,: The mimetype to test for acceptance on a specific widget
- Returns:
- Returns TRUE if the widget accepts the given type, FALSE otherwise
References DCHECK_PARAM_PTR_RET, DCHECK_TYPE_RET, DENTER_FUNCTION, DLEVEL_STABLE, DRETURN_INT, and EWL_WIDGET_TYPE.
Referenced by ewl_dnd_drag_drop(), ewl_embed_dnd_data_received_feed(), ewl_embed_dnd_drop_feed(), and ewl_embed_dnd_position_feed().
| char** ewl_dnd_accepted_types_get | ( | Ewl_Widget * | w | ) |
: Gets the mimetypes the designated widget can accept for DND
- Parameters:
-
w,: The widget to retrieve accepted types
- Returns:
- Returns a NULL terminated array of mimetypes widget accepts for DND
References DCHECK_PARAM_PTR_RET, DCHECK_TYPE_RET, DENTER_FUNCTION, DLEVEL_STABLE, DRETURN_PTR, and EWL_WIDGET_TYPE.
| void ewl_dnd_accepted_types_set | ( | Ewl_Widget * | w, | |
| const char ** | types | |||
| ) |
: Sets the mimetypes the designated widget can accept for DND
- Parameters:
-
w,: The widget to set accepted types types,: A NULL terminated array of mimetypes widget accepts for DND
- Returns:
- Returns no value
References DCHECK_PARAM_PTR, DCHECK_TYPE, DENTER_FUNCTION, DLEAVE_FUNCTION, DLEVEL_STABLE, ewl_embed_dnd_aware_remove(), ewl_embed_dnd_aware_set(), ewl_embed_widget_find(), EWL_FLAG_PROPERTY_DND_TARGET, EWL_FLAGS_PROPERTY_MASK, ewl_widget_flags_add(), ewl_widget_flags_remove(), EWL_WIDGET_TYPE, IF_FREE, REALIZED, and REVEALED.
Referenced by ewl_colorpicker_init(), and ewl_entry_init().
| void ewl_dnd_disable | ( | void | ) |
Disables DND.
- Returns:
- Returns no value
References DENTER_FUNCTION, DLEAVE_FUNCTION, and DLEVEL_STABLE.
| void ewl_dnd_drag_data_send | ( | Ewl_Embed * | emb, | |
| void * | handle, | |||
| void * | data, | |||
| int | len | |||
| ) |
- Parameters:
-
emb,: Embed to send to handle,: Handle to the window data,: Data to send len,: The size of the data
References DCHECK_PARAM_PTR, DENTER_FUNCTION, DLEVEL_STABLE, DRETURN, EWL_DRAGGING_INTERNAL, and ewl_engine_embed_dnd_drag_data_send().
| void ewl_dnd_drag_drop | ( | Ewl_Widget * | w | ) |
Tells the widget to drop its data.
- Parameters:
-
w,: The widget to stop dragging
- Returns:
- Returns no value
References DCHECK_PARAM_PTR, DCHECK_TYPE, DENTER_FUNCTION, DLEAVE_FUNCTION, DLEVEL_STABLE, Ewl_Embed::drag_widget, DRETURN, Ewl_Embed::drop_widget, DWARNING, ewl_attach_list_del(), EWL_ATTACH_TYPE_MOUSE_ARGB_CURSOR, ewl_callback_call_with_event_data(), EWL_CALLBACK_DND_DATA_REQUEST, ewl_dnd_accepted_types_contains(), ewl_dnd_provided_types_get(), EWL_DRAGGING_EXTERNAL, EWL_DRAGGING_INTERNAL, EWL_DRAGGING_NONE, ewl_embed_dnd_data_received_feed(), ewl_embed_mouse_cursor_set(), ewl_embed_widget_find(), ewl_engine_embed_dnd_drag_drop(), EWL_WIDGET, EWL_WIDGET_TYPE, Ewl_Embed::last, and Ewl_Event_Dnd_Data_Request::type.
Referenced by ewl_widget_cb_mouse_up().
| void ewl_dnd_drag_widget_clear | ( | void | ) |
Clears the current DND widget.
- Returns:
- Returns no value.
References DENTER_FUNCTION, DLEAVE_FUNCTION, and DLEVEL_STABLE.
Referenced by ewl_embed_dnd_drop_feed().
| Ewl_Widget* ewl_dnd_drag_widget_get | ( | void | ) |
Retrieves the current DND widget.
- Returns:
- Returns the current DND widget
References DENTER_FUNCTION, DLEVEL_STABLE, and DRETURN_PTR.
| void ewl_dnd_enable | ( | void | ) |
Enables DND.
- Returns:
- Returns no value
References DENTER_FUNCTION, DLEAVE_FUNCTION, and DLEVEL_STABLE.
| void ewl_dnd_external_drag_start | ( | Ewl_Widget * | w | ) |
Creates the proper condition for external dragging.
- Parameters:
-
w,: The widget to start dragging
- Returns:
- Returns no value
References DCHECK_PARAM_PTR, DCHECK_TYPE, DENTER_FUNCTION, DLEAVE_FUNCTION, DLEVEL_STABLE, DRETURN, ewl_dnd_provided_types_get(), EWL_DRAGGING_EXTERNAL, EWL_DRAGGING_INTERNAL, ewl_embed_widget_find(), ewl_engine_embed_dnd_drag_start(), ewl_engine_embed_dnd_drag_types_set(), and EWL_WIDGET_TYPE.
Referenced by ewl_embed_mouse_out_feed().
| int ewl_dnd_init | ( | void | ) |
References DENTER_FUNCTION, DLEVEL_STABLE, DRETURN_INT, EWL_CALLBACK_DND_DATA_RECEIVED, EWL_CALLBACK_DND_DATA_REQUEST, EWL_CALLBACK_DND_DROP, EWL_CALLBACK_DND_ENTER, EWL_CALLBACK_DND_LEAVE, EWL_CALLBACK_DND_POSITION, EWL_CALLBACK_SELECTION_CLEAR, ewl_callback_type_add(), EWL_DRAGGING_NONE, and IF_FREE_HASH.
Referenced by ewl_init().
| void ewl_dnd_internal_drag_start | ( | Ewl_Widget * | w | ) |
Creates the proper condition for internal dragging.
- Parameters:
-
w,: The widget to start dragging
- Returns:
- Returns no value
References DCHECK_PARAM_PTR, DCHECK_TYPE, DENTER_FUNCTION, DLEAVE_FUNCTION, DLEVEL_STABLE, DRETURN, ewl_attach_mouse_argb_cursor_set, ewl_cursor_new(), EWL_DRAGGING_INTERNAL, ewl_embed_mouse_cursor_set(), ewl_embed_widget_find(), EWL_WIDGET, ewl_widget_appearance_set(), ewl_widget_show(), and EWL_WIDGET_TYPE.
Referenced by ewl_widget_cb_mouse_move().
| int ewl_dnd_provided_types_contains | ( | Ewl_Widget * | w, | |
| char * | type | |||
| ) |
: Verifies the specified widget provides the given mimetype
- Parameters:
-
w,: The widget to test for an provided type type,: The mimetype to test for provideance on a specific widget
- Returns:
- Returns TRUE if the types contains the given type, FALSE otherwise
References DCHECK_PARAM_PTR_RET, DCHECK_TYPE_RET, DENTER_FUNCTION, DLEVEL_STABLE, DRETURN_INT, and EWL_WIDGET_TYPE.
Referenced by ewl_embed_dnd_data_request_feed().
| char** ewl_dnd_provided_types_get | ( | Ewl_Widget * | w | ) |
: Gets the mimetypes the designated widget can provide for DND
- Parameters:
-
w,: The widget to retrieve provided types
- Returns:
- Returns a NULL terminated array of mimetypes widget provides for DND
References DCHECK_PARAM_PTR_RET, DCHECK_TYPE_RET, DENTER_FUNCTION, DLEVEL_STABLE, DRETURN_PTR, and EWL_WIDGET_TYPE.
Referenced by ewl_dnd_drag_drop(), and ewl_dnd_external_drag_start().
| void ewl_dnd_provided_types_set | ( | Ewl_Widget * | w, | |
| const char ** | types | |||
| ) |
: Sets the mimetypes the designated widget can provide for DND
- Parameters:
-
w,: The widget to set provided types types,: A NULL terminated array of mimetypes widget provides for DND
- Returns:
- Returns no value
References DCHECK_PARAM_PTR, DCHECK_TYPE, DENTER_FUNCTION, DLEAVE_FUNCTION, DLEVEL_STABLE, EWL_FLAG_PROPERTY_DND_SOURCE, EWL_FLAGS_PROPERTY_MASK, ewl_widget_flags_add(), ewl_widget_flags_remove(), EWL_WIDGET_TYPE, and IF_FREE.
Referenced by ewl_filelist_view_widget_fetch().
| void ewl_dnd_shutdown | ( | void | ) |
References DENTER_FUNCTION, DLEAVE_FUNCTION, DLEVEL_STABLE, and IF_FREE_HASH.
Referenced by ewl_init().
| int ewl_dnd_status_get | ( | void | ) |
Retrieves the current DND status.
- Returns:
- Returns the current DND status
References DENTER_FUNCTION, DLEVEL_STABLE, and DRETURN_INT.
Variable Documentation
| unsigned int EWL_CALLBACK_DND_DATA_RECEIVED |
Data received event
Referenced by ewl_colorpicker_init(), ewl_dnd_init(), ewl_embed_dnd_data_received_feed(), and ewl_entry_init().
| unsigned int EWL_CALLBACK_DND_DATA_REQUEST |
Data request event
Referenced by ewl_dnd_drag_drop(), ewl_dnd_init(), ewl_embed_dnd_data_request_feed(), and ewl_filelist_view_widget_fetch().
| unsigned int EWL_CALLBACK_DND_DROP |
Drop event
Referenced by ewl_dnd_init(), and ewl_embed_dnd_drop_feed().
| unsigned int EWL_CALLBACK_DND_ENTER |
On enter of a widget
Referenced by ewl_dnd_init(), and ewl_embed_dnd_position_feed().
| unsigned int EWL_CALLBACK_DND_LEAVE |
On exit of a widget
Referenced by ewl_dnd_init(), and ewl_embed_dnd_position_feed().
| unsigned int EWL_CALLBACK_DND_POSITION |
A DND position event
Referenced by ewl_dnd_init(), ewl_embed_dnd_position_feed(), and ewl_entry_init().
| unsigned int EWL_CALLBACK_SELECTION_CLEAR |
Selection clear event
Referenced by ewl_dnd_init(), ewl_embed_selection_text_clear_feed(), and ewl_text_selectable_set().