summaryrefslogtreecommitdiffstats
path: root/meta/packages/mozilla-headless/mozilla-headless/0001-Adds-initial-Gtk-clipboard-support-to-moz-headless.patch
diff options
context:
space:
mode:
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.patch1478
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 @@
1From fb41f028badb4dfddfc47fb2a1a68c1aa90dcef5 Mon Sep 17 00:00:00 2001
2From: Robert Bragg <robert@linux.intel.com>
3Date: Fri, 8 May 2009 13:57:22 +0100
4Subject: [PATCH] Adds initial Gtk clipboard support to moz-headless
5
6If build with MOZ_X11 enabled then this now builds the clipboard code taken
7from the gtk2 backend. This doesn't provide any embedding API yet to expose
8the 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
24Index: 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
41Index: 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+}
994Index: 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_ */
1092Index: 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
1159Index: 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+}
1360Index: 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
1436Index: 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",