[PATCH 6/6] winemac: Use window messages instead of named pipe for macdrv_UpdateClipboard implementation.
Jacek Caban
wine at gitlab.winehq.org
Mon May 30 07:42:19 CDT 2022
From: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
---
dlls/winemac.drv/clipboard.c | 261 +++--------------------------------
1 file changed, 22 insertions(+), 239 deletions(-)
diff --git a/dlls/winemac.drv/clipboard.c b/dlls/winemac.drv/clipboard.c
index dca62997028..d431728036e 100644
--- a/dlls/winemac.drv/clipboard.c
+++ b/dlls/winemac.drv/clipboard.c
@@ -87,6 +87,9 @@ static CFDataRef export_unicodetext_to_utf16(void *data, size_t size);
* Static Variables
**************************************************************************/
+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};
+
/* Clipboard formats */
static struct list format_list = LIST_INIT(format_list);
@@ -194,7 +197,6 @@ static ULONG last_clipboard_update;
static DWORD last_get_seqno;
static WINE_CLIPFORMAT **current_mac_formats;
static unsigned int nb_current_mac_formats;
-static WCHAR clipboard_pipe_name[256];
/**************************************************************************
@@ -1605,6 +1607,9 @@ static LRESULT CALLBACK clipboard_wndproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM
is_clipboard_owner = FALSE;
KillTimer(hwnd, 1);
break;
+ case WM_USER:
+ update_clipboard();
+ break;
}
return DefWindowProcW(hwnd, msg, wp, lp);
}
@@ -1639,42 +1644,6 @@ static BOOL wait_clipboard_mutex(void)
}
-/**************************************************************************
- * init_pipe_name
- *
- * Init-once helper for get_pipe_name.
- */
-static BOOL CALLBACK init_pipe_name(INIT_ONCE* once, void* param, void** context)
-{
- static const WCHAR prefix[] = {'\\','\\','.','\\','p','i','p','e','\\','_','_','w','i','n','e','_','c','l','i','p','b','o','a','r','d','_'};
-
- memcpy(clipboard_pipe_name, prefix, sizeof(prefix));
- if (!GetUserObjectInformationW(GetProcessWindowStation(), UOI_NAME,
- clipboard_pipe_name + ARRAY_SIZE(prefix),
- sizeof(clipboard_pipe_name) - sizeof(prefix), NULL))
- {
- ERR("failed to get winstation name\n");
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-/**************************************************************************
- * get_pipe_name
- *
- * Get the name of the pipe used to communicate with the per-window-station
- * clipboard manager thread.
- */
-static const WCHAR* get_pipe_name(void)
-{
- static INIT_ONCE once = INIT_ONCE_STATIC_INIT;
- InitOnceExecuteOnce(&once, init_pipe_name, NULL, NULL);
- return clipboard_pipe_name[0] ? clipboard_pipe_name : NULL;
-}
-
-
/**************************************************************************
* clipboard_thread
*
@@ -1682,14 +1651,8 @@ static const WCHAR* get_pipe_name(void)
*/
static DWORD WINAPI clipboard_thread(void *arg)
{
- 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;
struct macdrv_window_features wf;
- const WCHAR* pipe_name;
- HANDLE pipe = NULL;
- HANDLE event = NULL;
- OVERLAPPED overlapped;
- BOOL need_connect = TRUE, pending = FALSE;
MSG msg;
if (!wait_clipboard_mutex()) return 0;
@@ -1719,103 +1682,15 @@ static DWORD WINAPI clipboard_thread(void *arg)
goto done;
}
- pipe_name = get_pipe_name();
- if (!pipe_name)
- {
- ERR("failed to get pipe name\n");
- goto done;
- }
-
- pipe = CreateNamedPipeW(pipe_name, PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED,
- PIPE_TYPE_BYTE, PIPE_UNLIMITED_INSTANCES, 1, 1, 0, NULL);
- if (!pipe)
- {
- ERR("failed to create named pipe: %u\n", GetLastError());
- goto done;
- }
-
- event = CreateEventW(NULL, TRUE, FALSE, NULL);
- if (!event)
- {
- ERR("failed to create event: %d\n", GetLastError());
- goto done;
- }
-
clipboard_thread_id = GetCurrentThreadId();
NtUserAddClipboardFormatListener(clipboard_hwnd);
register_builtin_formats();
grab_win32_clipboard();
TRACE("clipboard thread %04x running\n", GetCurrentThreadId());
- while (1)
- {
- DWORD result;
-
- if (need_connect)
- {
- pending = FALSE;
- memset(&overlapped, 0, sizeof(overlapped));
- overlapped.hEvent = event;
- if (ConnectNamedPipe(pipe, &overlapped))
- {
- ERR("asynchronous ConnectNamedPipe unexpectedly returned true: %d\n", GetLastError());
- ResetEvent(event);
- }
- else
- {
- result = GetLastError();
- switch (result)
- {
- case ERROR_PIPE_CONNECTED:
- case ERROR_NO_DATA:
- SetEvent(event);
- need_connect = FALSE;
- break;
- case ERROR_IO_PENDING:
- need_connect = FALSE;
- pending = TRUE;
- break;
- default:
- ERR("failed to initiate pipe connection: %d\n", result);
- break;
- }
- }
- }
-
- result = MsgWaitForMultipleObjectsEx(1, &event, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
- switch (result)
- {
- case WAIT_OBJECT_0:
- {
- DWORD written;
-
- if (pending && !GetOverlappedResult(pipe, &overlapped, &written, FALSE))
- ERR("failed to connect pipe: %d\n", GetLastError());
-
- update_clipboard();
- DisconnectNamedPipe(pipe);
- need_connect = TRUE;
- break;
- }
- case WAIT_OBJECT_0 + 1:
- while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
- {
- if (msg.message == WM_QUIT)
- goto done;
- DispatchMessageW(&msg);
- }
- break;
- case WAIT_IO_COMPLETION:
- break;
- default:
- ERR("failed to wait for connection or input: %d\n", GetLastError());
- break;
- }
- }
+ while (GetMessageW(&msg, 0, 0, 0)) DispatchMessageW(&msg);
done:
- if (event) CloseHandle(event);
- if (pipe) CloseHandle(pipe);
macdrv_destroy_cocoa_window(clipboard_cocoa_window);
DestroyWindow(clipboard_hwnd);
return 0;
@@ -1833,124 +1708,32 @@ done:
void macdrv_UpdateClipboard(void)
{
static ULONG last_update;
- ULONG now, end;
- const WCHAR* pipe_name;
- HANDLE pipe;
- BYTE dummy;
- DWORD count;
- OVERLAPPED overlapped = { 0 };
- BOOL canceled = FALSE;
+ static HWND clipboard_manager;
+ ULONG now;
+ DWORD_PTR ret;
if (GetCurrentThreadId() == clipboard_thread_id) return;
TRACE("\n");
- now = GetTickCount();
- if ((int)(now - last_update) <= CLIPBOARD_UPDATE_DELAY) return;
- last_update = now;
-
- if (!(pipe_name = get_pipe_name())) return;
- pipe = CreateFileW(pipe_name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
- if (pipe == INVALID_HANDLE_VALUE)
- {
- WARN("failed to open pipe to clipboard manager: %d\n", GetLastError());
- return;
- }
-
- overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
- if (!overlapped.hEvent)
- {
- ERR("failed to create event: %d\n", GetLastError());
- goto done;
- }
-
- /* We expect the read to fail because the server just closes our connection. This
- is just waiting for that close to happen. */
- if (ReadFile(pipe, &dummy, sizeof(dummy), NULL, &overlapped))
- {
- WARN("asynchronous ReadFile unexpectedly returned true: %d\n", GetLastError());
- goto done;
- }
- else
- {
- DWORD error = GetLastError();
- if (error == ERROR_PIPE_NOT_CONNECTED || error == ERROR_BROKEN_PIPE)
- {
- /* The server accepted, handled, and closed our connection before we
- attempted the read, which is fine. */
- goto done;
- }
- else if (error != ERROR_IO_PENDING)
- {
- ERR("failed to initiate read from pipe: %d\n", error);
- goto done;
- }
- }
+ now = NtGetTickCount();
+ if (last_update && (int)(now - last_update) <= CLIPBOARD_UPDATE_DELAY) return;
- end = now + 500;
- while (1)
+ if (!NtUserIsWindow(clipboard_manager))
{
- DWORD result, timeout;
-
- if (canceled)
- timeout = INFINITE;
- else
+ UNICODE_STRING str;
+ RtlInitUnicodeString(&str, clipboard_classname);
+ clipboard_manager = NtUserFindWindowEx(NULL, NULL, &str, NULL, 0);
+ if (!clipboard_manager)
{
- now = GetTickCount();
- timeout = end - now;
- if ((int)timeout < 0)
- timeout = 0;
- }
-
- result = MsgWaitForMultipleObjectsEx(1, &overlapped.hEvent, timeout, QS_SENDMESSAGE, MWMO_ALERTABLE);
- switch (result)
- {
- case WAIT_OBJECT_0:
- {
- if (GetOverlappedResult(pipe, &overlapped, &count, FALSE))
- WARN("unexpectedly succeeded in reading from pipe\n");
- else
- {
- result = GetLastError();
- if (result != ERROR_BROKEN_PIPE && result != ERROR_OPERATION_ABORTED &&
- result != ERROR_HANDLES_CLOSED)
- WARN("failed to read from pipe: %d\n", result);
- }
-
- goto done;
- }
- case WAIT_OBJECT_0 + 1:
- {
- MSG msg;
- while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE))
- DispatchMessageW(&msg);
- break;
- }
- case WAIT_IO_COMPLETION:
- break;
- case WAIT_TIMEOUT:
- WARN("timed out waiting for read\n");
- CancelIoEx(pipe, &overlapped);
- canceled = TRUE;
- break;
- default:
- if (canceled)
- {
- ERR("failed to wait for cancel: %d\n", GetLastError());
- goto done;
- }
-
- ERR("failed to wait for read: %d\n", GetLastError());
- CancelIoEx(pipe, &overlapped);
- canceled = TRUE;
- break;
+ ERR("clipboard manager not found\n");
+ return;
}
}
-done:
- if (overlapped.hEvent) CloseHandle(overlapped.hEvent);
- CloseHandle(pipe);
+ send_message_timeout(clipboard_manager, WM_USER, 0, 0,
+ SMTO_ABORTIFHUNG, 5000, &ret);
+ last_update = now;
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/154
More information about the wine-devel
mailing list