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

winewayland.drv: Create dedicated window to handle clipboard messages.


The clipboard window is created in the PE code, initiated by a driver
kernel callback invoked from the unixlib side. Clipboard messages
are received in the PE side and forwarded to the unixlib side to
be handled there.

Signed-off-by: default avatarAlexandros Frantzis <alexandros.frantzis@collabora.com>
parent d7d7414d
No related branches found
No related tags found
No related merge requests found
MODULE = winewayland.drv
UNIXLIB = winewayland.so
IMPORTS = user32
UNIX_CFLAGS = $(WAYLAND_CLIENT_CFLAGS) $(WAYLAND_CURSOR_CFLAGS) $(XKBCOMMON_CFLAGS) \
$(GBM_CFLAGS) $(UDEV_CFLAGS) $(DRM_CFLAGS)
UNIX_LIBS = -lwin32u -lm $(WAYLAND_CLIENT_LIBS) $(WAYLAND_CURSOR_LIBS) \
......@@ -20,6 +21,7 @@ C_SRCS = \
wayland_buffer_queue.c \
wayland_cursor.c \
wayland_data_device.c \
wayland_data_device_dll.c \
wayland_dmabuf.c \
wayland_keyboard.c \
wayland_keyboard_layout.c \
......
......@@ -23,6 +23,7 @@
typedef NTSTATUS (WINAPI *kernel_callback)(void *params, ULONG size);
static const kernel_callback kernel_callbacks[] =
{
waylanddrv_client_create_clipboard_window,
};
C_ASSERT(NtUserDriverCallbackFirst + ARRAYSIZE(kernel_callbacks) == waylanddrv_client_func_last);
......
......@@ -27,13 +27,23 @@ enum waylanddrv_unix_func
{
waylanddrv_unix_func_init,
waylanddrv_unix_func_read_events,
waylanddrv_unix_func_clipboard_message,
waylanddrv_unix_func_count,
};
struct waylanddrv_unix_clipboard_message_params
{
HWND hwnd;
UINT msg;
WPARAM wparam;
LPARAM lparam;
};
/* driver client callbacks exposed with KernelCallbackTable interface */
enum waylanddrv_client_func
{
waylanddrv_client_func_last = NtUserDriverCallbackFirst
waylanddrv_client_func_create_clipboard_window = NtUserDriverCallbackFirst,
waylanddrv_client_func_last
};
C_ASSERT(waylanddrv_client_func_last <= NtUserDriverCallbackLast + 1);
......
......@@ -261,3 +261,35 @@ void wayland_data_device_deinit(struct wayland_data_device *data_device)
memset(data_device, 0, sizeof(*data_device));
}
/**********************************************************************
* waylanddrv_unix_clipboard_message
*/
NTSTATUS waylanddrv_unix_clipboard_message(void *arg)
{
struct waylanddrv_unix_clipboard_message_params *params = arg;
switch (params->msg)
{
case WM_NCCREATE:
return TRUE;
}
return NtUserMessageCall(params->hwnd, params->msg, params->wparam,
params->lparam, NULL, NtUserDefWindowProc, FALSE);
}
/**********************************************************************
* wayland_data_device_ensure_clipboard_window
*
* Creates (if not already created) the window which handles clipboard
* messages for the specified wayland instance.
*/
void wayland_data_device_ensure_clipboard_window(struct wayland *wayland)
{
if (!wayland->clipboard_hwnd)
{
wayland->clipboard_hwnd =
ULongToHandle(WAYLANDDRV_CLIENT_CALL(create_clipboard_window, NULL, 0));
}
}
/*
* Wayland data device (clipboard and DnD) handling (DLL code)
*
* Copyright (c) 2020 Alexandros Frantzis for Collabora Ltd
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "waylanddrv_dll.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(clipboard);
static LRESULT CALLBACK clipboard_wndproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
struct waylanddrv_unix_clipboard_message_params params;
switch (msg)
{
case WM_NCCREATE:
case WM_CLIPBOARDUPDATE:
case WM_RENDERFORMAT:
case WM_DESTROYCLIPBOARD:
params.hwnd = hwnd;
params.msg = msg;
params.wparam = wp;
params.lparam = lp;
return WAYLANDDRV_UNIX_CALL(clipboard_message, &params);
}
return DefWindowProcW(hwnd, msg, wp, lp);
}
NTSTATUS WINAPI waylanddrv_client_create_clipboard_window(void *arg, ULONG size)
{
static const WCHAR clipboard_classname[] = {
'_','_','w','i','n','e','_','c','l','i','p','b','o','a','r','d',
'_','m','a','n','a','g','e','r',0
};
WNDCLASSW class;
HWND clipboard_hwnd;
memset(&class, 0, sizeof(class));
class.lpfnWndProc = clipboard_wndproc;
class.lpszClassName = clipboard_classname;
if (!RegisterClassW(&class) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
{
ERR("could not register clipboard window class err %lu\n", GetLastError());
return 0;
}
if (!(clipboard_hwnd = CreateWindowW(clipboard_classname, NULL, 0, 0, 0, 0, 0,
HWND_MESSAGE, 0, 0, NULL)))
{
ERR("failed to create clipboard window err %lu\n", GetLastError());
return 0;
}
if (!AddClipboardFormatListener(clipboard_hwnd))
ERR("failed to set clipboard listener %lu\n", GetLastError());
TRACE("clipboard_hwnd=%p\n", clipboard_hwnd);
return HandleToUlong(clipboard_hwnd);
}
......@@ -77,6 +77,7 @@ enum wayland_window_message
WM_WAYLAND_WINDOW_SURFACE_FLUSH,
WM_WAYLAND_REMOTE_SURFACE,
WM_WAYLAND_POINTER_CONSTRAINT_UPDATE,
WM_WAYLAND_CLIPBOARD_WINDOW_CREATE,
};
enum wayland_surface_role
......@@ -278,6 +279,7 @@ struct wayland
uint32_t last_button_serial;
int last_event_type;
int event_notification_pipe[2];
HWND clipboard_hwnd;
RECT cursor_clip;
};
......@@ -689,6 +691,7 @@ void wayland_invalidate_vulkan_objects(HWND hwnd) DECLSPEC_HIDDEN;
void wayland_data_device_init(struct wayland_data_device *data_device,
struct wayland *wayland) DECLSPEC_HIDDEN;
void wayland_data_device_deinit(struct wayland_data_device *data_device) DECLSPEC_HIDDEN;
void wayland_data_device_ensure_clipboard_window(struct wayland *wayland) DECLSPEC_HIDDEN;
/**********************************************************************
* Registry helpers
......@@ -802,6 +805,7 @@ static inline HWND get_focus(void)
NTSTATUS waylanddrv_client_call(enum waylanddrv_client_func func, const void *params,
ULONG size) DECLSPEC_HIDDEN;
NTSTATUS waylanddrv_unix_clipboard_message(void *arg) DECLSPEC_HIDDEN;
/**********************************************************************
* USER driver functions
......
......@@ -29,4 +29,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);
#endif /* __WINE_WAYLANDDRV_DLL_H */
......@@ -95,6 +95,14 @@ struct wayland_thread_data *wayland_init_thread_data(void)
set_queue_fd(&data->wayland);
NtUserGetThreadInfo()->driver_data = (UINT_PTR)data;
/* Create the clipboard window outside of thread init. We delay window
* creation since the thread init function may be invoked from within the
* context of a user32 function which holds the internal Wine user32 lock.
* In such a case creating the clipboard window would cause an internal
* user32 lock error. */
NtUserPostThreadMessage(data->wayland.thread_id,
WM_WAYLAND_CLIPBOARD_WINDOW_CREATE, 0, 0);
return data;
}
......@@ -215,16 +223,35 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
{
waylanddrv_unix_init,
waylanddrv_unix_read_events,
waylanddrv_unix_clipboard_message,
};
C_ASSERT(ARRAYSIZE(__wine_unix_call_funcs) == waylanddrv_unix_func_count);
#ifdef _WIN64
static NTSTATUS waylanddrv_unix_clipboard_message_wow64(void *arg)
{
struct {
ULONG hwnd;
UINT msg;
ULONG wparam;
ULONG lparam;
} *params32 = arg;
struct waylanddrv_unix_clipboard_message_params params;
params.hwnd = UlongToHandle(params32->hwnd);
params.msg = params32->msg;
params.wparam = params32->wparam;
params.lparam = params32->lparam;
return waylanddrv_unix_clipboard_message(&params);
}
const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
{
waylanddrv_unix_init,
waylanddrv_unix_read_events,
waylanddrv_unix_clipboard_message_wow64,
};
C_ASSERT(ARRAYSIZE(__wine_unix_call_wow64_funcs) == waylanddrv_unix_func_count);
......
......@@ -1786,6 +1786,9 @@ LRESULT WAYLAND_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
wayland_surface_for_hwnd_unlock(wayland_surface);
}
break;
case WM_WAYLAND_CLIPBOARD_WINDOW_CREATE:
wayland_data_device_ensure_clipboard_window(thread_wayland());
break;
default:
FIXME("got window msg %x hwnd %p wp %lx lp %lx\n", msg, hwnd, (long)wp, lp);
}
......
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