VirtualBox

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

Last change on this file since 72293 was 69500, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

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