VirtualBox

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

Last change on this file since 61465 was 57358, checked in by vboxsync, 9 years ago

*: scm cleanup run.

  • 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 57358 2015-08-14 15:16:38Z vboxsync $ */
2/** @file
3 * VBoxClient - Shared Slipboard Dispatcher, Darwin.
4 */
5
6/*
7 * Copyright (C) 2007-2013 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 ThreadSelf Unused parameter.
149 * @param pvUser Unused parameter.
150 *
151 * @return IPRT status code.
152 */
153static DECLCALLBACK(int) vbclGuestPasteboardPoll(RTTHREAD ThreadSelf, void *pvUser)
154{
155 /*
156 * Block all signals for this thread. Only the main thread will handle signals.
157 */
158 sigset_t signalMask;
159 sigfillset(&signalMask);
160 pthread_sigmask(SIG_BLOCK, &signalMask, NULL);
161
162 VBoxClientVerbose(2, "starting guest clipboard polling thread\n");
163
164 while (!ASMAtomicReadBool(&g_fShouldStop))
165 {
166 PasteboardSyncFlags fSyncFlags;
167 uint32_t fFormats;
168 int rc;
169
170 RTCritSectEnter(&g_critsect);
171
172 fSyncFlags = PasteboardSynchronize(g_PasteboardRef);
173 if (fSyncFlags & kPasteboardModified)
174 {
175 fFormats = vbclClipboardGetAvailableFormats(g_PasteboardRef);
176 rc = VbglR3ClipboardReportFormats(g_u32ClientId, fFormats);
177 if (RT_FAILURE(rc))
178 {
179 VBoxClientVerbose(2, "failed to report pasteboard update (%Rrc)\n", rc);
180 }
181 else
182 {
183 VBoxClientVerbose(2, "guest clipboard update reported: %d\n", (int)fFormats);
184 }
185 }
186
187 RTCritSectLeave(&g_critsect);
188
189 /* Check pasteboard every 200 ms */
190 RTThreadSleep(200);
191 }
192
193 VBoxClientVerbose(2, "guest clipboard polling thread stopped\n");
194
195 return VINF_SUCCESS;
196}
197
198
199/**
200 * Initialize host and guest clipboards, start clipboard dispatcher loop.
201 *
202 * @return IPRT status code.
203 */
204static int vbclClipboardStart(void)
205{
206 int rc;
207
208 VBoxClientVerbose(2, "starting clipboard\n");
209
210 rc = RTCritSectInit(&g_critsect);
211 if (RT_FAILURE(rc))
212 return VERR_GENERAL_FAILURE;
213
214 rc = VbglR3ClipboardConnect(&g_u32ClientId);
215 if (RT_SUCCESS(rc))
216 {
217 rc = PasteboardCreate(kPasteboardClipboard, &g_PasteboardRef);
218 if (rc == noErr)
219 {
220 /* Start dispatcher loop */
221 ASMAtomicWriteBool(&g_fShouldStop, false);
222 rc = RTThreadCreate(&g_DispatcherThread,
223 vbclClipboardDispatcher,
224 (void *)NULL,
225 0,
226 RTTHREADTYPE_DEFAULT,
227 RTTHREADFLAGS_WAITABLE,
228 VBOXCLIENT_SERVICE_NAME);
229 if (RT_SUCCESS(rc))
230 {
231 /* Start dispatcher loop */
232 ASMAtomicWriteBool(&g_fShouldStop, false);
233 rc = RTThreadCreate(&g_GuestPasteboardThread,
234 vbclGuestPasteboardPoll,
235 (void *)NULL,
236 0,
237 RTTHREADTYPE_DEFAULT,
238 RTTHREADFLAGS_WAITABLE,
239 VBOXCLIENT_SERVICE_NAME);
240 if (RT_SUCCESS(rc))
241 return VINF_SUCCESS;
242
243 /* Stop dispatcher thread */
244 ASMAtomicWriteBool(&g_fShouldStop, true);
245 RTThreadWait(g_DispatcherThread, 10 * 1000 /* Wait 10 seconds */, NULL);
246
247 }
248 VBoxClientVerbose(2, "unable create dispatcher thread\n");
249 CFRelease(g_PasteboardRef);
250 g_PasteboardRef = NULL;
251
252 }
253 else
254 {
255 rc = VERR_GENERAL_FAILURE;
256 VBoxClientVerbose(2, "unable access guest clipboard\n");
257 }
258
259 vbclClipboardStop();
260
261 }
262 else
263 {
264 VBoxClientVerbose(2, "unable to establish connection to clipboard service: %Rrc\n", rc);
265 }
266
267 RTCritSectDelete(&g_critsect);
268
269 return rc;
270}
271
272
273/**
274 * Release host and guest clipboards, stop clipboard dispatcher loop.
275 *
276 * @return IPRT status code.
277 */
278static int vbclClipboardStop(void)
279{
280 int rc;
281
282 VBoxClientVerbose(2, "stopping clipboard\n");
283
284 AssertReturn(g_u32ClientId != 0, VERR_GENERAL_FAILURE);
285
286 VbglR3ClipboardReportFormats(g_u32ClientId, 0);
287
288 rc = VbglR3ClipboardDisconnect(g_u32ClientId);
289 if (RT_SUCCESS(rc))
290 g_u32ClientId = 0;
291 else
292 VBoxClientVerbose(2, "unable to close clipboard service connection: %Rrc\n", rc);
293
294 if (g_PasteboardRef)
295 {
296 CFRelease(g_PasteboardRef);
297 g_PasteboardRef = NULL;
298 }
299
300 /* Stop dispatcher thread */
301 ASMAtomicWriteBool(&g_fShouldStop, true);
302 rc = RTThreadWait(g_DispatcherThread, 10 * 1000 /* Wait 10 seconds */, NULL);
303 if (RT_FAILURE(rc))
304 VBoxClientVerbose(2, "failed to stop dispatcher thread");
305
306 /* Stop Pasteboard polling thread */
307 rc = RTThreadWait(g_GuestPasteboardThread, 10 * 1000 /* Wait 10 seconds */, NULL);
308 if (RT_FAILURE(rc))
309 VBoxClientVerbose(2, "failed to stop pasteboard polling thread");
310
311 RTCritSectDelete(&g_critsect);
312
313 return rc;
314}
315
316
317/* Clipboard service struct */
318VBOXCLIENTSERVICE g_ClipboardService =
319{
320 /* pszName */
321 VBOXCLIENT_SERVICE_NAME,
322
323 /* pfnStart */
324 vbclClipboardStart,
325
326 /* pfnStop */
327 vbclClipboardStop,
328};
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