VirtualBox

source: vbox/trunk/src/VBox/Additions/darwin/VBoxClient/VBoxClientClipboard.cpp@ 94876

Last change on this file since 94876 was 94876, checked in by vboxsync, 3 years ago

Reverted r151276.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1/** $Id: VBoxClientClipboard.cpp 94876 2022-05-06 02:31:18Z vboxsync $ */
2/** @file
3 * VBoxClient - Shared Slipboard Dispatcher, Darwin.
4 */
5
6/*
7 * Copyright (C) 2007-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include <Carbon/Carbon.h>
23
24#include <iprt/asm.h>
25#include <iprt/stream.h>
26#include <iprt/thread.h>
27#include <iprt/critsect.h>
28#include <VBox/VBoxGuestLib.h>
29#include <VBox/GuestHost/SharedClipboard.h>
30#include <VBox/HostServices/VBoxClipboardSvc.h>
31#include <VBox/GuestHost/clipboard-helper.h>
32#include "VBoxClientInternal.h"
33
34
35/*********************************************************************************************************************************
36* Global Variables *
37*********************************************************************************************************************************/
38
39/** Host clipboard connection client ID */
40static uint32_t g_u32ClientId;
41/* Guest clipboard reference */
42static PasteboardRef g_PasteboardRef;
43/* Dispatcher tharead handle */
44RTTHREAD g_DispatcherThread;
45/* Pasteboard polling tharead handle */
46RTTHREAD g_GuestPasteboardThread;
47/* Flag that indicates whether or not dispatcher and Pasteboard polling threada should stop */
48static bool volatile g_fShouldStop;
49/* Barrier for Pasteboard */
50static RTCRITSECT g_critsect;
51
52
53/*********************************************************************************************************************************
54* Local Macros *
55*********************************************************************************************************************************/
56
57#define VBOXCLIENT_SERVICE_NAME "clipboard"
58
59
60/*********************************************************************************************************************************
61* Local Function Prototypes *
62*********************************************************************************************************************************/
63static int vbclClipboardStop(void);
64
65
66/**
67 * Clipboard dispatcher function.
68 *
69 * Forwards cliproard content between host and guest.
70 *
71 * @param ThreadSelf Unused parameter.
72 * @param pvUser Unused parameter.
73 *
74 * @return IPRT status code.
75 */
76static DECLCALLBACK(int) vbclClipboardDispatcher(RTTHREAD ThreadSelf, void *pvUser)
77{
78 bool fQuit = false;
79 NOREF(ThreadSelf);
80 NOREF(pvUser);
81
82 VBoxClientVerbose(2, "starting host clipboard polling thread\n");
83
84 /*
85 * Block all signals for this thread. Only the main thread will handle signals.
86 */
87 sigset_t signalMask;
88 sigfillset(&signalMask);
89 pthread_sigmask(SIG_BLOCK, &signalMask, NULL);
90
91 while (!fQuit && !ASMAtomicReadBool(&g_fShouldStop))
92 {
93 int rc;
94 uint32_t Msg;
95 uint32_t fFormats;
96
97 VBoxClientVerbose(2, "waiting for new host request\n");
98
99 rc = VbglR3ClipboardGetHostMsgOld(g_u32ClientId, &Msg, &fFormats);
100 if (RT_SUCCESS(rc))
101 {
102 RTCritSectEnter(&g_critsect);
103 switch (Msg)
104 {
105 /* The host is terminating */
106 case VBOX_SHCL_HOST_MSG_QUIT:
107 VBoxClientVerbose(2, "host requested quit\n");
108 fQuit = true;
109 break;
110
111 /* The host needs data in the specified format */
112 case VBOX_SHCL_HOST_MSG_READ_DATA:
113 VBoxClientVerbose(2, "host requested guest's clipboard read\n");
114 rc = vbclClipboardForwardToHost(g_u32ClientId, g_PasteboardRef, fFormats);
115 AssertMsg(RT_SUCCESS(rc), ("paste to host failed\n"));
116 break;
117
118 /* The host has announced available clipboard formats */
119 case VBOX_SHCL_HOST_MSG_FORMATS_REPORT:
120 VBoxClientVerbose(2, "host requested guest's clipboard write\n");
121 rc = vbclClipboardForwardToGuest(g_u32ClientId, g_PasteboardRef, fFormats);
122 AssertMsg(RT_SUCCESS(rc), ("paste to guest failed\n"));
123 break;
124
125 default:
126 VBoxClientVerbose(2, "received unknow command from host service\n");
127 RTThreadSleep(1000);
128 }
129
130 RTCritSectLeave(&g_critsect);
131 }
132 else
133 {
134 RTThreadSleep(1000);
135 }
136 }
137
138 VBoxClientVerbose(2, "host clipboard polling thread stopped\n");
139
140 return VINF_SUCCESS;
141}
142
143
144/**
145 * Clipboard dispatcher function.
146 *
147 * Forwards cliproard content between host and guest.
148 *
149 * @param hThreadSelf Unused parameter.
150 * @param pvUser Unused parameter.
151 *
152 * @return IPRT status code.
153 */
154static DECLCALLBACK(int) vbclGuestPasteboardPoll(RTTHREAD hThreadSelf, void *pvUser)
155{
156 RT_NOREF(hThreadSelf, pvUser);
157
158 /*
159 * Block all signals for this thread. Only the main thread will handle signals.
160 */
161 sigset_t signalMask;
162 sigfillset(&signalMask);
163 pthread_sigmask(SIG_BLOCK, &signalMask, NULL);
164
165 VBoxClientVerbose(2, "starting guest clipboard polling thread\n");
166
167 while (!ASMAtomicReadBool(&g_fShouldStop))
168 {
169 PasteboardSyncFlags fSyncFlags;
170 uint32_t fFormats;
171 int rc;
172
173 RTCritSectEnter(&g_critsect);
174
175 fSyncFlags = PasteboardSynchronize(g_PasteboardRef);
176 if (fSyncFlags & kPasteboardModified)
177 {
178 fFormats = vbclClipboardGetAvailableFormats(g_PasteboardRef);
179 rc = VbglR3ClipboardReportFormats(g_u32ClientId, fFormats);
180 if (RT_FAILURE(rc))
181 {
182 VBoxClientVerbose(2, "failed to report pasteboard update (%Rrc)\n", rc);
183 }
184 else
185 {
186 VBoxClientVerbose(2, "guest clipboard update reported: %d\n", (int)fFormats);
187 }
188 }
189
190 RTCritSectLeave(&g_critsect);
191
192 /* Check pasteboard every 200 ms */
193 RTThreadSleep(200);
194 }
195
196 VBoxClientVerbose(2, "guest clipboard polling thread stopped\n");
197
198 return VINF_SUCCESS;
199}
200
201
202/**
203 * Initialize host and guest clipboards, start clipboard dispatcher loop.
204 *
205 * @return IPRT status code.
206 */
207static int vbclClipboardStart(void)
208{
209 int rc;
210
211 VBoxClientVerbose(2, "starting clipboard\n");
212
213 rc = RTCritSectInit(&g_critsect);
214 if (RT_FAILURE(rc))
215 return VERR_GENERAL_FAILURE;
216
217 rc = VbglR3ClipboardConnect(&g_u32ClientId);
218 if (RT_SUCCESS(rc))
219 {
220 rc = PasteboardCreate(kPasteboardClipboard, &g_PasteboardRef);
221 if (rc == noErr)
222 {
223 /* Start dispatcher loop */
224 ASMAtomicWriteBool(&g_fShouldStop, false);
225 rc = RTThreadCreate(&g_DispatcherThread,
226 vbclClipboardDispatcher,
227 (void *)NULL,
228 0,
229 RTTHREADTYPE_DEFAULT,
230 RTTHREADFLAGS_WAITABLE,
231 VBOXCLIENT_SERVICE_NAME);
232 if (RT_SUCCESS(rc))
233 {
234 /* Start dispatcher loop */
235 ASMAtomicWriteBool(&g_fShouldStop, false);
236 rc = RTThreadCreate(&g_GuestPasteboardThread,
237 vbclGuestPasteboardPoll,
238 (void *)NULL,
239 0,
240 RTTHREADTYPE_DEFAULT,
241 RTTHREADFLAGS_WAITABLE,
242 VBOXCLIENT_SERVICE_NAME);
243 if (RT_SUCCESS(rc))
244 return VINF_SUCCESS;
245
246 /* Stop dispatcher thread */
247 ASMAtomicWriteBool(&g_fShouldStop, true);
248 RTThreadWait(g_DispatcherThread, 10 * 1000 /* Wait 10 seconds */, NULL);
249
250 }
251 VBoxClientVerbose(2, "unable create dispatcher thread\n");
252 CFRelease(g_PasteboardRef);
253 g_PasteboardRef = NULL;
254
255 }
256 else
257 {
258 rc = VERR_GENERAL_FAILURE;
259 VBoxClientVerbose(2, "unable access guest clipboard\n");
260 }
261
262 vbclClipboardStop();
263
264 }
265 else
266 {
267 VBoxClientVerbose(2, "unable to establish connection to clipboard service: %Rrc\n", rc);
268 }
269
270 RTCritSectDelete(&g_critsect);
271
272 return rc;
273}
274
275
276/**
277 * Release host and guest clipboards, stop clipboard dispatcher loop.
278 *
279 * @return IPRT status code.
280 */
281static int vbclClipboardStop(void)
282{
283 int rc;
284
285 VBoxClientVerbose(2, "stopping clipboard\n");
286
287 AssertReturn(g_u32ClientId != 0, VERR_GENERAL_FAILURE);
288
289 VbglR3ClipboardReportFormats(g_u32ClientId, 0);
290
291 rc = VbglR3ClipboardDisconnect(g_u32ClientId);
292 if (RT_SUCCESS(rc))
293 g_u32ClientId = 0;
294 else
295 VBoxClientVerbose(2, "unable to close clipboard service connection: %Rrc\n", rc);
296
297 if (g_PasteboardRef)
298 {
299 CFRelease(g_PasteboardRef);
300 g_PasteboardRef = NULL;
301 }
302
303 /* Stop dispatcher thread */
304 ASMAtomicWriteBool(&g_fShouldStop, true);
305 rc = RTThreadWait(g_DispatcherThread, 10 * 1000 /* Wait 10 seconds */, NULL);
306 if (RT_FAILURE(rc))
307 VBoxClientVerbose(2, "failed to stop dispatcher thread");
308
309 /* Stop Pasteboard polling thread */
310 rc = RTThreadWait(g_GuestPasteboardThread, 10 * 1000 /* Wait 10 seconds */, NULL);
311 if (RT_FAILURE(rc))
312 VBoxClientVerbose(2, "failed to stop pasteboard polling thread");
313
314 RTCritSectDelete(&g_critsect);
315
316 return rc;
317}
318
319
320/* Clipboard service struct */
321VBOXCLIENTSERVICE g_ClipboardService =
322{
323 /* pszName */
324 VBOXCLIENT_SERVICE_NAME,
325
326 /* pfnStart */
327 vbclClipboardStart,
328
329 /* pfnStop */
330 vbclClipboardStop,
331};
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette