command: add dropped-file property

This adds dropped-file property which contains a list of dropped files
and the type of the drop. This allows clients to implement custom drag
and drop handling.
This commit is contained in:
nanahi
2026-03-30 19:45:56 -04:00
committed by Kacper Michajłow
parent e12ab84571
commit 87ccb6022c
7 changed files with 115 additions and 2 deletions
+1
View File
@@ -1 +1,2 @@
add `--input-builtin-drag-and-drop` option
add `dropped-file` property
+33
View File
@@ -3231,6 +3231,39 @@ Property list
"pad-btns" MPV_FORMAT_NODE_MAP
(key and string value for each pad-btn entry)
``dropped-files``
Information of the most recent drag-and-drop event mpv received. This
property is only updated when ``--input-builtin-drag-and-drop=no``.
A client can observe this property to detect when a drag-and-drop event
happens. This property is unavailable if no drag-and-drop event has
happened.
Has the following sub-properties:
``dropped-files/time``
The timestamp of the last drag-and-drop event mpv received, in
nanoseconds. This uses the same clock as ``mpv_get_time_ns()``.
``dropped-files/action``
The action of the drag-and-drop event, can be one of ``replace``,
``append``, or ``insert-next``. This is affected by the
``--drag-and-drop`` option.
``dropped-files/files``
The dropped file names of the drag-and-drop event.
When querying the property with the client API using ``MPV_FORMAT_NODE``,
or with Lua ``mp.get_property_native``, this will return a mpv_node with
the following contents:
::
MPV_FORMAT_NODE_MAP
"time" MPV_FORMAT_INT64
"action" MPV_FORMAT_STRING
"files" MPV_FORMAT_NODE_ARRAY
MPV_FORMAT_STRING
``sub-ass-extradata``
The current ASS subtitle track's extradata. There is no formatting done.
The extradata is returned as a string as-is. This property is not
+2 -1
View File
@@ -4454,7 +4454,8 @@ Input
``--input-builtin-drag-and-drop=<yes|no>``
Enable the built-in drag-and-drop behavior (default: yes). Setting it to no
disables the built-in drag-and-drop handling.
disables the built-in drag-and-drop handling and enables the ``dropped-files``
property, which can be used to retrieve information about dropped files.
``--input-cmdlist``
Prints all commands that can be bound to keys.
+1
View File
@@ -25,6 +25,7 @@ enum mp_dnd_action {
DND_REPLACE,
DND_APPEND,
DND_INSERT_NEXT,
DND_NONE,
};
// Drop data in a specific format (identified by the mimetype).
+33
View File
@@ -160,6 +160,12 @@ struct input_ctx {
struct touch_point *touch_points;
int num_touch_points;
// List of last dropped files
int64_t dnd_ts;
enum mp_dnd_action dnd_action;
bstr *dropped_files;
int num_dropped_files;
int tablet_x, tablet_y;
// Indicates tablet tools in proximity / close to tablet surface
bool tablet_tool_in_proximity;
@@ -1286,6 +1292,15 @@ void mp_input_drop_files(struct input_ctx *ictx, int num_files, char **files,
{
input_lock(ictx);
if (!ictx->opts->builtin_dnd) {
TA_FREEP(&ictx->dropped_files);
ictx->dropped_files = talloc_zero_array(ictx, bstr, num_files);
ictx->num_dropped_files = num_files;
ictx->dnd_ts = mp_time_ns();
ictx->dnd_action = action;
for (int i = 0; i < num_files; i++)
ictx->dropped_files[i] = bstrdup(ictx->dropped_files, bstr0(files[i]));
notify_event_update(ictx);
input_unlock(ictx);
return;
}
@@ -1336,6 +1351,23 @@ void mp_input_drop_files(struct input_ctx *ictx, int num_files, char **files,
input_unlock(ictx);
}
void mp_input_get_dropped_files(struct input_ctx *ictx, void *talloc_ctx,
int64_t *dnd_ts,
enum mp_dnd_action *dnd_action,
char ***dropped_files)
{
input_lock(ictx);
*dnd_ts = ictx->dnd_ts;
*dnd_action = ictx->dnd_action;
*dropped_files = NULL;
int num = 0;
for (int i = 0; i < ictx->num_dropped_files; i++)
MP_TARRAY_APPEND(talloc_ctx, *dropped_files, num,
bstrto0(talloc_ctx, ictx->dropped_files[i]));
MP_TARRAY_APPEND(talloc_ctx, *dropped_files, num, NULL);
input_unlock(ictx);
}
unsigned int mp_input_get_mouse_event_counter(struct input_ctx *ictx)
{
// Make the frontend always display the mouse cursor (as long as it's not
@@ -1746,6 +1778,7 @@ struct input_ctx *mp_input_init(struct mpv_global *global,
.wakeup_ctx = wakeup_ctx,
.active_sections = talloc_array(ictx, struct active_section, 0),
.touch_points = talloc_array(ictx, struct touch_point, 0),
.dnd_action = DND_NONE,
};
ictx->opts = ictx->opts_cache->opts;
+5
View File
@@ -209,6 +209,11 @@ bool mp_input_test_dragging(struct input_ctx *ictx, int x, int y);
// Enqueue files for playback after drag and drop
void mp_input_drop_files(struct input_ctx *ictx, int num_files, char **files,
enum mp_dnd_action action);
// Last dropped files
void mp_input_get_dropped_files(struct input_ctx *ictx, void *talloc_ctx,
int64_t *dnd_ts,
enum mp_dnd_action *dnd_action,
char ***dropped_files);
// Initialize the input system
struct mpv_global;
+40 -1
View File
@@ -3267,6 +3267,44 @@ static int mp_property_tablet_pos(void *ctx, struct m_property *prop,
return M_PROPERTY_NOT_IMPLEMENTED;
}
static int mp_property_dropped_files(void *ctx, struct m_property *prop,
int action, void *arg)
{
MPContext *mpctx = ctx;
int valid = m_property_read_sub_validate(ctx, prop, action, arg);
if (valid != M_PROPERTY_VALID)
return valid;
int64_t dnd_ts;
enum mp_dnd_action dnd_action;
char **dropped_files;
void *talloc_ctx = talloc_new(NULL);
mp_input_get_dropped_files(mpctx->input, talloc_ctx, &dnd_ts,
&dnd_action, &dropped_files);
int r = M_PROPERTY_UNAVAILABLE;
if (dnd_action == DND_NONE)
goto done;
char *actionstr = dnd_action == DND_REPLACE ? "replace" :
dnd_action == DND_APPEND ? "append" :
dnd_action == DND_INSERT_NEXT ? "insert-next" :
"none";
struct m_sub_property props[] = {
{"time", SUB_PROP_INT64(dnd_ts)},
{"action", SUB_PROP_STR(actionstr)},
{"files", SUB_PROP_STRING_LIST(dropped_files)},
{0}
};
r = m_property_read_sub(props, action, arg);
done:
talloc_free(talloc_ctx);
return r;
}
/// Video fps (RO)
static int mp_property_fps(void *ctx, struct m_property *prop,
int action, void *arg)
@@ -4666,6 +4704,7 @@ static const struct m_property mp_properties_base[] = {
{"mouse-pos", mp_property_mouse_pos},
{"touch-pos", mp_property_touch_pos},
{"tablet-pos", mp_property_tablet_pos},
{"dropped-files", mp_property_dropped_files},
// Subs
{"sid", mp_property_switch_track, .priv = (void *)(const int[]){0, STREAM_SUB}},
@@ -4810,7 +4849,7 @@ static const char *const *const mp_event_property_change[] = {
E(MP_EVENT_CHANGE_PLAYLIST, "playlist", "playlist-pos", "playlist-pos-1",
"playlist-count", "playlist/count", "playlist-current-pos",
"playlist-playing-pos"),
E(MP_EVENT_INPUT_PROCESSED, "mouse-pos", "touch-pos", "tablet-pos"),
E(MP_EVENT_INPUT_PROCESSED, "mouse-pos", "touch-pos", "tablet-pos", "dropped-files"),
E(MP_EVENT_CORE_IDLE, "core-idle", "eof-reached"),
};
#undef E