VirtualBox

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

Last change on this file since 105006 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

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