diff options
Diffstat (limited to 'meta/packages/mozilla-headless/mozilla-headless/0001-Adds-initial-Gtk-clipboard-support-to-moz-headless.patch')
-rw-r--r-- | meta/packages/mozilla-headless/mozilla-headless/0001-Adds-initial-Gtk-clipboard-support-to-moz-headless.patch | 1478 |
1 files changed, 0 insertions, 1478 deletions
diff --git a/meta/packages/mozilla-headless/mozilla-headless/0001-Adds-initial-Gtk-clipboard-support-to-moz-headless.patch b/meta/packages/mozilla-headless/mozilla-headless/0001-Adds-initial-Gtk-clipboard-support-to-moz-headless.patch deleted file mode 100644 index db9e147990..0000000000 --- a/meta/packages/mozilla-headless/mozilla-headless/0001-Adds-initial-Gtk-clipboard-support-to-moz-headless.patch +++ /dev/null | |||
@@ -1,1478 +0,0 @@ | |||
1 | From fb41f028badb4dfddfc47fb2a1a68c1aa90dcef5 Mon Sep 17 00:00:00 2001 | ||
2 | From: Robert Bragg <robert@linux.intel.com> | ||
3 | Date: Fri, 8 May 2009 13:57:22 +0100 | ||
4 | Subject: [PATCH] Adds initial Gtk clipboard support to moz-headless | ||
5 | |||
6 | If build with MOZ_X11 enabled then this now builds the clipboard code taken | ||
7 | from the gtk2 backend. This doesn't provide any embedding API yet to expose | ||
8 | the clipboard. | ||
9 | --- | ||
10 | widget/src/headless/Makefile.in | 6 + | ||
11 | widget/src/headless/nsClipboard.cpp | 948 +++++++++++++++++++++++++++++++ | ||
12 | widget/src/headless/nsClipboard.h | 93 +++ | ||
13 | widget/src/headless/nsIImageToPixbuf.h | 62 ++ | ||
14 | widget/src/headless/nsImageToPixbuf.cpp | 196 +++++++ | ||
15 | widget/src/headless/nsImageToPixbuf.h | 71 +++ | ||
16 | widget/src/headless/nsWidgetFactory.cpp | 18 + | ||
17 | 7 files changed, 1394 insertions(+), 0 deletions(-) | ||
18 | create mode 100644 widget/src/headless/nsClipboard.cpp | ||
19 | create mode 100644 widget/src/headless/nsClipboard.h | ||
20 | create mode 100644 widget/src/headless/nsIImageToPixbuf.h | ||
21 | create mode 100644 widget/src/headless/nsImageToPixbuf.cpp | ||
22 | create mode 100644 widget/src/headless/nsImageToPixbuf.h | ||
23 | |||
24 | Index: offscreen/widget/src/headless/Makefile.in | ||
25 | =================================================================== | ||
26 | --- offscreen.orig/widget/src/headless/Makefile.in 2009-05-16 18:23:25.000000000 +0100 | ||
27 | +++ offscreen/widget/src/headless/Makefile.in 2009-06-12 14:14:05.000000000 +0100 | ||
28 | @@ -95,6 +95,12 @@ | ||
29 | nsScreenManagerHeadless.cpp \ | ||
30 | $(NULL) | ||
31 | |||
32 | +ifdef MOZ_X11 | ||
33 | +CPPSRCS += nsClipboard.cpp \ | ||
34 | + nsImageToPixbuf.cpp \ | ||
35 | + $(NULL) | ||
36 | +endif | ||
37 | + | ||
38 | # build our subdirs, too | ||
39 | SHARED_LIBRARY_LIBS = ../xpwidgets/libxpwidgets_s.a | ||
40 | |||
41 | Index: offscreen/widget/src/headless/nsClipboard.cpp | ||
42 | =================================================================== | ||
43 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | ||
44 | +++ offscreen/widget/src/headless/nsClipboard.cpp 2009-06-12 14:14:05.000000000 +0100 | ||
45 | @@ -0,0 +1,948 @@ | ||
46 | +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | ||
47 | +/* vim:expandtab:shiftwidth=4:tabstop=4: | ||
48 | + */ | ||
49 | +/* ***** BEGIN LICENSE BLOCK ***** | ||
50 | + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | ||
51 | + * | ||
52 | + * The contents of this file are subject to the Mozilla Public License Version | ||
53 | + * 1.1 (the "License"); you may not use this file except in compliance with | ||
54 | + * the License. You may obtain a copy of the License at | ||
55 | + * http://www.mozilla.org/MPL/ | ||
56 | + * | ||
57 | + * Software distributed under the License is distributed on an "AS IS" basis, | ||
58 | + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | ||
59 | + * for the specific language governing rights and limitations under the | ||
60 | + * License. | ||
61 | + * | ||
62 | + * The Original Code is mozilla.org code. | ||
63 | + * | ||
64 | + * The Initial Developer of the Original Code is Christopher Blizzard | ||
65 | + * <blizzard@mozilla.org>. Portions created by the Initial Developer | ||
66 | + * are Copyright (C) 2001 the Initial Developer. All Rights Reserved. | ||
67 | + * | ||
68 | + * Contributor(s): | ||
69 | + * | ||
70 | + * Alternatively, the contents of this file may be used under the terms of | ||
71 | + * either the GNU General Public License Version 2 or later (the "GPL"), or | ||
72 | + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), | ||
73 | + * in which case the provisions of the GPL or the LGPL are applicable instead | ||
74 | + * of those above. If you wish to allow use of your version of this file only | ||
75 | + * under the terms of either the GPL or the LGPL, and not to allow others to | ||
76 | + * use your version of this file under the terms of the MPL, indicate your | ||
77 | + * decision by deleting the provisions above and replace them with the notice | ||
78 | + * and other provisions required by the GPL or the LGPL. If you do not delete | ||
79 | + * the provisions above, a recipient may use your version of this file under | ||
80 | + * the terms of any one of the MPL, the GPL or the LGPL. | ||
81 | + * | ||
82 | + * ***** END LICENSE BLOCK ***** */ | ||
83 | + | ||
84 | +#include "nsClipboard.h" | ||
85 | +#include "nsSupportsPrimitives.h" | ||
86 | +#include "nsString.h" | ||
87 | +#include "nsReadableUtils.h" | ||
88 | +#include "nsXPIDLString.h" | ||
89 | +#include "nsPrimitiveHelpers.h" | ||
90 | +#include "nsICharsetConverterManager.h" | ||
91 | +#include "nsIServiceManager.h" | ||
92 | +#include "nsIImage.h" | ||
93 | +#include "nsImageToPixbuf.h" | ||
94 | +#include "nsStringStream.h" | ||
95 | + | ||
96 | +#include <gtk/gtk.h> | ||
97 | + | ||
98 | +// For manipulation of the X event queue | ||
99 | +#include <X11/Xlib.h> | ||
100 | +#include <gdk/gdkx.h> | ||
101 | +#include <sys/time.h> | ||
102 | +#include <sys/types.h> | ||
103 | +#include <unistd.h> | ||
104 | + | ||
105 | +#ifdef POLL_WITH_XCONNECTIONNUMBER | ||
106 | +#include <poll.h> | ||
107 | +#endif | ||
108 | + | ||
109 | +// Callback when someone asks us for the selection | ||
110 | +void | ||
111 | +invisible_selection_get_cb (GtkWidget *aWidget, | ||
112 | + GtkSelectionData *aSelectionData, | ||
113 | + guint aTime, | ||
114 | + guint aInfo, | ||
115 | + nsClipboard *aClipboard); | ||
116 | + | ||
117 | +gboolean | ||
118 | +selection_clear_event_cb (GtkWidget *aWidget, | ||
119 | + GdkEventSelection *aEvent, | ||
120 | + nsClipboard *aClipboard); | ||
121 | + | ||
122 | +static void | ||
123 | +ConvertHTMLtoUCS2 (guchar *data, | ||
124 | + PRInt32 dataLength, | ||
125 | + PRUnichar **unicodeData, | ||
126 | + PRInt32 &outUnicodeLen); | ||
127 | + | ||
128 | +static void | ||
129 | +GetHTMLCharset (guchar * data, PRInt32 dataLength, nsCString& str); | ||
130 | + | ||
131 | + | ||
132 | +// Our own versions of gtk_clipboard_wait_for_contents and | ||
133 | +// gtk_clipboard_wait_for_text, which don't run the event loop while | ||
134 | +// waiting for the data. This prevents a lot of problems related to | ||
135 | +// dispatching events at unexpected times. | ||
136 | + | ||
137 | +static GtkSelectionData * | ||
138 | +wait_for_contents (GtkClipboard *clipboard, GdkAtom target); | ||
139 | + | ||
140 | +static gchar * | ||
141 | +wait_for_text (GtkClipboard *clipboard); | ||
142 | + | ||
143 | +static Bool | ||
144 | +checkEventProc(Display *display, XEvent *event, XPointer arg); | ||
145 | + | ||
146 | +struct retrieval_context | ||
147 | +{ | ||
148 | + PRBool completed; | ||
149 | + void *data; | ||
150 | + | ||
151 | + retrieval_context() : completed(PR_FALSE), data(nsnull) { } | ||
152 | +}; | ||
153 | + | ||
154 | +static void | ||
155 | +wait_for_retrieval(GtkClipboard *clipboard, retrieval_context *transferData); | ||
156 | + | ||
157 | +static void | ||
158 | +clipboard_contents_received(GtkClipboard *clipboard, | ||
159 | + GtkSelectionData *selection_data, | ||
160 | + gpointer data); | ||
161 | + | ||
162 | +static void | ||
163 | +clipboard_text_received(GtkClipboard *clipboard, | ||
164 | + const gchar *text, | ||
165 | + gpointer data); | ||
166 | + | ||
167 | +nsClipboard::nsClipboard() | ||
168 | +{ | ||
169 | + mWidget = nsnull; | ||
170 | +} | ||
171 | + | ||
172 | +nsClipboard::~nsClipboard() | ||
173 | +{ | ||
174 | + if (mWidget) | ||
175 | + gtk_widget_destroy(mWidget); | ||
176 | +} | ||
177 | + | ||
178 | +NS_IMPL_ISUPPORTS1(nsClipboard, nsIClipboard) | ||
179 | + | ||
180 | +nsresult | ||
181 | +nsClipboard::Init(void) | ||
182 | +{ | ||
183 | + mWidget = gtk_invisible_new(); | ||
184 | + if (!mWidget) | ||
185 | + return NS_ERROR_FAILURE; | ||
186 | + | ||
187 | + g_signal_connect(G_OBJECT(mWidget), "selection_get", | ||
188 | + G_CALLBACK(invisible_selection_get_cb), this); | ||
189 | + | ||
190 | + g_signal_connect(G_OBJECT(mWidget), "selection_clear_event", | ||
191 | + G_CALLBACK(selection_clear_event_cb), this); | ||
192 | + | ||
193 | + // XXX make sure to set up the selection_clear event | ||
194 | + | ||
195 | + return NS_OK; | ||
196 | +} | ||
197 | + | ||
198 | +NS_IMETHODIMP | ||
199 | +nsClipboard::SetData(nsITransferable *aTransferable, | ||
200 | + nsIClipboardOwner *aOwner, PRInt32 aWhichClipboard) | ||
201 | +{ | ||
202 | + // See if we can short cut | ||
203 | + if ((aWhichClipboard == kGlobalClipboard && | ||
204 | + aTransferable == mGlobalTransferable.get() && | ||
205 | + aOwner == mGlobalOwner.get()) || | ||
206 | + (aWhichClipboard == kSelectionClipboard && | ||
207 | + aTransferable == mSelectionTransferable.get() && | ||
208 | + aOwner == mSelectionOwner.get())) { | ||
209 | + return NS_OK; | ||
210 | + } | ||
211 | + | ||
212 | + nsresult rv; | ||
213 | + if (!mPrivacyHandler) { | ||
214 | + rv = NS_NewClipboardPrivacyHandler(getter_AddRefs(mPrivacyHandler)); | ||
215 | + NS_ENSURE_SUCCESS(rv, rv); | ||
216 | + } | ||
217 | + rv = mPrivacyHandler->PrepareDataForClipboard(aTransferable); | ||
218 | + NS_ENSURE_SUCCESS(rv, rv); | ||
219 | + | ||
220 | + // Clear out the clipboard in order to set the new data | ||
221 | + EmptyClipboard(aWhichClipboard); | ||
222 | + | ||
223 | + if (aWhichClipboard == kSelectionClipboard) { | ||
224 | + mSelectionOwner = aOwner; | ||
225 | + mSelectionTransferable = aTransferable; | ||
226 | + } | ||
227 | + else { | ||
228 | + mGlobalOwner = aOwner; | ||
229 | + mGlobalTransferable = aTransferable; | ||
230 | + } | ||
231 | + | ||
232 | + // Which selection are we about to claim, CLIPBOARD or PRIMARY? | ||
233 | + GdkAtom selectionAtom = GetSelectionAtom(aWhichClipboard); | ||
234 | + | ||
235 | + // Make ourselves the owner. If we fail to, return. | ||
236 | + if (!gtk_selection_owner_set(mWidget, selectionAtom, GDK_CURRENT_TIME)) | ||
237 | + return NS_ERROR_FAILURE; | ||
238 | + | ||
239 | + // Clear the old selection target list. | ||
240 | + gtk_selection_clear_targets(mWidget, selectionAtom); | ||
241 | + | ||
242 | + // Get the types of supported flavors | ||
243 | + nsCOMPtr<nsISupportsArray> flavors; | ||
244 | + | ||
245 | + rv = aTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavors)); | ||
246 | + if (!flavors || NS_FAILED(rv)) | ||
247 | + return NS_ERROR_FAILURE; | ||
248 | + | ||
249 | + // Add all the flavors to this widget's supported type. | ||
250 | + PRUint32 count; | ||
251 | + flavors->Count(&count); | ||
252 | + for (PRUint32 i=0; i < count; i++) { | ||
253 | + nsCOMPtr<nsISupports> tastesLike; | ||
254 | + flavors->GetElementAt(i, getter_AddRefs(tastesLike)); | ||
255 | + nsCOMPtr<nsISupportsCString> flavor = do_QueryInterface(tastesLike); | ||
256 | + | ||
257 | + if (flavor) { | ||
258 | + nsXPIDLCString flavorStr; | ||
259 | + flavor->ToString(getter_Copies(flavorStr)); | ||
260 | + | ||
261 | + // special case text/unicode since we can handle all of | ||
262 | + // the string types | ||
263 | + if (!strcmp(flavorStr, kUnicodeMime)) { | ||
264 | + AddTarget(gdk_atom_intern("UTF8_STRING", FALSE), | ||
265 | + selectionAtom); | ||
266 | + AddTarget(gdk_atom_intern("COMPOUND_TEXT", FALSE), | ||
267 | + selectionAtom); | ||
268 | + AddTarget(gdk_atom_intern("TEXT", FALSE), selectionAtom); | ||
269 | + AddTarget(GDK_SELECTION_TYPE_STRING, selectionAtom); | ||
270 | + // next loop iteration | ||
271 | + continue; | ||
272 | + } | ||
273 | + | ||
274 | + // very special case for this one. since our selection mechanism doesn't work for images, | ||
275 | + // we must use GTK's clipboard utility functions | ||
276 | + if (!strcmp(flavorStr, kNativeImageMime) || !strcmp(flavorStr, kPNGImageMime) || | ||
277 | + !strcmp(flavorStr, kJPEGImageMime) || !strcmp(flavorStr, kGIFImageMime)) { | ||
278 | + nsCOMPtr<nsISupports> item; | ||
279 | + PRUint32 len; | ||
280 | + rv = aTransferable->GetTransferData(flavorStr, getter_AddRefs(item), &len); | ||
281 | + nsCOMPtr<nsISupportsInterfacePointer> ptrPrimitive(do_QueryInterface(item)); | ||
282 | + if (!ptrPrimitive) | ||
283 | + continue; | ||
284 | + | ||
285 | + nsCOMPtr<nsISupports> primitiveData; | ||
286 | + ptrPrimitive->GetData(getter_AddRefs(primitiveData)); | ||
287 | + nsCOMPtr<nsIImage> image(do_QueryInterface(primitiveData)); | ||
288 | + if (!image) // Not getting an image for an image mime type!? | ||
289 | + continue; | ||
290 | + | ||
291 | + if (NS_FAILED(image->LockImagePixels(PR_FALSE))) | ||
292 | + continue; | ||
293 | + GdkPixbuf* pixbuf = nsImageToPixbuf::ImageToPixbuf(image); | ||
294 | + if (!pixbuf) { | ||
295 | + image->UnlockImagePixels(PR_FALSE); | ||
296 | + continue; | ||
297 | + } | ||
298 | + | ||
299 | + GtkClipboard *aClipboard = gtk_clipboard_get(GetSelectionAtom(aWhichClipboard)); | ||
300 | + gtk_clipboard_set_image(aClipboard, pixbuf); | ||
301 | + g_object_unref(pixbuf); | ||
302 | + image->UnlockImagePixels(PR_FALSE); | ||
303 | + continue; | ||
304 | + } | ||
305 | + | ||
306 | + // Add this to our list of valid targets | ||
307 | + GdkAtom atom = gdk_atom_intern(flavorStr, FALSE); | ||
308 | + AddTarget(atom, selectionAtom); | ||
309 | + } | ||
310 | + } | ||
311 | + | ||
312 | + return NS_OK; | ||
313 | +} | ||
314 | + | ||
315 | +NS_IMETHODIMP | ||
316 | +nsClipboard::GetData(nsITransferable *aTransferable, PRInt32 aWhichClipboard) | ||
317 | +{ | ||
318 | + if (!aTransferable) | ||
319 | + return NS_ERROR_FAILURE; | ||
320 | + | ||
321 | + GtkClipboard *clipboard; | ||
322 | + clipboard = gtk_clipboard_get(GetSelectionAtom(aWhichClipboard)); | ||
323 | + | ||
324 | + guchar *data = NULL; | ||
325 | + gint length = 0; | ||
326 | + PRBool foundData = PR_FALSE; | ||
327 | + nsCAutoString foundFlavor; | ||
328 | + | ||
329 | + // Get a list of flavors this transferable can import | ||
330 | + nsCOMPtr<nsISupportsArray> flavors; | ||
331 | + nsresult rv; | ||
332 | + rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavors)); | ||
333 | + if (!flavors || NS_FAILED(rv)) | ||
334 | + return NS_ERROR_FAILURE; | ||
335 | + | ||
336 | + PRUint32 count; | ||
337 | + flavors->Count(&count); | ||
338 | + for (PRUint32 i=0; i < count; i++) { | ||
339 | + nsCOMPtr<nsISupports> genericFlavor; | ||
340 | + flavors->GetElementAt(i, getter_AddRefs(genericFlavor)); | ||
341 | + | ||
342 | + nsCOMPtr<nsISupportsCString> currentFlavor; | ||
343 | + currentFlavor = do_QueryInterface(genericFlavor); | ||
344 | + | ||
345 | + if (currentFlavor) { | ||
346 | + nsXPIDLCString flavorStr; | ||
347 | + currentFlavor->ToString(getter_Copies(flavorStr)); | ||
348 | + | ||
349 | + // Special case text/unicode since we can convert any | ||
350 | + // string into text/unicode | ||
351 | + if (!strcmp(flavorStr, kUnicodeMime)) { | ||
352 | + gchar* new_text = wait_for_text(clipboard); | ||
353 | + if (new_text) { | ||
354 | + // Convert utf-8 into our unicode format. | ||
355 | + NS_ConvertUTF8toUTF16 ucs2string(new_text); | ||
356 | + data = (guchar *)ToNewUnicode(ucs2string); | ||
357 | + length = ucs2string.Length() * 2; | ||
358 | + g_free(new_text); | ||
359 | + foundData = PR_TRUE; | ||
360 | + foundFlavor = kUnicodeMime; | ||
361 | + break; | ||
362 | + } | ||
363 | + // If the type was text/unicode and we couldn't get | ||
364 | + // text off the clipboard, run the next loop | ||
365 | + // iteration. | ||
366 | + continue; | ||
367 | + } | ||
368 | + | ||
369 | + // For images, we must wrap the data in an nsIInputStream then return instead of break, | ||
370 | + // because that code below won't help us. | ||
371 | + if (!strcmp(flavorStr, kJPEGImageMime) || !strcmp(flavorStr, kPNGImageMime) || !strcmp(flavorStr, kGIFImageMime)) { | ||
372 | + GdkAtom atom; | ||
373 | + if (!strcmp(flavorStr, kJPEGImageMime)) // This is image/jpg, but X only understands image/jpeg | ||
374 | + atom = gdk_atom_intern("image/jpeg", FALSE); | ||
375 | + else | ||
376 | + atom = gdk_atom_intern(flavorStr, FALSE); | ||
377 | + | ||
378 | + GtkSelectionData *selectionData = wait_for_contents(clipboard, atom); | ||
379 | + if (!selectionData) | ||
380 | + continue; | ||
381 | + | ||
382 | + nsCOMPtr<nsIInputStream> byteStream; | ||
383 | + NS_NewByteInputStream(getter_AddRefs(byteStream), (const char*)selectionData->data, | ||
384 | + selectionData->length, NS_ASSIGNMENT_COPY); | ||
385 | + aTransferable->SetTransferData(flavorStr, byteStream, sizeof(nsIInputStream*)); | ||
386 | + gtk_selection_data_free(selectionData); | ||
387 | + return NS_OK; | ||
388 | + } | ||
389 | + | ||
390 | + // Get the atom for this type and try to request it off | ||
391 | + // the clipboard. | ||
392 | + GdkAtom atom = gdk_atom_intern(flavorStr, FALSE); | ||
393 | + GtkSelectionData *selectionData; | ||
394 | + selectionData = wait_for_contents(clipboard, atom); | ||
395 | + if (selectionData) { | ||
396 | + length = selectionData->length; | ||
397 | + // Special case text/html since we can convert into UCS2 | ||
398 | + if (!strcmp(flavorStr, kHTMLMime)) { | ||
399 | + PRUnichar* htmlBody= nsnull; | ||
400 | + PRInt32 htmlBodyLen = 0; | ||
401 | + // Convert text/html into our unicode format | ||
402 | + ConvertHTMLtoUCS2((guchar *)selectionData->data, length, | ||
403 | + &htmlBody, htmlBodyLen); | ||
404 | + if (!htmlBodyLen) | ||
405 | + break; | ||
406 | + data = (guchar *)htmlBody; | ||
407 | + length = htmlBodyLen * 2; | ||
408 | + } else { | ||
409 | + data = (guchar *)nsMemory::Alloc(length); | ||
410 | + if (!data) | ||
411 | + break; | ||
412 | + memcpy(data, selectionData->data, length); | ||
413 | + } | ||
414 | + foundData = PR_TRUE; | ||
415 | + foundFlavor = flavorStr; | ||
416 | + break; | ||
417 | + } | ||
418 | + } | ||
419 | + } | ||
420 | + | ||
421 | + if (foundData) { | ||
422 | + nsCOMPtr<nsISupports> wrapper; | ||
423 | + nsPrimitiveHelpers::CreatePrimitiveForData(foundFlavor.get(), | ||
424 | + data, length, | ||
425 | + getter_AddRefs(wrapper)); | ||
426 | + aTransferable->SetTransferData(foundFlavor.get(), | ||
427 | + wrapper, length); | ||
428 | + } | ||
429 | + | ||
430 | + if (data) | ||
431 | + nsMemory::Free(data); | ||
432 | + | ||
433 | + return NS_OK; | ||
434 | +} | ||
435 | + | ||
436 | +NS_IMETHODIMP | ||
437 | +nsClipboard::EmptyClipboard(PRInt32 aWhichClipboard) | ||
438 | +{ | ||
439 | + if (aWhichClipboard == kSelectionClipboard) { | ||
440 | + if (mSelectionOwner) { | ||
441 | + mSelectionOwner->LosingOwnership(mSelectionTransferable); | ||
442 | + mSelectionOwner = nsnull; | ||
443 | + } | ||
444 | + mSelectionTransferable = nsnull; | ||
445 | + } | ||
446 | + else { | ||
447 | + if (mGlobalOwner) { | ||
448 | + mGlobalOwner->LosingOwnership(mGlobalTransferable); | ||
449 | + mGlobalOwner = nsnull; | ||
450 | + } | ||
451 | + mGlobalTransferable = nsnull; | ||
452 | + } | ||
453 | + | ||
454 | + return NS_OK; | ||
455 | +} | ||
456 | + | ||
457 | +NS_IMETHODIMP | ||
458 | +nsClipboard::HasDataMatchingFlavors(const char** aFlavorList, PRUint32 aLength, | ||
459 | + PRInt32 aWhichClipboard, PRBool *_retval) | ||
460 | +{ | ||
461 | + if (!aFlavorList || !_retval) | ||
462 | + return NS_ERROR_NULL_POINTER; | ||
463 | + | ||
464 | + *_retval = PR_FALSE; | ||
465 | + | ||
466 | + GtkSelectionData *selection_data = | ||
467 | + GetTargets(GetSelectionAtom(aWhichClipboard)); | ||
468 | + if (!selection_data) | ||
469 | + return NS_OK; | ||
470 | + | ||
471 | + gint n_targets = 0; | ||
472 | + GdkAtom *targets = NULL; | ||
473 | + | ||
474 | + if (!gtk_selection_data_get_targets(selection_data, | ||
475 | + &targets, &n_targets) || | ||
476 | + !n_targets) | ||
477 | + return NS_OK; | ||
478 | + | ||
479 | + // Walk through the provided types and try to match it to a | ||
480 | + // provided type. | ||
481 | + for (PRUint32 i = 0; i < aLength && !*_retval; i++) { | ||
482 | + // We special case text/unicode here. | ||
483 | + if (!strcmp(aFlavorList[i], kUnicodeMime) && | ||
484 | + gtk_selection_data_targets_include_text(selection_data)) { | ||
485 | + *_retval = PR_TRUE; | ||
486 | + break; | ||
487 | + } | ||
488 | + | ||
489 | + for (PRInt32 j = 0; j < n_targets; j++) { | ||
490 | + gchar *atom_name = gdk_atom_name(targets[j]); | ||
491 | + if (!strcmp(atom_name, aFlavorList[i])) | ||
492 | + *_retval = PR_TRUE; | ||
493 | + | ||
494 | + // X clipboard wants image/jpeg, not image/jpg | ||
495 | + if (!strcmp(aFlavorList[i], kJPEGImageMime) && !strcmp(atom_name, "image/jpeg")) | ||
496 | + *_retval = PR_TRUE; | ||
497 | + | ||
498 | + g_free(atom_name); | ||
499 | + | ||
500 | + if (*_retval) | ||
501 | + break; | ||
502 | + } | ||
503 | + } | ||
504 | + gtk_selection_data_free(selection_data); | ||
505 | + g_free(targets); | ||
506 | + | ||
507 | + return NS_OK; | ||
508 | +} | ||
509 | + | ||
510 | +NS_IMETHODIMP | ||
511 | +nsClipboard::SupportsSelectionClipboard(PRBool *_retval) | ||
512 | +{ | ||
513 | + *_retval = PR_TRUE; // yeah, unix supports the selection clipboard | ||
514 | + return NS_OK; | ||
515 | +} | ||
516 | + | ||
517 | +/* static */ | ||
518 | +GdkAtom | ||
519 | +nsClipboard::GetSelectionAtom(PRInt32 aWhichClipboard) | ||
520 | +{ | ||
521 | + if (aWhichClipboard == kGlobalClipboard) | ||
522 | + return GDK_SELECTION_CLIPBOARD; | ||
523 | + | ||
524 | + return GDK_SELECTION_PRIMARY; | ||
525 | +} | ||
526 | + | ||
527 | +/* static */ | ||
528 | +GtkSelectionData * | ||
529 | +nsClipboard::GetTargets(GdkAtom aWhichClipboard) | ||
530 | +{ | ||
531 | + GtkClipboard *clipboard = gtk_clipboard_get(aWhichClipboard); | ||
532 | + return wait_for_contents(clipboard, gdk_atom_intern("TARGETS", FALSE)); | ||
533 | +} | ||
534 | + | ||
535 | +nsITransferable * | ||
536 | +nsClipboard::GetTransferable(PRInt32 aWhichClipboard) | ||
537 | +{ | ||
538 | + nsITransferable *retval; | ||
539 | + | ||
540 | + if (aWhichClipboard == kSelectionClipboard) | ||
541 | + retval = mSelectionTransferable.get(); | ||
542 | + else | ||
543 | + retval = mGlobalTransferable.get(); | ||
544 | + | ||
545 | + return retval; | ||
546 | +} | ||
547 | + | ||
548 | +void | ||
549 | +nsClipboard::AddTarget(GdkAtom aName, GdkAtom aClipboard) | ||
550 | +{ | ||
551 | + gtk_selection_add_target(mWidget, aClipboard, aName, 0); | ||
552 | +} | ||
553 | + | ||
554 | +void | ||
555 | +nsClipboard::SelectionGetEvent (GtkWidget *aWidget, | ||
556 | + GtkSelectionData *aSelectionData, | ||
557 | + guint aTime) | ||
558 | +{ | ||
559 | + // Someone has asked us to hand them something. The first thing | ||
560 | + // that we want to do is see if that something includes text. If | ||
561 | + // it does, try to give it text/unicode after converting it to | ||
562 | + // utf-8. | ||
563 | + | ||
564 | + PRInt32 whichClipboard; | ||
565 | + | ||
566 | + // which clipboard? | ||
567 | + if (aSelectionData->selection == GDK_SELECTION_PRIMARY) | ||
568 | + whichClipboard = kSelectionClipboard; | ||
569 | + else if (aSelectionData->selection == GDK_SELECTION_CLIPBOARD) | ||
570 | + whichClipboard = kGlobalClipboard; | ||
571 | + else | ||
572 | + return; // THAT AIN'T NO CLIPBOARD I EVER HEARD OF | ||
573 | + | ||
574 | + nsCOMPtr<nsITransferable> trans = GetTransferable(whichClipboard); | ||
575 | + | ||
576 | + nsresult rv; | ||
577 | + nsCOMPtr<nsISupports> item; | ||
578 | + PRUint32 len; | ||
579 | + | ||
580 | + // Check to see if the selection data includes any of the string | ||
581 | + // types that we support. | ||
582 | + if (aSelectionData->target == gdk_atom_intern ("STRING", FALSE) || | ||
583 | + aSelectionData->target == gdk_atom_intern ("TEXT", FALSE) || | ||
584 | + aSelectionData->target == gdk_atom_intern ("COMPOUND_TEXT", FALSE) || | ||
585 | + aSelectionData->target == gdk_atom_intern ("UTF8_STRING", FALSE)) { | ||
586 | + // Try to convert our internal type into a text string. Get | ||
587 | + // the transferable for this clipboard and try to get the | ||
588 | + // text/unicode type for it. | ||
589 | + rv = trans->GetTransferData("text/unicode", getter_AddRefs(item), | ||
590 | + &len); | ||
591 | + if (!item || NS_FAILED(rv)) | ||
592 | + return; | ||
593 | + | ||
594 | + nsCOMPtr<nsISupportsString> wideString; | ||
595 | + wideString = do_QueryInterface(item); | ||
596 | + if (!wideString) | ||
597 | + return; | ||
598 | + | ||
599 | + nsAutoString ucs2string; | ||
600 | + wideString->GetData(ucs2string); | ||
601 | + char *utf8string = ToNewUTF8String(ucs2string); | ||
602 | + if (!utf8string) | ||
603 | + return; | ||
604 | + | ||
605 | + gtk_selection_data_set_text (aSelectionData, utf8string, | ||
606 | + strlen(utf8string)); | ||
607 | + | ||
608 | + nsMemory::Free(utf8string); | ||
609 | + return; | ||
610 | + } | ||
611 | + | ||
612 | + // Try to match up the selection data target to something our | ||
613 | + // transferable provides. | ||
614 | + gchar *target_name = gdk_atom_name(aSelectionData->target); | ||
615 | + if (!target_name) | ||
616 | + return; | ||
617 | + | ||
618 | + rv = trans->GetTransferData(target_name, getter_AddRefs(item), &len); | ||
619 | + // nothing found? | ||
620 | + if (!item || NS_FAILED(rv)) { | ||
621 | + g_free(target_name); | ||
622 | + return; | ||
623 | + } | ||
624 | + | ||
625 | + void *primitive_data = nsnull; | ||
626 | + nsPrimitiveHelpers::CreateDataFromPrimitive(target_name, item, | ||
627 | + &primitive_data, len); | ||
628 | + | ||
629 | + if (primitive_data) { | ||
630 | + // Check to see if the selection data is text/html | ||
631 | + if (aSelectionData->target == gdk_atom_intern (kHTMLMime, FALSE)) { | ||
632 | + /* | ||
633 | + * "text/html" can be encoded UCS2. It is recommended that | ||
634 | + * documents transmitted as UCS2 always begin with a ZERO-WIDTH | ||
635 | + * NON-BREAKING SPACE character (hexadecimal FEFF, also called | ||
636 | + * Byte Order Mark (BOM)). Adding BOM can help other app to | ||
637 | + * detect mozilla use UCS2 encoding when copy-paste. | ||
638 | + */ | ||
639 | + guchar *buffer = (guchar *) | ||
640 | + nsMemory::Alloc((len * sizeof(guchar)) + sizeof(PRUnichar)); | ||
641 | + if (!buffer) | ||
642 | + return; | ||
643 | + PRUnichar prefix = 0xFEFF; | ||
644 | + memcpy(buffer, &prefix, sizeof(prefix)); | ||
645 | + memcpy(buffer + sizeof(prefix), primitive_data, len); | ||
646 | + nsMemory::Free((guchar *)primitive_data); | ||
647 | + primitive_data = (guchar *)buffer; | ||
648 | + len += sizeof(prefix); | ||
649 | + } | ||
650 | + | ||
651 | + gtk_selection_data_set(aSelectionData, aSelectionData->target, | ||
652 | + 8, /* 8 bits in a unit */ | ||
653 | + (const guchar *)primitive_data, len); | ||
654 | + nsMemory::Free(primitive_data); | ||
655 | + } | ||
656 | + | ||
657 | + g_free(target_name); | ||
658 | + | ||
659 | +} | ||
660 | + | ||
661 | +void | ||
662 | +nsClipboard::SelectionClearEvent (GtkWidget *aWidget, | ||
663 | + GdkEventSelection *aEvent) | ||
664 | +{ | ||
665 | + PRInt32 whichClipboard; | ||
666 | + | ||
667 | + // which clipboard? | ||
668 | + if (aEvent->selection == GDK_SELECTION_PRIMARY) | ||
669 | + whichClipboard = kSelectionClipboard; | ||
670 | + else if (aEvent->selection == GDK_SELECTION_CLIPBOARD) | ||
671 | + whichClipboard = kGlobalClipboard; | ||
672 | + else | ||
673 | + return; // THAT AIN'T NO CLIPBOARD I EVER HEARD OF | ||
674 | + | ||
675 | + EmptyClipboard(whichClipboard); | ||
676 | +} | ||
677 | + | ||
678 | +void | ||
679 | +invisible_selection_get_cb (GtkWidget *aWidget, | ||
680 | + GtkSelectionData *aSelectionData, | ||
681 | + guint aTime, | ||
682 | + guint aInfo, | ||
683 | + nsClipboard *aClipboard) | ||
684 | +{ | ||
685 | + aClipboard->SelectionGetEvent(aWidget, aSelectionData, aTime); | ||
686 | +} | ||
687 | + | ||
688 | +gboolean | ||
689 | +selection_clear_event_cb (GtkWidget *aWidget, | ||
690 | + GdkEventSelection *aEvent, | ||
691 | + nsClipboard *aClipboard) | ||
692 | +{ | ||
693 | + aClipboard->SelectionClearEvent(aWidget, aEvent); | ||
694 | + return TRUE; | ||
695 | +} | ||
696 | + | ||
697 | +/* | ||
698 | + * when copy-paste, mozilla wants data encoded using UCS2, | ||
699 | + * other app such as StarOffice use "text/html"(RFC2854). | ||
700 | + * This function convert data(got from GTK clipboard) | ||
701 | + * to data mozilla wanted. | ||
702 | + * | ||
703 | + * data from GTK clipboard can be 3 forms: | ||
704 | + * 1. From current mozilla | ||
705 | + * "text/html", charset = utf-16 | ||
706 | + * 2. From old version mozilla or mozilla-based app | ||
707 | + * content("body" only), charset = utf-16 | ||
708 | + * 3. From other app who use "text/html" when copy-paste | ||
709 | + * "text/html", has "charset" info | ||
710 | + * | ||
711 | + * data : got from GTK clipboard | ||
712 | + * dataLength: got from GTK clipboard | ||
713 | + * body : pass to Mozilla | ||
714 | + * bodyLength: pass to Mozilla | ||
715 | + */ | ||
716 | +void ConvertHTMLtoUCS2(guchar * data, PRInt32 dataLength, | ||
717 | + PRUnichar** unicodeData, PRInt32& outUnicodeLen) | ||
718 | +{ | ||
719 | + nsCAutoString charset; | ||
720 | + GetHTMLCharset(data, dataLength, charset);// get charset of HTML | ||
721 | + if (charset.EqualsLiteral("UTF-16")) {//current mozilla | ||
722 | + outUnicodeLen = (dataLength / 2) - 1; | ||
723 | + *unicodeData = reinterpret_cast<PRUnichar*> | ||
724 | + (nsMemory::Alloc((outUnicodeLen + sizeof('\0')) * | ||
725 | + sizeof(PRUnichar))); | ||
726 | + if (*unicodeData) { | ||
727 | + memcpy(*unicodeData, data + sizeof(PRUnichar), | ||
728 | + outUnicodeLen * sizeof(PRUnichar)); | ||
729 | + (*unicodeData)[outUnicodeLen] = '\0'; | ||
730 | + } | ||
731 | + } else if (charset.EqualsLiteral("UNKNOWN")) { | ||
732 | + outUnicodeLen = 0; | ||
733 | + return; | ||
734 | + } else { | ||
735 | + // app which use "text/html" to copy&paste | ||
736 | + nsCOMPtr<nsIUnicodeDecoder> decoder; | ||
737 | + nsresult rv; | ||
738 | + // get the decoder | ||
739 | + nsCOMPtr<nsICharsetConverterManager> ccm = | ||
740 | + do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv); | ||
741 | + if (NS_FAILED(rv)) { | ||
742 | +#ifdef DEBUG_CLIPBOARD | ||
743 | + g_print(" can't get CHARSET CONVERTER MANAGER service\n"); | ||
744 | +#endif | ||
745 | + outUnicodeLen = 0; | ||
746 | + return; | ||
747 | + } | ||
748 | + rv = ccm->GetUnicodeDecoder(charset.get(), getter_AddRefs(decoder)); | ||
749 | + if (NS_FAILED(rv)) { | ||
750 | +#ifdef DEBUG_CLIPBOARD | ||
751 | + g_print(" get unicode decoder error\n"); | ||
752 | +#endif | ||
753 | + outUnicodeLen = 0; | ||
754 | + return; | ||
755 | + } | ||
756 | + // converting | ||
757 | + decoder->GetMaxLength((const char *)data, dataLength, &outUnicodeLen); | ||
758 | + // |outUnicodeLen| is number of chars | ||
759 | + if (outUnicodeLen) { | ||
760 | + *unicodeData = reinterpret_cast<PRUnichar*> | ||
761 | + (nsMemory::Alloc((outUnicodeLen + sizeof('\0')) * | ||
762 | + sizeof(PRUnichar))); | ||
763 | + if (*unicodeData) { | ||
764 | + PRInt32 numberTmp = dataLength; | ||
765 | + decoder->Convert((const char *)data, &numberTmp, | ||
766 | + *unicodeData, &outUnicodeLen); | ||
767 | +#ifdef DEBUG_CLIPBOARD | ||
768 | + if (numberTmp != dataLength) | ||
769 | + printf("didn't consume all the bytes\n"); | ||
770 | +#endif | ||
771 | + // null terminate. Convert() doesn't do it for us | ||
772 | + (*unicodeData)[outUnicodeLen] = '\0'; | ||
773 | + } | ||
774 | + } // if valid length | ||
775 | + } | ||
776 | +} | ||
777 | + | ||
778 | +/* | ||
779 | + * get "charset" information from clipboard data | ||
780 | + * return value can be: | ||
781 | + * 1. "UTF-16": mozilla or "text/html" with "charset=utf-16" | ||
782 | + * 2. "UNKNOWN": mozilla can't detect what encode it use | ||
783 | + * 3. other: "text/html" with other charset than utf-16 | ||
784 | + */ | ||
785 | +void GetHTMLCharset(guchar * data, PRInt32 dataLength, nsCString& str) | ||
786 | +{ | ||
787 | + // if detect "FFFE" or "FEFF", assume UTF-16 | ||
788 | + PRUnichar* beginChar = (PRUnichar*)data; | ||
789 | + if ((beginChar[0] == 0xFFFE) || (beginChar[0] == 0xFEFF)) { | ||
790 | + str.AssignLiteral("UTF-16"); | ||
791 | + return; | ||
792 | + } | ||
793 | + // no "FFFE" and "FEFF", assume ASCII first to find "charset" info | ||
794 | + const nsDependentCString htmlStr((const char *)data, dataLength); | ||
795 | + nsACString::const_iterator start, end; | ||
796 | + htmlStr.BeginReading(start); | ||
797 | + htmlStr.EndReading(end); | ||
798 | + nsACString::const_iterator valueStart(start), valueEnd(start); | ||
799 | + | ||
800 | + if (CaseInsensitiveFindInReadable( | ||
801 | + NS_LITERAL_CSTRING("CONTENT=\"text/html;"), | ||
802 | + start, end)) { | ||
803 | + start = end; | ||
804 | + htmlStr.EndReading(end); | ||
805 | + | ||
806 | + if (CaseInsensitiveFindInReadable( | ||
807 | + NS_LITERAL_CSTRING("charset="), | ||
808 | + start, end)) { | ||
809 | + valueStart = end; | ||
810 | + start = end; | ||
811 | + htmlStr.EndReading(end); | ||
812 | + | ||
813 | + if (FindCharInReadable('"', start, end)) | ||
814 | + valueEnd = start; | ||
815 | + } | ||
816 | + } | ||
817 | + // find "charset" in HTML | ||
818 | + if (valueStart != valueEnd) { | ||
819 | + str = Substring(valueStart, valueEnd); | ||
820 | + ToUpperCase(str); | ||
821 | +#ifdef DEBUG_CLIPBOARD | ||
822 | + printf("Charset of HTML = %s\n", charsetUpperStr.get()); | ||
823 | +#endif | ||
824 | + return; | ||
825 | + } | ||
826 | + str.AssignLiteral("UNKNOWN"); | ||
827 | +} | ||
828 | + | ||
829 | +static void | ||
830 | +DispatchSelectionNotifyEvent(GtkWidget *widget, XEvent *xevent) | ||
831 | +{ | ||
832 | + GdkEvent event; | ||
833 | + event.selection.type = GDK_SELECTION_NOTIFY; | ||
834 | + event.selection.window = widget->window; | ||
835 | + event.selection.selection = gdk_x11_xatom_to_atom(xevent->xselection.selection); | ||
836 | + event.selection.target = gdk_x11_xatom_to_atom(xevent->xselection.target); | ||
837 | + event.selection.property = gdk_x11_xatom_to_atom(xevent->xselection.property); | ||
838 | + event.selection.time = xevent->xselection.time; | ||
839 | + | ||
840 | + gtk_widget_event(widget, &event); | ||
841 | +} | ||
842 | + | ||
843 | +static void | ||
844 | +DispatchPropertyNotifyEvent(GtkWidget *widget, XEvent *xevent) | ||
845 | +{ | ||
846 | + if (((GdkWindowObject *) widget->window)->event_mask & GDK_PROPERTY_CHANGE_MASK) { | ||
847 | + GdkEvent event; | ||
848 | + event.property.type = GDK_PROPERTY_NOTIFY; | ||
849 | + event.property.window = widget->window; | ||
850 | + event.property.atom = gdk_x11_xatom_to_atom(xevent->xproperty.atom); | ||
851 | + event.property.time = xevent->xproperty.time; | ||
852 | + event.property.state = xevent->xproperty.state; | ||
853 | + | ||
854 | + gtk_widget_event(widget, &event); | ||
855 | + } | ||
856 | +} | ||
857 | + | ||
858 | +struct checkEventContext | ||
859 | +{ | ||
860 | + GtkWidget *cbWidget; | ||
861 | + Atom selAtom; | ||
862 | +}; | ||
863 | + | ||
864 | +static Bool | ||
865 | +checkEventProc(Display *display, XEvent *event, XPointer arg) | ||
866 | +{ | ||
867 | + checkEventContext *context = (checkEventContext *) arg; | ||
868 | + | ||
869 | + if (event->xany.type == SelectionNotify || | ||
870 | + (event->xany.type == PropertyNotify && | ||
871 | + event->xproperty.atom == context->selAtom)) { | ||
872 | + | ||
873 | + GdkWindow *cbWindow = gdk_window_lookup(event->xany.window); | ||
874 | + if (cbWindow) { | ||
875 | + GtkWidget *cbWidget = NULL; | ||
876 | + gdk_window_get_user_data(cbWindow, (gpointer *)&cbWidget); | ||
877 | + if (cbWidget && GTK_IS_WIDGET(cbWidget)) { | ||
878 | + context->cbWidget = cbWidget; | ||
879 | + return True; | ||
880 | + } | ||
881 | + } | ||
882 | + } | ||
883 | + | ||
884 | + return False; | ||
885 | +} | ||
886 | + | ||
887 | +// Idle timeout for receiving selection and property notify events (microsec) | ||
888 | +static const int kClipboardTimeout = 500000; | ||
889 | + | ||
890 | +static void | ||
891 | +wait_for_retrieval(GtkClipboard *clipboard, retrieval_context *r_context) | ||
892 | +{ | ||
893 | + if (r_context->completed) // the request completed synchronously | ||
894 | + return; | ||
895 | + | ||
896 | + Display *xDisplay = GDK_DISPLAY(); | ||
897 | + checkEventContext context; | ||
898 | + context.cbWidget = NULL; | ||
899 | + context.selAtom = gdk_x11_atom_to_xatom(gdk_atom_intern("GDK_SELECTION", | ||
900 | + FALSE)); | ||
901 | + | ||
902 | + // Send X events which are relevant to the ongoing selection retrieval | ||
903 | + // to the clipboard widget. Wait until either the operation completes, or | ||
904 | + // we hit our timeout. All other X events remain queued. | ||
905 | + | ||
906 | + int select_result; | ||
907 | + | ||
908 | +#ifdef POLL_WITH_XCONNECTIONNUMBER | ||
909 | + struct pollfd fds[1]; | ||
910 | + fds[0].fd = XConnectionNumber(xDisplay); | ||
911 | + fds[0].events = POLLIN; | ||
912 | +#else | ||
913 | + int cnumber = ConnectionNumber(xDisplay); | ||
914 | + fd_set select_set; | ||
915 | + FD_ZERO(&select_set); | ||
916 | + FD_SET(cnumber, &select_set); | ||
917 | + ++cnumber; | ||
918 | + struct timeval tv; | ||
919 | +#endif | ||
920 | + | ||
921 | + do { | ||
922 | + XEvent xevent; | ||
923 | + | ||
924 | + while (XCheckIfEvent(xDisplay, &xevent, checkEventProc, | ||
925 | + (XPointer) &context)) { | ||
926 | + | ||
927 | + if (xevent.xany.type == SelectionNotify) | ||
928 | + DispatchSelectionNotifyEvent(context.cbWidget, &xevent); | ||
929 | + else | ||
930 | + DispatchPropertyNotifyEvent(context.cbWidget, &xevent); | ||
931 | + | ||
932 | + if (r_context->completed) | ||
933 | + return; | ||
934 | + } | ||
935 | + | ||
936 | +#ifdef POLL_WITH_XCONNECTIONNUMBER | ||
937 | + select_result = poll(fds, 1, kClipboardTimeout / 1000); | ||
938 | +#else | ||
939 | + tv.tv_sec = 0; | ||
940 | + tv.tv_usec = kClipboardTimeout; | ||
941 | + select_result = select(cnumber, &select_set, NULL, NULL, &tv); | ||
942 | +#endif | ||
943 | + } while (select_result == 1); | ||
944 | + | ||
945 | +#ifdef DEBUG_CLIPBOARD | ||
946 | + printf("exceeded clipboard timeout\n"); | ||
947 | +#endif | ||
948 | +} | ||
949 | + | ||
950 | +static void | ||
951 | +clipboard_contents_received(GtkClipboard *clipboard, | ||
952 | + GtkSelectionData *selection_data, | ||
953 | + gpointer data) | ||
954 | +{ | ||
955 | + retrieval_context *context = static_cast<retrieval_context *>(data); | ||
956 | + context->completed = PR_TRUE; | ||
957 | + | ||
958 | + if (selection_data->length >= 0) | ||
959 | + context->data = gtk_selection_data_copy(selection_data); | ||
960 | +} | ||
961 | + | ||
962 | + | ||
963 | +static GtkSelectionData * | ||
964 | +wait_for_contents(GtkClipboard *clipboard, GdkAtom target) | ||
965 | +{ | ||
966 | + retrieval_context context; | ||
967 | + gtk_clipboard_request_contents(clipboard, target, | ||
968 | + clipboard_contents_received, | ||
969 | + &context); | ||
970 | + | ||
971 | + wait_for_retrieval(clipboard, &context); | ||
972 | + return static_cast<GtkSelectionData *>(context.data); | ||
973 | +} | ||
974 | + | ||
975 | +static void | ||
976 | +clipboard_text_received(GtkClipboard *clipboard, | ||
977 | + const gchar *text, | ||
978 | + gpointer data) | ||
979 | +{ | ||
980 | + retrieval_context *context = static_cast<retrieval_context *>(data); | ||
981 | + context->completed = PR_TRUE; | ||
982 | + context->data = g_strdup(text); | ||
983 | +} | ||
984 | + | ||
985 | +static gchar * | ||
986 | +wait_for_text(GtkClipboard *clipboard) | ||
987 | +{ | ||
988 | + retrieval_context context; | ||
989 | + gtk_clipboard_request_text(clipboard, clipboard_text_received, &context); | ||
990 | + | ||
991 | + wait_for_retrieval(clipboard, &context); | ||
992 | + return static_cast<gchar *>(context.data); | ||
993 | +} | ||
994 | Index: offscreen/widget/src/headless/nsClipboard.h | ||
995 | =================================================================== | ||
996 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | ||
997 | +++ offscreen/widget/src/headless/nsClipboard.h 2009-06-12 14:14:05.000000000 +0100 | ||
998 | @@ -0,0 +1,93 @@ | ||
999 | +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | ||
1000 | +/* vim:expandtab:shiftwidth=4:tabstop=4: | ||
1001 | + */ | ||
1002 | +/* ***** BEGIN LICENSE BLOCK ***** | ||
1003 | + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | ||
1004 | + * | ||
1005 | + * The contents of this file are subject to the Mozilla Public License Version | ||
1006 | + * 1.1 (the "License"); you may not use this file except in compliance with | ||
1007 | + * the License. You may obtain a copy of the License at | ||
1008 | + * http://www.mozilla.org/MPL/ | ||
1009 | + * | ||
1010 | + * Software distributed under the License is distributed on an "AS IS" basis, | ||
1011 | + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | ||
1012 | + * for the specific language governing rights and limitations under the | ||
1013 | + * License. | ||
1014 | + * | ||
1015 | + * The Original Code is mozilla.org code. | ||
1016 | + * | ||
1017 | + * The Initial Developer of the Original Code is Christopher Blizzard | ||
1018 | + * <blizzard@mozilla.org>. Portions created by the Initial Developer | ||
1019 | + * are Copyright (C) 2001 the Initial Developer. All Rights Reserved. | ||
1020 | + * | ||
1021 | + * Contributor(s): | ||
1022 | + * | ||
1023 | + * Alternatively, the contents of this file may be used under the terms of | ||
1024 | + * either the GNU General Public License Version 2 or later (the "GPL"), or | ||
1025 | + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), | ||
1026 | + * in which case the provisions of the GPL or the LGPL are applicable instead | ||
1027 | + * of those above. If you wish to allow use of your version of this file only | ||
1028 | + * under the terms of either the GPL or the LGPL, and not to allow others to | ||
1029 | + * use your version of this file under the terms of the MPL, indicate your | ||
1030 | + * decision by deleting the provisions above and replace them with the notice | ||
1031 | + * and other provisions required by the GPL or the LGPL. If you do not delete | ||
1032 | + * the provisions above, a recipient may use your version of this file under | ||
1033 | + * the terms of any one of the MPL, the GPL or the LGPL. | ||
1034 | + * | ||
1035 | + * ***** END LICENSE BLOCK ***** */ | ||
1036 | + | ||
1037 | +#ifndef __nsClipboard_h_ | ||
1038 | +#define __nsClipboard_h_ | ||
1039 | + | ||
1040 | +#include "nsIClipboard.h" | ||
1041 | +#include "nsClipboardPrivacyHandler.h" | ||
1042 | +#include "nsAutoPtr.h" | ||
1043 | +#include <gtk/gtk.h> | ||
1044 | + | ||
1045 | +class nsClipboard : public nsIClipboard | ||
1046 | +{ | ||
1047 | +public: | ||
1048 | + nsClipboard(); | ||
1049 | + virtual ~nsClipboard(); | ||
1050 | + | ||
1051 | + NS_DECL_ISUPPORTS | ||
1052 | + | ||
1053 | + NS_DECL_NSICLIPBOARD | ||
1054 | + | ||
1055 | + // Make sure we are initialized, called from the factory | ||
1056 | + // constructor | ||
1057 | + nsresult Init (void); | ||
1058 | + // Someone requested the selection from the hidden widget | ||
1059 | + void SelectionGetEvent (GtkWidget *aWidget, | ||
1060 | + GtkSelectionData *aSelectionData, | ||
1061 | + guint aTime); | ||
1062 | + void SelectionClearEvent (GtkWidget *aWidget, | ||
1063 | + GdkEventSelection *aEvent); | ||
1064 | + | ||
1065 | + | ||
1066 | +private: | ||
1067 | + // Utility methods | ||
1068 | + static GdkAtom GetSelectionAtom (PRInt32 aWhichClipboard); | ||
1069 | + static GtkSelectionData *GetTargets (GdkAtom aWhichClipboard); | ||
1070 | + | ||
1071 | + // Get our hands on the correct transferable, given a specific | ||
1072 | + // clipboard | ||
1073 | + nsITransferable *GetTransferable (PRInt32 aWhichClipboard); | ||
1074 | + | ||
1075 | + // Add a target type to the hidden widget | ||
1076 | + void AddTarget (GdkAtom aName, | ||
1077 | + GdkAtom aClipboard); | ||
1078 | + | ||
1079 | + // The hidden widget where we do all of our operations | ||
1080 | + GtkWidget *mWidget; | ||
1081 | + // Hang on to our owners and transferables so we can transfer data | ||
1082 | + // when asked. | ||
1083 | + nsCOMPtr<nsIClipboardOwner> mSelectionOwner; | ||
1084 | + nsCOMPtr<nsIClipboardOwner> mGlobalOwner; | ||
1085 | + nsCOMPtr<nsITransferable> mSelectionTransferable; | ||
1086 | + nsCOMPtr<nsITransferable> mGlobalTransferable; | ||
1087 | + nsRefPtr<nsClipboardPrivacyHandler> mPrivacyHandler; | ||
1088 | + | ||
1089 | +}; | ||
1090 | + | ||
1091 | +#endif /* __nsClipboard_h_ */ | ||
1092 | Index: offscreen/widget/src/headless/nsIImageToPixbuf.h | ||
1093 | =================================================================== | ||
1094 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | ||
1095 | +++ offscreen/widget/src/headless/nsIImageToPixbuf.h 2009-06-12 14:14:05.000000000 +0100 | ||
1096 | @@ -0,0 +1,62 @@ | ||
1097 | +/* ***** BEGIN LICENSE BLOCK ***** | ||
1098 | + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | ||
1099 | + * | ||
1100 | + * The contents of this file are subject to the Mozilla Public License Version | ||
1101 | + * 1.1 (the "License"); you may not use this file except in compliance with | ||
1102 | + * the License. You may obtain a copy of the License at | ||
1103 | + * http://www.mozilla.org/MPL/ | ||
1104 | + * | ||
1105 | + * Software distributed under the License is distributed on an "AS IS" basis, | ||
1106 | + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | ||
1107 | + * for the specific language governing rights and limitations under the | ||
1108 | + * License. | ||
1109 | + * | ||
1110 | + * The Original Code is mozilla.org widget code. | ||
1111 | + * | ||
1112 | + * The Initial Developer of the Original Code is | ||
1113 | + * Christian Biesinger <cbiesinger@web.de>. | ||
1114 | + * Portions created by the Initial Developer are Copyright (C) 2006 | ||
1115 | + * the Initial Developer. All Rights Reserved. | ||
1116 | + * | ||
1117 | + * Contributor(s): | ||
1118 | + * | ||
1119 | + * Alternatively, the contents of this file may be used under the terms of | ||
1120 | + * either the GNU General Public License Version 2 or later (the "GPL"), or | ||
1121 | + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), | ||
1122 | + * in which case the provisions of the GPL or the LGPL are applicable instead | ||
1123 | + * of those above. If you wish to allow use of your version of this file only | ||
1124 | + * under the terms of either the GPL or the LGPL, and not to allow others to | ||
1125 | + * use your version of this file under the terms of the MPL, indicate your | ||
1126 | + * decision by deleting the provisions above and replace them with the notice | ||
1127 | + * and other provisions required by the GPL or the LGPL. If you do not delete | ||
1128 | + * the provisions above, a recipient may use your version of this file under | ||
1129 | + * the terms of any one of the MPL, the GPL or the LGPL. | ||
1130 | + * | ||
1131 | + * ***** END LICENSE BLOCK ***** */ | ||
1132 | + | ||
1133 | +#ifndef NSIIMAGETOPIXBUF_H_ | ||
1134 | +#define NSIIMAGETOPIXBUF_H_ | ||
1135 | + | ||
1136 | +#include "nsISupports.h" | ||
1137 | + | ||
1138 | +// dfa4ac93-83f2-4ab8-9b2a-0ff7022aebe2 | ||
1139 | +#define NSIIMAGETOPIXBUF_IID \ | ||
1140 | +{ 0xdfa4ac93, 0x83f2, 0x4ab8, \ | ||
1141 | + { 0x9b, 0x2a, 0x0f, 0xf7, 0x02, 0x2a, 0xeb, 0xe2 } } | ||
1142 | + | ||
1143 | +class nsIImage; | ||
1144 | +typedef struct _GdkPixbuf GdkPixbuf; | ||
1145 | + | ||
1146 | +/** | ||
1147 | + * An interface that allows converting an nsIImage to a GdkPixbuf*. | ||
1148 | + */ | ||
1149 | +class nsIImageToPixbuf : public nsISupports { | ||
1150 | + public: | ||
1151 | + NS_DECLARE_STATIC_IID_ACCESSOR(NSIIMAGETOPIXBUF_IID) | ||
1152 | + | ||
1153 | + NS_IMETHOD_(GdkPixbuf*) ConvertImageToPixbuf(nsIImage* aImage) = 0; | ||
1154 | +}; | ||
1155 | + | ||
1156 | +NS_DEFINE_STATIC_IID_ACCESSOR(nsIImageToPixbuf, NSIIMAGETOPIXBUF_IID) | ||
1157 | + | ||
1158 | +#endif | ||
1159 | Index: offscreen/widget/src/headless/nsImageToPixbuf.cpp | ||
1160 | =================================================================== | ||
1161 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | ||
1162 | +++ offscreen/widget/src/headless/nsImageToPixbuf.cpp 2009-06-12 14:14:05.000000000 +0100 | ||
1163 | @@ -0,0 +1,196 @@ | ||
1164 | +/* vim:set sw=4 sts=4 et cin: */ | ||
1165 | +/* ***** BEGIN LICENSE BLOCK ***** | ||
1166 | + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | ||
1167 | + * | ||
1168 | + * The contents of this file are subject to the Mozilla Public License Version | ||
1169 | + * 1.1 (the "License"); you may not use this file except in compliance with | ||
1170 | + * the License. You may obtain a copy of the License at | ||
1171 | + * http://www.mozilla.org/MPL/ | ||
1172 | + * | ||
1173 | + * Software distributed under the License is distributed on an "AS IS" basis, | ||
1174 | + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | ||
1175 | + * for the specific language governing rights and limitations under the | ||
1176 | + * License. | ||
1177 | + * | ||
1178 | + * The Original Code is mozilla.org widget code. | ||
1179 | + * | ||
1180 | + * The Initial Developer of the Original Code is | ||
1181 | + * Christian Biesinger <cbiesinger@web.de>. | ||
1182 | + * Portions created by the Initial Developer are Copyright (C) 2006 | ||
1183 | + * the Initial Developer. All Rights Reserved. | ||
1184 | + * | ||
1185 | + * Contributor(s): | ||
1186 | + * | ||
1187 | + * Alternatively, the contents of this file may be used under the terms of | ||
1188 | + * either the GNU General Public License Version 2 or later (the "GPL"), or | ||
1189 | + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), | ||
1190 | + * in which case the provisions of the GPL or the LGPL are applicable instead | ||
1191 | + * of those above. If you wish to allow use of your version of this file only | ||
1192 | + * under the terms of either the GPL or the LGPL, and not to allow others to | ||
1193 | + * use your version of this file under the terms of the MPL, indicate your | ||
1194 | + * decision by deleting the provisions above and replace them with the notice | ||
1195 | + * and other provisions required by the GPL or the LGPL. If you do not delete | ||
1196 | + * the provisions above, a recipient may use your version of this file under | ||
1197 | + * the terms of any one of the MPL, the GPL or the LGPL. | ||
1198 | + * | ||
1199 | + * ***** END LICENSE BLOCK ***** */ | ||
1200 | + | ||
1201 | +#include <gdk-pixbuf/gdk-pixbuf.h> | ||
1202 | + | ||
1203 | +#include "gfxASurface.h" | ||
1204 | +#include "gfxImageSurface.h" | ||
1205 | +#include "gfxContext.h" | ||
1206 | + | ||
1207 | +#include "nsIImage.h" | ||
1208 | + | ||
1209 | +#include "nsAutoPtr.h" | ||
1210 | + | ||
1211 | +#include "nsImageToPixbuf.h" | ||
1212 | + | ||
1213 | +NS_IMPL_ISUPPORTS1(nsImageToPixbuf, nsIImageToPixbuf) | ||
1214 | + | ||
1215 | +inline unsigned char | ||
1216 | +unpremultiply (unsigned char color, | ||
1217 | + unsigned char alpha) | ||
1218 | +{ | ||
1219 | + if (alpha == 0) | ||
1220 | + return 0; | ||
1221 | + // plus alpha/2 to round instead of truncate | ||
1222 | + return (color * 255 + alpha / 2) / alpha; | ||
1223 | +} | ||
1224 | + | ||
1225 | +NS_IMETHODIMP_(GdkPixbuf*) | ||
1226 | +nsImageToPixbuf::ConvertImageToPixbuf(nsIImage* aImage) | ||
1227 | +{ | ||
1228 | + return ImageToPixbuf(aImage); | ||
1229 | +} | ||
1230 | + | ||
1231 | +GdkPixbuf* | ||
1232 | +nsImageToPixbuf::ImageToPixbuf(nsIImage* aImage) | ||
1233 | +{ | ||
1234 | + PRInt32 width = aImage->GetWidth(), | ||
1235 | + height = aImage->GetHeight(); | ||
1236 | + | ||
1237 | + nsRefPtr<gfxPattern> pattern; | ||
1238 | + aImage->GetPattern(getter_AddRefs(pattern)); | ||
1239 | + | ||
1240 | + return PatternToPixbuf(pattern, width, height); | ||
1241 | +} | ||
1242 | + | ||
1243 | +GdkPixbuf* | ||
1244 | +nsImageToPixbuf::ImgSurfaceToPixbuf(gfxImageSurface* aImgSurface, PRInt32 aWidth, PRInt32 aHeight) | ||
1245 | +{ | ||
1246 | + GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, PR_TRUE, 8, | ||
1247 | + aWidth, aHeight); | ||
1248 | + if (!pixbuf) | ||
1249 | + return nsnull; | ||
1250 | + | ||
1251 | + PRUint32 rowstride = gdk_pixbuf_get_rowstride (pixbuf); | ||
1252 | + guchar* pixels = gdk_pixbuf_get_pixels (pixbuf); | ||
1253 | + | ||
1254 | + long cairoStride = aImgSurface->Stride(); | ||
1255 | + unsigned char* cairoData = aImgSurface->Data(); | ||
1256 | + | ||
1257 | + gfxASurface::gfxImageFormat format = aImgSurface->Format(); | ||
1258 | + | ||
1259 | + for (PRInt32 row = 0; row < aHeight; ++row) { | ||
1260 | + for (PRInt32 col = 0; col < aWidth; ++col) { | ||
1261 | + guchar* pixel = pixels + row * rowstride + 4 * col; | ||
1262 | + | ||
1263 | + PRUint32* cairoPixel = reinterpret_cast<PRUint32*> | ||
1264 | + ((cairoData + row * cairoStride + 4 * col)); | ||
1265 | + | ||
1266 | + if (format == gfxASurface::ImageFormatARGB32) { | ||
1267 | + const PRUint8 a = (*cairoPixel >> 24) & 0xFF; | ||
1268 | + const PRUint8 r = unpremultiply((*cairoPixel >> 16) & 0xFF, a); | ||
1269 | + const PRUint8 g = unpremultiply((*cairoPixel >> 8) & 0xFF, a); | ||
1270 | + const PRUint8 b = unpremultiply((*cairoPixel >> 0) & 0xFF, a); | ||
1271 | + | ||
1272 | + *pixel++ = r; | ||
1273 | + *pixel++ = g; | ||
1274 | + *pixel++ = b; | ||
1275 | + *pixel++ = a; | ||
1276 | + } else { | ||
1277 | + NS_ASSERTION(format == gfxASurface::ImageFormatRGB24, | ||
1278 | + "unexpected format"); | ||
1279 | + const PRUint8 r = (*cairoPixel >> 16) & 0xFF; | ||
1280 | + const PRUint8 g = (*cairoPixel >> 8) & 0xFF; | ||
1281 | + const PRUint8 b = (*cairoPixel >> 0) & 0xFF; | ||
1282 | + | ||
1283 | + *pixel++ = r; | ||
1284 | + *pixel++ = g; | ||
1285 | + *pixel++ = b; | ||
1286 | + *pixel++ = 0xFF; // A | ||
1287 | + } | ||
1288 | + } | ||
1289 | + } | ||
1290 | + | ||
1291 | + return pixbuf; | ||
1292 | +} | ||
1293 | + | ||
1294 | +GdkPixbuf* | ||
1295 | +nsImageToPixbuf::SurfaceToPixbuf(gfxASurface* aSurface, PRInt32 aWidth, PRInt32 aHeight) | ||
1296 | +{ | ||
1297 | + if (aSurface->CairoStatus()) { | ||
1298 | + NS_ERROR("invalid surface"); | ||
1299 | + return nsnull; | ||
1300 | + } | ||
1301 | + | ||
1302 | + nsRefPtr<gfxImageSurface> imgSurface; | ||
1303 | + if (aSurface->GetType() == gfxASurface::SurfaceTypeImage) { | ||
1304 | + imgSurface = static_cast<gfxImageSurface*> | ||
1305 | + (static_cast<gfxASurface*>(aSurface)); | ||
1306 | + } else { | ||
1307 | + imgSurface = new gfxImageSurface(gfxIntSize(aWidth, aHeight), | ||
1308 | + gfxImageSurface::ImageFormatARGB32); | ||
1309 | + | ||
1310 | + if (!imgSurface) | ||
1311 | + return nsnull; | ||
1312 | + | ||
1313 | + nsRefPtr<gfxContext> context = new gfxContext(imgSurface); | ||
1314 | + if (!context) | ||
1315 | + return nsnull; | ||
1316 | + | ||
1317 | + context->SetOperator(gfxContext::OPERATOR_SOURCE); | ||
1318 | + context->SetSource(aSurface); | ||
1319 | + context->Paint(); | ||
1320 | + } | ||
1321 | + | ||
1322 | + return ImgSurfaceToPixbuf(imgSurface, aWidth, aHeight); | ||
1323 | +} | ||
1324 | + | ||
1325 | +GdkPixbuf* | ||
1326 | +nsImageToPixbuf::PatternToPixbuf(gfxPattern* aPattern, PRInt32 aWidth, PRInt32 aHeight) | ||
1327 | +{ | ||
1328 | + if (aPattern->CairoStatus()) { | ||
1329 | + NS_ERROR("invalid pattern"); | ||
1330 | + return nsnull; | ||
1331 | + } | ||
1332 | + | ||
1333 | + nsRefPtr<gfxImageSurface> imgSurface; | ||
1334 | + if (aPattern->GetType() == gfxPattern::PATTERN_SURFACE) { | ||
1335 | + nsRefPtr<gfxASurface> surface = aPattern->GetSurface(); | ||
1336 | + if (surface->GetType() == gfxASurface::SurfaceTypeImage) { | ||
1337 | + imgSurface = static_cast<gfxImageSurface*> | ||
1338 | + (static_cast<gfxASurface*>(surface.get())); | ||
1339 | + } | ||
1340 | + } | ||
1341 | + | ||
1342 | + if (!imgSurface) { | ||
1343 | + imgSurface = new gfxImageSurface(gfxIntSize(aWidth, aHeight), | ||
1344 | + gfxImageSurface::ImageFormatARGB32); | ||
1345 | + | ||
1346 | + if (!imgSurface) | ||
1347 | + return nsnull; | ||
1348 | + | ||
1349 | + nsRefPtr<gfxContext> context = new gfxContext(imgSurface); | ||
1350 | + if (!context) | ||
1351 | + return nsnull; | ||
1352 | + | ||
1353 | + context->SetOperator(gfxContext::OPERATOR_SOURCE); | ||
1354 | + context->SetPattern(aPattern); | ||
1355 | + context->Paint(); | ||
1356 | + } | ||
1357 | + | ||
1358 | + return ImgSurfaceToPixbuf(imgSurface, aWidth, aHeight); | ||
1359 | +} | ||
1360 | Index: offscreen/widget/src/headless/nsImageToPixbuf.h | ||
1361 | =================================================================== | ||
1362 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | ||
1363 | +++ offscreen/widget/src/headless/nsImageToPixbuf.h 2009-06-12 14:14:05.000000000 +0100 | ||
1364 | @@ -0,0 +1,71 @@ | ||
1365 | +/* vim:set sw=4 sts=4 et cin: */ | ||
1366 | +/* ***** BEGIN LICENSE BLOCK ***** | ||
1367 | + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | ||
1368 | + * | ||
1369 | + * The contents of this file are subject to the Mozilla Public License Version | ||
1370 | + * 1.1 (the "License"); you may not use this file except in compliance with | ||
1371 | + * the License. You may obtain a copy of the License at | ||
1372 | + * http://www.mozilla.org/MPL/ | ||
1373 | + * | ||
1374 | + * Software distributed under the License is distributed on an "AS IS" basis, | ||
1375 | + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | ||
1376 | + * for the specific language governing rights and limitations under the | ||
1377 | + * License. | ||
1378 | + * | ||
1379 | + * The Original Code is mozilla.org widget code. | ||
1380 | + * | ||
1381 | + * The Initial Developer of the Original Code is | ||
1382 | + * Christian Biesinger <cbiesinger@web.de>. | ||
1383 | + * Portions created by the Initial Developer are Copyright (C) 2006 | ||
1384 | + * the Initial Developer. All Rights Reserved. | ||
1385 | + * | ||
1386 | + * Contributor(s): | ||
1387 | + * | ||
1388 | + * Alternatively, the contents of this file may be used under the terms of | ||
1389 | + * either the GNU General Public License Version 2 or later (the "GPL"), or | ||
1390 | + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), | ||
1391 | + * in which case the provisions of the GPL or the LGPL are applicable instead | ||
1392 | + * of those above. If you wish to allow use of your version of this file only | ||
1393 | + * under the terms of either the GPL or the LGPL, and not to allow others to | ||
1394 | + * use your version of this file under the terms of the MPL, indicate your | ||
1395 | + * decision by deleting the provisions above and replace them with the notice | ||
1396 | + * and other provisions required by the GPL or the LGPL. If you do not delete | ||
1397 | + * the provisions above, a recipient may use your version of this file under | ||
1398 | + * the terms of any one of the MPL, the GPL or the LGPL. | ||
1399 | + * | ||
1400 | + * ***** END LICENSE BLOCK ***** */ | ||
1401 | + | ||
1402 | +#ifndef NSIMAGETOPIXBUF_H_ | ||
1403 | +#define NSIMAGETOPIXBUF_H_ | ||
1404 | + | ||
1405 | +#include "nsIImageToPixbuf.h" | ||
1406 | + | ||
1407 | +class gfxASurface; | ||
1408 | +class gfxPattern; | ||
1409 | +class gfxImageSurface; | ||
1410 | + | ||
1411 | +class nsImageToPixbuf : public nsIImageToPixbuf { | ||
1412 | + public: | ||
1413 | + NS_DECL_ISUPPORTS | ||
1414 | + NS_IMETHOD_(GdkPixbuf*) ConvertImageToPixbuf(nsIImage* aImage); | ||
1415 | + | ||
1416 | + // Friendlier version of ConvertImageToPixbuf for callers inside of | ||
1417 | + // widget | ||
1418 | + static GdkPixbuf* ImageToPixbuf(nsIImage* aImage); | ||
1419 | + static GdkPixbuf* SurfaceToPixbuf(gfxASurface* aSurface, | ||
1420 | + PRInt32 aWidth, PRInt32 aHeight); | ||
1421 | + static GdkPixbuf* PatternToPixbuf(gfxPattern* aPattern, | ||
1422 | + PRInt32 aWidth, PRInt32 aHeight); | ||
1423 | + private: | ||
1424 | + static GdkPixbuf* ImgSurfaceToPixbuf(gfxImageSurface* aImgSurface, | ||
1425 | + PRInt32 aWidth, PRInt32 aHeight); | ||
1426 | + ~nsImageToPixbuf() {} | ||
1427 | +}; | ||
1428 | + | ||
1429 | + | ||
1430 | +// fc2389b8-c650-4093-9e42-b05e5f0685b7 | ||
1431 | +#define NS_IMAGE_TO_PIXBUF_CID \ | ||
1432 | +{ 0xfc2389b8, 0xc650, 0x4093, \ | ||
1433 | + { 0x9e, 0x42, 0xb0, 0x5e, 0x5f, 0x06, 0x85, 0xb7 } } | ||
1434 | + | ||
1435 | +#endif | ||
1436 | Index: offscreen/widget/src/headless/nsWidgetFactory.cpp | ||
1437 | =================================================================== | ||
1438 | --- offscreen.orig/widget/src/headless/nsWidgetFactory.cpp 2009-06-12 14:08:56.000000000 +0100 | ||
1439 | +++ offscreen/widget/src/headless/nsWidgetFactory.cpp 2009-06-12 14:15:24.000000000 +0100 | ||
1440 | @@ -46,6 +46,10 @@ | ||
1441 | #include "nsWindow.h" | ||
1442 | #include "nsTransferable.h" | ||
1443 | #include "nsHTMLFormatConverter.h" | ||
1444 | +#ifdef MOZ_X11 | ||
1445 | +#include "nsClipboardHelper.h" | ||
1446 | +#include "nsClipboard.h" | ||
1447 | +#endif | ||
1448 | #include "nsSound.h" | ||
1449 | #include "nsBidiKeyboard.h" | ||
1450 | #include "nsScreenManagerHeadless.h" | ||
1451 | @@ -66,6 +70,10 @@ | ||
1452 | NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable) | ||
1453 | NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard) | ||
1454 | NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter) | ||
1455 | +#ifdef MOZ_X11 | ||
1456 | +NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper) | ||
1457 | +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsClipboard, Init) | ||
1458 | +#endif | ||
1459 | NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound) | ||
1460 | NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerHeadless) | ||
1461 | //NS_GENERIC_FACTORY_CONSTRUCTOR(nsImageToPixbuf) | ||
1462 | @@ -142,6 +150,16 @@ | ||
1463 | NS_TRANSFERABLE_CID, | ||
1464 | "@mozilla.org/widget/transferable;1", | ||
1465 | nsTransferableConstructor }, | ||
1466 | +#ifdef MOZ_X11 | ||
1467 | + { "Gtk Clipboard", | ||
1468 | + NS_CLIPBOARD_CID, | ||
1469 | + "@mozilla.org/widget/clipboard;1", | ||
1470 | + nsClipboardConstructor }, | ||
1471 | + { "Clipboard Helper", | ||
1472 | + NS_CLIPBOARDHELPER_CID, | ||
1473 | + "@mozilla.org/widget/clipboardhelper;1", | ||
1474 | + nsClipboardHelperConstructor }, | ||
1475 | +#endif | ||
1476 | { "HTML Format Converter", | ||
1477 | NS_HTMLFORMATCONVERTER_CID, | ||
1478 | "@mozilla.org/widget/htmlformatconverter;1", | ||