VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedClipboard/darwin-pasteboard.cpp@ 34014

Last change on this file since 34014 was 28800, checked in by vboxsync, 15 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

  • Property eol-style set to native
  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 11.2 KB
Line 
1/* $Id: darwin-pasteboard.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
2/** @file
3 * Shared Clipboard: Mac OS X host implementation.
4 */
5
6/*
7 * Copyright (C) 2008 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#define LOG_GROUP LOG_GROUP_HGCM
19#include <Carbon/Carbon.h>
20
21#include <iprt/mem.h>
22#include <iprt/assert.h>
23#include "iprt/err.h"
24
25#include "VBox/log.h"
26#include "VBox/HostServices/VBoxClipboardSvc.h"
27#include "VBox/GuestHost/clipboard-helper.h"
28
29/* For debugging */
30//#define SHOW_CLIPBOARD_CONTENT
31
32/**
33 * Initialize the global pasteboard and return a reference to it.
34 *
35 * @param pPasteboardRef Reference to the global pasteboard.
36 *
37 * @returns IPRT status code.
38 */
39int initPasteboard (PasteboardRef *pPasteboardRef)
40{
41 int rc = VINF_SUCCESS;
42
43 if (PasteboardCreate (kPasteboardClipboard, pPasteboardRef))
44 rc = VERR_NOT_SUPPORTED;
45
46 return rc;
47}
48
49/**
50 * Release the reference to the global pasteboard.
51 *
52 * @param pPasteboardRef Reference to the global pasteboard.
53 */
54void destroyPasteboard (PasteboardRef *pPasteboardRef)
55{
56 CFRelease (*pPasteboardRef);
57 *pPasteboardRef = NULL;
58}
59
60/**
61 * Inspect the global pasteboard for new content. Check if there is some type
62 * that is supported by vbox and return it.
63 *
64 * @param pPasteboardRef Reference to the global pasteboard.
65 * @param pfFormats Pointer for the bit combination of the
66 * supported types.
67 * @param pbChanged True if something has changed after the
68 * last call.
69 *
70 * @returns IPRT status code. (Always VINF_SUCCESS atm.)
71 */
72int queryNewPasteboardFormats (PasteboardRef pPasteboard, uint32_t *pfFormats, bool *pfChanged)
73{
74 Log (("queryNewPasteboardFormats\n"));
75
76 OSStatus err = noErr;
77 *pfChanged = true;
78
79 PasteboardSyncFlags syncFlags;
80 /* Make sure all is in sync */
81 syncFlags = PasteboardSynchronize (pPasteboard);
82 /* If nothing changed return */
83 if (!(syncFlags & kPasteboardModified))
84 {
85 *pfChanged = false;
86 return VINF_SUCCESS;
87 }
88
89 /* Are some items in the pasteboard? */
90 ItemCount itemCount;
91 err = PasteboardGetItemCount (pPasteboard, &itemCount);
92 if (itemCount < 1)
93 return VINF_SUCCESS;
94
95 /* The id of the first element in the pasteboard */
96 int rc = VINF_SUCCESS;
97 PasteboardItemID itemID;
98 if (!(err = PasteboardGetItemIdentifier (pPasteboard, 1, &itemID)))
99 {
100 /* Retrieve all flavors in the pasteboard, maybe there
101 * is something we can use. */
102 CFArrayRef flavorTypeArray;
103 if (!(err = PasteboardCopyItemFlavors (pPasteboard, itemID, &flavorTypeArray)))
104 {
105 CFIndex flavorCount;
106 flavorCount = CFArrayGetCount (flavorTypeArray);
107 for (CFIndex flavorIndex = 0; flavorIndex < flavorCount; flavorIndex++)
108 {
109 CFStringRef flavorType;
110 flavorType = static_cast <CFStringRef> (CFArrayGetValueAtIndex (flavorTypeArray,
111 flavorIndex));
112 /* Currently only unicode supported */
113 if (UTTypeConformsTo (flavorType, CFSTR ("public.utf8-plain-text")) ||
114 UTTypeConformsTo (flavorType, CFSTR ("public.utf16-plain-text")))
115 {
116 Log (("Unicode flavor detected.\n"));
117 *pfFormats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
118 }
119 }
120 CFRelease (flavorTypeArray);
121 }
122 }
123
124 Log (("queryNewPasteboardFormats: rc = %02X\n", rc));
125 return rc;
126}
127
128/**
129 * Read content from the host clipboard and write it to the internal clipboard
130 * structure for further processing.
131 *
132 * @param pPasteboardRef Reference to the global pasteboard.
133 * @param fFormats The format type which should be read.
134 * @param pv The destination buffer.
135 * @param cb The size of the destination buffer.
136 * @param pcbActual The size which is needed to transfer the content.
137 *
138 * @returns IPRT status code.
139 */
140int readFromPasteboard (PasteboardRef pPasteboard, uint32_t fFormat, void *pv, uint32_t cb, uint32_t *pcbActual)
141{
142 Log (("readFromPasteboard: fFormat = %02X\n", fFormat));
143
144 OSStatus err = noErr;
145
146 /* Make sure all is in sync */
147 PasteboardSynchronize (pPasteboard);
148
149 /* Are some items in the pasteboard? */
150 ItemCount itemCount;
151 err = PasteboardGetItemCount (pPasteboard, &itemCount);
152 if (itemCount < 1)
153 return VINF_SUCCESS;
154
155 /* The id of the first element in the pasteboard */
156 int rc = VERR_NOT_SUPPORTED;
157 PasteboardItemID itemID;
158 if (!(err = PasteboardGetItemIdentifier (pPasteboard, 1, &itemID)))
159 {
160 /* The guest request unicode */
161 if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
162 {
163 CFDataRef outData;
164 PRTUTF16 pwszTmp = NULL;
165 /* Try utf-16 first */
166 if (!(err = PasteboardCopyItemFlavorData (pPasteboard, itemID, CFSTR ("public.utf16-plain-text"), &outData)))
167 {
168 Log (("Clipboard content is utf-16\n"));
169 rc = RTUtf16DupEx (&pwszTmp, (PRTUTF16)CFDataGetBytePtr (outData), 0);
170 }
171 /* Second try is utf-8 */
172 else
173 if (!(err = PasteboardCopyItemFlavorData (pPasteboard, itemID, CFSTR ("public.utf8-plain-text"), &outData)))
174 {
175 Log (("readFromPasteboard: clipboard content is utf-8\n"));
176 rc = RTStrToUtf16 ((const char*)CFDataGetBytePtr (outData), &pwszTmp);
177 }
178 if (pwszTmp)
179 {
180 /* Check how much longer will the converted text will be. */
181 size_t cwSrc = RTUtf16Len (pwszTmp);
182 size_t cwDest;
183 rc = vboxClipboardUtf16GetWinSize (pwszTmp, cwSrc, &cwDest);
184 if (RT_FAILURE (rc))
185 {
186 RTUtf16Free (pwszTmp);
187 Log (("readFromPasteboard: clipboard conversion failed. vboxClipboardUtf16GetWinSize returned %Rrc. Abandoning.\n", rc));
188 AssertRCReturn (rc, rc);
189 }
190 /* Set the actually needed data size */
191 *pcbActual = cwDest * 2;
192 /* Return success state */
193 rc = VINF_SUCCESS;
194 /* Do not copy data if the dst buffer is not big enough. */
195 if (*pcbActual <= cb)
196 {
197 rc = vboxClipboardUtf16LinToWin (pwszTmp, RTUtf16Len (pwszTmp), static_cast <PRTUTF16> (pv), cb / 2);
198 if (RT_FAILURE (rc))
199 {
200 RTUtf16Free (pwszTmp);
201 Log (("readFromPasteboard: clipboard conversion failed. vboxClipboardUtf16LinToWin() returned %Rrc. Abandoning.\n", rc));
202 AssertRCReturn (rc, rc);
203 }
204#ifdef SHOW_CLIPBOARD_CONTENT
205 Log (("readFromPasteboard: clipboard content: %ls\n", static_cast <PRTUTF16> (pv)));
206#endif
207 }
208 /* Free the temp string */
209 RTUtf16Free (pwszTmp);
210 }
211 }
212 }
213
214 Log (("readFromPasteboard: rc = %02X\n", rc));
215 return rc;
216}
217
218/**
219 * Write clipboard content to the host clipboard from the internal clipboard
220 * structure.
221 *
222 * @param pPasteboardRef Reference to the global pasteboard.
223 * @param pv The source buffer.
224 * @param cb The size of the source buffer.
225 * @param fFormats The format type which should be written.
226 *
227 * @returns IPRT status code.
228 */
229int writeToPasteboard (PasteboardRef pPasteboard, void *pv, uint32_t cb, uint32_t fFormat)
230{
231 Log (("writeToPasteboard: fFormat = %02X\n", fFormat));
232
233 /* Clear the pasteboard */
234 if (PasteboardClear (pPasteboard))
235 return VERR_NOT_SUPPORTED;
236
237 /* Make sure all is in sync */
238 PasteboardSynchronize (pPasteboard);
239
240 int rc = VERR_NOT_SUPPORTED;
241 /* Handle the unicode text */
242 if (fFormat & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
243 {
244 PRTUTF16 pwszSrcText = static_cast <PRTUTF16> (pv);
245 size_t cwSrc = cb / 2;
246 size_t cwDest = 0;
247 /* How long will the converted text be? */
248 rc = vboxClipboardUtf16GetLinSize (pwszSrcText, cwSrc, &cwDest);
249 if (RT_FAILURE (rc))
250 {
251 Log (("writeToPasteboard: clipboard conversion failed. vboxClipboardUtf16GetLinSize returned %Rrc. Abandoning.\n", rc));
252 AssertRCReturn (rc, rc);
253 }
254 /* Empty clipboard? Not critical */
255 if (cwDest == 0)
256 {
257 Log (("writeToPasteboard: received empty clipboard data from the guest, returning false.\n"));
258 return VINF_SUCCESS;
259 }
260 /* Allocate the necessary memory */
261 PRTUTF16 pwszDestText = static_cast <PRTUTF16> (RTMemAlloc (cwDest * 2));
262 if (pwszDestText == NULL)
263 {
264 Log (("writeToPasteboard: failed to allocate %d bytes\n", cwDest * 2));
265 return VERR_NO_MEMORY;
266 }
267 /* Convert the EOL */
268 rc = vboxClipboardUtf16WinToLin (pwszSrcText, cwSrc, pwszDestText, cwDest);
269 if (RT_FAILURE (rc))
270 {
271 Log (("writeToPasteboard: clipboard conversion failed. vboxClipboardUtf16WinToLin() returned %Rrc. Abandoning.\n", rc));
272 RTMemFree (pwszDestText);
273 AssertRCReturn (rc, rc);
274 }
275
276 CFDataRef textData = NULL;
277 /* Item id is 1. Nothing special here. */
278 PasteboardItemID itemId = (PasteboardItemID)1;
279 /* Create a CData object which we could pass to the pasteboard */
280 if ((textData = CFDataCreate (kCFAllocatorDefault,
281 reinterpret_cast<UInt8*> (pwszDestText), cwDest * 2)))
282 {
283 /* Put the Utf-16 version to the pasteboard */
284 PasteboardPutItemFlavor (pPasteboard, itemId,
285 CFSTR ("public.utf16-plain-text"),
286 textData, 0);
287 }
288 /* Create a Utf-8 version */
289 char *pszDestText;
290 rc = RTUtf16ToUtf8 (pwszDestText, &pszDestText);
291 if (RT_SUCCESS (rc))
292 {
293 /* Create a CData object which we could pass to the pasteboard */
294 if ((textData = CFDataCreate (kCFAllocatorDefault,
295 reinterpret_cast<UInt8*> (pszDestText), strlen(pszDestText))))
296 {
297 /* Put the Utf-8 version to the pasteboard */
298 PasteboardPutItemFlavor (pPasteboard, itemId,
299 CFSTR ("public.utf8-plain-text"),
300 textData, 0);
301 }
302 RTStrFree (pszDestText);
303 }
304
305 RTMemFree (pwszDestText);
306 rc = VINF_SUCCESS;
307 }
308 else
309 rc = VERR_NOT_IMPLEMENTED;
310
311 Log (("writeToPasteboard: rc = %02X\n", rc));
312 return rc;
313}
314
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