Skip to content

Commit

Permalink
Wayland: Add support for file drop events
Browse files Browse the repository at this point in the history
This adds support for file path drop events in text/uri-list format.

It is based on work by Pilzschaf in glfw#2040.

Closes glfw#2040
elmindreda committed Apr 3, 2022
1 parent 0f38382 commit 4cb3687
Showing 5 changed files with 62 additions and 4 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -162,6 +162,7 @@ video tutorials.
- Orson Peters
- Emmanuel Gil Peyrot
- Cyril Pichard
- Pilzschaf
- Keith Pitt
- Stanislav Podgorskiy
- Konstantin Podsvirov
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -287,6 +287,7 @@ information on what to include when reporting a bug.
- [X11] Bugfix: Left shift of int constant relied on undefined behavior (#1951)
- [Wayland] Added dynamic loading of all Wayland libraries
- [Wayland] Added support for key names via xkbcommon
- [Wayland] Added support for file path drop events (#2040)
- [Wayland] Removed support for `wl_shell` (#1443)
- [Wayland] Bugfix: The `GLFW_HAND_CURSOR` shape used the wrong image (#1432)
- [Wayland] Bugfix: `CLOCK_MONOTONIC` was not correctly enabled
2 changes: 2 additions & 0 deletions src/wl_init.c
Original file line number Diff line number Diff line change
@@ -714,6 +714,8 @@ void _glfwTerminateWayland(void)
xdg_wm_base_destroy(_glfw.wl.wmBase);
if (_glfw.wl.selectionOffer)
wl_data_offer_destroy(_glfw.wl.selectionOffer);
if (_glfw.wl.dragOffer)
wl_data_offer_destroy(_glfw.wl.dragOffer);
if (_glfw.wl.selectionSource)
wl_data_source_destroy(_glfw.wl.selectionSource);
if (_glfw.wl.dataDevice)
5 changes: 5 additions & 0 deletions src/wl_platform.h
Original file line number Diff line number Diff line change
@@ -223,6 +223,7 @@ typedef struct _GLFWofferWayland
{
struct wl_data_offer* offer;
GLFWbool text_plain_utf8;
GLFWbool text_uri_list;
} _GLFWofferWayland;

// Wayland-specific per-window data
@@ -300,6 +301,10 @@ typedef struct _GLFWlibraryWayland
struct wl_data_offer* selectionOffer;
struct wl_data_source* selectionSource;

struct wl_data_offer* dragOffer;
_GLFWwindow* dragFocus;
uint32_t dragSerial;

int compositorVersion;
int seatVersion;

57 changes: 53 additions & 4 deletions src/wl_window.c
Original file line number Diff line number Diff line change
@@ -1534,6 +1534,8 @@ static void dataOfferHandleOffer(void* userData,
{
if (strcmp(mimeType, "text/plain;charset=utf-8") == 0)
_glfw.wl.offers[i].text_plain_utf8 = GLFW_TRUE;
else if (strcmp(mimeType, "text/uri-list") == 0)
_glfw.wl.offers[i].text_uri_list = GLFW_TRUE;

break;
}
@@ -1572,24 +1574,53 @@ static void dataDeviceHandleEnter(void* userData,
wl_fixed_t y,
struct wl_data_offer* offer)
{
if (_glfw.wl.dragOffer)
{
wl_data_offer_destroy(_glfw.wl.dragOffer);
_glfw.wl.dragOffer = NULL;
_glfw.wl.dragFocus = NULL;
}

for (unsigned int i = 0; i < _glfw.wl.offerCount; i++)
{
if (_glfw.wl.offers[i].offer == offer)
{
_GLFWwindow* window = NULL;

if (surface)
window = wl_surface_get_user_data(surface);

if (window && _glfw.wl.offers[i].text_uri_list)
{
_glfw.wl.dragOffer = offer;
_glfw.wl.dragFocus = window;
_glfw.wl.dragSerial = serial;
}

_glfw.wl.offers[i] = _glfw.wl.offers[_glfw.wl.offerCount - 1];
_glfw.wl.offerCount--;

// We don't yet handle drag and drop
wl_data_offer_accept(offer, serial, NULL);
wl_data_offer_destroy(offer);
break;
}
}

if (_glfw.wl.dragOffer)
wl_data_offer_accept(offer, serial, "text/uri-list");
else
{
wl_data_offer_accept(offer, serial, NULL);
wl_data_offer_destroy(offer);
}
}

static void dataDeviceHandleLeave(void* userData,
struct wl_data_device* device)
{
if (_glfw.wl.dragOffer)
{
wl_data_offer_destroy(_glfw.wl.dragOffer);
_glfw.wl.dragOffer = NULL;
_glfw.wl.dragFocus = NULL;
}
}

static void dataDeviceHandleMotion(void* userData,
@@ -1603,6 +1634,24 @@ static void dataDeviceHandleMotion(void* userData,
static void dataDeviceHandleDrop(void* userData,
struct wl_data_device* device)
{
if (!_glfw.wl.dragOffer)
return;

char* string = readDataOfferAsString(_glfw.wl.dragOffer, "text/uri-list");
if (string)
{
int count;
char** paths = _glfwParseUriList(string, &count);
if (paths)
_glfwInputDrop(_glfw.wl.dragFocus, count, (const char**) paths);

for (int i = 0; i < count; i++)
_glfw_free(paths[i]);

_glfw_free(paths);
}

_glfw_free(string);
}

static void dataDeviceHandleSelection(void* userData,

0 comments on commit 4cb3687

Please sign in to comment.