]> git.ipfire.org Git - thirdparty/openembedded/openembedded-core-contrib.git/blob
db9e1479904eb7dde76c28074748e9e138125dd2
[thirdparty/openembedded/openembedded-core-contrib.git] /
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",