Skip to content
Snippets Groups Projects
Commit 1a289544 authored by Alexandros Frantzis's avatar Alexandros Frantzis
Browse files

winewayland.drv: Handle the wl_data_device::enter event.


Relay the event to the IDropTarget at the enter position, and notify the
Wayland compositor of any accepted format/mime type and actions.

The accepted mime type is set indirectly through IDropTarget_DragEnter
eventually calling our IDataObject_(Query)GetData implementation for the
associated data offer.

Signed-off-by: default avatarAlexandros Frantzis <alexandros.frantzis@collabora.com>
parent 275010e0
No related branches found
No related tags found
No related merge requests found
......@@ -24,6 +24,7 @@ typedef NTSTATUS (WINAPI *kernel_callback)(void *params, ULONG size);
static const kernel_callback kernel_callbacks[] =
{
waylanddrv_client_create_clipboard_window,
waylanddrv_client_dnd,
};
C_ASSERT(NtUserDriverCallbackFirst + ARRAYSIZE(kernel_callbacks) == waylanddrv_client_func_last);
......
......@@ -26,6 +26,9 @@
/* A pointer to memory that is guaranteed to be usable by both 32-bit and
* 64-bit processes. */
typedef UINT PTR32;
/* A handle value that is guaranteed to be usable by both 32-bit and 64-bit
* processes. */
typedef UINT HANDLE32;
enum waylanddrv_unix_func
{
......@@ -71,9 +74,24 @@ struct waylanddrv_unix_data_offer_enum_formats_params
enum waylanddrv_client_func
{
waylanddrv_client_func_create_clipboard_window = NtUserDriverCallbackFirst,
waylanddrv_client_func_dnd,
waylanddrv_client_func_last
};
C_ASSERT(waylanddrv_client_func_last <= NtUserDriverCallbackLast + 1);
enum waylanddrv_client_dnd_event
{
CLIENT_DND_EVENT_ENTER,
};
struct waylanddrv_client_dnd_params
{
UINT event;
HANDLE32 hwnd;
POINT point;
DWORD drop_effect;
PTR32 data_object;
};
#endif /* __WINE_WAYLANDDRV_UNIXLIB_H */
......@@ -88,6 +88,20 @@ static char *normalize_mime_type(const char *mime)
return new_mime;
}
static DWORD dnd_actions_to_drop_effect(uint32_t actions)
{
DWORD drop_effect = 0;
if (actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
drop_effect |= DROPEFFECT_COPY;
if (actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
drop_effect |= DROPEFFECT_MOVE;
if (actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
drop_effect |= DROPEFFECT_COPY | DROPEFFECT_MOVE;
return drop_effect;
}
/**********************************************************************
* wl_data_offer handling
*/
......@@ -315,12 +329,58 @@ static void data_device_enter(void *data, struct wl_data_device *wl_data_device,
wl_fixed_t x_w, wl_fixed_t y_w,
struct wl_data_offer *wl_data_offer)
{
struct waylanddrv_client_dnd_params params;
struct wayland_data_device *data_device = data;
struct wayland_data_offer *data_offer;
struct wayland_surface *wayland_surface;
POINT point;
/* Any previous dnd offer should have been freed by a drop or leave event. */
assert(data_device->dnd_wl_data_offer == NULL);
data_device->dnd_wl_data_offer = wl_data_offer;
if (!wl_data_offer)
return;
data_offer = wl_data_offer_get_user_data(wl_data_offer);
wayland_surface = wl_surface_get_user_data(wl_surface);
if (!wayland_surface || !wayland_surface->hwnd)
return;
data_device->dnd_enter_serial = serial;
data_device->dnd_surface = wayland_surface;
data_device->dnd_x = wl_fixed_to_int(x_w);
data_device->dnd_y = wl_fixed_to_int(y_w);
wayland_surface_coords_to_screen(data_device->dnd_surface,
data_device->dnd_x, data_device->dnd_y,
(int *)&point.x, (int *)&point.y);
TRACE("surface=%p hwnd=%p source_actions=%x action=%x\n",
data_device->dnd_surface, data_device->dnd_surface->hwnd,
data_offer->source_actions, data_offer->action);
/* Clear accepted_mime_type here. It should be eventually set by
* the DnD client call below. */
data_offer->accepted_mime_type = NULL;
params.event = CLIENT_DND_EVENT_ENTER;
params.hwnd = HandleToULong(data_device->dnd_surface->hwnd);
params.point = point;
params.drop_effect = dnd_actions_to_drop_effect(data_offer->source_actions);
params.data_object = PtrToUint(data_offer);
if (WAYLANDDRV_CLIENT_CALL(dnd, &params, sizeof(params)) != 0)
return;
wl_data_offer_set_actions(wl_data_offer, data_offer->source_actions,
data_offer->action);
wl_data_offer_accept(wl_data_offer,
data_device->dnd_enter_serial,
data_offer->accepted_mime_type);
}
static void data_device_leave(void *data, struct wl_data_device *wl_data_device)
......
......@@ -18,6 +18,9 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "waylanddrv_dll.h"
#define COBJMACROS
......@@ -183,6 +186,45 @@ static IDropTarget *drop_target_from_window_point(HWND hwnd, POINT point)
return drop_target;
}
static NTSTATUS WINAPI waylanddrv_client_dnd_enter(void *params, ULONG size)
{
struct waylanddrv_client_dnd_params *p = params;
IDropTarget *drop_target;
DWORD drop_effect = p->drop_effect;
IDataObject *data_object = UIntToPtr(p->data_object);
HRESULT hr;
/* If unixlib is 64 bits and PE is 32 bits, this will write a 32 bit
* pointer value to the bottom of 64 bit pointer variable, which works out
* fine due to little-endianness and the fact that lpVtbl has been zero
* initialized. */
data_object->lpVtbl = &dataOfferDataObjectVtbl;
drop_target = drop_target_from_window_point(ULongToHandle(p->hwnd), p->point);
if (!drop_target)
return STATUS_UNSUCCESSFUL;
hr = IDropTarget_DragEnter(drop_target, data_object, MK_LBUTTON,
*(POINTL*)&p->point, &drop_effect);
IDropTarget_Release(drop_target);
if (FAILED(hr))
return STATUS_UNSUCCESSFUL;
return STATUS_SUCCESS;
}
NTSTATUS WINAPI waylanddrv_client_dnd(void *params, ULONG size)
{
struct waylanddrv_client_dnd_params *p = params;
switch (p->event) {
case CLIENT_DND_EVENT_ENTER:
return waylanddrv_client_dnd_enter(params, size);
}
return STATUS_UNSUCCESSFUL;
}
/*********************************************************
* Implementation of IDataObject for wayland data offers *
*********************************************************/
......
......@@ -671,6 +671,7 @@ void wayland_surface_destroy(struct wayland_surface *surface)
{
struct wayland_pointer *pointer = &surface->wayland->pointer;
struct wayland_keyboard *keyboard = &surface->wayland->keyboard;
struct wayland_data_device *data_device = &surface->wayland->data_device;
struct wayland_surface *child, *child_tmp;
struct wayland_output_ref *ref, *ref_tmp;
......@@ -682,6 +683,9 @@ void wayland_surface_destroy(struct wayland_surface *surface)
if (keyboard->focused_surface == surface)
keyboard->focused_surface = NULL;
if (data_device->dnd_surface == surface)
data_device->dnd_surface = NULL;
/* There are children left only when we force a destruction during
* thread deinitialization, otherwise the children hold a reference
* to the parent and won't let it be destroyed. */
......
......@@ -245,6 +245,10 @@ struct wayland_data_device
struct wl_data_offer *clipboard_wl_data_offer;
struct wl_data_offer *dnd_wl_data_offer;
struct wl_data_source *wl_data_source;
uint32_t dnd_enter_serial;
struct wayland_surface *dnd_surface;
int dnd_x;
int dnd_y;
};
struct wayland_data_device_format
......
......@@ -30,5 +30,6 @@
#define WAYLANDDRV_UNIX_CALL(func, params) WINE_UNIX_CALL(waylanddrv_unix_func_ ## func, params)
NTSTATUS WINAPI waylanddrv_client_create_clipboard_window(void *arg, ULONG size);
NTSTATUS WINAPI waylanddrv_client_dnd(void *params, ULONG size);
#endif /* __WINE_WAYLANDDRV_DLL_H */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment